aboutsummaryrefslogtreecommitdiff
path: root/official_climb/matcher.go
diff options
context:
space:
mode:
Diffstat (limited to 'official_climb/matcher.go')
-rw-r--r--official_climb/matcher.go66
1 files changed, 23 insertions, 43 deletions
diff --git a/official_climb/matcher.go b/official_climb/matcher.go
index e7b51de..faf51a7 100644
--- a/official_climb/matcher.go
+++ b/official_climb/matcher.go
@@ -4,52 +4,32 @@ import (
"math"
"github.com/jftuga/geodist"
- "github.com/martinlehoux/biking_home/ride"
+ "github.com/martinlehoux/biking_home/geo"
)
-func MatchClimb(route ride.Ride, climb ride.Climb, officialClimbs []OfficialClimb, policy MatchPolicy) (OfficialClimb, bool) {
- if policy.Validate() != nil {
- return OfficialClimb{}, false
- }
- bestDistance := math.Inf(1)
- var best OfficialClimb
- found := false
- for _, official := range officialClimbs {
- startIndex, startDistance := nearestRoutePoint(route, official.StartCoord)
- endIndex, endDistance := nearestRoutePoint(route, official.EndCoord)
- if startDistance > policy.EndpointRadiusM || endDistance > policy.EndpointRadiusM {
- continue
- }
- if startIndex >= endIndex {
- continue
- }
- if endIndex < climb.StartIndex() || startIndex > climb.EndIndex() {
- continue
- }
- totalDistance := startDistance + endDistance
- if totalDistance < bestDistance || (totalDistance == bestDistance && (!found || official.ID < best.ID)) {
- best = official
- bestDistance = totalDistance
- found = true
- }
- }
- return best, found
+// MatchedClimb is an official climb that lies on a route, together with the
+// route point indexes of its start and end. It lets the climb detector know
+// which segment of the route is already claimed by an official climb.
+type MatchedClimb struct {
+ OfficialClimb
+ StartIndex int
+ EndIndex int
}
-func nearestRoutePoint(route ride.Ride, target geodist.Coord) (int, float64) {
- bestIndex := 0
- bestDistance := math.Inf(1)
- for index := 0; index < route.Len(); index++ {
- distance := distanceM(route.Coord(index), target)
- if distance < bestDistance {
- bestIndex = index
- bestDistance = distance
- }
+// MatchClimb matches an official climb against a route purely by
+// coordinates: both the start and end coordinates must be within radiusM of a
+// route point, and the matched start point must precede the matched end point.
+func MatchClimb(route []geodist.Coord, official OfficialClimb, radiusM float64) (MatchedClimb, bool) {
+ if math.IsNaN(radiusM) || math.IsInf(radiusM, 0) || radiusM <= 0 {
+ return MatchedClimb{}, false
}
- return bestIndex, bestDistance
-}
-
-func distanceM(a, b geodist.Coord) float64 {
- _, distanceKm := geodist.HaversineDistance(a, b)
- return distanceKm * 1000
+ startIndex, startDistance := geo.Nearest(route, official.StartCoord)
+ endIndex, endDistance := geo.Nearest(route, official.EndCoord)
+ if startDistance > radiusM || endDistance > radiusM {
+ return MatchedClimb{}, false
+ }
+ if startIndex >= endIndex {
+ return MatchedClimb{}, false
+ }
+ return MatchedClimb{OfficialClimb: official, StartIndex: startIndex, EndIndex: endIndex}, true
}