Add tiles management
This commit is contained in:
33
tiles/grid.go
Normal file
33
tiles/grid.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package tiles
|
||||
|
||||
import "github.com/paulmach/orb"
|
||||
|
||||
// GridId defines the position of a tile
|
||||
// It follows the Valhalla way of handling tiles : https://github.com/Telenav/open-source-spec/blob/master/valhalla/doc/valhalla-tiles-basic.md
|
||||
type GridId uint64
|
||||
|
||||
const tilesize float64 = 1.0
|
||||
|
||||
// PointGridId returns the id on the grid for a given point
|
||||
func PointGridId(point orb.Point) GridId {
|
||||
width := int64(360 / tilesize)
|
||||
return GridId(int64((point.Lat()+90)/tilesize)*width + int64((point.Lon()+180)/tilesize))
|
||||
}
|
||||
|
||||
// LineStringGridIds returns the list of ids on the grid the linestring goes through.
|
||||
// In some really specific cases on tile edges, this could be unaccurate if the polyline was too much simplified
|
||||
func LineStringGridIds(linestring orb.LineString) []GridId {
|
||||
results := []GridId{}
|
||||
|
||||
gidmap := map[int64]bool{}
|
||||
|
||||
for _, p := range linestring {
|
||||
gid := PointGridId(p)
|
||||
if _, ok := gidmap[int64(gid)]; !ok {
|
||||
gidmap[int64(gid)] = true
|
||||
results = append(results, gid)
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
21
tiles/routes.go
Normal file
21
tiles/routes.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package tiles
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/paulmach/orb/geojson"
|
||||
)
|
||||
|
||||
type TiledRouteType int
|
||||
|
||||
const (
|
||||
TiledRouteRegular TiledRouteType = iota
|
||||
TiledRoutePunctual
|
||||
)
|
||||
|
||||
type TiledRoute struct {
|
||||
ID string
|
||||
Type TiledRouteType
|
||||
Route *geojson.FeatureCollection
|
||||
DepartureDate time.Time
|
||||
}
|
||||
49
tiles/tiles-handler.go
Normal file
49
tiles/tiles-handler.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package tiles
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.coopgo.io/coopgo-platform/carpool-service/storage"
|
||||
"github.com/paulmach/orb"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type TilesHandler struct {
|
||||
Config *viper.Viper
|
||||
PersistentStorage storage.Storage
|
||||
|
||||
CachedTileset map[string]Tileset
|
||||
}
|
||||
|
||||
func NewTilesHandler(cfg *viper.Viper, persistantStorage storage.Storage) (*TilesHandler, error) {
|
||||
return &TilesHandler{
|
||||
Config: cfg,
|
||||
PersistentStorage: persistantStorage,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetTiles retrieves tiles
|
||||
func (h *TilesHandler) GetTiles(driverOrPassenger string, date time.Time, points ...orb.Point) (*Tileset, error) {
|
||||
result := Tileset{}
|
||||
|
||||
grid_ids := []GridId{}
|
||||
|
||||
nb_points := len(points)
|
||||
|
||||
if nb_points > 1 {
|
||||
grid_ids = LineStringGridIds(orb.LineString(points))
|
||||
} else if nb_points == 1 {
|
||||
grid_ids = []GridId{PointGridId(points[0])}
|
||||
}
|
||||
|
||||
dateString := date.Format("2006-01-02")
|
||||
for _, gid := range grid_ids {
|
||||
tile, err := h.GetTile(driverOrPassenger, date, gid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[dateString] = tile
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
@@ -2,26 +2,83 @@ package tiles
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/paulmach/orb"
|
||||
"git.coopgo.io/coopgo-platform/carpool-service/helpers"
|
||||
"github.com/google/uuid"
|
||||
"github.com/paulmach/orb/geojson"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type IndexedTilesets struct {
|
||||
Tileset map[string]*Tile // Key is "date:geo" (example : "2023-01-01:fr-south-west")
|
||||
ByDate map[string]Tileset // Key is the date in the form "YYYY-MM-DD"
|
||||
ByGeo map[string]Tileset // Key is the Geo tiles id (could be any string as defined in the configuration)
|
||||
}
|
||||
|
||||
type Tileset []*Tile
|
||||
|
||||
// Tiles are defined as :
|
||||
// - "driver" or "passenger" string depending on the status of the journeys included in the tiles
|
||||
// - a date formatted as "2006-01-02"
|
||||
// - Bounds of the tile
|
||||
type Tile struct {
|
||||
Date string
|
||||
GeoId string
|
||||
Bounds orb.Bound
|
||||
Journeys []*geojson.FeatureCollection
|
||||
DriverOrPassenger string
|
||||
Date string // Date formatted as "2006-01-02"
|
||||
GridId GridId
|
||||
|
||||
TiledRoutes []TiledRoute
|
||||
}
|
||||
|
||||
func (t Tile) Id() string {
|
||||
return fmt.Sprintf("%s:%s", t.Date, t.GeoId)
|
||||
func (tile *Tile) ID() string {
|
||||
return fmt.Sprintf("%s/%s/%d", tile.DriverOrPassenger, tile.Date, tile.GridId)
|
||||
}
|
||||
|
||||
// GetTile retrieves a tile from persistant storage or cache
|
||||
func (h *TilesHandler) GetTile(driverOrPassenger string, date time.Time, gridid GridId) (*Tile, error) {
|
||||
routes := []*geojson.FeatureCollection{}
|
||||
day := strings.ToUpper(date.Format("Mon"))
|
||||
dateString := date.Format("2006-01-02")
|
||||
|
||||
if driverOrPassenger == "driver" {
|
||||
regroutes, err := h.PersistentStorage.GetDriverRegularRoutesForTile(day, int64(gridid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
routes = regroutes
|
||||
} else if driverOrPassenger == "passenger" {
|
||||
regroutes, err := h.PersistentStorage.GetPassengerRegularRoutesForTile(day, int64(gridid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
routes = regroutes
|
||||
}
|
||||
|
||||
date0h, _ := time.Parse("2006-01-02", dateString)
|
||||
date24h := date0h.Add(24 * time.Hour)
|
||||
|
||||
result := []TiledRoute{}
|
||||
|
||||
for _, r := range routes {
|
||||
|
||||
rr := helpers.RegularRoute(*r)
|
||||
schedules, err := rr.PlannedJourneySchedules(date0h, date24h)
|
||||
if err != nil {
|
||||
log.Error().Err(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(schedules) > 0 {
|
||||
tiledRoute := TiledRoute{
|
||||
ID: uuid.NewString(),
|
||||
Route: r,
|
||||
Type: TiledRouteRegular,
|
||||
DepartureDate: schedules[0].DepartureDate,
|
||||
}
|
||||
|
||||
result = append(result, tiledRoute)
|
||||
}
|
||||
}
|
||||
|
||||
return &Tile{
|
||||
DriverOrPassenger: driverOrPassenger,
|
||||
Date: dateString,
|
||||
GridId: gridid,
|
||||
TiledRoutes: result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
18
tiles/tilesets.go
Normal file
18
tiles/tilesets.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package tiles
|
||||
|
||||
// Tileset stores tiles by TileID
|
||||
type Tileset map[string]*Tile
|
||||
|
||||
func (tileset Tileset) GetTiledRoutes() []TiledRoute {
|
||||
idmap := map[string]bool{}
|
||||
result := []TiledRoute{}
|
||||
for _, tile := range tileset {
|
||||
for _, tr := range tile.TiledRoutes {
|
||||
if _, ok := idmap[tr.Route.ExtraMembers.MustString("id")]; !ok {
|
||||
idmap[tr.Route.ExtraMembers.MustString("id")] = true
|
||||
result = append(result, tr)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user