feat(extract): Bordstein an jeder Straße, auch an der Gasse
Der Bordstein ist keine Ausstattung wie ein Gehweg, sondern die Kante, an der der Asphalt endet — und die hat auch eine Hinterhofgasse. _kerb_lines() schneidet darum nur noch die Brücken aus dem Fahrbahnrand: Dort steckt die Fahrbahn im Deck, eine Kante stünde in der Luft. Gehweg und Markierung bleiben der Gasse weiterhin fern. Das Feld kerb im Querschnitt entfällt. Es steuerte zuletzt nur noch Gehweg und Markierung und war aus walk > 0 ableitbar; kerb_only heißt deshalb jetzt walk_only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
897eb8a1f6
commit
322693c892
5 files changed
+50
-50
No files matched your search
@@ -31,15 +31,14 @@ class Section:
|
||||
walk: float
|
||||
lanes: int
|
||||
parking: float
|
||||
kerb: bool
|
||||
|
||||
|
||||
SECTION = {
|
||||
# Hinterhofgasse: eine Fahrgasse, kein Bordstein, kein Gehweg, keine Markierung.
|
||||
"gasse": Section(corridor=6.0, carriageway=6.0, walk=0.0, lanes=1, parking=0.0, kerb=False),
|
||||
"wohnstrasse": Section(corridor=12.0, carriageway=7.0, walk=2.5, lanes=2, parking=0.0, kerb=True),
|
||||
"hauptstrasse": Section(corridor=18.0, carriageway=12.0, walk=3.0, lanes=2, parking=2.5, kerb=True),
|
||||
"boulevard": Section(corridor=24.0, carriageway=18.0, walk=3.0, lanes=4, parking=2.0, kerb=True),
|
||||
"gasse": Section(corridor=6.0, carriageway=6.0, walk=0.0, lanes=1, parking=0.0),
|
||||
"wohnstrasse": Section(corridor=12.0, carriageway=7.0, walk=2.5, lanes=2, parking=0.0),
|
||||
"hauptstrasse": Section(corridor=18.0, carriageway=12.0, walk=3.0, lanes=2, parking=2.5),
|
||||
"boulevard": Section(corridor=24.0, carriageway=18.0, walk=3.0, lanes=4, parking=2.0),
|
||||
}
|
||||
assert all(s.carriageway + 2 * s.walk == s.corridor == CLASS_WIDTH[n] for n, s in SECTION.items())
|
||||
|
||||
@@ -78,18 +77,18 @@ def ribbon(graph: Graph, k: int):
|
||||
FILLET = 6.0
|
||||
|
||||
|
||||
def junction_arms(graph: Graph, node: int, kerb_only: bool = False) -> list:
|
||||
def junction_arms(graph: Graph, node: int, walk_only: bool = False) -> list:
|
||||
"""Die Armstummel einer Kreuzung, je auf ihre eigene Fahrbahnbreite gepuffert.
|
||||
|
||||
Zweimal gebraucht (Fixrunde 5 zu Task 7): junction_area() vereinigt alle und rundet die
|
||||
einspringenden Ecken; die Gehwegquelle in street.py nimmt nur die Arme mit Bordstein, ohne
|
||||
einspringenden Ecken; die Gehwegquelle in street.py nimmt nur die Arme mit Gehweg, ohne
|
||||
Rundung. Deshalb hier einmal, statt die Stummelbildung zu wiederholen.
|
||||
"""
|
||||
reach = setback(graph, node)
|
||||
arme = []
|
||||
for k in graph.incident(node):
|
||||
edge = graph.edges[k]
|
||||
if len(edge.points) < 2 or (kerb_only and not SECTION[edge.klass].kerb):
|
||||
if len(edge.points) < 2 or (walk_only and not SECTION[edge.klass].walk):
|
||||
continue # Punktkanten haben keine Richtung; LineString wirft an ihnen
|
||||
# Eine Schleife hängt mit beiden Enden am selben Knoten und braucht deshalb zwei Stummel.
|
||||
# incident() liefert sie nur einmal, und edge.a == node ist bei ihr immer wahr — ohne den
|
||||
@@ -104,23 +103,23 @@ def junction_arms(graph: Graph, node: int, kerb_only: bool = False) -> list:
|
||||
return arme
|
||||
|
||||
|
||||
def junction_area(graph: Graph, node: int, kerb_only: bool = False):
|
||||
def junction_area(graph: Graph, node: int, walk_only: bool = False):
|
||||
"""Die Fläche einer Kreuzung: die Stummel aller Arme, mit gerundeten einspringenden Ecken.
|
||||
|
||||
Gerundet wird durch Schließen (aufblasen, dann wieder schrumpfen) - und ausdrücklich nur
|
||||
innerhalb einer Scheibe um den Knoten. Auf das ganze Netz angewandt verklebte dieselbe
|
||||
Operation zwei parallele Straßen, deren Fahrbahnen weniger als 2 * FILLET auseinanderliegen.
|
||||
|
||||
kerb_only rundet nur den Kreuzungsanteil der bordsteintragenden Arme (Befund 7 der Fixwelle,
|
||||
walk_only rundet nur den Kreuzungsanteil der Arme mit Gehweg (Befund 7 der Fixwelle,
|
||||
für die Gehwegquelle in street.py): Eine Gasse liefert dabei gar keinen Arm in die zu
|
||||
schließende Fläche, kann also auch keine Nische mit einem Nachbararm bilden - anders als
|
||||
Fixrunde 4, die dieselbe Rundung auf ALLE Arme anwandte und damit Gassen mit rundete.
|
||||
"""
|
||||
incident = graph.incident(node)
|
||||
if not incident or (kerb_only and not any(SECTION[graph.edges[k].klass].kerb for k in incident)):
|
||||
if not incident or (walk_only and not any(SECTION[graph.edges[k].klass].walk for k in incident)):
|
||||
return None
|
||||
reach = setback(graph, node)
|
||||
star = unary_union(junction_arms(graph, node, kerb_only=kerb_only))
|
||||
star = unary_union(junction_arms(graph, node, walk_only=walk_only))
|
||||
near = Point(graph.nodes[node].point).buffer(reach + FILLET + 2.0)
|
||||
rounded = star.buffer(FILLET, join_style="round").buffer(-FILLET, join_style="round")
|
||||
return star.union(rounded.intersection(near))
|
||||
|
||||
Reference in new issue
Block a user