fix(extract): Schleifen-Kante bekommt zwei Stummel in junction_area()
incident() liefert eine Schleife (a == b) nur einmal, und edge.a == node ist bei ihr immer wahr - die zweite Abgangsrichtung bekam deshalb nie einen eigenen Arm im Kreuzungsfächer. Das war kein Schönheitsfehler, sondern ein Loch in der Fahrbahn genau dort, wo das zurückgeschnittene Schleifenband auf die Kreuzungsfläche trifft: 179 von 196 Schleifen sitzen an einem Knoten mit Grad >= 3 und waren betroffen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5ddcbbfc17
commit
f91b5ab7c6
2 files changed
+29
-5
No files matched your search
@@ -92,11 +92,18 @@ def junction_area(graph: Graph, node: int):
|
|||||||
arms = []
|
arms = []
|
||||||
for k in incident:
|
for k in incident:
|
||||||
edge = graph.edges[k]
|
edge = graph.edges[k]
|
||||||
points = edge.points if edge.a == node else list(reversed(edge.points))
|
if len(edge.points) < 2:
|
||||||
line = LineString(points)
|
continue # Punktkanten haben keine Richtung; LineString wirft an ihnen
|
||||||
stub = substring(line, 0.0, min(reach + 1.0, line.length))
|
# Eine Schleife hängt mit beiden Enden am selben Knoten und braucht deshalb zwei Stummel.
|
||||||
arms.append(stub.buffer(SECTION[edge.klass].carriageway / 2,
|
# incident() liefert sie nur einmal, und edge.a == node ist bei ihr immer wahr — ohne den
|
||||||
cap_style="flat", join_style="mitre", mitre_limit=1.5))
|
# zweiten Stummel bliebe an ihrem anderen Ende ein Loch in der Fahrbahn.
|
||||||
|
richtungen = ([edge.points, list(reversed(edge.points))] if edge.a == edge.b
|
||||||
|
else [edge.points if edge.a == node else list(reversed(edge.points))])
|
||||||
|
for points in richtungen:
|
||||||
|
line = LineString(points)
|
||||||
|
stub = substring(line, 0.0, min(reach + 1.0, line.length))
|
||||||
|
arms.append(stub.buffer(SECTION[edge.klass].carriageway / 2,
|
||||||
|
cap_style="flat", join_style="mitre", mitre_limit=1.5))
|
||||||
star = unary_union(arms)
|
star = unary_union(arms)
|
||||||
near = Point(graph.nodes[node].point).buffer(reach + FILLET + 2.0)
|
near = Point(graph.nodes[node].point).buffer(reach + FILLET + 2.0)
|
||||||
rounded = star.buffer(FILLET, join_style="round").buffer(-FILLET, join_style="round")
|
rounded = star.buffer(FILLET, join_style="round").buffer(-FILLET, join_style="round")
|
||||||
|
|||||||
@@ -42,3 +42,20 @@ def test_fahrbahn_enthaelt_baender_und_kreuzung():
|
|||||||
assert area.contains(Point(0, 0)), "die Kreuzung selbst"
|
assert area.contains(Point(0, 0)), "die Kreuzung selbst"
|
||||||
assert area.contains(Point(40, 0)), "ein Band"
|
assert area.contains(Point(40, 0)), "ein Band"
|
||||||
assert not area.contains(Point(40, 40)), "die Ecke zwischen zwei Armen bleibt frei"
|
assert not area.contains(Point(40, 40)), "die Ecke zwischen zwei Armen bleibt frei"
|
||||||
|
|
||||||
|
|
||||||
|
def test_schleife_bekommt_zwei_stummel_kein_loch_im_belag():
|
||||||
|
# Eine Schleife hängt mit beiden Enden am selben Knoten. incident() liefert sie nur einmal,
|
||||||
|
# und edge.a == node ist bei ihr immer wahr - ohne einen zweiten Stummel für die zweite
|
||||||
|
# Abgangsrichtung bliebe zwischen dem zurückgeschnittenen Schleifenband und der
|
||||||
|
# Kreuzungsfläche ein Loch. Zwei gerade Arme sorgen dafür, dass der Knoten überhaupt als
|
||||||
|
# Kreuzung (Grad >= 3) zählt.
|
||||||
|
graph = Graph(
|
||||||
|
nodes=[Node((0.0, 0.0)), Node((-100.0, 0.0)), Node((0.0, -100.0))],
|
||||||
|
edges=[Edge(0, 0, [(0.0, 0.0), (0.0, 20.0), (20.0, 20.0), (20.0, 0.0), (0.0, 0.0)], 18.0, "hauptstrasse"),
|
||||||
|
Edge(0, 1, [(0.0, 0.0), (-100.0, 0.0)], 18.0, "hauptstrasse"),
|
||||||
|
Edge(0, 2, [(0.0, 0.0), (0.0, -100.0)], 18.0, "hauptstrasse")])
|
||||||
|
area = carriageway_area(graph)
|
||||||
|
# Zwischen der Kreuzungsfläche (endet bei halber Fahrbahn = 6 m) und dem zurückgeschnittenen
|
||||||
|
# Schleifenband (beginnt beim Setback = 8 m) liegt (7, 0) - ohne den zweiten Stummel außerhalb.
|
||||||
|
assert area.contains(Point(7.0, 0.0))
|
||||||
Reference in new issue
Block a user