diff options
Diffstat (limited to 'mountain_pass')
| -rw-r--r-- | mountain_pass/detection.go | 33 | ||||
| -rw-r--r-- | mountain_pass/detection_test.go | 24 |
2 files changed, 28 insertions, 29 deletions
diff --git a/mountain_pass/detection.go b/mountain_pass/detection.go index 40281f3..79e55e4 100644 --- a/mountain_pass/detection.go +++ b/mountain_pass/detection.go @@ -5,7 +5,8 @@ import ( "math" "github.com/jftuga/geodist" - "github.com/martinlehoux/biking_home/ride" + "github.com/martinlehoux/biking_home/climb" + "github.com/martinlehoux/biking_home/geo" ) // MountainPass is a pass extracted from OpenStreetMap: a node tagged @@ -112,9 +113,9 @@ func DetectCrossings(coords []geodist.Coord, distances, elevations []float64, pa // MatchClimb returns the pass whose coordinates lie within radiusM of the // climb's highest point and whose elevation is within elevationToleranceM of // that point's elevation, nearest first. Found is false when no pass matches. -func MatchClimb(climb ride.Climb, passes []MountainPass, radiusM, elevationToleranceM float64) (MountainPass, bool) { - topCoord := climb.TopCoord() - topElevation := climb.TopElevationM() +func MatchClimb(segment climb.Climb, passes []MountainPass, radiusM, elevationToleranceM float64) (MountainPass, bool) { + topIndex, topElevation := segment.Top() + topCoord := segment.Coords[topIndex] var best MountainPass bestDistanceM := radiusM found := false @@ -139,21 +140,17 @@ func MatchClimb(climb ride.Climb, passes []MountainPass, radiusM, elevationToler } func nearestCrossing(coords []geodist.Coord, distances, elevations []float64, mountainPass MountainPass) (Crossing, bool) { - best := Crossing{Pass: mountainPass, DistanceToM: 1e18} - for i := range coords { - distanceKm, _ := geodist.HaversineDistance(coords[i], *mountainPass.Coord) - distanceM := distanceKm * 1000 - if distanceM < best.DistanceToM { - best.DistanceToM = distanceM - best.RideDistanceM = distances[i] - best.RideElevation = elevations[i] - best.ElevationDiff = absFloat64(elevations[i] - float64(mountainPass.Elevation)) - } - } - if best.DistanceToM > 1e17 { - return best, false + index, distanceM := geo.Nearest(coords, *mountainPass.Coord) + if math.IsInf(distanceM, 1) { + return Crossing{Pass: mountainPass}, false } - return best, true + return Crossing{ + Pass: mountainPass, + DistanceToM: distanceM, + RideDistanceM: distances[index], + RideElevation: elevations[index], + ElevationDiff: absFloat64(elevations[index] - float64(mountainPass.Elevation)), + }, true } func absFloat64(value float64) float64 { diff --git a/mountain_pass/detection_test.go b/mountain_pass/detection_test.go index 6318ca3..6b297b5 100644 --- a/mountain_pass/detection_test.go +++ b/mountain_pass/detection_test.go @@ -5,8 +5,10 @@ import ( "testing" "github.com/jftuga/geodist" + "github.com/martinlehoux/biking_home/climb" "github.com/martinlehoux/biking_home/internal/dbtest" "github.com/martinlehoux/biking_home/internal/ridetest" + "github.com/martinlehoux/biking_home/internal/routetest" "github.com/martinlehoux/biking_home/mountain_pass" "github.com/martinlehoux/biking_home/ride" "github.com/stretchr/testify/assert" @@ -19,7 +21,7 @@ func TestDetectCrossingsFindsPass(t *testing.T) { Name: "Pas de Magnan", Elevation: 460, Coord: &geodist.Coord{Lat: 43.62, Lon: 5.43}, } - crossings := mountain_pass.DetectCrossings(r.Coords(), r.Distances(), r.Elevations(), []mountain_pass.MountainPass{pass}, 100, 25) + crossings := mountain_pass.DetectCrossings(r.Coords, r.Distances, r.Elevations, []mountain_pass.MountainPass{pass}, 100, 25) assert.Len(t, crossings, 1) assert.Equal(t, "Pas de Magnan", crossings[0].Pass.Name) assert.Less(t, crossings[0].DistanceToM, 10.0) @@ -42,7 +44,7 @@ func TestLoadMountainPassesAroundRideUsesExpandedBounds(t *testing.T) { require.NoError(t, err) route := ridetest.MustRide("1km at 10%", ridetest.StartCoord(43.0, 5.0), ridetest.Heading(0.1, 0.1), ridetest.StartElevation(100), ridetest.Sampling(1000)) - passes, err := mountain_pass.LoadMountainPassesAroundRide(db, route.Coords(), 10_000) + passes, err := mountain_pass.LoadMountainPassesAroundRide(db, route.Coords, 10_000) require.NoError(t, err) require.Len(t, passes, 3) assert.Equal(t, "On route edge", passes[0].Name) @@ -77,13 +79,13 @@ func TestDetectCrossingsIgnoresDistantPass(t *testing.T) { Name: "Col de la Faucille", Elevation: 1320, Coord: &geodist.Coord{Lat: 46.37, Lon: 6.02}, } - assert.Empty(t, mountain_pass.DetectCrossings(r.Coords(), r.Distances(), r.Elevations(), []mountain_pass.MountainPass{far}, 100, 25)) + assert.Empty(t, mountain_pass.DetectCrossings(r.Coords, r.Distances, r.Elevations, []mountain_pass.MountainPass{far}, 100, 25)) } func TestDetectCrossingsIgnoresPassWithoutCoordinates(t *testing.T) { r := rideFromPoint(t, 43.62, 5.43, 447) noCoord := mountain_pass.MountainPass{Name: "Col de la Gatasse", Elevation: 120} - assert.Empty(t, mountain_pass.DetectCrossings(r.Coords(), r.Distances(), r.Elevations(), []mountain_pass.MountainPass{noCoord}, 100, 25)) + assert.Empty(t, mountain_pass.DetectCrossings(r.Coords, r.Distances, r.Elevations, []mountain_pass.MountainPass{noCoord}, 100, 25)) } func TestDetectCrossingsRequiresElevationAgreement(t *testing.T) { @@ -92,7 +94,7 @@ func TestDetectCrossingsRequiresElevationAgreement(t *testing.T) { Name: "Pas de Magnan", Elevation: 900, Coord: &geodist.Coord{Lat: 43.62, Lon: 5.43}, } - assert.Empty(t, mountain_pass.DetectCrossings(r.Coords(), r.Distances(), r.Elevations(), []mountain_pass.MountainPass{pass}, 100, 25)) + assert.Empty(t, mountain_pass.DetectCrossings(r.Coords, r.Distances, r.Elevations, []mountain_pass.MountainPass{pass}, 100, 25)) } // rideFromPoint builds a 1 km ride ending at (latitude, longitude) at the @@ -144,10 +146,10 @@ func TestMatchClimbNearestOfTwo(t *testing.T) { // climbFixture builds a 2 km climb from 300 m up to 447 m then back down to // 380 m, heading northeast from (43.61, 5.42). -func climbFixture() ride.Climb { - r := ridetest.MustRide("1km at 14.7% | 1km at -6.7%", - ridetest.StartCoord(43.61, 5.42), - ridetest.StartElevation(300), - ridetest.Sampling(1000)) - return r.ClimbFromDist(0, 2000) +func climbFixture() climb.Climb { + route := routetest.MustRoute("1km at 14.7% | 1km at -6.7%", + routetest.StartCoord(43.61, 5.42), + routetest.StartElevation(300), + routetest.Sampling(1000)) + return climb.Climb{Route: route} } |
