list_trackids aus Merkmalen in eigene CSV-Spalte "TrackIds" verschoben
Statt eines JSON-Merkmals bekommen VF_n/GF_n/Kreisel jetzt eine eigene CSV-Spalte "TrackIds" (nach "Nachbarn", vor "Fehler") mit der Reihenfolge der Separator-/BTMT-/AS-ES-/Weichen-TeileIds entlang der Strecke bzw. um den Kreisel - analog zur bestehenden "Nachbarn"-Spalte statt versteckt im Merkmale-JSON. Referenz-CSV fuer den Omniflo-Test an den neuen Header angepasst. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+33
-24
@@ -41,7 +41,7 @@ Aufruf:
|
||||
|
||||
CSV-Format:
|
||||
Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;
|
||||
Insertpoint;K1;K2;K3;K4;Nachbarn;Fehler;Warnungen;Merkmale
|
||||
Insertpoint;K1;K2;K3;K4;Nachbarn;TrackIds;Fehler;Warnungen;Merkmale
|
||||
|
||||
Position und Boundingbox stammen aus der von export.lsp (csv:get-bbox, per
|
||||
vla-getboundingbox) ermittelten Bounding-Box je Block:
|
||||
@@ -68,6 +68,13 @@ das trennt bloss ueberlappende BBoxen von echten Anschluessen (Geraden fuehren
|
||||
dafuer beim Export synthetisierte K1/K2, siehe csv:gerade-k-kos-strings).
|
||||
Toleranzen und (Fallback-)Rastergroesse konfigurierbar ueber [Nachbarschaft]
|
||||
in cfg/export.cfg.
|
||||
TrackIds = kommaseparierte TeileId-Liste der Separatoren/BTMT-Beladung/
|
||||
BTMT-Entladung (und bei einem Kreisel zusaetzlich der AS/ES-Streckenenden
|
||||
und Kreisel-Kreisel-Weichen) entlang einer VF_n/GF_n-Strecke bzw. rund um
|
||||
einen Kreisel, in Baureihenfolge (Strecke) bzw. Umlaufreihenfolge ab Winkel
|
||||
0 Grad (Kreisel, siehe export_neighbors.compute_kreisel_umlauf) - nur bei
|
||||
VF_n/GF_n/Kreisel vorhanden, sonst leer. Siehe write_separatorliste_
|
||||
merkmale/write_kreisel_separatorliste_merkmale.
|
||||
Fehler = "unverbunden" (keine Partner, aber mindestens einer noetig),
|
||||
"nur ein Partner" (ein Partner, aber mindestens zwei noetig) oder leer
|
||||
(Mindestanzahl erreicht bzw. TeileArt wird nicht geprueft). Kreisel/Eckrad/
|
||||
@@ -250,11 +257,11 @@ def build_variofoerderer_merkmale(block):
|
||||
export_raw.json-Dateien (z.B. tests/reference/export_raw.json) und noch
|
||||
nicht neu aufgebaute Bloecke in der Zeichnung weiterhin Werte liefern.
|
||||
|
||||
Das Merkmal "list_trackids" (Reihenfolge der Separator-TeileIds entlang
|
||||
der Strecke) steht hier NICHT drin - es kommt erst nach der sepliste-
|
||||
Aufloesung dazu (siehe write_separatorliste_merkmale in process_blocks),
|
||||
weil an dieser Stelle die x/y-Koordinaten aus der sepliste-XDATA noch
|
||||
nicht auf reale Separator-TeileIds aufgeloest sind.
|
||||
Die CSV-Spalte "TrackIds" (item["trackids"], Reihenfolge der Separator-
|
||||
TeileIds entlang der Strecke) steht hier NICHT drin - sie kommt erst nach
|
||||
der sepliste-Aufloesung dazu (siehe write_separatorliste_merkmale in
|
||||
process_blocks), weil an dieser Stelle die x/y-Koordinaten aus der
|
||||
sepliste-XDATA noch nicht auf reale Separator-TeileIds aufgeloest sind.
|
||||
"""
|
||||
attribs = block.get("attribs", {})
|
||||
|
||||
@@ -844,9 +851,10 @@ def resolve_umlauf_und_sepliste_nachbarn(items, kreisel_umlauf, sep_kette,
|
||||
|
||||
|
||||
def write_separatorliste_merkmale(items, sep_kette_by_key, dbg=None):
|
||||
"""Traegt in jede Strecke (VF_n/GF_n mit "sepliste") das Merkmal
|
||||
"list_trackids" ein: die TeileIds ihrer Separatoren in Baureihenfolge,
|
||||
kommagetrennt (analog zu "Zuordnung"/"Nachbarn"), z.B. "0052, 0053, 0054".
|
||||
"""Traegt in jede Strecke (VF_n/GF_n mit "sepliste") die eigene CSV-Spalte
|
||||
"TrackIds" (item["trackids"]) ein: die TeileIds ihrer Separatoren in
|
||||
Baureihenfolge, kommagetrennt (analog zur "Nachbarn"-Spalte, ebenfalls
|
||||
ein Top-Level-Item-Feld statt eines Merkmals), z.B. "0052, 0053, 0054".
|
||||
|
||||
Quelle ist die rohe "sepliste" des Items (AS/SEP/ES mit x/y, bereits in
|
||||
Baureihenfolge - siehe compute_sep_kette) statt sep_kette selbst: dessen
|
||||
@@ -875,24 +883,24 @@ def write_separatorliste_merkmale(items, sep_kette_by_key, dbg=None):
|
||||
sep_item = sep_kette_by_key.get(key)
|
||||
if sep_item is None:
|
||||
if dbg:
|
||||
dbg(f" list_trackids {key}: kein aufgeloestes Separator-Item "
|
||||
dbg(f" TrackIds {key}: kein aufgeloestes Separator-Item "
|
||||
f"- uebersprungen")
|
||||
continue
|
||||
separator_ids.append(sep_item.get("teileid", ""))
|
||||
if separator_ids:
|
||||
item["merkmale"]["list_trackids"] = ", ".join(separator_ids)
|
||||
item["trackids"] = ", ".join(separator_ids)
|
||||
|
||||
|
||||
def write_kreisel_separatorliste_merkmale(items, kreisel_umlauf, sep_kette_by_key,
|
||||
weiche_by_key, dbg=None):
|
||||
"""Traegt in jeden Kreisel ("ILS 2.0 Kreisel") das Merkmal "list_trackids"
|
||||
ein (gleicher Schluessel wie bei VF_n/GF_n, siehe write_separatorliste_
|
||||
merkmale): die TeileIds aller auf ihm liegenden freien Punkte (Separator,
|
||||
BTMT Beladung/Entladung - siehe KREISEL_UMLAUF_TEILEARTEN),
|
||||
andockenden AS/ES-Streckenenden und Kreisel-Kreisel-Weichen, in
|
||||
Umlaufreihenfolge ab Winkel 0 Grad (siehe compute_kreisel_umlauf - die
|
||||
Liste beginnt dort bereits bei 0 Grad in Drehrichtung DREHRICHTUNG),
|
||||
kommagetrennt.
|
||||
"""Traegt in jeden Kreisel ("ILS 2.0 Kreisel") die eigene CSV-Spalte
|
||||
"TrackIds" (item["trackids"], gleiches Feld wie bei VF_n/GF_n, siehe
|
||||
write_separatorliste_merkmale) ein: die TeileIds aller auf ihm liegenden
|
||||
freien Punkte (Separator, BTMT Beladung/Entladung - siehe
|
||||
KREISEL_UMLAUF_TEILEARTEN), andockenden AS/ES-Streckenenden und Kreisel-
|
||||
Kreisel-Weichen, in Umlaufreihenfolge ab Winkel 0 Grad (siehe
|
||||
compute_kreisel_umlauf - die Liste beginnt dort bereits bei 0 Grad in
|
||||
Drehrichtung DREHRICHTUNG), kommagetrennt.
|
||||
|
||||
Quelle ist kreisel_umlauf (export_neighbors.compute_kreisel_umlauf), das
|
||||
fuer jeden Kreisel bereits alle Punkte (freie Punkte, AS/ES-Enden,
|
||||
@@ -920,12 +928,12 @@ def write_kreisel_separatorliste_merkmale(items, kreisel_umlauf, sep_kette_by_ke
|
||||
item = alle_schluessel.get(punkt_key)
|
||||
if item is None:
|
||||
if dbg:
|
||||
dbg(f" list_trackids Kreisel {tid}: kein Item fuer "
|
||||
dbg(f" TrackIds Kreisel {tid}: kein Item fuer "
|
||||
f"Umlauf-Punkt {punkt_key!r} - uebersprungen")
|
||||
continue
|
||||
teileids.append(item.get("teileid", ""))
|
||||
if teileids:
|
||||
kreisel_item["merkmale"]["list_trackids"] = ", ".join(teileids)
|
||||
kreisel_item["trackids"] = ", ".join(teileids)
|
||||
|
||||
|
||||
def process_blocks(blocks, lookup, dbg=None):
|
||||
@@ -1325,14 +1333,14 @@ def process_blocks(blocks, lookup, dbg=None):
|
||||
map_separator_kette_items(
|
||||
items, sep_kette, sep_kette_by_key=sep_kette_by_key, dbg=dbg)
|
||||
|
||||
# Merkmal "list_trackids" je Strecke (Reihenfolge der SEP-TeileIds aus der
|
||||
# Spalte "TrackIds" je Strecke (Reihenfolge der SEP-TeileIds aus der
|
||||
# sepliste, x/y bereits oben auf das reale Separator-Item aufgeloest).
|
||||
write_separatorliste_merkmale(items, sep_kette_by_key, dbg=dbg)
|
||||
|
||||
resolve_umlauf_und_sepliste_nachbarn(
|
||||
items, kreisel_umlauf, sep_kette, sep_kette_by_key, weiche_by_key)
|
||||
|
||||
# Merkmal "list_trackids" je Kreisel: dieselben Umlauf-Punkte (freie
|
||||
# Spalte "TrackIds" je Kreisel: dieselben Umlauf-Punkte (freie
|
||||
# Separatoren, AS/ES-Enden, Kreisel-Kreisel-Weichen), die oben schon die
|
||||
# "Nachbarn"-Spalte gespeist haben, jetzt als eine einzige, bei 0 Grad
|
||||
# beginnende Reihenfolge auf den Kreisel selbst geschrieben (analog zu
|
||||
@@ -1380,6 +1388,7 @@ def format_csv_line(item):
|
||||
f';"{csv_quote(item["k3"])}"'
|
||||
f';"{csv_quote(item["k4"])}"'
|
||||
f';"{csv_quote(item["nachbarn"])}"'
|
||||
f';"{csv_quote(item.get("trackids", ""))}"'
|
||||
f';"{csv_quote(item["fehler"])}"'
|
||||
f';"{csv_quote(item.get("warnung", ""))}"'
|
||||
f';{merkmale_json}'
|
||||
@@ -1438,7 +1447,7 @@ def main():
|
||||
print(f"[export_csv] Kollisions-Debuglog geschrieben: {NEIGHBOR_DEBUG_TARGET}")
|
||||
|
||||
header = ("Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;"
|
||||
"Insertpoint;K1;K2;K3;K4;Nachbarn;Fehler;Warnungen;Merkmale")
|
||||
"Insertpoint;K1;K2;K3;K4;Nachbarn;TrackIds;Fehler;Warnungen;Merkmale")
|
||||
with open(output_csv, "w", encoding="utf-8") as f:
|
||||
f.write(header + "\n")
|
||||
for item in items:
|
||||
|
||||
@@ -75,8 +75,9 @@ OMNIFLO_TEILEARTEN = {"Omniflo Kurve", "Omniflo Weiche", "Omniflo Gerade"}
|
||||
SENSOR_TEILEARTEN = {"ILS 2.0 Separator", "ILS 2.0 Scanner"}
|
||||
|
||||
# Frei auf der Bahn platzierte Elemente, die im Kreisel-Umlauf
|
||||
# (compute_kreisel_umlauf) und im Kreisel-Merkmal "list_trackids" (export_csv.py
|
||||
# write_kreisel_separatorliste_merkmale) als eigene Punkte auftreten koennen -
|
||||
# (compute_kreisel_umlauf) und in der Kreisel-CSV-Spalte "TrackIds"
|
||||
# (export_csv.py write_kreisel_separatorliste_merkmale) als eigene Punkte
|
||||
# auftreten koennen -
|
||||
# wie ein Separator per Bounding-Box-Ueberschneidung einer Kreiselhaelfte/
|
||||
# einem Kreisel zugeordnet (siehe compute_sensor_zuordnung/compute_kreisel_
|
||||
# umlauf). BTMT-Beladung/-Entladung sind Stationen AUF der Strecke, keine
|
||||
@@ -1417,7 +1418,7 @@ def compute_kreisel_umlauf(items, sep_kette, tolerance_mm, durchmesser_mm=800.0,
|
||||
diesem Nullpunkt (kleinster Winkel >= 0 Grad in Umlaufrichtung) - das ist
|
||||
fuer die reine Vorgaenger-/Nachfolger-Ermittlung (zirkulaer) irrelevant,
|
||||
aber Voraussetzung fuer eine reproduzierbare, bei 0 Grad beginnende
|
||||
"list_trackids" (siehe export_csv.py write_kreisel_separatorliste_merkmale).
|
||||
"TrackIds"-Spalte (siehe export_csv.py write_kreisel_separatorliste_merkmale).
|
||||
|
||||
items = dieselbe Liste wie bei compute_neighbor_ids/compute_sensor_
|
||||
zuordnung. sep_kette = Rueckgabe von compute_sep_kette (fuer die AS/ES-
|
||||
|
||||
Reference in New Issue
Block a user