diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-25 11:32:57 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-25 11:32:57 +0200 |
| commit | 708f5428968b7c1526f257b683d0146ef5dae418 (patch) | |
| tree | 8b4fb6a4e020d79c8a3e62e11defe4cbdc7a3896 /mountain_pass | |
| parent | ff3cd6248f2b78dc76f1ce8cc2337907188fd401 (diff) | |
Make mountain pass and web consumers take ride components instead of a whole Ride
rideBounds, nearestCrossing and DetectCrossings now accept the coordinate,
distance and elevation component slices they read. LoadMountainPassesAroundRide
takes the coords slice only. Web ride view builders and the official climb
creation path iterate ride components (Coords, Distances, Elevations) rather
than per-index accessors on Ride.
Diffstat (limited to 'mountain_pass')
| -rw-r--r-- | mountain_pass/detection.go | 30 | ||||
| -rw-r--r-- | mountain_pass/detection_test.go | 10 |
2 files changed, 20 insertions, 20 deletions
diff --git a/mountain_pass/detection.go b/mountain_pass/detection.go index 09792e3..139bc60 100644 --- a/mountain_pass/detection.go +++ b/mountain_pass/detection.go @@ -29,8 +29,8 @@ func LoadMountainPasses(db *sql.DB) ([]MountainPass, error) { return loadMountainPasses(db, nil) } -func LoadMountainPassesAroundRide(db *sql.DB, route ride.Ride, marginM float64) ([]MountainPass, error) { - return loadMountainPasses(db, rideBounds(route, marginM)) +func LoadMountainPassesAroundRide(db *sql.DB, routeCoords []geodist.Coord, marginM float64) ([]MountainPass, error) { + return loadMountainPasses(db, rideBounds(routeCoords, marginM)) } type coordinateBounds struct { @@ -40,11 +40,11 @@ type coordinateBounds struct { maxLongitude float64 } -func rideBounds(route ride.Ride, marginM float64) *coordinateBounds { - minLatitude, maxLatitude := route.Coord(0).Lat, route.Coord(0).Lat - minLongitude, maxLongitude := route.Coord(0).Lon, route.Coord(0).Lon - for index := 1; index < route.Len(); index++ { - coordinate := route.Coord(index) +func rideBounds(coords []geodist.Coord, marginM float64) *coordinateBounds { + minLatitude, maxLatitude := coords[0].Lat, coords[0].Lat + minLongitude, maxLongitude := coords[0].Lon, coords[0].Lon + for index := 1; index < len(coords); index++ { + coordinate := coords[index] minLatitude = math.Min(minLatitude, coordinate.Lat) maxLatitude = math.Max(maxLatitude, coordinate.Lat) minLongitude = math.Min(minLongitude, coordinate.Lon) @@ -95,13 +95,13 @@ func loadMountainPasses(db *sql.DB, bounds *coordinateBounds) ([]MountainPass, e return mountainPasses, rows.Err() } -func DetectCrossings(ride ride.Ride, passes []MountainPass, radiusM, elevationToleranceM float64) []Crossing { +func DetectCrossings(coords []geodist.Coord, distances, elevations []float64, passes []MountainPass, radiusM, elevationToleranceM float64) []Crossing { crossings := make([]Crossing, 0) for _, mountainPass := range passes { if mountainPass.Coord == nil { continue } - crossing, found := nearestCrossing(ride, mountainPass) + crossing, found := nearestCrossing(coords, distances, elevations, mountainPass) if found && crossing.DistanceToM <= radiusM && crossing.ElevationDiff <= elevationToleranceM { crossings = append(crossings, crossing) } @@ -138,16 +138,16 @@ func MatchClimb(climb ride.Climb, passes []MountainPass, radiusM, elevationToler return best, found } -func nearestCrossing(ride ride.Ride, mountainPass MountainPass) (Crossing, bool) { +func nearestCrossing(coords []geodist.Coord, distances, elevations []float64, mountainPass MountainPass) (Crossing, bool) { best := Crossing{Pass: mountainPass, DistanceToM: 1e18} - for i := 0; i < ride.Len(); i++ { - distanceKm, _ := geodist.HaversineDistance(ride.Coord(i), *mountainPass.Coord) + for i := 0; i < len(coords); i++ { + distanceKm, _ := geodist.HaversineDistance(coords[i], *mountainPass.Coord) distanceM := distanceKm * 1000 if distanceM < best.DistanceToM { best.DistanceToM = distanceM - best.RideDistanceM = ride.DistanceM(i) - best.RideElevation = ride.ElevationM(i) - best.ElevationDiff = absFloat64(ride.ElevationM(i) - float64(mountainPass.Elevation)) + best.RideDistanceM = distances[i] + best.RideElevation = elevations[i] + best.ElevationDiff = absFloat64(elevations[i] - float64(mountainPass.Elevation)) } } if best.DistanceToM > 1e17 { diff --git a/mountain_pass/detection_test.go b/mountain_pass/detection_test.go index f55532b..39bb9ae 100644 --- a/mountain_pass/detection_test.go +++ b/mountain_pass/detection_test.go @@ -18,7 +18,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, []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) @@ -46,7 +46,7 @@ func TestLoadMountainPassesAroundRideUsesExpandedBounds(t *testing.T) { []geodist.Coord{{Lat: 43.0, Lon: 5.0}, {Lat: 43.1, Lon: 5.1}}, make([]time.Time, 2), ) - passes, err := mountain_pass.LoadMountainPassesAroundRide(db, route, 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) @@ -81,13 +81,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, []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, []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) { @@ -96,7 +96,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, []mountain_pass.MountainPass{pass}, 100, 25)) + assert.Empty(t, mountain_pass.DetectCrossings(r.Coords(), r.Distances(), r.Elevations(), []mountain_pass.MountainPass{pass}, 100, 25)) } func rideFromPoint(t *testing.T, latitude, longitude, elevation float64) ride.Ride { |
