feat: Eingang/Ausgang-Symbole als eigene CSV-Zeile + in TrackIds
Die Materialfluss-Ein-/Ausgangssymbole (Bloecke Eingang_<DIM>/Ausgang_<DIM>,
eingefuegt ueber ils-insert-station) erscheinen jetzt NUR im CSV-Export als
eigene TeileArt-Zeile ("Eingang"/"Ausgang", Merkmale wie BTMT). Wie
Separator/AS/ES nehmen sie als freie Umlauf-Punkte (KREISEL_UMLAUF_TEILEARTEN)
an der TrackIds-Spalte teil und tauchen so auch auf Kreiseln auf, auf deren
Bahn sie liegen. Der Sivas-Export schliesst sie bewusst aus.
- cfg/export.cfg: pattern_eingang/pattern_ausgang
- Lisp/export.lsp: csv:collect-export-blocks sammelt beide Muster
- Lisp/ssg_id.lsp: ssg-id-collect-blocks erfasst sie (ssg-id-check-all fuellt
das nachgetragene ID-ATTDEF, dokumentiert in data/ils/allocations.json)
- lib/export_csv.py: Klassifikations-Zweige Eingang/Ausgang
- lib/export_neighbors.py: KREISEL_UMLAUF_TEILEARTEN um Eingang/Ausgang erweitert
- lib/export_sivas.py: Eingang/Ausgang uebersprungen (kein Sivas-Eintrag)
- Tests: test_export_eingang_ausgang.py + Kreisel-Umlauf-Test
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
52b0699862
commit
1d082ccde7
@@ -1088,6 +1088,13 @@
|
||||
;; ils-insert-station in SSG_LIB_Commands.lsp). Anders als Separator/
|
||||
;; Scanner werden sie von KEINEM anderen Element mitgezaehlt - export_csv.py
|
||||
;; UND export_sivas.py fuehren sie beide als eigene TeileArt-Zeilen.
|
||||
;; Eingang*/Ausgang* = Materialfluss-Ein-/Ausgangssymbole (siehe
|
||||
;; pattern_eingang/pattern_ausgang in cfg/export.cfg, ils-insert-station in
|
||||
;; SSG_LIB_Commands.lsp). Wie BTMT eigenstaendig, aber NUR fuer den
|
||||
;; CSV-Export: export_csv.py gibt ihnen eigene TeileArt-Zeilen und traegt
|
||||
;; sie - wie Separator/AS/ES - in die "TrackIds"-Spalte ein (auch auf
|
||||
;; Kreiseln, siehe KREISEL_UMLAUF_TEILEARTEN in lib/export_neighbors.py);
|
||||
;; export_sivas.py schliesst sie bewusst aus.
|
||||
;; GR_* = Geruest-Baugruppen (siehe pattern_geruest in cfg/export.cfg,
|
||||
;; GeruestInsert.lsp). Wie BTMT eigenstaendig und von keinem anderen
|
||||
;; Element mitgezaehlt - export_csv.py UND export_sivas.py fuehren sie
|
||||
@@ -1111,6 +1118,8 @@
|
||||
(wcmatch bname (export:pattern "pattern_scanner" "Scanner*"))
|
||||
(wcmatch bname (export:pattern "pattern_btmt_beladung" "BTMT-Beladung*"))
|
||||
(wcmatch bname (export:pattern "pattern_btmt_entladung" "SC_Entladung*"))
|
||||
(wcmatch bname (export:pattern "pattern_eingang" "Eingang*"))
|
||||
(wcmatch bname (export:pattern "pattern_ausgang" "Ausgang*"))
|
||||
(wcmatch bname (export:pattern "pattern_geruest" "GR_*"))
|
||||
;; Rein numerische Namen = Omniflo SivasNr (Boegen/Weichen)
|
||||
;; Rein LISP-intern (Python klassifiziert Omniflo stattdessen
|
||||
|
||||
@@ -38,6 +38,11 @@
|
||||
;; pattern_btmt_entladung in cfg/export.cfg) aus demselben Grund: sonst bleibt
|
||||
;; ihre ID trotz ATTDEF leer und sie fehlen bei der zeichnungsweiten Duplikat-
|
||||
;; pruefung/Maximum-Ermittlung (ssg-id-check-all).
|
||||
;; Eingang*/Ausgang* (Materialfluss-Ein-/Ausgangssymbole, siehe
|
||||
;; pattern_eingang/pattern_ausgang in cfg/export.cfg) ebenso: die DWGs haben
|
||||
;; seit dem ID-Nachtrag (allocations.json) ein leeres ID-ATTDEF, das hier
|
||||
;; gefuellt werden muss, damit sie eine stabile TeileId fuer die "TrackIds"-
|
||||
;; Spalte (auch auf Kreiseln) bekommen.
|
||||
;; GR_* (Geruest-Baugruppen, siehe pattern_geruest in cfg/export.cfg) ebenso -
|
||||
;; das ID-ATTDEF steht seit *geruest-attrib-defs* zur Verfuegung.
|
||||
(defun ssg-id-collect-blocks ( / ss-all ss-out i ename ed bname)
|
||||
@@ -57,6 +62,7 @@
|
||||
(wcmatch bname "Vario*,Staustrecke*,AUS_Element*,EIN_Element*,VF_*,GF_*")
|
||||
(wcmatch bname "Separator_SP*,S-LP*,Scanner*")
|
||||
(wcmatch bname "BTMT-Beladung*,SC_Entladung*")
|
||||
(wcmatch bname "Eingang*,Ausgang*")
|
||||
(wcmatch bname "GR_*")
|
||||
(wcmatch bname "#*")
|
||||
)
|
||||
|
||||
@@ -37,6 +37,17 @@
|
||||
# in den Summierungszaehlern "Anzahl aller BTBeladung"/"Anzahl aller
|
||||
# Abwurfstationen" der ILS-Automation-Zeile).
|
||||
#
|
||||
# pattern_eingang/pattern_ausgang: Eingangs-/Ausgangssymbole des Material-
|
||||
# flusses (siehe ils-insert-station in SSG_LIB_Commands.lsp, Bloecke
|
||||
# Eingang_<DIM>/Ausgang_<DIM>). NUR fuer den CSV-Export: export_csv.py fuehrt
|
||||
# sie als eigene TeileArt-Zeilen ("Eingang"/"Ausgang", Merkmale wie BTMT) UND
|
||||
# als frei platzierte Umlauf-Punkte auf einem Kreisel (KREISEL_UMLAUF_TEILEARTEN
|
||||
# in lib/export_neighbors.py), damit sie - wie Separator/AS/ES - in die
|
||||
# "TrackIds"-Spalte gelangen. export_sivas.py schliesst sie bewusst aus (kein
|
||||
# Sivas-Eintrag). Voraussetzung fuer eine stabile TeileId ist ein ID-ATTDEF in
|
||||
# den DWGs (ssg-id-check-all fuellt es vor jedem Export, siehe
|
||||
# ssg-id-collect-blocks in ssg_id.lsp).
|
||||
#
|
||||
# pattern_geruest: Geruest-Baugruppen (GeruestInsert.lsp, GR_<id>_<timestamp>).
|
||||
# Eigenstaendig wie BTMT, kein ANZAHL_*-Attribut an einem Carrier - export_csv.py
|
||||
# UND export_sivas.py fuehren sie als eigene TeileArt-Zeilen.
|
||||
@@ -54,6 +65,8 @@ pattern_separator= Separator_SP*, S-LP*
|
||||
pattern_scanner= Scanner*
|
||||
pattern_btmt_beladung= BTMT-Beladung*
|
||||
pattern_btmt_entladung= SC_Entladung*
|
||||
pattern_eingang= Eingang*
|
||||
pattern_ausgang= Ausgang*
|
||||
pattern_geruest= GR_*
|
||||
pattern_ks_subblocks= KS_EIN, KS_AUS, K1, K2, K3, K4
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"Eingang_2D": {
|
||||
"ID": ""
|
||||
},
|
||||
"Eingang_3D": {
|
||||
"ID": ""
|
||||
},
|
||||
"Ausgang_2D": {
|
||||
"ID": ""
|
||||
},
|
||||
"Ausgang_3D": {
|
||||
"ID": ""
|
||||
}
|
||||
}
|
||||
+25
-5
@@ -70,8 +70,8 @@ Bounding-Boxen braucht).
|
||||
`vla-update` auf, das allein reichte in diesem Fall nicht aus.
|
||||
7. **`csv:collect-export-blocks`** — sammelt alle relevanten top-level
|
||||
INSERTs (Kreisel, Omniflo, VF/GF-Wrapper, Separator/Scanner,
|
||||
BTMT-Stationen) ueber die Blockname-Muster aus `cfg/export.cfg`
|
||||
`[blockpattern]`.
|
||||
BTMT-Stationen, Eingang/Ausgang) ueber die Blockname-Muster aus
|
||||
`cfg/export.cfg` `[blockpattern]`.
|
||||
8. **`csv:block-to-json`** je Fund — siehe naechster Abschnitt.
|
||||
|
||||
### `csv:block-to-json` — Inhalt eines JSON-Eintrags
|
||||
@@ -277,7 +277,8 @@ Zu beachten:
|
||||
Eine grosse Schleife über alle rohen JSON-Blöcke ordnet jeden Block anhand
|
||||
der `cfg/export.cfg [blockpattern]`-Muster einer TeileArt zu (Kreisel,
|
||||
Eckrad, Omniflo Bogen/Weiche/Gerade, VF-Strecke, Gefaellestrecke,
|
||||
Strecke-Modul, Separator, Scanner, BTMT Be-/Entladung) und baut daraus ein
|
||||
Strecke-Modul, Separator, Scanner, BTMT Be-/Entladung, Eingang/Ausgang) und
|
||||
baut daraus ein
|
||||
Item-dict mit `teileart`, `teileid`, `bezeichnung`, `planquadrat`,
|
||||
`merkmale` und den bbox-/KOS-Spalten (`bbox_columns`). VF_n/GF_n-Items
|
||||
bekommen dabei zusaetzlich `x`/`y` (Kettenanfang, fuer die Schleuselement-
|
||||
@@ -299,6 +300,24 @@ Default 210x150x14mm) und der bekannten Position/Rotation eine synthetische
|
||||
`_bbox`, damit der Separator trotzdem an der Nachbarschaftserkennung
|
||||
teilnimmt.
|
||||
|
||||
#### Eingang/Ausgang — nur im CSV-Export
|
||||
|
||||
Die Materialfluss-Ein-/Ausgangssymbole (Bloecke `Eingang_<DIM>`/`Ausgang_<DIM>`,
|
||||
eingefuegt ueber `ils-insert-station`, Befehle `ILS_EINGANG_INSERT`/
|
||||
`ILS_AUSGANG_INSERT`) werden **nur im CSV-Export** als eigene Zeile gefuehrt
|
||||
(TeileArt `"Eingang"`/`"Ausgang"`, Merkmale wie BTMT: ARTINR/Hoehe/Drehung).
|
||||
`export_sivas.py` ueberspringt sie bewusst — ein Fluss-Symbol hat keinen
|
||||
eigenen Sivas-Artikel.
|
||||
|
||||
Wie Separator/AS/ES nehmen sie als **freie Umlauf-Punkte**
|
||||
(`KREISEL_UMLAUF_TEILEARTEN`) an der `"TrackIds"`-Spalte teil und tauchen so
|
||||
auch auf einem Kreisel auf, auf dessen Bahn sie liegen. Voraussetzung fuer
|
||||
eine ueber Exportlaeufe stabile TeileId ist ein `ID`-ATTDEF in den DWGs
|
||||
(nachgetragen, dokumentiert in `data/ils/allocations.json`); `ssg-id-check-all`
|
||||
fuellt es vor jedem Export, und `ssg-id-collect-blocks` (`Lisp/ssg_id.lsp`)
|
||||
erfasst die Bloecke dafuer. Fehlt die ID (noch), greift wie bei BTMT eine
|
||||
lauf-lokale Fallback-Nummer (`EIN-`/`AUS-`-Praefix).
|
||||
|
||||
### 2. `compute_neighbor_ids` — die generische Bounding-Box-Nachbarschaft
|
||||
|
||||
Datei `lib/export_neighbors.py`. Testet drei Gruppen gegeneinander (NICHT
|
||||
@@ -347,8 +366,9 @@ Weichen zu einer widerspruchsfreien Nachbarschaft zusammenfuehrt. Fuer jeden
|
||||
echten Kreisel werden alle Punkte gesammelt, die dort geometrisch liegen:
|
||||
|
||||
- freie Punkte (`KREISEL_UMLAUF_TEILEARTEN` in `lib/export_neighbors.py`:
|
||||
Separator, BTMT Beladung, BTMT Entladung — alles Stationen direkt auf der
|
||||
Bahn/dem Track), deren Bounding-Box die Kreisel-Box ueberschneidet,
|
||||
Separator, BTMT Beladung, BTMT Entladung, Eingang, Ausgang — alles
|
||||
Stationen/Markierungen direkt auf der Bahn/dem Track), deren Bounding-Box
|
||||
die Kreisel-Box ueberschneidet,
|
||||
- die Kreisel-Kreisel-Weichen aus Schritt 3 (in BEIDEN beteiligten
|
||||
Kreisel-Umlaeufen, da eine Weiche der gemeinsame Verzweigungspunkt ist —
|
||||
man kann von Kreisel A nach B und zurueck),
|
||||
|
||||
@@ -886,6 +886,8 @@ def process_blocks(blocks, lookup, dbg=None):
|
||||
scanner_count = 0
|
||||
btmt_beladung_count = 0
|
||||
btmt_entladung_count = 0
|
||||
eingang_count = 0
|
||||
ausgang_count = 0
|
||||
geruest_count = 0
|
||||
|
||||
# Zaehlung fuer die Omniflo-Sum-Zeile (nur Bogen/Weiche/Gerade)
|
||||
@@ -1159,6 +1161,44 @@ def process_blocks(blocks, lookup, dbg=None):
|
||||
})
|
||||
continue
|
||||
|
||||
# Eingangssymbol (Materialfluss-Eingang der Anlage) - eigene
|
||||
# TeileArt-Zeile, analog zu BTMT. Wie BTMT von keinem Carrier-Attribut
|
||||
# mitgezaehlt; anders als BTMT NUR im CSV-Export (export_sivas.py
|
||||
# ueberspringt Eingang/Ausgang). Die TeileId kommt aus dem ID-Attribut
|
||||
# (ssg-id-check-all fuellt es vor jedem Export, ID-ATTDEF seit dem
|
||||
# allocations.json-Nachtrag) - dieselbe TeileId, die die
|
||||
# "TrackIds"-Spalte an Kreisel/Strecke referenziert (KREISEL_UMLAUF_
|
||||
# TEILEARTEN in export_neighbors.py). Fallback-Nummer wie bei BTMT.
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_eingang", [])):
|
||||
elem_nr += 1
|
||||
eingang_count += 1
|
||||
items.append({
|
||||
"nr": elem_nr,
|
||||
"teileart": "Eingang",
|
||||
"teileid": block.get("attribs", {}).get("ID") or format_sensor_id("EIN", eingang_count),
|
||||
"bezeichnung": f"Eingang :{eingang_count}",
|
||||
"planquadrat": planquadrat_column(block, planquadrat_cfg),
|
||||
"merkmale": build_btmt_merkmale(block),
|
||||
**bbox_columns(block),
|
||||
})
|
||||
continue
|
||||
|
||||
# Ausgangssymbol (Materialfluss-Ausgang der Anlage) - analog zum
|
||||
# Eingangssymbol oben.
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_ausgang", [])):
|
||||
elem_nr += 1
|
||||
ausgang_count += 1
|
||||
items.append({
|
||||
"nr": elem_nr,
|
||||
"teileart": "Ausgang",
|
||||
"teileid": block.get("attribs", {}).get("ID") or format_sensor_id("AUS", ausgang_count),
|
||||
"bezeichnung": f"Ausgang :{ausgang_count}",
|
||||
"planquadrat": planquadrat_column(block, planquadrat_cfg),
|
||||
"merkmale": build_btmt_merkmale(block),
|
||||
**bbox_columns(block),
|
||||
})
|
||||
continue
|
||||
|
||||
# Geruest-Baugruppe (GR_<id>_<timestamp>) - eigene TeileArt-Zeile,
|
||||
# analog zu BTMT: kein ANZAHL_*-Attribut an einem Carrier zaehlt sie
|
||||
# mit. TeileId ist das echte ID-Attribut (ssg-id-check-all fuellt es
|
||||
|
||||
@@ -84,8 +84,15 @@ SENSOR_TEILEARTEN = {"ILS 2.0 Separator", "ILS 2.0 Scanner"}
|
||||
# Sensoren - eigene Konstante statt Erweiterung von SENSOR_TEILEARTEN, damit
|
||||
# deren Sensor-spezifische Weiterverarbeitung (z.B. compute_scanner_nearest_
|
||||
# separator) unberuehrt bleibt.
|
||||
# Eingang/Ausgang (Materialfluss-Ein-/Ausgangssymbole, siehe pattern_eingang/
|
||||
# pattern_ausgang in cfg/export.cfg) werden hier wie BTMT als frei platzierte
|
||||
# Umlauf-Punkte gefuehrt - so tauchen sie, wenn sie auf einer Kreiselbahn
|
||||
# liegen, in dessen "TrackIds"-Spalte auf (Nutzeranforderung: wie
|
||||
# Separator/AS/ES behandeln). Die TeileArt-Strings sind bewusst OHNE "ILS 2.0"-
|
||||
# Praefix (siehe export_csv.py) - dieselben Strings muessen hier stehen.
|
||||
KREISEL_UMLAUF_TEILEARTEN = {
|
||||
"ILS 2.0 Separator", "ILS 2.0 BTMT Beladung", "ILS 2.0 BTMT Entladung", "ILS Weiche",
|
||||
"Eingang", "Ausgang",
|
||||
}
|
||||
|
||||
# Nur "ILS 2.0 Kreisel" (echte Kreisel-Bloecke mit AN8/Antrieb + SP8/Spann-
|
||||
|
||||
@@ -504,6 +504,16 @@ def process_blocks(blocks, lookup):
|
||||
counters["anzahl_abwurfstationen"] += 1
|
||||
continue
|
||||
|
||||
# --- Eingangs-/Ausgangssymbol (Materialfluss-Ein-/Ausgang) ---
|
||||
# Bewusst NUR im CSV-Export als eigene Zeile (siehe export_csv.py) -
|
||||
# hier ohne Sivas-Zeile und ohne eigenen Zaehler ueberspringen. Ein
|
||||
# Eingangs-/Ausgangssymbol ist eine reine Fluss-Markierung ohne Sivas-
|
||||
# Artikel; ein eigener Sivas-Eintrag wuerde die Stueckliste verfaelschen
|
||||
# (Nutzeranforderung: Eingang/Ausgang nur im CSV-Export).
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_eingang", [])) or \
|
||||
matches_any(bname, BLOCKPATTERNS.get("pattern_ausgang", [])):
|
||||
continue
|
||||
|
||||
# --- Geruest-Baugruppe ---
|
||||
# Anders als BTMT/Separator je Block eine EIGENE Zeile statt gruppiert:
|
||||
# ARTINR (Sivas-IDs) und Laenge/Farbe koennen von Block zu Block
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_export_eingang_ausgang.py - Eingangs-/Ausgangssymbole im Export.
|
||||
Laeuft komplett ohne BricsCAD (reine Python-Logik).
|
||||
|
||||
Kundenwunsch: die Materialfluss-Ein-/Ausgangssymbole (Bloecke
|
||||
Eingang_<DIM>/Ausgang_<DIM>, eingefuegt ueber ils-insert-station) sollen
|
||||
- NUR im CSV-Export - als eigene Zeile erscheinen, inhaltlich aehnlich den
|
||||
BTMT Be-/Entladestationen, und
|
||||
- wie Separator/AS/ES in die "TrackIds" eingebaut werden (auch auf Kreiseln,
|
||||
siehe test_export_kreisel_umlauf.py).
|
||||
Im Sivas-Export duerfen sie NICHT auftauchen.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
|
||||
|
||||
import export_csv # noqa: E402
|
||||
import export_sivas # noqa: E402
|
||||
|
||||
|
||||
def _block(block_name, teileid, artinr="12345", x=0.0, y=0.0):
|
||||
return {
|
||||
"block_name": block_name,
|
||||
"x": x, "y": y, "z": 0.0,
|
||||
"rotation": 0.0,
|
||||
"attribs": {"ID": teileid, "ARTINR": artinr, "LAYER": "ILS_Flow",
|
||||
"ZUORDNUNG": ""},
|
||||
"_bbox": {"cx": x, "cy": y, "cz": 0.0, "dx": 200.0, "dy": 150.0},
|
||||
}
|
||||
|
||||
|
||||
class TestCsvKlassifikation:
|
||||
"""export_csv.process_blocks gibt Eingang/Ausgang je eine eigene
|
||||
TeileArt-Zeile ("Eingang"/"Ausgang") mit der Block-ID als TeileId."""
|
||||
|
||||
def test_eingang_und_ausgang_bekommen_eigene_zeile(self):
|
||||
blocks = [
|
||||
_block("Eingang_2D", "0050", x=0.0),
|
||||
_block("Ausgang_3D", "0051", x=1000.0),
|
||||
]
|
||||
items = export_csv.process_blocks(blocks, lookup={})
|
||||
nach_art = {it["teileart"]: it for it in items}
|
||||
|
||||
assert "Eingang" in nach_art, "Eingang-Zeile fehlt im CSV-Export"
|
||||
assert "Ausgang" in nach_art, "Ausgang-Zeile fehlt im CSV-Export"
|
||||
|
||||
ein = nach_art["Eingang"]
|
||||
aus = nach_art["Ausgang"]
|
||||
# TeileId kommt aus dem ID-Attribut (stabil ueber Exportlaeufe).
|
||||
assert ein["teileid"] == "0050"
|
||||
assert aus["teileid"] == "0051"
|
||||
# Merkmale wie BTMT: ARTINR als Merkmal gefuehrt.
|
||||
assert ein["merkmale"].get("ARTINR") == "12345"
|
||||
|
||||
def test_teileid_fallback_ohne_id_attribut(self):
|
||||
"""Ohne (noch) gefuelltes ID-Attribut greift der Fallback (EIN-/AUS-
|
||||
Praefix), damit die Zeile trotzdem eine TeileId traegt - wie bei BTMT."""
|
||||
blocks = [
|
||||
{"block_name": "Eingang_2D", "x": 0.0, "y": 0.0, "z": 0.0,
|
||||
"rotation": 0.0, "attribs": {},
|
||||
"_bbox": {"cx": 0.0, "cy": 0.0, "cz": 0.0, "dx": 200.0, "dy": 150.0}},
|
||||
]
|
||||
items = export_csv.process_blocks(blocks, lookup={})
|
||||
ein = next(it for it in items if it["teileart"] == "Eingang")
|
||||
assert ein["teileid"].startswith("EIN-")
|
||||
|
||||
|
||||
class TestSivasSchliesstAus:
|
||||
"""export_sivas.process_blocks fuehrt Eingang/Ausgang bewusst NICHT als
|
||||
eigene Zeile und zaehlt sie in keinem Summenzaehler mit."""
|
||||
|
||||
def test_keine_sivas_zeile_und_kein_zaehler(self):
|
||||
blocks = [
|
||||
_block("Eingang_2D", "0050"),
|
||||
_block("Ausgang_3D", "0051"),
|
||||
]
|
||||
items, counters = export_sivas.process_blocks(blocks, lookup={})
|
||||
|
||||
arten = {it.get("teileart", "") for it in items}
|
||||
assert "Eingang" not in arten
|
||||
assert "Ausgang" not in arten
|
||||
# Kein bestehender Zaehler darf durch die zwei Symbole hochgezaehlt
|
||||
# worden sein (alle Zaehler bleiben 0, da nur Eingang/Ausgang im Satz).
|
||||
assert all(v == 0 for v in counters.values()), (
|
||||
f"Eingang/Ausgang haben einen Sivas-Zaehler beeinflusst: "
|
||||
f"{{k: v for k, v in counters.items() if v}}")
|
||||
@@ -64,6 +64,17 @@ def _btmt(teileart, teileid, x, y):
|
||||
}
|
||||
|
||||
|
||||
def _flusssymbol(teileart, teileid, x, y):
|
||||
"""Eingangs-/Ausgangssymbol ("Eingang"/"Ausgang") - frei auf der Bahn
|
||||
platziert wie ein Separator/BTMT, siehe KREISEL_UMLAUF_TEILEARTEN. Die
|
||||
TeileArt-Strings sind bewusst OHNE "ILS 2.0"-Praefix (siehe export_csv.py)."""
|
||||
return {
|
||||
"teileart": teileart,
|
||||
"teileid": teileid,
|
||||
"_bbox": {"cx": x, "cy": y, "cz": 0.0, "dx": 200.0, "dy": 150.0},
|
||||
}
|
||||
|
||||
|
||||
def _zwei_beruehrende_kreisel():
|
||||
"""Zwei Kreisel, deren AN8-Enden sich exakt beruehren (End-an-End, wie im
|
||||
Mubea-Fall: 'Kreis/Kreis'-Beruehrung an der jeweiligen AN8-Kappe).
|
||||
@@ -422,3 +433,25 @@ class TestKreiselTrackidsSpalte:
|
||||
write_kreisel_separatorliste_merkmale(
|
||||
items, kreisel_umlauf, sep_kette_by_key={}, weiche_by_key={})
|
||||
assert k["trackids"] == "0031, 0020, 0030"
|
||||
|
||||
def test_eingang_und_ausgang_zaehlen_als_freie_punkte(self):
|
||||
"""Eingangs-/Ausgangssymbole ("Eingang"/"Ausgang") sind Fluss-
|
||||
Markierungen AUF der Bahn wie ein Separator/BTMT - sie muessen (auf
|
||||
Kundenwunsch) im Kreisel-Umlauf UND in der TrackIds-Spalte des
|
||||
Kreisels auftauchen, genau wie Separator/AS/ES."""
|
||||
k = _kreisel("0001", 0.0, 0.0, 0.0, abstand=1000.0)
|
||||
k["merkmale"] = {}
|
||||
sep = _separator("0020", 300.0, 300.0)
|
||||
ein = _flusssymbol("Eingang", "0040", 900.0, 400.0)
|
||||
aus = _flusssymbol("Ausgang", "0041", 1400.0, -50.0)
|
||||
items = [k, sep, ein, aus]
|
||||
|
||||
kreisel_umlauf = compute_kreisel_umlauf(
|
||||
items, sep_kette={}, tolerance_mm=200.0, durchmesser_mm=DURCHMESSER_MM)
|
||||
keys = [p[0] for p in kreisel_umlauf["0001"]]
|
||||
assert set(keys) == {"0020", "0040", "0041"}, (
|
||||
f"Eingang/Ausgang fehlen im Kreisel-Umlauf: {keys}")
|
||||
|
||||
write_kreisel_separatorliste_merkmale(
|
||||
items, kreisel_umlauf, sep_kette_by_key={}, weiche_by_key={})
|
||||
assert k["trackids"] == "0041, 0020, 0040"
|
||||
|
||||
Reference in New Issue
Block a user