260 lines
8.1 KiB
Python
260 lines
8.1 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
export_csv.py - Erzeugt eine einfache Item-Liste als CSV (ohne Summierung).
|
|
|
|
Aufruf:
|
|
python export_csv.py <export_raw.json> <data_dir> <output.csv>
|
|
|
|
CSV-Format:
|
|
Elementnummer;TeileArt;TeileId;NachbarIds;Bezeichnung;Planquadrat;rotation;Merkmale
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import os
|
|
import uuid
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Gemeinsame Hilfsfunktionen (auch in export_sivas.py verwendet)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def load_json(path):
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
return json.load(f)
|
|
|
|
|
|
def build_lookup(boegen, weichen):
|
|
"""Erzeugt ein Dict: SivasNr (als String) -> (typ, eintrag)"""
|
|
lookup = {}
|
|
for b in boegen:
|
|
lookup[str(b["Sivasnr"])] = ("bogen", b)
|
|
for w in weichen:
|
|
lookup[str(w["Sivasnr"])] = ("weiche", w)
|
|
return lookup
|
|
|
|
|
|
def generate_shape_id():
|
|
return "shape_" + str(uuid.uuid4())
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Merkmale-Builder
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def build_bogen_merkmale(block, eintrag):
|
|
return {
|
|
"Länge in Meter": "0",
|
|
"Kurvenwinkel": eintrag.get("KurvenWinkel", 0),
|
|
"Radius": eintrag.get("Radius", 0),
|
|
"Höhe": "2000",
|
|
"Drehung": block.get("rotation", 0.0),
|
|
"SivasNummer": str(eintrag.get("Sivasnr", ""))
|
|
}
|
|
|
|
|
|
def build_weiche_merkmale(block, eintrag):
|
|
wt = eintrag.get("WeichenTyp", "Einzelweiche")
|
|
return {
|
|
"Länge in Meter links": None,
|
|
"Länge in Meter rechts": None,
|
|
"Länge in Meter gerade": None,
|
|
"Weichentyp": wt,
|
|
"Richtung": str(eintrag.get("KurvenRichtung", "")),
|
|
"Weichenwinkel": eintrag.get("KurvenWinkel", 0),
|
|
"Höhe": "2000",
|
|
"Drehung": block.get("rotation", 0.0),
|
|
"Antrieb Kurve": eintrag.get("SivasnrTEF") is not None,
|
|
"SivasNummer": str(eintrag.get("Sivasnr", ""))
|
|
}
|
|
|
|
|
|
def build_gerade_merkmale(block):
|
|
return {
|
|
"Anzahl der Separatoren": "0",
|
|
"Länge in Meter": "2",
|
|
"Winkel": "0",
|
|
"Anzahl der Scanner": 0,
|
|
"Höhe oben": "2000",
|
|
"Höhe unten": "2000",
|
|
"Drehung": block.get("rotation", 0.0),
|
|
"SivasNummer": ""
|
|
}
|
|
|
|
|
|
def build_kreisel_merkmale(block):
|
|
return {
|
|
"Abstand (Kreiselachse A - Kreiselachse) in Meter": "3",
|
|
"Anzahl der Separatoren": "2",
|
|
"Kreiselart": "Standard",
|
|
"Anzahl der Scanner": "0",
|
|
"Anzahl der Rampen": "0",
|
|
"Höhe in m": "2",
|
|
"Drehrichtung": "UZS",
|
|
"Drehung": block.get("rotation", 0.0)
|
|
}
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Bekannte Blocknamen
|
|
# ---------------------------------------------------------------------------
|
|
|
|
KREISEL_BLOCKS = {"AN8", "SP8"}
|
|
SKIP_BLOCKS = {"K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"}
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Planquadrat aus Block-Koordinaten
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def format_planquadrat(block):
|
|
x = block.get("x", 0.0)
|
|
y = block.get("y", 0.0)
|
|
return f"X:{x:.2f} Y:{y:.2f}"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Bloecke verarbeiten (einfache Liste, keine Summierung)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def process_blocks(blocks, lookup):
|
|
items = []
|
|
elem_nr = -1
|
|
bogen_count = 0
|
|
weiche_count = {}
|
|
gerade_count = 0
|
|
kreisel_count = 0
|
|
|
|
for block in blocks:
|
|
bname = block.get("block_name", "")
|
|
|
|
if bname in SKIP_BLOCKS:
|
|
continue
|
|
|
|
# Omniflo Bogen oder Weiche
|
|
if bname in lookup:
|
|
typ, eintrag = lookup[bname]
|
|
elem_nr += 1
|
|
shape_id = generate_shape_id()
|
|
|
|
if typ == "bogen":
|
|
bogen_count += 1
|
|
items.append({
|
|
"nr": elem_nr,
|
|
"teileart": "Omniflo Kurve",
|
|
"teileid": shape_id,
|
|
"nachbarids": "",
|
|
"bezeichnung": f"OFBogen :{bogen_count}",
|
|
"planquadrat": format_planquadrat(block),
|
|
"rotation": block.get("rotation", 0.0),
|
|
"merkmale": build_bogen_merkmale(block, eintrag),
|
|
})
|
|
|
|
elif typ == "weiche":
|
|
wt = eintrag.get("WeichenTyp", "Einzelweiche")
|
|
weiche_count[wt] = weiche_count.get(wt, 0) + 1
|
|
items.append({
|
|
"nr": elem_nr,
|
|
"teileart": "Omniflo Weiche",
|
|
"teileid": shape_id,
|
|
"nachbarids": "",
|
|
"bezeichnung": f"OFWeiche :{weiche_count[wt]}",
|
|
"planquadrat": format_planquadrat(block),
|
|
"rotation": block.get("rotation", 0.0),
|
|
"merkmale": build_weiche_merkmale(block, eintrag),
|
|
})
|
|
continue
|
|
|
|
# Omniflo Gerade (AP110)
|
|
if "AP110" in bname.upper() or "AP_110" in bname.upper():
|
|
elem_nr += 1
|
|
gerade_count += 1
|
|
items.append({
|
|
"nr": elem_nr,
|
|
"teileart": "Omniflo Gerade",
|
|
"teileid": generate_shape_id(),
|
|
"nachbarids": "",
|
|
"bezeichnung": f"OFGerade :{gerade_count}",
|
|
"planquadrat": format_planquadrat(block),
|
|
"rotation": block.get("rotation", 0.0),
|
|
"merkmale": build_gerade_merkmale(block),
|
|
})
|
|
continue
|
|
|
|
# ILS Kreisel
|
|
if bname in KREISEL_BLOCKS:
|
|
elem_nr += 1
|
|
kreisel_count += 1
|
|
items.append({
|
|
"nr": elem_nr,
|
|
"teileart": "ILS 2.0 Kreisel",
|
|
"teileid": generate_shape_id(),
|
|
"nachbarids": "",
|
|
"bezeichnung": f"Kreisel :{kreisel_count}",
|
|
"planquadrat": format_planquadrat(block),
|
|
"rotation": block.get("rotation", 0.0),
|
|
"merkmale": build_kreisel_merkmale(block),
|
|
})
|
|
continue
|
|
|
|
return items
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CSV-Formatierung
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def format_csv_line(item):
|
|
merkmale_json = json.dumps(item["merkmale"], ensure_ascii=False)
|
|
return (
|
|
f'{item["nr"]}'
|
|
f';"{item["teileart"]}"'
|
|
f';"{item["teileid"]}"'
|
|
f';{item["nachbarids"]}'
|
|
f';"{item["bezeichnung"]}"'
|
|
f';"{item["planquadrat"]}"'
|
|
f';'
|
|
f';{merkmale_json}'
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Main
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def main():
|
|
if len(sys.argv) < 4:
|
|
print("Aufruf: python export_csv.py <export_raw.json> <data_dir> <output.csv>")
|
|
sys.exit(1)
|
|
|
|
raw_json_path = sys.argv[1]
|
|
data_dir = sys.argv[2]
|
|
output_csv = sys.argv[3]
|
|
|
|
blocks = load_json(raw_json_path)
|
|
boegen_path = os.path.join(data_dir, "json", "omniflo_boegen.json")
|
|
weichen_path = os.path.join(data_dir, "json", "omniflo_weichen.json")
|
|
|
|
boegen = load_json(boegen_path) if os.path.exists(boegen_path) else []
|
|
weichen = load_json(weichen_path) if os.path.exists(weichen_path) else []
|
|
|
|
lookup = build_lookup(boegen, weichen)
|
|
|
|
print(f"[export_csv] {len(blocks)} Bloecke geladen, "
|
|
f"{len(boegen)} Boegen, {len(weichen)} Weichen im Katalog.")
|
|
|
|
items = process_blocks(blocks, lookup)
|
|
|
|
header = "Elementnummer;TeileArt;TeileId;NachbarIds;Bezeichnung;Planquadrat;rotation;Merkmale"
|
|
with open(output_csv, "w", encoding="utf-8") as f:
|
|
f.write(header + "\n")
|
|
for item in items:
|
|
f.write(format_csv_line(item) + "\n")
|
|
|
|
print(f"[export_csv] CSV geschrieben: {output_csv} ({len(items)} Zeilen)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|