tro_flow.link_tros: Uebergang durch eine Weiche zwischen zwei Kreiseln

Der Weichenknoten-TRO leitet ueber jede seiner Weichen auf den
Partnerkreisel um; dort faehrt der Traeger zum naechsten Halt nach der
Weiche. Ohne diese Kante fehlte z. B. in der Testanlage test_system
TRO(0011) -> TRO(0010), der Ausgang war vom Eingang aus unerreichbar.
Test tests/test_tro_link.py mit Fixture test_system_sep22_export.csv;
ID-Datei cfg/export_tro_ids.ini der Testanlage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Samer Ayadi
2026-10-15 16:16:21 +02:00
co-authored by Claude Opus 5.5
parent df24cf5adb
commit 77c5aac343
4 changed files with 210 additions and 0 deletions
+38
View File
@@ -1957,6 +1957,44 @@ def link_tros(
if nxt is not None and nxt != vario_id:
_add_chain_pair(vario_id, nxt)
# 1b. Uebergang durch eine Weiche zwischen zwei Kreiseln: der Weichen-
# knoten-TRO (derive_tros Schritt 3c) leitet ueber jede seiner Weichen auf
# den Partnerkreisel um - dort faehrt der Traeger zum naechsten Halt NACH
# der Weiche (wie beim Einschleuselement oben). Die Ketten der Kreisel
# kennen Weichen nicht als Glied; ohne diese Kante fehlte der Uebergang,
# sobald der TRO auf seinem eigenen Kreisel schon eine praezise Kette hat
# (dxfmakros test_system: TRO09 auf Kreisel 0008 -> Weiche 0023 ->
# Kreisel 0009 -> TRO10 fehlte, der Ausgang war unerreichbar). Nur in
# Richtung eines Kreisels, auf dem der TRO NICHT allein steuert: ein
# Separator auf dem Zielkreisel selbst leitet von dort weg, nicht dorthin.
# Ausgangsstationen vor dem naechsten Halt bekommen ihren Ablaufpfeil.
kreisel_by_id = {e.teile_id: e for e in elements
if e.is_circle and len(e.track_ids) >= 2}
for knoten in find_junctions(elements, []):
knoten_tros = {ketten_owner[s] for s in knoten.separators if s in ketten_owner}
if len(knoten_tros) != 1:
continue
tro_id = knoten_tros.pop()
sep_kreisel = set(knoten.sep_kreisel.values())
for contact in knoten.contacts:
for ziel_id in contact.kreisel:
ziel = kreisel_by_id.get(ziel_id)
if (ziel is None or not sep_kreisel - {ziel_id}
or contact.weiche_id not in ziel.track_ids):
continue
ids = list(ziel.track_ids)
i = ids.index(contact.weiche_id)
folge = ids[i + 1:]
if ziel.rotation in (ROTATION_CW, ROTATION_CCW):
folge += ids[:i]
for tid in folge:
station = station_hosts.get(tid)
if station is not None and station.type_name == BOUNDARY_EXIT:
_add_chain_pair(tro_id, station.tro_id)
if tid in ketten_owner:
_add_chain_pair(tro_id, ketten_owner[tid])
break
# Nur TROs, fuer die die Umlaufkette tatsaechlich einen praezisen
# Nachfolger gefunden hat (precise_sources) - ein TRO ohne brauchbare
# TrackIds-Abdeckung behaelt seine bisherigen (ungenaueren, aber nicht