carpool-service/handler/search.go

216 lines
6.5 KiB
Go
Raw Normal View History

2023-03-27 18:54:56 +00:00
package handler
import (
"time"
2023-03-29 22:45:18 +00:00
"git.coopgo.io/coopgo-platform/carpool-service/geoutils"
2023-03-29 10:50:25 +00:00
"git.coopgo.io/coopgo-platform/routing-service"
2023-03-29 22:45:18 +00:00
"git.coopgo.io/coopgo-platform/routing-service/encoding/polylines"
2023-03-27 18:54:56 +00:00
"github.com/paulmach/orb"
2023-03-29 10:50:25 +00:00
"github.com/paulmach/orb/geojson"
"github.com/rs/zerolog/log"
2023-03-27 18:54:56 +00:00
)
2023-03-29 10:50:25 +00:00
type SearchResult struct {
ID string
Route *geojson.FeatureCollection
DepartureDate time.Time
Itinerary *routing.Route
2023-03-27 18:54:56 +00:00
}
2023-03-29 10:50:25 +00:00
func (h *CarpoolServiceHandler) GetDriverJourneys(departure orb.Point, arrival orb.Point, departureRadius *float64, arrivalRadius *float64, minDate time.Time, maxDate time.Time, count *int64) ([]SearchResult, error) {
log.Debug().
Any("departure", departure).
Any("arrival", arrival).
Any("dep radius", departureRadius).
Any("arr radius", arrivalRadius).
Str("mindate", minDate.Format(time.RFC3339)).
Str("maxdate", maxDate.Format(time.RFC3339)).
Any("count", count).
Msg("Carpool service handler - GetDriverJourneys")
if count == nil {
c := int64(10)
count = &c
}
2023-03-29 22:45:18 +00:00
drad := float64(1000)
if departureRadius != nil {
drad = *departureRadius * 1000
2023-03-29 10:50:25 +00:00
}
2023-03-29 22:45:18 +00:00
arad := float64(1000)
if arrivalRadius != nil {
arad = *arrivalRadius * 1000
2023-03-29 10:50:25 +00:00
}
tileset, err := h.Tiles.GetTiles("driver", minDate, departure, arrival)
if err != nil {
log.Error().
Str("date", minDate.Format(time.RFC3339)).
Any("departure", departure).
Any("arrival", arrival).
Err(err).
Msg("could not retrieve tiles")
return nil, err
}
log.Debug().Any("tileset", tileset).Msg("got tileset")
candidate_routes := tileset.GetTiledRoutes()
journeys := []SearchResult{}
counted := int64(0)
for _, r := range candidate_routes {
2023-03-29 22:45:18 +00:00
ls := r.Route.Features[2].Geometry.(orb.LineString)
2023-03-29 10:50:25 +00:00
2023-03-29 22:45:18 +00:00
// distanceFromDeparture, indexDeparture := planar.DistanceFromWithIndex(ls, departure)
// distanceFromArrival, indexArrival := planar.DistanceFromWithIndex(ls, arrival)
distanceFromDeparture, indexDeparture := geoutils.DistanceFromLineString(departure, ls)
distanceFromArrival, indexArrival := geoutils.DistanceFromLineString(arrival, ls)
2023-03-29 10:50:25 +00:00
2023-03-29 22:45:18 +00:00
if indexArrival >= indexDeparture && distanceFromDeparture <= drad && distanceFromArrival < arad {
//routePoints := []orb.Point{r.Route.Features[0].Point(), departure, arrival, r.Route.Features[1].Point()}
routePoints := []orb.Point{departure, arrival}
log.Debug().Any("route points", routePoints).Msg("calculate multipoint route")
itinerary, err := h.Routing.Route(routePoints)
if err != nil {
log.Error().Err(err).Msg("error getting route with viapoints")
continue
}
journeys = append(journeys, SearchResult{
ID: r.ID,
Route: r.Route,
DepartureDate: r.DepartureDate,
Itinerary: itinerary,
})
counted = counted + 1
if counted == *count {
break
}
}
}
return journeys, nil
}
func (h *CarpoolServiceHandler) GetPassengerJourneys(departure orb.Point, arrival orb.Point, departureRadius *float64, arrivalRadius *float64, minDate time.Time, maxDate time.Time, count *int64) ([]SearchResult, error) {
log.Debug().
Any("departure", departure).
Any("arrival", arrival).
Any("dep radius", departureRadius).
Any("arr radius", arrivalRadius).
Str("mindate", minDate.Format(time.RFC3339)).
Str("maxdate", maxDate.Format(time.RFC3339)).
Any("count", count).
Msg("Carpool service handler - GetDriverJourneys")
routePoints := []orb.Point{departure, arrival}
itinerary, err := h.Routing.Route(routePoints)
if err != nil {
log.Error().Err(err).Msg("error getting route with viapoints")
return nil, err
}
if count == nil {
c := int64(10)
count = &c
}
drad := float64(1000)
if departureRadius != nil {
drad = *departureRadius * 1000
}
arad := float64(1000)
if arrivalRadius != nil {
arad = *arrivalRadius * 1000
}
decodedPolyline := polylines.Decode(&itinerary.Summary.Polyline, 5)
points := []orb.Point{departure, arrival}
for _, p := range decodedPolyline {
points = append(points, p)
}
tileset, err := h.Tiles.GetTiles("passenger", minDate, points...)
if err != nil {
log.Error().
Str("date", minDate.Format(time.RFC3339)).
Any("departure", departure).
Any("arrival", arrival).
Err(err).
Msg("could not retrieve tiles")
return nil, err
}
log.Debug().Any("tileset", tileset).Msg("got tileset")
candidate_routes := tileset.GetTiledRoutes()
journeys := []SearchResult{}
counted := int64(0)
for _, r := range candidate_routes {
ls := decodedPolyline
// distanceFromDeparture, indexDeparture := planar.DistanceFromWithIndex(ls, r.Route.Features[0].Point())
// distanceFromArrival, indexArrival := planar.DistanceFromWithIndex(ls, r.Route.Features[1].Point())
distanceFromDeparture, indexDeparture := geoutils.DistanceFromLineString(r.Route.Features[0].Point(), ls)
distanceFromArrival, indexArrival := geoutils.DistanceFromLineString(r.Route.Features[1].Point(), ls)
if indexArrival >= indexDeparture && distanceFromDeparture <= drad && distanceFromArrival < arad {
2023-03-29 10:50:25 +00:00
routePoints := []orb.Point{r.Route.Features[0].Point(), departure, arrival, r.Route.Features[0].Point()}
itinerary, err := h.Routing.Route(routePoints)
if err != nil {
log.Error().Err(err).Msg("error getting route with viapoints")
continue
}
journeys = append(journeys, SearchResult{
ID: r.ID,
Route: r.Route,
DepartureDate: r.DepartureDate,
Itinerary: itinerary,
})
counted = counted + 1
if counted == *count {
break
}
}
}
return journeys, nil
}
// //distance to Linestring computes the distance from point to the given linestring anf returns this minimum distance and the segment number
// func distanceToLineSTring(point orb.Point, lineString orb.LineString) (distance float64, closest_segment_index int) {
// minDistance := math.Inf(1)
// closest := -1
// for i := 0; i < len(lineString)-1; i++ {
// segment1 := lineString[i]
// segment2 := lineString[i+1]
// dist := distanceToSegment(point, segment1, segment2)
// if dist < minDistance {
// minDistance = dist
// closest = i
// }
// }
// return minDistance, closest
// }
// //distanceToSegment computes the distance to the segment defined with a starting and a ending point
// func distanceToSegment(point orb.Point, start orb.Point, end orb.Point) float64 {
// len := (end.Lon()-start.Lon())*(end.Lon()-start.Lon()) + (end.Lat()-start.Lat())*(end.Lat()-start.Lat())
// s := ((start.Lat()-point.Lat())*(end.Lon()-start.Lon()) - (start.Lon()-point.Lon())*(end.Lat()-start.Lat())) / len
// distance := math.Abs(s) * math.Sqrt(len)
// return distance
// }