latest changes
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
@echo off
|
||||
REM ================================================================
|
||||
REM SPS_SKEL - FB_Main-Geruest als SCL erzeugen
|
||||
REM ================================================================
|
||||
REM Aufruf:
|
||||
REM bin\tro_flow.bat --file mubea.csv
|
||||
REM bin\tro_flow.bat --file mubea.csv --tosvg
|
||||
REM bin\tro_flow.bat --file mubea.csv --tosvg --doc
|
||||
REM
|
||||
REM Die JSON-Datei wird in %SKEL_RESULTS% gesucht, die SCL-Datei wird
|
||||
REM ebenfalls dort abgelegt.
|
||||
REM
|
||||
REM Schwesterprogramm: bin\material_flow.bat (Materialfluss der Objekte)
|
||||
REM ================================================================
|
||||
|
||||
setlocal
|
||||
|
||||
REM Umgebung setzen (SKEL_DATA, SKEL_RESULTS, SKEL_LIB, PYTHONPATH ...)
|
||||
call "%~dp0setenv.bat" >nul
|
||||
|
||||
REM Virtuelle Umgebung nutzen, falls vorhanden (pydantic wird benoetigt)
|
||||
if exist "%SPS_SKEL%\.venv\Scripts\activate.bat" (
|
||||
call "%SPS_SKEL%\.venv\Scripts\activate.bat"
|
||||
)
|
||||
|
||||
REM Python-Interpreter bestimmen (py-Launcher bevorzugt, sonst python)
|
||||
set "PY=py"
|
||||
py --version >nul 2>&1 || set "PY=python"
|
||||
|
||||
"%PY%" "%SKEL_LIB%\scl_skeleton.py" %*
|
||||
set "RC=%ERRORLEVEL%"
|
||||
|
||||
endlocal & exit /b %RC%
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
# ================================================================
|
||||
# SPS_SKEL - FB_Main-Geruest als SCL erzeugen
|
||||
# ================================================================
|
||||
# Aufruf:
|
||||
# bash bin/scl_skeleton.sh
|
||||
# bash bin/scl_skeleton.sh --json export_tro.json
|
||||
# bash bin/scl_skeleton.sh --json export_tro.json --out FB_Main.scl
|
||||
#
|
||||
# Die JSON-Datei wird in $SKEL_RESULTS gesucht, die SCL-Datei wird
|
||||
# ebenfalls dort abgelegt.
|
||||
#
|
||||
# Vorstufe: bin/tro_extract.sh (Zeichnung -> JSON)
|
||||
# ================================================================
|
||||
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Umgebung setzen (SKEL_DATA, SKEL_RESULTS, SKEL_LIB, PYTHONPATH ...)
|
||||
# shellcheck source=/dev/null
|
||||
. "$SCRIPT_DIR/setenv.sh" >/dev/null
|
||||
|
||||
# Virtuelle Umgebung nutzen, falls vorhanden (pydantic wird benoetigt)
|
||||
if [ -f "$SPS_SKEL/.venv/bin/activate" ]; then
|
||||
# shellcheck source=/dev/null
|
||||
. "$SPS_SKEL/.venv/bin/activate"
|
||||
fi
|
||||
|
||||
# Python-Interpreter bestimmen
|
||||
PY="python3"
|
||||
command -v python3 >/dev/null 2>&1 || PY="python"
|
||||
|
||||
exec "$PY" "$SKEL_LIB/scl_skeleton.py" "$@"
|
||||
@@ -0,0 +1,33 @@
|
||||
@echo off
|
||||
REM ================================================================
|
||||
REM SPS_SKEL - TROs aus der annotierten Zeichnung nach JSON lesen
|
||||
REM ================================================================
|
||||
REM Aufruf:
|
||||
REM bin\tro_flow.bat --file mubea.csv
|
||||
REM bin\tro_flow.bat --file mubea.csv --tosvg
|
||||
REM bin\tro_flow.bat --file mubea.csv --tosvg --doc
|
||||
REM
|
||||
REM Die Zeichnung wird in %SKEL_RESULTS% gesucht, die JSON-Datei wird
|
||||
REM ebenfalls dort abgelegt.
|
||||
REM
|
||||
REM Schwesterprogramm: bin\material_flow.bat (Materialfluss der Objekte)
|
||||
REM ================================================================
|
||||
|
||||
setlocal
|
||||
|
||||
REM Umgebung setzen (SKEL_DATA, SKEL_RESULTS, SKEL_LIB, PYTHONPATH ...)
|
||||
call "%~dp0setenv.bat" >nul
|
||||
|
||||
REM Virtuelle Umgebung nutzen, falls vorhanden (pydantic wird benoetigt)
|
||||
if exist "%SPS_SKEL%\.venv\Scripts\activate.bat" (
|
||||
call "%SPS_SKEL%\.venv\Scripts\activate.bat"
|
||||
)
|
||||
|
||||
REM Python-Interpreter bestimmen (py-Launcher bevorzugt, sonst python)
|
||||
set "PY=py"
|
||||
py --version >nul 2>&1 || set "PY=python"
|
||||
|
||||
"%PY%" "%SKEL_LIB%\tro_extract.py" %*
|
||||
set "RC=%ERRORLEVEL%"
|
||||
|
||||
endlocal & exit /b %RC%
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
# ================================================================
|
||||
# SPS_SKEL - TROs aus der annotierten Zeichnung nach JSON lesen
|
||||
# ================================================================
|
||||
# Aufruf:
|
||||
# bash bin/tro_extract.sh
|
||||
# bash bin/tro_extract.sh --dxf export_annotated.dxf
|
||||
# bash bin/tro_extract.sh --dxf export_annotated.dxf --out tros.json
|
||||
#
|
||||
# Die Zeichnung wird in $SKEL_RESULTS gesucht, die JSON-Datei wird
|
||||
# ebenfalls dort abgelegt.
|
||||
#
|
||||
# Gegenrichtung zu: bin/tro_annotate.sh (JSON <- Zeichnung)
|
||||
# ================================================================
|
||||
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Umgebung setzen (SKEL_DATA, SKEL_RESULTS, SKEL_LIB, PYTHONPATH ...)
|
||||
# shellcheck source=/dev/null
|
||||
. "$SCRIPT_DIR/setenv.sh" >/dev/null
|
||||
|
||||
# Virtuelle Umgebung nutzen, falls vorhanden (pydantic wird benoetigt)
|
||||
if [ -f "$SPS_SKEL/.venv/bin/activate" ]; then
|
||||
# shellcheck source=/dev/null
|
||||
. "$SPS_SKEL/.venv/bin/activate"
|
||||
fi
|
||||
|
||||
# Python-Interpreter bestimmen
|
||||
PY="python3"
|
||||
command -v python3 >/dev/null 2>&1 || PY="python"
|
||||
|
||||
exec "$PY" "$SKEL_LIB/tro_extract.py" "$@"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
;; Automatisch erzeugt von lib/tro_annotate.py --emit-lisp
|
||||
;; Quelle: TRO_CATALOG in lib/tro_catalog.py - nicht manuell aendern.
|
||||
(setq *TRO-TYPES* (list "1Sep" "1Sep1Swi" "1Sep2Swi" "1Sep_SSCC" "Vario" "PinStore_Auto" "Vario_workStation" "EmptyCarrBuffer" "LoadingBoom" "2Sep1Swi"))
|
||||
(setq *TRO-TYPES* (list "1Sep" "1Sep1Swi" "1Sep2Swi" "1Sep_SSCC" "Vario" "PinStore_Auto" "Vario_workStation" "EmptyCarrBuffer" "LoadingBoom" "2Sep1Swi" "2Sep2Swi"))
|
||||
(princ)
|
||||
|
||||
@@ -12,5 +12,19 @@
|
||||
"csv_file": "mubea.csv",
|
||||
"dxf_file": "500573_60_1.dxf",
|
||||
"created": "2026-07-30 15:32"
|
||||
},
|
||||
"export.csv|Mubea.dxf": {
|
||||
"dx": 59.950000000000045,
|
||||
"dy": 0.0,
|
||||
"rotation": 0.0,
|
||||
"source": "auto",
|
||||
"anchor": "21 exakte Treffer (<= 50 mm) ueber die Rollen Scanner:8, Separator:35; 21 Stimmen im 100-mm-Raster, 6 Kandidaten geprueft",
|
||||
"matched": 43,
|
||||
"candidates": 43,
|
||||
"residual_max": 419.95000000000005,
|
||||
"residual_mean": 90.1746667187897,
|
||||
"csv_file": "export.csv",
|
||||
"dxf_file": "Mubea.dxf",
|
||||
"created": "2026-08-12 10:09"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
; ============================================================
|
||||
; tro_overrides.ini - manuelle Korrekturen an der TRO-Ableitung
|
||||
; Gelesen von lib/tro_overrides.py, angewandt in lib/tro_flow.py und
|
||||
; lib/tro_annotate.py. Von Hand gepflegt - wird NICHT generiert.
|
||||
;
|
||||
; Warum es diese Datei gibt: tro_flow.py leitet die TROs allein aus dem
|
||||
; mechanischen Layout (CSV-Export) ab. Weichen, die im Export fehlen, oder
|
||||
; ein SSCC-Scanner sind dort nicht erkennbar. Solche Erkenntnisse aus der
|
||||
; Begehung stehen hier, damit sie den naechsten Lauf ueberleben.
|
||||
;
|
||||
; [<csv>.tro.<TRO-ID>] Typkorrektur an einem abgeleiteten TRO
|
||||
; type = <Katalogtyp aus lib/tro_catalog.py>
|
||||
; reason = <Begruendung, erscheint in der Doku>
|
||||
; confidence = <Vertrauensangabe, Default 'bestaetigt'>
|
||||
;
|
||||
; [<csv>.openpoint.<Name>] offener Punkt - ausdruecklich noch KEIN TRO
|
||||
; x / y / z = Anlagenkoordinate in mm (CSV-Koordinatensystem)
|
||||
; expect = hier erwarteter TRO-Typ
|
||||
; belongs_to = TRO, der das Bauteil heute enthaelt
|
||||
; note = Erlaeuterung
|
||||
;
|
||||
; Offene Punkte aendern die TRO-Struktur nicht. Sie werden nur in der Doku
|
||||
; und in der annotierten Zeichnung markiert - erst nach Pruefung in BricsCAD
|
||||
; werden daraus echte TROs.
|
||||
;
|
||||
; ACHTUNG: die TRO-IDs sind laufende Nummern eines Laufs. Sie gelten nur zur
|
||||
; angegebenen CSV-Datei. Wechselt die Datenbasis (z.B. auf export.csv),
|
||||
; verschieben sich die Nummern und die Abschnitte muessen nachgezogen werden.
|
||||
; ============================================================
|
||||
|
||||
; ------------------------------------------------------------
|
||||
; Mubea 500573 - Review vom 2026-08-10 (Begehung/Layoutpruefung)
|
||||
; Basis: data/mubea.csv
|
||||
; ------------------------------------------------------------
|
||||
|
||||
[mubea.csv.tro.TRO03]
|
||||
type = 1Sep1Swi
|
||||
reason = Weiche am Separator 0010 vor Ort bestaetigt (Review 2026-08-10) - an dieser Stelle wird die Fahrtrichtung umgestellt; im CSV-Export fehlt das Weichenelement
|
||||
confidence = bestaetigt
|
||||
|
||||
[mubea.csv.tro.TRO04]
|
||||
type = 1Sep_SSCC
|
||||
reason = Separator 0011 mit Scanner 0006 - im Review als Scanner-Stelle bestaetigt (Review 2026-08-10)
|
||||
confidence = bestaetigt
|
||||
|
||||
[mubea.csv.tro.TRO05]
|
||||
type = 1Sep1Swi
|
||||
reason = Weiche am Separator 0059 vor Ort bestaetigt (Review 2026-08-10) - im CSV-Export fehlt das Weichenelement
|
||||
confidence = bestaetigt
|
||||
|
||||
[mubea.csv.openpoint.Qualitaetskontrolle]
|
||||
x = -1026.00
|
||||
y = 5250.05
|
||||
z = 1478.50
|
||||
expect = 1Sep1Swi
|
||||
belongs_to = TRO09
|
||||
note = Im Review als eigene Uebergabestelle (1 Separator + 1 Weiche) gemeldet. In mubea.csv gibt es an dieser Stelle ueberhaupt kein Bauteil - Separator 0059 und Scanner 0060 tauchen erst in export.csv auf. Koordinate daher aus export.csv uebernommen. Vor der Umsetzung in BricsCAD pruefen.
|
||||
|
||||
[mubea.csv.openpoint.Foerderer_unten_links]
|
||||
x = 529.95
|
||||
y = -3895.27
|
||||
z = 1468.50
|
||||
expect = 1Sep1Swi
|
||||
belongs_to = TRO10
|
||||
note = Im Review als eigene Uebergabestelle (1 Separator + 1 Weiche) gemeldet, Position aus der Zeichnung (DXF -50375.7283 / -12309.7617, ueber cfg/dxf_registration.json auf Anlagenkoordinaten umgerechnet). Naechstes Bauteil ist Separator 0004 'Separator :30' bei 400 / -3755 auf Gefaellestrecke 0035, das derzeit zum Linienspeicher TRO10 gehoert. Vor der Umsetzung in BricsCAD pruefen.
|
||||
|
||||
; ------------------------------------------------------------
|
||||
; export.csv - Stand Review 2026-08-10 (Begehung + Ablaufbeschreibung)
|
||||
;
|
||||
; Adressiert wird ueber SEP<Separatornummer>, nicht ueber die TRO-ID: die
|
||||
; TRO-IDs sind laufende Nummern eines Laufs und verschieben sich, sobald - wie
|
||||
; hier - TROs dazukommen. Die Separatornummer aus dem CSV-Export bleibt gleich.
|
||||
; ------------------------------------------------------------
|
||||
|
||||
[export.csv.tro.SEP0011]
|
||||
type = 1Sep1Swi
|
||||
reason = Weiche am Separator 0011 vor Ort bestaetigt (Review 2026-08-10) - hier wird die Fahrtrichtung umgestellt; im CSV-Export fehlt das Weichenelement
|
||||
confidence = bestaetigt
|
||||
|
||||
; Separator bei 10310 / -440 auf Kreisel3 Bahn R (Scanner 0008).
|
||||
; Export vom 2026-08-12: aus 0063 wurde 0064 - die neuen Bauteile haben die
|
||||
; Nummerierung verschoben, die Stelle selbst ist dieselbe.
|
||||
[export.csv.tro.SEP0064]
|
||||
type = 1Sep_SSCC
|
||||
reason = Review 2026-08-12: Scanner-Stelle, keine Weiche - Einstufung gegenueber dem ersten Review (1Sep1Swi) korrigiert. Separator mit Scanner 0008.
|
||||
confidence = bestaetigt
|
||||
|
||||
; Separator 0003 (-400 / 13920) mit Scanner 0004 auf Kreisel2 Bahn L.
|
||||
; Die Ableitung stuft das als 1Sep ein (ein Scanner aendert den Typ nicht) und
|
||||
; gibt nur einen Hinweis - Review 2026-08-12 bestaetigt hier die Scanner-Stelle.
|
||||
[export.csv.tro.SEP0003]
|
||||
type = 1Sep_SSCC
|
||||
reason = Review 2026-08-12: Scanner-Stelle bestaetigt (Separator 0003 mit Scanner 0004)
|
||||
confidence = bestaetigt
|
||||
|
||||
; Separator 0012 + Scanner 0007 bleiben als Scanner-Stelle eingestuft
|
||||
; (Review 2026-08-10: "keep 1sep1scanner"). 1Sep_SSCC ist der einzige
|
||||
; Katalogtyp, der Separator und Scanner zusammen fuehrt.
|
||||
[export.csv.tro.SEP0012]
|
||||
type = 1Sep_SSCC
|
||||
reason = Separator 0012 mit Scanner 0007 - im Review als Scanner-Stelle bestaetigt (Review 2026-08-10)
|
||||
confidence = bestaetigt
|
||||
|
||||
; --- manuell ergaenzte Uebergabestellen -----------------------------------
|
||||
; Beide Separatoren sind im Export vorhanden, ihre "Zuordnung" zeigt aber auf
|
||||
; ein Transportobjekt statt auf die Kreisel-Bahn, an der sie schalten. Die
|
||||
; Ableitung hat sie deshalb dem Foerderer bzw. dem Linienspeicher zugeschlagen.
|
||||
|
||||
[export.csv.split.Kreisel2_R_vor_Foerderer]
|
||||
type = 1Sep1Swi
|
||||
separators = 0005
|
||||
scanners = 0006
|
||||
host = 0002-R
|
||||
label = Separator 0005 auf Kreisel2 Bahn R (vor dem Foerderer)
|
||||
reason = Review 2026-08-10: liegt auf Kreisel2 Bahn R zwischen Linienspeicher und Foerderer. Vor Ort 1 Separator + 1 Scanner, keine mechanische Weiche - wird auf Wunsch als Schaltstelle (1Sep1Swi) gefuehrt, weil hier die Wegeentscheidung faellt. Export vom 2026-08-12: Position 400/-3978 (223 mm verschoben), Zuordnung jetzt Strecke 0014 statt Gefaellestrecke 0036 - der Separator wuerde also dem Vario-TRO zugeschlagen statt dem Linienspeicher.
|
||||
confidence = bestaetigt
|
||||
|
||||
; --- Zusammenfassung ------------------------------------------------------
|
||||
; Die beiden Stellen beiderseits des Beruehrpunkts Kreisel2/Kreisel1 sind
|
||||
; mechanisch getrennt (1,54 m Abstand, zwei verschiedene Kreisel), steuerungs-
|
||||
; technisch aber eine Uebergabestelle. Laeuft NACH den beiden Splits oben -
|
||||
; erst dadurch existieren die zwei TROs, die hier zusammengefasst werden.
|
||||
;
|
||||
; ACHTUNG: Typ 2Sep2Swi wurde am 2026-08-12 neu in lib/tro_catalog.py
|
||||
; aufgenommen. Der Baustein FB_ILS_MTRO_2Sep2Swi existiert in der ILSLib noch
|
||||
; nicht und muss dort angelegt werden.
|
||||
[export.csv.merge.Beruehrpunkt_K2_K1_gesamt]
|
||||
type = 2Sep2Swi
|
||||
separators = 0005, 0057
|
||||
host = 0002-R
|
||||
label = Uebergabestelle Kreisel2/Kreisel1 (beide Sperren)
|
||||
reason = Review 2026-08-12: die Sperre auf Kreisel2 Bahn R und die am Beruehrpunkt bilden zusammen eine Uebergabestelle - als ein Steuerobjekt mit 2 Separatoren, 2 Scannern und 2 Weichen gefuehrt
|
||||
confidence = bestaetigt
|
||||
|
||||
[export.csv.split.Beruehrpunkt_K2_K1]
|
||||
type = 1Sep1Swi
|
||||
separators = 0057
|
||||
; Scanner 0062 (1415 / -5460) ist im Export vom 2026-08-12 neu dazugekommen und
|
||||
; liest an Separator 0057 - er muss mit herausgeloest werden, sonst bliebe er
|
||||
; beim Vario-TRO haengen.
|
||||
scanners = 0062
|
||||
host = 0001-L
|
||||
label = Separator 0057 am Beruehrpunkt Kreisel2/Kreisel1
|
||||
reason = Review 2026-08-10: Uebergabestelle am Beruehrpunkt der beiden Kreisel (ILS Weiche 0067 bei 400/-5478, Kreisel A 0002 / Kreisel B 0001). Hier faellt die Entscheidung Kreisel1 weiter oder auf den unteren Foerderer. Zuordnung im Export zeigt auf Strecke 0014, daher bisher Teil des Vario-TRO.
|
||||
confidence = bestaetigt
|
||||
|
||||
; ------------------------------------------------------------
|
||||
; Gesetzte TRO-Topologie - Aufnahme vom 2026-08-14
|
||||
;
|
||||
; Diese Verbindungen ERSETZEN die abgeleiteten vollstaendig. Grund: die
|
||||
; Ableitung kontrahiert ueber Kreisel-Bahnen, die als EIN Knoten modelliert
|
||||
; sind, und verbindet dadurch jeden ankommenden TRO mit ALLEN TROs der Bahn
|
||||
; statt nur mit dem ersten. Ausserdem ist die Fahrtrichtung der Foerderer
|
||||
; zwischen zwei Kreiseln aus dem Layout nicht bestimmbar.
|
||||
;
|
||||
; Adressiert ueber TRO-IDs. Die sind laufende Nummern eines Laufs - kommt ein
|
||||
; TRO dazu oder faellt weg, muss dieser Abschnitt nachgezogen werden. Zur
|
||||
; Wiedererkennung der Stellen der Stand vom 2026-08-14:
|
||||
; TRO01 Sep 0061 TRO02 Sep 0003 TRO03 Sep 0011 TRO04 Sep 0012
|
||||
; TRO05 Sep 0005+0057 (2Sep2Swi) TRO06 Sep 0064 TRO07 Sep 0065
|
||||
; TRO08 Sep 0066 TRO09 Vario 0013 TRO10 Vario 0014 TRO11 Vario 0016
|
||||
; TRO12 PinStore (20 Linien)
|
||||
; ------------------------------------------------------------
|
||||
|
||||
[export.csv.connections]
|
||||
c001 = TRO09 -> TRO07 | transfer
|
||||
c002 = TRO07 -> TRO06 | bahn
|
||||
c003 = TRO06 -> TRO08 | bahn
|
||||
c004 = TRO08 -> TRO12 | transfer
|
||||
c005 = TRO12 -> TRO05 | transfer
|
||||
c006 = TRO05 -> TRO01 | weiche
|
||||
c007 = TRO05 -> TRO04 | umlauf
|
||||
c008 = TRO05 -> TRO10 | transfer
|
||||
c009 = TRO01 -> TRO05 | weiche
|
||||
c010 = TRO10 -> TRO12 | transfer
|
||||
c011 = TRO04 -> TRO03 | bahn
|
||||
c012 = TRO03 -> TRO11 | transfer
|
||||
c013 = TRO03 -> TRO02 | bahn
|
||||
c014 = TRO11 -> TRO02 | transfer
|
||||
c015 = TRO02 -> TRO09 | transfer
|
||||
@@ -0,0 +1,193 @@
|
||||
# Mubea — Material Flow & TROs (from the dxfmakros layout)
|
||||
|
||||
**As of:** 2026-08-07 · **Source:** `data/export.csv` (113 rows, fresh `EXPORTCSV`) · **Plant:** Mubea 500573 "Sitzbezügelager"
|
||||
|
||||
> **Update (2026-08-07 — material flow rebuilt from the richer `export.csv`).**
|
||||
> The new export adds the **transfer/switch elements** — 23 Einschleuselement, 23
|
||||
> Ausschleuselement, 1 Weiche — and fully populated `Nachbarn`. `material_flow.py` now
|
||||
> **uses the Ein-/Ausschleuselement to direct every Kreisel↔Strecke edge**
|
||||
> (`Ausschleusung` = Kreisel→Strecke at the strecke's *Anfang*, `Einschleusung` =
|
||||
> Strecke→Kreisel at its *Ende*) instead of guessing from heights, and **marks the Weiche**
|
||||
> on the Kreisel↔Kreisel link. Result: directions are now deterministic (no more "unknown
|
||||
> type" warnings, ambiguities resolved). Two return-lane ends remain unreachable **on
|
||||
> purpose** — they are the open ends the **BTMT entry/exit (Beladung/Entladung)** will close
|
||||
> once those stations are placed. *The TRO section further below still reflects the earlier
|
||||
> `mubea.csv` run and is regenerated in the **next** step.*
|
||||
|
||||
> **How to read this.** The Mubea layout was drawn in BricsCAD with our **dxfmakros**
|
||||
> library, so every conveyor object is a real, attributed item. dxfmakros exported those
|
||||
> items — with their **coordinates, properties and neighbours** — to `mubea.csv`. From that
|
||||
> CSV the `lib/` tooling derives two graphs, both **laid out at the real plant coordinates**
|
||||
> so they match the drawing:
|
||||
>
|
||||
> 1. the **material-flow graph** — the mechanical objects and how material moves between them;
|
||||
> 2. the **TRO graph** — the control units (Transfer Route Objects) derived from that flow.
|
||||
>
|
||||
> This is generated output, not hand-authored — see [§5](#5-how-this-was-produced) to regenerate.
|
||||
> (The earlier [TRO_Identifikation_500573.md](TRO_Identifikation_500573.md) was a manual first
|
||||
> pass on a *different*, purely mechanical drawing; **this** file supersedes it for Mubea.)
|
||||
|
||||
---
|
||||
|
||||
## 1. The plant in one paragraph
|
||||
|
||||
Empty hanger carriers (**Bügelträger**) circulate on three rotary tables (**Kreisel**) linked
|
||||
by driven conveyor segments (**VarioFörderer / Strecke**). The core is a **line store** of
|
||||
**20 gravity lanes** (**Gefällestrecke**), each with its own separator, sharing a common
|
||||
in-/outfeed — i.e. one **PinStore**. Barcode **scanners** read carriers at three points.
|
||||
|
||||
**Item inventory (from `export.csv`):**
|
||||
|
||||
| Item type (German) | Meaning | Count | Role in the graph |
|
||||
|---|---|---:|---|
|
||||
| `ILS 2.0 Gefaellestrecke` | gravity lane (rolls down by slope) | 20 | node |
|
||||
| `ILS 2.0 Separator` | stopper / separator (releases one carrier) | 33 | attached (`Zuordnung`) |
|
||||
| `ILS 2.0 Scanner` | barcode scanner | 7 | attached (`Zuordnung`) |
|
||||
| `ILS 2.0 Kreisel` | rotary table / turntable (2 lanes each) | 3 | node (2 lanes each) |
|
||||
| `ILS 2.0 Strecke` | driven conveyor segment (VarioFörderer) | 3 | node |
|
||||
| `ILS Ausschleuselement` | Kreisel→Strecke transfer (at strecke *Anfang*) | 23 | **directs an edge** |
|
||||
| `ILS Einschleuselement` | Strecke→Kreisel transfer (at strecke *Ende*) | 23 | **directs an edge** |
|
||||
| `ILS Weiche` | switch between two Kreisel | 1 | **marks an edge** |
|
||||
| **Total** | | **113** | |
|
||||
|
||||
The transfer/switch elements don't become their own nodes — they supply the **direction** of
|
||||
the Kreisel↔Strecke edges and mark the Weiche, so the graph stays at the conveyor-object level.
|
||||
|
||||
---
|
||||
|
||||
## 2. Material-flow graph (real-layout placement)
|
||||
|
||||
Nodes are placed at their true plant coordinates (`neato -n`, 0.25 pt/mm), so the picture
|
||||
matches the drawing: the 20 gravity lanes form the central vertical stack, fed by **Kreisel 3**
|
||||
(left) and discharging into **Kreisel 2** (right).
|
||||
|
||||

|
||||
|
||||
> Open [`graphs/mubea_material_flow.svg`](graphs/mubea_material_flow.svg) for the full-resolution,
|
||||
> zoomable version. Full node/connection listing: [`graphs/mubea_material_flow_report.md`](graphs/mubea_material_flow_report.md).
|
||||
|
||||
### 2.1 Items with their properties (flow objects)
|
||||
|
||||
Separators and scanners are *attachments* — they appear in the last two columns of the object
|
||||
they sit on. A **Kreisel** is a loop, modelled as two lanes (`-L` / `-R`).
|
||||
|
||||
| Node | Type | Name | Grid | Height [m] | Separators | Scanners |
|
||||
|---|---|---|---|---:|---|---|
|
||||
| `0001-L` | Kreisel | Kreisel 3 (lane L) | A/1 | 1.470 | – | – |
|
||||
| `0001-R` | Kreisel | Kreisel 3 (lane R) | A/1 | 1.470 | 0057 | – |
|
||||
| `0002-L` | Kreisel | Kreisel 2 (lane L) | A/1 | 1.470 | 0003, 0010, 0011 | 0006 |
|
||||
| `0002-R` | Kreisel | Kreisel 2 (lane R) | A/1 | 1.470 | – | – |
|
||||
| `0009-L` | Kreisel | Kreisel 1 (lane L) | F/1 | 1.940 | – | – |
|
||||
| `0009-R` | Kreisel | Kreisel 1 (lane R) | F/1 | 1.940 | 0059, 0060 | – |
|
||||
| `0012` | Strecke | VarioFörderer 3 | A/10 | 0.237 | 0014, 0058 | – |
|
||||
| `0013` | Strecke | VarioFörderer 2 | A/1 | 0.237 | 0056, 0061 | 0005 |
|
||||
| `0015` | Strecke | VarioFörderer 1 | A/3 | 0.000 | – | 0008 |
|
||||
| `0016`–`0035` | Gefällestrecke ×20 | Gravity lanes 1–20 | E/2–E/10 | 1.941 | one each (0036–0055, +0004) | – |
|
||||
|
||||
*Coordinates, heights and the `Merkmale` (feature) properties per item are carried through from
|
||||
the CSV; the full per-lane table is in the [material report](graphs/mubea_material_flow_report.md).*
|
||||
|
||||
---
|
||||
|
||||
## 3. TRO graph (control units)
|
||||
|
||||
The TROs are **derived** from the material flow using the rules in `lib/tro_flow.py`
|
||||
(catalogue: `lib/tro_catalog.py`). The graph is placed at the same real coordinates.
|
||||
|
||||

|
||||
|
||||
> Full-resolution: [`graphs/mubea_tro_flow.svg`](graphs/mubea_tro_flow.svg) ·
|
||||
> full report incl. connections & rules: [`graphs/mubea_tro_report.md`](graphs/mubea_tro_report.md).
|
||||
|
||||
### 3.1 Result: 10 TROs
|
||||
|
||||
| Type | FB block | Count | Components per TRO |
|
||||
|---|---|---:|---|
|
||||
| `1Sep` | `FB_ILS_MTRO_1Sep` | 6 | 1× separator |
|
||||
| `Vario` | `FB_ILS_MTRO_Vario` | 3 | 1× separator, 1× drive |
|
||||
| `PinStore_Auto` | `FB_ILS_MTRO_PinStore_Auto` | 1 | 1× encoder, 1× scanner, 1× separator, 19× storage line |
|
||||
|
||||
### 3.2 TROs with their properties
|
||||
|
||||
| TRO | Type | X [mm] | Y [mm] | Host node(s) | Separators | Scanner | Why this type | Confidence |
|
||||
|---|---|---:|---:|---|---|---|---|---|
|
||||
| `TRO01` | `1Sep` | 5355 | −5878 | `0001-R` | 0057 | – | single separator on a driven Kreisel lane | medium |
|
||||
| `TRO02` | `1Sep` | −400 | 13920 | `0002-L` | 0003 | – | single separator on a driven Kreisel lane | medium |
|
||||
| `TRO03` | `1Sep` | −220 | −481 | `0002-L` | 0010 | 0008 | separator + scanner on a driven Kreisel lane | medium |
|
||||
| `TRO04` | `1Sep` | −220 | −3472 | `0002-L` | 0011 | 0006 | separator + scanner on a driven Kreisel lane | medium |
|
||||
| `TRO05` | `1Sep` | 10490 | −525 | `0009-R` | 0059 | 0007 | separator + scanner on a driven Kreisel lane | medium |
|
||||
| `TRO06` | `1Sep` | 10310 | 160 | `0009-R` | 0060 | – | single separator on a driven Kreisel lane | medium |
|
||||
| `TRO07` | `Vario` | 9186 | 13893 | `0012` | 0014, 0058 | – | driven conveyor segment (drive dir: up) | high |
|
||||
| `TRO08` | `Vario` | 5492 | −4980 | `0013` | 0056, 0061 | – | driven conveyor segment (drive dir: up) | high |
|
||||
| `TRO09` | `Vario` | −641 | 5859 | `0015` | – | – | driven conveyor segment (drive dir: up) | high |
|
||||
| `TRO10` | **`PinStore_Auto`** | 989 | 3924 | `0016 … 0035` (20 nodes) | 0004 … 0055 (21) | 0005 | **20 gravity lanes, each with its own separator, common in-/outfeed — the line-store pattern** | high |
|
||||
|
||||
*X/Y is the centroid of the components a TRO was built from (in the CSV plant coordinate system).*
|
||||
|
||||
---
|
||||
|
||||
## 4. Findings to confirm with the E-planning
|
||||
|
||||
The TRO **types** are solid; a few points can't be decided from the mechanical layout alone:
|
||||
|
||||
- **`1Sep` vs `1Sep_SSCC`.** TRO03, TRO04, TRO05 each have a scanner at the separator. They are
|
||||
typed `1Sep`; whether any is really `1Sep_SSCC` (SSCC scanner + end-measurement + WCS telegram)
|
||||
cannot be seen mechanically — confirm against the I/O list.
|
||||
- **Scanner mounting vs. reading point.** Scanner 0005 is mounted on `0013` but reads at
|
||||
separator 0004 on lane `0035`; scanner 0008 is mounted on `0015` but reads at separator 0010.
|
||||
(Noise from the export; noted, not fatal.)
|
||||
- **Two flow directions undetermined** around the Kreisel↔Strecke hand-overs (neighbours at equal
|
||||
height) — drawn bidirectional in the material graph until the drive directions are confirmed.
|
||||
- **CSV plausibility deltas** (stated `Anzahl_Separator`/`Anzahl_Scanner` vs. actually attached)
|
||||
are listed in the material report — worth a quick check in the drawing.
|
||||
|
||||
What is **not** derivable here and must come from the electrical planning / `FB_Main`: the binding
|
||||
TRO numbering, sensor/actuator tags, JamAreas, destination logic and timing.
|
||||
|
||||
---
|
||||
|
||||
## 5. How this was produced
|
||||
|
||||
```bat
|
||||
:: 1) items + material flow, placed at real coordinates
|
||||
bin\material_flow.bat --file mubea.csv --tosvg --use-cords --doc
|
||||
|
||||
:: 2) derive the TROs, placed at real coordinates
|
||||
bin\tro_flow.bat --file mubea.csv --tosvg --use-cords --doc
|
||||
```
|
||||
|
||||
Outputs land in `%SKEL_RESULTS%` (`results/`); the SVGs and reports here are copies. The
|
||||
`--use-cords` flag (new for `material_flow.py`, matching `tro_flow.py`) places every node at its
|
||||
plant coordinate and renders with Graphviz `neato -n`, so both graphs mirror the real layout.
|
||||
|
||||
**Next step (later, not now):** feed these TROs back into the BricsCAD drawing as TRO symbols
|
||||
with their connections (`lib/tro_annotate.py` → `results/mubea_annotated.dxf`, then the
|
||||
`dxfmakros` `TRO_INSERT` / `TRO_EDIT` menu), and record neighbours in `connect.ini`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Entry / exit points (BTMT Be-/Entladestation) & data freshness
|
||||
|
||||
The **entry and exit points** of the material flow are the **BTMT Be-/Entladestation**
|
||||
(`BTMT-Beladung` = loading = **entry/source**, `SC_Entladung` = unloading = **exit/sink**).
|
||||
`material_flow.py` now **recognises them** (matched on `TeileArt`/`Bezeichnung`): an entry
|
||||
becomes a green source node feeding the flow, an exit a red sink node — connected via the
|
||||
export's `Nachbarn`, or to the nearest object if none is given.
|
||||
|
||||
Two current limitations to be aware of:
|
||||
|
||||
1. **The stations are not in the drawing / CSV yet.** They are not placed in `Mubea.dxf`,
|
||||
and — importantly — dxfmakros' `EXPORTCSV` does **not** export them at all (their block
|
||||
names match no export pattern; dxfmakros docs mark this *"Export noch offen"*). So a
|
||||
freshly exported CSV still won't contain them until either the export is extended in
|
||||
dxfmakros or the rows are added by hand. The sps_skel recognition is ready for that moment.
|
||||
2. **The TRO graph does not yet show entry/exit.** `tro_flow.py` ignores the stations for
|
||||
now (they carry no separator, so they are not TROs). Adding them as boundary markers in
|
||||
the TRO graph is the planned follow-up, best done against a real BTMT row.
|
||||
|
||||
**On reading straight from the DXF instead of the CSV:** ezdxf reads `Mubea.dxf` fine (2.6 s)
|
||||
and gives correct item positions + attributes, but it **cannot reproduce the 3-D bounding
|
||||
boxes** that dxfmakros' neighbour detection relies on (`export_neighbors.py`, from BricsCAD's
|
||||
`vla-getboundingbox`) — so a BricsCAD-free reader can place items but not rebuild the
|
||||
connections reliably. The reliable path to *current* data is therefore a fresh
|
||||
`EXPORTCSV` run in BricsCAD; the graphs above are then regenerated with the two commands in §5.
|
||||
@@ -0,0 +1,102 @@
|
||||
; ============================================================
|
||||
; connect.ini - Materialfluss-Topologie (Item-/Flussebene)
|
||||
; Automatisch erzeugt von lib/material_flow.py aus 'export.csv'.
|
||||
; Zwischenstand fuer die TRO-Ableitung; von Hand editierbar.
|
||||
;
|
||||
; [<Anlage>.nodes] <Knoten> = <Art> | <Bezeichnung>
|
||||
; [<Anlage>.connections] cNNN = <von> -> <nach> | <JamArea> | <kind>
|
||||
; kind: normal | umlauf | weiche | einschleusung | ausschleusung | unbestimmt
|
||||
; [<Anlage>.externals] eNNN = EXTERN -> <Knoten> | <Info> (Zulauf/Beladung)
|
||||
; eNNN = <Knoten> -> EXTERN | <Info> (Ablauf/Entladung)
|
||||
; ============================================================
|
||||
|
||||
[Mubea.nodes]
|
||||
0001-L = Kreisel | Kreisel1 (Bahn L)
|
||||
0001-R = Kreisel | Kreisel1 (Bahn R)
|
||||
0002-L = Kreisel | Kreisel2 (Bahn L)
|
||||
0002-R = Kreisel | Kreisel2 (Bahn R)
|
||||
0010-L = Kreisel | Kreisel3 (Bahn L)
|
||||
0010-R = Kreisel | Kreisel3 (Bahn R)
|
||||
0013 = Strecke | VarioFoerderer :3
|
||||
0014 = Strecke | VarioFoerderer :2
|
||||
0016 = Strecke | VarioFoerderer :1
|
||||
0017 = Gefaellestrecke | Gefaellestrecke :20
|
||||
0018 = Gefaellestrecke | Gefaellestrecke :19
|
||||
0019 = Gefaellestrecke | Gefaellestrecke :18
|
||||
0020 = Gefaellestrecke | Gefaellestrecke :17
|
||||
0021 = Gefaellestrecke | Gefaellestrecke :16
|
||||
0022 = Gefaellestrecke | Gefaellestrecke :15
|
||||
0023 = Gefaellestrecke | Gefaellestrecke :14
|
||||
0024 = Gefaellestrecke | Gefaellestrecke :13
|
||||
0025 = Gefaellestrecke | Gefaellestrecke :12
|
||||
0026 = Gefaellestrecke | Gefaellestrecke :11
|
||||
0027 = Gefaellestrecke | Gefaellestrecke :10
|
||||
0028 = Gefaellestrecke | Gefaellestrecke :9
|
||||
0029 = Gefaellestrecke | Gefaellestrecke :8
|
||||
0030 = Gefaellestrecke | Gefaellestrecke :7
|
||||
0031 = Gefaellestrecke | Gefaellestrecke :6
|
||||
0032 = Gefaellestrecke | Gefaellestrecke :5
|
||||
0033 = Gefaellestrecke | Gefaellestrecke :4
|
||||
0034 = Gefaellestrecke | Gefaellestrecke :3
|
||||
0035 = Gefaellestrecke | Gefaellestrecke :2
|
||||
0036 = Gefaellestrecke | Gefaellestrecke :1
|
||||
|
||||
[Mubea.connections]
|
||||
c001 = 0001-L -> 0002-R | | weiche
|
||||
c002 = 0001-R -> 0001-L | | umlauf
|
||||
c003 = 0001-R -> 0002-R | | weiche
|
||||
c004 = 0002-L -> 0016 | | ausschleusung
|
||||
c005 = 0002-R -> 0002-L | | umlauf
|
||||
c006 = 0002-R -> 0013 | | ausschleusung
|
||||
c007 = 0002-R -> 0014 | | ausschleusung
|
||||
c008 = 0010-L -> 0017 | | ausschleusung
|
||||
c009 = 0010-L -> 0018 | | ausschleusung
|
||||
c010 = 0010-L -> 0019 | | ausschleusung
|
||||
c011 = 0010-L -> 0020 | | ausschleusung
|
||||
c012 = 0010-L -> 0021 | | ausschleusung
|
||||
c013 = 0010-L -> 0022 | | ausschleusung
|
||||
c014 = 0010-L -> 0023 | | ausschleusung
|
||||
c015 = 0010-L -> 0024 | | ausschleusung
|
||||
c016 = 0010-L -> 0025 | | ausschleusung
|
||||
c017 = 0010-L -> 0026 | | ausschleusung
|
||||
c018 = 0010-L -> 0027 | | ausschleusung
|
||||
c019 = 0010-L -> 0028 | | ausschleusung
|
||||
c020 = 0010-L -> 0029 | | ausschleusung
|
||||
c021 = 0010-L -> 0030 | | ausschleusung
|
||||
c022 = 0010-L -> 0031 | | ausschleusung
|
||||
c023 = 0010-L -> 0032 | | ausschleusung
|
||||
c024 = 0010-L -> 0033 | | ausschleusung
|
||||
c025 = 0010-L -> 0034 | | ausschleusung
|
||||
c026 = 0010-L -> 0035 | | ausschleusung
|
||||
c027 = 0010-L -> 0036 | | ausschleusung
|
||||
c028 = 0010-R -> 0010-L | | umlauf
|
||||
c029 = 0013 -> 0010-L | | einschleusung
|
||||
c030 = 0014 -> 0010-L | | einschleusung
|
||||
c031 = 0016 -> 0002-R | | einschleusung
|
||||
c032 = 0017 -> 0002-R | | einschleusung
|
||||
c033 = 0018 -> 0002-R | | einschleusung
|
||||
c034 = 0019 -> 0002-R | | einschleusung
|
||||
c035 = 0020 -> 0002-R | | einschleusung
|
||||
c036 = 0021 -> 0002-R | | einschleusung
|
||||
c037 = 0022 -> 0002-R | | einschleusung
|
||||
c038 = 0023 -> 0002-R | | einschleusung
|
||||
c039 = 0024 -> 0002-R | | einschleusung
|
||||
c040 = 0025 -> 0002-R | | einschleusung
|
||||
c041 = 0026 -> 0002-R | | einschleusung
|
||||
c042 = 0027 -> 0002-R | | einschleusung
|
||||
c043 = 0028 -> 0002-R | | einschleusung
|
||||
c044 = 0029 -> 0002-R | | einschleusung
|
||||
c045 = 0030 -> 0002-R | | einschleusung
|
||||
c046 = 0031 -> 0002-R | | einschleusung
|
||||
c047 = 0032 -> 0002-R | | einschleusung
|
||||
c048 = 0033 -> 0002-R | | einschleusung
|
||||
c049 = 0034 -> 0002-R | | einschleusung
|
||||
c050 = 0035 -> 0002-R | | einschleusung
|
||||
c051 = 0036 -> 0002-R | | einschleusung
|
||||
|
||||
[Mubea.externals]
|
||||
; Noch keine BTMT Be-/Entladestation im Layout - Ein-/Ausgang offen.
|
||||
; Kandidaten (offene Enden aus dem Materialfluss):
|
||||
; Beladung? EXTERN -> 0001-R (Kreisel, keine Zufuhr)
|
||||
; Beladung? EXTERN -> 0010-R (Kreisel, keine Zufuhr)
|
||||
|
||||
@@ -0,0 +1,637 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 15.1.0 (20260618.0150)
|
||||
-->
|
||||
<!-- Title: Materialfluss Pages: 1 -->
|
||||
<svg width="2928pt" height="5734pt"
|
||||
viewBox="0.00 0.00 2928.00 5734.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 5730.07)">
|
||||
<title>Materialfluss</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-5730.07 2924.07,-5730.07 2924.07,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1460.04" y="-5711.62" font-family="Segoe UI" font-size="11.00">Materialfluss - export.csv</text>
|
||||
<!-- 0001-L -->
|
||||
<g id="node1" class="node">
|
||||
<title>0001-L</title>
|
||||
<path fill="#2f5597" stroke="#1f3864" d="M1241.32,-981.25C1241.32,-981.25 1182.57,-981.25 1182.57,-981.25 1176.57,-981.25 1170.57,-975.25 1170.57,-969.25 1170.57,-969.25 1170.57,-947 1170.57,-947 1170.57,-941 1176.57,-935 1182.57,-935 1182.57,-935 1241.32,-935 1241.32,-935 1247.32,-935 1253.32,-941 1253.32,-947 1253.32,-947 1253.32,-969.25 1253.32,-969.25 1253.32,-975.25 1247.32,-981.25 1241.32,-981.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1211.95" y="-968.7" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Kreisel1  [0001-L]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1211.95" y="-955.95" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Bahn L (links)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1211.95" y="-943.2" font-family="Segoe UI" font-size="9.00" fill="#ffffff">h = 1.470 m</text>
|
||||
</g>
|
||||
<!-- 0002-R -->
|
||||
<g id="node4" class="node">
|
||||
<title>0002-R</title>
|
||||
<path fill="#2f5597" stroke="#1f3864" d="M416.69,-3308.13C416.69,-3308.13 357.19,-3308.13 357.19,-3308.13 351.19,-3308.13 345.19,-3302.13 345.19,-3296.13 345.19,-3296.13 345.19,-3273.88 345.19,-3273.88 345.19,-3267.88 351.19,-3261.88 357.19,-3261.88 357.19,-3261.88 416.69,-3261.88 416.69,-3261.88 422.69,-3261.88 428.69,-3267.88 428.69,-3273.88 428.69,-3273.88 428.69,-3296.13 428.69,-3296.13 428.69,-3302.13 422.69,-3308.13 416.69,-3308.13"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.94" y="-3295.58" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Kreisel2  [0002-R]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.94" y="-3282.83" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Bahn R (rechts)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.94" y="-3270.08" font-family="Segoe UI" font-size="9.00" fill="#ffffff">h = 1.470 m</text>
|
||||
</g>
|
||||
<!-- 0001-L->0002-R -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>0001-L->0002-R</title>
|
||||
<g id="a_edge1"><a xlink:title="Richtung Weiche">
|
||||
<path fill="none" stroke="#bf8f00" stroke-width="1.2" stroke-dasharray="5,2" d="M1200.43,-990.59C1108.22,-1250.68 490.75,-2992.22 398.47,-3252.49"/>
|
||||
<polygon fill="#bf8f00" stroke="#bf8f00" stroke-width="1.2" points="1203,-991.72 1203.04,-983.24 1197.73,-989.85 1203,-991.72"/>
|
||||
<polygon fill="#bf8f00" stroke="#bf8f00" stroke-width="1.2" points="395.94,-3251.27 395.9,-3259.74 401.21,-3253.14 395.94,-3251.27"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="786.11" y="-2124.76" font-family="Segoe UI" font-size="8.00" fill="#cc8800">Weiche</text>
|
||||
</g>
|
||||
<!-- 0001-R -->
|
||||
<g id="node2" class="node">
|
||||
<title>0001-R</title>
|
||||
<path fill="#2f5597" stroke="#1f3864" d="M1244.32,-812.62C1244.32,-812.62 1179.57,-812.62 1179.57,-812.62 1173.57,-812.62 1167.57,-806.62 1167.57,-800.62 1167.57,-800.62 1167.57,-765.62 1167.57,-765.62 1167.57,-759.62 1173.57,-753.62 1179.57,-753.62 1179.57,-753.62 1244.32,-753.62 1244.32,-753.62 1250.32,-753.62 1256.32,-759.62 1256.32,-765.62 1256.32,-765.62 1256.32,-800.62 1256.32,-800.62 1256.32,-806.62 1250.32,-812.62 1244.32,-812.62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1211.95" y="-800.08" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Kreisel1  [0001-R]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1211.95" y="-787.33" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Bahn R (rechts)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1211.95" y="-774.58" font-family="Segoe UI" font-size="9.00" fill="#ffffff">h = 1.470 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1211.95" y="-761.83" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Separator (1): 0061</text>
|
||||
</g>
|
||||
<!-- 0001-R->0001-L -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>0001-R->0001-L</title>
|
||||
<g id="a_edge5"><a xlink:title="Kreisel-Umlauf UZS">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M1211.95,-812.81C1211.95,-843.6 1211.95,-891.69 1211.95,-924.02"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1208.8,-923.93 1211.95,-932.93 1215.1,-923.93 1208.8,-923.93"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1204.82" y="-877.56" font-family="Segoe UI" font-size="8.00" fill="#5b7fc7">UZS</text>
|
||||
</g>
|
||||
<!-- 0001-R->0002-R -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>0001-R->0002-R</title>
|
||||
<g id="a_edge2"><a xlink:title="Richtung Weiche">
|
||||
<path fill="none" stroke="#bf8f00" stroke-width="1.2" stroke-dasharray="5,2" d="M1199.1,-822.08C1102.18,-1116.01 487.19,-2981.01 397.78,-3252.15"/>
|
||||
<polygon fill="#bf8f00" stroke="#bf8f00" stroke-width="1.2" points="1201.69,-823.16 1201.54,-814.69 1196.37,-821.41 1201.69,-823.16"/>
|
||||
<polygon fill="#bf8f00" stroke="#bf8f00" stroke-width="1.2" points="395.12,-3251.26 395.28,-3259.74 400.44,-3253.02 395.12,-3251.26"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="782.11" y="-2049.34" font-family="Segoe UI" font-size="8.00" fill="#cc8800">Weiche</text>
|
||||
</g>
|
||||
<!-- 0002-L -->
|
||||
<g id="node3" class="node">
|
||||
<title>0002-L</title>
|
||||
<path fill="#2f5597" stroke="#1f3864" d="M441.82,-3495.88C441.82,-3495.88 332.07,-3495.88 332.07,-3495.88 326.07,-3495.88 320.07,-3489.88 320.07,-3483.88 320.07,-3483.88 320.07,-3436.13 320.07,-3436.13 320.07,-3430.13 326.07,-3424.13 332.07,-3424.13 332.07,-3424.13 441.82,-3424.13 441.82,-3424.13 447.82,-3424.13 453.82,-3430.13 453.82,-3436.13 453.82,-3436.13 453.82,-3483.88 453.82,-3483.88 453.82,-3489.88 447.82,-3495.88 441.82,-3495.88"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.94" y="-3483.33" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Kreisel2  [0002-L]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.94" y="-3470.58" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Bahn L (links)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.94" y="-3457.83" font-family="Segoe UI" font-size="9.00" fill="#ffffff">h = 1.470 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.94" y="-3445.08" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Separator (3): 0003, 0011, 0012</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="386.94" y="-3432.33" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Scanner (3): 0004, 0007, 0009</text>
|
||||
</g>
|
||||
<!-- 0016 -->
|
||||
<g id="node9" class="node">
|
||||
<title>0016</title>
|
||||
<path fill="#e2f0d9" stroke="#548235" d="M279.12,-3816.49C279.12,-3816.49 179.13,-3816.49 179.13,-3816.49 173.13,-3816.49 167.13,-3810.49 167.13,-3804.49 167.13,-3804.49 167.13,-3743.99 167.13,-3743.99 167.13,-3737.99 173.13,-3731.99 179.13,-3731.99 179.13,-3731.99 279.12,-3731.99 279.12,-3731.99 285.12,-3731.99 291.12,-3737.99 291.12,-3743.99 291.12,-3743.99 291.12,-3804.49 291.12,-3804.49 291.12,-3810.49 285.12,-3816.49 279.12,-3816.49"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="229.13" y="-3803.94" font-family="Segoe UI" font-size="9.00" fill="#375623">VarioFoerderer :1  [0016]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="229.13" y="-3791.19" font-family="Segoe UI" font-size="9.00" fill="#375623">Strecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="229.13" y="-3778.44" font-family="Segoe UI" font-size="9.00" fill="#375623">h = 0.000 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="229.13" y="-3765.69" font-family="Segoe UI" font-size="9.00" fill="#375623">0 -> 0 mm (+0) = aufwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="229.13" y="-3752.94" font-family="Segoe UI" font-size="9.00" fill="#375623">Separator (2): 0058, 0059</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="229.13" y="-3740.19" font-family="Segoe UI" font-size="9.00" fill="#375623">Scanner (1): 0060</text>
|
||||
</g>
|
||||
<!-- 0002-L->0016 -->
|
||||
<g id="edge46" class="edge">
|
||||
<title>0002-L->0016</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M368.69,-3496.36C340.63,-3552.22 286.83,-3659.35 254.84,-3723.04"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="252.38,-3721.7 251.29,-3730.1 257.39,-3724.21 252.38,-3721.7"/>
|
||||
</g>
|
||||
<!-- 0002-R->0002-L -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>0002-R->0002-L</title>
|
||||
<g id="a_edge4"><a xlink:title="Kreisel-Umlauf UZS">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M386.94,-3308.61C386.94,-3335.29 386.94,-3379.42 386.94,-3413.16"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="383.8,-3412.9 386.95,-3421.9 390.1,-3412.9 383.8,-3412.9"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="379.82" y="-3369.77" font-family="Segoe UI" font-size="8.00" fill="#5b7fc7">UZS</text>
|
||||
</g>
|
||||
<!-- 0013 -->
|
||||
<g id="node7" class="node">
|
||||
<title>0013</title>
|
||||
<path fill="#e2f0d9" stroke="#548235" d="M1681.56,-5703.07C1681.56,-5703.07 1563.56,-5703.07 1563.56,-5703.07 1557.56,-5703.07 1551.56,-5697.07 1551.56,-5691.07 1551.56,-5691.07 1551.56,-5643.32 1551.56,-5643.32 1551.56,-5637.32 1557.56,-5631.32 1563.56,-5631.32 1563.56,-5631.32 1681.56,-5631.32 1681.56,-5631.32 1687.56,-5631.32 1693.56,-5637.32 1693.56,-5643.32 1693.56,-5643.32 1693.56,-5691.07 1693.56,-5691.07 1693.56,-5697.07 1687.56,-5703.07 1681.56,-5703.07"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-5690.52" font-family="Segoe UI" font-size="9.00" fill="#375623">VarioFoerderer :3  [0013]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-5677.77" font-family="Segoe UI" font-size="9.00" fill="#375623">Strecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-5665.02" font-family="Segoe UI" font-size="9.00" fill="#375623">h = 0.237 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-5652.27" font-family="Segoe UI" font-size="9.00" fill="#375623">0 -> 474 mm (+474) = aufwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-5639.52" font-family="Segoe UI" font-size="9.00" fill="#375623">Separator (2): 0015, 0062</text>
|
||||
</g>
|
||||
<!-- 0002-R->0013 -->
|
||||
<g id="edge50" class="edge">
|
||||
<title>0002-R->0013</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M399.2,-3308.48C413.29,-3335.48 437.1,-3381.15 457.52,-3420.43 918.48,-4307.16 1480.01,-5391.79 1599.53,-5622.68"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1596.92,-5623.73 1603.08,-5629.55 1601.89,-5621.16 1596.92,-5623.73"/>
|
||||
</g>
|
||||
<!-- 0014 -->
|
||||
<g id="node8" class="node">
|
||||
<title>0014</title>
|
||||
<path fill="#e2f0d9" stroke="#548235" d="M1681.56,-1146.19C1681.56,-1146.19 1563.56,-1146.19 1563.56,-1146.19 1557.56,-1146.19 1551.56,-1140.19 1551.56,-1134.19 1551.56,-1134.19 1551.56,-1073.69 1551.56,-1073.69 1551.56,-1067.69 1557.56,-1061.69 1563.56,-1061.69 1563.56,-1061.69 1681.56,-1061.69 1681.56,-1061.69 1687.56,-1061.69 1693.56,-1067.69 1693.56,-1073.69 1693.56,-1073.69 1693.56,-1134.19 1693.56,-1134.19 1693.56,-1140.19 1687.56,-1146.19 1681.56,-1146.19"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-1133.64" font-family="Segoe UI" font-size="9.00" fill="#375623">VarioFoerderer :2  [0014]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-1120.89" font-family="Segoe UI" font-size="9.00" fill="#375623">Strecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-1108.14" font-family="Segoe UI" font-size="9.00" fill="#375623">h = 0.237 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-1095.39" font-family="Segoe UI" font-size="9.00" fill="#375623">0 -> 474 mm (+474) = aufwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-1082.64" font-family="Segoe UI" font-size="9.00" fill="#375623">Separator (2): 0057, 0065</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1622.56" y="-1069.89" font-family="Segoe UI" font-size="9.00" fill="#375623">Scanner (1): 0006</text>
|
||||
</g>
|
||||
<!-- 0002-R->0014 -->
|
||||
<g id="edge48" class="edge">
|
||||
<title>0002-R->0014</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M400.19,-3261.62C520.3,-3049.62 1420.55,-1460.54 1593.78,-1154.76"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1596.05,-1156.43 1597.55,-1148.09 1591.18,-1153.67 1596.05,-1156.43"/>
|
||||
</g>
|
||||
<!-- 0010-L -->
|
||||
<g id="node5" class="node">
|
||||
<title>0010-L</title>
|
||||
<path fill="#2f5597" stroke="#1f3864" d="M2893.82,-3483.13C2893.82,-3483.13 2835.07,-3483.13 2835.07,-3483.13 2829.07,-3483.13 2823.07,-3477.13 2823.07,-3471.13 2823.07,-3471.13 2823.07,-3448.88 2823.07,-3448.88 2823.07,-3442.88 2829.07,-3436.88 2835.07,-3436.88 2835.07,-3436.88 2893.82,-3436.88 2893.82,-3436.88 2899.82,-3436.88 2905.82,-3442.88 2905.82,-3448.88 2905.82,-3448.88 2905.82,-3471.13 2905.82,-3471.13 2905.82,-3477.13 2899.82,-3483.13 2893.82,-3483.13"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2864.44" y="-3470.58" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Kreisel3  [0010-L]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2864.44" y="-3457.83" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Bahn L (links)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2864.44" y="-3445.08" font-family="Segoe UI" font-size="9.00" fill="#ffffff">h = 1.940 m</text>
|
||||
</g>
|
||||
<!-- 0017 -->
|
||||
<g id="node10" class="node">
|
||||
<title>0017</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-5327.64C1693.98,-5327.64 1563.23,-5327.64 1563.23,-5327.64 1557.23,-5327.64 1551.23,-5321.64 1551.23,-5315.64 1551.23,-5315.64 1551.23,-5267.89 1551.23,-5267.89 1551.23,-5261.89 1557.23,-5255.89 1563.23,-5255.89 1563.23,-5255.89 1693.98,-5255.89 1693.98,-5255.89 1699.98,-5255.89 1705.98,-5261.89 1705.98,-5267.89 1705.98,-5267.89 1705.98,-5315.64 1705.98,-5315.64 1705.98,-5321.64 1699.98,-5327.64 1693.98,-5327.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5315.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :20  [0017]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5302.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5289.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5276.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5264.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0037</text>
|
||||
</g>
|
||||
<!-- 0010-L->0017 -->
|
||||
<g id="edge44" class="edge">
|
||||
<title>0010-L->0017</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2848.59,-3483.5C2718.91,-3675.72 1832.79,-4989.12 1658.37,-5247.64"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1656.12,-5245.98 1653.96,-5254.18 1660.76,-5249.11 1656.12,-5245.98"/>
|
||||
</g>
|
||||
<!-- 0018 -->
|
||||
<g id="node11" class="node">
|
||||
<title>0018</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-5127.64C1693.98,-5127.64 1563.23,-5127.64 1563.23,-5127.64 1557.23,-5127.64 1551.23,-5121.64 1551.23,-5115.64 1551.23,-5115.64 1551.23,-5067.89 1551.23,-5067.89 1551.23,-5061.89 1557.23,-5055.89 1563.23,-5055.89 1563.23,-5055.89 1693.98,-5055.89 1693.98,-5055.89 1699.98,-5055.89 1705.98,-5061.89 1705.98,-5067.89 1705.98,-5067.89 1705.98,-5115.64 1705.98,-5115.64 1705.98,-5121.64 1699.98,-5127.64 1693.98,-5127.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5115.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :19  [0018]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5102.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5089.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5076.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-5064.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0038</text>
|
||||
</g>
|
||||
<!-- 0010-L->0018 -->
|
||||
<g id="edge42" class="edge">
|
||||
<title>0010-L->0018</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2846.74,-3483.39C2711.56,-3661.86 1843.31,-4808.27 1661.83,-5047.9"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1659.61,-5046.19 1657.01,-5054.26 1664.07,-5049.57 1659.61,-5046.19"/>
|
||||
</g>
|
||||
<!-- 0019 -->
|
||||
<g id="node12" class="node">
|
||||
<title>0019</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-4927.64C1693.98,-4927.64 1563.23,-4927.64 1563.23,-4927.64 1557.23,-4927.64 1551.23,-4921.64 1551.23,-4915.64 1551.23,-4915.64 1551.23,-4867.89 1551.23,-4867.89 1551.23,-4861.89 1557.23,-4855.89 1563.23,-4855.89 1563.23,-4855.89 1693.98,-4855.89 1693.98,-4855.89 1699.98,-4855.89 1705.98,-4861.89 1705.98,-4867.89 1705.98,-4867.89 1705.98,-4915.64 1705.98,-4915.64 1705.98,-4921.64 1699.98,-4927.64 1693.98,-4927.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4915.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :18  [0019]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4902.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4889.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4876.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4864.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0039</text>
|
||||
</g>
|
||||
<!-- 0010-L->0019 -->
|
||||
<g id="edge40" class="edge">
|
||||
<title>0010-L->0019</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2844.28,-3483.37C2702.46,-3647.67 1855.06,-4629.41 1665.99,-4848.45"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1664.1,-4846.36 1660.99,-4854.24 1668.34,-4850.02 1664.1,-4846.36"/>
|
||||
</g>
|
||||
<!-- 0020 -->
|
||||
<g id="node13" class="node">
|
||||
<title>0020</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-4727.64C1693.98,-4727.64 1563.23,-4727.64 1563.23,-4727.64 1557.23,-4727.64 1551.23,-4721.64 1551.23,-4715.64 1551.23,-4715.64 1551.23,-4667.89 1551.23,-4667.89 1551.23,-4661.89 1557.23,-4655.89 1563.23,-4655.89 1563.23,-4655.89 1693.98,-4655.89 1693.98,-4655.89 1699.98,-4655.89 1705.98,-4661.89 1705.98,-4667.89 1705.98,-4667.89 1705.98,-4715.64 1705.98,-4715.64 1705.98,-4721.64 1699.98,-4727.64 1693.98,-4727.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4715.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :17  [0020]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4702.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4689.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4676.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4664.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0040</text>
|
||||
</g>
|
||||
<!-- 0010-L->0020 -->
|
||||
<g id="edge38" class="edge">
|
||||
<title>0010-L->0020</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2840.86,-3483.51C2690.89,-3632.99 1870.17,-4451 1671.79,-4648.73"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1669.97,-4646.58 1666.28,-4654.21 1673.92,-4650.55 1669.97,-4646.58"/>
|
||||
</g>
|
||||
<!-- 0021 -->
|
||||
<g id="node14" class="node">
|
||||
<title>0021</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-4527.64C1693.98,-4527.64 1563.23,-4527.64 1563.23,-4527.64 1557.23,-4527.64 1551.23,-4521.64 1551.23,-4515.64 1551.23,-4515.64 1551.23,-4467.89 1551.23,-4467.89 1551.23,-4461.89 1557.23,-4455.89 1563.23,-4455.89 1563.23,-4455.89 1693.98,-4455.89 1693.98,-4455.89 1699.98,-4455.89 1705.98,-4461.89 1705.98,-4467.89 1705.98,-4467.89 1705.98,-4515.64 1705.98,-4515.64 1705.98,-4521.64 1699.98,-4527.64 1693.98,-4527.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4515.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :16  [0021]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4502.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4489.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4476.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4464.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0041</text>
|
||||
</g>
|
||||
<!-- 0010-L->0021 -->
|
||||
<g id="edge36" class="edge">
|
||||
<title>0010-L->0021</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2836.31,-3483.49C2677.05,-3616.46 1888.32,-4274.94 1679.44,-4449.33"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1677.7,-4447.13 1673.36,-4454.4 1681.29,-4451.43 1677.7,-4447.13"/>
|
||||
</g>
|
||||
<!-- 0022 -->
|
||||
<g id="node15" class="node">
|
||||
<title>0022</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-4327.64C1693.98,-4327.64 1563.23,-4327.64 1563.23,-4327.64 1557.23,-4327.64 1551.23,-4321.64 1551.23,-4315.64 1551.23,-4315.64 1551.23,-4267.89 1551.23,-4267.89 1551.23,-4261.89 1557.23,-4255.89 1563.23,-4255.89 1563.23,-4255.89 1693.98,-4255.89 1693.98,-4255.89 1699.98,-4255.89 1705.98,-4261.89 1705.98,-4267.89 1705.98,-4267.89 1705.98,-4315.64 1705.98,-4315.64 1705.98,-4321.64 1699.98,-4327.64 1693.98,-4327.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4315.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :15  [0022]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4302.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4289.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4276.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4264.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0042</text>
|
||||
</g>
|
||||
<!-- 0010-L->0022 -->
|
||||
<g id="edge34" class="edge">
|
||||
<title>0010-L->0022</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2829.45,-3483.56C2658.63,-3598.53 1911.67,-4101.25 1690.51,-4250.1"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1689.13,-4247.65 1684.06,-4254.44 1692.26,-4252.3 1689.13,-4247.65"/>
|
||||
</g>
|
||||
<!-- 0023 -->
|
||||
<g id="node16" class="node">
|
||||
<title>0023</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-4127.64C1693.98,-4127.64 1563.23,-4127.64 1563.23,-4127.64 1557.23,-4127.64 1551.23,-4121.64 1551.23,-4115.64 1551.23,-4115.64 1551.23,-4067.89 1551.23,-4067.89 1551.23,-4061.89 1557.23,-4055.89 1563.23,-4055.89 1563.23,-4055.89 1693.98,-4055.89 1693.98,-4055.89 1699.98,-4055.89 1705.98,-4061.89 1705.98,-4067.89 1705.98,-4067.89 1705.98,-4115.64 1705.98,-4115.64 1705.98,-4121.64 1699.98,-4127.64 1693.98,-4127.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4115.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :14  [0023]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4102.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4089.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4076.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-4064.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0043</text>
|
||||
</g>
|
||||
<!-- 0010-L->0023 -->
|
||||
<g id="edge32" class="edge">
|
||||
<title>0010-L->0023</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2822.62,-3481.39C2644.26,-3572.56 1945.55,-3929.74 1708.09,-4051.13"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1706.97,-4048.56 1701.12,-4054.7 1709.52,-4053.55 1706.97,-4048.56"/>
|
||||
</g>
|
||||
<!-- 0024 -->
|
||||
<g id="node17" class="node">
|
||||
<title>0024</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-3927.64C1693.98,-3927.64 1563.23,-3927.64 1563.23,-3927.64 1557.23,-3927.64 1551.23,-3921.64 1551.23,-3915.64 1551.23,-3915.64 1551.23,-3867.89 1551.23,-3867.89 1551.23,-3861.89 1557.23,-3855.89 1563.23,-3855.89 1563.23,-3855.89 1693.98,-3855.89 1693.98,-3855.89 1699.98,-3855.89 1705.98,-3861.89 1705.98,-3867.89 1705.98,-3867.89 1705.98,-3915.64 1705.98,-3915.64 1705.98,-3921.64 1699.98,-3927.64 1693.98,-3927.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3915.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :13  [0024]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3902.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3889.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3876.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3864.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0044</text>
|
||||
</g>
|
||||
<!-- 0010-L->0024 -->
|
||||
<g id="edge30" class="edge">
|
||||
<title>0010-L->0024</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2822.62,-3474.62C2646.11,-3536.28 1960.05,-3775.97 1715.66,-3861.35"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1714.8,-3858.69 1708.17,-3863.97 1716.64,-3863.97 1714.8,-3858.69"/>
|
||||
</g>
|
||||
<!-- 0025 -->
|
||||
<g id="node18" class="node">
|
||||
<title>0025</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-3727.64C1693.98,-3727.64 1563.23,-3727.64 1563.23,-3727.64 1557.23,-3727.64 1551.23,-3721.64 1551.23,-3715.64 1551.23,-3715.64 1551.23,-3667.89 1551.23,-3667.89 1551.23,-3661.89 1557.23,-3655.89 1563.23,-3655.89 1563.23,-3655.89 1693.98,-3655.89 1693.98,-3655.89 1699.98,-3655.89 1705.98,-3661.89 1705.98,-3667.89 1705.98,-3667.89 1705.98,-3715.64 1705.98,-3715.64 1705.98,-3721.64 1699.98,-3727.64 1693.98,-3727.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3715.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :12  [0025]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3702.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3689.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3676.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3664.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0045</text>
|
||||
</g>
|
||||
<!-- 0010-L->0025 -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>0010-L->0025</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2822.62,-3467.85C2646.2,-3500.93 1960.73,-3629.48 1716.02,-3675.37"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1715.59,-3672.6 1708.24,-3676.83 1716.62,-3678.11 1715.59,-3672.6"/>
|
||||
</g>
|
||||
<!-- 0026 -->
|
||||
<g id="node19" class="node">
|
||||
<title>0026</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-3527.64C1693.98,-3527.64 1563.23,-3527.64 1563.23,-3527.64 1557.23,-3527.64 1551.23,-3521.64 1551.23,-3515.64 1551.23,-3515.64 1551.23,-3467.89 1551.23,-3467.89 1551.23,-3461.89 1557.23,-3455.89 1563.23,-3455.89 1563.23,-3455.89 1693.98,-3455.89 1693.98,-3455.89 1699.98,-3455.89 1705.98,-3461.89 1705.98,-3467.89 1705.98,-3467.89 1705.98,-3515.64 1705.98,-3515.64 1705.98,-3521.64 1699.98,-3527.64 1693.98,-3527.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3515.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :11  [0026]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3502.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3489.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3476.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3464.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0046</text>
|
||||
</g>
|
||||
<!-- 0010-L->0026 -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>0010-L->0026</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2822.62,-3461.08C2646.2,-3465.61 1960.73,-3483.23 1716.02,-3489.52"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1716.19,-3486.71 1708.27,-3489.72 1716.34,-3492.31 1716.19,-3486.71"/>
|
||||
</g>
|
||||
<!-- 0027 -->
|
||||
<g id="node20" class="node">
|
||||
<title>0027</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-3327.64C1693.98,-3327.64 1563.23,-3327.64 1563.23,-3327.64 1557.23,-3327.64 1551.23,-3321.64 1551.23,-3315.64 1551.23,-3315.64 1551.23,-3267.89 1551.23,-3267.89 1551.23,-3261.89 1557.23,-3255.89 1563.23,-3255.89 1563.23,-3255.89 1693.98,-3255.89 1693.98,-3255.89 1699.98,-3255.89 1705.98,-3261.89 1705.98,-3267.89 1705.98,-3267.89 1705.98,-3315.64 1705.98,-3315.64 1705.98,-3321.64 1699.98,-3327.64 1693.98,-3327.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3315.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :10  [0027]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3302.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3289.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3276.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3264.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0047</text>
|
||||
</g>
|
||||
<!-- 0010-L->0027 -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>0010-L->0027</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2822.62,-3454.31C2646.2,-3430.29 1960.73,-3336.98 1716.02,-3303.67"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1716.56,-3300.91 1708.25,-3302.61 1715.8,-3306.46 1716.56,-3300.91"/>
|
||||
</g>
|
||||
<!-- 0028 -->
|
||||
<g id="node21" class="node">
|
||||
<title>0028</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-3127.64C1693.98,-3127.64 1563.23,-3127.64 1563.23,-3127.64 1557.23,-3127.64 1551.23,-3121.64 1551.23,-3115.64 1551.23,-3115.64 1551.23,-3067.89 1551.23,-3067.89 1551.23,-3061.89 1557.23,-3055.89 1563.23,-3055.89 1563.23,-3055.89 1693.98,-3055.89 1693.98,-3055.89 1699.98,-3055.89 1705.98,-3061.89 1705.98,-3067.89 1705.98,-3067.89 1705.98,-3115.64 1705.98,-3115.64 1705.98,-3121.64 1699.98,-3127.64 1693.98,-3127.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3115.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :9  [0028]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3102.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3089.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3076.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-3064.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0048</text>
|
||||
</g>
|
||||
<!-- 0010-L->0028 -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>0010-L->0028</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2822.62,-3447.54C2646.11,-3394.95 1960.05,-3190.52 1715.66,-3117.7"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1716.66,-3115.08 1708.19,-3115.48 1715.06,-3120.45 1716.66,-3115.08"/>
|
||||
</g>
|
||||
<!-- 0029 -->
|
||||
<g id="node22" class="node">
|
||||
<title>0029</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-2927.64C1693.98,-2927.64 1563.23,-2927.64 1563.23,-2927.64 1557.23,-2927.64 1551.23,-2921.64 1551.23,-2915.64 1551.23,-2915.64 1551.23,-2867.89 1551.23,-2867.89 1551.23,-2861.89 1557.23,-2855.89 1563.23,-2855.89 1563.23,-2855.89 1693.98,-2855.89 1693.98,-2855.89 1699.98,-2855.89 1705.98,-2861.89 1705.98,-2867.89 1705.98,-2867.89 1705.98,-2915.64 1705.98,-2915.64 1705.98,-2921.64 1699.98,-2927.64 1693.98,-2927.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2915.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :8  [0029]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2902.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2889.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2876.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2864.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0049</text>
|
||||
</g>
|
||||
<!-- 0010-L->0029 -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>0010-L->0029</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2822.62,-3440.77C2646.03,-3359.58 1959.37,-3043.85 1715.3,-2931.63"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1716.54,-2929.12 1708.1,-2928.32 1714.2,-2934.2 1716.54,-2929.12"/>
|
||||
</g>
|
||||
<!-- 0030 -->
|
||||
<g id="node23" class="node">
|
||||
<title>0030</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-2727.64C1693.98,-2727.64 1563.23,-2727.64 1563.23,-2727.64 1557.23,-2727.64 1551.23,-2721.64 1551.23,-2715.64 1551.23,-2715.64 1551.23,-2667.89 1551.23,-2667.89 1551.23,-2661.89 1557.23,-2655.89 1563.23,-2655.89 1563.23,-2655.89 1693.98,-2655.89 1693.98,-2655.89 1699.98,-2655.89 1705.98,-2661.89 1705.98,-2667.89 1705.98,-2667.89 1705.98,-2715.64 1705.98,-2715.64 1705.98,-2721.64 1699.98,-2727.64 1693.98,-2727.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2715.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :7  [0030]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2702.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2689.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2676.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2664.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0050</text>
|
||||
</g>
|
||||
<!-- 0010-L->0030 -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>0010-L->0030</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2826.44,-3436.38C2651.2,-3327.44 1920.01,-2872.91 1694.88,-2732.96"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1696.58,-2730.72 1688.31,-2728.88 1693.62,-2735.48 1696.58,-2730.72"/>
|
||||
</g>
|
||||
<!-- 0031 -->
|
||||
<g id="node24" class="node">
|
||||
<title>0031</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-2527.64C1693.98,-2527.64 1563.23,-2527.64 1563.23,-2527.64 1557.23,-2527.64 1551.23,-2521.64 1551.23,-2515.64 1551.23,-2515.64 1551.23,-2467.89 1551.23,-2467.89 1551.23,-2461.89 1557.23,-2455.89 1563.23,-2455.89 1563.23,-2455.89 1693.98,-2455.89 1693.98,-2455.89 1699.98,-2455.89 1705.98,-2461.89 1705.98,-2467.89 1705.98,-2467.89 1705.98,-2515.64 1705.98,-2515.64 1705.98,-2521.64 1699.98,-2527.64 1693.98,-2527.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2515.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :6  [0031]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2502.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2489.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2476.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2464.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0051</text>
|
||||
</g>
|
||||
<!-- 0010-L->0031 -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>0010-L->0031</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2834.51,-3436.55C2672.02,-3309.25 1895.48,-2700.85 1682.65,-2534.11"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1684.47,-2531.98 1676.45,-2529.25 1681.02,-2536.39 1684.47,-2531.98"/>
|
||||
</g>
|
||||
<!-- 0032 -->
|
||||
<g id="node25" class="node">
|
||||
<title>0032</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-2327.64C1693.98,-2327.64 1563.23,-2327.64 1563.23,-2327.64 1557.23,-2327.64 1551.23,-2321.64 1551.23,-2315.64 1551.23,-2315.64 1551.23,-2267.89 1551.23,-2267.89 1551.23,-2261.89 1557.23,-2255.89 1563.23,-2255.89 1563.23,-2255.89 1693.98,-2255.89 1693.98,-2255.89 1699.98,-2255.89 1705.98,-2261.89 1705.98,-2267.89 1705.98,-2267.89 1705.98,-2315.64 1705.98,-2315.64 1705.98,-2321.64 1699.98,-2327.64 1693.98,-2327.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2315.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :5  [0032]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2302.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2289.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2276.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2264.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0052</text>
|
||||
</g>
|
||||
<!-- 0010-L->0032 -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>0010-L->0032</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2839.48,-3436.4C2686.46,-3291.75 1875.24,-2524.91 1673.87,-2334.56"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1676.03,-2332.74 1668.29,-2329.28 1672.18,-2336.81 1676.03,-2332.74"/>
|
||||
</g>
|
||||
<!-- 0033 -->
|
||||
<g id="node26" class="node">
|
||||
<title>0033</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-2127.64C1693.98,-2127.64 1563.23,-2127.64 1563.23,-2127.64 1557.23,-2127.64 1551.23,-2121.64 1551.23,-2115.64 1551.23,-2115.64 1551.23,-2067.89 1551.23,-2067.89 1551.23,-2061.89 1557.23,-2055.89 1563.23,-2055.89 1563.23,-2055.89 1693.98,-2055.89 1693.98,-2055.89 1699.98,-2055.89 1705.98,-2061.89 1705.98,-2067.89 1705.98,-2067.89 1705.98,-2115.64 1705.98,-2115.64 1705.98,-2121.64 1699.98,-2127.64 1693.98,-2127.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2115.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :4  [0033]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2102.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2089.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2076.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-2064.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0053</text>
|
||||
</g>
|
||||
<!-- 0010-L->0033 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>0010-L->0033</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2843.25,-3436.54C2698.93,-3276.76 1860.49,-2348.49 1667.99,-2135.37"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1670.07,-2133.5 1662.63,-2129.44 1665.92,-2137.25 1670.07,-2133.5"/>
|
||||
</g>
|
||||
<!-- 0034 -->
|
||||
<g id="node27" class="node">
|
||||
<title>0034</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-1927.64C1693.98,-1927.64 1563.23,-1927.64 1563.23,-1927.64 1557.23,-1927.64 1551.23,-1921.64 1551.23,-1915.64 1551.23,-1915.64 1551.23,-1867.89 1551.23,-1867.89 1551.23,-1861.89 1557.23,-1855.89 1563.23,-1855.89 1563.23,-1855.89 1693.98,-1855.89 1693.98,-1855.89 1699.98,-1855.89 1705.98,-1861.89 1705.98,-1867.89 1705.98,-1867.89 1705.98,-1915.64 1705.98,-1915.64 1705.98,-1921.64 1699.98,-1927.64 1693.98,-1927.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1915.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :3  [0034]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1902.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1889.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1876.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1864.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0054</text>
|
||||
</g>
|
||||
<!-- 0010-L->0034 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>0010-L->0034</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2846.02,-3436.62C2708.85,-3262.56 1847.34,-2169.33 1663.21,-1935.68"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1665.47,-1934.03 1658.32,-1929.48 1661.08,-1937.49 1665.47,-1934.03"/>
|
||||
</g>
|
||||
<!-- 0035 -->
|
||||
<g id="node28" class="node">
|
||||
<title>0035</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-1727.64C1693.98,-1727.64 1563.23,-1727.64 1563.23,-1727.64 1557.23,-1727.64 1551.23,-1721.64 1551.23,-1715.64 1551.23,-1715.64 1551.23,-1667.89 1551.23,-1667.89 1551.23,-1661.89 1557.23,-1655.89 1563.23,-1655.89 1563.23,-1655.89 1693.98,-1655.89 1693.98,-1655.89 1699.98,-1655.89 1705.98,-1661.89 1705.98,-1667.89 1705.98,-1667.89 1705.98,-1715.64 1705.98,-1715.64 1705.98,-1721.64 1699.98,-1727.64 1693.98,-1727.64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1715.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :2  [0035]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1702.34" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1689.59" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1676.84" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1664.09" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (1): 0055</text>
|
||||
</g>
|
||||
<!-- 0010-L->0035 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>0010-L->0035</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2848.14,-3436.67C2717.11,-3249.2 1836.18,-1988.76 1659.44,-1735.89"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1661.86,-1734.45 1654.98,-1729.5 1657.27,-1737.66 1661.86,-1734.45"/>
|
||||
</g>
|
||||
<!-- 0036 -->
|
||||
<g id="node29" class="node">
|
||||
<title>0036</title>
|
||||
<path fill="#fbe5d6" stroke="#c55a11" d="M1693.98,-1534.01C1693.98,-1534.01 1563.23,-1534.01 1563.23,-1534.01 1557.23,-1534.01 1551.23,-1528.01 1551.23,-1522.01 1551.23,-1522.01 1551.23,-1461.51 1551.23,-1461.51 1551.23,-1455.51 1557.23,-1449.51 1563.23,-1449.51 1563.23,-1449.51 1693.98,-1449.51 1693.98,-1449.51 1699.98,-1449.51 1705.98,-1455.51 1705.98,-1461.51 1705.98,-1461.51 1705.98,-1522.01 1705.98,-1522.01 1705.98,-1528.01 1699.98,-1534.01 1693.98,-1534.01"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1521.46" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke :1  [0036]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1508.71" font-family="Segoe UI" font-size="9.00" fill="#833c00">Gefaellestrecke</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1495.96" font-family="Segoe UI" font-size="9.00" fill="#833c00">h = 1.941 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1483.21" font-family="Segoe UI" font-size="9.00" fill="#833c00">1941 -> 1466 mm (-475) = abwaerts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1470.46" font-family="Segoe UI" font-size="9.00" fill="#833c00">Separator (2): 0005, 0056</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1628.61" y="-1457.71" font-family="Segoe UI" font-size="9.00" fill="#833c00">Scanner (1): 0066</text>
|
||||
</g>
|
||||
<!-- 0010-L->0036 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>0010-L->0036</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2849.7,-3436.53C2724.51,-3237.14 1839.69,-1827.95 1660.29,-1542.22"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1662.78,-1540.93 1656.15,-1535.64 1658.04,-1543.9 1662.78,-1540.93"/>
|
||||
</g>
|
||||
<!-- 0010-R -->
|
||||
<g id="node6" class="node">
|
||||
<title>0010-R</title>
|
||||
<path fill="#2f5597" stroke="#1f3864" d="M2908.07,-3314.51C2908.07,-3314.51 2820.82,-3314.51 2820.82,-3314.51 2814.82,-3314.51 2808.82,-3308.51 2808.82,-3302.51 2808.82,-3302.51 2808.82,-3267.51 2808.82,-3267.51 2808.82,-3261.51 2814.82,-3255.51 2820.82,-3255.51 2820.82,-3255.51 2908.07,-3255.51 2908.07,-3255.51 2914.07,-3255.51 2920.07,-3261.51 2920.07,-3267.51 2920.07,-3267.51 2920.07,-3302.51 2920.07,-3302.51 2920.07,-3308.51 2914.07,-3314.51 2908.07,-3314.51"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2864.44" y="-3301.95" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Kreisel3  [0010-R]</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2864.44" y="-3289.2" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Bahn R (rechts)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2864.44" y="-3276.45" font-family="Segoe UI" font-size="9.00" fill="#ffffff">h = 1.940 m</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2864.44" y="-3263.7" font-family="Segoe UI" font-size="9.00" fill="#ffffff">Separator (2): 0063, 0064</text>
|
||||
</g>
|
||||
<!-- 0010-R->0010-L -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>0010-R->0010-L</title>
|
||||
<g id="a_edge3"><a xlink:title="Kreisel-Umlauf UZS">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M2864.44,-3314.69C2864.44,-3345.48 2864.44,-3393.57 2864.44,-3425.9"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="2861.3,-3425.81 2864.45,-3434.81 2867.6,-3425.81 2861.3,-3425.81"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2857.32" y="-3379.44" font-family="Segoe UI" font-size="8.00" fill="#5b7fc7">UZS</text>
|
||||
</g>
|
||||
<!-- 0013->0010-L -->
|
||||
<g id="edge51" class="edge">
|
||||
<title>0013->0010-L</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1642.83,-5631.18C1791.09,-5367.68 2706.66,-3740.44 2846.53,-3491.85"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="2848.8,-3493.52 2850.29,-3485.17 2843.92,-3490.77 2848.8,-3493.52"/>
|
||||
</g>
|
||||
<!-- 0014->0010-L -->
|
||||
<g id="edge49" class="edge">
|
||||
<title>0014->0010-L</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1645.05,-1146.6C1800.36,-1441.25 2711.82,-3170.45 2847.55,-3427.95"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="2844.99,-3429.1 2851.2,-3434.87 2849.94,-3426.49 2844.99,-3429.1"/>
|
||||
</g>
|
||||
<!-- 0016->0002-R -->
|
||||
<g id="edge47" class="edge">
|
||||
<title>0016->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M236.24,-3731.59C248.24,-3664.1 275.3,-3529.18 316.37,-3420.43 330.4,-3383.28 352.17,-3343.24 367.83,-3316.41"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="370.1,-3318.06 371.75,-3309.75 365.28,-3315.22 370.1,-3318.06"/>
|
||||
</g>
|
||||
<!-- 0017->0002-R -->
|
||||
<g id="edge45" class="edge">
|
||||
<title>0017->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1606.26,-5255.65C1452.33,-5006.88 550.95,-3550.07 406.48,-3316.57"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="409.02,-3315.35 402.43,-3310.02 404.25,-3318.3 409.02,-3315.35"/>
|
||||
</g>
|
||||
<!-- 0018->0002-R -->
|
||||
<g id="edge43" class="edge">
|
||||
<title>0018->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1603.8,-5055.67C1443.76,-4822.8 558.75,-3535 408.6,-3316.51"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="411.04,-3315.12 404.2,-3310.11 406.42,-3318.29 411.04,-3315.12"/>
|
||||
</g>
|
||||
<!-- 0019->0002-R -->
|
||||
<g id="edge41" class="edge">
|
||||
<title>0019->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1600.63,-4855.57C1433.32,-4639.06 566.89,-3517.86 410.99,-3316.12"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="413.34,-3314.58 406.23,-3309.97 408.91,-3318.01 413.34,-3314.58"/>
|
||||
</g>
|
||||
<!-- 0020->0002-R -->
|
||||
<g id="edge39" class="edge">
|
||||
<title>0020->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1596.66,-4655.58C1421.17,-4456.74 576.18,-3499.4 413.92,-3315.57"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="416.17,-3313.88 408.78,-3309.74 411.97,-3317.59 416.17,-3313.88"/>
|
||||
</g>
|
||||
<!-- 0021->0002-R -->
|
||||
<g id="edge37" class="edge">
|
||||
<title>0021->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1591.44,-4455.65C1406.47,-4275.87 587.15,-3479.59 417.68,-3314.88"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="419.78,-3313.01 412.09,-3309.44 415.88,-3317.03 419.78,-3313.01"/>
|
||||
</g>
|
||||
<!-- 0022->0002-R -->
|
||||
<g id="edge35" class="edge">
|
||||
<title>0022->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1584.05,-4255.64C1387.82,-4096.53 602.5,-3459.78 423.42,-3314.58"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="425.23,-3312.44 417.25,-3309.58 421.7,-3316.79 425.23,-3312.44"/>
|
||||
</g>
|
||||
<!-- 0023->0002-R -->
|
||||
<g id="edge33" class="edge">
|
||||
<title>0023->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1572.84,-4055.53C1362.67,-3918.98 620.79,-3436.94 431.28,-3313.81"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="432.95,-3311.56 424.72,-3309.55 429.9,-3316.26 432.95,-3311.56"/>
|
||||
</g>
|
||||
<!-- 0024->0002-R -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>0024->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1554.19,-3855.4C1324.63,-3743.22 631.34,-3404.43 437.68,-3309.8"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="439.16,-3307.4 430.74,-3306.41 436.7,-3312.43 439.16,-3307.4"/>
|
||||
</g>
|
||||
<!-- 0025->0002-R -->
|
||||
<g id="edge29" class="edge">
|
||||
<title>0025->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1550.93,-3666.32C1318.35,-3590.13 631.64,-3365.17 438.19,-3301.79"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="439.28,-3299.2 430.81,-3299.38 437.54,-3304.53 439.28,-3299.2"/>
|
||||
</g>
|
||||
<!-- 0026->0002-R -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>0026->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1550.93,-3478.83C1318.58,-3440.14 633,-3325.98 438.77,-3293.63"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="439.23,-3290.87 430.88,-3292.32 438.31,-3296.4 439.23,-3290.87"/>
|
||||
</g>
|
||||
<!-- 0027->0002-R -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>0027->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1550.93,-3291.34C1318.58,-3290.08 633,-3286.34 438.77,-3285.29"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="438.92,-3282.49 430.9,-3285.24 438.89,-3288.09 438.92,-3282.49"/>
|
||||
</g>
|
||||
<!-- 0028->0002-R -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>0028->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1550.93,-3103.85C1318.58,-3140.01 633,-3246.71 438.77,-3276.94"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="438.35,-3274.17 430.88,-3278.17 439.21,-3279.7 438.35,-3274.17"/>
|
||||
</g>
|
||||
<!-- 0029->0002-R -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>0029->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1550.93,-2916.36C1318.35,-2990.02 631.64,-3207.51 438.19,-3268.78"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="437.6,-3266.03 430.82,-3271.11 439.29,-3271.36 437.6,-3266.03"/>
|
||||
</g>
|
||||
<!-- 0030->0002-R -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>0030->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1552.8,-2727.98C1321.9,-2838.3 631.24,-3168.29 437.8,-3260.71"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="436.62,-3258.17 430.61,-3264.14 439.03,-3263.22 436.62,-3258.17"/>
|
||||
</g>
|
||||
<!-- 0031->0002-R -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>0031->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1572.03,-2527.91C1360.96,-2662.75 621.93,-3134.88 431.81,-3256.34"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="430.47,-3253.88 425.23,-3260.54 433.48,-3258.6 430.47,-3253.88"/>
|
||||
</g>
|
||||
<!-- 0032->0002-R -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>0032->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1583.31,-2328C1386.05,-2485.79 603.75,-3111.57 423.93,-3255.42"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="422.23,-3253.19 417.73,-3260.38 425.73,-3257.57 422.23,-3253.19"/>
|
||||
</g>
|
||||
<!-- 0033->0002-R -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>0033->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1590.77,-2128.13C1404.65,-2306.98 588.5,-3091.31 418.17,-3255"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="416.37,-3252.84 412.54,-3260.41 420.25,-3256.88 416.37,-3252.84"/>
|
||||
</g>
|
||||
<!-- 0034->0002-R -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>0034->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1596.35,-1927.96C1420.24,-2125.57 576.89,-3071.87 414.16,-3254.47"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="412.23,-3252.43 408.99,-3260.27 416.41,-3256.16 412.23,-3252.43"/>
|
||||
</g>
|
||||
<!-- 0035->0002-R -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>0035->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1600.34,-1728.04C1432.38,-1943.55 567.62,-3053.17 411.21,-3253.87"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="409.15,-3251.96 406.44,-3259.99 413.57,-3255.4 409.15,-3251.96"/>
|
||||
</g>
|
||||
<!-- 0036->0002-R -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>0036->0002-R</title>
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1599.14,-1534.32C1427.36,-1782.41 557.72,-3038.36 408.69,-3253.6"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="406.4,-3252 404.14,-3260.17 411,-3255.18 406.4,-3252"/>
|
||||
</g>
|
||||
<!-- legende -->
|
||||
<g id="node30" class="node">
|
||||
<title>legende</title>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-48.5" font-family="Segoe UI" font-size="9.00">durchgezogen</text>
|
||||
<text xml:space="preserve" text-anchor="start" x="78.75" y="-48.5" font-family="Segoe UI" font-size="9.00">Materialfluss</text>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-29.75" font-family="Segoe UI" font-size="9.00" fill="#8ea9db">gestrichelt blau</text>
|
||||
<text xml:space="preserve" text-anchor="start" x="78.75" y="-29.75" font-family="Segoe UI" font-size="9.00">Kreisel-Umlauf, Richtung aus Drehrichtung (UZS = rechts nach links, GUZ = links nach rechts)</text>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-11" font-family="Segoe UI" font-size="9.00" fill="#bf8f00">gestrichelt gelb</text>
|
||||
<text xml:space="preserve" text-anchor="start" x="78.75" y="-11" font-family="Segoe UI" font-size="9.00">Richtung nicht bestimmbar</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 58 KiB |
@@ -0,0 +1,145 @@
|
||||
<!-- erzeugt von lib/material_flow.py -->
|
||||
# Materialfluss - export.csv
|
||||
|
||||
**Erzeugt:** 2026-08-07 13:20 von `lib/material_flow.py`
|
||||
**Quelle:** `C:\develop\sps_skel\data\export.csv`
|
||||
|
||||
> Materialfluss der mechanischen Objekte. Die daraus abgeleiteten Steuerungsobjekte (TROs) dokumentiert `lib/tro_flow.py --doc`.
|
||||
|
||||
## 1. Kurzfassung
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Flussknoten | 29 (Gefaellestrecke: 20, Kreisel: 6, Strecke: 3) |
|
||||
| Flusskanten | 46 gerichtet, 3 Kreisel-Umlauf, 2 Richtung unbestimmt |
|
||||
| Anbauteile | Scanner: 6, Separator: 33 |
|
||||
| Plausibilitaetshinweise | 7 |
|
||||
|
||||
Graph: [`export_material_flow.dot`](export_material_flow.dot) - [`export_material_flow.svg`](export_material_flow.svg)
|
||||
|
||||
Ein **Kreisel** ist ein Umlauf und wird als zwei Knoten modelliert - eine Bahn je Fahrtrichtung (`-L` links, `-R` rechts), die zu einem Kreis verbunden sind.
|
||||
|
||||
## 2. Anlagenobjekte
|
||||
|
||||
| Knoten | Art | Bezeichnung | Planquadrat | Hoehe [m] | Separatoren | Scanner |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `0001-L` | Kreisel | Kreisel :3 / Kreisel1 (Bahn L) | A/1 | 1.470 | - | - |
|
||||
| `0001-R` | Kreisel | Kreisel :3 / Kreisel1 (Bahn R) | A/1 | 1.470 | 0061 | - |
|
||||
| `0002-L` | Kreisel | Kreisel :2 / Kreisel2 (Bahn L) | A/1 | 1.470 | 0003, 0011, 0012 | 0004, 0007, 0009 |
|
||||
| `0002-R` | Kreisel | Kreisel :2 / Kreisel2 (Bahn R) | A/1 | 1.470 | - | - |
|
||||
| `0010-L` | Kreisel | Kreisel :1 / Kreisel3 (Bahn L) | F/1 | 1.940 | - | - |
|
||||
| `0010-R` | Kreisel | Kreisel :1 / Kreisel3 (Bahn R) | F/1 | 1.940 | 0063, 0064 | - |
|
||||
| `0013` | Strecke | VarioFoerderer :3 | A/10 | 0.237 | 0015, 0062 | - |
|
||||
| `0014` | Strecke | VarioFoerderer :2 | A/1 | 0.237 | 0057, 0065 | 0006 |
|
||||
| `0016` | Strecke | VarioFoerderer :1 | A/4 | 0.000 | 0058, 0059 | 0060 |
|
||||
| `0017` | Gefaellestrecke | Gefaellestrecke :20 | F/10 | 1.941 | 0037 | - |
|
||||
| `0018` | Gefaellestrecke | Gefaellestrecke :19 | F/9 | 1.941 | 0038 | - |
|
||||
| `0019` | Gefaellestrecke | Gefaellestrecke :18 | F/9 | 1.941 | 0039 | - |
|
||||
| `0020` | Gefaellestrecke | Gefaellestrecke :17 | F/8 | 1.941 | 0040 | - |
|
||||
| `0021` | Gefaellestrecke | Gefaellestrecke :16 | F/8 | 1.941 | 0041 | - |
|
||||
| `0022` | Gefaellestrecke | Gefaellestrecke :15 | F/8 | 1.941 | 0042 | - |
|
||||
| `0023` | Gefaellestrecke | Gefaellestrecke :14 | F/7 | 1.941 | 0043 | - |
|
||||
| `0024` | Gefaellestrecke | Gefaellestrecke :13 | F/7 | 1.941 | 0044 | - |
|
||||
| `0025` | Gefaellestrecke | Gefaellestrecke :12 | F/6 | 1.941 | 0045 | - |
|
||||
| `0026` | Gefaellestrecke | Gefaellestrecke :11 | F/6 | 1.941 | 0046 | - |
|
||||
| `0027` | Gefaellestrecke | Gefaellestrecke :10 | F/6 | 1.941 | 0047 | - |
|
||||
| `0028` | Gefaellestrecke | Gefaellestrecke :9 | F/5 | 1.941 | 0048 | - |
|
||||
| `0029` | Gefaellestrecke | Gefaellestrecke :8 | F/5 | 1.941 | 0049 | - |
|
||||
| `0030` | Gefaellestrecke | Gefaellestrecke :7 | F/4 | 1.941 | 0050 | - |
|
||||
| `0031` | Gefaellestrecke | Gefaellestrecke :6 | F/4 | 1.941 | 0051 | - |
|
||||
| `0032` | Gefaellestrecke | Gefaellestrecke :5 | F/4 | 1.941 | 0052 | - |
|
||||
| `0033` | Gefaellestrecke | Gefaellestrecke :4 | F/3 | 1.941 | 0053 | - |
|
||||
| `0034` | Gefaellestrecke | Gefaellestrecke :3 | F/3 | 1.941 | 0054 | - |
|
||||
| `0035` | Gefaellestrecke | Gefaellestrecke :2 | F/2 | 1.941 | 0055 | - |
|
||||
| `0036` | Gefaellestrecke | Gefaellestrecke :1 | F/2 | 1.941 | 0005, 0056 | 0066 |
|
||||
|
||||
Bezeichnung: `Bezeichnung` aus dem CSV; wo das Merkmal `Name` abweicht, steht es dahinter (die beiden Nummerierungen laufen nicht zwangslaeufig gleich).
|
||||
|
||||
Hoehe: bei Kreiseln aus dem Merkmal `Höhe in m`, bei Gefaellestrecke und Strecke aus `Montagehoehe_m` - unveraendert aus dem CSV uebernommen. Fuer die Richtungsableitung werden nur die Hoehen der **Nachbarn** verglichen, nie die des Transportobjekts selbst.
|
||||
|
||||
**Anbauteile ohne Zuordnung**
|
||||
|
||||
- Scanner 0008 'Scanner :4' (Zuordnung: `nicht zugeordnet`)
|
||||
|
||||
## 3. Verbindungen
|
||||
|
||||
| von | nach | Art |
|
||||
|---|---|---|
|
||||
| `0001-L` | `0002-R` | Richtung unbestimmt (Weiche) |
|
||||
| `0001-R` | `0002-R` | Richtung unbestimmt (Weiche) |
|
||||
| `0010-R` | `0010-L` | Kreisel-Umlauf (UZS) |
|
||||
| `0002-R` | `0002-L` | Kreisel-Umlauf (UZS) |
|
||||
| `0001-R` | `0001-L` | Kreisel-Umlauf (UZS) |
|
||||
| `0010-L` | `0036` | Materialfluss |
|
||||
| `0036` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0035` | Materialfluss |
|
||||
| `0035` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0034` | Materialfluss |
|
||||
| `0034` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0033` | Materialfluss |
|
||||
| `0033` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0032` | Materialfluss |
|
||||
| `0032` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0031` | Materialfluss |
|
||||
| `0031` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0030` | Materialfluss |
|
||||
| `0030` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0029` | Materialfluss |
|
||||
| `0029` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0028` | Materialfluss |
|
||||
| `0028` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0027` | Materialfluss |
|
||||
| `0027` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0026` | Materialfluss |
|
||||
| `0026` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0025` | Materialfluss |
|
||||
| `0025` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0024` | Materialfluss |
|
||||
| `0024` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0023` | Materialfluss |
|
||||
| `0023` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0022` | Materialfluss |
|
||||
| `0022` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0021` | Materialfluss |
|
||||
| `0021` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0020` | Materialfluss |
|
||||
| `0020` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0019` | Materialfluss |
|
||||
| `0019` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0018` | Materialfluss |
|
||||
| `0018` | `0002-R` | Materialfluss |
|
||||
| `0010-L` | `0017` | Materialfluss |
|
||||
| `0017` | `0002-R` | Materialfluss |
|
||||
| `0002-L` | `0016` | Materialfluss |
|
||||
| `0016` | `0002-R` | Materialfluss |
|
||||
| `0002-R` | `0014` | Materialfluss |
|
||||
| `0014` | `0010-L` | Materialfluss |
|
||||
| `0002-R` | `0013` | Materialfluss |
|
||||
| `0013` | `0010-L` | Materialfluss |
|
||||
|
||||
Die Richtung innerhalb eines Kreisels kommt aus dem Merkmal `Drehrichtung`: **UZS** (im Uhrzeigersinn) laesst das Material rechts nach links laufen, **GUZ** (gegen den Uhrzeigersinn) links nach rechts.
|
||||
|
||||
## 4. Plausibilitaetshinweise
|
||||
|
||||
Abweichungen zwischen den Merkmalen des CSV-Exports und den tatsaechlich vorhandenen Objekten.
|
||||
|
||||
- Gefaellestrecke 0036 'Gefaellestrecke :1': Merkmal 'Anzahl_Scanner' = 0, tatsaechlich 1 Scanner
|
||||
- Gefaellestrecke 0036 'Gefaellestrecke :1': Merkmal 'Anzahl_Separator' = 1, tatsaechlich 2 Separator
|
||||
- Kreisel 0001 'Kreisel :3': Merkmal 'Anzahl der Separatoren' = 2, tatsaechlich 1 Separator
|
||||
- Kreisel 0002 'Kreisel :2': Merkmal 'Anzahl der Scanner' = 0, tatsaechlich 3 Scanner
|
||||
- Kreisel 0002 'Kreisel :2': Merkmal 'Anzahl der Separatoren' = 2, tatsaechlich 3 Separator
|
||||
- Strecke 0014 'VarioFoerderer :2': Merkmal 'Anzahl_Scanner' = 0, tatsaechlich 1 Scanner
|
||||
- Strecke 0016 'VarioFoerderer :1': Merkmal 'Anzahl_Scanner' = 0, tatsaechlich 1 Scanner
|
||||
|
||||
## 5. Warnungen des Laufs
|
||||
|
||||
- Zeile 52 (Strecke 0016 'VarioFoerderer :1'): alle Nachbarn auf gleicher Hoehe (1.470 m) - Richtung nicht bestimmbar
|
||||
- Verbindung 0001-L <-> 0002-R: Richtung nicht bestimmbar (kein Transportobjekt beteiligt) - beidseitig gezeichnet
|
||||
- Verbindung 0001-R <-> 0002-R: Richtung nicht bestimmbar (kein Transportobjekt beteiligt) - beidseitig gezeichnet
|
||||
- Verbindung 0002-L <-> 0016: Richtung nicht bestimmbar (kein Transportobjekt beteiligt) - beidseitig gezeichnet
|
||||
- Verbindung 0002-R <-> 0016: Richtung nicht bestimmbar (kein Transportobjekt beteiligt) - beidseitig gezeichnet
|
||||
- Strecke 0016: Ein- und Ausschleusung am selben Kreisel 0002 (Ruecklauf) - Bahnen 0002-L/0002-R angenommen
|
||||
- Kante 0001-L <-> 0014: Kreisel<->Strecke ohne Transferelement - als Bounding-Box-Falschtreffer verworfen
|
||||
- Bahn 0001-R (Separatoren 0061): keine ankommende Verbindung - fuer das Material nicht erreichbar
|
||||
- Bahn 0010-R (Separatoren 0063, 0064): keine ankommende Verbindung - fuer das Material nicht erreichbar
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 15.1.0 (20260618.0150)
|
||||
-->
|
||||
<!-- Title: TROFluss Pages: 1 -->
|
||||
<svg width="3852pt" height="5897pt"
|
||||
viewBox="0.00 0.00 3852.00 5897.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 5892.89)">
|
||||
<title>TROFluss</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-5892.89 3848.25,-5892.89 3848.25,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1922.12" y="-5874.44" font-family="Segoe UI" font-size="11.00">TRO-Fluss lagerichtig (0.25 pt/mm) - export.csv</text>
|
||||
<!-- TRO01->TRO02 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>TRO01->TRO02</title>
|
||||
<g id="a_edge1"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M2473.07,-900.25C2346.54,-1350.49 1254.4,-5236.7 1107.56,-5759.24"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1104.92,-5758.28 1105.45,-5766.74 1110.31,-5759.79 1104.92,-5758.28"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO01->TRO03 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>TRO01->TRO03</title>
|
||||
<g id="a_edge2"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M2441,-900.36C2236.51,-1098.32 1379.47,-1927.99 1148.69,-2151.4"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1146.83,-2149.31 1143.03,-2156.88 1150.72,-2153.33 1146.83,-2149.31"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO01->TRO04 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>TRO01->TRO04</title>
|
||||
<g id="a_edge3"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M2409.09,-890.51C2168.95,-994.13 1426.97,-1314.27 1175.55,-1422.76"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1174.72,-1420.06 1168.49,-1425.8 1176.94,-1425.21 1174.72,-1420.06"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO01->TRO07 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>TRO01->TRO07</title>
|
||||
<g id="a_edge4"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2493.44,-900.48C2581.69,-1348.03 3335.54,-5170.8 3432.51,-5662.51"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="3429.7,-5662.76 3434,-5670.07 3435.2,-5661.68 3429.7,-5662.76"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO01->TRO08 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>TRO01->TRO08</title>
|
||||
<g id="a_edge5"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2527.35,-900.37C2599.94,-973.46 2748.13,-1122.65 2828.82,-1203.87"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="2826.55,-1205.57 2834.18,-1209.27 2830.53,-1201.62 2826.55,-1205.57"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO02->TRO03 -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>TRO02->TRO03</title>
|
||||
<g id="a_edge25"><a xlink:title="gleiche Bahn">
|
||||
<path fill="none" stroke="#7f7f7f" stroke-width="1.2" stroke-dasharray="1,5" d="M1091.25,-5768.28C1091.25,-5369.14 1091.25,-2655.36 1091.25,-2256.04"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO02->TRO04 -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>TRO02->TRO04</title>
|
||||
<g id="a_edge26"><a xlink:title="gleiche Bahn">
|
||||
<path fill="none" stroke="#7f7f7f" stroke-width="1.2" stroke-dasharray="1,5" d="M1092.74,-5768.38C1102.22,-5454.9 1154.18,-3694.58 1170.08,-2259.33 1170.59,-2212.83 1172.7,-2201.12 1170.08,-2154.68 1156.3,-1910.8 1115.56,-1621.1 1098.69,-1507.88"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO02->TRO09 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>TRO02->TRO09</title>
|
||||
<g id="a_edge6"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1087.12,-5768.56C1059.71,-5524.2 911.88,-4432.84 870.34,-4167.47"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="873.15,-4167.27 869.14,-4159.8 867.62,-4168.14 873.15,-4167.27"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO03->TRO04 -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>TRO03->TRO04</title>
|
||||
<g id="a_edge27"><a xlink:title="gleiche Bahn">
|
||||
<path fill="none" stroke="#7f7f7f" stroke-width="1.2" stroke-dasharray="1,5" d="M1091.25,-2157.94C1091.25,-2022.27 1091.25,-1643.2 1091.25,-1507.89"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO03->TRO09 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>TRO03->TRO09</title>
|
||||
<g id="a_edge7"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1082.98,-2255.66C1045.15,-2518.3 893.28,-3765.59 864.29,-4050.93"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="861.55,-4050.23 863.54,-4058.47 867.12,-4050.79 861.55,-4050.23"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO04->TRO09 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>TRO04->TRO09</title>
|
||||
<g id="a_edge8"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1015.98,-1493.2C1007.3,-1497.76 1000.96,-1501.65 999.42,-1503.98 990.31,-1517.73 881.98,-3666.6 862.69,-4050.67"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="859.9,-4050.26 862.3,-4058.39 865.5,-4050.54 859.9,-4050.26"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO05->TRO06 -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>TRO05->TRO06</title>
|
||||
<g id="a_edge28"><a xlink:title="gleiche Bahn">
|
||||
<path fill="none" stroke="#7f7f7f" stroke-width="1.2" stroke-dasharray="1,5" d="M3755.85,-2245.06C3749.26,-2270.17 3741.31,-2300.43 3734.97,-2324.56"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO05->TRO10 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>TRO05->TRO10</title>
|
||||
<g id="a_edge9"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M3693.08,-2231.42C3347.86,-2393.07 1921.37,-3061 1506.91,-3255.06"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1505.9,-3252.44 1499.85,-3258.37 1508.28,-3257.51 1505.9,-3252.44"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO06->TRO10 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>TRO06->TRO10</title>
|
||||
<g id="a_edge10"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M3647.87,-2397.88C3309.47,-2534.52 1936.18,-3089.04 1516.16,-3258.64"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1515.37,-3255.93 1509,-3261.53 1517.47,-3261.13 1515.37,-3255.93"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO07->TRO10 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>TRO07->TRO10</title>
|
||||
<g id="a_edge11"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M3409.09,-5672C3170.24,-5381.78 1733.51,-3694.53 1444.22,-3364.23"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1446.59,-3362.67 1439.21,-3358.5 1442.37,-3366.37 1446.59,-3362.67"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO08->TRO10 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>TRO08->TRO10</title>
|
||||
<g id="a_edge12"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M2845.65,-1308.63C2636.53,-1585.96 1639.83,-2955.65 1431.65,-3251.69"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1429.65,-3249.67 1427.34,-3257.82 1434.23,-3252.89 1429.65,-3249.67"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO01 -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>TRO09->TRO01</title>
|
||||
<g id="a_edge13"><a xlink:title="Weiche (Kreisel-Uebergang)">
|
||||
<path fill="none" stroke="#cc8800" stroke-width="1.8" d="M883.26,-4060.48C946.37,-3929.91 1124.95,-3561.19 1276.43,-3255.84 1744.9,-2311.57 2328.58,-1164.71 2458.56,-909.63"/>
|
||||
<polygon fill="#cc8800" stroke="#cc8800" stroke-width="1.8" points="2460.97,-911.06 2462.11,-902.66 2455.98,-908.52 2460.97,-911.06"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1652.3" y="-2480.01" font-family="Segoe UI" font-size="8.00" fill="#cc8800">Weiche</text>
|
||||
</g>
|
||||
<!-- TRO09->TRO02 -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>TRO09->TRO02</title>
|
||||
<g id="a_edge14"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M863.88,-4157.87C891.29,-4402.23 1039.12,-5493.59 1080.66,-5758.96"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1077.85,-5759.16 1081.86,-5766.63 1083.38,-5758.29 1077.85,-5759.16"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO03 -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>TRO09->TRO03</title>
|
||||
<g id="a_edge15"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M868.02,-4060.52C905.85,-3797.88 1057.72,-2550.59 1086.71,-2265.25"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1089.45,-2265.95 1087.46,-2257.71 1083.88,-2265.39 1089.45,-2265.95"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO04 -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>TRO09->TRO04</title>
|
||||
<g id="a_edge16"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M862.49,-4060.07C881.68,-3716.07 995.95,-1672.6 1014.3,-1516.27"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1017,-1517.07 1015.57,-1508.71 1011.48,-1516.13 1017,-1517.07"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO07 -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>TRO09->TRO07</title>
|
||||
<g id="a_edge17"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M920.74,-4147.07C1269.14,-4363.61 3004.98,-5442.43 3373.8,-5671.65"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="3372.18,-5673.94 3380.46,-5675.79 3375.14,-5669.19 3372.18,-5673.94"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO08 -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>TRO09->TRO08</title>
|
||||
<g id="a_edge18"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M906.4,-4060.33C1016.85,-3943.71 1300.78,-3638 1510.59,-3360.48 2096.53,-2585.4 2703.77,-1566.76 2850.72,-1316.79"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="2852.99,-1318.45 2854.63,-1310.13 2848.16,-1315.61 2852.99,-1318.45"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO01 -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>TRO10->TRO01</title>
|
||||
<g id="a_edge19"><a xlink:title="Weiche (Kreisel-Uebergang)">
|
||||
<path fill="none" stroke="#cc8800" stroke-width="1.8" d="M1415.31,-3259.21C1554.56,-2946.6 2318.17,-1232.31 2461.73,-910"/>
|
||||
<polygon fill="#cc8800" stroke="#cc8800" stroke-width="1.8" points="2464.19,-911.37 2464.89,-902.93 2459.07,-909.1 2464.19,-911.37"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1927.05" y="-2083.71" font-family="Segoe UI" font-size="8.00" fill="#cc8800">Weiche</text>
|
||||
</g>
|
||||
<!-- TRO10->TRO02 -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>TRO10->TRO02</title>
|
||||
<g id="a_edge20"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M1387.61,-3357.16C1349.6,-3672.66 1139.61,-5415.85 1098.3,-5758.71"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1095.55,-5758.13 1097.38,-5766.4 1101.11,-5758.8 1095.55,-5758.13"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO03 -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>TRO10->TRO03</title>
|
||||
<g id="a_edge21"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M1380.03,-3259.07C1330.77,-3079.61 1160.57,-2459.55 1107.31,-2265.52"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1110.01,-2264.79 1105.2,-2257.82 1104.61,-2266.27 1110.01,-2264.79"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO04 -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>TRO10->TRO04</title>
|
||||
<g id="a_edge22"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M1385.5,-3259.18C1343.27,-3000.81 1146.58,-1797.59 1100.79,-1517.5"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1103.57,-1517.17 1099.52,-1509.72 1098.05,-1518.07 1103.57,-1517.17"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO07 -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>TRO10->TRO07</title>
|
||||
<g id="a_edge23"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1432.41,-3357.03C1687.95,-3666.69 3123.8,-5352.79 3397.65,-5664.84"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="3395.32,-5666.43 3402.7,-5670.59 3399.53,-5662.73 3395.32,-5666.43"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO08 -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>TRO10->TRO08</title>
|
||||
<g id="a_edge24"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1432.02,-3259.12C1641.14,-2981.79 2637.84,-1612.1 2846.02,-1316.06"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="2848.02,-1318.08 2850.33,-1309.93 2843.44,-1314.86 2848.02,-1318.08"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO01 -->
|
||||
<g id="node1" class="node">
|
||||
<title>TRO01</title>
|
||||
<path fill="#d4e8ff" stroke="#3388cc" d="M2548.51,-900C2548.51,-900 2421.51,-900 2421.51,-900 2415.51,-900 2409.51,-894 2409.51,-888 2409.51,-888 2409.51,-827.5 2409.51,-827.5 2409.51,-821.5 2415.51,-815.5 2421.51,-815.5 2421.51,-815.5 2548.51,-815.5 2548.51,-815.5 2554.51,-815.5 2560.51,-821.5 2560.51,-827.5 2560.51,-827.5 2560.51,-888 2560.51,-888 2560.51,-894 2554.51,-900 2548.51,-900"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2485.01" y="-887.45" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO01  (1Sep)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2485.01" y="-874.7" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0061 auf Kreisel1 Bahn R</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2485.01" y="-861.95" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2485.01" y="-849.2" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2485.01" y="-836.45" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0061</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2485.01" y="-823.7" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 5355, -5878</text>
|
||||
</g>
|
||||
<!-- TRO02 -->
|
||||
<g id="node2" class="node">
|
||||
<title>TRO02</title>
|
||||
<path fill="#d4e8ff" stroke="#3388cc" d="M1154.38,-5865.89C1154.38,-5865.89 1028.12,-5865.89 1028.12,-5865.89 1022.12,-5865.89 1016.12,-5859.89 1016.12,-5853.89 1016.12,-5853.89 1016.12,-5780.64 1016.12,-5780.64 1016.12,-5774.64 1022.12,-5768.64 1028.12,-5768.64 1028.12,-5768.64 1154.38,-5768.64 1154.38,-5768.64 1160.38,-5768.64 1166.38,-5774.64 1166.38,-5780.64 1166.38,-5780.64 1166.38,-5853.89 1166.38,-5853.89 1166.38,-5859.89 1160.38,-5865.89 1154.38,-5865.89"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-5853.34" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO02  (1Sep)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-5840.59" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0003 auf Kreisel2 Bahn L</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-5827.84" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-5815.09" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-5802.34" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0003</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-5789.59" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0004</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-5776.84" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: -220, 13960</text>
|
||||
</g>
|
||||
<!-- TRO03 -->
|
||||
<g id="node3" class="node">
|
||||
<title>TRO03</title>
|
||||
<path fill="#ffe4a0" stroke="#cc8800" d="M1154.38,-2255.63C1154.38,-2255.63 1028.12,-2255.63 1028.12,-2255.63 1022.12,-2255.63 1016.12,-2249.63 1016.12,-2243.63 1016.12,-2243.63 1016.12,-2170.38 1016.12,-2170.38 1016.12,-2164.38 1022.12,-2158.38 1028.12,-2158.38 1028.12,-2158.38 1154.38,-2158.38 1154.38,-2158.38 1160.38,-2158.38 1166.38,-2164.38 1166.38,-2170.38 1166.38,-2170.38 1166.38,-2243.63 1166.38,-2243.63 1166.38,-2249.63 1160.38,-2255.63 1154.38,-2255.63"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-2243.08" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO03  (1Sep1Swi)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-2230.33" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0011 auf Kreisel2 Bahn L</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-2217.58" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep1Swi</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-2204.83" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x Switch</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-2192.08" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0011</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-2179.33" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0009</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-2166.58" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: -220, -481</text>
|
||||
</g>
|
||||
<!-- TRO04 -->
|
||||
<g id="node4" class="node">
|
||||
<title>TRO04</title>
|
||||
<path fill="#ffd4d4" stroke="#cc3333" d="M1154.38,-1507.75C1154.38,-1507.75 1028.12,-1507.75 1028.12,-1507.75 1022.12,-1507.75 1016.12,-1501.75 1016.12,-1495.75 1016.12,-1495.75 1016.12,-1422.5 1016.12,-1422.5 1016.12,-1416.5 1022.12,-1410.5 1028.12,-1410.5 1028.12,-1410.5 1154.38,-1410.5 1154.38,-1410.5 1160.38,-1410.5 1166.38,-1416.5 1166.38,-1422.5 1166.38,-1422.5 1166.38,-1495.75 1166.38,-1495.75 1166.38,-1501.75 1160.38,-1507.75 1154.38,-1507.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-1495.2" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO04  (1Sep_SSCC)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-1482.45" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0012 auf Kreisel2 Bahn L</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-1469.7" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep_SSCC</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-1456.95" font-family="Segoe UI" font-size="9.00" fill="#111111">1x SSCC, 1x Scanner, 1x Separator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-1444.2" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0012</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-1431.45" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0007</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1091.25" y="-1418.7" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: -220, -3472</text>
|
||||
</g>
|
||||
<!-- TRO05 -->
|
||||
<g id="node5" class="node">
|
||||
<title>TRO05</title>
|
||||
<path fill="#ffe4a0" stroke="#cc8800" d="M3832.25,-2244.61C3832.25,-2244.61 3705.25,-2244.61 3705.25,-2244.61 3699.25,-2244.61 3693.25,-2238.61 3693.25,-2232.61 3693.25,-2232.61 3693.25,-2159.36 3693.25,-2159.36 3693.25,-2153.36 3699.25,-2147.36 3705.25,-2147.36 3705.25,-2147.36 3832.25,-2147.36 3832.25,-2147.36 3838.25,-2147.36 3844.25,-2153.36 3844.25,-2159.36 3844.25,-2159.36 3844.25,-2232.61 3844.25,-2232.61 3844.25,-2238.61 3838.25,-2244.61 3832.25,-2244.61"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3768.75" y="-2232.06" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO05  (1Sep1Swi)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3768.75" y="-2219.31" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0063 auf Kreisel3 Bahn R</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3768.75" y="-2206.56" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep1Swi</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3768.75" y="-2193.81" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x Switch</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3768.75" y="-2181.06" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0063</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3768.75" y="-2168.31" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0008</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3768.75" y="-2155.56" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 10490, -525</text>
|
||||
</g>
|
||||
<!-- TRO06 -->
|
||||
<g id="node6" class="node">
|
||||
<title>TRO06</title>
|
||||
<path fill="#d4e8ff" stroke="#3388cc" d="M3787.25,-2409.49C3787.25,-2409.49 3660.25,-2409.49 3660.25,-2409.49 3654.25,-2409.49 3648.25,-2403.49 3648.25,-2397.49 3648.25,-2397.49 3648.25,-2336.99 3648.25,-2336.99 3648.25,-2330.99 3654.25,-2324.99 3660.25,-2324.99 3660.25,-2324.99 3787.25,-2324.99 3787.25,-2324.99 3793.25,-2324.99 3799.25,-2330.99 3799.25,-2336.99 3799.25,-2336.99 3799.25,-2397.49 3799.25,-2397.49 3799.25,-2403.49 3793.25,-2409.49 3787.25,-2409.49"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3723.75" y="-2396.94" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO06  (1Sep)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3723.75" y="-2384.19" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0064 auf Kreisel3 Bahn R</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3723.75" y="-2371.44" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3723.75" y="-2358.69" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3723.75" y="-2345.94" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0064</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3723.75" y="-2333.19" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 10310, 160</text>
|
||||
</g>
|
||||
<!-- TRO07 -->
|
||||
<g id="node7" class="node">
|
||||
<title>TRO07</title>
|
||||
<path fill="#e8d4f0" stroke="#883388" d="M3491.26,-5756.76C3491.26,-5756.76 3394.26,-5756.76 3394.26,-5756.76 3388.26,-5756.76 3382.26,-5750.76 3382.26,-5744.76 3382.26,-5744.76 3382.26,-5684.26 3382.26,-5684.26 3382.26,-5678.26 3388.26,-5672.26 3394.26,-5672.26 3394.26,-5672.26 3491.26,-5672.26 3491.26,-5672.26 3497.26,-5672.26 3503.26,-5678.26 3503.26,-5684.26 3503.26,-5684.26 3503.26,-5744.76 3503.26,-5744.76 3503.26,-5750.76 3497.26,-5756.76 3491.26,-5756.76"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3442.76" y="-5744.21" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO07  (Vario)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3442.76" y="-5731.46" font-family="Segoe UI" font-size="9.00" fill="#111111">VarioFoerderer :3</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3442.76" y="-5718.71" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_Vario</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3442.76" y="-5705.96" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x VarioDrive</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3442.76" y="-5693.21" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0015, 0062</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="3442.76" y="-5680.46" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 9186, 13549</text>
|
||||
</g>
|
||||
<!-- TRO08 -->
|
||||
<g id="node8" class="node">
|
||||
<title>TRO08</title>
|
||||
<path fill="#e8d4f0" stroke="#883388" d="M2932.66,-1308.21C2932.66,-1308.21 2835.66,-1308.21 2835.66,-1308.21 2829.66,-1308.21 2823.66,-1302.21 2823.66,-1296.21 2823.66,-1296.21 2823.66,-1222.96 2823.66,-1222.96 2823.66,-1216.96 2829.66,-1210.96 2835.66,-1210.96 2835.66,-1210.96 2932.66,-1210.96 2932.66,-1210.96 2938.66,-1210.96 2944.66,-1216.96 2944.66,-1222.96 2944.66,-1222.96 2944.66,-1296.21 2944.66,-1296.21 2944.66,-1302.21 2938.66,-1308.21 2932.66,-1308.21"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2884.16" y="-1295.66" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO08  (Vario)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2884.16" y="-1282.91" font-family="Segoe UI" font-size="9.00" fill="#111111">VarioFoerderer :2</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2884.16" y="-1270.16" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_Vario</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2884.16" y="-1257.41" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x VarioDrive</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2884.16" y="-1244.66" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0057, 0065</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2884.16" y="-1231.91" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0066</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2884.16" y="-1219.16" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 6952, -4271</text>
|
||||
</g>
|
||||
<!-- TRO09 -->
|
||||
<g id="node9" class="node">
|
||||
<title>TRO09</title>
|
||||
<path fill="#e8d4f0" stroke="#883388" d="M908.25,-4157.8C908.25,-4157.8 811.25,-4157.8 811.25,-4157.8 805.25,-4157.8 799.25,-4151.8 799.25,-4145.8 799.25,-4145.8 799.25,-4072.55 799.25,-4072.55 799.25,-4066.55 805.25,-4060.55 811.25,-4060.55 811.25,-4060.55 908.25,-4060.55 908.25,-4060.55 914.25,-4060.55 920.25,-4066.55 920.25,-4072.55 920.25,-4072.55 920.25,-4145.8 920.25,-4145.8 920.25,-4151.8 914.25,-4157.8 908.25,-4157.8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="859.75" y="-4145.24" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO09  (Vario)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="859.75" y="-4132.49" font-family="Segoe UI" font-size="9.00" fill="#111111">VarioFoerderer :1</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="859.75" y="-4119.74" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_Vario</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="859.75" y="-4106.99" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x VarioDrive</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="859.75" y="-4094.24" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0058, 0059</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="859.75" y="-4081.49" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0060</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="859.75" y="-4068.74" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: -1146, 7128</text>
|
||||
</g>
|
||||
<!-- TRO10 -->
|
||||
<g id="node10" class="node">
|
||||
<title>TRO10</title>
|
||||
<path fill="#d4f0d4" stroke="#338833" d="M1494.88,-3356.78C1494.88,-3356.78 1292.13,-3356.78 1292.13,-3356.78 1286.13,-3356.78 1280.13,-3350.78 1280.13,-3344.78 1280.13,-3344.78 1280.13,-3271.53 1280.13,-3271.53 1280.13,-3265.53 1286.13,-3259.53 1292.13,-3259.53 1292.13,-3259.53 1494.88,-3259.53 1494.88,-3259.53 1500.88,-3259.53 1506.88,-3265.53 1506.88,-3271.53 1506.88,-3271.53 1506.88,-3344.78 1506.88,-3344.78 1506.88,-3350.78 1500.88,-3356.78 1494.88,-3356.78"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1393.51" y="-3344.23" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO10  (PinStore_Auto)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1393.51" y="-3331.48" font-family="Segoe UI" font-size="9.00" fill="#111111">Speicher (20 Schwerkraftlinien)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1393.51" y="-3318.73" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_PinStore_Auto</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1393.51" y="-3305.98" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Encoder, 1x Scanner, 1x Separator, 19x StorageLine</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1393.51" y="-3293.23" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0005 … 0056 (21)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1393.51" y="-3280.48" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0006</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1393.51" y="-3267.73" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 989, 3924</text>
|
||||
</g>
|
||||
<!-- legende -->
|
||||
<g id="node11" class="node">
|
||||
<title>legende</title>
|
||||
<polygon fill="#d4e8ff" stroke="none" points="8,-190.75 8,-211.5 76.75,-211.5 76.75,-190.75 8,-190.75"/>
|
||||
<polygon fill="none" stroke="black" points="8,-190.75 8,-211.5 76.75,-211.5 76.75,-190.75 8,-190.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-197.75" font-family="Segoe UI" font-size="9.00">  sep  </text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-190.75 76.75,-211.5 211.5,-211.5 211.5,-190.75 76.75,-190.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-197.75" font-family="Segoe UI" font-size="9.00">Separator</text>
|
||||
<polygon fill="#ffe4a0" stroke="none" points="8,-170 8,-190.75 76.75,-190.75 76.75,-170 8,-170"/>
|
||||
<polygon fill="none" stroke="black" points="8,-170 8,-190.75 76.75,-190.75 76.75,-170 8,-170"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-177" font-family="Segoe UI" font-size="9.00">  swi  </text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-170 76.75,-190.75 211.5,-190.75 211.5,-170 76.75,-170"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-177" font-family="Segoe UI" font-size="9.00">Weiche</text>
|
||||
<polygon fill="#ffd4d4" stroke="none" points="8,-149.25 8,-170 76.75,-170 76.75,-149.25 8,-149.25"/>
|
||||
<polygon fill="none" stroke="black" points="8,-149.25 8,-170 76.75,-170 76.75,-149.25 8,-149.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-156.25" font-family="Segoe UI" font-size="9.00">  sscc  </text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-149.25 76.75,-170 211.5,-170 211.5,-149.25 76.75,-149.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-156.25" font-family="Segoe UI" font-size="9.00">Scanner (SSCC)</text>
|
||||
<polygon fill="#e8d4f0" stroke="none" points="8,-128.5 8,-149.25 76.75,-149.25 76.75,-128.5 8,-128.5"/>
|
||||
<polygon fill="none" stroke="black" points="8,-128.5 8,-149.25 76.75,-149.25 76.75,-128.5 8,-128.5"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-135.5" font-family="Segoe UI" font-size="9.00">  vario  </text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-128.5 76.75,-149.25 211.5,-149.25 211.5,-128.5 76.75,-128.5"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-135.5" font-family="Segoe UI" font-size="9.00">Kettenfoerderer</text>
|
||||
<polygon fill="#d4f0d4" stroke="none" points="8,-107.75 8,-128.5 76.75,-128.5 76.75,-107.75 8,-107.75"/>
|
||||
<polygon fill="none" stroke="black" points="8,-107.75 8,-128.5 76.75,-128.5 76.75,-107.75 8,-107.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-114.75" font-family="Segoe UI" font-size="9.00">  store  </text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-107.75 76.75,-128.5 211.5,-128.5 211.5,-107.75 76.75,-107.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-114.75" font-family="Segoe UI" font-size="9.00">Speicher / Puffer</text>
|
||||
<polygon fill="#f0f0f0" stroke="none" points="8,-87 8,-107.75 76.75,-107.75 76.75,-87 8,-87"/>
|
||||
<polygon fill="none" stroke="black" points="8,-87 8,-107.75 76.75,-107.75 76.75,-87 8,-87"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-94" font-family="Segoe UI" font-size="9.00">  ext  </text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-87 76.75,-107.75 211.5,-107.75 211.5,-87 76.75,-87"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-94" font-family="Segoe UI" font-size="9.00">Systemgrenze / extern</text>
|
||||
<polygon fill="none" stroke="black" points="8,-66.25 8,-87 76.75,-87 76.75,-66.25 8,-66.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-73.25" font-family="Segoe UI" font-size="9.00" fill="#2f5597">durchgezogen</text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-66.25 76.75,-87 211.5,-87 211.5,-66.25 76.75,-66.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-73.25" font-family="Segoe UI" font-size="9.00">Uebergabe / Ein-Ausschleusung</text>
|
||||
<polygon fill="none" stroke="black" points="8,-45.5 8,-66.25 76.75,-66.25 76.75,-45.5 8,-45.5"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-52.5" font-family="Segoe UI" font-size="9.00" fill="#8ea9db">blau gestrichelt</text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-45.5 76.75,-66.25 211.5,-66.25 211.5,-45.5 76.75,-45.5"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-52.5" font-family="Segoe UI" font-size="9.00">Kreisel-Umlauf</text>
|
||||
<polygon fill="none" stroke="black" points="8,-24.75 8,-45.5 76.75,-45.5 76.75,-24.75 8,-24.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-31.75" font-family="Segoe UI" font-size="9.00" fill="#cc8800">orange</text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-24.75 76.75,-45.5 211.5,-45.5 211.5,-24.75 76.75,-24.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-31.75" font-family="Segoe UI" font-size="9.00">Weiche (Kreisel-Uebergang)</text>
|
||||
<polygon fill="none" stroke="black" points="8,-4 8,-24.75 76.75,-24.75 76.75,-4 8,-4"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="12" y="-11" font-family="Segoe UI" font-size="9.00">grau gepunktet</text>
|
||||
<polygon fill="none" stroke="black" points="76.75,-4 76.75,-24.75 211.5,-24.75 211.5,-4 76.75,-4"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="80.75" y="-11" font-family="Segoe UI" font-size="9.00">gleiche Bahn / Strecke</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,436 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 15.1.0 (20260618.0150)
|
||||
-->
|
||||
<!-- Title: TROFluss Pages: 1 -->
|
||||
<svg width="1513pt" height="948pt"
|
||||
viewBox="0.00 0.00 1513.00 948.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 944.32)">
|
||||
<title>TROFluss</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-944.32 1508.75,-944.32 1508.75,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="752.38" y="-925.87" font-family="Segoe UI" font-size="11.00">TRO-Fluss - export.csv</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_legende</title>
|
||||
<path fill="none" stroke="#a6a6a6" d="M20,-607.32C20,-607.32 231.5,-607.32 231.5,-607.32 237.5,-607.32 243.5,-613.32 243.5,-619.32 243.5,-619.32 243.5,-849.32 243.5,-849.32 243.5,-855.32 237.5,-861.32 231.5,-861.32 231.5,-861.32 20,-861.32 20,-861.32 14,-861.32 8,-855.32 8,-849.32 8,-849.32 8,-619.32 8,-619.32 8,-613.32 14,-607.32 20,-607.32"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="125.75" y="-847.82" font-family="Segoe UI" font-size="10.00" fill="#404040">Legende</text>
|
||||
</g>
|
||||
<!-- TRO01 -->
|
||||
<g id="node1" class="node">
|
||||
<title>TRO01</title>
|
||||
<path fill="#d4e8ff" stroke="#3388cc" d="M189.25,-590.57C189.25,-590.57 62.25,-590.57 62.25,-590.57 56.25,-590.57 50.25,-584.57 50.25,-578.57 50.25,-578.57 50.25,-518.07 50.25,-518.07 50.25,-512.07 56.25,-506.07 62.25,-506.07 62.25,-506.07 189.25,-506.07 189.25,-506.07 195.25,-506.07 201.25,-512.07 201.25,-518.07 201.25,-518.07 201.25,-578.57 201.25,-578.57 201.25,-584.57 195.25,-590.57 189.25,-590.57"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="125.75" y="-578.02" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO01  (1Sep)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="125.75" y="-565.27" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0061 auf Kreisel1 Bahn R</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="125.75" y="-552.52" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="125.75" y="-539.77" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="125.75" y="-527.02" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0061</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="125.75" y="-514.27" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 5355, -5878</text>
|
||||
</g>
|
||||
<!-- TRO02 -->
|
||||
<g id="node2" class="node">
|
||||
<title>TRO02</title>
|
||||
<path fill="#d4e8ff" stroke="#3388cc" d="M467.75,-683.94C467.75,-683.94 341.5,-683.94 341.5,-683.94 335.5,-683.94 329.5,-677.94 329.5,-671.94 329.5,-671.94 329.5,-598.69 329.5,-598.69 329.5,-592.69 335.5,-586.69 341.5,-586.69 341.5,-586.69 467.75,-586.69 467.75,-586.69 473.75,-586.69 479.75,-592.69 479.75,-598.69 479.75,-598.69 479.75,-671.94 479.75,-671.94 479.75,-677.94 473.75,-683.94 467.75,-683.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404.62" y="-671.39" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO02  (1Sep)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404.62" y="-658.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0003 auf Kreisel2 Bahn L</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404.62" y="-645.89" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404.62" y="-633.14" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404.62" y="-620.39" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0003</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404.62" y="-607.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0004</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="404.62" y="-594.89" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: -220, 13960</text>
|
||||
</g>
|
||||
<!-- TRO01->TRO02 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>TRO01->TRO02</title>
|
||||
<g id="a_edge1"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M201.68,-571.86C238.3,-583.37 282.49,-597.25 320.19,-609.1"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="318.91,-611.63 327.39,-611.36 320.59,-606.29 318.91,-611.63"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO03 -->
|
||||
<g id="node3" class="node">
|
||||
<title>TRO03</title>
|
||||
<path fill="#ffe4a0" stroke="#cc8800" d="M1492.75,-851.94C1492.75,-851.94 1366.5,-851.94 1366.5,-851.94 1360.5,-851.94 1354.5,-845.94 1354.5,-839.94 1354.5,-839.94 1354.5,-766.69 1354.5,-766.69 1354.5,-760.69 1360.5,-754.69 1366.5,-754.69 1366.5,-754.69 1492.75,-754.69 1492.75,-754.69 1498.75,-754.69 1504.75,-760.69 1504.75,-766.69 1504.75,-766.69 1504.75,-839.94 1504.75,-839.94 1504.75,-845.94 1498.75,-851.94 1492.75,-851.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-839.39" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO03  (1Sep1Swi)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-826.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0011 auf Kreisel2 Bahn L</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-813.89" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep1Swi</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-801.14" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x Switch</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-788.39" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0011</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-775.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0009</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-762.89" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: -220, -481</text>
|
||||
</g>
|
||||
<!-- TRO01->TRO03 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>TRO01->TRO03</title>
|
||||
<g id="a_edge2"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M201.51,-574.64C216.36,-581.9 231.16,-590.75 243.5,-601.32 296.41,-646.61 279.42,-683.91 329.5,-732.32 443.15,-842.18 475.18,-917.32 633.25,-917.32 633.25,-917.32 633.25,-917.32 865.25,-917.32 1042.55,-917.32 1088.25,-905.34 1260.5,-863.32 1288.63,-856.45 1318.63,-846.61 1345.37,-836.87"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1346.07,-839.6 1352.61,-834.2 1344.13,-834.34 1346.07,-839.6"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO04 -->
|
||||
<g id="node4" class="node">
|
||||
<title>TRO04</title>
|
||||
<path fill="#ffd4d4" stroke="#cc3333" d="M1492.75,-693.94C1492.75,-693.94 1366.5,-693.94 1366.5,-693.94 1360.5,-693.94 1354.5,-687.94 1354.5,-681.94 1354.5,-681.94 1354.5,-608.69 1354.5,-608.69 1354.5,-602.69 1360.5,-596.69 1366.5,-596.69 1366.5,-596.69 1492.75,-596.69 1492.75,-596.69 1498.75,-596.69 1504.75,-602.69 1504.75,-608.69 1504.75,-608.69 1504.75,-681.94 1504.75,-681.94 1504.75,-687.94 1498.75,-693.94 1492.75,-693.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-681.39" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO04  (1Sep_SSCC)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-668.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0012 auf Kreisel2 Bahn L</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-655.89" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep_SSCC</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-643.14" font-family="Segoe UI" font-size="9.00" fill="#111111">1x SSCC, 1x Scanner, 1x Separator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-630.39" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0012</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-617.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0007</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-604.89" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: -220, -3472</text>
|
||||
</g>
|
||||
<!-- TRO01->TRO04 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>TRO01->TRO04</title>
|
||||
<g id="a_edge3"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M148.76,-505.93C209.61,-395.31 391.66,-106.32 633.25,-106.32 633.25,-106.32 633.25,-106.32 865.25,-106.32 1097.26,-106.32 1098.99,-280.75 1260.5,-447.32 1306.69,-494.96 1311.35,-512.91 1354.5,-563.32 1361.72,-571.74 1369.45,-580.55 1377.11,-589.13"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1374.87,-590.82 1382.29,-594.91 1379.04,-587.09 1374.87,-590.82"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO07 -->
|
||||
<g id="node7" class="node">
|
||||
<title>TRO07</title>
|
||||
<path fill="#e8d4f0" stroke="#883388" d="M1478.12,-550.57C1478.12,-550.57 1381.12,-550.57 1381.12,-550.57 1375.12,-550.57 1369.12,-544.57 1369.12,-538.57 1369.12,-538.57 1369.12,-478.07 1369.12,-478.07 1369.12,-472.07 1375.12,-466.07 1381.12,-466.07 1381.12,-466.07 1478.12,-466.07 1478.12,-466.07 1484.12,-466.07 1490.12,-472.07 1490.12,-478.07 1490.12,-478.07 1490.12,-538.57 1490.12,-538.57 1490.12,-544.57 1484.12,-550.57 1478.12,-550.57"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-538.02" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO07  (Vario)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-525.27" font-family="Segoe UI" font-size="9.00" fill="#111111">VarioFoerderer :3</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-512.52" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_Vario</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-499.77" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x VarioDrive</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-487.02" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0015, 0062</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1429.62" y="-474.27" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 9186, 13549</text>
|
||||
</g>
|
||||
<!-- TRO01->TRO07 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>TRO01->TRO07</title>
|
||||
<g id="a_edge4"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M133.01,-505.8C148.68,-414.86 198.23,-200.51 329.5,-87.32 435.49,4.08 493.3,-4.32 633.25,-4.32 633.25,-4.32 633.25,-4.32 865.25,-4.32 1044.75,-4.32 1123.09,28.17 1260.5,-87.32 1374.18,-182.86 1411.62,-366.25 1423.44,-456.1"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1420.66,-456.42 1424.44,-464 1426.22,-455.72 1420.66,-456.42"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO08 -->
|
||||
<g id="node8" class="node">
|
||||
<title>TRO08</title>
|
||||
<path fill="#e8d4f0" stroke="#883388" d="M912.75,-626.94C912.75,-626.94 815.75,-626.94 815.75,-626.94 809.75,-626.94 803.75,-620.94 803.75,-614.94 803.75,-614.94 803.75,-541.69 803.75,-541.69 803.75,-535.69 809.75,-529.69 815.75,-529.69 815.75,-529.69 912.75,-529.69 912.75,-529.69 918.75,-529.69 924.75,-535.69 924.75,-541.69 924.75,-541.69 924.75,-614.94 924.75,-614.94 924.75,-620.94 918.75,-626.94 912.75,-626.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-614.39" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO08  (Vario)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-601.64" font-family="Segoe UI" font-size="9.00" fill="#111111">VarioFoerderer :2</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-588.89" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_Vario</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-576.14" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x VarioDrive</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-563.39" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0057, 0065</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-550.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0066</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-537.89" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 6952, -4271</text>
|
||||
</g>
|
||||
<!-- TRO01->TRO08 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>TRO01->TRO08</title>
|
||||
<g id="a_edge5"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M201.42,-551.36C344.45,-557.18 655.16,-569.84 793.91,-575.49"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="793.67,-578.28 801.78,-575.81 793.9,-572.69 793.67,-578.28"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO02->TRO03 -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>TRO02->TRO03</title>
|
||||
<g id="a_edge25"><a xlink:title="gleiche Bahn">
|
||||
<path fill="none" stroke="#7f7f7f" stroke-width="1.2" stroke-dasharray="1,5" d="M445.3,-684.23C476.3,-718.57 522.59,-762.01 573.75,-783.32 842.37,-895.17 1200.78,-847.47 1354.03,-818.97"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO02->TRO04 -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>TRO02->TRO04</title>
|
||||
<g id="a_edge26"><a xlink:title="gleiche Bahn">
|
||||
<path fill="none" stroke="#7f7f7f" stroke-width="1.2" stroke-dasharray="1,5" d="M432.64,-586.29C511.11,-450.02 745.81,-86.19 939.75,-233.32 1063.29,-327.04 919.66,-464.29 1033.75,-569.32 1120.94,-649.58 1266.12,-656.82 1354.05,-652.58"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09 -->
|
||||
<g id="node9" class="node">
|
||||
<title>TRO09</title>
|
||||
<path fill="#e8d4f0" stroke="#883388" d="M682.75,-770.94C682.75,-770.94 585.75,-770.94 585.75,-770.94 579.75,-770.94 573.75,-764.94 573.75,-758.94 573.75,-758.94 573.75,-685.69 573.75,-685.69 573.75,-679.69 579.75,-673.69 585.75,-673.69 585.75,-673.69 682.75,-673.69 682.75,-673.69 688.75,-673.69 694.75,-679.69 694.75,-685.69 694.75,-685.69 694.75,-758.94 694.75,-758.94 694.75,-764.94 688.75,-770.94 682.75,-770.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="634.25" y="-758.39" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO09  (Vario)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="634.25" y="-745.64" font-family="Segoe UI" font-size="9.00" fill="#111111">VarioFoerderer :1</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="634.25" y="-732.89" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_Vario</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="634.25" y="-720.14" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x VarioDrive</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="634.25" y="-707.39" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0058, 0059</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="634.25" y="-694.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0060</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="634.25" y="-681.89" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: -1146, 7128</text>
|
||||
</g>
|
||||
<!-- TRO02->TRO09 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>TRO02->TRO09</title>
|
||||
<g id="a_edge6"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M480.16,-654.94C507.3,-664.58 537.84,-676.31 564.46,-687.33"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="563.19,-689.84 571.65,-690.34 565.35,-684.67 563.19,-689.84"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO03->TRO04 -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>TRO03->TRO04</title>
|
||||
<g id="a_edge27"><a xlink:title="gleiche Bahn">
|
||||
<path fill="none" stroke="#7f7f7f" stroke-width="1.2" stroke-dasharray="1,5" d="M1429.62,-754.38C1429.62,-734.38 1429.62,-714.38 1429.62,-694.38"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO03->TRO09 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>TRO03->TRO09</title>
|
||||
<g id="a_edge7"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1354.03,-806.74C1234.44,-803.86 992.54,-786.79 788.75,-760.82 761.17,-757.3 730.97,-752.41 704.71,-747.01"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="705.41,-744.3 697,-745.38 704.24,-749.78 705.41,-744.3"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO04->TRO09 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>TRO04->TRO09</title>
|
||||
<g id="a_edge8"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1354.23,-677.04C1325.19,-684.99 1291.49,-692.31 1260.5,-696.82 1060.04,-725.95 820.29,-732.8 704.54,-729.56"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="704.97,-726.78 696.89,-729.32 704.8,-732.37 704.97,-726.78"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO05 -->
|
||||
<g id="node5" class="node">
|
||||
<title>TRO05</title>
|
||||
<path fill="#ffe4a0" stroke="#cc8800" d="M927.75,-452.94C927.75,-452.94 800.75,-452.94 800.75,-452.94 794.75,-452.94 788.75,-446.94 788.75,-440.94 788.75,-440.94 788.75,-367.69 788.75,-367.69 788.75,-361.69 794.75,-355.69 800.75,-355.69 800.75,-355.69 927.75,-355.69 927.75,-355.69 933.75,-355.69 939.75,-361.69 939.75,-367.69 939.75,-367.69 939.75,-440.94 939.75,-440.94 939.75,-446.94 933.75,-452.94 927.75,-452.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-440.39" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO05  (1Sep1Swi)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-427.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0063 auf Kreisel3 Bahn R</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-414.89" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep1Swi</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-402.14" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator, 1x Switch</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-389.39" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0063</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-376.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0008</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-363.89" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 10490, -525</text>
|
||||
</g>
|
||||
<!-- TRO06 -->
|
||||
<g id="node6" class="node">
|
||||
<title>TRO06</title>
|
||||
<path fill="#d4e8ff" stroke="#3388cc" d="M927.75,-330.57C927.75,-330.57 800.75,-330.57 800.75,-330.57 794.75,-330.57 788.75,-324.57 788.75,-318.57 788.75,-318.57 788.75,-258.07 788.75,-258.07 788.75,-252.07 794.75,-246.07 800.75,-246.07 800.75,-246.07 927.75,-246.07 927.75,-246.07 933.75,-246.07 939.75,-252.07 939.75,-258.07 939.75,-258.07 939.75,-318.57 939.75,-318.57 939.75,-324.57 933.75,-330.57 927.75,-330.57"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-318.02" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO06  (1Sep)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-305.27" font-family="Segoe UI" font-size="9.00" fill="#111111">Separator 0064 auf Kreisel3 Bahn R</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-292.52" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_1Sep</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-279.77" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Separator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-267.02" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0064</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="864.25" y="-254.27" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 10310, 160</text>
|
||||
</g>
|
||||
<!-- TRO05->TRO06 -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>TRO05->TRO06</title>
|
||||
<g id="a_edge28"><a xlink:title="gleiche Bahn">
|
||||
<path fill="none" stroke="#7f7f7f" stroke-width="1.2" stroke-dasharray="1,5" d="M864.25,-355.28C864.25,-347.16 864.25,-339.03 864.25,-330.91"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10 -->
|
||||
<g id="node10" class="node">
|
||||
<title>TRO10</title>
|
||||
<path fill="#d4f0d4" stroke="#338833" d="M1248.5,-556.94C1248.5,-556.94 1045.75,-556.94 1045.75,-556.94 1039.75,-556.94 1033.75,-550.94 1033.75,-544.94 1033.75,-544.94 1033.75,-471.69 1033.75,-471.69 1033.75,-465.69 1039.75,-459.69 1045.75,-459.69 1045.75,-459.69 1248.5,-459.69 1248.5,-459.69 1254.5,-459.69 1260.5,-465.69 1260.5,-471.69 1260.5,-471.69 1260.5,-544.94 1260.5,-544.94 1260.5,-550.94 1254.5,-556.94 1248.5,-556.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1147.12" y="-544.39" font-family="Segoe UI" font-size="9.00" fill="#111111">TRO10  (PinStore_Auto)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1147.12" y="-531.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Speicher (20 Schwerkraftlinien)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1147.12" y="-518.89" font-family="Segoe UI" font-size="9.00" fill="#111111">FB_ILS_MTRO_PinStore_Auto</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1147.12" y="-506.14" font-family="Segoe UI" font-size="9.00" fill="#111111">1x Encoder, 1x Scanner, 1x Separator, 19x StorageLine</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1147.12" y="-493.39" font-family="Segoe UI" font-size="9.00" fill="#111111">Sep: 0005 … 0056 (21)</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1147.12" y="-480.64" font-family="Segoe UI" font-size="9.00" fill="#111111">Scan: 0006</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1147.12" y="-467.89" font-family="Segoe UI" font-size="9.00" fill="#111111">x/y: 989, 3924</text>
|
||||
</g>
|
||||
<!-- TRO05->TRO10 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>TRO05->TRO10</title>
|
||||
<g id="a_edge9"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M940.15,-432.05C966.07,-441.65 995.83,-452.67 1024.52,-463.29"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1023.21,-465.79 1031.68,-465.94 1025.15,-460.54 1023.21,-465.79"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO06->TRO10 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>TRO06->TRO10</title>
|
||||
<g id="a_edge10"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M923.57,-331.04C929.06,-335.16 934.52,-339.3 939.75,-343.32 986.66,-379.36 1038.69,-420.97 1078.77,-453.38"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1076.71,-455.33 1084.69,-458.18 1080.24,-450.97 1076.71,-455.33"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO07->TRO10 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>TRO07->TRO10</title>
|
||||
<g id="a_edge11"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1368.89,-516.15C1340.07,-517.4 1304.4,-517.89 1270.2,-517.62"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1270.44,-514.82 1262.42,-517.54 1270.39,-520.42 1270.44,-514.82"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO08->TRO10 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>TRO08->TRO10</title>
|
||||
<g id="a_edge12"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M925.16,-555.54C954.07,-547.09 989.87,-537.69 1024.16,-529.41"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1024.42,-532.23 1031.55,-527.64 1023.12,-526.78 1024.42,-532.23"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO01 -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>TRO09->TRO01</title>
|
||||
<g id="a_edge13"><a xlink:title="Weiche (Kreisel-Uebergang)">
|
||||
<path fill="none" stroke="#cc8800" stroke-width="1.8" d="M573.3,-729.64C509.43,-734.7 407.03,-734.75 329.5,-696.32 278.47,-671.02 289.5,-634.9 243.5,-601.32 233.53,-594.04 222.4,-587.42 211.07,-581.53"/>
|
||||
<polygon fill="#cc8800" stroke="#cc8800" stroke-width="1.8" points="212.38,-579.05 203.98,-577.97 209.87,-584.06 212.38,-579.05"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="316" y="-688.71" font-family="Segoe UI" font-size="8.00" fill="#cc8800">Weiche</text>
|
||||
</g>
|
||||
<!-- TRO09->TRO02 -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>TRO09->TRO02</title>
|
||||
<g id="a_edge14"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M573.33,-707.78C547.57,-698.98 517.03,-687.54 489.12,-676.3"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="490.31,-673.76 481.84,-673.35 488.2,-678.95 490.31,-673.76"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO03 -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>TRO09->TRO03</title>
|
||||
<g id="a_edge15"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M695.22,-722.3C723.51,-726.19 757.78,-731.87 788.75,-735.82 987.17,-761.1 1221.71,-777.96 1344.32,-790.08"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1343.99,-792.86 1352.23,-790.88 1344.54,-787.29 1343.99,-792.86"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO04 -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>TRO09->TRO04</title>
|
||||
<g id="a_edge16"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M695.07,-714.73C806.78,-708.17 1054.41,-701.77 1260.5,-671.82 1288.22,-667.79 1318.11,-661.5 1344.89,-655.75"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1345.22,-658.54 1352.45,-654.13 1344.04,-653.07 1345.22,-658.54"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO07 -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>TRO09->TRO07</title>
|
||||
<g id="a_edge17"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M694.88,-709.98C806.77,-686.33 1055.41,-631.42 1260.5,-569.32 1293.49,-559.33 1329.49,-546.53 1359.67,-535.24"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1360.65,-537.86 1367.15,-532.43 1358.67,-532.62 1360.65,-537.86"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO09->TRO08 -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>TRO09->TRO08</title>
|
||||
<g id="a_edge18"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M695.15,-684.48C725.93,-665.05 763.55,-641.29 795.39,-621.18"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="796.55,-623.76 801.81,-617.12 793.56,-619.02 796.55,-623.76"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO01 -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>TRO10->TRO01</title>
|
||||
<g id="a_edge19"><a xlink:title="Weiche (Kreisel-Uebergang)">
|
||||
<path fill="none" stroke="#cc8800" stroke-width="1.8" d="M1126.3,-459.41C1096.73,-393.93 1034.26,-280.55 939.75,-233.32 879.72,-203.31 854.21,-218.53 788.75,-233.32 560.06,-284.95 317.73,-425.36 199.79,-500.07"/>
|
||||
<polygon fill="#cc8800" stroke="#cc8800" stroke-width="1.8" points="198.38,-497.65 193.13,-504.3 201.38,-502.37 198.38,-497.65"/>
|
||||
</a>
|
||||
</g>
|
||||
<text xml:space="preserve" text-anchor="middle" x="570.92" y="-291.4" font-family="Segoe UI" font-size="8.00" fill="#cc8800">Weiche</text>
|
||||
</g>
|
||||
<!-- TRO10->TRO02 -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>TRO10->TRO02</title>
|
||||
<g id="a_edge20"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M1033.52,-503.32C962.79,-502.11 869.91,-504.05 788.75,-517.32 682.98,-534.6 565.83,-573.79 489.26,-602.27"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="488.34,-599.63 481.83,-605.05 490.3,-604.87 488.34,-599.63"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO03 -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>TRO10->TRO03</title>
|
||||
<g id="a_edge21"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M1194.76,-557.36C1244.66,-609.84 1323.65,-692.91 1375.81,-747.77"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1373.55,-749.46 1381.1,-753.33 1377.61,-745.6 1373.55,-749.46"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO04 -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>TRO10->TRO04</title>
|
||||
<g id="a_edge22"><a xlink:title="Kreisel-Umlauf">
|
||||
<path fill="none" stroke="#8ea9db" stroke-width="1.2" stroke-dasharray="5,2" d="M1248.6,-557.39C1280.5,-572.97 1315.39,-590.01 1345.89,-604.91"/>
|
||||
<polygon fill="#8ea9db" stroke="#8ea9db" stroke-width="1.2" points="1344.32,-607.26 1352.74,-608.25 1346.78,-602.23 1344.32,-607.26"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO07 -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>TRO10->TRO07</title>
|
||||
<g id="a_edge23"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1260.6,-499.11C1294.02,-498.7 1329.63,-499.04 1359.43,-500.1"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="1358.97,-502.89 1367.07,-500.41 1359.19,-497.29 1358.97,-502.89"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- TRO10->TRO08 -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>TRO10->TRO08</title>
|
||||
<g id="a_edge24"><a xlink:title="Uebergabe (Ein-/Ausschleusung)">
|
||||
<path fill="none" stroke="#2f5597" stroke-width="1.2" d="M1033.31,-545.64C999.93,-554.36 964.38,-562.89 934.61,-569.24"/>
|
||||
<polygon fill="#2f5597" stroke="#2f5597" stroke-width="1.2" points="934.19,-566.47 926.94,-570.85 935.34,-571.95 934.19,-566.47"/>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- legende -->
|
||||
<g id="node11" class="node">
|
||||
<title>legende</title>
|
||||
<polygon fill="#d4e8ff" stroke="none" points="24,-806.32 24,-827.07 92.75,-827.07 92.75,-806.32 24,-806.32"/>
|
||||
<polygon fill="none" stroke="black" points="24,-806.32 24,-827.07 92.75,-827.07 92.75,-806.32 24,-806.32"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-813.32" font-family="Segoe UI" font-size="9.00">  sep  </text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-806.32 92.75,-827.07 227.5,-827.07 227.5,-806.32 92.75,-806.32"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-813.32" font-family="Segoe UI" font-size="9.00">Separator</text>
|
||||
<polygon fill="#ffe4a0" stroke="none" points="24,-785.57 24,-806.32 92.75,-806.32 92.75,-785.57 24,-785.57"/>
|
||||
<polygon fill="none" stroke="black" points="24,-785.57 24,-806.32 92.75,-806.32 92.75,-785.57 24,-785.57"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-792.57" font-family="Segoe UI" font-size="9.00">  swi  </text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-785.57 92.75,-806.32 227.5,-806.32 227.5,-785.57 92.75,-785.57"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-792.57" font-family="Segoe UI" font-size="9.00">Weiche</text>
|
||||
<polygon fill="#ffd4d4" stroke="none" points="24,-764.82 24,-785.57 92.75,-785.57 92.75,-764.82 24,-764.82"/>
|
||||
<polygon fill="none" stroke="black" points="24,-764.82 24,-785.57 92.75,-785.57 92.75,-764.82 24,-764.82"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-771.82" font-family="Segoe UI" font-size="9.00">  sscc  </text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-764.82 92.75,-785.57 227.5,-785.57 227.5,-764.82 92.75,-764.82"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-771.82" font-family="Segoe UI" font-size="9.00">Scanner (SSCC)</text>
|
||||
<polygon fill="#e8d4f0" stroke="none" points="24,-744.07 24,-764.82 92.75,-764.82 92.75,-744.07 24,-744.07"/>
|
||||
<polygon fill="none" stroke="black" points="24,-744.07 24,-764.82 92.75,-764.82 92.75,-744.07 24,-744.07"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-751.07" font-family="Segoe UI" font-size="9.00">  vario  </text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-744.07 92.75,-764.82 227.5,-764.82 227.5,-744.07 92.75,-744.07"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-751.07" font-family="Segoe UI" font-size="9.00">Kettenfoerderer</text>
|
||||
<polygon fill="#d4f0d4" stroke="none" points="24,-723.32 24,-744.07 92.75,-744.07 92.75,-723.32 24,-723.32"/>
|
||||
<polygon fill="none" stroke="black" points="24,-723.32 24,-744.07 92.75,-744.07 92.75,-723.32 24,-723.32"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-730.32" font-family="Segoe UI" font-size="9.00">  store  </text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-723.32 92.75,-744.07 227.5,-744.07 227.5,-723.32 92.75,-723.32"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-730.32" font-family="Segoe UI" font-size="9.00">Speicher / Puffer</text>
|
||||
<polygon fill="#f0f0f0" stroke="none" points="24,-702.57 24,-723.32 92.75,-723.32 92.75,-702.57 24,-702.57"/>
|
||||
<polygon fill="none" stroke="black" points="24,-702.57 24,-723.32 92.75,-723.32 92.75,-702.57 24,-702.57"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-709.57" font-family="Segoe UI" font-size="9.00">  ext  </text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-702.57 92.75,-723.32 227.5,-723.32 227.5,-702.57 92.75,-702.57"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-709.57" font-family="Segoe UI" font-size="9.00">Systemgrenze / extern</text>
|
||||
<polygon fill="none" stroke="black" points="24,-681.82 24,-702.57 92.75,-702.57 92.75,-681.82 24,-681.82"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-688.82" font-family="Segoe UI" font-size="9.00" fill="#2f5597">durchgezogen</text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-681.82 92.75,-702.57 227.5,-702.57 227.5,-681.82 92.75,-681.82"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-688.82" font-family="Segoe UI" font-size="9.00">Uebergabe / Ein-Ausschleusung</text>
|
||||
<polygon fill="none" stroke="black" points="24,-661.07 24,-681.82 92.75,-681.82 92.75,-661.07 24,-661.07"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-668.07" font-family="Segoe UI" font-size="9.00" fill="#8ea9db">blau gestrichelt</text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-661.07 92.75,-681.82 227.5,-681.82 227.5,-661.07 92.75,-661.07"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-668.07" font-family="Segoe UI" font-size="9.00">Kreisel-Umlauf</text>
|
||||
<polygon fill="none" stroke="black" points="24,-640.32 24,-661.07 92.75,-661.07 92.75,-640.32 24,-640.32"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-647.32" font-family="Segoe UI" font-size="9.00" fill="#cc8800">orange</text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-640.32 92.75,-661.07 227.5,-661.07 227.5,-640.32 92.75,-640.32"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-647.32" font-family="Segoe UI" font-size="9.00">Weiche (Kreisel-Uebergang)</text>
|
||||
<polygon fill="none" stroke="black" points="24,-619.57 24,-640.32 92.75,-640.32 92.75,-619.57 24,-619.57"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="28" y="-626.57" font-family="Segoe UI" font-size="9.00">grau gepunktet</text>
|
||||
<polygon fill="none" stroke="black" points="92.75,-619.57 92.75,-640.32 227.5,-640.32 227.5,-619.57 92.75,-619.57"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="96.75" y="-626.57" font-family="Segoe UI" font-size="9.00">gleiche Bahn / Strecke</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,225 @@
|
||||
<!-- erzeugt von lib/tro_flow.py -->
|
||||
# TRO-Liste und TRO-Fluss - export.csv
|
||||
|
||||
**Erzeugt:** 2026-08-10 10:53 von `lib/tro_flow.py`
|
||||
**Quelle:** `C:\develop\sps_skel\data\export.csv`
|
||||
**Typdefinition:** `lib/tro_catalog.py` (Stand 2026-07-20)
|
||||
|
||||
> Automatisch aus dem CSV-Export erzeugt. Die TRO-Typen sind aus dem mechanischen Layout **abgeleitet** - ohne E-Planung (I/O-Liste) und ohne `FB_Main`-Aufrufstellen gibt es noch keine verbindliche TRO-Nummerierung. Die IDs unten sind laufende Nummern dieses Laufs.
|
||||
|
||||
## 1. Kurzfassung
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Ermittelte TROs | 10 |
|
||||
| TRO-Verbindungen | 24 |
|
||||
| Nicht verbundene TROs | 0 |
|
||||
| Hinweise | 3 |
|
||||
| Manuelle Typkorrekturen | 3 |
|
||||
| Offene Punkte (noch kein TRO) | 2 |
|
||||
|
||||
| Typ | FB-Baustein | Anzahl hier | Bauteile je TRO | Farbgruppe |
|
||||
|---|---|---:|---|---|
|
||||
| `1Sep` | `FB_ILS_MTRO_1Sep` | 3 | 1x Separator | sep |
|
||||
| `1Sep1Swi` | `FB_ILS_MTRO_1Sep1Swi` | 2 | 1x Separator, 1x Switch | swi |
|
||||
| `1Sep_SSCC` | `FB_ILS_MTRO_1Sep_SSCC` | 1 | 1x SSCC, 1x Scanner, 1x Separator | sscc |
|
||||
| `PinStore_Auto` | `FB_ILS_MTRO_PinStore_Auto` | 1 | 1x Encoder, 1x Scanner, 1x Separator, 19x StorageLine | store |
|
||||
| `Vario` | `FB_ILS_MTRO_Vario` | 3 | 1x Separator, 1x VarioDrive | vario |
|
||||
|
||||
## 2. TRO-Flussdiagramm
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
classDef sep fill:#d4e8ff,stroke:#3388cc,color:#111111
|
||||
classDef swi fill:#ffe4a0,stroke:#cc8800,color:#111111
|
||||
classDef sscc fill:#ffd4d4,stroke:#cc3333,color:#111111
|
||||
classDef vario fill:#e8d4f0,stroke:#883388,color:#111111
|
||||
classDef store fill:#d4f0d4,stroke:#338833,color:#111111
|
||||
classDef ext fill:#f0f0f0,stroke:#888888,color:#404040
|
||||
TRO01["TRO01<br/>1Sep<br/>Separator 0061 auf Kreisel1 Bahn R"]:::sep
|
||||
TRO02["TRO02<br/>1Sep<br/>Separator 0003 auf Kreisel2 Bahn L"]:::sep
|
||||
TRO03["TRO03<br/>1Sep1Swi<br/>Separator 0011 auf Kreisel2 Bahn L"]:::swi
|
||||
TRO04["TRO04<br/>1Sep_SSCC<br/>Separator 0012 auf Kreisel2 Bahn L"]:::sscc
|
||||
TRO05["TRO05<br/>1Sep1Swi<br/>Separator 0063 auf Kreisel3 Bahn R"]:::swi
|
||||
TRO06["TRO06<br/>1Sep<br/>Separator 0064 auf Kreisel3 Bahn R"]:::sep
|
||||
TRO07["TRO07<br/>Vario<br/>VarioFoerderer :3"]:::vario
|
||||
TRO08["TRO08<br/>Vario<br/>VarioFoerderer :2"]:::vario
|
||||
TRO09["TRO09<br/>Vario<br/>VarioFoerderer :1"]:::vario
|
||||
TRO10["TRO10<br/>PinStore_Auto<br/>Speicher (20 Schwerkraftlinien)"]:::store
|
||||
TRO01 --> TRO02
|
||||
TRO01 --> TRO03
|
||||
TRO01 --> TRO04
|
||||
TRO01 --> TRO07
|
||||
TRO01 --> TRO08
|
||||
TRO02 --> TRO09
|
||||
TRO03 --> TRO09
|
||||
TRO04 --> TRO09
|
||||
TRO05 --> TRO10
|
||||
TRO06 --> TRO10
|
||||
TRO07 --> TRO10
|
||||
TRO08 --> TRO10
|
||||
TRO09 --> TRO01
|
||||
TRO09 --> TRO02
|
||||
TRO09 --> TRO03
|
||||
TRO09 --> TRO04
|
||||
TRO09 --> TRO07
|
||||
TRO09 --> TRO08
|
||||
TRO10 --> TRO01
|
||||
TRO10 --> TRO02
|
||||
TRO10 --> TRO03
|
||||
TRO10 --> TRO04
|
||||
TRO10 --> TRO07
|
||||
TRO10 --> TRO08
|
||||
TRO02 -. gleiche Bahn .- TRO03
|
||||
TRO02 -. gleiche Bahn .- TRO04
|
||||
TRO03 -. gleiche Bahn .- TRO04
|
||||
TRO05 -. gleiche Bahn .- TRO06
|
||||
```
|
||||
|
||||
Gerendert: [`export_tro_flow.dot`](export_tro_flow.dot) - [`export_tro_flow.svg`](export_tro_flow.svg)
|
||||
|
||||
## 3. TRO-Liste
|
||||
|
||||
| TRO | Typ | FB-Baustein | Bauteile laut Typ | X [mm] | Y [mm] | Z [mm] | Host-Knoten | Separatoren | Scanner | Begruendung | Vertrauen |
|
||||
|---|---|---|---|---:|---:|---:|---|---|---|---|---|
|
||||
| `TRO01` | `1Sep` | `FB_ILS_MTRO_1Sep` | 1x Separator | 5355 | -5878 | 1468 | `0001-R` | 0061 | - | einzelner Separator auf angetriebener Kreisel-Bahn | mittel |
|
||||
| `TRO02` | `1Sep` | `FB_ILS_MTRO_1Sep` | 1x Separator | -220 | 13960 | 1468 | `0002-L` | 0003 | 0004 | Separator mit Scanner auf angetriebener Kreisel-Bahn | mittel |
|
||||
| `TRO03` | `1Sep1Swi` | `FB_ILS_MTRO_1Sep1Swi` | 1x Separator, 1x Switch | -220 | -481 | 1468 | `0002-L` | 0011 | 0009 | Separator mit Scanner auf angetriebener Kreisel-Bahn; manuell auf 1Sep1Swi gesetzt (Weiche am Separator 0011 vor Ort bestaetigt (Review 2026-08-10) - an dieser Stelle wird die Fahrtrichtung umgestellt; im CSV-Export fehlt das Weichenelement) | bestaetigt |
|
||||
| `TRO04` | `1Sep_SSCC` | `FB_ILS_MTRO_1Sep_SSCC` | 1x SSCC, 1x Scanner, 1x Separator | -220 | -3472 | 1468 | `0002-L` | 0012 | 0007 | Separator mit Scanner auf angetriebener Kreisel-Bahn; manuell auf 1Sep_SSCC gesetzt (Separator 0012 mit Scanner 0007 - im Review als Scanner-Stelle bestaetigt (Review 2026-08-10)) | bestaetigt |
|
||||
| `TRO05` | `1Sep1Swi` | `FB_ILS_MTRO_1Sep1Swi` | 1x Separator, 1x Switch | 10490 | -525 | 1705 | `0010-R` | 0063 | 0008 | Separator mit Scanner auf angetriebener Kreisel-Bahn; manuell auf 1Sep1Swi gesetzt (Weiche am Separator 0063 vor Ort bestaetigt (Review 2026-08-10) - im CSV-Export fehlt das Weichenelement) | bestaetigt |
|
||||
| `TRO06` | `1Sep` | `FB_ILS_MTRO_1Sep` | 1x Separator | 10310 | 160 | 1942 | `0010-R` | 0064 | - | einzelner Separator auf angetriebener Kreisel-Bahn | mittel |
|
||||
| `TRO07` | `Vario` | `FB_ILS_MTRO_Vario` | 1x Separator, 1x VarioDrive | 9186 | 13549 | 1706 | `0013` | 0015, 0062 | - | angetriebenes Streckensegment (Antriebfahrtrichtung: Auf) | hoch |
|
||||
| `TRO08` | `Vario` | `FB_ILS_MTRO_Vario` | 1x Separator, 1x VarioDrive | 6952 | -4271 | 1784 | `0014` | 0057, 0065 | 0066 | angetriebenes Streckensegment (Antriebfahrtrichtung: Auf) | hoch |
|
||||
| `TRO09` | `Vario` | `FB_ILS_MTRO_Vario` | 1x Separator, 1x VarioDrive | -1146 | 7128 | 1530 | `0016` | 0058, 0059 | 0060 | angetriebenes Streckensegment (Antriebfahrtrichtung: Auf) | hoch |
|
||||
| `TRO10` | `PinStore_Auto` | `FB_ILS_MTRO_PinStore_Auto` | 1x Encoder, 1x Scanner, 1x Separator, 19x StorageLine | 989 | 3924 | 1553 | `0017` … `0036` (20 Knoten) | 0005 … 0056 (21) | 0006 | 20 Gefaellestrecken mit je eigenem Separator, gemeinsamer Zu-/Ablauf - Muster eines Linienspeichers | hoch |
|
||||
|
||||
**X/Y/Z** ist der Mittelpunkt der Bauteile, aus denen der TRO gebildet wurde (Separatoren und Scanner) - beim Linienspeicher also der Mittelwert aller Linien-Separatoren. Koordinaten in mm im Anlagen-Koordinatensystem des CSV-Exports.
|
||||
|
||||
| TRO | Koordinate aus | Anzahl Punkte |
|
||||
|---|---|---:|
|
||||
| `TRO01` | Bauteile | 1 |
|
||||
| `TRO02` | Bauteile | 2 |
|
||||
| `TRO03` | Bauteile | 2 |
|
||||
| `TRO04` | Bauteile | 2 |
|
||||
| `TRO05` | Bauteile | 2 |
|
||||
| `TRO06` | Bauteile | 1 |
|
||||
| `TRO07` | Bauteile | 2 |
|
||||
| `TRO08` | Bauteile | 3 |
|
||||
| `TRO09` | Bauteile | 3 |
|
||||
| `TRO10` | Bauteile | 22 |
|
||||
|
||||
## 4. TRO-Verbindungen
|
||||
|
||||
Richtung des Materialflusses zwischen den Uebergabestellen. Passive Zwischenknoten ohne eigenen TRO sind zusammengefasst.
|
||||
|
||||
| von | nach | Typ von -> Typ nach |
|
||||
|---|---|---|
|
||||
| `TRO01` | `TRO02` | `1Sep` -> `1Sep` |
|
||||
| `TRO01` | `TRO03` | `1Sep` -> `1Sep1Swi` |
|
||||
| `TRO01` | `TRO04` | `1Sep` -> `1Sep_SSCC` |
|
||||
| `TRO01` | `TRO07` | `1Sep` -> `Vario` |
|
||||
| `TRO01` | `TRO08` | `1Sep` -> `Vario` |
|
||||
| `TRO02` | `TRO09` | `1Sep` -> `Vario` |
|
||||
| `TRO03` | `TRO09` | `1Sep1Swi` -> `Vario` |
|
||||
| `TRO04` | `TRO09` | `1Sep_SSCC` -> `Vario` |
|
||||
| `TRO05` | `TRO10` | `1Sep1Swi` -> `PinStore_Auto` |
|
||||
| `TRO06` | `TRO10` | `1Sep` -> `PinStore_Auto` |
|
||||
| `TRO07` | `TRO10` | `Vario` -> `PinStore_Auto` |
|
||||
| `TRO08` | `TRO10` | `Vario` -> `PinStore_Auto` |
|
||||
| `TRO09` | `TRO01` | `Vario` -> `1Sep` |
|
||||
| `TRO09` | `TRO02` | `Vario` -> `1Sep` |
|
||||
| `TRO09` | `TRO03` | `Vario` -> `1Sep1Swi` |
|
||||
| `TRO09` | `TRO04` | `Vario` -> `1Sep_SSCC` |
|
||||
| `TRO09` | `TRO07` | `Vario` -> `Vario` |
|
||||
| `TRO09` | `TRO08` | `Vario` -> `Vario` |
|
||||
| `TRO10` | `TRO01` | `PinStore_Auto` -> `1Sep` |
|
||||
| `TRO10` | `TRO02` | `PinStore_Auto` -> `1Sep` |
|
||||
| `TRO10` | `TRO03` | `PinStore_Auto` -> `1Sep1Swi` |
|
||||
| `TRO10` | `TRO04` | `PinStore_Auto` -> `1Sep_SSCC` |
|
||||
| `TRO10` | `TRO07` | `PinStore_Auto` -> `Vario` |
|
||||
| `TRO10` | `TRO08` | `PinStore_Auto` -> `Vario` |
|
||||
|
||||
## 5. Hinweise
|
||||
|
||||
- Scanner 0006 'Scanner :6': montiert an 0014, liest aber an Separator 0005 auf 0036
|
||||
- Scanner 0066 'Scanner :1': montiert an 0036, liest aber an Separator 0065 auf 0014
|
||||
- TRO02 (Separator 0003 auf Kreisel2 Bahn L): Scanner 0004 am Separator - als 1Sep eingestuft. Pruefen, ob 1Sep_SSCC (SSCC-Scanner, Endmessung, WCS-Telegramm) erforderlich ist; das ist aus dem mechanischen Layout nicht erkennbar.
|
||||
|
||||
## 6. Manuelle Korrekturen und offene Punkte
|
||||
|
||||
Quelle: `C:\develop\sps_skel\cfg\tro_overrides.ini`
|
||||
|
||||
### 6.1 Angewandte Typkorrekturen
|
||||
|
||||
Diese Typen stammen **nicht** aus dem Layout, sondern aus der Begehung bzw. dem Review - im Layout sind sie nicht erkennbar.
|
||||
|
||||
| Korrektur | Begruendung |
|
||||
|---|---|
|
||||
| `TRO03: 1Sep -> 1Sep1Swi` | Weiche am Separator 0011 vor Ort bestaetigt (Review 2026-08-10) - an dieser Stelle wird die Fahrtrichtung umgestellt; im CSV-Export fehlt das Weichenelement |
|
||||
| `TRO04: 1Sep -> 1Sep_SSCC` | Separator 0012 mit Scanner 0007 - im Review als Scanner-Stelle bestaetigt (Review 2026-08-10) |
|
||||
| `TRO05: 1Sep -> 1Sep1Swi` | Weiche am Separator 0063 vor Ort bestaetigt (Review 2026-08-10) - im CSV-Export fehlt das Weichenelement |
|
||||
|
||||
### 6.2 Offene Punkte - noch kein TRO
|
||||
|
||||
Im Review gemeldete Stellen. Die TRO-Struktur ist hier **bewusst unveraendert**; die Punkte sind nur markiert (auch in der annotierten Zeichnung, Layer `TRO_OPENPOINT`), damit sie in BricsCAD geprueft werden koennen.
|
||||
|
||||
| Punkt | X [mm] | Y [mm] | Z [mm] | erwartet | heute Teil von | Anmerkung |
|
||||
|---|---:|---:|---:|---|---|---|
|
||||
| Foerderer_unten_links | 530 | -3895 | 1468 | `1Sep1Swi` | `TRO10` | Im Review als eigene Uebergabestelle (1 Separator + 1 Weiche) gemeldet, Position aus der Zeichnung (DXF -50375.7283 / -12309.7617, ueber cfg/dxf_registration.json auf Anlagenkoordinaten umgerechnet). Naechstes Bauteil ist Separator 0005 'Separator :32' bei 400 / -3755 auf Gefaellestrecke 0036, das derzeit zum Linienspeicher TRO10 gehoert. Vor der Umsetzung in BricsCAD pruefen. |
|
||||
| Qualitaetskontrolle | -1026 | 5250 | 1478 | `1Sep1Swi` | `TRO09` | Im Review als eigene Uebergabestelle (1 Separator + 1 Weiche) gemeldet. Separator 0059 und Scanner 0060 gehoeren derzeit zum Vario-TRO09 auf Strecke 0016. Vor der Umsetzung in BricsCAD pruefen. |
|
||||
|
||||
## 7. Ableitungsregeln und Typdefinition
|
||||
|
||||
Ein TRO ist die Steuerungslogik **einer Uebergabestelle**. Ausgangspunkt ist der Separator und das, was an ihm haengt (Host-Objekt, Scanner).
|
||||
|
||||
| Host des Separators | TRO-Typ |
|
||||
|---|---|
|
||||
| Gefaellestrecke, >= 2 Linien mit gemeinsamem Zu-/Ablauf | `PinStore_Auto` (ein Block je Liniengruppe) |
|
||||
| Gefaellestrecke, einzelne Linie | `1Sep` |
|
||||
| Strecke (angetrieben) | `Vario` (je Streckensegment) |
|
||||
| Kreisel-Bahn | `1Sep` |
|
||||
| zusaetzlich: 2 bzw. 3 abgehende Wege | Aufwertung zu `1Sep1Swi` / `1Sep2Swi` |
|
||||
|
||||
Ein **Scanner** am Separator aendert den Typ nicht. In der Referenzanlage sind Separatoren mit Scanner ueberwiegend `1Sep`. `1Sep_SSCC` ist dem Sonderfall mit SSCC-Scanner, Endmessung und WCS-Telegramm vorbehalten und aus einem mechanischen Layout nicht erkennbar - betroffene Stellen stehen als Hinweis in Abschnitt 5.
|
||||
|
||||
Was aus dem CSV **nicht** ableitbar ist: TRO-Nummerierung, Sensor- und Aktor-Tags, JamAreas, Zielsteuerung und Timing. Das kommt aus der E-Planung (I/O-Liste) bzw. aus `FB_Main`.
|
||||
|
||||
Typen, FB-Bausteine, Bauteile und Farben stammen vollstaendig aus `TRO_CATALOG` in `lib/tro_catalog.py` (Stand 2026-07-20):
|
||||
|
||||
| # | Typ | FB-Baustein | Bauteile je TRO | Farbgruppe |
|
||||
|---:|---|---|---|---|
|
||||
| 1 | `1Sep` | `FB_ILS_MTRO_1Sep` | 1x Separator | sep |
|
||||
| 2 | `1Sep1Swi` | `FB_ILS_MTRO_1Sep1Swi` | 1x Separator, 1x Switch | swi |
|
||||
| 3 | `1Sep2Swi` | `FB_ILS_MTRO_1Sep2Swi` | 1x Scanner, 1x Separator, 2x Switch | swi |
|
||||
| 4 | `1Sep_SSCC` | `FB_ILS_MTRO_1Sep_SSCC` | 1x SSCC, 1x Scanner, 1x Separator | sscc |
|
||||
| 5 | `Vario` | `FB_ILS_MTRO_Vario` | 1x Separator, 1x VarioDrive | vario |
|
||||
| 6 | `PinStore_Auto` | `FB_ILS_MTRO_PinStore_Auto` | 1x Encoder, 1x Scanner, 1x Separator, 19x StorageLine | store |
|
||||
| 7 | `Vario_workStation` | `FB_ILS_MTRO_Vario_workStation` | 1x Accumulate, 1x Scanner, 1x Separator, 1x VarioDrive, 1x WorkStation | vario |
|
||||
| 8 | `EmptyCarrBuffer` | `FB_EmptyCarrBuffer` | 5x Accumulate, 5x StorageLine | store |
|
||||
| 9 | `LoadingBoom` | `FB_LoadingBoom_INBOUND` | 1x Boom, 1x Foot, 1x TiltSensor | ext |
|
||||
| 10 | `2Sep1Swi` | `FB_ILS_MTRO_2Sep1Swi` | 2x Scanner, 2x Separator, 1x Switch | swi |
|
||||
|
||||
| Bauteil | Sub-FB |
|
||||
|---|---|
|
||||
| Accumulate | `FB_CarrAccumulate1Sep` |
|
||||
| Boom | `FB_BoomWorkStation` |
|
||||
| Encoder | _kein eigener FB_ |
|
||||
| Foot | `FB_DistanceFoot` |
|
||||
| SSCC | _kein eigener FB_ |
|
||||
| Scanner | `FB_BarcodeReaderCognex` |
|
||||
| Separator | `FB_ILS_STRO_Sep` |
|
||||
| StorageLine | `FB_ILS_STRO_Sep` |
|
||||
| Switch | `FB_ILS_STRO_Switch` |
|
||||
| TiltSensor | `FB_Tilt_TEST` |
|
||||
| VarioDrive | `FB_ILS_STRO_Vario` |
|
||||
| WorkStation | `FB_ILS_STRO_Vario_WorkStation` |
|
||||
|
||||
| Farbgruppe | Bedeutung | Fuellfarbe |
|
||||
|---|---|---|
|
||||
| sep | Separator | `#d4e8ff` |
|
||||
| swi | Weiche | `#ffe4a0` |
|
||||
| sscc | Scanner (SSCC) | `#ffd4d4` |
|
||||
| vario | Kettenfoerderer | `#e8d4f0` |
|
||||
| store | Speicher / Puffer | `#d4f0d4` |
|
||||
| ext | Systemgrenze / extern | `#f0f0f0` |
|
||||
|
||||
+230
-9
@@ -66,11 +66,14 @@ Each CLI tool is invoked through its `bin/<name>.bat` (Windows) / `bin/<name>.sh
|
||||
3. runs the module with `py` (falling back to `python`).
|
||||
|
||||
```bat
|
||||
bin\material_flow.bat --file mubea.csv --tosvg
|
||||
bin\tro_flow.bat --file mubea.csv --tosvg --doc
|
||||
bin\material_flow.bat --file mubea.csv --tosvg --use-cords --doc
|
||||
bin\tro_flow.bat --file mubea.csv --tosvg --use-cords --doc
|
||||
bin\tro_annotate.bat --file mubea.csv --dxf 500573_60_1.dxf --flow --fb --legend
|
||||
```
|
||||
|
||||
(`--use-cords` lays both graphs out at the real plant coordinates; drop it for
|
||||
Graphviz's computed left-to-right arrangement.)
|
||||
|
||||
Conventions shared by all three tools:
|
||||
|
||||
- `--file` / `--dxf` accept either a bare filename — resolved against
|
||||
@@ -97,6 +100,27 @@ Reads the CSV export and builds a directed graph of the mechanical objects:
|
||||
counter-clockwise = left→right).
|
||||
- **Separator** / **Scanner** → no node of their own; shown via `Zuordnung`
|
||||
(assignment) on the label of their owning node.
|
||||
- **Einschleuselement** / **Ausschleuselement** / **Weiche** (from the richer export)
|
||||
→ no node of their own; they supply the **direction** of the Kreisel↔Strecke edges
|
||||
(`Ausschleusung` = Kreisel→Strecke at the strecke's *Anfang*, `Einschleusung` =
|
||||
Strecke→Kreisel at its *Ende*, read from their `Kreisel`/`Strecke`/`Streckenende`
|
||||
`Merkmale`) and **mark the Weiche** on a Kreisel↔Kreisel link. A strecke whose two
|
||||
ends touch the *same* Kreisel (return loop) is split across that Kreisel's two lanes.
|
||||
This makes Kreisel↔Strecke direction deterministic instead of height-inferred.
|
||||
- **BTMT Be-/Entladestation** (entry/exit points) → one node each, recognised by
|
||||
`TeileArt`/`Bezeichnung` containing `Beladung`/`BTMT-Beladung` (→ **entry**, a
|
||||
material *source*) or `Entladung`/`SC_Entladung`/`Abwurf` (→ **exit**, a *sink*).
|
||||
An entry gets an outgoing edge, an exit an incoming edge, to the object named in
|
||||
its `Nachbarn`; if the export lists no neighbour (dxfmakros does not export BTMT
|
||||
yet — see below), the nearest object by 2-D distance is used and a note is
|
||||
printed. Recognition is **sps_skel-side only** — nothing in dxfmakros changes;
|
||||
it simply activates when such a row appears in the CSV.
|
||||
|
||||
> **Note on BTMT / entry-exit data.** dxfmakros' `EXPORTCSV` currently does **not**
|
||||
> emit the BTMT stations (their block names match no export pattern; documented as
|
||||
> *"Export noch offen"*). Until that is addressed, a freshly exported `mubea.csv`
|
||||
> will contain the 61 conveyor items but **no** BTMT rows, so no entry/exit nodes
|
||||
> appear. The recognition above is ready for when BTMT rows are present.
|
||||
|
||||
Flow direction between conveyor segments is derived from height change
|
||||
(`Hoehe_Von_mm`/`Hoehe_Bis_mm`) or, failing that, from `Antriebfahrtrichtung`
|
||||
@@ -109,11 +133,13 @@ attached.
|
||||
|---|---|---|---|
|
||||
| `--file` | `NAME` | `export.csv` | CSV input file, resolved against `%SKEL_DATA%`, or a full path. |
|
||||
| `--tosvg` | — | off | Also render the `.dot` file to `.svg` via Graphviz `dot`. |
|
||||
| `--use-cords` (alias `--use-coords`) | — | off | Place every node at its plant coordinate and render with `neato -n` (fixed positions) instead of `dot`, so the material graph matches the plant layout — the same option `tro_flow.py` has. The two Kreisel lanes (`-L`/`-R`) are nudged apart by `LANE_NUDGE_MM`; scale is `COORD_SCALE` (0.25 pt/mm, identical to `tro_flow.py`). Only has an effect together with `--tosvg`; fails (exit 1) if any flow node has no coordinate. |
|
||||
| `--doc` | — | off | Also write a Markdown report (`<name>_material_flow.md`) with object list, connections and plausibility findings. |
|
||||
| `--connect` | — | off | Also write the topology as `<name>_connect.ini` (item/flow level): `[…nodes]` (Kreisel lanes, Strecke, Gefällestrecke), `[…connections]` with a `kind` per edge (`normal`/`umlauf`/`weiche`/`einschleusung`/`ausschleusung`), and `[…externals]` — the BTMT entry/exit if present, otherwise the open lane-ends listed as entry candidates. A hand-editable bridge into the TRO step, styled after `doc/TRO_Katalog/connect.ini`. |
|
||||
|
||||
**Output** (in `%SKEL_RESULTS%`): `<name>_material_flow.dot` (always),
|
||||
`<name>_material_flow.svg` (with `--tosvg`), `<name>_material_flow.md`
|
||||
(with `--doc`).
|
||||
**Output** (in `%SKEL_RESULTS%`): `<name>_material_flow.dot` (always, with `pos`
|
||||
attributes when `--use-cords` was used), `<name>_material_flow.svg` (with `--tosvg`),
|
||||
`<name>_material_flow.md` (with `--doc`), `<name>_connect.ini` (with `--connect`).
|
||||
|
||||
**Exit codes:** `0` ok · `1` input/CLI error · `2` SVG rendering failed
|
||||
(Graphviz).
|
||||
@@ -210,19 +236,195 @@ overridden.
|
||||
could not be proven (or exceeds `--max-residual`) — resolve with `--offset` or
|
||||
by raising `--max-residual`.
|
||||
|
||||
## 5a. `tro_extract.py` — read the TROs back out of the drawing into JSON
|
||||
|
||||
The counter-direction to `tro_annotate.py`:
|
||||
|
||||
```
|
||||
tro_annotate.py CSV + derivation -> markers in the drawing
|
||||
tro_extract.py drawing -> JSON
|
||||
```
|
||||
|
||||
It reads **only the drawing**, never the CSV. So what comes back is what is
|
||||
actually in the DXF — including anything adjusted by hand in BricsCAD (markers
|
||||
moved, type changed via `TRO_EDIT`). That is the point: after a review, the
|
||||
drawing is the current state, not the export.
|
||||
|
||||
It finds the objects `tro_annotate.py` tagged with XDATA (AppID
|
||||
`SPS_SKEL_TRO`): the `TRO_SYM_<type>` block references (attributes
|
||||
`ID`/`TYPE`/`ITEMS`/`CONFIDENCE`/`SEPARATORS`, plus `FB_BLOCK` when annotated
|
||||
with `--fb`), the flow arrows (`"<from>-><to>"`), and the open-point markers
|
||||
(`"OFFEN:<name>"`). Each TRO also gets `predecessors`/`successors` computed
|
||||
from the arrows.
|
||||
|
||||
Coordinates appear twice: `positionDxf` is the drawing coordinate,
|
||||
`position` the plant coordinate. The conversion uses the registration written
|
||||
by `tro_annotate.py` (`<stem>_registration.json`; the `_annotated` suffix and
|
||||
the file's own `dxf_file` field are both taken into account when locating it).
|
||||
If no registration is found, `position` is **left out rather than guessed**,
|
||||
and a warning says so.
|
||||
|
||||
Switches: `--dxf NAME` (default `export_annotated.dxf`, looked up in
|
||||
`%SKEL_RESULTS%`), `--out NAME` (default `<drawing>_tro.json`). Exit codes:
|
||||
`0` ok, `1` input error, `2` no TRO markers in the drawing.
|
||||
|
||||
`fbType` is worth one note: unless the drawing was annotated with `--fb`, the
|
||||
FB block is not an attribute in the DXF. It is then looked up from
|
||||
`tro_catalog.py` and marked `"fbTypeFrom": "tro_catalog"` — so a consumer can
|
||||
tell a value that came out of the drawing from one that was resolved.
|
||||
|
||||
## 5b. `scl_skeleton.py` — generate the FB_Main skeleton as SCL
|
||||
|
||||
Last step of the chain:
|
||||
|
||||
```
|
||||
material_flow.py objects -> material flow
|
||||
tro_flow.py flow -> TROs
|
||||
tro_annotate.py TROs -> markers in the drawing
|
||||
tro_extract.py drawing -> JSON
|
||||
scl_skeleton.py JSON -> FB_Main.scl
|
||||
```
|
||||
|
||||
Produces a **skeleton, not a running program**: one `REGION` per TRO with the
|
||||
instance call and every parameter line in the right order, following the real
|
||||
call sites in `doc/TRO_Katalog/scl_templates/*.scl`.
|
||||
|
||||
**It will not compile as delivered, and that is deliberate.** Every value that
|
||||
has to come from the electrical planning is a visible gap marked
|
||||
`TODO(E-Planung)` — never an invented value, because a plausible-looking wrong
|
||||
sensor address is far worse than an empty one. Grep for that marker and nothing
|
||||
is missed.
|
||||
|
||||
| filled from the layout | left as `TODO(E-Planung)` |
|
||||
|---|---|
|
||||
| REGION order (material flow), instance list, FB type per TRO | sensor/actuator addresses (`cInBG`, `MB`, `MA`) |
|
||||
| number of separator / switch / scanner parameter blocks | separator and switch numbers, `cMainTro` |
|
||||
| `nTo1Destinations` when the TRO has exactly one switch | jam areas (`DB_JamArea…`) |
|
||||
| destination list per switch exit (graph reachability) | times marked "pruefen" |
|
||||
| cross-reference to the layout parts (separator numbers, coordinate) | |
|
||||
|
||||
Two derivations worth knowing about. **The destination list per switch exit** is
|
||||
computed by walking the TRO graph from each exit without going back through the
|
||||
switch — that is exactly what `FC_Direction` needs to map destination to
|
||||
direction, and it does *not* require the I/O list. And **`nTo1Destinations`** is
|
||||
only auto-filled for a single-switch TRO; where several switches share the
|
||||
exits, how they divide them is a planning decision, so it stays a gap rather
|
||||
than a guess.
|
||||
|
||||
Switches: `--json NAME` (default `export_tro.json`), `--out NAME` (default
|
||||
`<source>_FB_Main.scl`), `--start TRO`. The last one matters while the plant has
|
||||
no loading/unloading station: the flow is then a closed loop with no entry, so
|
||||
the order has to be broken somewhere arbitrary. The chosen start and the reason
|
||||
are recorded in the file header.
|
||||
|
||||
## 6. `tro_catalog.py` — TRO type catalog (library, no CLI)
|
||||
|
||||
The single source of truth for everything needed to generate or draw a TRO
|
||||
type: short name (as used in `FB_Main`/`connect.ini`), Siemens FB block,
|
||||
sub-components and their counts, color group (for Graphviz/Mermaid/CAD) and
|
||||
CAD marker shape. Ten types are defined in `TRO_CATALOG`, verified against
|
||||
`data/*.scl` where the source is vendored locally and against `TRO_Typen.md`'s
|
||||
mapping table otherwise (see the module docstring, `CATALOG_AS_OF`, for
|
||||
provenance per type). Everything is a Pydantic v2 model
|
||||
CAD marker shape. **Eleven** types are defined in `TRO_CATALOG`. Ten of them are
|
||||
verified against `data/*.scl` where the source is vendored locally, and against
|
||||
`TRO_Typen.md`'s mapping table otherwise (see the module docstring,
|
||||
`CATALOG_AS_OF`, for provenance per type).
|
||||
|
||||
> **`2Sep2Swi` is the exception — it is not backed by any SCL.** It was added on
|
||||
> 2026-08-12 for project 500573 (Mubea), to model the transfer point at the
|
||||
> Kreisel2/Kreisel1 touch as a single control object with 2 separators,
|
||||
> 2 scanners and 2 switches. **`FB_ILS_MTRO_2Sep2Swi` does not exist** in this
|
||||
> repository or in `doc/TRO_Katalog/scl_templates/`, and has to be created in
|
||||
> the ILSLib — otherwise a future SCL generator will emit a call to a missing
|
||||
> block. The closest verified type is `2Sep1Swi` (2 separators, 2 scanners,
|
||||
> **1** switch), which matches the hardware actually present in that export.
|
||||
|
||||
Everything is a Pydantic v2 model
|
||||
(`TroDefinition`/`TroStyle`), so it validates on every assignment and comes
|
||||
with `model_dump()`/`model_validate()` for the planned JSON layout model for
|
||||
free. Consumed by `tro_flow.py` and `tro_annotate.py`; not run directly.
|
||||
|
||||
## 6a. `tro_overrides.py` — manual corrections to the derived TROs (library, no CLI)
|
||||
|
||||
`tro_flow.py` derives TRO types from the mechanical layout alone. Some things
|
||||
are simply not in the CSV export: a switch that the export does not carry, a
|
||||
scanner that lifts the type to `1Sep_SSCC`, or a spot that a walkthrough
|
||||
identified as its own transfer point. Those findings come from a site review,
|
||||
and they must survive the next run — the `.dot`/`.svg`/`.md`/`.ini` outputs are
|
||||
all regenerated from scratch every time, so editing them is not an option.
|
||||
|
||||
They therefore live in **`%SKEL_CFG%\tro_overrides.ini`** (hand-maintained,
|
||||
never generated). Section names are prefixed with the CSV file they apply to,
|
||||
so several plants — and several exports of the same plant — can coexist:
|
||||
|
||||
```ini
|
||||
[export.csv.tro.SEP0011] ; type correction, keyed on separator 0011
|
||||
type = 1Sep1Swi ; a type from lib/tro_catalog.py
|
||||
reason = Weiche vor Ort bestaetigt (Review 2026-08-10)
|
||||
confidence = bestaetigt ; default when omitted
|
||||
|
||||
[mubea.csv.openpoint.Qualitaetskontrolle] ; explicitly NOT a TRO yet
|
||||
x = -1026.00 ; plant coordinates in mm (CSV system)
|
||||
y = 5250.05
|
||||
z = 1478.50
|
||||
expect = 1Sep1Swi ; type expected here
|
||||
belongs_to = TRO09 ; TRO that owns the part today
|
||||
note = ...
|
||||
```
|
||||
|
||||
A fourth kind folds several derived TROs into one control object:
|
||||
|
||||
```ini
|
||||
[export.csv.merge.Beruehrpunkt_K2_K1_gesamt]
|
||||
type = 2Sep2Swi
|
||||
separators = 0005, 0057 ; at least two, addressed by separator
|
||||
host = 0002-R ; primary flow node; the others are kept
|
||||
label = ...
|
||||
reason = ...
|
||||
```
|
||||
|
||||
A third kind creates a TRO the derivation missed entirely:
|
||||
|
||||
```ini
|
||||
[export.csv.split.Beruehrpunkt_K2_K1] ; pull a separator out of its TRO
|
||||
type = 1Sep1Swi
|
||||
separators = 0057 ; comma-separated
|
||||
scanners = ; optional, follow the separators
|
||||
host = 0001-L ; flow node the new TRO sits on
|
||||
label = ...
|
||||
reason = ...
|
||||
```
|
||||
|
||||
Three kinds of entry, deliberately different in weight:
|
||||
|
||||
- **`tro`** — changes the type of an already-derived TRO. Applied after the
|
||||
TRO numbers are assigned (the sections address them by ID) and before the FB
|
||||
block and component list are pulled from the catalog, so the type change
|
||||
drags both along. A manually set type also suppresses the automatic
|
||||
"check whether `1Sep_SSCC` is needed" hint for that TRO.
|
||||
- **`split`** — creates a new TRO from separators taken out of an existing one.
|
||||
For transfer points the derivation misses because the separator's
|
||||
`Zuordnung` points at a conveyor (Strecke/Gefaellestrecke) instead of the
|
||||
Kreisel lane it actually switches on. Applied *before* the numbers are
|
||||
assigned, so the new TROs slot into the normal ordering — which means
|
||||
**adding a split renumbers everything after it**. That is exactly why type
|
||||
corrections should be keyed `SEP<number>`, not `TRO<number>`.
|
||||
- **`merge`** — folds several TROs into one. Runs *after* the splits, so a
|
||||
freshly split-out TRO can be part of a merge. The first affected TRO survives
|
||||
and absorbs the others' separators, scanners and hosts; `host` picks which
|
||||
flow node is primary, the rest stay attached so the linking still sees both
|
||||
sides of a transition. Like splits, this renumbers.
|
||||
- **`openpoint`** — a spot reported in a review that is **not** turned into a
|
||||
TRO. The structure stays untouched; the point is only marked, in the doc
|
||||
(section 6) and in the annotated drawing on layer `TRO_OPENPOINT` as a red
|
||||
crossed circle with plain-text label. This keeps "derived" and "asserted"
|
||||
distinguishable until the spot has been checked in BricsCAD.
|
||||
|
||||
Consumers: `tro_flow.py` (type corrections + doc section 6), `tro_annotate.py`
|
||||
(corrected marker types + open-point markers), `material_flow.py` (writes the
|
||||
`[<plant>.manual]` section into `connect.ini`). Unknown TRO IDs and types are
|
||||
not applied silently — they are reported as warnings in the console output and
|
||||
in doc section 6.3, which catches the common trap: **TRO IDs are running
|
||||
numbers of one run and are only valid for the CSV named in the section.** Swap
|
||||
the data basis and the numbers shift.
|
||||
|
||||
## 7. `dxf_registration.py` — CSV↔DXF coordinate registration (library, no CLI)
|
||||
|
||||
Derives the rigid transform (rotation + offset, no scaling) between the CSV
|
||||
@@ -235,6 +437,25 @@ Persists/loads the verified transform per CSV/DXF filename pair under
|
||||
`%SKEL_CFG%\dxf_registration.json`. Used exclusively by `tro_annotate.py`; not
|
||||
run directly.
|
||||
|
||||
`ANCHOR_BLOCKS` holds **name patterns** (fnmatch, case-insensitive), not fixed
|
||||
names, because two naming worlds occur in this project:
|
||||
|
||||
| Drawing | Separator blocks | Scanner blocks |
|
||||
|---|---|---|
|
||||
| original customer drawing (`500573_60_1.dxf`) | `S-SP`, `S-LP` | `SCAN` |
|
||||
| macro-generated (`Mubea.dxf`, from dxfmakros) | `Separator_SP_2D`/`_3D` | `Scanner_2D`/`_3D` |
|
||||
|
||||
`Staustrecke_Separator_SP_*` is deliberately **not** an anchor: it is a
|
||||
conveyor module with a built-in separator, so its insertion point is the module
|
||||
origin rather than the separator, which would feed a second cluster — offset by
|
||||
exactly that distance — into the vote.
|
||||
|
||||
Note that the two roles can carry slightly different systematic offsets (in
|
||||
`Mubea.dxf`: separators land on +100/0, scanners on +400/0), so a mixed fit
|
||||
shows a larger `residual_max` than either role alone. That is expected; the
|
||||
mean residual is the number to watch, and only pairs within `FIT_TOL` (50 mm)
|
||||
enter the Procrustes fit.
|
||||
|
||||
## 8. `gen_tro_graphs.py` — documentation image generator (doc tooling, not part of the generator)
|
||||
|
||||
Lives under `doc/TRO_Katalog/tro_graphs/`, not `lib/` — it produces the
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
# gereral TODOS
|
||||
|
||||
## 1. target: Workflow chain
|
||||
bricscad layout
|
||||
-> extract TROs to .svg/.dxf (sps_skel)
|
||||
-> modify symbols in Brciscad (dxfmakros)
|
||||
-> extract the new modified symbols from the .dxf into a .json (sps_skel)
|
||||
-> create a .scl file from the .json (sps_skel)
|
||||
|
||||
## 2. use Mubea as basis test
|
||||
- Create the material Flow (ask Simon about the entry point / exit makros ): done
|
||||
- create a tro of the Mubea Layout in the given state :done
|
||||
- discuss the tro result with Embiya and Thomas (results as .svg or in .dxf layer):done
|
||||
- correct your program if necessary. Recreate Mubea until they think it is fine : done
|
||||
- create scl files and try to import in TIA Portal : done
|
||||
|
||||
## 3. create another test case H & M
|
||||
- extract the basic items and elements from the H&M Part 5 layout
|
||||
- create a new test case with our makros
|
||||
- use for testing the workflow chain and compare result with existing TRO code/concept
|
||||
+12
-4
@@ -69,11 +69,19 @@ __all__ = [
|
||||
"registration_path",
|
||||
]
|
||||
|
||||
# Rollen fuer den Lagebezug: CSV-Objektart -> Blocknamen im DXF.
|
||||
# Erweiterbar, wenn eine Zeichnung andere Bloecke verwendet.
|
||||
# Rollen fuer den Lagebezug: CSV-Objektart -> Blocknamen im DXF, als Muster
|
||||
# (fnmatch, Gross-/Kleinschreibung egal). Es gibt zwei Namenswelten, und beide
|
||||
# kommen im Projekt vor:
|
||||
# - Original-Kundenzeichnung (z.B. 500573_60_1.dxf): S-SP / S-LP / SCAN
|
||||
# - von den dxfmakros-Makros erzeugte Zeichnung (z.B. Mubea.dxf): die flachen
|
||||
# Blocknamen mit Dimensionssuffix, also Separator_SP_2D/_3D, Scanner_2D/_3D
|
||||
# Bewusst NICHT aufgenommen: Staustrecke_Separator_SP_*. Das ist ein Streckenmodul
|
||||
# mit eingebautem Separator - sein Einfuegepunkt ist der Modulursprung, nicht der
|
||||
# Separator, was einen zweiten, um genau diesen Versatz verschobenen Cluster in
|
||||
# die Abstimmung braechte.
|
||||
ANCHOR_BLOCKS: dict[str, tuple[str, ...]] = {
|
||||
"Separator": ("S-SP", "S-LP"),
|
||||
"Scanner": ("SCAN",),
|
||||
"Separator": ("S-SP", "S-LP", "Separator_SP*"),
|
||||
"Scanner": ("SCAN", "Scanner_*"),
|
||||
}
|
||||
|
||||
# Rastergroesse der Abstimmung in mm
|
||||
|
||||
+472
-10
@@ -77,6 +77,35 @@ CIRCLE_KINDS = ("Kreisel",)
|
||||
# Objektarten, die per "Zuordnung" an einem Knoten haengen (kein eigener Knoten)
|
||||
DEVICE_KINDS = ("Separator", "Scanner")
|
||||
|
||||
# Ein-/Ausgabestationen (BTMT Be-/Entladung) = Materialquelle/-senke, d.h. die
|
||||
# Ein-/Ausgangspunkte des Materialflusses. Sie werden in sps_skel erkannt;
|
||||
# dxfmakros exportiert sie derzeit NICHT (Blockmuster fehlt), die Erkennung
|
||||
# greift also, sobald eine passende Zeile im CSV auftaucht - erkannt an
|
||||
# TeileArt/Bezeichnung: "Beladung"/"BTMT-Beladung" -> Eingang, "Entladung"/
|
||||
# "SC_Entladung"/"Abwurf" -> Ausgang.
|
||||
ENTRY_KINDS = ("Beladung",) # BTMT-Beladung -> Materialeingang (Quelle)
|
||||
EXIT_KINDS = ("Entladung",) # SC_Entladung -> Materialausgang (Senke)
|
||||
STATION_KINDS = ENTRY_KINDS + EXIT_KINDS
|
||||
|
||||
# Schluesselwoerter zur Erkennung der Stationen (Kleinschreibung, Teilstring)
|
||||
STATION_PATTERNS = (
|
||||
("Beladung", ("beladung", "beladestation", "btmt-beladung", "btmt beladung")),
|
||||
("Entladung", ("entladung", "entladestation", "sc_entladung", "abwurf")),
|
||||
)
|
||||
|
||||
# Transfer-/Weichenelemente aus dem erweiterten Export. Sie bilden KEINE eigenen
|
||||
# Knoten, liefern aber die *gerichtete* Verbindung zwischen den Transportobjekten:
|
||||
# Ausschleuselement = Kreisel -> Strecke (am Streckenanfang, Material verlaesst Kreisel)
|
||||
# Einschleuselement = Strecke -> Kreisel (am Streckenende, Material laeuft in Kreisel)
|
||||
# Weiche = Uebergang zwischen zwei Kreiseln
|
||||
# Merkmale: {"Kreisel","Strecke","Streckenende"} bzw. {"Kreisel A","Kreisel B"}.
|
||||
TRANSFER_KINDS = ("Einschleus", "Ausschleus", "Weiche")
|
||||
TRANSFER_PATTERNS = (
|
||||
("Ausschleus", ("ausschleus",)),
|
||||
("Einschleus", ("einschleus",)),
|
||||
("Weiche", ("weiche",)),
|
||||
)
|
||||
|
||||
LANE_LEFT = "L"
|
||||
LANE_RIGHT = "R"
|
||||
LANE_NAMES = {LANE_LEFT: "links", LANE_RIGHT: "rechts"}
|
||||
@@ -104,6 +133,8 @@ NODE_STYLES = {
|
||||
"Kreisel": dict(fillcolor="#2f5597", fontcolor="#ffffff", color="#1f3864"),
|
||||
"Gefaellestrecke": dict(fillcolor="#fbe5d6", fontcolor="#833c00", color="#c55a11"),
|
||||
"Strecke": dict(fillcolor="#e2f0d9", fontcolor="#375623", color="#548235"),
|
||||
"Beladung": dict(fillcolor="#d4f0d4", fontcolor="#1e5b1e", color="#338833"),
|
||||
"Entladung": dict(fillcolor="#f4d4d4", fontcolor="#7a1f1f", color="#cc3333"),
|
||||
}
|
||||
DEFAULT_NODE_STYLE = dict(fillcolor="#f2f2f2", fontcolor="#404040", color="#808080")
|
||||
|
||||
@@ -152,6 +183,25 @@ class Element:
|
||||
def is_device(self) -> bool:
|
||||
return self.kind in DEVICE_KINDS
|
||||
|
||||
@property
|
||||
def is_entry(self) -> bool:
|
||||
"""BTMT-Beladung: Materialeingang (Quelle)."""
|
||||
return self.kind in ENTRY_KINDS
|
||||
|
||||
@property
|
||||
def is_exit(self) -> bool:
|
||||
"""SC_Entladung: Materialausgang (Senke)."""
|
||||
return self.kind in EXIT_KINDS
|
||||
|
||||
@property
|
||||
def is_station(self) -> bool:
|
||||
return self.kind in STATION_KINDS
|
||||
|
||||
@property
|
||||
def is_transfer(self) -> bool:
|
||||
"""Ein-/Ausschleuselement oder Weiche (liefert Richtung, kein Knoten)."""
|
||||
return self.kind in TRANSFER_KINDS
|
||||
|
||||
@property
|
||||
def height(self) -> float | None:
|
||||
"""Montage-/Einbauhoehe in Meter, falls ableitbar."""
|
||||
@@ -323,6 +373,25 @@ def parse_neighbours(raw: str) -> list[tuple[str, str | None]]:
|
||||
return result
|
||||
|
||||
|
||||
def _match_kind(patterns, *texts: str) -> str | None:
|
||||
"""Erste Musterklasse, deren Schluesselwort in den Texten vorkommt."""
|
||||
haystack = " ".join(t.lower() for t in texts if t)
|
||||
for kind, keys in patterns:
|
||||
if any(key in haystack for key in keys):
|
||||
return kind
|
||||
return None
|
||||
|
||||
|
||||
def classify_station(*texts: str) -> str | None:
|
||||
"""BTMT Be-/Entladestation an TeileArt/Bezeichnung erkennen (sonst None)."""
|
||||
return _match_kind(STATION_PATTERNS, *texts)
|
||||
|
||||
|
||||
def classify_transfer(*texts: str) -> str | None:
|
||||
"""Ein-/Ausschleuselement bzw. Weiche erkennen (sonst None)."""
|
||||
return _match_kind(TRANSFER_PATTERNS, *texts)
|
||||
|
||||
|
||||
def read_elements(path: Path, warnings: list[str]) -> list[Element]:
|
||||
"""CSV-Export einlesen."""
|
||||
with path.open("r", encoding=CSV_ENCODING, newline="") as handle:
|
||||
@@ -343,6 +412,14 @@ def read_elements(path: Path, warnings: list[str]) -> list[Element]:
|
||||
|
||||
teile_art = (row.get("TeileArt") or "").strip()
|
||||
kind = teile_art[len(TEILEART_PREFIX):] if teile_art.startswith(TEILEART_PREFIX) else teile_art
|
||||
# BTMT Be-/Entladestation als Ein-/Ausgang erkennen (sps_skel-seitig)
|
||||
station_kind = classify_station(teile_art, row.get("Bezeichnung") or "")
|
||||
if station_kind:
|
||||
kind = station_kind
|
||||
# Ein-/Ausschleuselement bzw. Weiche erkennen (liefern Richtung)
|
||||
transfer_kind = classify_transfer(teile_art, row.get("Bezeichnung") or "")
|
||||
if transfer_kind:
|
||||
kind = transfer_kind
|
||||
|
||||
raw_merkmale = (row.get("Merkmale") or "").strip()
|
||||
merkmale: dict = {}
|
||||
@@ -395,6 +472,12 @@ def _build_nodes(elements: list[Element], warnings: list[str]) -> dict[str, Node
|
||||
for lane in (LANE_LEFT, LANE_RIGHT):
|
||||
node_id = f"{element.teile_id}-{lane}"
|
||||
nodes[node_id] = Node(node_id, element.kind, element, lane=lane)
|
||||
elif element.is_station:
|
||||
nodes[element.teile_id] = Node(element.teile_id, element.kind, element)
|
||||
elif element.is_transfer:
|
||||
# Ein-/Ausschleuselement / Weiche liefern nur die (gerichtete)
|
||||
# Verbindung, siehe _apply_transfers - kein eigener Knoten.
|
||||
continue
|
||||
elif not element.is_device:
|
||||
warnings.append(
|
||||
f"{element.describe()}: unbekannte TeileArt '{element.teile_art}' - kein Knoten erzeugt"
|
||||
@@ -611,6 +694,160 @@ def _orient(
|
||||
return edges
|
||||
|
||||
|
||||
def _nearest_node(station: Element, nodes: dict[str, Node]) -> str | None:
|
||||
"""Naechster Nicht-Stations-Knoten zur Station (2D-Abstand)."""
|
||||
if station.x is None or station.y is None:
|
||||
return None
|
||||
best, best_d = None, None
|
||||
for node_id, node in nodes.items():
|
||||
if node.element.is_station or node.element.x is None or node.element.y is None:
|
||||
continue
|
||||
d = (node.element.x - station.x) ** 2 + (node.element.y - station.y) ** 2
|
||||
if best_d is None or d < best_d:
|
||||
best, best_d = node_id, d
|
||||
return best
|
||||
|
||||
|
||||
def _attach_stations(
|
||||
elements: list[Element], nodes: dict[str, Node], warnings: list[str]
|
||||
) -> list[Edge]:
|
||||
"""
|
||||
Ein-/Ausgabestationen (BTMT Be-/Entladung) mit dem Fluss verbinden.
|
||||
|
||||
Eingang (Beladung) ist Quelle: Kante Station -> Ziel.
|
||||
Ausgang (Entladung) ist Senke: Kante Ziel -> Station.
|
||||
Ziel kommt aus den 'Nachbarn' des Exports; fehlen sie (dxfmakros exportiert
|
||||
fuer BTMT derzeit keine), wird das naechstgelegene Objekt per Abstand genommen.
|
||||
"""
|
||||
edges: list[Edge] = []
|
||||
for element in elements:
|
||||
if not element.is_station:
|
||||
continue
|
||||
sid = element.teile_id
|
||||
if sid not in nodes:
|
||||
continue
|
||||
partners: list[str] = []
|
||||
for base, lane in element.neighbours:
|
||||
if lane and f"{base}-{lane}" in nodes:
|
||||
partners.append(f"{base}-{lane}")
|
||||
elif base in nodes:
|
||||
partners.append(base)
|
||||
else:
|
||||
partners += [f"{base}-{L}" for L in (LANE_LEFT, LANE_RIGHT)
|
||||
if f"{base}-{L}" in nodes]
|
||||
if not partners:
|
||||
nearest = _nearest_node(element, nodes)
|
||||
if nearest:
|
||||
partners = [nearest]
|
||||
warnings.append(
|
||||
f"{element.describe()}: keine Nachbarn im Export - "
|
||||
f"naechstes Objekt '{nearest}' per Abstand verbunden"
|
||||
)
|
||||
else:
|
||||
warnings.append(f"{element.describe()}: kein Ziel gefunden - unverbunden")
|
||||
continue
|
||||
for partner in partners:
|
||||
if element.is_entry:
|
||||
edges.append(Edge(sid, partner, EDGE_FLOW))
|
||||
else:
|
||||
edges.append(Edge(partner, sid, EDGE_FLOW))
|
||||
return edges
|
||||
|
||||
|
||||
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:
|
||||
if base == kreisel_base:
|
||||
node_id = f"{base}-{lane}" if lane else base
|
||||
return node_id if node_id in nodes else None
|
||||
for lane in (LANE_LEFT, LANE_RIGHT): # Fallback: irgendeine Bahn
|
||||
if f"{kreisel_base}-{lane}" in nodes:
|
||||
return f"{kreisel_base}-{lane}"
|
||||
return kreisel_base if kreisel_base in nodes else None
|
||||
|
||||
|
||||
def _apply_transfers(
|
||||
elements: list[Element], by_id: dict[str, Element],
|
||||
nodes: dict[str, Node], edges: list[Edge], warnings: list[str]
|
||||
) -> list[Edge]:
|
||||
"""
|
||||
Kreisel<->Strecke-Kanten anhand der Transferelemente gerichtet setzen.
|
||||
|
||||
Ausschleuselement: Kreisel -> Strecke (Streckenanfang).
|
||||
Einschleuselement: Strecke -> Kreisel (Streckenende).
|
||||
Weiche: Kreisel<->Kreisel als Weiche markieren.
|
||||
Die so definierten Kanten sind massgeblich und ersetzen die aus Hoehe/
|
||||
Nachbarn abgeleitete Richtung fuer genau diese Knotenpaare.
|
||||
"""
|
||||
# Transfer je Strecke sammeln: aus = Einlauf (Kreisel->Strecke, Anfang),
|
||||
# ein = Auslauf (Strecke->Kreisel, Ende)
|
||||
per_strecke: dict[str, dict[str, str]] = {}
|
||||
weiche_pairs: list[set[str]] = []
|
||||
for el in elements:
|
||||
if el.kind in ("Ausschleus", "Einschleus"):
|
||||
k = str(_merkmal(el.merkmale, "Kreisel") or "").strip()
|
||||
s = str(_merkmal(el.merkmale, "Strecke") or "").strip()
|
||||
if k and s:
|
||||
role = "aus" if el.kind == "Ausschleus" else "ein"
|
||||
per_strecke.setdefault(s, {})[role] = k
|
||||
elif el.kind == "Weiche":
|
||||
a = str(_merkmal(el.merkmale, "Kreisel A") or "").strip()
|
||||
b = str(_merkmal(el.merkmale, "Kreisel B") or "").strip()
|
||||
if a and b:
|
||||
weiche_pairs.append({a, b})
|
||||
|
||||
directed: dict[frozenset, tuple[str, str]] = {}
|
||||
for s, roles in per_strecke.items():
|
||||
if s not in nodes or nodes[s].element.is_circle:
|
||||
continue
|
||||
strecke_el = by_id.get(s)
|
||||
aus_lane = _kreisel_lane_node(roles["aus"], strecke_el, nodes) if roles.get("aus") else None
|
||||
ein_lane = _kreisel_lane_node(roles["ein"], strecke_el, nodes) if roles.get("ein") else None
|
||||
# Ruecklauf-Strecke (beide Enden am selben Kreisel): auf die zwei Bahnen verteilen
|
||||
if aus_lane and aus_lane == ein_lane:
|
||||
base = aus_lane.split("-")[0]
|
||||
lanes = [f"{base}-{L}" for L in (LANE_LEFT, LANE_RIGHT) if f"{base}-{L}" in nodes]
|
||||
if len(lanes) == 2:
|
||||
aus_lane, ein_lane = lanes
|
||||
warnings.append(
|
||||
f"Strecke {s}: Ein- und Ausschleusung am selben Kreisel {base} "
|
||||
f"(Ruecklauf) - Bahnen {lanes[0]}/{lanes[1]} angenommen"
|
||||
)
|
||||
if aus_lane: # Kreisel -> Strecke
|
||||
directed[frozenset({aus_lane, s})] = (aus_lane, s, "Ausschleusung")
|
||||
if ein_lane: # Strecke -> Kreisel
|
||||
directed[frozenset({ein_lane, s})] = (s, ein_lane, "Einschleusung")
|
||||
|
||||
# Fuer Strecken mit Transferelementen sind ALLEIN diese massgeblich fuer die
|
||||
# Kreisel<->Strecke-Verbindung. Jede weitere Kreisel<->Strecke-Kante aus den
|
||||
# rohen Nachbarn (Bounding-Box-Ueberlappung, z. B. ein VF, der zufaellig neben
|
||||
# einem dritten Kreisel liegt) ist ein Falschtreffer und wird verworfen.
|
||||
covered = set(per_strecke)
|
||||
result: list[Edge] = []
|
||||
for e in edges:
|
||||
if frozenset({e.src, e.dst}) in directed:
|
||||
continue # wird gerichtet neu gesetzt
|
||||
ends = {e.src, e.dst}
|
||||
strecke_end = ends & covered
|
||||
others = ends - strecke_end
|
||||
if strecke_end and len(others) == 1:
|
||||
other = next(iter(others))
|
||||
if other in nodes and nodes[other].kind in CIRCLE_KINDS:
|
||||
warnings.append(
|
||||
f"Kante {other} <-> {next(iter(strecke_end))}: Kreisel<->Strecke "
|
||||
f"ohne Transferelement - als Bounding-Box-Falschtreffer verworfen"
|
||||
)
|
||||
continue
|
||||
result.append(e)
|
||||
for (src, dst, note) in directed.values():
|
||||
result.append(Edge(src, dst, EDGE_FLOW, note))
|
||||
# Kreisel<->Kreisel-Kanten, die eine Weiche verbinden, markieren
|
||||
for e in result:
|
||||
if {e.src.split("-")[0], e.dst.split("-")[0]} in weiche_pairs:
|
||||
e.note = "Weiche"
|
||||
return result
|
||||
|
||||
|
||||
def build_graph(elements: list[Element], source: str, warnings: list[str]) -> Graph:
|
||||
by_id = {element.teile_id: element for element in elements}
|
||||
nodes = _build_nodes(elements, warnings)
|
||||
@@ -650,6 +887,12 @@ def build_graph(elements: list[Element], source: str, warnings: list[str]) -> Gr
|
||||
edges.append(Edge(left, right, EDGE_CIRCLE, "unbestimmt"))
|
||||
edges.append(Edge(right, left, EDGE_CIRCLE, "unbestimmt"))
|
||||
|
||||
# Ein-/Ausgabestationen (BTMT Be-/Entladung) als Quelle/Senke anbinden
|
||||
edges.extend(_attach_stations(elements, nodes, warnings))
|
||||
|
||||
# Kreisel<->Strecke gerichtet aus den Transferelementen (massgeblich)
|
||||
edges = _apply_transfers(elements, by_id, nodes, edges, warnings)
|
||||
|
||||
# Sackgassen und unerreichbare Bahnen melden. Sie entstehen, wenn ein
|
||||
# Kreisel nur in einer Richtung durchlaufen wird (Drehrichtung) und die
|
||||
# Gegenrichtung nicht ueber aeussere Verbindungen geschlossen ist.
|
||||
@@ -685,6 +928,14 @@ def _node_label(node: Node) -> str:
|
||||
element = node.element
|
||||
lines: list[str] = []
|
||||
|
||||
if element.is_station:
|
||||
role = "Materialeingang" if element.is_entry else "Materialausgang"
|
||||
lines.append(f"{element.name or element.kind} [{element.teile_id}]")
|
||||
lines.append(f"{element.kind} - {role}")
|
||||
if element.height is not None:
|
||||
lines.append(f"h = {element.height:.3f} m")
|
||||
return _dot_label(lines)
|
||||
|
||||
if node.lane:
|
||||
name = _merkmal(element.merkmale, "Name") or element.name
|
||||
lines.append(f"{name} [{node.node_id}]")
|
||||
@@ -716,12 +967,47 @@ def _node_label(node: Node) -> str:
|
||||
return _dot_label(lines)
|
||||
|
||||
|
||||
def render_dot(graph: Graph) -> str:
|
||||
# Zeichnungsmassstab fuer --use-cords: Graphviz rechnet in Punkt, die Anlage in
|
||||
# Millimeter. 0.25 pt/mm (1:4) - wie in tro_flow.py, damit Material- und TRO-Graph
|
||||
# im selben Massstab lagerichtig sind.
|
||||
COORD_SCALE = 0.25
|
||||
# Die beiden Bahnen (L/R) eines Kreisels teilen sich eine Position; im
|
||||
# lagerichtigen Layout leicht versetzen, damit sie nicht uebereinander liegen.
|
||||
LANE_NUDGE_MM = 350.0
|
||||
|
||||
|
||||
def _node_xy(node: "Node") -> tuple[float, float] | None:
|
||||
"""Anlagenkoordinate eines Knotens (Kreisel-Bahnen L/R leicht versetzt)."""
|
||||
el = node.element
|
||||
if el.x is None or el.y is None:
|
||||
return None
|
||||
x, y = el.x, el.y
|
||||
if node.lane == "L":
|
||||
y += LANE_NUDGE_MM
|
||||
elif node.lane == "R":
|
||||
y -= LANE_NUDGE_MM
|
||||
return (x, y)
|
||||
|
||||
|
||||
def _pos_attr(node: "Node", use_coords: bool) -> str:
|
||||
"""pos-Attribut fuer 'neato -n', oder leer ohne --use-cords."""
|
||||
if not use_coords:
|
||||
return ""
|
||||
xy = _node_xy(node)
|
||||
if xy is None:
|
||||
return ""
|
||||
return f', pos="{xy[0] * COORD_SCALE:.2f},{xy[1] * COORD_SCALE:.2f}"'
|
||||
|
||||
|
||||
def render_dot(graph: Graph, use_coords: bool = False) -> str:
|
||||
out: list[str] = []
|
||||
add = out.append
|
||||
|
||||
add("// Automatisch erzeugt von lib/material_flow.py - nicht manuell aendern.")
|
||||
add(f"// Quelle: {graph.source}")
|
||||
if use_coords:
|
||||
add(f"// Lagerichtig: Knoten auf Anlagenkoordinate, {COORD_SCALE} pt/mm.")
|
||||
add("// Rendern mit: neato -n -Tsvg <datei>.dot -o <datei>.svg")
|
||||
add("digraph Materialfluss {")
|
||||
add(' graph [rankdir=LR, splines=spline, nodesep=0.25, ranksep=1.6,')
|
||||
add(' fontname="Segoe UI", fontsize=11, labelloc="t",')
|
||||
@@ -755,7 +1041,8 @@ def render_dot(graph: Graph) -> str:
|
||||
style = NODE_STYLES.get(element.kind, DEFAULT_NODE_STYLE)
|
||||
for node in sorted(lanes, key=lambda n: n.lane or ""):
|
||||
attrs = ", ".join(f'{key}="{value}"' for key, value in style.items())
|
||||
add(f' "{node.node_id}" [label="{_node_label(node)}", {attrs}];')
|
||||
add(f' "{node.node_id}" [label="{_node_label(node)}", {attrs}'
|
||||
f'{_pos_attr(node, use_coords)}];')
|
||||
add(" { rank=same; " + " ".join(f'"{n.node_id}";' for n in lanes) + " }")
|
||||
add(" }")
|
||||
add("")
|
||||
@@ -763,7 +1050,8 @@ def render_dot(graph: Graph) -> str:
|
||||
for node in plain:
|
||||
style = NODE_STYLES.get(node.kind, DEFAULT_NODE_STYLE)
|
||||
attrs = ", ".join(f'{key}="{value}"' for key, value in style.items())
|
||||
add(f' "{node.node_id}" [label="{_node_label(node)}", {attrs}];')
|
||||
add(f' "{node.node_id}" [label="{_node_label(node)}", {attrs}'
|
||||
f'{_pos_attr(node, use_coords)}];')
|
||||
add("")
|
||||
|
||||
for edge in graph.edges:
|
||||
@@ -774,17 +1062,30 @@ def render_dot(graph: Graph) -> str:
|
||||
'arrowsize=0.9, fontcolor="#5b7fc7", '
|
||||
f'tooltip="Kreisel-Umlauf {edge.note}"{label}]')
|
||||
elif edge.kind == EDGE_UNRESOLVED:
|
||||
weiche = ', xlabel="Weiche", fontcolor="#cc8800"' if edge.note == "Weiche" else ""
|
||||
attrs = ('[color="#bf8f00", style=dashed, dir=both, '
|
||||
f'tooltip="Richtung {edge.note}"]')
|
||||
f'tooltip="Richtung {edge.note}"{weiche}]')
|
||||
elif edge.note == "Weiche":
|
||||
attrs = ('[color="#cc8800", penwidth=1.6, xlabel="Weiche", '
|
||||
'fontcolor="#cc8800", tooltip="Weiche (Kreisel-Uebergang)"]')
|
||||
else:
|
||||
attrs = "[]"
|
||||
add(f' "{edge.src}" -> "{edge.dst}" {attrs};')
|
||||
add("")
|
||||
|
||||
legend_pos = ""
|
||||
if use_coords:
|
||||
xs = [xy[0] for n in graph.nodes.values() if (xy := _node_xy(n))]
|
||||
ys = [xy[1] for n in graph.nodes.values() if (xy := _node_xy(n))]
|
||||
if xs and ys:
|
||||
lx, ly = min(xs), min(ys) - 3000.0 # etwas unterhalb der Anlage
|
||||
legend_pos = (f' pos="{lx * COORD_SCALE:.2f},'
|
||||
f'{ly * COORD_SCALE:.2f}",')
|
||||
|
||||
add(" subgraph cluster_legende {")
|
||||
add(' label="Legende"; style="rounded"; color="#a6a6a6";')
|
||||
add(' fontname="Segoe UI"; fontsize=10; fontcolor="#404040";')
|
||||
add(' legende [shape=plaintext, style="", fillcolor="none", label=<'
|
||||
add(f' legende [shape=plaintext, style="", fillcolor="none",{legend_pos} label=<'
|
||||
'<table border="0" cellborder="0" cellspacing="2" cellpadding="2">'
|
||||
'<tr><td align="left">durchgezogen</td><td align="left">Materialfluss</td></tr>'
|
||||
'<tr><td align="left"><font color="#8ea9db">gestrichelt blau</font></td>'
|
||||
@@ -800,6 +1101,120 @@ def render_dot(graph: Graph) -> str:
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# connect.ini (Item-/Flussebene) erzeugen
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _connect_kind(edge: Edge) -> str:
|
||||
"""Kantenart fuer connect.ini."""
|
||||
if edge.kind == EDGE_CIRCLE:
|
||||
return "umlauf"
|
||||
if edge.note == "Weiche":
|
||||
return "weiche"
|
||||
if edge.kind == EDGE_UNRESOLVED:
|
||||
return "unbestimmt"
|
||||
if edge.note in ("Einschleusung", "Ausschleusung"):
|
||||
return edge.note.lower()
|
||||
return "normal"
|
||||
|
||||
|
||||
def render_connect_ini(graph: Graph, section: str = "Anlage", overrides=None) -> str:
|
||||
"""
|
||||
Materialfluss-Topologie als connect.ini (Item-/Flussebene).
|
||||
|
||||
Zwischenstand fuer die TRO-Ableitung: Knoten = Flussobjekte (Kreisel-Bahnen,
|
||||
Strecke, Gefaellestrecke), Kanten = gerichteter Materialfluss. Von Hand
|
||||
editierbar. Aufbau angelehnt an doc/TRO_Katalog/connect.ini.
|
||||
|
||||
`overrides` (aus cfg/tro_overrides.ini) wird als eigener Abschnitt
|
||||
`[<Anlage>.manual]` angehaengt. Die Datei hier wird bei jedem Lauf neu
|
||||
geschrieben - von Hand eingetragene Weichen waeren sonst weg. Der Abschnitt
|
||||
beschreibt bewusst nur, WAS vor Ort bestaetigt wurde; er erfindet keine
|
||||
Flusskanten, denn welche Kante zur Weiche gehoert, ist aus dem Layout nicht
|
||||
ableitbar.
|
||||
"""
|
||||
out: list[str] = []
|
||||
add = out.append
|
||||
add("; ============================================================")
|
||||
add("; connect.ini - Materialfluss-Topologie (Item-/Flussebene)")
|
||||
add(f"; Automatisch erzeugt von lib/material_flow.py aus '{graph.source}'.")
|
||||
add("; Zwischenstand fuer die TRO-Ableitung; von Hand editierbar.")
|
||||
add(";")
|
||||
add("; [<Anlage>.nodes] <Knoten> = <Art> | <Bezeichnung>")
|
||||
add("; [<Anlage>.connections] cNNN = <von> -> <nach> | <JamArea> | <kind>")
|
||||
add("; kind: normal | umlauf | weiche | einschleusung | ausschleusung | unbestimmt")
|
||||
add("; [<Anlage>.externals] eNNN = EXTERN -> <Knoten> | <Info> (Zulauf/Beladung)")
|
||||
add("; eNNN = <Knoten> -> EXTERN | <Info> (Ablauf/Entladung)")
|
||||
add("; [<Anlage>.manual] vor Ort bestaetigte Angaben aus cfg/tro_overrides.ini")
|
||||
add("; ============================================================")
|
||||
add("")
|
||||
add(f"[{section}.nodes]")
|
||||
for node_id in sorted(graph.nodes):
|
||||
node = graph.nodes[node_id]
|
||||
el = node.element
|
||||
if node.lane:
|
||||
name = _merkmal(el.merkmale, "Name") or el.name
|
||||
comment = f"{name} (Bahn {node.lane})"
|
||||
else:
|
||||
comment = el.name or el.kind
|
||||
add(f"{node_id} = {node.kind} | {comment}")
|
||||
add("")
|
||||
add(f"[{section}.connections]")
|
||||
for i, edge in enumerate(sorted(graph.edges, key=lambda e: (e.src, e.dst)), start=1):
|
||||
add(f"c{i:03d} = {edge.src} -> {edge.dst} | | {_connect_kind(edge)}")
|
||||
add("")
|
||||
add(f"[{section}.externals]")
|
||||
stations = [n for n in graph.nodes.values() if n.element.is_station]
|
||||
if stations:
|
||||
for j, node in enumerate(sorted(stations, key=lambda n: n.node_id), start=1):
|
||||
if node.element.is_entry:
|
||||
add(f"e{j:03d} = EXTERN -> {node.node_id} | {node.element.name}")
|
||||
else:
|
||||
add(f"e{j:03d} = {node.node_id} -> EXTERN | {node.element.name}")
|
||||
else:
|
||||
add("; Noch keine BTMT Be-/Entladestation im Layout - Ein-/Ausgang offen.")
|
||||
add("; Kandidaten (offene Enden aus dem Materialfluss):")
|
||||
incoming = {e.dst for e in graph.edges}
|
||||
outgoing = {e.src for e in graph.edges}
|
||||
for node_id in sorted(graph.nodes):
|
||||
node = graph.nodes[node_id]
|
||||
if node.element.is_station:
|
||||
continue
|
||||
if node_id not in incoming:
|
||||
add(f"; Beladung? EXTERN -> {node_id} ({node.kind}, keine Zufuhr)")
|
||||
if node_id not in outgoing:
|
||||
add(f"; Entladung? {node_id} -> EXTERN ({node.kind}, kein Abfluss)")
|
||||
add("")
|
||||
|
||||
if overrides is not None and (overrides.tros or overrides.splits
|
||||
or overrides.open_points):
|
||||
add(f"[{section}.manual]")
|
||||
add("; Vor Ort bestaetigt, im CSV-Export nicht enthalten.")
|
||||
add(f"; Quelle: {overrides.source}")
|
||||
add("; Diese Zeilen werden aus der Override-Datei erzeugt - nicht hier")
|
||||
add("; editieren, sonst sind sie beim naechsten Lauf wieder weg.")
|
||||
for section_key, override in sorted(overrides.tros.items()):
|
||||
if not override.type_name:
|
||||
continue
|
||||
wie = f"Separator {override.key}" if override.by_separator else override.key
|
||||
add(f"{section_key} = {override.type_name} | {wie} | {override.reason}")
|
||||
for spec in overrides.splits:
|
||||
add(f"{spec.name} = NEU {spec.type_name} "
|
||||
f"| Separator {', '.join(spec.separators)}"
|
||||
+ (f" + Scanner {', '.join(spec.scanners)}" if spec.scanners else "")
|
||||
+ (f" | Bahn {spec.host}" if spec.host else "")
|
||||
+ f" | {spec.reason}")
|
||||
for point in overrides.open_points:
|
||||
add(f"{point.name} = OFFEN {point.expect or '?'} "
|
||||
f"| x={point.x:.2f} y={point.y:.2f} "
|
||||
f"| heute Teil von {point.belongs_to or '-'} "
|
||||
f"| {point.note}")
|
||||
add("")
|
||||
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# SVG erzeugen
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -851,9 +1266,13 @@ def graph_to_svg(
|
||||
f"'{engine}' ist mit Code {result.returncode} fehlgeschlagen:\n"
|
||||
f"{(result.stderr or result.stdout).strip()}"
|
||||
)
|
||||
# neato meldet fehlende Positionen nur als Warnung auf stderr
|
||||
if result.stderr.strip():
|
||||
raise RuntimeError(f"'{engine}' meldet: {result.stderr.strip()}")
|
||||
# 'neato -n' gibt harmlose Warnungen auf stderr aus (z. B. sich beruehrende
|
||||
# Knoten -> gerade Kanten). Nur dann scheitern, wenn wirklich keine SVG
|
||||
# entstanden ist; sonst ist die Datei gueltig und die Warnung unkritisch.
|
||||
if not svg_file.is_file() or svg_file.stat().st_size == 0:
|
||||
raise RuntimeError(
|
||||
f"'{engine}' hat keine SVG erzeugt: {result.stderr.strip() or '(keine Meldung)'}"
|
||||
)
|
||||
|
||||
|
||||
def dot_to_svg(dot_file: Path, svg_file: Path) -> None:
|
||||
@@ -1164,12 +1583,28 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
||||
help="Aus der erzeugten DOT-Datei zusaetzlich eine SVG-Datei erzeugen "
|
||||
"(benoetigt Graphviz 'dot').",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--use-cords",
|
||||
"--use-coords",
|
||||
dest="use_cords",
|
||||
action="store_true",
|
||||
help="Jeden Knoten auf seine Anlagenkoordinate setzen und das SVG von "
|
||||
f"Graphviz 'neato -n' erzeugen statt von 'dot' (lagerichtig, "
|
||||
f"{COORD_SCALE} pt/mm). Nur mit --tosvg wirksam.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--doc",
|
||||
action="store_true",
|
||||
help="Dokumentation des Materialflusses als Markdown in %%SKEL_RESULTS%% "
|
||||
"erzeugen (Anlagenobjekte, Verbindungen, Pruefungen).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--connect",
|
||||
action="store_true",
|
||||
help="Materialfluss-Topologie zusaetzlich als connect.ini (Item-/Flussebene) "
|
||||
"nach %%SKEL_RESULTS%% schreiben (Knoten, gerichtete Verbindungen, "
|
||||
"Ein-/Ausgang-Kandidaten) - Zwischenstand fuer die TRO-Ableitung.",
|
||||
)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
@@ -1210,13 +1645,26 @@ def main(argv: list[str] | None = None) -> int:
|
||||
svg_file = results / f"{stem}_material_flow.svg"
|
||||
doc_target = results / f"{stem}_material_flow.md"
|
||||
|
||||
# --use-cords braucht an jedem Knoten eine Koordinate
|
||||
if args.use_cords:
|
||||
without = [n.node_id for n in graph.nodes.values() if _node_xy(n) is None]
|
||||
if without:
|
||||
print(f"FEHLER: --use-cords nicht moeglich, {len(without)} Knoten ohne "
|
||||
f"Koordinate: {', '.join(without)}", file=sys.stderr)
|
||||
print(" Ohne pos an jedem Knoten kann 'neato -n' nicht zeichnen.",
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
|
||||
existing_svg = svg_file if svg_file.is_file() else None
|
||||
dot_file.write_text(render_dot(graph), encoding="utf-8")
|
||||
dot_file.write_text(render_dot(graph, use_coords=args.use_cords), encoding="utf-8")
|
||||
|
||||
svg_error: str | None = None
|
||||
if args.tosvg:
|
||||
try:
|
||||
dot_to_svg(dot_file, svg_file)
|
||||
if args.use_cords:
|
||||
graph_to_svg(dot_file, svg_file, engine="neato", no_op=1)
|
||||
else:
|
||||
dot_to_svg(dot_file, svg_file)
|
||||
except RuntimeError as exc:
|
||||
svg_error = str(exc)
|
||||
created_svg = svg_file if args.tosvg and svg_error is None else None
|
||||
@@ -1229,6 +1677,20 @@ def main(argv: list[str] | None = None) -> int:
|
||||
)
|
||||
doc_file = doc_target
|
||||
|
||||
connect_file = None
|
||||
if args.connect:
|
||||
# Spaet importiert: tro_overrides zieht tro_catalog nach, das
|
||||
# material_flow sonst nicht braucht.
|
||||
from tro_overrides import load_overrides
|
||||
|
||||
overrides = load_overrides(csv_file.name, env_dir("SKEL_CFG", "cfg"))
|
||||
connect_target = results / f"{stem}_connect.ini"
|
||||
connect_target.write_text(
|
||||
render_connect_ini(graph, section=stem, overrides=overrides),
|
||||
encoding="utf-8",
|
||||
)
|
||||
connect_file = connect_target
|
||||
|
||||
report(
|
||||
graph,
|
||||
findings,
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Absichtlich ohne Shebang: der Windows-py-Launcher wuerde daraus "python3"
|
||||
# ableiten und scheitert, wenn keine PythonCore-Installation registriert ist.
|
||||
"""
|
||||
scl_skeleton.py - FB_Main-Geruest als SCL aus der TRO-Liste erzeugen.
|
||||
|
||||
Letzter Schritt der Kette:
|
||||
|
||||
material_flow.py Objekte -> Materialfluss
|
||||
tro_flow.py Fluss -> TROs
|
||||
tro_annotate.py TROs -> Marker in der Zeichnung
|
||||
tro_extract.py Zeichnung -> JSON
|
||||
scl_skeleton.py JSON -> FB_Main.scl <- hier
|
||||
|
||||
Erzeugt wird ein **Geruest**, kein fertiges Programm: je TRO eine REGION mit
|
||||
Instanzaufruf und allen Parameterzeilen in der richtigen Reihenfolge, so wie es
|
||||
die realen Aufrufstellen in doc/TRO_Katalog/scl_templates/*.scl zeigen.
|
||||
|
||||
Was aus dem Layout kommt, steht drin. Was aus der E-Planung kommen muss, steht
|
||||
als Platzhalter mit `TODO(E-Planung)` da - bewusst als offensichtliche Luecke
|
||||
und nicht als erfundener Wert, denn eine plausibel aussehende falsche
|
||||
Sensoradresse ist schlimmer als eine leere. Alle Platzhalter sind ueber genau
|
||||
diesen Marker auffindbar.
|
||||
|
||||
Ableitbar und daher gefuellt:
|
||||
- Reihenfolge der REGIONs (Materialfluss), Instanzliste, FB-Typ je TRO
|
||||
- Anzahl der Separator-/Weichen-/Scanner-Parameterbloecke je TRO
|
||||
- nTo1Destinations einer Weiche = Anzahl ihrer Abgaenge
|
||||
- die Zielliste je Weichenabgang (Erreichbarkeit im TRO-Graphen)
|
||||
- Querverweis auf die Bauteile im Layout (Separatornummern, Koordinate)
|
||||
|
||||
Aufruf ueber bin/scl_skeleton.bat bzw. bin/scl_skeleton.sh.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from collections import deque
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from material_flow import env_dir
|
||||
|
||||
TODO = "TODO(E-Planung)"
|
||||
|
||||
# Zeitwerte aus den Referenz-Aufrufstellen. Sie sind plausible Startwerte, KEINE
|
||||
# fuer diese Anlage ermittelten - deshalb ueberall mit Pruefhinweis.
|
||||
DEFAULT_SEP_TIMES = (
|
||||
("tDelayToNextItem", '"TimeForSepWaiting_Short"', None),
|
||||
("tTrailingTime", "t#600ms", "pruefen"),
|
||||
("tHandlingTime", "t#200ms", "pruefen"),
|
||||
("tJam", '"TimeForSepJam"', None),
|
||||
)
|
||||
|
||||
|
||||
def load_tros(path: Path) -> dict:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def flow_order(tros: list[dict], start_id: str = "") -> tuple[list[dict], str]:
|
||||
"""TROs in Fliessrichtung sortieren.
|
||||
|
||||
Startpunkt ist ein TRO ohne Vorgaenger - also die Stelle, an der Material
|
||||
in die Anlage kommt. Solange Be-/Entladestation fehlen, ist der Fluss ein
|
||||
geschlossener Kreis und es gibt keinen solchen TRO; dann muss der Kreis
|
||||
irgendwo aufgetrennt werden. Das ist eine willkuerliche Wahl, deshalb wird
|
||||
sie zurueckgegeben und im Kopf der SCL vermerkt (und laesst sich mit
|
||||
--start ueberschreiben). Nicht erreichte TROs haengt die Funktion hinten
|
||||
an, damit nie einer verlorengeht.
|
||||
"""
|
||||
nach_id = {t["id"]: t for t in tros}
|
||||
ohne_vorgaenger = sorted(t["id"] for t in tros if not t.get("predecessors"))
|
||||
|
||||
if start_id and start_id in nach_id:
|
||||
start, grund = [start_id], "per --start gesetzt"
|
||||
elif ohne_vorgaenger:
|
||||
start, grund = ohne_vorgaenger, "TRO ohne Vorgaenger (Materialeingang)"
|
||||
else:
|
||||
start = [min(nach_id)]
|
||||
grund = ("Kreislauf ohne Eingang - willkuerlich aufgetrennt; sobald "
|
||||
"Be-/Entladestation im Export stehen, ergibt sich der Anfang")
|
||||
|
||||
gesehen: list[str] = []
|
||||
queue = deque(start)
|
||||
while queue:
|
||||
tro_id = queue.popleft()
|
||||
if tro_id in gesehen:
|
||||
continue
|
||||
gesehen.append(tro_id)
|
||||
for nxt in nach_id.get(tro_id, {}).get("successors", []):
|
||||
if nxt not in gesehen:
|
||||
queue.append(nxt)
|
||||
for tro_id in sorted(nach_id):
|
||||
if tro_id not in gesehen:
|
||||
gesehen.append(tro_id)
|
||||
return [nach_id[i] for i in gesehen], grund
|
||||
|
||||
|
||||
def reachable_via(start: str, first: str, tros: dict[str, dict]) -> list[str]:
|
||||
"""Welche TROs sind ueber diesen Abgang erreichbar?
|
||||
|
||||
Das ist die Zielliste eines Weichenabgangs: von `first` aus weiterlaufen,
|
||||
ohne ueber die Weiche selbst zurueckzugehen. Genau die Information, die
|
||||
FC_Direction braucht, um zu entscheiden - und sie steht im Graphen.
|
||||
"""
|
||||
gesehen: set[str] = set()
|
||||
queue = deque([first])
|
||||
while queue:
|
||||
node = queue.popleft()
|
||||
if node in gesehen or node == start:
|
||||
continue
|
||||
gesehen.add(node)
|
||||
queue.extend(tros.get(node, {}).get("successors", []))
|
||||
return sorted(gesehen)
|
||||
|
||||
|
||||
def region_title(tro: dict) -> str:
|
||||
seps = ", ".join(tro.get("separators", []))
|
||||
teile = f" Sep {seps}" if seps else ""
|
||||
return f"{tro['id']} ({tro['type']}){teile}"
|
||||
|
||||
|
||||
def emit_separators(add, tro: dict, anzahl: int, hat_scanner: bool) -> None:
|
||||
seps = tro.get("separators", [])
|
||||
for i in range(1, anzahl + 1):
|
||||
pfad = f"#{tro['id']}.stInSeparator{i}"
|
||||
layout = seps[i - 1] if i <= len(seps) else "?"
|
||||
add(f" // Separator {i} = Bauteil {layout} aus dem Layout")
|
||||
add(f' {pfad}.Settings.nSeparatorNo := "cSep_____"; // {TODO}')
|
||||
for name, wert, hinweis in DEFAULT_SEP_TIMES:
|
||||
kommentar = f" // {TODO}: {hinweis}" if hinweis else ""
|
||||
add(f" {pfad}.Settings.{name} := {wert};{kommentar}")
|
||||
add(f" {pfad}.Settings.xPluggedJam := TRUE;")
|
||||
add(f" {pfad}.Settings.xPluggedPart := FALSE;")
|
||||
add(f" {pfad}.Settings.xPluggedScanner := "
|
||||
f"{'TRUE' if hat_scanner else 'FALSE'};")
|
||||
add(f' {pfad}.stSenInSep := "DB_Inputs".Sensors["cInBG____"]; // {TODO}')
|
||||
add(f" {pfad}.Settings.tSenFree := T#1500ms; // {TODO}: pruefen")
|
||||
add(f" {pfad}.Settings.tSenWait := T#4000ms; // {TODO}: pruefen")
|
||||
add("")
|
||||
|
||||
|
||||
def emit_switches(add, tro: dict, anzahl: int, alle: dict[str, dict]) -> None:
|
||||
abgaenge = tro.get("successors", [])
|
||||
for j in range(1, anzahl + 1):
|
||||
pfad = f"#{tro['id']}.stInSwitch{j}"
|
||||
add(f' {pfad}.Settings.nSwitchNo := "cSwi_____"; // {TODO}')
|
||||
add(f" {pfad}.Settings.xPluggedExSen3 := FALSE;")
|
||||
add(f" {pfad}.Settings.xPluggedExSen4 := FALSE;")
|
||||
if anzahl == 1:
|
||||
# Eine Weiche bedient alle Abgaenge - direkt ableitbar.
|
||||
add(f" {pfad}.Settings.nTo1Destinations := {len(abgaenge)};"
|
||||
f" // Abgaenge laut Topologie")
|
||||
else:
|
||||
# Bei mehreren Weichen ist es eine Planungsentscheidung, welche
|
||||
# Weiche welche Abgaenge bedient - die Summe ist bekannt, die
|
||||
# Aufteilung nicht. Deshalb hier kein geratener Wert.
|
||||
add(f" {pfad}.Settings.nTo1Destinations := _;"
|
||||
f" // {TODO}: dieser TRO hat {len(abgaenge)} "
|
||||
f"Abgaenge auf {anzahl} Weichen - Aufteilung festlegen")
|
||||
add("")
|
||||
if abgaenge:
|
||||
add(" // Zielliste je Abgang (aus dem TRO-Graphen berechnet) -")
|
||||
add(" // Grundlage fuer die Zuordnung Ziel -> Richtung in FC_Direction:")
|
||||
for abgang in abgaenge:
|
||||
ziele = reachable_via(tro["id"], abgang, alle)
|
||||
add(f" // ueber {abgang}: {', '.join(ziele) if ziele else '-'}")
|
||||
add("")
|
||||
|
||||
|
||||
def emit_vario(add, tro: dict) -> None:
|
||||
pfad = f"#{tro['id']}.stInVario"
|
||||
add(f" {pfad}.Settings.xContinousEmptying := FALSE;")
|
||||
add(f" {pfad}.Settings.tWaitForJog := T#300ms; // {TODO}: pruefen")
|
||||
add(f" {pfad}.Settings.tConvEmpty := T#45000ms; // {TODO}: pruefen")
|
||||
add(f" {pfad}.Settings.nCountCarrier := 1; // {TODO}: pruefen")
|
||||
add(f" {pfad}.Settings.tWaitForStop := t#3s;")
|
||||
add(f" {pfad}.Settings.tCarrierInPosDelay := t#1200ms;")
|
||||
add(f" {pfad}.Settings.tCarrierInPosEdgeDelay := t#100ms;")
|
||||
add(f" {pfad}.Settings.xJamSenDelayActive := TRUE;")
|
||||
add(f" {pfad}.Settings.tJamSenDelay := T#2s;")
|
||||
add(f' {pfad}.stSenCarrInPos := "DB_Inputs".Sensors["cInBG____"]; // {TODO}')
|
||||
add(f' {pfad}.stSenFinger := "DB_Inputs".Sensors["cInBG____"]; // {TODO}')
|
||||
add(f' {pfad}.stSenLastPos := "DB_Inputs".Sensors["cInBG____"]; // {TODO}')
|
||||
add(f' {pfad}.stSenJam := "DB_Inputs".Sensors["cInBG____"]; // {TODO}')
|
||||
add("")
|
||||
|
||||
|
||||
def emit_barcode(add, tro: dict, anzahl: int) -> None:
|
||||
for i in range(1, anzahl + 1):
|
||||
suffix = "" if anzahl == 1 else str(i)
|
||||
pfad = f"#{tro['id']}.stInBarcodeReader{suffix}"
|
||||
add(f" {pfad}.Settings.xActivateCheckASCI := TRUE;")
|
||||
add(f" {pfad}.Settings.tTimeout := T#3000ms;")
|
||||
add(f' // {TODO}: Cognex-Interface verdrahten '
|
||||
f'(#arCognexInterface["cScanner____"])')
|
||||
add("")
|
||||
|
||||
|
||||
def emit_call(add, tro: dict, items: dict[str, int]) -> None:
|
||||
"""Aufrufstelle schreiben.
|
||||
|
||||
Die Zeilen werden als (Code, Kommentar) gefuehrt und das Komma erst beim
|
||||
Zusammensetzen gesetzt - sonst landet es hinter dem "//" und ist Teil des
|
||||
Kommentars, womit die Parameterliste nicht mehr uebersetzt.
|
||||
"""
|
||||
tro_id = tro["id"]
|
||||
zeilen: list[tuple[str, str]] = [
|
||||
('nInMainTroNo := "cMainTro____"', TODO),
|
||||
('xInSftyOk := "DB_InterfaceSafety".stFromSafety.EStopMain.Q', TODO),
|
||||
("xInAllRdyToStart := TRUE", ""),
|
||||
(f'xInRelease := "DB_TRO_TEST".{tro_id}', ""),
|
||||
]
|
||||
if items.get("VarioDrive"):
|
||||
zeilen.append(('xInMotorProtection := "FC____"', TODO))
|
||||
zeilen.append(("xInAutomatic := #t_automatik", ""))
|
||||
zeilen.append(("stInOutMachineState := #stInOutControlUnitCabinet", ""))
|
||||
zeilen.append(("stInOutCognexInterface := #stCognexInterfaceDummy", ""))
|
||||
|
||||
# Staubereiche: je ankommender/abgehender Verbindung einer. Welche
|
||||
# DB-Struktur dahintersteht, ist eine Planungsentscheidung - hier steht
|
||||
# nur, WIE VIELE es sein muessen und zu welchem Nachbarn sie gehoeren.
|
||||
for n, vor in enumerate(tro.get("predecessors", []), start=1):
|
||||
zeilen.append((f'arInOutJamEntr{n} := "DB_JamArea____".stJam____.arCarrier',
|
||||
f"{TODO} - Staubereich von {vor}"))
|
||||
zeilen.append((f'stInOutJamEntr{n} := "DB_JamArea____".stJam____.stData', ""))
|
||||
for n, nach in enumerate(tro.get("successors", []), start=2):
|
||||
zeilen.append((f'arInOutJamExit{n} := "DB_JamArea____".stJam____.arCarrier',
|
||||
f"{TODO} - Staubereich nach {nach}"))
|
||||
zeilen.append((f'stInOutJamExit{n} := "DB_JamArea____".stJam____.stData', ""))
|
||||
|
||||
for i in range(1, items.get("Separator", 1) + 1):
|
||||
zeilen.append((f'xOutStopper{i} => "MB____"', TODO))
|
||||
if items.get("VarioDrive"):
|
||||
zeilen.append(('xOutVarioMotor => "MA____"', TODO))
|
||||
for j in range(1, items.get("Switch", 0) + 1):
|
||||
zeilen.append((f'xOutSw{j}ExTo3 => "MB____"', TODO))
|
||||
zeilen.append((f'stInOutHMI := "DB_Interface_HMI".stTRO.{tro_id}', ""))
|
||||
zeilen.append(('nOutStateLast => "DB_GLOB_TroState".arTroState["cMainTro____"]',
|
||||
TODO))
|
||||
|
||||
kopf = f" #{tro_id}("
|
||||
einzug = " " * len(kopf)
|
||||
for index, (code, kommentar) in enumerate(zeilen):
|
||||
trenner = ");" if index == len(zeilen) - 1 else ","
|
||||
prefix = kopf if index == 0 else einzug
|
||||
text = f"{prefix}{code}{trenner}"
|
||||
add(f"{text} // {kommentar}" if kommentar else text)
|
||||
|
||||
|
||||
def emit_direction(add, tro: dict, anzahl: int) -> None:
|
||||
"""Weichenlogik - je Weiche ein FC_Direction-Aufruf."""
|
||||
add("")
|
||||
add(" REGION Direction")
|
||||
for j in range(1, anzahl + 1):
|
||||
ziel = (f"#{tro['id']}.nInDirection" if anzahl == 1
|
||||
else f"#{tro['id']}.nInDirection{j}")
|
||||
add(f' "FC_Direction"(nInSwitchNo := "cSwi_____", // {TODO}')
|
||||
add(f" nOutDirection => {ziel},")
|
||||
add(f' InOutCarrier := "DB_JamArea____".stJam____'
|
||||
f".arCarrier[1]);")
|
||||
if j < anzahl:
|
||||
add("")
|
||||
add(" END_REGION")
|
||||
|
||||
|
||||
def render(daten: dict, quelle: str, start_id: str = "") -> str:
|
||||
tros = daten["tros"]
|
||||
alle = {t["id"]: t for t in tros}
|
||||
geordnet, startgrund = flow_order(tros, start_id)
|
||||
|
||||
out: list[str] = []
|
||||
add = out.append
|
||||
|
||||
add("// ============================================================")
|
||||
add("// FB_Main - GERUEST, erzeugt von lib/scl_skeleton.py")
|
||||
add(f"// Quelle : {quelle}")
|
||||
add(f"// Erzeugt: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
|
||||
add("//")
|
||||
add("// Das ist KEIN lauffaehiges Programm, sondern ein Geruest zum")
|
||||
add("// Ausfuellen. Struktur, Reihenfolge und Bauteilzahl stammen aus dem")
|
||||
add("// Anlagenlayout und der vor Ort aufgenommenen Topologie.")
|
||||
add("//")
|
||||
add(f"// Jede Stelle, die aus der E-Planung kommen muss, ist mit")
|
||||
add(f"// '{TODO}' markiert - danach suchen, dann ist nichts vergessen.")
|
||||
add("// Offen sind durchgaengig: Sensor-/Aktoradressen (cInBG/MB/MA),")
|
||||
add("// Separator- und Weichennummern, MainTro-Nummern, die Staubereiche")
|
||||
add("// (DB_JamArea...) und die Zeiten, soweit als 'pruefen' vermerkt.")
|
||||
add("//")
|
||||
add("// Reihenfolge der REGIONs = Materialfluss.")
|
||||
add(f"// Anfang bei {geordnet[0]['id']}: {startgrund}.")
|
||||
add("// ============================================================")
|
||||
add("")
|
||||
add('FUNCTION_BLOCK "FB_Main"')
|
||||
add("{ S7_Optimized_Access := 'TRUE' }")
|
||||
add("VERSION : 0.1")
|
||||
add(" VAR ")
|
||||
for tro in geordnet:
|
||||
fb = tro.get("fbType") or "FB_UNBEKANNT"
|
||||
kommentar = f" // {tro['type']}"
|
||||
if tro.get("separators"):
|
||||
kommentar += f", Sep {', '.join(tro['separators'])}"
|
||||
add(f' {tro["id"]} : "{fb}";{kommentar}')
|
||||
add(" END_VAR")
|
||||
add("")
|
||||
add("BEGIN")
|
||||
|
||||
for tro in geordnet:
|
||||
items = tro.get("items", {})
|
||||
n_sep = items.get("Separator", 1)
|
||||
n_swi = items.get("Switch", 0)
|
||||
n_scan = items.get("Scanner", 0)
|
||||
|
||||
add("")
|
||||
add(f"REGION {region_title(tro)}")
|
||||
pos = tro.get("position")
|
||||
if pos:
|
||||
add(f" // Anlagenkoordinate x/y: {pos['x']:.0f} / {pos['y']:.0f} mm")
|
||||
add(f" // Vorgaenger: {', '.join(tro.get('predecessors', [])) or '-'}")
|
||||
add(f" // Nachfolger: {', '.join(tro.get('successors', [])) or '-'}")
|
||||
if tro.get("confidence"):
|
||||
add(f" // Einstufung: {tro['confidence']}")
|
||||
add("")
|
||||
|
||||
emit_separators(add, tro, n_sep, hat_scanner=bool(n_scan))
|
||||
if n_swi:
|
||||
emit_switches(add, tro, n_swi, alle)
|
||||
if items.get("VarioDrive"):
|
||||
emit_vario(add, tro)
|
||||
if n_scan:
|
||||
emit_barcode(add, tro, n_scan)
|
||||
if items.get("StorageLine"):
|
||||
add(f" // {TODO}: Linienspeicher mit {items['StorageLine']} Linien - "
|
||||
f"Parametrierung je Linie")
|
||||
add("")
|
||||
|
||||
add(" #%s.stInPriorityManager.xReleaseOk := TRUE;" % tro["id"])
|
||||
add("")
|
||||
emit_call(add, tro, items)
|
||||
if n_swi:
|
||||
emit_direction(add, tro, n_swi)
|
||||
add("END_REGION")
|
||||
|
||||
add("")
|
||||
add("END_FUNCTION_BLOCK")
|
||||
add("")
|
||||
return "\n".join(out)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
args = parse_args(argv)
|
||||
results = env_dir("SKEL_RESULTS", "results")
|
||||
|
||||
json_file = Path(args.json)
|
||||
if not json_file.is_absolute() and json_file.parent == Path("."):
|
||||
json_file = results / args.json
|
||||
if not json_file.is_file():
|
||||
print(f"FEHLER: JSON nicht gefunden: {json_file}", file=sys.stderr)
|
||||
print(" Zuerst bin/tro_extract.bat laufen lassen.", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
try:
|
||||
daten = load_tros(json_file)
|
||||
except (OSError, ValueError) as exc:
|
||||
print(f"FEHLER: {json_file} nicht lesbar: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
if not daten.get("tros"):
|
||||
print(f"FEHLER: {json_file} enthaelt keine TROs.", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
text = render(daten, json_file.name, args.start)
|
||||
out_file = results / (args.out or f"{json_file.stem.replace('_tro', '')}_FB_Main.scl")
|
||||
out_file.write_text(text, encoding="utf-8")
|
||||
|
||||
offen = text.count(TODO)
|
||||
geordnet, startgrund = flow_order(daten["tros"], args.start)
|
||||
print("")
|
||||
print("================================================================")
|
||||
print("FB_MAIN-GERUEST")
|
||||
print("================================================================")
|
||||
print(f"Quelle = {json_file}")
|
||||
print(f"TROs = {len(daten['tros'])}")
|
||||
print(f"Reihenfolge = {' -> '.join(t['id'] for t in geordnet)}")
|
||||
print(f"Anfang = {geordnet[0]['id']} ({startgrund})")
|
||||
print(f"Offene Stellen = {offen} (Marker '{TODO}')")
|
||||
print(f"SCL = {out_file}")
|
||||
print("================================================================")
|
||||
print("")
|
||||
return 0
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="scl_skeleton",
|
||||
description="Erzeugt aus der extrahierten TRO-Liste ein FB_Main-Geruest "
|
||||
"als SCL zum Import in TIA Portal.",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="Beispiele:\n"
|
||||
" scl_skeleton.bat\n"
|
||||
" scl_skeleton.bat --json export_tro.json --out FB_Main.scl\n"
|
||||
"\n"
|
||||
"Exit-Codes:\n"
|
||||
" 0 ok\n"
|
||||
" 1 Eingabe- oder Aufruffehler\n",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--json",
|
||||
default="export_tro.json",
|
||||
metavar="NAME",
|
||||
help="TRO-JSON aus tro_extract.py in %%SKEL_RESULTS%% "
|
||||
"(oder ein vollstaendiger Pfad). Standard: %(default)s",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--out",
|
||||
metavar="NAME",
|
||||
help="Name der SCL-Datei in %%SKEL_RESULTS%%. Standard: <Quelle>_FB_Main.scl",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--start",
|
||||
default="",
|
||||
metavar="TRO",
|
||||
help="TRO, bei dem die Reihenfolge beginnt. Nur noetig, solange der "
|
||||
"Fluss ein geschlossener Kreis ohne Be-/Entladestation ist.",
|
||||
)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -152,6 +152,9 @@ class TroSymbol:
|
||||
HEXAGON = "hexagon" # Sechseck
|
||||
RECT = "rect" # liegendes Rechteck
|
||||
ARROW = "arrow" # Pfeil/Fahne
|
||||
# Dreieck mit zweitem Dreieck innen - fuer 2Sep2Swi, sichtbar verwandt mit
|
||||
# TRIANGLE_DOWN (2Sep1Swi) und trotzdem davon unterscheidbar.
|
||||
DOUBLE_TRIANGLE_DOWN = "double_triangle_down"
|
||||
|
||||
@classmethod
|
||||
def all(cls) -> tuple[str, ...]:
|
||||
@@ -508,6 +511,20 @@ TRO_CATALOG: tuple[TroDefinition, ...] = (
|
||||
TroItem.SWITCH: 1,
|
||||
TroItem.SCANNER: 2,
|
||||
}, STYLE_SWI, TroSymbol.TRIANGLE_DOWN),
|
||||
# ACHTUNG - NICHT aus SCL belegt. Alle Typen oberhalb stammen aus
|
||||
# vorhandenem Code bzw. der Mapping-Tabelle in TRO_Typen.md; dieser hier
|
||||
# wurde am 2026-08-12 auf Anforderung aus dem Projekt 500573 (Mubea)
|
||||
# aufgenommen, um zwei Uebergabestellen am Beruehrpunkt Kreisel2/Kreisel1
|
||||
# zu einem Steuerobjekt zusammenzufassen.
|
||||
# Der Baustein FB_ILS_MTRO_2Sep2Swi existiert in diesem Repository nicht
|
||||
# und ist auch in doc/TRO_Katalog/scl_templates/ nicht hinterlegt - er muss
|
||||
# in der ILSLib angelegt werden, sonst erzeugt ein spaeterer
|
||||
# SCL-Generator einen Aufruf auf einen fehlenden Baustein.
|
||||
TroDefinition("2Sep2Swi", "FB_ILS_MTRO_2Sep2Swi", {
|
||||
TroItem.SEPARATOR: 2,
|
||||
TroItem.SWITCH: 2,
|
||||
TroItem.SCANNER: 2,
|
||||
}, STYLE_SWI, TroSymbol.DOUBLE_TRIANGLE_DOWN),
|
||||
)
|
||||
|
||||
_BY_NAME: dict[str, TroDefinition] = {t.get_name(): t for t in TRO_CATALOG}
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Absichtlich ohne Shebang: der Windows-py-Launcher wuerde daraus "python3"
|
||||
# ableiten und scheitert, wenn keine PythonCore-Installation registriert ist.
|
||||
"""
|
||||
tro_extract.py - TROs aus der annotierten Zeichnung zurueck nach JSON lesen.
|
||||
|
||||
Gegenrichtung zu tro_annotate.py:
|
||||
|
||||
tro_annotate.py CSV + Ableitung -> Marker in der Zeichnung
|
||||
tro_extract.py Zeichnung -> JSON
|
||||
|
||||
Gelesen wird ausschliesslich die Zeichnung, nicht der CSV-Export. Damit
|
||||
kommt zurueck, was tatsaechlich in der Zeichnung steht - also auch das, was
|
||||
in BricsCAD von Hand nachgezogen wurde (Marker verschoben, Typ ueber TRO_EDIT
|
||||
geaendert). Genau dafuer ist der Weg gedacht: die Zeichnung ist nach dem
|
||||
Review der Stand der Dinge, nicht der Export.
|
||||
|
||||
Erkannt werden die Objekte, die tro_annotate.py mit seinen XDATA (AppID
|
||||
SPS_SKEL_TRO) gekennzeichnet hat:
|
||||
|
||||
Blockreferenz TRO_SYM_<Typ> ein TRO, Attribute ID/TYPE/ITEMS/
|
||||
CONFIDENCE/SEPARATORS (+ FB_BLOCK mit --fb)
|
||||
LWPOLYLINE "<von>-><nach>" ein Flusspfeil = eine Verbindung
|
||||
Kreis/Linien "OFFEN:<Name>" ein offener Punkt (noch kein TRO)
|
||||
|
||||
Die Koordinaten stehen doppelt in der Datei: `positionDxf` ist die
|
||||
Zeichnungskoordinate, `position` die Anlagenkoordinate. Umgerechnet wird mit
|
||||
dem Lagebezug aus <stem>_registration.json (von tro_annotate.py geschrieben);
|
||||
fehlt der, bleibt `position` leer statt geraten zu werden.
|
||||
|
||||
Aufruf ueber bin/tro_extract.bat bzw. bin/tro_extract.sh.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from collections import Counter
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import ezdxf
|
||||
|
||||
from dxf_registration import Transform
|
||||
from material_flow import env_dir
|
||||
from tro_catalog import get_tro
|
||||
|
||||
APPID = "SPS_SKEL_TRO"
|
||||
BLOCK_PREFIX = "TRO_SYM_"
|
||||
OPEN_PREFIX = "OFFEN:"
|
||||
|
||||
# XDATA-Nutzlast eines Flusspfeils: "<von>-><nach>"
|
||||
EDGE_RE = re.compile(r"^(?P<src>[^>]+)->(?P<dst>.+)$")
|
||||
|
||||
# "1x SSCC, 1x Scanner, 1x Separator" -> {"SSCC": 1, "Scanner": 1, ...}
|
||||
ITEM_RE = re.compile(r"(?P<count>\d+)\s*x\s*(?P<item>.+)")
|
||||
|
||||
|
||||
def xdata_payload(entity) -> str | None:
|
||||
"""Zweiter String der XDATA von tro_annotate, sonst None.
|
||||
|
||||
Aufbau: (1000, "tro_annotate"), (1000, <Nutzlast>). Die Nutzlast ist je
|
||||
nach Objekt die TRO-ID, "<von>-><nach>" oder "OFFEN:<Name>".
|
||||
"""
|
||||
try:
|
||||
tags = entity.get_xdata(APPID)
|
||||
except (ezdxf.DXFValueError, ezdxf.DXFTypeError, ezdxf.DXFError):
|
||||
return None
|
||||
strings = [str(value) for code, value in tags if code == 1000]
|
||||
if len(strings) < 2 or strings[0] != "tro_annotate":
|
||||
return None
|
||||
return strings[1]
|
||||
|
||||
|
||||
def parse_items(text: str) -> dict[str, int]:
|
||||
"""Bauteilliste aus dem ITEMS-Attribut zurueckgewinnen."""
|
||||
items: dict[str, int] = {}
|
||||
for part in (text or "").split(","):
|
||||
match = ITEM_RE.match(part.strip())
|
||||
if match:
|
||||
items[match.group("item").strip()] = int(match.group("count"))
|
||||
return items
|
||||
|
||||
|
||||
def attrib(ref, tag: str) -> str:
|
||||
"""Attributwert einer Blockreferenz (leerer String, wenn nicht da)."""
|
||||
try:
|
||||
return (ref.get_attrib_text(tag) or "").strip()
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def load_transform(dxf_file: Path, results: Path, warnings: list[str]) -> Transform | None:
|
||||
"""Lagebezug zu dieser Zeichnung suchen.
|
||||
|
||||
tro_annotate.py benennt die Datei nach dem CSV-Stamm (export_registration
|
||||
.json), die Zeichnung heisst aber <stamm>_annotated.dxf - daher wird das
|
||||
Suffix "_annotated" zusaetzlich ohne Endung probiert. Zuletzt entscheidet
|
||||
der Inhalt: eine Registrierung, deren `dxf_file` auf diese Zeichnung passt,
|
||||
gilt auch dann, wenn der Dateiname anders lautet.
|
||||
"""
|
||||
stem = dxf_file.stem
|
||||
namen = [stem]
|
||||
if stem.endswith("_annotated"):
|
||||
namen.append(stem[: -len("_annotated")])
|
||||
|
||||
kandidaten = [results / f"{n}_registration.json" for n in namen]
|
||||
kandidaten += [dxf_file.with_name(f"{n}_registration.json") for n in namen]
|
||||
kandidaten += sorted(results.glob("*_registration.json"))
|
||||
|
||||
for candidate in kandidaten:
|
||||
if not candidate.is_file():
|
||||
continue
|
||||
try:
|
||||
roh = json.loads(candidate.read_text(encoding="utf-8"))
|
||||
transform = Transform(**roh)
|
||||
except (OSError, ValueError, TypeError) as exc:
|
||||
warnings.append(f"{candidate.name} nicht lesbar ({exc})")
|
||||
continue
|
||||
# Bei den aus dem Glob gefundenen Dateien pruefen, ob sie ueberhaupt
|
||||
# zu dieser Zeichnung gehoeren - sonst waere der Bezug frei erfunden.
|
||||
passt = candidate.stem.split("_registration")[0] in namen
|
||||
if not passt and Path(roh.get("dxf_file", "")).stem not in (stem, *namen):
|
||||
continue
|
||||
return transform
|
||||
|
||||
warnings.append(
|
||||
f"kein Lagebezug gefunden (gesucht: "
|
||||
f"{', '.join(n + '_registration.json' for n in namen)}) - "
|
||||
f"'position' bleibt leer, 'positionDxf' ist trotzdem gefuellt"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def extract(doc, transform: Transform | None, warnings: list[str]) -> dict:
|
||||
"""TROs, Verbindungen und offene Punkte aus dem Modelbereich lesen."""
|
||||
msp = doc.modelspace()
|
||||
tros: list[dict] = []
|
||||
edges: list[dict] = []
|
||||
open_points: list[dict] = []
|
||||
seen_edges: set[tuple[str, str]] = set()
|
||||
|
||||
for entity in msp:
|
||||
payload = xdata_payload(entity)
|
||||
if payload is None:
|
||||
continue
|
||||
|
||||
if entity.dxftype() == "INSERT" and entity.dxf.name.startswith(BLOCK_PREFIX):
|
||||
tro_id = attrib(entity, "ID") or payload
|
||||
type_name = attrib(entity, "TYPE") or entity.dxf.name[len(BLOCK_PREFIX):]
|
||||
insert = entity.dxf.insert
|
||||
eintrag = {
|
||||
"id": tro_id,
|
||||
"type": type_name,
|
||||
"items": parse_items(attrib(entity, "ITEMS")),
|
||||
"confidence": attrib(entity, "CONFIDENCE"),
|
||||
"separators": [s.strip() for s in attrib(entity, "SEPARATORS").split(",")
|
||||
if s.strip()],
|
||||
"positionDxf": {"x": round(insert.x, 2), "y": round(insert.y, 2),
|
||||
"z": round(insert.z, 2)},
|
||||
"layer": entity.dxf.layer,
|
||||
"block": entity.dxf.name,
|
||||
}
|
||||
# FB-Baustein: als Attribut nur vorhanden, wenn mit --fb annotiert
|
||||
# wurde. Sonst aus dem Katalog nachgeschlagen und als solches
|
||||
# gekennzeichnet - er steht dann nicht in der Zeichnung.
|
||||
fb = attrib(entity, "FB_BLOCK")
|
||||
if fb and fb != "-":
|
||||
eintrag["fbType"] = fb
|
||||
eintrag["fbTypeFrom"] = "dxf"
|
||||
else:
|
||||
definition = get_tro(type_name)
|
||||
if definition:
|
||||
eintrag["fbType"] = definition.get_fb_block()
|
||||
eintrag["fbTypeFrom"] = "tro_catalog"
|
||||
else:
|
||||
eintrag["fbType"] = None
|
||||
eintrag["fbTypeFrom"] = "unbekannter Typ"
|
||||
warnings.append(
|
||||
f"{tro_id}: Typ '{type_name}' steht nicht im TRO-Katalog"
|
||||
)
|
||||
if transform is not None:
|
||||
x, y = transform.to_csv(insert.x, insert.y)
|
||||
eintrag["position"] = {"x": round(x, 2), "y": round(y, 2)}
|
||||
tros.append(eintrag)
|
||||
continue
|
||||
|
||||
if payload.startswith(OPEN_PREFIX):
|
||||
name = payload[len(OPEN_PREFIX):]
|
||||
if entity.dxftype() != "CIRCLE":
|
||||
continue # Kreis, Kreuz und Text tragen dieselbe Nutzlast
|
||||
center = entity.dxf.center
|
||||
punkt = {"name": name,
|
||||
"positionDxf": {"x": round(center.x, 2), "y": round(center.y, 2)}}
|
||||
if transform is not None:
|
||||
x, y = transform.to_csv(center.x, center.y)
|
||||
punkt["position"] = {"x": round(x, 2), "y": round(y, 2)}
|
||||
open_points.append(punkt)
|
||||
continue
|
||||
|
||||
match = EDGE_RE.match(payload)
|
||||
if match:
|
||||
# Schaft und Spitze eines Pfeils tragen dieselbe Nutzlast
|
||||
pair = (match.group("src"), match.group("dst"))
|
||||
if pair not in seen_edges:
|
||||
seen_edges.add(pair)
|
||||
edges.append({"from": pair[0], "to": pair[1]})
|
||||
|
||||
tros.sort(key=lambda t: t["id"])
|
||||
edges.sort(key=lambda e: (e["from"], e["to"]))
|
||||
open_points.sort(key=lambda p: p["name"])
|
||||
|
||||
# Vorgaenger/Nachfolger je TRO - das ist die Frage, die man an so eine
|
||||
# Datei stellt ("was kommt vor diesem TRO, was danach").
|
||||
bekannt = {t["id"] for t in tros}
|
||||
for tro in tros:
|
||||
tro["predecessors"] = sorted(e["from"] for e in edges if e["to"] == tro["id"])
|
||||
tro["successors"] = sorted(e["to"] for e in edges if e["from"] == tro["id"])
|
||||
for edge in edges:
|
||||
for seite in ("from", "to"):
|
||||
if edge[seite] not in bekannt:
|
||||
warnings.append(
|
||||
f"Verbindung {edge['from']} -> {edge['to']}: '{edge[seite]}' "
|
||||
f"ist kein TRO in dieser Zeichnung"
|
||||
)
|
||||
return {"tros": tros, "connections": edges, "openPoints": open_points}
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
args = parse_args(argv)
|
||||
warnings: list[str] = []
|
||||
results = env_dir("SKEL_RESULTS", "results")
|
||||
|
||||
dxf_file = Path(args.dxf)
|
||||
if not dxf_file.is_absolute() and dxf_file.parent == Path("."):
|
||||
dxf_file = results / args.dxf
|
||||
if not dxf_file.is_file():
|
||||
print(f"FEHLER: Zeichnung nicht gefunden: {dxf_file}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
try:
|
||||
doc = ezdxf.readfile(str(dxf_file))
|
||||
except (OSError, ezdxf.DXFError) as exc:
|
||||
print(f"FEHLER: {dxf_file} nicht lesbar: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
transform = load_transform(dxf_file, results, warnings)
|
||||
daten = extract(doc, transform, warnings)
|
||||
|
||||
if not daten["tros"]:
|
||||
print(f"FEHLER: keine TRO-Marker in {dxf_file} gefunden. Wurde sie mit "
|
||||
f"tro_annotate.py erzeugt?", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
kopf = {
|
||||
"schema": "sps_skel-tro-extract-v1",
|
||||
"source": dxf_file.name,
|
||||
"extracted": datetime.now().strftime("%Y-%m-%d %H:%M"),
|
||||
"note": "Aus der Zeichnung gelesen, nicht aus dem CSV-Export - "
|
||||
"Aenderungen aus BricsCAD sind enthalten.",
|
||||
}
|
||||
if transform is not None:
|
||||
kopf["transform"] = {"dx": round(transform.dx, 3), "dy": round(transform.dy, 3),
|
||||
"rotation": transform.rotation,
|
||||
"note": "Anlagenkoordinate = Zeichnung + (dx, dy)"}
|
||||
|
||||
out_file = results / (args.out or f"{dxf_file.stem}_tro.json")
|
||||
out_file.write_text(
|
||||
json.dumps({**kopf, **daten}, indent=2, ensure_ascii=False) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
typen = Counter(t["type"] for t in daten["tros"])
|
||||
print("")
|
||||
print("================================================================")
|
||||
print("TRO-EXTRAKT")
|
||||
print("================================================================")
|
||||
print(f"Zeichnung = {dxf_file}")
|
||||
print(f"Lagebezug = "
|
||||
+ (transform.describe() if transform else "- (nur DXF-Koordinaten)"))
|
||||
print(f"TROs = {len(daten['tros'])} "
|
||||
f"({', '.join(f'{k}: {v}' for k, v in sorted(typen.items()))})")
|
||||
print(f"Verbindungen = {len(daten['connections'])}")
|
||||
print(f"Offene Punkte = {len(daten['openPoints'])}")
|
||||
print(f"JSON = {out_file}")
|
||||
print("================================================================")
|
||||
if warnings:
|
||||
print("")
|
||||
print(f"Hinweise ({len(warnings)}):")
|
||||
for warning in warnings:
|
||||
print(f" ! {warning}")
|
||||
print("")
|
||||
return 0
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="tro_extract",
|
||||
description="Liest die von tro_annotate.py gesetzten TRO-Marker aus "
|
||||
"einer Zeichnung zurueck und schreibt sie als JSON.",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="Beispiele:\n"
|
||||
" tro_extract.bat\n"
|
||||
" tro_extract.bat --dxf export_annotated.dxf\n"
|
||||
" tro_extract.bat --dxf export_annotated.dxf --out tros.json\n"
|
||||
"\n"
|
||||
"Exit-Codes:\n"
|
||||
" 0 ok\n"
|
||||
" 1 Eingabe- oder Aufruffehler\n"
|
||||
" 2 keine TRO-Marker in der Zeichnung\n",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dxf",
|
||||
default="export_annotated.dxf",
|
||||
metavar="NAME",
|
||||
help="Annotierte Zeichnung in %%SKEL_RESULTS%% (oder ein vollstaendiger "
|
||||
"Pfad). Standard: %(default)s",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--out",
|
||||
metavar="NAME",
|
||||
help="Name der JSON-Datei in %%SKEL_RESULTS%%. "
|
||||
"Standard: <Zeichnung>_tro.json",
|
||||
)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
+266
-20
@@ -58,6 +58,7 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import math
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
@@ -69,6 +70,8 @@ from material_flow import (
|
||||
EDGE_UNRESOLVED,
|
||||
LANE_LEFT,
|
||||
LANE_RIGHT,
|
||||
ROTATION_CCW,
|
||||
ROTATION_CW,
|
||||
UNASSIGNED,
|
||||
Element,
|
||||
Graph,
|
||||
@@ -91,6 +94,14 @@ from tro_catalog import (
|
||||
get_tro,
|
||||
mermaid_classdefs,
|
||||
)
|
||||
from tro_overrides import (
|
||||
Overrides,
|
||||
apply_connections,
|
||||
apply_merges,
|
||||
apply_overrides,
|
||||
apply_splits,
|
||||
load_overrides,
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Konstanten
|
||||
@@ -169,9 +180,13 @@ class Tro:
|
||||
class Analysis:
|
||||
tros: list[Tro] = field(default_factory=list)
|
||||
edges: list[tuple[str, str]] = field(default_factory=list)
|
||||
# (von, nach) -> Kantenart (transfer / umlauf / weiche / unbestimmt / normal)
|
||||
edge_kinds: dict[tuple[str, str], str] = field(default_factory=dict)
|
||||
isolated: list[Tro] = field(default_factory=list)
|
||||
unknown_types: list[str] = field(default_factory=list)
|
||||
findings: list[str] = field(default_factory=list)
|
||||
# Manuelle Korrekturen aus cfg/tro_overrides.ini (Typkorrekturen, offene Punkte)
|
||||
overrides: Overrides = field(default_factory=Overrides)
|
||||
|
||||
def by_id(self, tro_id: str) -> Tro | None:
|
||||
for tro in self.tros:
|
||||
@@ -228,7 +243,12 @@ def _switch_exits(hosts: list[str], graph: Graph) -> list[str]:
|
||||
)
|
||||
|
||||
|
||||
def derive_tros(graph: Graph, elements: list[Element], findings: list[str]) -> list[Tro]:
|
||||
def derive_tros(
|
||||
graph: Graph,
|
||||
elements: list[Element],
|
||||
findings: list[str],
|
||||
overrides: Overrides | None = None,
|
||||
) -> list[Tro]:
|
||||
"""TRO-Liste aus den Separatoren und ihren angeschlossenen Objekten bilden."""
|
||||
separators = sorted(
|
||||
(e for e in elements if e.kind == "Separator"), key=lambda e: e.teile_id
|
||||
@@ -376,12 +396,41 @@ def derive_tros(graph: Graph, elements: list[Element], findings: list[str]) -> l
|
||||
tro.reason = f"{tro.reason}; {len(exits)} abgehende Wege -> Weiche"
|
||||
tro.confidence = "niedrig"
|
||||
|
||||
# 4b) Manuell ergaenzte Uebergabestellen (cfg/tro_overrides.ini, [.split.]).
|
||||
# Vor der Nummernvergabe, damit die neuen TROs in derselben Reihenfolge
|
||||
# eine Nummer bekommen wie die abgeleiteten.
|
||||
if overrides is not None and overrides.splits:
|
||||
def _neuer_tro(spec, hosts, label):
|
||||
return Tro(
|
||||
tro_id="",
|
||||
type_name=spec.type_name,
|
||||
label=label,
|
||||
hosts=hosts,
|
||||
separators=list(spec.separators),
|
||||
scanners=list(spec.scanners),
|
||||
reason=spec.reason or "manuell ergaenzte Uebergabestelle",
|
||||
confidence=spec.confidence,
|
||||
)
|
||||
|
||||
apply_splits(tros, overrides, _neuer_tro)
|
||||
|
||||
# 4c) Zusammenfassungen - nach den Splits, damit auch ein frisch
|
||||
# herausgeloester TRO Teil einer Zusammenfassung sein kann.
|
||||
if overrides is not None and overrides.merges:
|
||||
apply_merges(tros, overrides)
|
||||
|
||||
# 5) Stabile, laufende Nummern in Reihenfolge der Host-Knoten
|
||||
tros.sort(key=lambda t: (t.hosts[0], t.separators[0] if t.separators else ""))
|
||||
width = max(2, len(str(len(tros))))
|
||||
for index, tro in enumerate(tros, start=1):
|
||||
tro.tro_id = f"TRO{index:0{width}d}"
|
||||
|
||||
# 5b) Manuelle Korrekturen aus cfg/tro_overrides.ini. Sie greifen erst hier,
|
||||
# weil sie ueber die TRO-ID adressiert sind, und noch vor Schritt 6, damit
|
||||
# ein manuell gesetzter Typ den SSCC-Hinweis nicht mehr ausloest.
|
||||
if overrides is not None:
|
||||
apply_overrides(tros, overrides)
|
||||
|
||||
# 6) Scanner am Separator: 1Sep_SSCC laesst sich mechanisch nicht erkennen
|
||||
for tro in tros:
|
||||
if tro.type_name == "1Sep" and tro.scanners:
|
||||
@@ -394,53 +443,129 @@ def derive_tros(graph: Graph, elements: list[Element], findings: list[str]) -> l
|
||||
return tros
|
||||
|
||||
|
||||
def link_tros(graph: Graph, tros: list[Tro]) -> list[tuple[str, str]]:
|
||||
def _tro_edge_kind(edge: Edge) -> str:
|
||||
"""Materialkante -> Kantenart des TRO-Flusses (fuer Einfaerbung)."""
|
||||
if edge.note == "Weiche":
|
||||
return "weiche"
|
||||
if edge.kind == EDGE_CIRCLE:
|
||||
return "umlauf"
|
||||
if edge.kind == EDGE_UNRESOLVED:
|
||||
return "unbestimmt"
|
||||
if edge.note in ("Einschleusung", "Ausschleusung"):
|
||||
return "transfer"
|
||||
return "normal"
|
||||
|
||||
|
||||
def _bahn_richtung(node) -> tuple[float, float] | None:
|
||||
"""Foerderrichtung einer Kreisel-Bahn als Einheitsvektor.
|
||||
|
||||
Der Kreisel ist eine geschlossene Schleife: auf der einen Bahn laeuft das
|
||||
Material hin, auf der anderen zurueck. Welche Richtung das ist, ergibt sich
|
||||
aus der Laengsachse ("Drehung") und dem Umlaufsinn ("Drehrichtung"):
|
||||
|
||||
UZS (im Uhrzeigersinn) Bahn R entgegen der Achse, Bahn L mit ihr
|
||||
GUZ (gegen den UZS) umgekehrt
|
||||
|
||||
Rueckgabe None, wenn eines der beiden Merkmale fehlt - dann bleibt es bei
|
||||
der ungerichteten "gleiche Bahn"-Notiz.
|
||||
"""
|
||||
element = node.element
|
||||
drehung = _as_float(_merkmal(element.merkmale, "Drehung"))
|
||||
umlauf = element.rotation
|
||||
if drehung is None or umlauf not in (ROTATION_CW, ROTATION_CCW):
|
||||
return None
|
||||
rad = math.radians(drehung)
|
||||
achse = (math.cos(rad), math.sin(rad))
|
||||
mit_achse = (node.lane == LANE_LEFT) == (umlauf == ROTATION_CW)
|
||||
return achse if mit_achse else (-achse[0], -achse[1])
|
||||
|
||||
|
||||
def link_tros(
|
||||
graph: Graph, tros: list[Tro]
|
||||
) -> tuple[list[tuple[str, str]], dict[tuple[str, str], str]]:
|
||||
"""
|
||||
TROs verknuepfen.
|
||||
|
||||
Der Materialfluss laeuft von Uebergabestelle zu Uebergabestelle, ggf. durch
|
||||
passive Zwischenknoten (Strecken/Bahnen ohne eigenen TRO). Solche Knoten
|
||||
werden daher durchlaufen ("kontrahiert"), belegte Knoten beenden den Pfad.
|
||||
Jede TRO-Kante bekommt zusaetzlich die Art der *ankommenden* Materialkante
|
||||
(transfer / umlauf / weiche / unbestimmt / normal).
|
||||
"""
|
||||
owners: dict[str, list[str]] = {}
|
||||
for tro in tros:
|
||||
for host in tro.hosts:
|
||||
owners.setdefault(host, []).append(tro.tro_id)
|
||||
|
||||
forward: dict[str, list[str]] = {}
|
||||
forward: dict[str, list[tuple[str, str]]] = {}
|
||||
for edge in graph.edges:
|
||||
forward.setdefault(edge.src, []).append(edge.dst)
|
||||
kind = _tro_edge_kind(edge)
|
||||
forward.setdefault(edge.src, []).append((edge.dst, kind))
|
||||
if edge.kind == EDGE_UNRESOLVED:
|
||||
# unbestimmte Richtung: in beide Richtungen begehbar
|
||||
forward.setdefault(edge.dst, []).append(edge.src)
|
||||
forward.setdefault(edge.dst, []).append((edge.src, kind))
|
||||
|
||||
edges: set[tuple[str, str]] = set()
|
||||
edge_kinds: dict[tuple[str, str], str] = {}
|
||||
for tro in tros:
|
||||
seen = set(tro.hosts)
|
||||
queue = [n for host in tro.hosts for n in forward.get(host, [])]
|
||||
queue = [(nxt, k) for host in tro.hosts for (nxt, k) in forward.get(host, [])]
|
||||
while queue:
|
||||
node = queue.pop()
|
||||
node, arriving = queue.pop()
|
||||
if node in seen:
|
||||
continue
|
||||
seen.add(node)
|
||||
if node in owners:
|
||||
for other in owners[node]:
|
||||
if other != tro.tro_id:
|
||||
edges.add((tro.tro_id, other))
|
||||
pair = (tro.tro_id, other)
|
||||
edges.add(pair)
|
||||
edge_kinds.setdefault(pair, arriving)
|
||||
continue
|
||||
queue.extend(forward.get(node, []))
|
||||
|
||||
# gleicher Host = physisch dieselbe Strecke/Bahn
|
||||
# Mehrere TROs auf derselben Kreisel-Bahn liegen HINTEREINANDER, nicht
|
||||
# nebeneinander: das Material laeuft die Bahn in Foerderrichtung ab. Sie
|
||||
# werden daher der Reihe nach verkettet statt nur als "gleiche Bahn"
|
||||
# markiert - sonst fehlt z. B. die Kante von der einen Sperre zur naechsten.
|
||||
verkettet: set[str] = set()
|
||||
for host, ids in owners.items():
|
||||
if len(ids) < 2:
|
||||
continue
|
||||
node = graph.nodes.get(host)
|
||||
if node is None or node.kind != "Kreisel" or not node.lane:
|
||||
continue
|
||||
richtung = _bahn_richtung(node)
|
||||
if richtung is None:
|
||||
continue
|
||||
auf_bahn = [t for t in tros if t.tro_id in ids and t.position]
|
||||
if len(auf_bahn) < 2:
|
||||
continue
|
||||
# Projektion auf die Foerderrichtung: kleinster Wert kommt zuerst
|
||||
auf_bahn.sort(key=lambda t: t.position[0] * richtung[0]
|
||||
+ t.position[1] * richtung[1])
|
||||
for vorher, nachher in zip(auf_bahn, auf_bahn[1:]):
|
||||
pair = (vorher.tro_id, nachher.tro_id)
|
||||
edges.add(pair)
|
||||
edge_kinds.setdefault(pair, "bahn")
|
||||
verkettet.update(pair)
|
||||
|
||||
# gleicher Host = physisch dieselbe Strecke/Bahn. Verkettete Bahnen sind
|
||||
# oben schon gerichtet verbunden und brauchen die ungerichtete Notiz nicht.
|
||||
for host, ids in owners.items():
|
||||
for tro_id in ids:
|
||||
tro = next(t for t in tros if t.tro_id == tro_id)
|
||||
tro.colocated = sorted(set(tro.colocated) | {o for o in ids if o != tro_id})
|
||||
if tro_id in verkettet:
|
||||
continue
|
||||
tro.colocated = sorted(
|
||||
set(tro.colocated) | {o for o in ids if o != tro_id and o not in verkettet}
|
||||
)
|
||||
|
||||
for tro in tros:
|
||||
tro.successors = sorted(dst for src, dst in edges if src == tro.tro_id)
|
||||
tro.predecessors = sorted(src for src, dst in edges if dst == tro.tro_id)
|
||||
|
||||
return sorted(edges)
|
||||
return sorted(edges), edge_kinds
|
||||
|
||||
|
||||
def _centroid(
|
||||
@@ -494,12 +619,36 @@ def locate_tros(tros: list[Tro], elements: list[Element], graph: Graph) -> None:
|
||||
tro.position_from = source if tro.position else "keine Position"
|
||||
|
||||
|
||||
def analyse_tros(graph: Graph, elements: list[Element]) -> Analysis:
|
||||
def analyse_tros(
|
||||
graph: Graph, elements: list[Element], overrides: Overrides | None = None
|
||||
) -> Analysis:
|
||||
"""TROs ermitteln, verknuepfen, verorten und gegen die Typdefinition pruefen."""
|
||||
analysis = Analysis()
|
||||
analysis.tros = derive_tros(graph, elements, analysis.findings)
|
||||
analysis.edges = link_tros(graph, analysis.tros)
|
||||
analysis.overrides = overrides if overrides is not None else Overrides()
|
||||
analysis.tros = derive_tros(graph, elements, analysis.findings, analysis.overrides)
|
||||
# Verorten vor dem Verknuepfen: die Reihenfolge mehrerer TROs auf einer
|
||||
# Kreisel-Bahn wird ueber ihre Koordinate bestimmt.
|
||||
locate_tros(analysis.tros, elements, graph)
|
||||
analysis.edges, analysis.edge_kinds = link_tros(graph, analysis.tros)
|
||||
|
||||
# Vor Ort aufgenommene Topologie schlaegt die abgeleitete. Die Differenz
|
||||
# wird protokolliert, damit sichtbar bleibt, was die Ableitung falsch hatte.
|
||||
if analysis.overrides.connections:
|
||||
abgeleitet = set(analysis.edges)
|
||||
analysis.edges, analysis.edge_kinds = apply_connections(
|
||||
analysis.tros, analysis.overrides
|
||||
)
|
||||
gesetzt = set(analysis.edges)
|
||||
for src, dst in sorted(abgeleitet - gesetzt):
|
||||
analysis.findings.append(
|
||||
f"abgeleitete Verbindung {src} -> {dst} entfaellt - steht nicht "
|
||||
f"in der gesetzten Topologie"
|
||||
)
|
||||
for src, dst in sorted(gesetzt - abgeleitet):
|
||||
analysis.findings.append(
|
||||
f"Verbindung {src} -> {dst} nur gesetzt, aus dem Layout nicht "
|
||||
f"ableitbar"
|
||||
)
|
||||
|
||||
for tro in analysis.tros:
|
||||
definition = tro.definition()
|
||||
@@ -552,6 +701,21 @@ def _legend_pos(analysis: Analysis) -> tuple[float, float]:
|
||||
return (min(xs) - LEGEND_MARGIN, min(ys) - LEGEND_MARGIN)
|
||||
|
||||
|
||||
# Kantenstil je Art (an material_flow.py angelehnt: Umlauf hellblau gestrichelt,
|
||||
# Weiche orange). "transfer"/"normal" bleiben der durchgezogene Standardfluss.
|
||||
TRO_EDGE_STYLE = {
|
||||
"umlauf": 'color="#8ea9db", style=dashed, tooltip="Kreisel-Umlauf"',
|
||||
"weiche": 'color="#cc8800", penwidth=1.8, xlabel="Weiche", fontcolor="#cc8800", '
|
||||
'tooltip="Weiche (Kreisel-Uebergang)"',
|
||||
"unbestimmt": 'color="#bf8f00", style=dashed, dir=both, tooltip="Richtung unbestimmt"',
|
||||
"transfer": 'tooltip="Uebergabe (Ein-/Ausschleusung)"',
|
||||
}
|
||||
|
||||
|
||||
def _tro_edge_attrs(kind: str | None) -> str:
|
||||
return TRO_EDGE_STYLE.get(kind or "normal", "")
|
||||
|
||||
|
||||
def render_dot(analysis: Analysis, source: str, use_coords: bool = False) -> str:
|
||||
"""
|
||||
Gerichtetes Flussdiagramm der TROs als Graphviz-Quelle.
|
||||
@@ -601,7 +765,7 @@ def render_dot(analysis: Analysis, source: str, use_coords: bool = False) -> str
|
||||
add("")
|
||||
|
||||
for src, dst in analysis.edges:
|
||||
add(f' "{src}" -> "{dst}" [];')
|
||||
add(f' "{src}" -> "{dst}" [{_tro_edge_attrs(analysis.edge_kinds.get((src, dst)))}];')
|
||||
|
||||
seen: set[frozenset] = set()
|
||||
for tro in analysis.tros:
|
||||
@@ -624,9 +788,13 @@ def render_dot(analysis: Analysis, source: str, use_coords: bool = False) -> str
|
||||
)
|
||||
legend_label = ('<<table border="0" cellborder="1" cellspacing="0" cellpadding="3">'
|
||||
+ rows
|
||||
+ '<tr><td align="left">durchgezogen</td>'
|
||||
'<td align="left">Materialfluss</td></tr>'
|
||||
'<tr><td align="left">gepunktet</td>'
|
||||
+ '<tr><td align="left"><font color="#2f5597">durchgezogen</font></td>'
|
||||
'<td align="left">Uebergabe / Ein-Ausschleusung</td></tr>'
|
||||
'<tr><td align="left"><font color="#8ea9db">blau gestrichelt</font></td>'
|
||||
'<td align="left">Kreisel-Umlauf</td></tr>'
|
||||
'<tr><td align="left"><font color="#cc8800">orange</font></td>'
|
||||
'<td align="left">Weiche (Kreisel-Uebergang)</td></tr>'
|
||||
'<tr><td align="left">grau gepunktet</td>'
|
||||
'<td align="left">gleiche Bahn / Strecke</td></tr>'
|
||||
"</table>>")
|
||||
if use_coords:
|
||||
@@ -787,6 +955,11 @@ def render_doc(
|
||||
add(f"| TRO-Verbindungen | {len(analysis.edges)} |")
|
||||
add(f"| Nicht verbundene TROs | {len(analysis.isolated)} |")
|
||||
add(f"| Hinweise | {len(analysis.findings)} |")
|
||||
if analysis.overrides.applied:
|
||||
add(f"| Manuelle Typkorrekturen | {len(analysis.overrides.applied)} |")
|
||||
if analysis.overrides.open_points:
|
||||
add(f"| Offene Punkte (noch kein TRO) | "
|
||||
f"{len(analysis.overrides.open_points)} |")
|
||||
add("")
|
||||
add("| Typ | FB-Baustein | Anzahl hier | Bauteile je TRO | Farbgruppe |")
|
||||
add("|---|---|---:|---|---|")
|
||||
@@ -873,7 +1046,56 @@ def render_doc(
|
||||
add("_Keine._")
|
||||
add("")
|
||||
|
||||
add("## 6. Ableitungsregeln und Typdefinition")
|
||||
add("## 6. Manuelle Korrekturen und offene Punkte")
|
||||
add("")
|
||||
overrides = analysis.overrides
|
||||
if not overrides and not overrides.warnings:
|
||||
add("_Keine._ Alles unten Stehende ist rein aus dem Layout abgeleitet.")
|
||||
add("")
|
||||
else:
|
||||
add(f"Quelle: `{overrides.source}`" if overrides.source
|
||||
else "_Keine Override-Datei gefunden._")
|
||||
add("")
|
||||
|
||||
if overrides.applied:
|
||||
add("### 6.1 Angewandte Typkorrekturen")
|
||||
add("")
|
||||
add("Diese Typen stammen **nicht** aus dem Layout, sondern aus der "
|
||||
"Begehung bzw. dem Review - im Layout sind sie nicht erkennbar.")
|
||||
add("")
|
||||
add("| Korrektur | Begruendung |")
|
||||
add("|---|---|")
|
||||
for entry in overrides.applied:
|
||||
head, _, tail = entry.partition(" (")
|
||||
add(f"| `{head}` | {tail[:-1] if tail.endswith(')') else tail} |")
|
||||
add("")
|
||||
|
||||
if overrides.open_points:
|
||||
add("### 6.2 Offene Punkte - noch kein TRO")
|
||||
add("")
|
||||
add("Im Review gemeldete Stellen. Die TRO-Struktur ist hier "
|
||||
"**bewusst unveraendert**; die Punkte sind nur markiert (auch in der "
|
||||
"annotierten Zeichnung, Layer `TRO_OPENPOINT`), damit sie in BricsCAD "
|
||||
"geprueft werden koennen.")
|
||||
add("")
|
||||
add("| Punkt | X [mm] | Y [mm] | Z [mm] | erwartet | heute Teil von | Anmerkung |")
|
||||
add("|---|---:|---:|---:|---|---|---|")
|
||||
for point in overrides.open_points:
|
||||
z_text = f"{point.z:.0f}" if point.z is not None else "-"
|
||||
expect = f"`{point.expect}`" if point.expect else "-"
|
||||
owner = f"`{point.belongs_to}`" if point.belongs_to else "-"
|
||||
add(f"| {point.name} | {point.x:.0f} | {point.y:.0f} | {z_text} "
|
||||
f"| {expect} | {owner} | {point.note or '-'} |")
|
||||
add("")
|
||||
|
||||
if overrides.warnings:
|
||||
add("### 6.3 Probleme mit der Override-Datei")
|
||||
add("")
|
||||
for warning in overrides.warnings:
|
||||
add(f"- {warning}")
|
||||
add("")
|
||||
|
||||
add("## 7. Ableitungsregeln und Typdefinition")
|
||||
add("")
|
||||
add("Ein TRO ist die Steuerungslogik **einer Uebergabestelle**. Ausgangspunkt "
|
||||
"ist der Separator und das, was an ihm haengt (Host-Objekt, Scanner).")
|
||||
@@ -974,6 +1196,29 @@ def report(
|
||||
print("FEHLER: TRO-Typen ohne Eintrag in TRO_CATALOG: "
|
||||
+ ", ".join(analysis.unknown_types))
|
||||
|
||||
overrides = analysis.overrides
|
||||
if overrides.applied:
|
||||
print("")
|
||||
print(f"Manuelle Typkorrekturen ({len(overrides.applied)}) aus "
|
||||
f"{overrides.source}:")
|
||||
for entry in overrides.applied:
|
||||
print(f" * {entry}")
|
||||
|
||||
if overrides.open_points:
|
||||
print("")
|
||||
print(f"Offene Punkte ({len(overrides.open_points)}) - nur markiert, "
|
||||
f"TRO-Struktur unveraendert:")
|
||||
for point in overrides.open_points:
|
||||
expect = f" erwartet {point.expect}" if point.expect else ""
|
||||
owner = f", heute Teil von {point.belongs_to}" if point.belongs_to else ""
|
||||
print(f" o {point.name} bei {point.describe_position()}{expect}{owner}")
|
||||
|
||||
if overrides.warnings:
|
||||
print("")
|
||||
print(f"Probleme mit {overrides.source} ({len(overrides.warnings)}):")
|
||||
for warning in overrides.warnings:
|
||||
print(f" ! {warning}")
|
||||
|
||||
if analysis.findings:
|
||||
print("")
|
||||
print(f"Hinweise ({len(analysis.findings)}):")
|
||||
@@ -1071,7 +1316,8 @@ def main(argv: list[str] | None = None) -> int:
|
||||
print(f"FEHLER: {csv_file} enthaelt keine Flussobjekte.", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
analysis = analyse_tros(graph, elements)
|
||||
overrides = load_overrides(csv_file.name, env_dir("SKEL_CFG", "cfg"))
|
||||
analysis = analyse_tros(graph, elements, overrides)
|
||||
if not analysis.tros:
|
||||
print(f"FEHLER: {csv_file} enthaelt keine Separatoren - keine TROs "
|
||||
f"ableitbar.", file=sys.stderr)
|
||||
|
||||
@@ -0,0 +1,492 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tro_overrides.py - manuelle Korrekturen an der abgeleiteten TRO-Liste.
|
||||
|
||||
`tro_flow.py` leitet die TROs allein aus dem mechanischen Layout (CSV-Export)
|
||||
ab. Manches steht dort aber nicht drin: eine Weiche, die im Export fehlt, ein
|
||||
Scanner, der den Typ auf `1Sep_SSCC` hebt, oder eine Stelle, die vor Ort als
|
||||
eigener TRO erkannt wurde. Solche Erkenntnisse kommen aus der Begehung bzw.
|
||||
aus dem Review der erzeugten Diagramme.
|
||||
|
||||
Damit sie den naechsten Lauf ueberleben, stehen sie in einer INI-Datei
|
||||
(`%SKEL_CFG%/tro_overrides.ini`) statt in den erzeugten Dateien. `tro_flow.py`
|
||||
und `tro_annotate.py` lesen sie und wenden sie nach der Ableitung an; die Doku
|
||||
weist jede angewandte Korrektur getrennt aus, damit abgeleitet und behauptet
|
||||
unterscheidbar bleiben.
|
||||
|
||||
Aufbau der INI (Sektionsnamen mit dem CSV-Dateinamen als Praefix, damit
|
||||
mehrere Anlagen in einer Datei stehen koennen):
|
||||
|
||||
[<csv>.tro.<TRO-ID>] Korrektur an einem abgeleiteten TRO
|
||||
type = 1Sep1Swi neuer Katalogtyp
|
||||
reason = ... Begruendung (kommt in die Doku)
|
||||
confidence = bestaetigt Vertrauensangabe (Default: bestaetigt)
|
||||
|
||||
[<csv>.openpoint.<Name>] offener Punkt - noch KEIN TRO
|
||||
x = 529.95 Anlagenkoordinate in mm
|
||||
y = -3895.27
|
||||
z = 1468
|
||||
expect = 1Sep1Swi hier erwarteter TRO-Typ
|
||||
belongs_to = TRO10 TRO, der das Bauteil heute enthaelt
|
||||
note = ... Erlaeuterung
|
||||
|
||||
Offene Punkte aendern die TRO-Struktur ausdruecklich **nicht**. Sie werden nur
|
||||
in der Doku und in der annotierten Zeichnung markiert, damit sie in BricsCAD
|
||||
geprueft werden koennen, bevor daraus ein TRO wird.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import configparser
|
||||
import os
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
from tro_catalog import get_tro
|
||||
|
||||
OVERRIDE_FILE = "tro_overrides.ini"
|
||||
|
||||
# Vertrauensangabe fuer manuell gesetzte Typen. Bewusst ein eigener Wert - so
|
||||
# ist in der Doku sichtbar, dass der Typ nicht aus dem Layout stammt.
|
||||
DEFAULT_CONFIDENCE = "bestaetigt"
|
||||
|
||||
|
||||
@dataclass
|
||||
class TroOverride:
|
||||
"""Korrektur an einem abgeleiteten TRO.
|
||||
|
||||
Adressiert entweder ueber die TRO-ID (`TRO03`) oder - stabiler - ueber die
|
||||
Nummer eines seiner Separatoren (`SEP0011`). Die TRO-IDs sind laufende
|
||||
Nummern eines Laufs und verschieben sich, sobald TROs dazukommen oder
|
||||
wegfallen; die Separator-Nummer aus dem CSV-Export tut das nicht.
|
||||
"""
|
||||
|
||||
key: str
|
||||
by_separator: bool = False
|
||||
type_name: str = ""
|
||||
reason: str = ""
|
||||
confidence: str = ""
|
||||
|
||||
def matches(self, tro) -> bool:
|
||||
if self.by_separator:
|
||||
return self.key in tro.separators
|
||||
return self.key == tro.tro_id
|
||||
|
||||
|
||||
@dataclass
|
||||
class SplitSpec:
|
||||
"""Ein neuer TRO, herausgeloest aus einem bereits abgeleiteten.
|
||||
|
||||
Fuer Uebergabestellen, die die Ableitung nicht als eigenstaendig erkennt,
|
||||
weil die "Zuordnung" des Separators auf ein Transportobjekt zeigt (Strecke,
|
||||
Gefaellestrecke) statt auf die Kreisel-Bahn, an der er tatsaechlich
|
||||
schaltet. Die genannten Separatoren/Scanner werden ihrem bisherigen TRO
|
||||
entnommen und bilden einen neuen.
|
||||
"""
|
||||
|
||||
name: str
|
||||
type_name: str
|
||||
separators: list[str] = field(default_factory=list)
|
||||
scanners: list[str] = field(default_factory=list)
|
||||
host: str = ""
|
||||
label: str = ""
|
||||
reason: str = ""
|
||||
confidence: str = DEFAULT_CONFIDENCE
|
||||
|
||||
|
||||
@dataclass
|
||||
class ConnectionSpec:
|
||||
"""Eine vor Ort bestaetigte Verbindung zwischen zwei TROs."""
|
||||
|
||||
src: str
|
||||
dst: str
|
||||
kind: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class MergeSpec:
|
||||
"""Mehrere abgeleitete TROs zu einem Steuerobjekt zusammenfassen.
|
||||
|
||||
Fuer Stellen, die mechanisch aus mehreren Bauteilgruppen bestehen,
|
||||
steuerungstechnisch aber eine einzige Uebergabestelle sind - etwa zwei
|
||||
Sperren beiderseits eines Kreisel-Beruehrpunkts. Adressiert wird ueber die
|
||||
Separatoren, weil deren Nummern ueber Exporte hinweg stabiler sind als die
|
||||
laufenden TRO-Nummern.
|
||||
"""
|
||||
|
||||
name: str
|
||||
type_name: str
|
||||
separators: list[str] = field(default_factory=list)
|
||||
host: str = ""
|
||||
label: str = ""
|
||||
reason: str = ""
|
||||
confidence: str = DEFAULT_CONFIDENCE
|
||||
|
||||
|
||||
@dataclass
|
||||
class OpenPoint:
|
||||
"""Eine im Review gemeldete Stelle, die noch kein eigener TRO ist."""
|
||||
|
||||
name: str
|
||||
x: float
|
||||
y: float
|
||||
z: float | None = None
|
||||
expect: str = ""
|
||||
belongs_to: str = ""
|
||||
note: str = ""
|
||||
|
||||
def describe_position(self) -> str:
|
||||
return f"{self.x:.0f}, {self.y:.0f}"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Overrides:
|
||||
"""Alle Korrekturen zu einer CSV-Datei."""
|
||||
|
||||
source: Path | None = None
|
||||
tros: dict[str, TroOverride] = field(default_factory=dict)
|
||||
splits: list[SplitSpec] = field(default_factory=list)
|
||||
merges: list[MergeSpec] = field(default_factory=list)
|
||||
# Gesetzte Topologie: ersetzt die abgeleiteten Kanten vollstaendig
|
||||
connections: list[ConnectionSpec] = field(default_factory=list)
|
||||
open_points: list[OpenPoint] = field(default_factory=list)
|
||||
# Protokoll der tatsaechlich angewandten Korrekturen (fuer die Doku)
|
||||
applied: list[str] = field(default_factory=list)
|
||||
warnings: list[str] = field(default_factory=list)
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return bool(self.tros or self.splits or self.merges or self.connections
|
||||
or self.open_points)
|
||||
|
||||
|
||||
def override_path(cfg_dir: Path | None = None) -> Path:
|
||||
"""Pfad zur Override-Datei: %SKEL_CFG%, sonst <projekt>/cfg."""
|
||||
if cfg_dir is not None:
|
||||
return cfg_dir / OVERRIDE_FILE
|
||||
env = os.environ.get("SKEL_CFG")
|
||||
if env:
|
||||
return Path(env) / OVERRIDE_FILE
|
||||
return Path(__file__).resolve().parent.parent / "cfg" / OVERRIDE_FILE
|
||||
|
||||
|
||||
def _as_float(raw: str, where: str, warnings: list[str]) -> float | None:
|
||||
try:
|
||||
return float(str(raw).strip())
|
||||
except (TypeError, ValueError):
|
||||
warnings.append(f"{where}: '{raw}' ist keine Zahl - Eintrag ignoriert")
|
||||
return None
|
||||
|
||||
|
||||
def load_overrides(csv_name: str, cfg_dir: Path | None = None) -> Overrides:
|
||||
"""Korrekturen zu `csv_name` laden (leeres Ergebnis, wenn es keine gibt)."""
|
||||
path = override_path(cfg_dir)
|
||||
result = Overrides()
|
||||
if not path.is_file():
|
||||
return result
|
||||
result.source = path
|
||||
|
||||
parser = configparser.ConfigParser(inline_comment_prefixes=(";",))
|
||||
# Schluessel sind Kleinschreibung, Sektionsnamen bleiben wie geschrieben.
|
||||
parser.read(path, encoding="utf-8")
|
||||
|
||||
prefix = csv_name.lower()
|
||||
for section in parser.sections():
|
||||
# [<csv>.connections] - gesetzte Topologie, eigene Form ohne <name>
|
||||
if section.lower() == f"{prefix}.connections":
|
||||
for key, raw in parser[section].items():
|
||||
pfeil, _, rest = str(raw).partition("|")
|
||||
src, sep, dst = (t.strip() for t in pfeil.partition("->"))
|
||||
if not sep or not src or not dst:
|
||||
result.warnings.append(
|
||||
f"[{section}] {key}: '{raw}' ist keine Verbindung "
|
||||
f"'<von> -> <nach>'"
|
||||
)
|
||||
continue
|
||||
result.connections.append(
|
||||
ConnectionSpec(src=src, dst=dst, kind=rest.strip())
|
||||
)
|
||||
continue
|
||||
|
||||
parts = section.split(".")
|
||||
# <csv>.<art>.<name> - der CSV-Name kann selbst einen Punkt enthalten
|
||||
if len(parts) < 3:
|
||||
continue
|
||||
kind, name = parts[-2].lower(), parts[-1]
|
||||
owner = ".".join(parts[:-2]).lower()
|
||||
if owner != prefix:
|
||||
continue
|
||||
values = parser[section]
|
||||
|
||||
if kind == "tro":
|
||||
type_name = values.get("type", "").strip()
|
||||
if type_name and get_tro(type_name) is None:
|
||||
result.warnings.append(
|
||||
f"[{section}]: Typ '{type_name}' steht nicht im TRO-Katalog "
|
||||
f"- Korrektur ignoriert"
|
||||
)
|
||||
continue
|
||||
key = name.upper()
|
||||
by_sep = key.startswith("SEP")
|
||||
result.tros[key] = TroOverride(
|
||||
key=key[3:] if by_sep else key,
|
||||
by_separator=by_sep,
|
||||
type_name=type_name,
|
||||
reason=values.get("reason", "").strip(),
|
||||
confidence=values.get("confidence", "").strip() or DEFAULT_CONFIDENCE,
|
||||
)
|
||||
elif kind == "split":
|
||||
type_name = values.get("type", "").strip()
|
||||
if get_tro(type_name) is None:
|
||||
result.warnings.append(
|
||||
f"[{section}]: Typ '{type_name}' steht nicht im TRO-Katalog "
|
||||
f"- neuer TRO nicht angelegt"
|
||||
)
|
||||
continue
|
||||
seps = [s.strip() for s in values.get("separators", "").split(",") if s.strip()]
|
||||
if not seps:
|
||||
result.warnings.append(
|
||||
f"[{section}]: 'separators' fehlt - ohne Separator kein TRO"
|
||||
)
|
||||
continue
|
||||
result.splits.append(
|
||||
SplitSpec(
|
||||
name=name,
|
||||
type_name=type_name,
|
||||
separators=seps,
|
||||
scanners=[s.strip() for s in values.get("scanners", "").split(",")
|
||||
if s.strip()],
|
||||
host=values.get("host", "").strip(),
|
||||
label=values.get("label", "").strip(),
|
||||
reason=values.get("reason", "").strip(),
|
||||
confidence=values.get("confidence", "").strip() or DEFAULT_CONFIDENCE,
|
||||
)
|
||||
)
|
||||
elif kind == "merge":
|
||||
type_name = values.get("type", "").strip()
|
||||
if get_tro(type_name) is None:
|
||||
result.warnings.append(
|
||||
f"[{section}]: Typ '{type_name}' steht nicht im TRO-Katalog "
|
||||
f"- Zusammenfassung nicht durchgefuehrt"
|
||||
)
|
||||
continue
|
||||
seps = [s.strip() for s in values.get("separators", "").split(",") if s.strip()]
|
||||
if len(seps) < 2:
|
||||
result.warnings.append(
|
||||
f"[{section}]: 'separators' braucht mindestens zwei Nummern"
|
||||
)
|
||||
continue
|
||||
result.merges.append(
|
||||
MergeSpec(
|
||||
name=name,
|
||||
type_name=type_name,
|
||||
separators=seps,
|
||||
host=values.get("host", "").strip(),
|
||||
label=values.get("label", "").strip(),
|
||||
reason=values.get("reason", "").strip(),
|
||||
confidence=values.get("confidence", "").strip() or DEFAULT_CONFIDENCE,
|
||||
)
|
||||
)
|
||||
elif kind == "openpoint":
|
||||
x = _as_float(values.get("x", ""), f"[{section}] x", result.warnings)
|
||||
y = _as_float(values.get("y", ""), f"[{section}] y", result.warnings)
|
||||
if x is None or y is None:
|
||||
continue
|
||||
z_raw = values.get("z", "").strip()
|
||||
expect = values.get("expect", "").strip()
|
||||
if expect and get_tro(expect) is None:
|
||||
result.warnings.append(
|
||||
f"[{section}]: erwarteter Typ '{expect}' steht nicht im "
|
||||
f"TRO-Katalog"
|
||||
)
|
||||
result.open_points.append(
|
||||
OpenPoint(
|
||||
name=name,
|
||||
x=x,
|
||||
y=y,
|
||||
z=_as_float(z_raw, f"[{section}] z", result.warnings)
|
||||
if z_raw
|
||||
else None,
|
||||
expect=expect,
|
||||
belongs_to=values.get("belongs_to", "").strip(),
|
||||
note=values.get("note", "").strip(),
|
||||
)
|
||||
)
|
||||
else:
|
||||
result.warnings.append(
|
||||
f"[{section}]: unbekannte Art '{kind}' - erwartet 'tro' oder "
|
||||
f"'openpoint'"
|
||||
)
|
||||
|
||||
result.open_points.sort(key=lambda p: p.name)
|
||||
return result
|
||||
|
||||
|
||||
def apply_splits(tros, overrides: Overrides, make_tro) -> list:
|
||||
"""Neue TROs aus bestehenden herausloesen (vor der Nummernvergabe).
|
||||
|
||||
`make_tro(spec, hosts, label)` erzeugt das projektspezifische Tro-Objekt -
|
||||
so bleibt dieses Modul frei von einem Import aus tro_flow (das umgekehrt
|
||||
schon von hier importiert).
|
||||
"""
|
||||
for spec in overrides.splits:
|
||||
quellen = [t for t in tros if set(spec.separators) & set(t.separators)]
|
||||
if not quellen:
|
||||
overrides.warnings.append(
|
||||
f"Split '{spec.name}': keiner der Separatoren "
|
||||
f"{', '.join(spec.separators)} kommt in diesem Lauf vor - "
|
||||
f"nicht angelegt"
|
||||
)
|
||||
continue
|
||||
|
||||
hosts: list[str] = []
|
||||
for quelle in quellen:
|
||||
quelle.separators = [s for s in quelle.separators
|
||||
if s not in spec.separators]
|
||||
quelle.scanners = [s for s in quelle.scanners if s not in spec.scanners]
|
||||
hosts.extend(quelle.hosts)
|
||||
if not quelle.separators and quelle.type_name not in ("Vario",):
|
||||
overrides.warnings.append(
|
||||
f"Split '{spec.name}': {quelle.label} hat danach keinen "
|
||||
f"Separator mehr - bitte pruefen"
|
||||
)
|
||||
|
||||
ziel_hosts = [spec.host] if spec.host else sorted(set(hosts))[:1]
|
||||
label = spec.label or (
|
||||
f"Separator {', '.join(spec.separators)} "
|
||||
f"(manuell aus {quellen[0].label} herausgeloest)"
|
||||
)
|
||||
tros.append(make_tro(spec, ziel_hosts, label))
|
||||
overrides.applied.append(
|
||||
f"neu {spec.name}: {spec.type_name} auf {', '.join(ziel_hosts)} "
|
||||
f"mit Separator {', '.join(spec.separators)}, herausgeloest aus "
|
||||
f"{', '.join(sorted({q.label for q in quellen}))} "
|
||||
f"({spec.reason or 'manuelle Ergaenzung'})"
|
||||
)
|
||||
return tros
|
||||
|
||||
|
||||
def apply_merges(tros, overrides: Overrides) -> list:
|
||||
"""Mehrere TROs zu einem zusammenfassen (nach den Splits, vor der Nummer).
|
||||
|
||||
Der erste betroffene TRO bleibt bestehen und uebernimmt Bauteile, Hosts und
|
||||
Typ; die uebrigen werden aus der Liste entfernt.
|
||||
"""
|
||||
for spec in overrides.merges:
|
||||
betroffen = [t for t in tros if set(spec.separators) & set(t.separators)]
|
||||
if len(betroffen) < 2:
|
||||
gefunden = ", ".join(t.tro_id or t.label for t in betroffen) or "keiner"
|
||||
overrides.warnings.append(
|
||||
f"Merge '{spec.name}': nur {len(betroffen)} der Separatoren "
|
||||
f"{', '.join(spec.separators)} gefunden ({gefunden}) - "
|
||||
f"nicht zusammengefasst"
|
||||
)
|
||||
continue
|
||||
|
||||
ziel = betroffen[0]
|
||||
quellen = betroffen[1:]
|
||||
for quelle in quellen:
|
||||
ziel.separators = sorted(set(ziel.separators) | set(quelle.separators))
|
||||
ziel.scanners = sorted(set(ziel.scanners) | set(quelle.scanners))
|
||||
ziel.hosts = sorted(set(ziel.hosts) | set(quelle.hosts))
|
||||
tros.remove(quelle)
|
||||
|
||||
if spec.host:
|
||||
# Ein Host bestimmt, wo der zusammengefasste TRO im Fluss haengt;
|
||||
# die uebrigen Bahnen bleiben als weitere Hosts erhalten, damit die
|
||||
# Verknuepfung beide Seiten des Uebergangs sieht.
|
||||
ziel.hosts = [spec.host] + [h for h in ziel.hosts if h != spec.host]
|
||||
ziel.type_name = spec.type_name
|
||||
ziel.confidence = spec.confidence
|
||||
ziel.label = spec.label or ziel.label
|
||||
grund = spec.reason or "manuell zusammengefasst"
|
||||
ziel.reason = f"{ziel.reason}; manuell zusammengefasst ({grund})"
|
||||
overrides.applied.append(
|
||||
f"merge {spec.name}: {len(betroffen)} TROs -> ein {spec.type_name} "
|
||||
f"mit Separatoren {', '.join(ziel.separators)} ({grund})"
|
||||
)
|
||||
return tros
|
||||
|
||||
|
||||
def apply_connections(tros, overrides: Overrides):
|
||||
"""Gesetzte Topologie an die Stelle der abgeleiteten Kanten setzen.
|
||||
|
||||
Ersetzt vollstaendig, nicht ergaenzend: wenn die Verbindungen vor Ort
|
||||
aufgenommen wurden, sind die abgeleiteten damit erledigt - sonst blieben
|
||||
genau die Kanten stehen, die korrigiert werden sollten. Was dabei wegfaellt
|
||||
bzw. hinzukommt, steht anschliessend in overrides.applied.
|
||||
|
||||
Rueckgabe: (edges, edge_kinds) wie von link_tros.
|
||||
"""
|
||||
bekannt = {t.tro_id for t in tros}
|
||||
edges: list[tuple[str, str]] = []
|
||||
kinds: dict[tuple[str, str], str] = {}
|
||||
for spec in overrides.connections:
|
||||
for seite, wert in (("von", spec.src), ("nach", spec.dst)):
|
||||
if wert not in bekannt:
|
||||
overrides.warnings.append(
|
||||
f"Verbindung {spec.src} -> {spec.dst}: {seite} '{wert}' ist "
|
||||
f"kein TRO dieses Laufs - Verbindung ignoriert"
|
||||
)
|
||||
break
|
||||
else:
|
||||
paar = (spec.src, spec.dst)
|
||||
if paar in kinds:
|
||||
continue
|
||||
edges.append(paar)
|
||||
kinds[paar] = spec.kind or "gesetzt"
|
||||
|
||||
for tro in tros:
|
||||
tro.successors = sorted(d for s, d in edges if s == tro.tro_id)
|
||||
tro.predecessors = sorted(s for s, d in edges if d == tro.tro_id)
|
||||
tro.colocated = []
|
||||
|
||||
ohne = [t.tro_id for t in tros if not t.successors and not t.predecessors]
|
||||
if ohne:
|
||||
overrides.warnings.append(
|
||||
"ohne Verbindung in der gesetzten Topologie: " + ", ".join(sorted(ohne))
|
||||
)
|
||||
overrides.applied.append(
|
||||
f"Topologie gesetzt: {len(edges)} Verbindungen aus der Override-Datei "
|
||||
f"ersetzen die abgeleiteten"
|
||||
)
|
||||
return sorted(edges), kinds
|
||||
|
||||
|
||||
def apply_overrides(tros, overrides: Overrides) -> None:
|
||||
"""Typkorrekturen auf die abgeleitete TRO-Liste anwenden.
|
||||
|
||||
Wird aufgerufen, nachdem die TRO-IDs vergeben sind (die Korrekturen sind
|
||||
ueber die ID adressiert) und bevor FB-Baustein und Bauteilliste aus dem
|
||||
Katalog gezogen werden - der Typwechsel zieht beides mit.
|
||||
"""
|
||||
if not overrides.tros:
|
||||
return
|
||||
for section_key, override in sorted(overrides.tros.items()):
|
||||
treffer = [t for t in tros if override.matches(t)]
|
||||
if not treffer:
|
||||
wie = "Separator" if override.by_separator else "TRO-ID"
|
||||
overrides.warnings.append(
|
||||
f"[{section_key}]: kein TRO mit {wie} '{override.key}' in diesem "
|
||||
f"Lauf - Korrektur nicht angewandt"
|
||||
+ ("" if override.by_separator else
|
||||
" (Nummerierung geaendert? Besser ueber SEP<Nummer> adressieren)")
|
||||
)
|
||||
continue
|
||||
if len(treffer) > 1:
|
||||
overrides.warnings.append(
|
||||
f"[{section_key}]: trifft {len(treffer)} TROs "
|
||||
f"({', '.join(t.tro_id for t in treffer)}) - auf alle angewandt"
|
||||
)
|
||||
for tro in treffer:
|
||||
if not override.type_name or override.type_name == tro.type_name:
|
||||
continue
|
||||
vorher = tro.type_name
|
||||
tro.type_name = override.type_name
|
||||
tro.confidence = override.confidence
|
||||
grund = override.reason or "manuelle Korrektur"
|
||||
tro.reason = (f"{tro.reason}; manuell auf {override.type_name} "
|
||||
f"gesetzt ({grund})")
|
||||
overrides.applied.append(
|
||||
f"{tro.tro_id}: {vorher} -> {override.type_name} ({grund})"
|
||||
)
|
||||
Reference in New Issue
Block a user