From 7b1ebfa7eaa0ed4f30035f905f64054578980020 Mon Sep 17 00:00:00 2001 From: Thomas Rouch Date: Wed, 16 Jul 2025 20:14:42 +0000 Subject: [PATCH 1/2] fix name --- pretty_gpx/test/test_bridges.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pretty_gpx/test/test_bridges.py b/pretty_gpx/test/test_bridges.py index 2fb37d2..64e94aa 100644 --- a/pretty_gpx/test/test_bridges.py +++ b/pretty_gpx/test/test_bridges.py @@ -49,7 +49,8 @@ def test_new_york_bridges() -> None: "Pulaski Bridge", "Willis Avenue Bridge", "Queensboro Bridge", - "Verrazzano-Narrows Bridge"}) + "Verrazzano Bridge"}) + def test_berlin_bridges() -> None: """Test Berlin Bridges.""" From 41725816183bfa9bd6b715440c7cceac23788afc Mon Sep 17 00:00:00 2001 From: Thomas Rouch Date: Wed, 16 Jul 2025 20:14:51 +0000 Subject: [PATCH 2/2] lint --- .../rendering_modes/city/data/bridges.py | 25 +++++++++++-------- pretty_gpx/test/test_bridges.py | 1 + 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/pretty_gpx/rendering_modes/city/data/bridges.py b/pretty_gpx/rendering_modes/city/data/bridges.py index a7166a5..9a9cc68 100644 --- a/pretty_gpx/rendering_modes/city/data/bridges.py +++ b/pretty_gpx/rendering_modes/city/data/bridges.py @@ -36,6 +36,7 @@ BRIDGES_RELATIONS_ARRAY_NAME = "bridges_relations" BRIDGES_WAYS_ARRAY_NAME = "bridges_ways" + @dataclass class Bridge: """Bridge.""" @@ -46,6 +47,7 @@ class Bridge: center: Point direction: tuple[float, float] | None + class BridgeApproximation: """Bridge rectangle approximation.""" MAXIMUM_BRIDGE_ASPECT_RATIO = 0.75 @@ -73,7 +75,7 @@ def get_minimum_rectangle(polygon: ShapelyPolygon, if not hasattr(min_rot_rect, "exterior"): raise ValueError("The minimum rotated rectangle does not have an exterior.") - rectangle = ShapelyPolygon(np.array(min_rot_rect.exterior.coords)) # type: ignore + rectangle = ShapelyPolygon(np.array(min_rot_rect.exterior.coords)) # type: ignore coords = list(rectangle.exterior.coords[:-1]) sides = [(np.linalg.norm(np.array(coords[i]) - np.array(coords[(i + 1) % 4])), LineString([coords[i], coords[(i + 1) % 4]])) for i in range(4)] @@ -101,8 +103,8 @@ def create_bridge(cls, bridge_coords = get_way_coordinates(way_or_relation) elif isinstance(way_or_relation, Relation) and way_or_relation.members: outer_members = [member.geometry for member in way_or_relation.members - if isinstance(member, RelationWay) and member.geometry - and member.role == "outer"] + if isinstance(member, RelationWay) and member.geometry + and member.role == "outer"] merged_ways = merge_ways(outer_members) if len(merged_ways) > 1: logger.error("Multiple geometries found") @@ -126,11 +128,12 @@ def create_bridge(cls, return None return Bridge(name=bridge_name, polygon=bridge_simplified, length=bridge_length, - aspect_ratio=aspect_ratio, center=bridge_polygon.centroid, direction=bridge_dir) + aspect_ratio=aspect_ratio, center=bridge_polygon.centroid, direction=bridge_dir) except Exception as e: logger.error(f"Error processing bridge: {e}") return None + class BridgeCrossingAnalyzer: """Bridge and track intersection.""" INTERSECTION_THRESHOLD = 0.75 @@ -147,8 +150,8 @@ def _calculate_intersection_length(intersection: BaseGeometry) -> float: def _extract_intersection_coordinates(intersection: BaseGeometry) -> tuple[list[float], list[float]] | None: """Extract x,y coordinates from intersection geometry.""" if isinstance(intersection, GeometryCollection | MultiLineString): - coords = [(x, y) for geom in intersection.geoms - if isinstance(geom, LineString) for x, y in geom.coords] + coords = [(x, y) for geom in intersection.geoms + if isinstance(geom, LineString) for x, y in geom.coords] if not coords: return None x_coords, y_coords = zip(*coords) @@ -192,7 +195,7 @@ def analyze_track_bridge_crossing(cls, track: GpxTrack, bridges: list[Bridge]) - intersection_direction = get_average_straight_line(coords[0], coords[1])[1] angle = cls._calculate_crossing_angle(intersection_direction, bridge.direction) - + if angle < cls.ANGLE_THRESHOLD: logger.debug(f"{bridge.name} crossed, angle : {angle}") crossed_bridges.append(bridge) @@ -201,6 +204,7 @@ def analyze_track_bridge_crossing(cls, track: GpxTrack, bridges: list[Bridge]) - return crossed_bridges + @profile def prepare_download_city_bridges(query: OverpassQuery, track: GpxTrack) -> None: """Add the queries for city bridges inside the global OverpassQuery.""" @@ -223,6 +227,7 @@ def prepare_download_city_bridges(query: OverpassQuery, track: GpxTrack) -> None relations=True, radius_m=40) + @profile def process_city_bridges(query: OverpassQuery, track: GpxTrack) -> list[ScatterPoint]: """Process the overpass API result to get the bridges of a city.""" @@ -233,7 +238,7 @@ def process_city_bridges(query: OverpassQuery, track: GpxTrack) -> list[ScatterP bridges_direction: dict[str, tuple[float, LineString]] = {} bridges_stats = {} bridges_to_process = [] - + for way in query.get_query_result(BRIDGES_WAYS_ARRAY_NAME).ways: if way.tags.get("bridge") and "man_made" not in way.tags: line = LineString(get_way_coordinates(way)) @@ -252,7 +257,7 @@ def process_city_bridges(query: OverpassQuery, track: GpxTrack) -> list[ScatterP bridges = [BridgeApproximation.create_bridge(way, bridges_stats) for way in bridges_to_process] bridges.extend(BridgeApproximation.create_bridge(rel, bridges_stats) for rel in query.get_query_result(BRIDGES_RELATIONS_ARRAY_NAME).relations) - + crossed_bridges = BridgeCrossingAnalyzer.analyze_track_bridge_crossing(track, [b for b in bridges if b]) result = [ScatterPoint(name=b.name, lat=b.center.y, lon=b.center.x, category=ScatterPointCategory.CITY_BRIDGE) for b in crossed_bridges] @@ -260,4 +265,4 @@ def process_city_bridges(query: OverpassQuery, track: GpxTrack) -> list[ScatterP logger.info(f"Found {len(result)} bridge(s)") write_pickle(BRIDGES_CACHE.get_path(track), result) query.add_cached_result(BRIDGES_CACHE.name, cache_file=BRIDGES_CACHE.get_path(track)) - return result \ No newline at end of file + return result diff --git a/pretty_gpx/test/test_bridges.py b/pretty_gpx/test/test_bridges.py index 64e94aa..6c81a7c 100644 --- a/pretty_gpx/test/test_bridges.py +++ b/pretty_gpx/test/test_bridges.py @@ -64,6 +64,7 @@ def test_berlin_bridges() -> None: "Kottbusser Brücke", "Potsdamer Brücke"}) + def test_london_bridges() -> None: """Test London Bridges.""" __core_test_bridges(os.path.join(RUNNING_DIR, "marathon_london.gpx"),