Add tiles management

This commit is contained in:
2023-03-29 12:50:25 +02:00
parent 77c8576254
commit bbc682386a
18 changed files with 559 additions and 64 deletions

33
tiles/grid.go Normal file
View 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
View 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
View 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
}

View File

@@ -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
View 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
}