TRO-Typen an Kreisel-Beruehrpunkten (lib/kreisel_junctions.py, derive_tros
Schritt 3c): jeder Kreisel als Stadion-Form mit Laufrichtung; jeder
gleichlaufende Beruehrpunkt ist eine Weiche (exportierte ILS Weiche oder
abgeleitet W<a>_<b>), Beruehrpunkte derselben Umlenkung bilden einen
Knoten. Ein Separator steuert ihn, wenn er in Laufrichtung unmittelbar
davor liegt (keine andere Weiche dazwischen). Typ = Separatoren x Weichen.
export.csv: 1Sep1Swi (9/1, 9/8, 8/7), 2Sep1Swi (7/2), 2Sep2Swi (2/3/4),
3Sep2Swi (4/5/6). Neuer Katalogtyp 3Sep2Swi (nicht aus SCL belegt).
Gegenlaeufige Beruehrpunkte (Mubea, Dematic) bleiben bei der alten Regel;
Mubea/HundM05/Dematic unveraendert, Showroom 0018+0019 jetzt 2Sep1Swi.
material_flow --track: Mouseover je Knoten mit Zugehoerigkeit zu
Kreisel/VF/GF (Zuordnung, TrackIds-Kette, Lage laut Geometrie), Weiche mit
beiden Kreiseln, Be-/Entladung mit ihrem Kreisel; Widersprueche mit "!".
Zahlenwerte (Toleranzen, Schwellen, Massstaebe, Groessen) aus allen
lib-Modulen nach cfg/parameter.ini (lib/parameter.py, Abschnitt je Modul,
Ueberschreiben je Anlage ueber %SKEL_CFG%/parameter.ini). Ausgaben aller
Anlagen bytegleich.
tro_flow.py: Docstrings mit Parametern/Rueckgabe, fehlende Typangaben.
Geprueft: 90 Tests gruen; tro_flow/material_flow/scl_skeleton auf 5 CSVs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- lib/model.py (neu, pydantic): TroBase -> DerivedTro, Connection, OpenPoint,
Analysis (aus tro_flow verschoben), TroDocument = TRO-JSON (Schema
sps_skel-tro-v2). items/fbType werden immer ueber den Typ aus tro_catalog
gelesen, nie gespeichert; abweichende Werte in einer JSON sind ein Fehler.
JSON-Schluessel wie bisher (id, type, fbType ...), extra="forbid".
- tro_flow: Tro/Analysis aus model.py; neuer Schalter --json schreibt
<name>_tro.json (TroDocument)
- scl_skeleton: liest die JSON ueber TroDocument statt per Dict-Zugriff,
Bauteile ueber TroItem-Konstanten; ungueltige JSON -> Exit 1 ohne SCL,
alte tro_extract-JSON (v1) mit Hinweis auf tro_flow --json
- tro_annotate: nur noch Ansicht; derselbe analyse_tros-Aufruf wie tro_flow
(inkl. sepliste-Gegenprobe), damit Zeichnung und JSON uebereinstimmen
- tro_extract: geparkt (unveraendert)
- tests/test_model.py + conftest.py, pytest in requirements.txt aktiviert
- Doku: Python_Scripts.md (§6b model.py), Commandlines.md, CLAUDE.md,
Aufrufkommentare in bin/ (scl_skeleton.bat zeigte tro_flow-Aufrufe)
Geprueft: alle tro_flow/tro_annotate-Ausgaben (8 CSVs) bis auf Zeitstempel
identisch zum vorherigen Stand; scl_skeleton alt/neu auf derselben JSON
byte-identisch (export, mubea, HundM05); 10 Tests gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- _weichen_aus_umlauf: ein Separator, auf den in Laufrichtung ein Ausschleuselement folgt (ohne Separator dazwischen), ist dessen Weiche - auch ohne CSV-Nachbarschaft (Dematic 0043 -> VF_5, Nachbarn nur Einschleuselemente); Speicherlinien ausgenommen
- Schritt 3b': weitere Ausschleuselemente bis zum naechsten Separator gehoeren zum selben Separator, zwei -> 1Sep2Swi (Dematic 0048 -> VF_4 + VF_6), Finding bei fehlendem Scanner bzw. mehr als zwei Weichen
- Weichenkante je Host; Weichen-TRO ohne Bahn-Nachfolger (einziger Separator seines Kreisels) zaehlt als praezise Quelle - entfernt die Contraction-Walk-Kanten an VF_4/VF_5/VF_6 vorbei
- keine gestrichelte "gleiche Bahn"-Notiz an Weichen-TROs (Host ist die Strecke, in die sie abzweigen, nicht ihre Bahn)
- HundM05 (28 Kanten) und Mubea (26) inhaltlich unveraendert, --use-cords-Ausgabe byte-identisch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- _speicher_bloecke: Schwerkraftlinien nach Umlaufreihenfolge in Bloecke schneiden (Separator dazwischen = neuer Block); der Weichen-Separator vor dem Block ist Steuer-Separator des PinStore_Auto statt eigener 1Sep1Swi (Dematic: 3 Speicher 10/7/10 statt einem mit 27)
- Umlauf schliessen bis zum ersten Element mit TRO, nicht nur ueber Stationen hinweg (Dematic Kreisel2 beginnt mit Einschleuselement: TRO01 -> Speicher fehlte; Mubea TRO06 -> TRO10 statt Fallback TRO06 -> TRO18)
- _weichen_nach_umlauf: Separator steuert ein Ausschleuselement nur als letzter Separator davor in Laufrichtung (Dematic 0047/0046 waren ueber den Ring-Schluss bzw. hinter dem Block "benachbart")
- _kreisel_bahn: Kreisel-Separator mit Gefaellestrecke als Zuordnung auf die Kreisel-Bahn haengen (Dematic 0046 zaehlte als Speicherlinie)
- HundM05 unveraendert, Mubea 26 Kanten (eine korrigiert)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TROs, Typen und Verbindungen kommen nur noch aus dem Layout. Fehler der
Ableitung werden im Code behoben, nicht in einer Korrekturdatei.
- tro_flow: Optionen --use-overrides/--no-overrides, --from-connect,
--geometry, --geo-tol-mm entfernt; analyse_tros/derive_tros ohne
overrides/resolve_host/count_exits-Parameter, Analysis.overrides entfernt,
Override-Schritte 4b/4c/5b, Doku-Abschnitt "6. Manuelle Korrekturen" und
die Override-Zeilen im Bericht entfernt; connect.ini ist reine Ausgabe
- lib/tro_geometry.py geloescht (nur von --geometry genutzt), shapely aus
requirements.txt
- tro_overrides: apply_splits/_merges/_connections/_overrides und
load_connect_ini entfernt - nur noch load_overrides fuer
material_flow.py --connect
- doc/Python_Scripts.md nachgezogen
Gegenprobe: DOT (beide Layouts) und connect.ini fuer HundM05 und Mubea
unveraendert (28 bzw. 26 Verbindungen), Doku nur ohne den leeren
Abschnitt 6.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tro_flow:
- _station_positionen: Richtung des Zu-/Ablaufpfeils mit groesstem
Winkelabstand zu allen Kanten des Anker-TROs und zu bereits gesetzten
Stationspfeilen (15-Grad-Raster), echte Stationsrichtung nur bei
Gleichstand - vorher lag z. B. Mubea TRO02 -> SYS2 fast auf TRO02 -> TRO13
tro_annotate:
- Symbole mit typ-eigener Fuellfarbe (Solid-Hatch) unter der Gruppenkontur
- Kantenfarben/-layer wie im SVG: Uebergabe blau, Weiche orange,
Materialeingang gruen, Materialausgang rot (TRO_WEICHE/_EINGANG/_AUSGANG)
- Stationen als farbige Beschriftung am Pfeilende, Lage ueber
tro_flow._station_positionen (ohne CONNECTION_ARROW-Block)
- Legende wie im SVG: je vorkommendem Typ Fuellung/Rand/Form, dann Kantenfarben
- CONNECTION_ARROW: FROM_TRO/TO_TRO unsichtbar (Daten bleiben), KIND auch weiche
cfg/dxf_registration.json: mubea.csv|mubea.dxf und HundM05.csv|HundM05.dxf
mit Versatz 0 (CSV aus derselben dxfmakros-Zeichnung; Auto-Ermittlung sieht
die verschachtelten Separatoren nicht und war mehrdeutig);
mubea.csv|500573_60_1.dxf neu ermittelt (36/46 Punkte).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- link_tros: Systemgrenzen (Be-/Entladung, Eingang/Ausgang) sind kein
Kettenglied mehr - die Umlaufkette verbindet die TROs direkt an ihnen
vorbei. Entladung/Ausgang haengt am TRO direkt davor, Beladung/Eingang
am TRO direkt danach. HundM05: TRO19 -> TRO20, SYS1/SYS2 -> TRO20,
TRO19 -> SYS3. Mubea: TRO02 -> TRO13, TRO04 -> TRO03, TRO02 -> SYS2/SYS3,
SYS1 -> TRO03.
- Umlauf schliessen ueber Stationen am Listenanfang hinweg (HundM05 Kreisel1
beginnt mit den Beladungen, sonst fehlte TRO19 -> TRO20)
- render_dot: Station als farbige Beschriftung am Ende eines Pfeils (gruen
Eingang, rot Ausgang) statt Ellipse, Legende entsprechend; lagerichtig
feste Pfeillaenge ab dem angehaengten TRO, mehrere Stationen am selben TRO
aufgefaechert (_station_positionen ersetzt _anzeige_position)
- HundM05 28 Verbindungen, Mubea 26
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Je Achse bleiben Reihenfolge und echte Abstaende der Knoten bis
COORD_MAX_LUECKE (1500 mm) erhalten, groessere Leerstrecken (lange Foerderer
ohne TRO) werden darauf gekuerzt (_achse_kompakt/_kompakte_positionen,
_zeichen_positionen). Legende naeher an der Anlage. Reine Darstellung:
Knoten, Kanten, Labels und Tooltips (mit echten Koordinaten) unveraendert -
DOT ohne pos-Attribute fuer HundM05 und Mubea identisch. Mubea 2929x3333 ->
2212x2411 px. --true-scale zeichnet weiterhin masstaeblich.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Ausschleuselemente der Speicherlinien zaehlen in der Umlaufkette als
Glied des PinStore-TROs, die Einschleuselemente liefern - wie bei einer
Vario-Strecke - den Ablauf zum naechsten Halt. Ersetzt die Regel
"letzter Halt vor dem Speicher speist ihn" aus f9c9d88.
Mubea Kreisel3: TRO05 -> TRO18 -> TRO07 (keine direkte Kante TRO05 -> TRO07
mehr, TRO05 bleibt 1Sep - kein ILS Ausschleuselement einer Strecke),
TRO12 (VF_2 muendet direkt vor den Speicherlinien) -> TRO18,
TRO18 -> TRO10 jetzt aus den Einschleuselementen auf Kreisel2.
Im Review 2026-10-01 bestaetigt. HundM05 unveraendert (28), Mubea 26.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- _add_chain_pair: Be- und Entladestationen sind in der Umlaufkette
gewoehnliche Glieder - der Kreisel laeuft immer weiter. HundM05 Kreisel1:
TRO19 -> SYS3 -> SYS1 -> SYS2 -> TRO20 (vorher endete der Fluss an SYS3).
Mubea: TRO04 -> SYS1 statt der groben Fehlkante TRO04 -> TRO18.
- link_tros: der letzte Halt vor dem ersten Ausschleuselement einer
Speicherlinie speist den PinStore-TRO (Mubea Kreisel3: TRO05 -> TRO18)
- HundM05 28 Verbindungen, Mubea 26
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lagerichtig liegen TROs derselben Bahn/Strecke ohnehin sichtbar
nebeneinander - die Punktlinien waren dort nur Unruhe. Gezeichnet werden
nur noch echte Verbindungen (HundM05 27, Mubea 25). Die berechnete
Anordnung ohne --use-cords behaelt Linien und Legendenzeile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- link_tros/_add_chain_pair: eine Materialausgang-Systemgrenze darf in der
Kreisel-Umlaufkette Quelle sein - was nicht entladen wird, faehrt weiter.
Mubea Kreisel2: TRO02 -> SYS3 -> SYS2 -> TRO13 (vorher endete der Fluss an
SYS3, TRO13 hatte keinen Vorgaenger). Beladung bleibt reine Quelle.
- Legende: Zeile "blau gestrichelt - Kreisel-Umlauf" entfernt
- HundM05 unveraendert (27 Verbindungen), Mubea 25 Verbindungen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- _find_weiche_separators: ILS Weiche (TeileArt) ist ein echtes Weichen-
Bauteil -> 1Sep1Swi; steuernder Separator = CSV-Nachbar mit Scanner
(Mubea 0125 -> 0036), mehrdeutig -> Finding statt Raten
- _find_switch_separators: Separator mit Zuordnung auf eine Strecke, der in
der TrackIds-Kette eines Kreisels steht, gilt als Kreisel-Separator
(Mubea 0005 vor Ausschleuselement 0057)
- derive_tros 3d: Ausschleuselement-Weiche und ILS Weiche direkt
hintereinander in der TrackIds-Kette -> ein 2Sep2Swi (Mubea TRO10:
Sep 0005/0036, Scan 0006/0041); FB_ILS_MTRO_2Sep2Swi fehlt noch in der ILSLib
- --use-cords: feste Symbolgroesse je Form, nur TRO-Nummer im Symbol,
Typ/Separator als xlabel, Details als Tooltip, Massstab 0.1 statt 0.25 pt/mm,
Legende rechts mit nur den vorkommenden Typen, blasse Linien fuer
gleiche Bahn, Systemgrenzen dicht an einem TRO werden in der Zeichnung
beiseitegeschoben
- HundM05 unveraendert (27 Verbindungen), Mubea 18 TROs / 23 Verbindungen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- tro_flow/tro_annotate: cfg/tro_overrides.ini nur noch mit --use-overrides
(die Abschnitte haengen an laufenden TRO-Nummern und am CSV-Namen und
veralten mit jedem Export; [export.csv.connections] ersetzte alle
abgeleiteten Kanten und liess TRO13-20 unverbunden)
- link_tros: Separatoren mit Zuordnung auf eine Strecke, die in keiner
TrackIds-Liste stehen, per Projektion AS->ES in die Strecken-Kette
einsortieren (Mubea VF_3: 0037/0038 erzeugten je 9 Fehlkanten;
mubea 38 -> 22 Verbindungen, HundM05 unveraendert)
- tro_catalog: typ-eigene Fuellfarbe je TRO-Typ, Mermaid-classDefs je Typ
- tro_overrides/tro_flow: connect.ini zurueck einlesen (--from-connect)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_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>
Bisher wurde auf einer Streckengruppe nur der jeweils letzte Separator (in
TrackIds-Reihenfolge) auf 1Sep umgestuft, alle davor blieben pauschal Vario.
Eine Streckengruppe ist baulich aber meist eine alternierende VF/GF-Kette
(angetriebener Abschnitt, Vereinzeler, unbetriebener Abschnitt, Vereinzeler,
...), nicht nur am Ende - fuer 2 Separatoren macht das keinen Unterschied,
ab 3 schon. Die Umstufung laeuft jetzt vom letzten Separator rueckwaerts und
alterniert: letzter = 1Sep, davor Vario, davor wieder 1Sep usw.
Bestaetigt an HundM05 VF_1 (4 Separatoren): der neue Positions-Nachweis stuft
den dritten von hinten (0035) unabhaengig auf 1Sep ein - deckungsgleich mit
dem bereits vorhandenen (aber als moeglicherweise unkorrigierte CAD-Vorgabe
mit Vorbehalt behafteten) Hoehen-/Antriebsnachweis (_incoming_drop). Der
Hoehen-/Antriebsnachweis bleibt als unabhaengige Zusatzpruefung erhalten und
kann eine laut Muster erwartete Vario-Position auf 1Sep umstufen, wenn dort
tatsaechlich ein unbetriebenes Gefaelle gemessen wird - nicht umgekehrt.
TRO-Typenzahl auf beiden Referenzanlagen (HundM05, Mubea) unveraendert,
nur die Finding-Texte wurden praeziser.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Optional: findet tro_flow.py neben der CSV ein <stamm>_raw.json (dxfmakros-
Rohattribute), vergleicht es je Strecke/Gefaellestrecke-Host die aus der CSV
abgeleitete Separatorenzahl mit der Anzahl 'SEP'-Eintraege in dessen eigener
'sepliste' und meldet Abweichungen als Finding - ohne TRO-Daten zu aendern,
die CSV bleibt die massgebliche Quelle. Faengt an HundM05 sofort einen
echten Fall: VF_5 hat laut CSV 3 zugeordnete Separatoren, sepliste nennt nur
2 - passt zum bereits gemeldeten Separator 0018 ohne TrackIds-Mitgliedschaft.
Bewusst NICHT verwendet: die sepliste-Koordinaten (der jeweils erste
SEP-Eintrag jedes VF-Blocks traegt durchgehend eine kaputte Position, ein
Bug im DXF-Export) und das Attribut "ANZAHL_SEPARATOR" (weicht in beiden
bisher geprueften Anlagen von TrackIds UND sepliste ab, vermutlich veraltet/
doppelt gezaehlt). Fehlt die Roh-JSON-Datei, entfaellt die Gegenprobe
stillschweigend; ist sie vorhanden aber kaputt (z. B. unvollstaendig
geschrieben), gibt es eine Warnung statt eines Abbruchs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ein per Zuordnung einer Streckengruppe zugeordneter Separator, der nicht Teil
von deren eigener TrackIds-Kette ist, wird direkt als 1Sep eingestuft statt
ueber die Vario/letzter-Separator-Logik zu laufen - vor Ort bei Mubea
VF_1-VF_3 bestaetigt: jede Streckengruppe hat genau einen echten
Kettenseparator, alle weiteren Zuordnung-Treffer sind eigenstaendige
Vereinzeler ohne eigenes VF-Teilstueck. Damit ein solcher Separator nicht
zugleich faelschlich als Weichen-Indiz zaehlt (engster Treffer ueberhaupt bei
Mubea 0005, 163mm), werden echte VF-Kettenmitglieder vor der
Weichenerkennung (_find_switch_separators) ausgenommen - Naehe zum eigenen
Aus-/Einschleuselement ist bei ihnen der normale, erwartete Aufbau, kein
Weichenbeleg.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_find_switch_separators: Regel 2 (naechster freier Separator <= 1500mm) lief
bisher nur auf einer Bahn, die Regel 1 (<=500mm) schon bestaetigt hatte. Bei
HundM05 lagen nach einer CAD-Aktualisierung alle 5 echten Weichen-Separatoren
gleichmaessig bei ca. 1013-1016mm - ausserhalb von Regel 1, wodurch die
Bahn-Sperre fuer jede Bahn zublieb und keine einzige Weiche mehr erkannt
wurde. Die Sperre entfaellt; SWITCH_FALLBACK_MM bleibt die alleinige Schranke
gegen Fehlzuordnungen (der eigentliche Schutz vor dem urspruenglichen
Mubea-Fehlfund, der 5-9m entfernte Separatoren betraf).
derive_tros, angetriebene Strecken (Schritt 2): zwei Faelle stufen einen
Separator trotz Host "Strecke" als 1Sep statt Vario ein:
- Letzter Separator vor dem Wiedereinschleusen auf die Kreisel-Bahn (in
TrackIds-Reihenfolge) - reiner Vereinzeler ohne eigene VarioDrive-Strecke,
die Kreisel-Bahn treibt ab dort selbst an (HundM05 VF_3 vor Ort bestaetigt).
- Ein nicht-letzter Separator, dessen vorangehendes Segment "horizontal"
(keine aktive Antriebsrichtung) gefuehrt wird, dabei aber tatsaechlich an
Hoehe verliert (> 30mm) - ein unbetriebenes Gefaelle-Teilstueck innerhalb
einer gemischten VF/GF-Streckengruppe (HundM05 VF_1/0035).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Seit der Weichenerkennung (c788647/fa96a6e) bekommt ein Weichen-TRO als Host
die gefuetterte Strecke statt die Kreisel-Bahn (derive_tros Schritt 3b) - fachlich
richtig fuer den Materialfluss, aber die Positions-Verkettung in link_tros()
gruppierte bisher rein nach Host: sobald nur noch ein einzelner "echter"
Separator auf einer Bahn uebrig blieb (HundM05 Kreisel1 Bahn L: 0020, nachdem
0008/0010/0012/0014 eigene Weichen-TROs wurden), verschwand die Reihenfolge
0008->0010->0012->0014->0020 komplett - im TRO-Flussdiagramm sah es aus, als
haenge jede der 5 Abzweigungen direkt und gleichrangig an genau diesem einen
TRO (Review 2026-09-21: "es gibt viele unnoetige Linien").
_tro_bahn() bestimmt die Kreisel-Bahn eines TROs jetzt zusaetzlich ueber die
Zuordnung seines eigenen Separators, wenn der TRO-Host selbst keine Bahn ist -
link_tros() verkettet danach alle TROs derselben Bahn per Position, nicht nur
die mit identischem Host. Die bestehenden Materialfluss-Kanten (Weiche/Vario
-> Ruecklauf-Bahn) bleiben unveraendert bestehen; die Verkettung ergaenzt nur
die bislang fehlende Reihenfolge der Abzweige.
Die Colocated-Markierung ("gleiche Bahn", gepunktete Linie) wird jetzt pro
Paar statt pro TRO unterdrueckt (verkettete_paare statt verkettet als TRO-Id-
Menge) - sonst waere z. B. TRO01 (Weiche, auf der Bahn verkettet) faelschlich
auch von seiner Colocated-Markierung mit TRO02 (Vario, gleiche Strecke)
ausgenommen worden, obwohl das zwei unabhaengige Beziehungen sind.
HundM05.csv: 24 -> 28 Kanten (4 neue Bahn-Kanten 0008->0010->0012->0014->0020).
Mubea unveraendert (13 TROs, 55 Kanten), keine Fehler in beiden Projekten.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Zwei Korrekturen zu c788647, beide durch Review gefunden (HundM05):
1. Ein Einschleuselement (Wiedereinschleusen in den Kreisel) ist keine
Weiche - das ist ein passiver Merge ohne Richtungsentscheidung, nur das
Ausschleusen (Verlassen der Bahn) legt die Fahrtrichtung fest.
_find_switch_separators() beruecksichtigt jetzt ausschliesslich
Ausschleuselemente; ein Separator an einem Einschleuselement (z. B.
HundM05 Separator 0018) wird nicht mehr als eigener 1Sep1Swi
herausgeloest, sondern zaehlt normal zum Vario-TRO seines Streckensegments.
HundM05.csv: 6 -> 5 automatisch erkannte Weichen (deckt sich jetzt mit den
5 Ausschleuselementen im Layout).
2. Beim Pruefen an Mubea (500573) fiel auf, dass Regel 2 (naechster freier
Separator, bisher ohne Obergrenze) dort mehrere Separatoren dem naechsten
noch freien Ausschleus-/Einschleuselement zugeordnet hatte, obwohl das
3.5-9m entfernt lag - eindeutig keine Weiche. Neue Konstante
SWITCH_FALLBACK_MM (1500mm) begrenzt Regel 2: grosszuegig genug fuer die
bei HundM05 beobachtete Kalibrierungs-Drift (bis 1139mm), zu eng fuer
Mubeas Fehlzuordnungen. mubea.csv: 9 -> 4 automatisch erkannte Weichen
(die beiden bestaetigten Handkorrekturen in tro_overrides.ini bleiben
unveraendert).
Beide Projekte weiterhin ohne Fehler, keine nicht verbundenen TROs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Korrektur zu 72d0a21: Regel 2 in _find_switch_separators() pruefte bisher,
ob ein Separator einen eigenen Scanner traegt, bevor sie ihn (ohne feste
mm-Grenze) einem Aus-/Einschleuselement zuordnete. Der Scanner ist aber nur
ein zusaetzliches Bauteil des TROs, kein Kennzeichen einer Weiche - viele
Separatoren tragen einen Scanner, ohne eine Weiche zu sein (siehe Docstring
und Hinweis in tro_flow.py selbst: "Ein Scanner am Separator aendert den Typ
NICHT").
Regel 2 ist jetzt reine naechster-freier-Nachbar-Zuordnung: jedes noch
unbelegte Aus-/Einschleuselement bekommt den naechstgelegenen freien
Separator derselben Rolle/Bahn, kleinste Distanz zuerst, jedes Paar nur
einmal - ohne Scanner-Kriterium und ohne feste mm-Grenze. Ein gewoehnlicher
Zwischenseparator ohne eigenes Uebergabeelement bleibt dadurch weiterhin
unbelegt, weil ihm kein Element mehr uebrig bleibt.
Ergebnis fuer HundM05.csv unveraendert (13 TROs, 6x 1Sep1Swi, keine Fehler) -
mit der zwischenzeitlich aktualisierten CSV liegen die echten Weichen jetzt
ohnehin wieder innerhalb der 500mm-Grenze aus Regel 1; Regel 2 bleibt als
Absicherung gegen erneute Kalibrierungs-Drift bestehen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
lib/tro_catalog.py: dot_shape_attrs()/SYMBOL_LABELS geben render_dot() eine
Graphviz-Form je TroSymbol (bisher nur fuer den CAD-Marker in tro_annotate.py
genutzt) - Farbe gruppiert weiterhin verwandte Typen, Form unterscheidet den
einzelnen Typ. Legende und Doku-Tabellen zeigen jetzt jeden Katalogtyp mit
Farbe+Symbol statt nur die 6 Farbgruppen.
lib/tro_flow.py: _find_switch_separators() bekommt einen zweiten Durchlauf,
der einen Separator mit eigenem Scanner (CAD-Merkmal "Naechster Separator")
als Weiche erkennt, wenn die reine Abstandsregel (SWITCH_PROXIMITY_MM) ihn
verfehlt - Rolle (Aus-/Einschleusung) wird aus einem bereits bestaetigten
Treffer auf derselben Kreisel-Bahn gelesen, keine neue feste mm-Schwelle.
Grund: bei HundM05 (5 Abzweige an einem Kreisel) lagen 3 der 5 echten
Weichen-Separatoren 727-1139mm von ihrem Ausschleuselement entfernt - ausserhalb
der auf einer aelteren Revision kalibrierten 500mm-Grenze - und wurden bisher
faelschlich als einfacher 1Sep statt 1Sep1Swi eingestuft.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
--chain-graph zeichnet einen massstabsgetreuen Chain-/Lageplan der groben
Objekte (Kreisel-Bahnhaelften, Strecke/Gefaellestrecke) als <name>_chain.svg,
ohne Graphviz. BTMT-Stationen werden jetzt auch an "Eingang"/"Ausgang" statt
nur "Beladung"/"Entladung" erkannt und bevorzugt ueber TrackIds statt Nachbarn
verbunden. tro_flow.py erkennt bei Aus-/Einschleuselementen jetzt auch
"Foerderer" als Merkmal-Schreibweise fuer die Strecke, nicht nur "Strecke".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a --use-cords switch to tro_flow.py (--use-coords accepted too). With it,
every TRO node carries its plant coordinate as a pos attribute and the SVG is
produced by "neato -n" instead of dot, so the diagram looks like the plant
layout rather than a computed left-to-right flow.
Scale is 0.25 pt/mm (COORD_SCALE), which turns the ~11 x 20 m plant into roughly
2800 x 5000 pt - large enough that the TRO boxes do not overlap. Without the
switch the pos attributes stay in the DOT as information only, at 1:100, and dot
ignores them; the default layout is unchanged.
Two details neato -n needs: the legend gets a position of its own, placed below
left of the plant bounding box, because with -n a node without pos would land at
0,0 in the middle of the drawing. And the switch is refused with a clear message
if any TRO has no coordinate, since -n cannot lay out a graph with missing
positions.
Verified that neato -n reproduces the given coordinates: the positions it reports
back differ from the input by a constant offset only (spread 0.08 pt, from
Graphviz moving the drawing into the positive quadrant), and no node distance
changes by more than 0.08 pt over spans of up to 3600 pt.
graph_to_svg() in material_flow.py replaces dot_to_svg() to take an engine and
the no-op flag; dot_to_svg() stays as a thin wrapper. It now also treats output
on stderr as an error, so neato's "node has no position" warnings do not pass
silently.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sister program to material_flow.py with the same switches, but --tosvg draws the
flow diagram of the TROs instead of the individual objects. It reuses
read_elements and build_graph, so CSV parsing and direction logic exist once.
A TRO is the control logic of one hand-over point, derived from the separator and
what is attached to it, following doc/500573_Mubea/TRO_Identifikation_500573.md:
Gefaellestrecke, >= 2 lines sharing feed/discharge -> PinStore_Auto per group
Gefaellestrecke, single line -> 1Sep
Strecke (driven) -> Vario per segment
Kreisel lane -> 1Sep
A scanner at the separator deliberately does not change the type: in connect.ini
separators with a scanner are predominantly 1Sep, and 1Sep_SSCC is reserved for
the SSCC/end-measurement/WCS case, which a mechanical layout cannot reveal.
Affected points are reported as hints instead. A host with 2 or 3 outgoing flow
edges upgrades 1Sep to 1Sep1Swi/1Sep2Swi.
Connectivity contracts passive nodes: material runs separator to separator, so a
carousel lane carrying no TRO is traversed rather than treated as a dead end.
Without that, a lone separator on a spur loop would be reported as an orphan
purely as an artifact of the model. Each TRO must connect to at least one other;
otherwise an error file is written and the exit code is 3.
Each TRO also carries a plant coordinate - the centroid of the components it was
built from, so a 1Sep1Swi sits between its separator and its switch. Written into
the DOT as a pos attribute (1:100), which dot ignores and "neato -n" can use to
draw the diagram to scale.
Types, function blocks, components and colours come exclusively from
lib/tro_catalog.py.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>