package handler import ( "time" "git.coopgo.io/coopgo-platform/routing-service" "github.com/paulmach/orb" "github.com/paulmach/orb/geojson" "github.com/paulmach/orb/planar" "github.com/rs/zerolog/log" ) type SearchResult struct { ID string Route *geojson.FeatureCollection DepartureDate time.Time Itinerary *routing.Route } 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 } if departureRadius == nil { d := float64(1000) departureRadius = &d } if arrivalRadius == nil { a := float64(1000) departureRadius = &a } 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 { ls := r.Route.Features[2].Geometry distanceFromDeparture, indexDeparture := planar.DistanceFromWithIndex(ls, departure) distanceFromArrival, indexArrival := planar.DistanceFromWithIndex(ls, arrival) if indexArrival >= indexDeparture && distanceFromDeparture <= *departureRadius && distanceFromArrival < *arrivalRadius { 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 // }