diff options
| author | Daniel Schadt <kingdread@gmx.de> | 2026-09-27 22:07:29 +0200 |
|---|---|---|
| committer | Daniel Schadt <kingdread@gmx.de> | 2026-09-27 22:07:29 +0200 |
| commit | 2ac7a51cfb51e4a9597e10cf081e81cc19c3f642 (patch) | |
| tree | 96e3bf8847d5ef72c137ff5abf617827217213be | |
| parent | 77a12c168822ec62a1669103f9e94a8d5d30c0b3 (diff) | |
| download | fietsboek-2ac7a51cfb51e4a9597e10cf081e81cc19c3f642.tar.gz fietsboek-2ac7a51cfb51e4a9597e10cf081e81cc19c3f642.tar.bz2 fietsboek-2ac7a51cfb51e4a9597e10cf081e81cc19c3f642.zip | |
shave trailing downhill off climbs
| -rw-r--r-- | fietsboek/geo.py | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/fietsboek/geo.py b/fietsboek/geo.py index 190454b..e747f4d 100644 --- a/fietsboek/geo.py +++ b/fietsboek/geo.py @@ -24,7 +24,7 @@ CLIMB_MIN_LENGTH = 500 CLIMB_MIN_ASCENSION = 0.03 """Minimum relative ascension for a segment to be considered a climb.""" -CLIMB_MERGE_THRESHOLD = 5 +CLIMB_MERGE_THRESHOLD = 50 """Window for when climbs are merged (in m).""" @@ -69,6 +69,15 @@ class MovementData: downhill: float = 0.0 """Downhill elevation, in meters.""" + elevation_gain: float = 0.0 + """Elevation gain, in meters.""" + + min_elevation: float = 0.0 + """Minimum elevation, in meters.""" + + max_elevation: float = 0.0 + """Maximum elevation, in meters.""" + @dataclass(slots=True) class Point: @@ -157,6 +166,25 @@ class Path: else: speed = 0.0 elevation = b.elevation - a.elevation + movement_data.elevation_gain += elevation + + if movement_data.min_elevation == 0.0: + movement_data.min_elevation = min(a.elevation, b.elevation) + else: + movement_data.min_elevation = min( + a.elevation, + b.elevation, + movement_data.min_elevation, + ) + + if movement_data.max_elevation == 0.0: + movement_data.max_elevation = max(a.elevation, b.elevation) + else: + movement_data.max_elevation = max( + a.elevation, + b.elevation, + movement_data.max_elevation, + ) movement_data.length += distance if speed >= MOVING_THRESHOLD: @@ -182,8 +210,21 @@ class Path: :return: An iterator over the climbs, represented by the starting index and ending index of points included in the climb. """ + return self._trimmed_climbs() + + def _trimmed_climbs(self): + for i, j in self._merged_climbs(): + # We don't want a climb to end in a "downhill" part, even if that + # technically is still above the grade threshold. Therefore, we + # shave off everything downhill at the end. + max_elevation = max(point.elevation for point in self.points[i:j]) + while self.points[j].elevation < max_elevation: + j -= 1 + yield (i, j) + + def _merged_climbs(self): current_climb = None - for climb in self._climbs(): + for climb in self._raw_climbs(): if current_climb is None: current_climb = climb else: @@ -196,7 +237,7 @@ class Path: if current_climb is not None: yield current_climb - def _climbs(self): + def _raw_climbs(self): i = 0 while i < len(self.points): |
