fix(extract): Kreuzungsstummel schmaeler wachsen lassen, GeometryCollection-Absturz beheben
_walk_source() nahm bisher die ganze junction_area() eines Knotens auf, sobald irgendein anliegender Arm Bordstein hat - auch den Anteil, der zu einer dort einmuendenden Gasse gehoert. Der Gehweg wuchs dadurch die volle Laenge des Kreuzungsstummels die Gasse hinauf (bis zu setback+1, beim Boulevard 11 m) statt nur um die Ecke. _kerbless_zone() bekommt den extra-Parameter zurueck (_kerb_lines() und _walk_source() rufen sie beide mit 0.2 auf) und beschneidet jetzt auch den Kreuzungsanteil der Gehwegquelle. Gemessen: an einer T-Kreuzung (2 Gassen + 1 Wohnstrasse) verschwindet der fehlerhafte Gassenstummel-Gehweg vollstaendig (53,11 -> 0,0 m2). An einer 4-Wege-Kreuzung mit 3 Gassen + 1 Boulevard reicht der Fix nicht aus: der Rest in der Nische zwischen zwei Gassenstummeln schrumpft nur auf 27,14 statt der erwarteten rund 2 m2, und seine maximale Ausdehnung von der Kreuzungsmitte (11,14 m) liegt weit ueber der als Grenze genannten 3-4 m - dokumentiert als bekannter, nicht ausreichend geloester Punkt, siehe Fixbericht. Unabhaengig davon: MultiPolygon([result]) wirft TypeError, wenn result eine GeometryCollection ist (intersection()/difference() liefern das gelegentlich an Beruehrstellen, mit einer entarteten Nulllinie neben echten Polygonen). Neuer Helfer to_multipolygon() in section.py filtert auf echte Polygone, statt daran abzustuerzen; carriageway_area() und _sidewalk() nutzen ihn beide. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ca5710730e
commit
685ac666e6
4 files changed
+127
-28
No files matched your search
@@ -1,8 +1,10 @@
|
||||
"""Querschnitte und Fahrbahnbänder."""
|
||||
from __future__ import annotations
|
||||
|
||||
from shapely.geometry import GeometryCollection, LineString, box
|
||||
|
||||
from leonida.roads import CLASS_WIDTH, Edge, Graph, Node
|
||||
from leonida.section import LANE, SECTION, ribbon, setback, trimmed_line
|
||||
from leonida.section import LANE, SECTION, ribbon, setback, to_multipolygon, trimmed_line
|
||||
|
||||
|
||||
def strecke(klass: str, length: float = 100.0) -> Graph:
|
||||
@@ -66,3 +68,25 @@ def test_kante_ganz_innerhalb_der_kreuzung_liefert_kein_band():
|
||||
assert graph.degree(0) == 3 and graph.degree(1) == 3
|
||||
assert trimmed_line(graph, 0) is None
|
||||
assert ribbon(graph, 0) is None
|
||||
|
||||
|
||||
def test_geometriesammlung_wird_zu_reinem_multipolygon():
|
||||
# Fixrunde 4 zu Task 7: intersection()/difference() liefern nicht immer sauber ein
|
||||
# (Multi)Polygon zurück - an einer Berührstelle kann eine GeometryCollection mit einer
|
||||
# zusätzlichen entarteten Linie oder einem Punkt herauskommen (am Gehweg gemeldet).
|
||||
# MultiPolygon(geoms) nimmt aber nur Polygone entgegen und wirft eine TypeError, sobald ein
|
||||
# Bestandteil davon abweicht - carriageway_area() und _sidewalk() (street.py) stürzten daran
|
||||
# ab. Hier direkt erzwungen (zwei Polygone plus eine entartete Nulllinie), weil sich die
|
||||
# Geometriesammlung über echte Fahrbahnrechnungen trotz mehrerer Versuche nicht zuverlässig
|
||||
# nachbauen ließ - GEOS bereinigt Berührstellen bei Polygon-Operationen erstaunlich robust.
|
||||
entartet = GeometryCollection([box(0, 0, 10, 10), box(20, 0, 30, 10), LineString([(15, 5), (15, 5)])])
|
||||
assert entartet.geom_type == "GeometryCollection"
|
||||
ergebnis = to_multipolygon(entartet)
|
||||
assert ergebnis.geom_type == "MultiPolygon"
|
||||
assert len(ergebnis.geoms) == 2, "nur die zwei echten Flächen, die Nulllinie fällt weg"
|
||||
assert round(ergebnis.area) == 200
|
||||
|
||||
|
||||
def test_leere_geometrie_wird_zu_leerem_multipolygon():
|
||||
assert to_multipolygon(GeometryCollection()).geom_type == "MultiPolygon"
|
||||
assert to_multipolygon(GeometryCollection()).is_empty
|
||||
Reference in new issue
Block a user