From 63779a61151babf9dc60d55acc81e3a97811a60e Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Sat, 4 Mar 2023 17:43:02 +0100 Subject: transformers: de-duplicate fixup code --- fietsboek/transformers/__init__.py | 43 ++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/fietsboek/transformers/__init__.py b/fietsboek/transformers/__init__.py index f98a545..f6318d7 100644 --- a/fietsboek/transformers/__init__.py +++ b/fietsboek/transformers/__init__.py @@ -10,7 +10,7 @@ function to load and apply transformers. """ from abc import ABC, abstractmethod -from collections.abc import Mapping +from collections.abc import Callable, Iterable, Mapping from itertools import islice from typing import Literal, NamedTuple, TypeVar @@ -155,7 +155,7 @@ class FixNullElevation(Transformer): def parameters(self, value): pass - def execute(self, gpx): + def execute(self, gpx: GPX): def all_points(): return ( point @@ -172,30 +172,37 @@ class FixNullElevation(Transformer): for point in reversed(segment.points) ) - max_slope = 1.0 + # First, from the front + self.fixup(all_points) + # Then, from the back + self.fixup(rev_points) - # First, from the front, find the first point with non-zero elevation (or low enough slope) - bad_until = 0 - final_elevation = 0 - for i, (point, next_point) in enumerate(zip(all_points(), islice(all_points(), 1, None))): - if point.elevation != 0.0 and self.slope(point, next_point) < max_slope: - bad_until = i - final_elevation = point.elevation - break + @classmethod + def fixup(cls, points: Callable[[], Iterable[GPXTrackPoint]]): + """Fixes the given GPX points. - for point in islice(all_points(), None, bad_until): - point.elevation = final_elevation + This iterates over the points and checks for the first point that has a + non-zero elevation, and a slope that doesn't exceed 100%. All previous + points will have their elevation adjusted to match this first "good + point". + + :param points: A function that generates the iterable of points. + """ + max_slope = 1.0 - # Second, from the back bad_until = 0 - final_elevation = 0 - for i, (point, prev_point) in enumerate(zip(rev_points(), islice(rev_points(), 1, None))): - if point.elevation != 0.0 and self.slope(point, prev_point) < max_slope: + final_elevation = 0.0 + for i, (point, next_point) in enumerate(zip(points(), islice(points(), 1, None))): + if ( + point.elevation is not None + and point.elevation != 0.0 + and cls.slope(point, next_point) < max_slope + ): bad_until = i final_elevation = point.elevation break - for point in islice(rev_points(), None, bad_until): + for point in islice(points(), None, bad_until): point.elevation = final_elevation @staticmethod -- cgit v1.2.3