fix(extract): Zebrabalken mittig verteilt, Kantenbreite gerundet
Befund 8, zwei kleine, aber datenwirksame Funde: - Zebrastreifen: Der Startversatz (-halb + BAR/2, Takt 2*BAR) liess die Balkenreihe an einem Fahrbahnrand bündig sitzen und am gegenüber- liegenden bis zu eine Taktbreite frei (0,6 m bei Hauptstraße/Boulevard, 0,4 m bei Wohnstraße), statt der laut Entwurf verlangten Aufteilung "Balken 60 cm, Lücke 60 cm" über die ganze Breite. n = floor((2*halb + BAR) / (2*BAR)) Balken, symmetrisch bei -(n-1)*BAR gestartet, lassen an beiden Rändern denselben Rest frei (nachgemessen: 0,3 m statt 0/0,6 m bei Hauptstraße, 0,2 m statt 0/0,4 m bei Wohnstraße), ohne die Balkenzahl je Arm zu ändern. - edges[].breite (Median aus der Distanztransformation) kam ungerundet an (Werte wie 31.622776601683793), während jede andere Zahl in der Ausgabe auf 2 Stellen gerundet ist. fahrbahn bleibt unverändert, weil es schon eine der vier festen SECTION-Konstanten ist. Zwei Tests, beide ohne die jeweilige Korrektur rot: die Zebrabalken einer Kreuzungszufahrt lassen ungleiche Ränder (0,0/0,6 m statt 0,3/0,3 m), und eine krumme Kantenbreite blieb ungerundet in der Ausgabe.
This commit is contained in:
1 parent
2605f95951
commit
ca01141c5b
4 files changed
+51
-5
No files matched your search
@@ -139,7 +139,11 @@ def chunk_payload(i, j, *, land, surfaces, carriageway, curb, sidewalk, markings
|
|||||||
key=lambda m: (m["poly"], m["art"])),
|
key=lambda m: (m["poly"], m["art"])),
|
||||||
"lots": sorted(({"poly": _rings(p, i, j)} for p in lots), key=lambda l: l["poly"]),
|
"lots": sorted(({"poly": _rings(p, i, j)} for p in lots), key=lambda l: l["poly"]),
|
||||||
"bridges": sorted(({"poly": _rings(p, i, j)} for p in bridges), key=lambda b: b["poly"]),
|
"bridges": sorted(({"poly": _rings(p, i, j)} for p in bridges), key=lambda b: b["poly"]),
|
||||||
"edges": sorted(({"line": _line(l, i, j), "klasse": k, "breite": w, "fahrbahn": f}
|
# breite ist die gemessene Kantenbreite (Median aus der Distanztransformation) und kommt
|
||||||
|
# ungerundet an (Befund 8 der Fixwelle: Werte wie 31.622776601683793), waehrend jede
|
||||||
|
# andere Zahl in der Ausgabe gerundet ist; fahrbahn ist dagegen schon eine der vier festen
|
||||||
|
# SECTION-Konstanten und braucht keine Rundung.
|
||||||
|
"edges": sorted(({"line": _line(l, i, j), "klasse": k, "breite": round(w, 2), "fahrbahn": f}
|
||||||
for l, k, w, f in edges),
|
for l, k, w, f in edges),
|
||||||
key=lambda e: (e["line"], e["klasse"], e["breite"], e["fahrbahn"])),
|
key=lambda e: (e["line"], e["klasse"], e["breite"], e["fahrbahn"])),
|
||||||
"buildings": sorted(({"poly": _rings(p, i, j), "height": h["height"],
|
"buildings": sorted(({"poly": _rings(p, i, j), "height": h["height"],
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ unterbringen, und aus der Nähe bleibt Geometrie scharf, wo eine Textur verwisch
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
from shapely.geometry import LineString, Polygon
|
from shapely.geometry import LineString, Polygon
|
||||||
from shapely.ops import substring
|
from shapely.ops import substring
|
||||||
|
|
||||||
@@ -157,9 +159,15 @@ def junction_marks(graph: Graph, node: int) -> list[tuple[Polygon, str]]:
|
|||||||
# Haltelinie brauchen unterschiedlich viel Platz, deshalb getrennt geprüft statt
|
# Haltelinie brauchen unterschiedlich viel Platz, deshalb getrennt geprüft statt
|
||||||
# gemeinsam verworfen.
|
# gemeinsam verworfen.
|
||||||
if länge >= reach + CROSSWALK_DEPTH:
|
if länge >= reach + CROSSWALK_DEPTH:
|
||||||
# Balken längs der Fahrtrichtung, quer über die Fahrbahn verteilt.
|
# Balken längs der Fahrtrichtung, mittig über die Fahrbahn verteilt (Befund 8 der
|
||||||
offset = -halb + BAR / 2
|
# Fixwelle): Der alte Startversatz (-halb + BAR/2, im Takt 2*BAR) saß am einen
|
||||||
while offset <= halb - BAR / 2 + 1e-9:
|
# Rand bündig und ließ am anderen bis zu eine Taktbreite frei - 0,6 m bei Haupt-
|
||||||
|
# straße/Boulevard, 0,4 m bei Wohnstraße, statt der verlangten 60/60-cm-Teilung
|
||||||
|
# über die ganze Breite. n Balken im selben Takt, symmetrisch um die Fahrbahnmitte
|
||||||
|
# gestartet, lassen an beiden Rändern denselben Rest frei.
|
||||||
|
n = math.floor((2 * halb + BAR) / (2 * BAR))
|
||||||
|
offset = -(n - 1) * BAR
|
||||||
|
for _ in range(n):
|
||||||
mitte = (origin[0] + across[0] * offset, origin[1] + across[1] * offset)
|
mitte = (origin[0] + across[0] * offset, origin[1] + across[1] * offset)
|
||||||
out.append((_rect(mitte, along, across, reach, CROSSWALK_DEPTH, BAR), "zebra"))
|
out.append((_rect(mitte, along, across, reach, CROSSWALK_DEPTH, BAR), "zebra"))
|
||||||
offset += 2 * BAR
|
offset += 2 * BAR
|
||||||
|
|||||||
@@ -174,6 +174,20 @@ def test_neue_schichten_stehen_im_chunk():
|
|||||||
assert "roads" not in payload and "centerlines" not in payload
|
assert "roads" not in payload and "centerlines" not in payload
|
||||||
|
|
||||||
|
|
||||||
|
def test_edges_breite_wird_gerundet():
|
||||||
|
"""Befund 8 der Fixwelle: breite ist die gemessene Kantenbreite (Median aus der
|
||||||
|
Distanztransformation) und kommt deshalb ungerundet an - am echten Netz Werte wie
|
||||||
|
31.622776601683793 -, während jede andere Zahl in der Ausgabe auf 2 Stellen gerundet ist.
|
||||||
|
fahrbahn bleibt unverändert: Es ist schon eine der vier festen SECTION-Konstanten."""
|
||||||
|
from shapely.geometry import LineString
|
||||||
|
payload = chunk_payload(0, 0, land=[], surfaces=[], carriageway=[], curb=[], sidewalk=[],
|
||||||
|
markings=[], lots=[], bridges=[],
|
||||||
|
edges=[(LineString([(0, 2400), (10, 2400)]), "wohnstrasse",
|
||||||
|
31.622776601683793, 7.0)],
|
||||||
|
buildings=[], palms=[])
|
||||||
|
assert payload["edges"][0]["breite"] == 31.62
|
||||||
|
|
||||||
|
|
||||||
def test_neue_schichten_sind_lauf_stabil():
|
def test_neue_schichten_sind_lauf_stabil():
|
||||||
"""Zwei Aufrufe mit vertauschter Eingabe liefern dieselbe Ausgabe (Fixrunde 3 aus Teil 1)."""
|
"""Zwei Aufrufe mit vertauschter Eingabe liefern dieselbe Ausgabe (Fixrunde 3 aus Teil 1)."""
|
||||||
from shapely.geometry import LineString, box
|
from shapely.geometry import LineString, box
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
|
import pytest
|
||||||
from shapely.geometry import LineString
|
from shapely.geometry import LineString
|
||||||
|
|
||||||
from leonida.roads import Edge, Graph, Node
|
from leonida.roads import Edge, Graph, Node
|
||||||
from leonida.marking import CROSSWALK_DEPTH, junction_marks, markings
|
from leonida.marking import BAR, CROSSWALK_DEPTH, junction_marks, markings
|
||||||
from leonida.section import SECTION, setback
|
from leonida.section import SECTION, setback
|
||||||
|
|
||||||
|
|
||||||
@@ -62,6 +63,25 @@ def test_haltelinie_deckt_nur_die_rechte_haelfte():
|
|||||||
assert round(ost.bounds[3] - ost.bounds[1], 1) == round(SECTION["hauptstrasse"].carriageway / 2, 1)
|
assert round(ost.bounds[3] - ost.bounds[1], 1) == round(SECTION["hauptstrasse"].carriageway / 2, 1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebrabalken_liegen_symmetrisch_zur_fahrbahnmitte():
|
||||||
|
"""Befund 8 der Fixwelle: Der alte Startversatz (-halb + BAR/2, Takt 2*BAR) liess die
|
||||||
|
Balkenreihe an einem Fahrbahnrand bündig sitzen und am gegenüberliegenden bis zu eine
|
||||||
|
Taktbreite frei - 0,6 m bei Hauptstraße/Boulevard, 0,4 m bei Wohnstraße, statt der laut
|
||||||
|
Entwurf verlangten Aufteilung "Balken 60 cm, Lücke 60 cm" über die ganze Breite. n Balken,
|
||||||
|
symmetrisch um die Fahrbahnmitte gestartet, lassen an beiden Rändern denselben Rest frei.
|
||||||
|
"""
|
||||||
|
halb = SECTION["hauptstrasse"].carriageway / 2
|
||||||
|
zebra = [p for p, art in junction_marks(kreuzung(), 0) if art == "zebra"]
|
||||||
|
# Wie in test_zebra_liegt_am_kreuzungsrand: nur der Ostarm, klar von den Nachbararmen isoliert.
|
||||||
|
ost = sorted((p.centroid.y for p in zebra if p.centroid.x > 0 and abs(p.centroid.y) < halb))
|
||||||
|
rand_unten = (ost[0] - BAR / 2) - (-halb)
|
||||||
|
rand_oben = halb - (ost[-1] + BAR / 2)
|
||||||
|
assert rand_unten == pytest.approx(rand_oben, abs=1e-6), (
|
||||||
|
f"Ränder ungleich: unten {rand_unten:.3f} m, oben {rand_oben:.3f} m"
|
||||||
|
)
|
||||||
|
assert rand_unten == pytest.approx(0.3, abs=1e-6), "bei 12 m Fahrbahn bleiben 0,3 m an jedem Rand"
|
||||||
|
|
||||||
|
|
||||||
def test_arm_der_eine_gasse_ist_bekommt_keinen_zebrastreifen():
|
def test_arm_der_eine_gasse_ist_bekommt_keinen_zebrastreifen():
|
||||||
graph = kreuzung(("hauptstrasse", "hauptstrasse", "hauptstrasse", "gasse"))
|
graph = kreuzung(("hauptstrasse", "hauptstrasse", "hauptstrasse", "gasse"))
|
||||||
marks = junction_marks(graph, 0)
|
marks = junction_marks(graph, 0)
|
||||||
|
|||||||
Reference in new issue
Block a user