test(extract): toothless Gassen-Gehweg-Probe entfernt, Flaechenvaliditaet abgesichert
Nachpruefung der Fixwelle, drei Punkte: test_gehweg_waechst_auch_bei_engem_winkel_nicht_in_die_gasse (test_street.py) besteht identisch (0,0000 m²) unter dem aktuellen Code, unter der verworfenen Fassung aus Fixrunde 4 und sogar unter einem komplett ungefilterten walk_source = carriageway_area(graph) - nachgerechnet mit einer Wegwerf-Kopie aller drei Varianten. Ursache: SECTION["gasse"].corridor == SECTION["gasse"].carriageway, weshalb .difference(carriage) am Ende von _sidewalk() den geprueften Streifen (die eigene Gassen-Fahrbahn) immer loescht, unabhaengig davon, was _walk_source() liefert. Die Eigenschaft selbst bleibt durch die drei benachbarten Tests (test_gasse_bekommt_weder_gehweg_noch_bordstein, test_gehweg_waechst_nicht_ueber_den_gassenstummel_an_geteilter_kreuzung, test_gehwegrest_an_kreuzung_mit_mehreren_gassen_bleibt_aus) abgesichert, die gegen dieselbe verworfene Fassung mit 53,11 bzw. 53,30 m² hart durchfallen. Ein Test, der nicht fehlschlagen kann, taeuscht Deckung vor, die es nicht gibt - entfernt statt umdimensioniert, weil eine Geometrie mit nur einem Gassenarm die eigentliche Fixrunde-4-Nische (zwischen ZWEI benachbarten Gassenstummeln) strukturell nie nachstellen kann. test_schleife_die_auf_sich_selbst_zurueckfuehrt_bekommt_keine_markierung_daneben (test_marking_junction.py) galt in der Nachpruefung ebenfalls als unterscheidungslos (100% Fahrbahnanteil auch mit altem Code). Mit den byte-genauen historischen Fassungen von junction_marks() (git show4bf670e/ca01141) direkt in die bestehende Testfunktion eingesetzt (Monkeypatch) zeigt sich das Gegenteil: Beide Vorstufen schlagen rot an (schlechtester Anteil 64,9% bzw. 85,3%, an Haltelinie und aeusserstem Zebrabalken), nur der aktuelle Code besteht. Der Test bleibt unveraendert, mit einem Kommentar zur Gegenpruefung. Neu: test_alle_flaechenschichten_sind_gueltige_polygone (test_committed_roads.py) - Waechter aus Befund 5 (die alte Koordinatenrundung erzeugte acht Selbstschnitte, ohne dass ein Test es merkte). Prueft ueber alle 144 Chunks und alle sieben Flaechenschichten (carriageway, land, sidewalk, surfaces, lots, bridges, paths), dass jeder Ring ein gueltiges Polygon ergibt. Heute gruen (4.190 Flaechen, 0 ungueltige); rot nachgewiesen gegen den Datenstand vor Commita397892(9 ungueltige Polygone in 6 Chunks, per git show ohne Codeaenderung nachgestellt). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5dcd188423
commit
35d69c3e6c
3 files changed
+52
-28
No files matched your search
@@ -13,8 +13,19 @@ from pathlib import Path
|
|||||||
|
|
||||||
from shapely.geometry import LineString, Point, Polygon
|
from shapely.geometry import LineString, Point, Polygon
|
||||||
from shapely.ops import unary_union
|
from shapely.ops import unary_union
|
||||||
|
from shapely.validation import explain_validity
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[3] / "public" / "data" / "vice-a"
|
ROOT = Path(__file__).resolve().parents[3] / "public" / "data" / "vice-a"
|
||||||
|
# Die sieben Flächenschichten eines Chunks (Entwurf, Abschnitt "Chunk-Format"). `land` liegt roh
|
||||||
|
# als Liste von Ringlisten vor ([ring, loch, ...]), die übrigen sechs als Liste von
|
||||||
|
# {"poly": [ring, loch, ...]}-Objekten - _flaechen_polygone() unten gleicht das an.
|
||||||
|
AREA_LAYERS = ["carriageway", "land", "sidewalk", "surfaces", "lots", "bridges", "paths"]
|
||||||
|
|
||||||
|
|
||||||
|
def _flaechen_polygone(chunk: dict, layer: str) -> list[Polygon]:
|
||||||
|
entries = chunk.get(layer) or []
|
||||||
|
ringlisten = entries if layer == "land" else [e["poly"] for e in entries]
|
||||||
|
return [Polygon(r[0], r[1:]) for r in ringlisten]
|
||||||
|
|
||||||
|
|
||||||
def _chunks() -> list[dict]:
|
def _chunks() -> list[dict]:
|
||||||
@@ -87,3 +98,34 @@ def test_markierung_liegt_nicht_wesentlich_ausserhalb_der_fahrbahn():
|
|||||||
f"{gesamt_ausserhalb:.2f} m² Markierungsfläche liegen außerhalb der Fahrbahn "
|
f"{gesamt_ausserhalb:.2f} m² Markierungsfläche liegen außerhalb der Fahrbahn "
|
||||||
"(Fixwelle-Stand: 110,06 m²) - das ist mehr als der dokumentierte Rest, nicht nur Rundung"
|
"(Fixwelle-Stand: 110,06 m²) - das ist mehr als der dokumentierte Rest, nicht nur Rundung"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_alle_flaechenschichten_sind_gueltige_polygone():
|
||||||
|
"""Wächter aus der Nachprüfung der Fixwelle (zu Befund 5, emit.py): Die alte
|
||||||
|
Koordinatenrundung (jede Zahl unabhängig auf 2 Stellen) konnte einen Ring selbst schneiden -
|
||||||
|
acht Fälle in den damals ausgelieferten Chunks (carriageway 3, land 2, sidewalk 2, surfaces
|
||||||
|
1), ohne dass ein Test es bemerkte. set_precision() behebt das (s. emit.py), aber bis zu
|
||||||
|
diesem Test hielt nichts fest, dass es dabei bleibt: Eine künftige Änderung an der Rundung
|
||||||
|
oder an set_precision() selbst könnte denselben Fehler wieder einschleppen, unbemerkt wie
|
||||||
|
beim ersten Mal.
|
||||||
|
|
||||||
|
Prüft darum über alle 144 Chunks und alle sieben Flächenschichten (`carriageway`, `land`,
|
||||||
|
`sidewalk`, `surfaces`, `lots`, `bridges`, `paths`), dass jeder Ring ein gültiges Polygon
|
||||||
|
ergibt. Am committeten Stand: 4.190 Flächen geprüft, 0 ungültige (nachgemessen). Rot gegen den
|
||||||
|
Datenstand vor Commit a397892 (Koordinatenrundung statt set_precision): 9 ungültige Polygone in
|
||||||
|
6 Chunks (dieselben acht Polygone wie im Befund - carriageway 3, land 2, sidewalk 2, surfaces 1
|
||||||
|
-, plus ein neuntes, vorbestehendes `paths`-Polygon in Chunk (10, 6), das set_precision() als
|
||||||
|
Nebeneffekt mitheilt) - mit einer Kopie der damaligen Chunk-Dateien nachgestellt (`git show
|
||||||
|
83140f8:...`), nicht mit dem heutigen Code.
|
||||||
|
"""
|
||||||
|
chunks = _chunks()
|
||||||
|
gesamt = 0
|
||||||
|
ungueltig = []
|
||||||
|
for c in chunks:
|
||||||
|
for layer in AREA_LAYERS:
|
||||||
|
for poly in _flaechen_polygone(c, layer):
|
||||||
|
gesamt += 1
|
||||||
|
if not poly.is_valid:
|
||||||
|
ungueltig.append((tuple(c["chunk"]), layer, explain_validity(poly)))
|
||||||
|
assert gesamt > 4000, f"nur {gesamt} Flächen geprüft - fehlt eine Schicht oder ein Chunk?"
|
||||||
|
assert ungueltig == [], f"{len(ungueltig)} von {gesamt} Flächen sind kein gültiges Polygon: {ungueltig}"
|
||||||
@@ -167,6 +167,16 @@ def test_schleife_die_auf_sich_selbst_zurueckfuehrt_bekommt_keine_markierung_dan
|
|||||||
|
|
||||||
Nachgebaut mit denselben Maßen wie am echten Netz (9 m hin, 6 m quer, macht 21,63 m Umweg;
|
Nachgebaut mit denselben Maßen wie am echten Netz (9 m hin, 6 m quer, macht 21,63 m Umweg;
|
||||||
reach=11 m, wie es der zweite Boulevard-Arm hier erzwingt).
|
reach=11 m, wie es der zweite Boulevard-Arm hier erzwingt).
|
||||||
|
|
||||||
|
Gegengeprüft in der Gehwegtextur-Korrekturrunde: Die Nachprüfung der Fixwelle vermutete, der
|
||||||
|
Test unterscheide nicht (halb=9 m deckt jede kleine Markierung nahe am Knoten ab, gleich wohin
|
||||||
|
sie zeigt) und schlage auch mit dem alten Code an dieser Schleife grün an. Nachgestellt mit den
|
||||||
|
byte-genauen historischen Fassungen von junction_marks() (Commits 4bf670e "vor Befund 3" und
|
||||||
|
ca01141 "nach Befund 3, vor dieser Korrektur hier") und exakt dieser Testfunktion (nur
|
||||||
|
junction_marks per Monkeypatch getauscht): Beide Fassungen schlagen rot an (schlechtester
|
||||||
|
Anteil 64,9 % bzw. 85,3 %, an der Haltelinie und am äußersten Zebrabalken - die runde Fuge am
|
||||||
|
Schleifenscheitel deckt zwar die meisten Balken vollständig ab, aber nicht alle). Nur der
|
||||||
|
aktuelle Code besteht (100 %). Der Test bleibt deshalb unverändert.
|
||||||
"""
|
"""
|
||||||
spitze = [(0.0, 0.0), (9.0, -6.0), (0.0, 0.0)]
|
spitze = [(0.0, 0.0), (9.0, -6.0), (0.0, 0.0)]
|
||||||
graph = Graph(
|
graph = Graph(
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
"""Die Mulde: Löcher in der Bodenplatte, Bordsteinlinien, Gehwegflächen, Restflächen."""
|
"""Die Mulde: Löcher in der Bodenplatte, Bordsteinlinien, Gehwegflächen, Restflächen."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import math
|
|
||||||
|
|
||||||
from shapely.geometry import LineString, Point, box
|
from shapely.geometry import LineString, Point, box
|
||||||
from shapely.ops import unary_union
|
from shapely.ops import unary_union
|
||||||
|
|
||||||
@@ -260,29 +258,3 @@ def test_gehweg_schliesst_die_luecke_an_gewoehnlicher_kreuzungsecke():
|
|||||||
luecke = sum(g.area for g in getattr(roh_rest, "geoms", [roh_rest])
|
luecke = sum(g.area for g in getattr(roh_rest, "geoms", [roh_rest])
|
||||||
if not g.is_empty and g.intersects(ecken) and g.area < LOT_MIN)
|
if not g.is_empty and g.intersects(ecken) and g.area < LOT_MIN)
|
||||||
assert luecke < 0.05, f"{luecke:.4f} m² Lücke an den Kreuzungsecken, sollte geschlossen sein"
|
assert luecke < 0.05, f"{luecke:.4f} m² Lücke an den Kreuzungsecken, sollte geschlossen sein"
|
||||||
|
|
||||||
|
|
||||||
def test_gehweg_waechst_auch_bei_engem_winkel_nicht_in_die_gasse():
|
|
||||||
"""Gegenprobe zu obigem Befund-7-Fix, am schärfsten denkbaren Fall: Die Rundung des
|
|
||||||
Kreuzungsanteils darf nicht wieder (wie in Fixrunde 4) über eine benachbarte Gasse
|
|
||||||
hinwegreichen, auch wenn die Gasse in einem enges Winkel zwischen zwei Armen mit Bordstein
|
|
||||||
liegt - der Fall, in dem eine Schließung am ehesten eine Nische neben der Gasse mitfüllen
|
|
||||||
könnte. Zwei Wohnstraßen-Arme bei 0° und 40°, eine Gasse dazwischen, bei 10° bis 30° in 5°-
|
|
||||||
Schritten durchprobiert: In jedem Fall bleibt der Gehweg außerhalb des Gassenkorridors, weil
|
|
||||||
die Gasse selbst nie einen Arm in die zu schließende Fläche liefert (kerb_only=True).
|
|
||||||
"""
|
|
||||||
for grad in (10.0, 15.0, 20.0, 25.0, 30.0):
|
|
||||||
rad = math.radians(grad)
|
|
||||||
a = (60.0, 0.0)
|
|
||||||
b = (60.0 * math.cos(math.radians(40.0)), 60.0 * math.sin(math.radians(40.0)))
|
|
||||||
g = (60.0 * math.cos(rad), 60.0 * math.sin(rad))
|
|
||||||
graph = Graph(
|
|
||||||
nodes=[Node((0.0, 0.0)), Node(a), Node(b), Node(g)],
|
|
||||||
edges=[Edge(0, 1, [(0.0, 0.0), a], SECTION["wohnstrasse"].corridor, "wohnstrasse"),
|
|
||||||
Edge(0, 2, [(0.0, 0.0), b], SECTION["wohnstrasse"].corridor, "wohnstrasse"),
|
|
||||||
Edge(0, 3, [(0.0, 0.0), g], SECTION["gasse"].corridor, "gasse")])
|
|
||||||
corridor = carriageway_area(graph).buffer(3.0, join_style="round")
|
|
||||||
street = build_street(graph, corridor, bridges=[])
|
|
||||||
gassen_korridor = LineString([(0.0, 0.0), g]).buffer(SECTION["gasse"].corridor / 2, cap_style="flat")
|
|
||||||
leck = street.sidewalk.intersection(gassen_korridor).area
|
|
||||||
assert leck < 0.01, f"{leck:.4f} m² Gehweg im Gassenkorridor bei {grad}° Gassenwinkel"
|
|
||||||
Reference in new issue
Block a user