TRO-Fluss: Weichenerkennung ueber CSV-Nachbarn statt Distanzschwelle

_find_switch_separators() ermittelt Weichen-Separatoren jetzt topologisch
(Ausschleuselement unter den CSV-Nachbarn, gleiche Kreisel-Bahn) statt ueber
eine Distanzschwelle - die Fallback-Schwelle paarte an Mubea unbeteiligte
Separatoren faelschlich mit dem naechsten freien Ausschleuselement, u.a. 20
PinStore_Auto-Speicherlinien wurden so faelschlich als 1Sep1Swi erkannt.

Materialfluss: _sole_kreisel_neighbour() als Fallback in _apply_transfers()
fuer AS/ES-Elemente ohne eigenes Merkmal "Kreisel" (Mubea), aufloesbar wenn
die Strecke genau einen Kreisel-Nachbarn hat.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Samer Ayadi
2026-09-25 15:06:25 +02:00
co-authored by Claude Sonnet 5
parent e4bfad4dcc
commit 058c60e23d
2 changed files with 88 additions and 89 deletions
+30
View File
@@ -1152,6 +1152,30 @@ def _attach_stations(
return edges
def _sole_kreisel_neighbour(strecke_id: str, by_id: dict[str, Element]) -> str:
"""Kreisel-Basis-Id, wenn die Strecke genau einen Kreisel als Nachbarn hat, sonst ''.
Fallback fuer _apply_transfers, wenn ein Ausschleus-/Einschleuselement
selbst kein Merkmal "Kreisel" traegt (z. B. Mubea: die dortigen AS/ES-
Bloecke haben dieses Merkmal grundsaetzlich nicht, siehe Review
2026-09-25). Bewusst nur bei GENAU einem Kreisel-Nachbarn: bei zwei
verschiedenen Kreiseln (der Normalfall) waere sonst nicht entscheidbar,
welcher zu "aus" (Ausschleusung) und welcher zu "ein" (Einschleusung)
gehoert - dort bleibt es beim bisherigen Hoehenvergleich in _orient(), der
dort zuverlaessig funktioniert (unterschiedliche Kreisel, unterschiedliche
Hoehe). Nur bei einer Ruecklauf-Strecke (beide Enden am selben Kreisel,
siehe unten) ist der einzige Nachbar ohnehin fuer beide Rollen richtig.
"""
strecke = by_id.get(strecke_id)
if strecke is None:
return ""
bases = {
base for base, _lane in strecke.neighbours
if (partner := by_id.get(base)) is not None and partner.is_circle
}
return next(iter(bases)) if len(bases) == 1 else ""
def _kreisel_lane_node(kreisel_base: str, strecke: Element, nodes: dict[str, Node]) -> str | None:
"""Die konkrete Kreisel-Bahn (…-L/…-R), an der die Strecke haengt."""
for base, lane in strecke.neighbours:
@@ -1217,6 +1241,12 @@ def _apply_transfers(
# "Strecke" (VF) oder "Foerderer"/"Förderer" (GF/Streckengruppe).
s = str(_merkmal(el.merkmale, "Strecke", "Foerderer", "Förderer") or "").strip()
if not k and s:
# AS/ES ohne eigenes Merkmal "Kreisel" (z. B. Mubea) - nur bei
# einem einzigen Kreisel-Nachbarn der Strecke aufloesbar, siehe
# _sole_kreisel_neighbour.
k = _sole_kreisel_neighbour(s, by_id)
if k and s:
role = "aus" if el.kind == "Ausschleus" else "ein"
per_strecke.setdefault(s, {})[role] = k