routing-service/valhalla.go

117 lines
2.7 KiB
Go
Raw Normal View History

2023-03-27 18:57:28 +00:00
package routing
import (
"bytes"
"errors"
"io/ioutil"
"net/http"
2023-03-29 10:51:09 +00:00
"time"
2023-03-27 18:57:28 +00:00
"git.coopgo.io/coopgo-platform/routing-service/encoding/polylines"
"git.coopgo.io/coopgo-platform/routing-service/proto/valhalla"
"github.com/paulmach/orb"
2023-03-29 22:45:55 +00:00
"github.com/rs/zerolog/log"
2023-03-27 18:57:28 +00:00
"google.golang.org/protobuf/proto"
)
type ValhallaRouting struct {
BaseURL string
}
func NewValhallaRouting(baseURL string) (*ValhallaRouting, error) {
return &ValhallaRouting{
BaseURL: baseURL,
}, nil
}
func (v *ValhallaRouting) Route(locations []orb.Point) (route *Route, err error) {
valhalla_locations := []*valhalla.Location{}
for _, loc := range locations {
valhalla_locations = append(valhalla_locations, &valhalla.Location{
Ll: &valhalla.LatLng{
HasLat: &valhalla.LatLng_Lat{Lat: loc.Lat()},
HasLng: &valhalla.LatLng_Lng{Lng: loc.Lon()},
},
})
}
request := &valhalla.Api{
Options: &valhalla.Options{
Action: valhalla.Options_route,
Locations: valhalla_locations,
CostingType: valhalla.Costing_auto_,
Format: valhalla.Options_pbf,
},
}
resp, err := v.protocolBufferRequest(request, "route")
if err != nil {
2023-03-29 22:45:55 +00:00
log.Error().Err(err).Msg("pb request to valhalla error")
2023-03-27 18:57:28 +00:00
return nil, err
}
2023-03-29 16:31:29 +00:00
if resp.Directions == nil || resp.Directions.Routes == nil || len(resp.Directions.Routes) < 1 {
2023-03-29 22:45:55 +00:00
return nil, errors.New("no routes returned by valhalla")
2023-03-27 18:57:28 +00:00
}
decodedLinestring := orb.LineString{}
2023-03-29 10:51:09 +00:00
legs := []RouteLeg{}
2023-03-27 18:57:28 +00:00
for _, leg := range resp.Directions.Routes[0].Legs {
shape := leg.Shape
decodedShape := polylines.Decode(&shape, 6)
decodedLinestring = append(decodedLinestring, decodedShape...)
2023-03-29 10:51:09 +00:00
routeLeg := RouteLeg{
Distance: float64(leg.Summary.Length),
Duration: time.Duration(leg.Summary.Time) * time.Second,
2023-03-29 22:45:55 +00:00
Polyline: polylines.Encode(decodedShape, 5),
2023-03-29 10:51:09 +00:00
}
legs = append(legs, routeLeg)
2023-03-27 18:57:28 +00:00
}
return &Route{
Summary: RouteSummary{
2023-03-29 22:45:55 +00:00
Polyline: polylines.Encode(decodedLinestring, 5),
2023-03-27 18:57:28 +00:00
},
2023-03-29 10:51:09 +00:00
Legs: legs,
2023-03-27 18:57:28 +00:00
}, nil
}
func (v *ValhallaRouting) protocolBufferRequest(api *valhalla.Api, path string) (*valhalla.Api, error) {
data, err := proto.Marshal(api)
if err != nil {
return nil, err
}
req, err := http.NewRequest(http.MethodGet, v.BaseURL+path, bytes.NewBuffer(data))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-protobuf")
client := http.Client{}
resp, err := client.Do(req)
//resp, err := http.Post(v.BaseURL+path, "application/x-protobuf", bytes.NewBuffer(data))
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
response := valhalla.Api{}
err = proto.Unmarshal(body, &response)
if err != nil {
return nil, err
}
return &response, nil
}