package handler import ( "time" "git.coopgo.io/coopgo-platform/carpool-service/geoutils" "git.coopgo.io/coopgo-platform/carpool-service/internal" "git.coopgo.io/coopgo-platform/routing-service/encoding/polylines" "github.com/paulmach/orb" "github.com/rs/zerolog/log" ) func (h *CarpoolServiceHandler) GetDriverJourneys(departure orb.Point, arrival orb.Point, departureRadius *float64, arrivalRadius *float64, minDate time.Time, maxDate time.Time, count *int64) ([]internal.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 } drad := float64(1000) if departureRadius != nil { drad = *departureRadius * 1000 } arad := float64(1000) if arrivalRadius != nil { arad = *arrivalRadius * 1000 } 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 := []internal.SearchResult{} counted := int64(0) for _, r := range candidate_routes { ls := r.Route.Features[2].Geometry.(orb.LineString) // distanceFromDeparture, indexDeparture := planar.DistanceFromWithIndex(ls, departure) // distanceFromArrival, indexArrival := planar.DistanceFromWithIndex(ls, arrival) distanceFromDeparture, indexDeparture := geoutils.DistanceFromLineString(departure, ls) distanceFromArrival, indexArrival := geoutils.DistanceFromLineString(arrival, ls) 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, internal.SearchResult{ ID: r.ID, Route: r.Route, DepartureDate: r.DepartureDate, Itinerary: itinerary, }) counted = counted + 1 if counted == *count { break } } } err = h.Storage.StoreSearchResults("driver", journeys) if err != nil { log.Error().Err(err).Msg("Error saving search results") return nil, err } 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) ([]internal.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 := []internal.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 { 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, internal.SearchResult{ ID: r.ID, Route: r.Route, DepartureDate: r.DepartureDate, Itinerary: itinerary, }) counted = counted + 1 if counted == *count { break } } } err = h.Storage.StoreSearchResults("passenger", journeys) if err != nil { log.Error().Err(err).Msg("Error saving search results") return nil, err } 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 // }