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
@@ -110,15 +110,26 @@ def junction_area(graph: Graph, node: int):
|
||||
return star.union(rounded.intersection(near))
|
||||
|
||||
|
||||
def to_multipolygon(geom) -> MultiPolygon:
|
||||
"""Nur die Flächenanteile einer Geometrie, als MultiPolygon.
|
||||
|
||||
intersection()/difference() liefern nicht immer sauber ein (Multi)Polygon: An einer
|
||||
Berührstelle kann eine GeometryCollection mit zusätzlichen entarteten Linien oder Punkten
|
||||
herauskommen (Fixrunde 4 zu Task 7, am Gehweg reproduziert). MultiPolygon(geoms) nimmt aber
|
||||
nur Polygone entgegen und wirft eine TypeError, sobald ein Element davon abweicht - hier
|
||||
werden die Nicht-Flächen-Teile deshalb verworfen, statt dass die Rechnung daran abstürzt.
|
||||
"""
|
||||
if geom.is_empty:
|
||||
return MultiPolygon()
|
||||
return MultiPolygon([g for g in getattr(geom, "geoms", [geom]) if g.geom_type == "Polygon"])
|
||||
|
||||
|
||||
def carriageway_area(graph: Graph):
|
||||
"""Alle Bänder und alle Kreuzungsflächen als eine Geometrie."""
|
||||
parts = [band for k in range(len(graph.edges)) if (band := ribbon(graph, k)) is not None]
|
||||
parts += [area for node in range(len(graph.nodes)) if graph.degree(node) >= 3
|
||||
and (area := junction_area(graph, node)) is not None]
|
||||
vereint = unary_union(parts)
|
||||
if vereint.is_empty:
|
||||
return MultiPolygon()
|
||||
# Zusage der Schnittstelle: immer MultiPolygon. unary_union() liefert bei zusammenhängender
|
||||
# Eingabe ein einfaches Polygon, und Task 7 iteriert über .geoms — das bricht dann an kleinen
|
||||
# Prüfkörpern, aber nicht am echten Netz, also genau da, wo niemand damit rechnet.
|
||||
return vereint if vereint.geom_type == "MultiPolygon" else MultiPolygon([vereint])
|
||||
return to_multipolygon(unary_union(parts))
|
||||
Reference in new issue
Block a user