-
Notifications
You must be signed in to change notification settings - Fork 7
/
isochrones_wrapper.go
65 lines (59 loc) · 1.97 KB
/
isochrones_wrapper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package horizon
import (
"fmt"
"log"
"github.com/pkg/errors"
)
// IsochronesResult Representation of isochrones algorithm's output
/*
*/
type IsochronesResult []*Isochrone
type Isochrone struct {
Vertex *Vertex
Cost float64
}
// FindIsochrones Find shortest path between two obserations (not necessary GPS points).
/*
NOTICE: this function snaps point to only one nearest vertex (without multiple candidates for provided point)
source - source for outcoming isochrones
maxCost - max cost restriction for single isochrone line
maxNearestRadius - max radius of search for nearest vertex
*/
func (matcher *MapMatcher) FindIsochrones(source *GPSMeasurement, maxCost float64, maxNearestRadius float64) (IsochronesResult, error) {
closestSource, _ := matcher.engine.s2Storage.NearestNeighborsInRadius(source.Point, maxNearestRadius, 1)
if len(closestSource) == 0 {
// @todo need to handle this case properly...
return nil, ErrSourceNotFound
}
// Find corresponding edge
s2polylineSource := matcher.engine.s2Storage.edges[closestSource[0].edgeID]
// Find vertex for 'source' point
m, n := s2polylineSource.Source, s2polylineSource.Target
edgeSource := matcher.engine.edges[m][n]
if edgeSource == nil {
return nil, fmt.Errorf("Edge 'source' not found in graph")
}
_, fractionSource, _ := calcProjection(*edgeSource.Polyline, source.Point)
choosenSourceVertex := n
if fractionSource > 0.5 {
choosenSourceVertex = m
} else {
choosenSourceVertex = n
}
ans, err := matcher.engine.graph.Isochrones(choosenSourceVertex, maxCost)
if err != nil {
return nil, errors.Wrapf(err, "Can't call isochrones for vertex with id '%d'", choosenSourceVertex)
}
isochrones := make(IsochronesResult, 0, len(ans))
for vertexID, cost := range ans {
vertex, ok := matcher.engine.vertices[vertexID]
if !ok {
log.Printf("[WARNING]; No such vertex in storage: %d\n", vertexID)
}
isochrones = append(isochrones, &Isochrone{
Vertex: vertex,
Cost: cost,
})
}
return isochrones, nil
}