From ad287b683d77b05382d93ded2b2d4b1f6e6695c8 Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Thu, 23 Jul 2026 10:13:18 +0200 Subject: [PATCH] CSV-Export: Nachbarschaftserkennung neu aufgebaut (ohne shapely), Fehlerspalte ergaenzt Nachbarschaft wird jetzt in drei getrennten Gruppen geprueft statt global ueber alle Elemente: Kreisel/Eckrad gegeneinander, Kreisel/Eckrad gegen Gefaellestrecke/Foerderer/Strecke-Modul (diese drei nicht gegeneinander), und Omniflo-Elemente gegeneinander (rasterbasiert vorgefiltert nach x/y- Koordinate). Ersetzt die bisherige shapely-STRtree-Loesung durch reines Python, da die shapely-Abhaengigkeit den regulaeren CSV-Export in der von BricsCAD genutzten Python-Umgebung brechen konnte. Neue Spalte "Fehler" markiert Elemente mit zu wenigen Partnern ("unverbunden"/"nur ein Partner") je nach TeileArt-Mindestanzahl. Ausserdem: SSG_RUN_ALL_TESTS-Absturz nach TEST_KREISEL behoben (ssg-start/ ssg-end nutzten flache globale Variablen statt eines Stacks, wodurch verschachtelte Aufrufe den *error*-Handler dauerhaft korrumpierten) und FILEDIA=0 um den DXFOUT-Kommandozeilenaufruf ergaenzt. --- Lisp/ssg_core.lsp | 103 ++++++-- cfg/export.cfg | 40 +++- lib/export_csv.py | 70 ++++-- lib/export_neighbors.py | 236 +++++++++++++++---- requirements.txt | 1 - tests/reference/omniflo_export_reference.csv | 218 ++++++++--------- tests/test_omniflo.py | 2 +- tests/test_run_all.lsp | 19 +- 8 files changed, 491 insertions(+), 198 deletions(-) diff --git a/Lisp/ssg_core.lsp b/Lisp/ssg_core.lsp index 054b481..461a4f3 100644 --- a/Lisp/ssg_core.lsp +++ b/Lisp/ssg_core.lsp @@ -13,25 +13,39 @@ ;; (ssg-start "Titel" '(("OSMODE") ("ORTHOMODE"))) ;; ... Makrocode ... ;; (ssg-end) +;; +;; Nestbar ueber *ssg-start-stack*: jedes ssg-start legt einen eigenen +;; Frame (vorheriger *error*-Handler + Variablenwerte) oben auf den +;; Stack, ssg-end nimmt genau diesen Frame wieder herunter. Noetig, weil +;; z.B. ein Test-Wrapper (ssg-start "TEST_KREISEL" ...) selbst wieder +;; Makros aufruft, die ihrerseits ssg-start/ssg-end nutzen - mit einer +;; einzelnen globalen Variable statt eines Stacks wuerde der innere +;; Aufruf den *error*-Handler und die CLAYER/CMDECHO/...-Werte des +;; aeusseren Aufrufs ueberschreiben. Ergebnis waere ein *error* wird +;; nach dem aeusseren ssg-end dauerhaft an ssg-errhan haengen bleiben +;; (statt zum urspruenglichen Default-Handler zurueckzukehren) und bei +;; jedem folgenden Fehler faelschlich veraltete CLAYER/CECOLOR-Werte +;; ueber "_LAYER"/"_undo" auf die Kommandozeile schreiben. ;; ------------------------------------------------------------ -(defun ssg-start (titel zusatz-vars / xlen xpos xvar) +(if (not (boundp '*ssg-start-stack*)) (setq *ssg-start-stack* nil)) + +(defun ssg-start (titel zusatz-vars / cavar xlen xpos xvar) ;; titel - Anzeigename des Makros ;; zusatz-vars - Liste zusaetzlicher Variablen z.B. '(("OSMODE")("ORTHOMODE")) ;; Immer CLAYER und CMDECHO werden automatisch gesichert. - (setq _ssg-olderr *error* - *error* (function ssg-errhan) - _ssg-cavar (append '(("CLAYER") ("CMDECHO")) zusatz-vars) - xlen (length _ssg-cavar) - xpos 0 + (setq cavar (append '(("CLAYER") ("CMDECHO")) zusatz-vars) + xlen (length cavar) + xpos 0 ) (repeat xlen - (setq xvar (car (nth xpos _ssg-cavar)) - _ssg-cavar (subst (cons xvar (getvar xvar)) - (nth xpos _ssg-cavar) _ssg-cavar) - xpos (1+ xpos) + (setq xvar (car (nth xpos cavar)) + cavar (subst (cons xvar (getvar xvar)) (nth xpos cavar) cavar) + xpos (1+ xpos) ) ) + (setq *ssg-start-stack* (cons (cons *error* cavar) *ssg-start-stack*)) + (setq *error* (function ssg-errhan)) (setvar "CMDECHO" 0) (command "_undo" "_G") (graphscr) @@ -39,26 +53,30 @@ (princ) ) -(defun ssg-end (/ xpos xlen xvar) - (if _ssg-cavar +(defun ssg-end (/ frame cavar xpos xlen xvar) + (if *ssg-start-stack* (progn + (setq frame (car *ssg-start-stack*) + *ssg-start-stack* (cdr *ssg-start-stack*) + cavar (cdr frame) + ) (command) (command "_undo" "_E") (setq xpos 1 - xlen (length _ssg-cavar) + xlen (length cavar) ) - (if (/= (getvar "CLAYER") (caar _ssg-cavar)) - (command "_LAYER" "_SE" (cdar _ssg-cavar) "") + (if (/= (getvar "CLAYER") (caar cavar)) + (command "_LAYER" "_SE" (cdar cavar) "") ) (repeat (1- xlen) - (setq xvar (nth xpos _ssg-cavar) + (setq xvar (nth xpos cavar) xpos (1+ xpos) ) (setvar (car xvar) (cdr xvar)) ) + (setq *error* (car frame)) ) ) - (if _ssg-olderr (setq *error* _ssg-olderr)) (princ) ) @@ -485,7 +503,56 @@ ;; (einsegmentige Gefaellestrecke: 1; Streckengruppe: gezaehlt). (setq *strecke-attr-hinten* '(("ANZAHL_SEPARATOR" "1") - ("ANZAHL_SCANNER" "0"))) + ("ANZAHL_SCANNER" "0") + ("GERUEST_EINZELMODUL" "0") + ("GERUEST_TYP" "Schoenenberger Geruest"))) + +;; ============================================================ +;; GERUESTOPTION - gemeinsame Combobox-Werte fuer Kreisel, Eckrad, +;; VarioFoerderer und Gefaellestrecke (Attribut GERUEST_TYP). +;; Reihenfolge = Reihenfolge in der Dialog-Combobox. Index 2 +;; ("Schoenenberger Geruest") ist der Default. +;; ============================================================ +(setq *ssg-geruest-optionen* + '("IPE-Geruest abgestuft" + "Obergeruest oben" + "Schoenenberger Geruest" + "nur Doppelrohrtraeger") +) + +;; Geruest-Typ (String) -> Combobox-Index. Unbekannter/leerer Wert -> Default (2). +(defun ssg-geruest-typ-to-idx (typ / idx i gefunden) + (setq idx 2 i 0 gefunden nil) + (foreach opt *ssg-geruest-optionen* + (if (and (not gefunden) (equal typ opt)) + (progn (setq idx i) (setq gefunden T)) + ) + (setq i (1+ i)) + ) + idx +) + +;; Combobox-Index -> Geruest-Typ (String). +(defun ssg-geruest-idx-to-typ (idx) + (nth idx *ssg-geruest-optionen*) +) + +;; Geruestoption per Kommandozeilen-Menue abfragen (fuer Module ohne DCL-Dialog, +;; z.B. ILS_Eckrad). Rueckgabe: Geruest-Typ-String aus *ssg-geruest-optionen*. +(defun ssg-ask-geruest-typ ( / i opt antwort idx) + (princ (ssg-text "geruest-typ-header")) + (setq i 1) + (foreach opt *ssg-geruest-optionen* + (princ (ssg-textf "geruest-typ-opt" (list i opt))) + (setq i (1+ i)) + ) + (setq antwort (getint (ssg-textf "geruest-typ-prompt" (list (itoa (1+ (ssg-geruest-typ-to-idx nil))))))) + (if (or (null antwort) (< antwort 1) (> antwort (length *ssg-geruest-optionen*))) + (setq idx (ssg-geruest-typ-to-idx nil)) + (setq idx (1- antwort)) + ) + (ssg-geruest-idx-to-typ idx) +) ;; Geordnete ATTDEF-Definitionsliste fuer einen Strecken-Block-Typ. ;; typ "Gefaellestrecke" -> Vorderteil + Hinterteil (reduziert) diff --git a/cfg/export.cfg b/cfg/export.cfg index 6e187c4..e7b0f7d 100644 --- a/cfg/export.cfg +++ b/cfg/export.cfg @@ -31,9 +31,22 @@ pattern_ks_subblocks= KS_EIN, KS_AUS, K1, K2, K3, K4 [Planquadrate] section=Planquadrate_AN +# x_origin/y_origin (in m, DXF-Koordinate der Planquadrat-Ecke A/1 bzw. 1/1): +# Der Zeichnungsnullpunkt (0,0) liegt in der Regel NICHT in der Gebaeudeecke - +# Bauteile mit negativer x/y-Koordinate wuerden ohne Offset einen Planquadrat- +# Index <= 0 ergeben und damit ein leeres Label (z.B. "/" oder "A/") liefern. +# Leer lassen/weglassen = automatisch: der Ursprung wird bei jedem Export neu +# auf das jeweils am weitesten links (x_origin) bzw. am weitesten unten +# (y_origin) liegende Element der aktuellen Zeichnung gesetzt, damit gilt +# immer Index 1 = dieses Element. Nur explizit setzen, wenn ein fester +# Bezug zur realen Gebaeudeecke gebraucht wird (z.B. Vergleich ueber +# mehrere Exportlaeufe/Zeichnungen hinweg). +x_origin= +y_origin= + # hier kann man im csv Export aus den Koordinaten der Bauteile die Planquadrate berechnen lassen, in denen sie liegen # Zählung ist numerisch oder Alphabetisch möglich, Schrittweite in m (z.B. 2m pro Spalte, 4m pro Zeile) -# liegt man im ersten Quadrat, ist diese A/1, oder 1/1 oder 1/A, je nach Formatierung. Die Zählung beginnt immer bei 1 +# liegt man im ersten Quadrat, ist diese A/1, oder 1/1 oder 1/A, je nach Formatierung. Die Zählung beginnt immer bei 1 [Planquadrate_NA] # z.B. 1/A x_step=2 @@ -48,7 +61,7 @@ x_step=2 x_description=alphabetisch # Buchstaben, von links nach rechts, 2m pro Spalte y_step=2 y_description=alphabetisch # Zahlen von unten nach oben, 2m pro Zeile -format= {x}/{y} +format= {x}/{y} [Planquadrate_NN] # z.B. 2/5 @@ -61,7 +74,22 @@ format= {x}/{y} [Nachbarschaft] # Toleranz fuer die Nachbarschaftserkennung beim CSV-Export (Spalte "Nachbarn"). # Die Bounding-Box jedes Elements wird um die Haelfte dieses Werts nach allen -# Seiten erweitert, bevor per STRtree (shapely) auf Ueberschneidung mit anderen -# Elementen geprueft wird - zwei Elemente mit einem Abstand <= toleranz_mm -# (z.B. zwei Kreisel) gelten dann ebenfalls als benachbart. Wert in mm. -toleranz_mm=200 \ No newline at end of file +# Seiten erweitert, bevor auf Ueberschneidung mit anderen Elementen geprueft +# wird - zwei Elemente mit einem Abstand <= toleranz_mm (z.B. zwei Kreisel) +# gelten dann ebenfalls als benachbart. Wert in mm. Siehe lib/export_neighbors.py. +toleranz_mm=200 + +# Rastergroesse (mm) fuer die Omniflo-Nachbarschaftspruefung (Bogen/Weiche/ +# Gerade gegen Bogen/Weiche/Gerade). Omniflo-Elemente werden vor dem +# Ueberschneidungstest nach x/y-Koordinate in Quadranten dieser Groesse +# eingeteilt, geprueft wird dann nur innerhalb derselben und der 8 +# angrenzenden Zellen (statt jedes Element gegen jedes). Sollte groesser +# als die ueblichen Omniflo-Bauteile sein (AP110-Geraden ca. 2000mm). +omniflo_zellgroesse_mm=3000 + +[Boundingbox] +# Mindesthoehe (Z-Ausdehnung) der von export.lsp (csv:get-bbox, per +# vla-getboundingbox) ermittelten Bounding-Box. Flache 2D-Bloecke (Draufsicht) +# haben oft dz=0 - wird auf diesen Wert angehoben. Wert in mm. Default 1, falls +# nicht gesetzt. +bb_minimum_height_mm=1 \ No newline at end of file diff --git a/lib/export_csv.py b/lib/export_csv.py index 7e296d8..3b91c67 100644 --- a/lib/export_csv.py +++ b/lib/export_csv.py @@ -11,7 +11,7 @@ Aufruf: python export_csv.py CSV-Format: - Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;Nachbarn;Merkmale + Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;Nachbarn;Fehler;Merkmale Position und Boundingbox stammen aus der von export.lsp (csv:get-bbox, per vla-getboundingbox) ermittelten Bounding-Box je Block: @@ -20,10 +20,21 @@ vla-getboundingbox) ermittelten Bounding-Box je Block: Planquadrat wird aus der x/y-Koordinate des Blocks berechnet, siehe export_planquadrat.py ([Planquadrate] in cfg/export.cfg). Nachbarn = kommaseparierte TeileId-Liste ueberschneidender Elemente (Bounding- -Box-Ueberschneidung in der x/y-Ebene per shapely-STRtree, Toleranz konfigurierbar -ueber [Nachbarschaft] -> toleranz_mm in cfg/export.cfg), siehe export_neighbors.py. -Position, Boundingbox, Planquadrat und Nachbarn sind nur fuer EXPORTCSV -vorhanden (nicht EXPORTSIVAS) - siehe csv:run-export. +Box-Ueberschneidung in der x/y-Ebene, reines Python ohne externe Abhaengigkeit, +siehe export_neighbors.py). Geprueft wird NICHT global ueber alle Elemente, +sondern in drei getrennten Gruppen: 1) Kreisel/Eckrad gegen Kreisel/Eckrad, +2) Kreisel/Eckrad gegen Gefaellestrecke/Foerderer/Strecke-Modul (diese drei +nicht gegeneinander), 3) Omniflo-Elemente gegen Omniflo-Elemente (rasterbasiert +vorgefiltert nach x/y-Koordinate). Toleranz und Omniflo-Rastergroesse +konfigurierbar ueber [Nachbarschaft] in cfg/export.cfg. +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/ +Omniflo-Elemente brauchen mindestens einen Partner, Gefaellestrecke/ +Foerderer/Strecke-Modul mindestens zwei (siehe export_neighbors.py +MIN_PARTNER). +Position, Boundingbox, Planquadrat, Nachbarn und Fehler sind nur fuer +EXPORTCSV vorhanden (nicht EXPORTSIVAS) - siehe csv:run-export. """ import json @@ -31,12 +42,18 @@ import sys import os from export_blockpatterns import load_patterns, matches_any -from export_planquadrat import load_planquadrat_config, compute_planquadrat -from export_neighbors import load_neighbor_tolerance_mm, compute_neighbor_ids +from export_planquadrat import load_planquadrat_config, resolve_origins, compute_planquadrat +from export_neighbors import ( + load_neighbor_tolerance_mm, + load_omniflo_cell_size_mm, + compute_neighbor_ids, + compute_neighbor_errors, +) BLOCKPATTERNS = load_patterns() PLANQUADRAT_CFG = load_planquadrat_config() NEIGHBOR_TOLERANCE_MM = load_neighbor_tolerance_mm() +NEIGHBOR_OMNIFLO_CELL_SIZE_MM = load_omniflo_cell_size_mm() # --------------------------------------------------------------------------- @@ -258,19 +275,21 @@ def bbox_columns(block): } -def planquadrat_column(block): +def planquadrat_column(block, planquadrat_cfg): """Berechnet das Planquadrat aus x/y des Blocks (siehe export_planquadrat.py). + planquadrat_cfg = Rueckgabe von resolve_origins() fuer den aktuellen + Exportlauf (x_origin_mm/y_origin_mm bereits aufgeloest). Leerer String, wenn keine Planquadrat-Konfiguration geladen werden konnte (fehlende/unvollstaendige [Planquadrate]-Sektion in cfg/export.cfg). """ - if PLANQUADRAT_CFG is None: + if planquadrat_cfg is None: return "" x = block.get("x") y = block.get("y") if x is None or y is None: return "" - return compute_planquadrat(float(x), float(y), PLANQUADRAT_CFG) + return compute_planquadrat(float(x), float(y), planquadrat_cfg) # --------------------------------------------------------------------------- @@ -285,6 +304,11 @@ SKIP_BLOCKS = set(BLOCKPATTERNS.get("pattern_ks_subblocks", ["K1", "K2", "K3", " # --------------------------------------------------------------------------- def process_blocks(blocks, lookup): + # x_origin_mm/y_origin_mm einmalig fuer diesen Exportlauf aufloesen (siehe + # export_planquadrat.resolve_origins): automatisch aus den Bloecken, falls + # nicht explizit in [Planquadrate] konfiguriert. + planquadrat_cfg = resolve_origins(PLANQUADRAT_CFG, blocks) + items = [] elem_nr = 0 bogen_count = 0 @@ -322,7 +346,7 @@ def process_blocks(blocks, lookup): "teileart": "Omniflo Kurve", "teileid": shape_id, "bezeichnung": f"OFBogen :{bogen_count}", - "planquadrat": planquadrat_column(block), + "planquadrat": planquadrat_column(block, planquadrat_cfg), "merkmale": build_bogen_merkmale(block, eintrag), **bbox_columns(block), }) @@ -335,7 +359,7 @@ def process_blocks(blocks, lookup): "teileart": "Omniflo Weiche", "teileid": shape_id, "bezeichnung": f"OFWeiche :{weiche_count[wt]}", - "planquadrat": planquadrat_column(block), + "planquadrat": planquadrat_column(block, planquadrat_cfg), "merkmale": build_weiche_merkmale(block, eintrag), **bbox_columns(block), }) @@ -362,7 +386,7 @@ def process_blocks(blocks, lookup): "teileart": "Omniflo Gerade", "teileid": block.get("attribs", {}).get("ID", "0000"), "bezeichnung": f"OFGerade :{gerade_count}", - "planquadrat": planquadrat_column(block), + "planquadrat": planquadrat_column(block, planquadrat_cfg), "merkmale": build_gerade_merkmale(block), **bbox_columns(block), }) @@ -378,7 +402,7 @@ def process_blocks(blocks, lookup): "teileart": "ILS 2.0 Strecke", "teileid": block.get("attribs", {}).get("ID", "0000"), "bezeichnung": f"VarioFoerderer :{vf_count}", - "planquadrat": planquadrat_column(block), + "planquadrat": planquadrat_column(block, planquadrat_cfg), "merkmale": build_variofoerderer_merkmale(block), **bbox_columns(block), }) @@ -393,7 +417,7 @@ def process_blocks(blocks, lookup): "teileart": "ILS 2.0 Gefaellestrecke", "teileid": block.get("attribs", {}).get("ID", "0000"), "bezeichnung": f"Gefaellestrecke :{gf_count}", - "planquadrat": planquadrat_column(block), + "planquadrat": planquadrat_column(block, planquadrat_cfg), "merkmale": build_variofoerderer_merkmale(block), **bbox_columns(block), }) @@ -409,7 +433,7 @@ def process_blocks(blocks, lookup): "teileart": "ILS 2.0 Eckrad", "teileid": block.get("attribs", {}).get("ID", "0000"), "bezeichnung": f"Eckrad :{eckrad_count}", - "planquadrat": planquadrat_column(block), + "planquadrat": planquadrat_column(block, planquadrat_cfg), "merkmale": build_kreisel_merkmale(block), **bbox_columns(block), }) @@ -424,7 +448,7 @@ def process_blocks(blocks, lookup): "teileart": "ILS 2.0 Kreisel", "teileid": block.get("attribs", {}).get("ID", "0000"), "bezeichnung": f"Kreisel :{kreisel_count}", - "planquadrat": planquadrat_column(block), + "planquadrat": planquadrat_column(block, planquadrat_cfg), "merkmale": build_kreisel_merkmale(block), **bbox_columns(block), }) @@ -439,7 +463,7 @@ def process_blocks(blocks, lookup): "teileart": "ILS 2.0 Strecke - Modul", "teileid": block.get("attribs", {}).get("ID", "0000"), "bezeichnung": f"Streckenmodul :{strecke_modul_count}", - "planquadrat": planquadrat_column(block), + "planquadrat": planquadrat_column(block, planquadrat_cfg), "merkmale": {"Blockname": bname}, **bbox_columns(block), }) @@ -460,9 +484,12 @@ def process_blocks(blocks, lookup): "boundingbox": "", }) - neighbor_ids = compute_neighbor_ids(items, NEIGHBOR_TOLERANCE_MM) - for item, nachbarn in zip(items, neighbor_ids): + neighbor_ids = compute_neighbor_ids( + items, NEIGHBOR_TOLERANCE_MM, NEIGHBOR_OMNIFLO_CELL_SIZE_MM) + neighbor_errors = compute_neighbor_errors(items, neighbor_ids) + for item, nachbarn, fehler in zip(items, neighbor_ids, neighbor_errors): item["nachbarn"] = nachbarn + item["fehler"] = fehler return items @@ -483,6 +510,7 @@ def format_csv_line(item): f';"{item["position"]}"' f';"{item["boundingbox"]}"' f';"{item["nachbarn"]}"' + f';"{item["fehler"]}"' f';{merkmale_json}' ) @@ -514,7 +542,7 @@ def main(): items = process_blocks(blocks, lookup) - header = "Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;Nachbarn;Merkmale" + header = "Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;Nachbarn;Fehler;Merkmale" with open(output_csv, "w", encoding="utf-8") as f: f.write(header + "\n") for item in items: diff --git a/lib/export_neighbors.py b/lib/export_neighbors.py index 98117aa..d66ab48 100644 --- a/lib/export_neighbors.py +++ b/lib/export_neighbors.py @@ -1,27 +1,57 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -export_neighbors.py - Ermittelt benachbarte Elemente ueber die Bounding-Box (STRtree). +export_neighbors.py - Ermittelt benachbarte Elemente ueber Bounding-Box- +Ueberschneidung in der x/y-Ebene (Grundriss, Z/Hoehe wird ignoriert). -Zwei Elemente gelten als benachbart, wenn ihre Bounding-Boxes sich in der -x/y-Ebene (Grundriss, Z/Hoehe wird ignoriert) ueberschneiden. Um auch nah -beieinander liegende, aber nicht direkt beruehrende Elemente (z.B. Kreisel) -als benachbart zu erkennen, wird jede Bounding-Box vor der Pruefung um die -Haelfte der konfigurierten Toleranz nach allen Seiten erweitert - zwei -Elemente mit einem Abstand <= toleranz_mm gelten dann ebenfalls als -benachbart. Die Toleranz wird aus cfg/export.cfg ([Nachbarschaft] -> -toleranz_mm) gelesen. +Reines Python (keine externe Abhaengigkeit wie shapely) - die Bloecke werden +dazu in drei Gruppen eingeteilt und NUR innerhalb dieser Kombinationen +gegeneinander geprueft (nicht mehr alle Elemente einer Zeichnung gemeinsam): + + 1. Kreisel/Eckrad gegen Kreisel/Eckrad + 2. Kreisel/Eckrad gegen Gefaellestrecke/Foerderer/Strecke-Modul - diese + drei Kategorien werden NICHT gegeneinander getestet (nur relevant, wo + sie an einen Kreisel/Eckrad anschliessen) + 3. Omniflo-Elemente (Bogen/Weiche/Gerade) gegen Omniflo-Elemente + +Omniflo-Anlagen koennen mehrere hundert Elemente enthalten - ein Test jedes +gegen jedes (O(n^2)) waere dort zu teuer. Die Omniflo-Gruppe wird daher vorab +per Raster (Zellgroesse siehe [Nachbarschaft] -> omniflo_zellgroesse_mm in +cfg/export.cfg) nach x/y-Koordinate in Quadranten/Zellen eingeteilt; jedes +Element wird nur gegen Elemente in derselben und den 8 angrenzenden Zellen +geprueft (3x3-Nachbarschaft, damit auch Elemente knapp jenseits einer +Zellgrenze noch erkannt werden). + +Zwei Bounding-Boxes gelten als benachbart, wenn sie sich (nach Erweiterung +um die halbe Toleranz je Seite) in x/y ueberschneiden. Toleranz aus +cfg/export.cfg ([Nachbarschaft] -> toleranz_mm), Wert in mm. + +compute_neighbor_errors() prueft zusaetzlich, ob jedes Element die fuer +seine TeileArt noetige Mindestanzahl an Partnern (Nachbarn) hat (siehe +MIN_PARTNER) - Ergebnis ist die CSV-Spalte "Fehler" in export_csv.py. Nur von export_csv.py genutzt (EXPORTCSV), nicht von export_sivas.py. """ import configparser -from shapely.geometry import box -from shapely.strtree import STRtree - from export_blockpatterns import cfg_path_from_env +KREISEL_TEILEARTEN = {"ILS 2.0 Kreisel", "ILS 2.0 Eckrad"} +STRECKEN_TEILEARTEN = {"ILS 2.0 Gefaellestrecke", "ILS 2.0 Strecke", "ILS 2.0 Strecke - Modul"} +OMNIFLO_TEILEARTEN = {"Omniflo Kurve", "Omniflo Weiche", "Omniflo Gerade"} + +# Mindestanzahl Partner (Nachbarn) je TeileArt fuer die Fehlerspalte "Fehler" +# (siehe compute_neighbor_errors): Kreisel/Eckrad und Omniflo-Elemente +# brauchen mindestens einen Partner, Gefaellestrecke/Foerderer/Strecke-Modul +# muessen an zwei Seiten anschliessen (mindestens zwei Partner). TeileArten, +# die hier nicht auftauchen (z.B. die synthetische "Omniflo Sum"-Zeile), +# werden nicht geprueft. +MIN_PARTNER = {} +MIN_PARTNER.update({t: 1 for t in KREISEL_TEILEARTEN}) +MIN_PARTNER.update({t: 1 for t in OMNIFLO_TEILEARTEN}) +MIN_PARTNER.update({t: 2 for t in STRECKEN_TEILEARTEN}) + def load_neighbor_tolerance_mm(cfg_path=None): """Liest die Nachbarschafts-Toleranz (mm) aus export.cfg. Default: 0.""" @@ -32,41 +62,165 @@ def load_neighbor_tolerance_mm(cfg_path=None): return parser.getfloat("Nachbarschaft", "toleranz_mm", fallback=0.0) -def compute_neighbor_ids(items, tolerance_mm): - """Ermittelt je Item die IDs (item["teileid"]) ueberschneidender Nachbarn. +def load_omniflo_cell_size_mm(cfg_path=None): + """Liest die Rastergroesse (mm) fuer die Omniflo-Nachbarschaftspruefung. - items = Liste von dict mit "teileid" und optional "_bbox" - ({"cx","cy","dx","dy",...}, siehe export.lsp csv:get-bbox / export_csv.py - bbox_columns). Items ohne _bbox (z.B. die synthetische Omniflo-Sum-Zeile) - haben keine Nachbarn. + Default 3000mm: groesser als die ueblichen Omniflo-Bauteile (AP110- + Geraden ca. 2000mm), damit ein Element nicht durch ein zu kleines + Raster in mehr als eine Zelle ueberlappt. + """ + if cfg_path is None: + cfg_path = cfg_path_from_env() + parser = configparser.ConfigParser(inline_comment_prefixes=("#",)) + parser.read(cfg_path, encoding="utf-8") + return parser.getfloat("Nachbarschaft", "omniflo_zellgroesse_mm", fallback=3000.0) + + +def _bounds(bbox, half_tol): + """(minx, maxx, miny, maxy) einer Bounding-Box, je Seite um half_tol erweitert.""" + return ( + bbox["cx"] - bbox["dx"] / 2.0 - half_tol, + bbox["cx"] + bbox["dx"] / 2.0 + half_tol, + bbox["cy"] - bbox["dy"] / 2.0 - half_tol, + bbox["cy"] + bbox["dy"] / 2.0 + half_tol, + ) + + +def _overlaps(bounds_a, bounds_b): + """True, wenn sich zwei (minx, maxx, miny, maxy)-Rechtecke in x/y ueberschneiden.""" + a_minx, a_maxx, a_miny, a_maxy = bounds_a + b_minx, b_maxx, b_miny, b_maxy = bounds_b + return a_minx <= b_maxx and b_minx <= a_maxx and a_miny <= b_maxy and b_miny <= a_maxy + + +def _add_neighbor(result, idx_a, idx_b, id_a, id_b): + result[idx_a].append(id_b) + result[idx_b].append(id_a) + + +def _test_group_pairs(group, result): + """Alle Paare EINER Gruppe gegeneinander testen (O(n^2) - fuer Kreisel/ + Eckrad-Stueckzahlen pro Zeichnung unkritisch).""" + n = len(group) + for a in range(n): + idx_a, bounds_a, id_a = group[a] + for b in range(a + 1, n): + idx_b, bounds_b, id_b = group[b] + if _overlaps(bounds_a, bounds_b): + _add_neighbor(result, idx_a, idx_b, id_a, id_b) + + +def _test_group_against_group(group_a, group_b, result): + """Jedes Element aus group_a gegen jedes Element aus group_b testen. + group_b wird NICHT gegen sich selbst getestet (Aufgabe des Aufrufers).""" + for idx_a, bounds_a, id_a in group_a: + for idx_b, bounds_b, id_b in group_b: + if _overlaps(bounds_a, bounds_b): + _add_neighbor(result, idx_a, idx_b, id_a, id_b) + + +def _grid_cell(bbox, cell_size_mm): + """Rasterzelle (Quadrant) einer Bounding-Box nach ihrem Mittelpunkt.""" + return (int(bbox["cx"] // cell_size_mm), int(bbox["cy"] // cell_size_mm)) + + +def _test_omniflo_grid(group, cell_size_mm, result): + """Omniflo-Elemente nur gegen Elemente in derselben oder einer der 8 + angrenzenden Rasterzellen testen (3x3-Nachbarschaft) statt gegen alle - + haelt den Aufwand bei mehreren hundert Omniflo-Elementen niedrig, ohne + Ueberschneidungen an Zellgrenzen zu verpassen.""" + buckets = {} + for entry in group: + idx, bounds, teileid, bbox = entry + buckets.setdefault(_grid_cell(bbox, cell_size_mm), []).append(entry) + + checked = set() + for (cx, cy), cell_items in buckets.items(): + candidates = [] + for dx in (-1, 0, 1): + for dy in (-1, 0, 1): + candidates.extend(buckets.get((cx + dx, cy + dy), [])) + + for idx_a, bounds_a, id_a, _ in cell_items: + for idx_b, bounds_b, id_b, _ in candidates: + if idx_a >= idx_b: + continue + pair = (idx_a, idx_b) + if pair in checked: + continue + checked.add(pair) + if _overlaps(bounds_a, bounds_b): + _add_neighbor(result, idx_a, idx_b, id_a, id_b) + + +def compute_neighbor_ids(items, tolerance_mm, omniflo_cell_size_mm=3000.0): + """Ermittelt je Item die IDs (item["teileid"]) benachbarter Elemente. + + items = Liste von dict mit "teileart", "teileid" und optional "_bbox" + ({"cx","cy","dx","dy",...}, siehe export_csv.py bbox_columns). Items + ohne _bbox (z.B. die synthetische Omniflo-Sum-Zeile) bleiben ohne + Nachbarn. Rueckgabe: Liste von kommaseparierten Nachbar-ID-Strings, positionsgleich zu items (nicht ueber die ID dedupliziert, da TeileId nicht zwingend eindeutig ist). """ - idx_with_bbox = [i for i, it in enumerate(items) if it.get("_bbox")] - result = [""] * len(items) - if len(idx_with_bbox) < 2: - return result - half_tol = tolerance_mm / 2.0 - geoms = [] - for i in idx_with_bbox: - bb = items[i]["_bbox"] - minx = bb["cx"] - bb["dx"] / 2.0 - half_tol - maxx = bb["cx"] + bb["dx"] / 2.0 + half_tol - miny = bb["cy"] - bb["dy"] / 2.0 - half_tol - maxy = bb["cy"] + bb["dy"] / 2.0 + half_tol - geoms.append(box(minx, miny, maxx, maxy)) + result = [[] for _ in items] - tree = STRtree(geoms) - for local_i, global_i in enumerate(idx_with_bbox): - hits = tree.query(geoms[local_i], predicate="intersects") - neighbor_ids = [ - items[idx_with_bbox[int(local_j)]]["teileid"] - for local_j in hits - if int(local_j) != local_i - ] - result[global_i] = ", ".join(neighbor_ids) + kreisel_group = [] + strecken_group = [] + omniflo_group = [] - return result + for idx, item in enumerate(items): + bbox = item.get("_bbox") + if not bbox: + continue + teileart = item.get("teileart", "") + teileid = item.get("teileid", "") + bounds = _bounds(bbox, half_tol) + if teileart in KREISEL_TEILEARTEN: + kreisel_group.append((idx, bounds, teileid)) + elif teileart in STRECKEN_TEILEARTEN: + strecken_group.append((idx, bounds, teileid)) + elif teileart in OMNIFLO_TEILEARTEN: + omniflo_group.append((idx, bounds, teileid, bbox)) + + # 1. Kreisel/Eckrad gegen Kreisel/Eckrad + _test_group_pairs(kreisel_group, result) + + # 2. Kreisel/Eckrad gegen Gefaellestrecke/Foerderer/Strecke-Modul - + # diese drei Kategorien nicht gegeneinander (siehe Modul-Docstring) + _test_group_against_group(kreisel_group, strecken_group, result) + + # 3. Omniflo gegen Omniflo, rasterbasiert vorgefiltert + _test_omniflo_grid(omniflo_group, omniflo_cell_size_mm, result) + + return [", ".join(neighbor_ids) for neighbor_ids in result] + + +def compute_neighbor_errors(items, neighbor_ids): + """Prueft je Item die Mindestanzahl an Partnern (siehe MIN_PARTNER). + + items = dieselbe Liste wie bei compute_neighbor_ids (braucht "teileart"). + neighbor_ids = Rueckgabe von compute_neighbor_ids (positionsgleich zu items). + + Rueckgabe: Liste von Fehlertexten, positionsgleich zu items: + "unverbunden" - keine Partner, obwohl mindestens einer noetig waere + "nur ein Partner" - genau ein Partner, obwohl mindestens zwei noetig waeren + "" - Mindestanzahl erreicht, oder TeileArt wird nicht geprueft + """ + errors = [] + for item, nachbarn in zip(items, neighbor_ids): + min_partner = MIN_PARTNER.get(item.get("teileart", "")) + if min_partner is None: + errors.append("") + continue + anzahl = len([p for p in nachbarn.split(",") if p.strip()]) + if anzahl == 0: + errors.append("unverbunden") + elif anzahl == 1 and min_partner >= 2: + errors.append("nur ein Partner") + else: + errors.append("") + return errors diff --git a/requirements.txt b/requirements.txt index a34eb0c..59150b5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,5 +3,4 @@ ezdxf==1.4.1 pytest==9.0.2 -shapely==2.1.2 diff --git a/tests/reference/omniflo_export_reference.csv b/tests/reference/omniflo_export_reference.csv index 35988b3..b13c0e5 100644 --- a/tests/reference/omniflo_export_reference.csv +++ b/tests/reference/omniflo_export_reference.csv @@ -1,109 +1,109 @@ -Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;Nachbarn;Merkmale -1;"Omniflo Kurve";"0000";"OFBogen :1";"A/A";1;"";"";"";{"Kurvenwinkel": 22.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104025"} -2;"Omniflo Kurve";"0000";"OFBogen :2";"A/A";1;"";"";"";{"Kurvenwinkel": 22.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104025+0_B10090"} -3;"Omniflo Kurve";"0000";"OFBogen :3";"A/A";1;"";"";"";{"Kurvenwinkel": 22.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104025+0_B10091"} -4;"Omniflo Kurve";"0000";"OFBogen :4";"A/A";1;"";"";"";{"Kurvenwinkel": 45.0, "Radius": 400.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104021"} -5;"Omniflo Kurve";"0000";"OFBogen :5";"A/A";1;"";"";"";{"Kurvenwinkel": 45.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104026"} -6;"Omniflo Kurve";"0000";"OFBogen :6";"A/A";1;"";"";"";{"Kurvenwinkel": 45.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104026+0_B10071"} -7;"Omniflo Kurve";"0000";"OFBogen :7";"A/A";1;"";"";"";{"Kurvenwinkel": 45.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104037"} -8;"Omniflo Kurve";"0000";"OFBogen :8";"A/A";1;"";"";"";{"Kurvenwinkel": 45.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104029"} -9;"Omniflo Kurve";"0000";"OFBogen :9";"A/A";1;"";"";"";{"Kurvenwinkel": 45.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104031"} -10;"Omniflo Kurve";"0000";"OFBogen :10";"A/A";1;"";"";"";{"Kurvenwinkel": 45.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104031+0_B10060"} -11;"Omniflo Kurve";"0000";"OFBogen :11";"B/A";1;"";"";"";{"Kurvenwinkel": 45.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104031+0_B10070"} -12;"Omniflo Kurve";"0000";"OFBogen :12";"B/A";1;"";"";"";{"Kurvenwinkel": 67.5, "Radius": 400.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104024"} -13;"Omniflo Kurve";"0000";"OFBogen :13";"B/A";1;"";"";"";{"Kurvenwinkel": 67.5, "Radius": 400.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104024+0_B10081"} -14;"Omniflo Kurve";"0000";"OFBogen :14";"B/A";1;"";"";"";{"Kurvenwinkel": 67.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104027"} -15;"Omniflo Kurve";"0000";"OFBogen :15";"B/A";1;"";"";"";{"Kurvenwinkel": 67.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104027+0_B10080"} -16;"Omniflo Kurve";"0000";"OFBogen :16";"B/A";1;"";"";"";{"Kurvenwinkel": 67.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104028"} -17;"Omniflo Kurve";"0000";"OFBogen :17";"B/A";1;"";"";"";{"Kurvenwinkel": 67.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104065"} -18;"Omniflo Kurve";"0000";"OFBogen :18";"B/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 400.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104022"} -19;"Omniflo Kurve";"0000";"OFBogen :19";"B/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 500.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104030"} -20;"Omniflo Kurve";"0000";"OFBogen :20";"B/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104033"} -21;"Omniflo Kurve";"0000";"OFBogen :21";"C/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104033+0_B10040"} -22;"Omniflo Kurve";"0000";"OFBogen :22";"C/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104033+0_B10050"} -23;"Omniflo Kurve";"0000";"OFBogen :23";"C/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104035"} -24;"Omniflo Kurve";"0000";"OFBogen :24";"C/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104041"} -25;"Omniflo Kurve";"0000";"OFBogen :25";"C/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104034"} -26;"Omniflo Kurve";"0000";"OFBogen :26";"C/A";1;"";"";"";{"Kurvenwinkel": 90.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104066"} -27;"Omniflo Kurve";"0000";"OFBogen :27";"C/A";1;"";"";"";{"Kurvenwinkel": 180.0, "Radius": 650.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104043"} -28;"Omniflo Weiche";"0000";"OFWeiche :1";"C/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342011"} -29;"Omniflo Weiche";"0000";"OFWeiche :2";"C/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342001"} -30;"Omniflo Weiche";"0000";"OFWeiche :3";"C/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342012"} -31;"Omniflo Weiche";"0000";"OFWeiche :4";"D/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342002"} -32;"Omniflo Weiche";"0000";"OFWeiche :1";"D/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342100"} -33;"Omniflo Weiche";"0000";"OFWeiche :2";"D/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342101"} -34;"Omniflo Weiche";"0000";"OFWeiche :1";"D/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342200"} -35;"Omniflo Weiche";"0000";"OFWeiche :2";"D/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342201"} -36;"Omniflo Weiche";"0000";"OFWeiche :5";"D/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372001"} -37;"Omniflo Weiche";"0000";"OFWeiche :6";"D/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372002"} -38;"Omniflo Weiche";"0000";"OFWeiche :7";"D/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372002+0_BG090090"} -39;"Omniflo Weiche";"0000";"OFWeiche :8";"D/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372004"} -40;"Omniflo Weiche";"0000";"OFWeiche :9";"D/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372005"} -41;"Omniflo Weiche";"0000";"OFWeiche :10";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372005+0_BG090090"} -42;"Omniflo Weiche";"0000";"OFWeiche :11";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372007"} -43;"Omniflo Weiche";"0000";"OFWeiche :12";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372008"} -44;"Omniflo Weiche";"0000";"OFWeiche :13";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372008+0_BG190090"} -45;"Omniflo Weiche";"0000";"OFWeiche :14";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372010"} -46;"Omniflo Weiche";"0000";"OFWeiche :15";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372011"} -47;"Omniflo Weiche";"0000";"OFWeiche :16";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372011+0_BG190090"} -48;"Omniflo Weiche";"0000";"OFWeiche :17";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372021"} -49;"Omniflo Weiche";"0000";"OFWeiche :18";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372022"} -50;"Omniflo Weiche";"0000";"OFWeiche :19";"E/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372024"} -51;"Omniflo Weiche";"0000";"OFWeiche :20";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372025"} -52;"Omniflo Weiche";"0000";"OFWeiche :21";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372027"} -53;"Omniflo Weiche";"0000";"OFWeiche :22";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372028"} -54;"Omniflo Weiche";"0000";"OFWeiche :23";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372028+0_BG080090"} -55;"Omniflo Weiche";"0000";"OFWeiche :24";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372030"} -56;"Omniflo Weiche";"0000";"OFWeiche :25";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372031"} -57;"Omniflo Weiche";"0000";"OFWeiche :26";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372031+0_BG080090"} -58;"Omniflo Weiche";"0000";"OFWeiche :27";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372047"} -59;"Omniflo Weiche";"0000";"OFWeiche :28";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372048"} -60;"Omniflo Weiche";"0000";"OFWeiche :29";"F/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372050"} -61;"Omniflo Weiche";"0000";"OFWeiche :30";"G/A";1;"";"";"";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372051"} -62;"Omniflo Weiche";"0000";"OFWeiche :3";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372100"} -63;"Omniflo Weiche";"0000";"OFWeiche :4";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372101"} -64;"Omniflo Weiche";"0000";"OFWeiche :5";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG090090+834372101"} -65;"Omniflo Weiche";"0000";"OFWeiche :6";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372101+0_BG090090"} -66;"Omniflo Weiche";"0000";"OFWeiche :7";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG090090+834372101+0_BG090090"} -67;"Omniflo Weiche";"0000";"OFWeiche :8";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372103"} -68;"Omniflo Weiche";"0000";"OFWeiche :9";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372104"} -69;"Omniflo Weiche";"0000";"OFWeiche :10";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG190090+834372104"} -70;"Omniflo Weiche";"0000";"OFWeiche :11";"G/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372104+0_BG190090"} -71;"Omniflo Weiche";"0000";"OFWeiche :12";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG190090+834372104+0_BG190090"} -72;"Omniflo Weiche";"0000";"OFWeiche :13";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372106"} -73;"Omniflo Weiche";"0000";"OFWeiche :14";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372107"} -74;"Omniflo Weiche";"0000";"OFWeiche :15";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372109"} -75;"Omniflo Weiche";"0000";"OFWeiche :16";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372110"} -76;"Omniflo Weiche";"0000";"OFWeiche :17";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG080090+834372110"} -77;"Omniflo Weiche";"0000";"OFWeiche :18";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372110+0_BG080090"} -78;"Omniflo Weiche";"0000";"OFWeiche :19";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG080090+834372110+0_BG080090"} -79;"Omniflo Weiche";"0000";"OFWeiche :20";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372115"} -80;"Omniflo Weiche";"0000";"OFWeiche :21";"H/A";1;"";"";"";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372116"} -81;"Omniflo Weiche";"0000";"OFWeiche :3";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372200"} -82;"Omniflo Weiche";"0000";"OFWeiche :4";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372201"} -83;"Omniflo Weiche";"0000";"OFWeiche :5";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG090090+834372201"} -84;"Omniflo Weiche";"0000";"OFWeiche :6";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372201+0_BG090090"} -85;"Omniflo Weiche";"0000";"OFWeiche :7";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG090090+834372201+0_BG090090"} -86;"Omniflo Weiche";"0000";"OFWeiche :8";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372203"} -87;"Omniflo Weiche";"0000";"OFWeiche :9";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372204"} -88;"Omniflo Weiche";"0000";"OFWeiche :10";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG190090+834372204"} -89;"Omniflo Weiche";"0000";"OFWeiche :11";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372204+0_BG190090"} -90;"Omniflo Weiche";"0000";"OFWeiche :12";"I/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG190090+834372204+0_BG190090"} -91;"Omniflo Weiche";"0000";"OFWeiche :13";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372206"} -92;"Omniflo Weiche";"0000";"OFWeiche :14";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372207"} -93;"Omniflo Weiche";"0000";"OFWeiche :15";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372209"} -94;"Omniflo Weiche";"0000";"OFWeiche :16";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372210"} -95;"Omniflo Weiche";"0000";"OFWeiche :17";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG080090+834372210"} -96;"Omniflo Weiche";"0000";"OFWeiche :18";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372210+0_BG080090"} -97;"Omniflo Weiche";"0000";"OFWeiche :19";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG080090+834372210+0_BG080090"} -98;"Omniflo Weiche";"0000";"OFWeiche :20";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372215"} -99;"Omniflo Weiche";"0000";"OFWeiche :21";"J/A";1;"";"";"";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372216"} -100;"Omniflo Weiche";"0000";"OFWeiche :1";"J/A";1;"";"";"";{"Weichentyp": "Dreifachweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372400"} -101;"Omniflo Weiche";"0000";"OFWeiche :2";"K/A";1;"";"";"";{"Weichentyp": "Dreifachweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372403"} -102;"Omniflo Weiche";"0000";"OFWeiche :3";"K/A";1;"";"";"";{"Weichentyp": "Dreifachweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372404"} -103;"Omniflo Weiche";"0000";"OFWeiche :4";"K/A";1;"";"";"";{"Weichentyp": "Dreifachweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG071090+834372404+0_BG071090"} -104;"Omniflo Weiche";"0000";"OFWeiche :5";"K/A";1;"";"";"";{"Weichentyp": "Dreifachweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG071090+834372404"} -105;"Omniflo Weiche";"0000";"OFWeiche :6";"K/A";1;"";"";"";{"Weichentyp": "Dreifachweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372404+0_BG071090"} -106;"Omniflo Weiche";"0000";"OFWeiche :1";"K/A";1;"";"";"";{"Weichentyp": "Deltaweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372401"} -107;"Omniflo Weiche";"0000";"OFWeiche :1";"K/A";1;"";"";"";{"Weichentyp": "Sternweiche", "Richtung": "3", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372420"} -108;"Omniflo Sum";"autogenerated_of_json";"Omniflo sum";"";1;"";"";"";{"Anzahl Bögen": 27, "Anzahl Weichengrundkörper": 0, "Anzahl Einwegweichen": 30, "Anzahl Deltaweichen": 7, "Anzahl Doppelweichen und Dreiwegeweichen": 42, "Anzahl Sternweichen": 1, "Gesamtlänge AP110": 0.0, "Gesamtlänge AP60": 0.0} +Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;Nachbarn;Fehler;Merkmale +1;"Omniflo Kurve";"0000";"OFBogen :1";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 22.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104025"} +2;"Omniflo Kurve";"0000";"OFBogen :2";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 22.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104025, 0_B10090"} +3;"Omniflo Kurve";"0000";"OFBogen :3";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 22.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104025, 0_B10091"} +4;"Omniflo Kurve";"0000";"OFBogen :4";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 45.0, "Radius": 400.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104021"} +5;"Omniflo Kurve";"0000";"OFBogen :5";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 45.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104026"} +6;"Omniflo Kurve";"0000";"OFBogen :6";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 45.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104026, 0_B10071"} +7;"Omniflo Kurve";"0000";"OFBogen :7";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 45.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104037"} +8;"Omniflo Kurve";"0000";"OFBogen :8";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 45.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104029"} +9;"Omniflo Kurve";"0000";"OFBogen :9";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 45.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104031"} +10;"Omniflo Kurve";"0000";"OFBogen :10";"A/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 45.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104031, 0_B10060"} +11;"Omniflo Kurve";"0000";"OFBogen :11";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 45.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104031, 0_B10070"} +12;"Omniflo Kurve";"0000";"OFBogen :12";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 67.5, "Radius": 400.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104024"} +13;"Omniflo Kurve";"0000";"OFBogen :13";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 67.5, "Radius": 400.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104024, 0_B10081"} +14;"Omniflo Kurve";"0000";"OFBogen :14";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 67.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104027"} +15;"Omniflo Kurve";"0000";"OFBogen :15";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 67.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104027, 0_B10080"} +16;"Omniflo Kurve";"0000";"OFBogen :16";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 67.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104028"} +17;"Omniflo Kurve";"0000";"OFBogen :17";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 67.5, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104065"} +18;"Omniflo Kurve";"0000";"OFBogen :18";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 400.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104022"} +19;"Omniflo Kurve";"0000";"OFBogen :19";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 500.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104030"} +20;"Omniflo Kurve";"0000";"OFBogen :20";"B/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104033"} +21;"Omniflo Kurve";"0000";"OFBogen :21";"C/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104033, 0_B10040"} +22;"Omniflo Kurve";"0000";"OFBogen :22";"C/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104033, 0_B10050"} +23;"Omniflo Kurve";"0000";"OFBogen :23";"C/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104035"} +24;"Omniflo Kurve";"0000";"OFBogen :24";"C/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104041"} +25;"Omniflo Kurve";"0000";"OFBogen :25";"C/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 630.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104034"} +26;"Omniflo Kurve";"0000";"OFBogen :26";"C/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 90.0, "Radius": 550.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104066"} +27;"Omniflo Kurve";"0000";"OFBogen :27";"C/A";1;"";"";"";"unverbunden";{"Kurvenwinkel": 180.0, "Radius": 650.0, "Höhe": "2000", "Drehung": 0.0, "SivasNummer": "821104043"} +28;"Omniflo Weiche";"0000";"OFWeiche :1";"C/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342011"} +29;"Omniflo Weiche";"0000";"OFWeiche :2";"C/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342001"} +30;"Omniflo Weiche";"0000";"OFWeiche :3";"C/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342012"} +31;"Omniflo Weiche";"0000";"OFWeiche :4";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342002"} +32;"Omniflo Weiche";"0000";"OFWeiche :1";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342100"} +33;"Omniflo Weiche";"0000";"OFWeiche :2";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342101"} +34;"Omniflo Weiche";"0000";"OFWeiche :1";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342200"} +35;"Omniflo Weiche";"0000";"OFWeiche :2";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 22.5, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834342201"} +36;"Omniflo Weiche";"0000";"OFWeiche :5";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372001"} +37;"Omniflo Weiche";"0000";"OFWeiche :6";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372002"} +38;"Omniflo Weiche";"0000";"OFWeiche :7";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372002, 0_BG090090"} +39;"Omniflo Weiche";"0000";"OFWeiche :8";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372004"} +40;"Omniflo Weiche";"0000";"OFWeiche :9";"D/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372005"} +41;"Omniflo Weiche";"0000";"OFWeiche :10";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372005, 0_BG090090"} +42;"Omniflo Weiche";"0000";"OFWeiche :11";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372007"} +43;"Omniflo Weiche";"0000";"OFWeiche :12";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372008"} +44;"Omniflo Weiche";"0000";"OFWeiche :13";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372008, 0_BG190090"} +45;"Omniflo Weiche";"0000";"OFWeiche :14";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372010"} +46;"Omniflo Weiche";"0000";"OFWeiche :15";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372011"} +47;"Omniflo Weiche";"0000";"OFWeiche :16";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372011, 0_BG190090"} +48;"Omniflo Weiche";"0000";"OFWeiche :17";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372021"} +49;"Omniflo Weiche";"0000";"OFWeiche :18";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372022"} +50;"Omniflo Weiche";"0000";"OFWeiche :19";"E/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372024"} +51;"Omniflo Weiche";"0000";"OFWeiche :20";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372025"} +52;"Omniflo Weiche";"0000";"OFWeiche :21";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372027"} +53;"Omniflo Weiche";"0000";"OFWeiche :22";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372028"} +54;"Omniflo Weiche";"0000";"OFWeiche :23";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372028, 0_BG080090"} +55;"Omniflo Weiche";"0000";"OFWeiche :24";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372030"} +56;"Omniflo Weiche";"0000";"OFWeiche :25";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372031"} +57;"Omniflo Weiche";"0000";"OFWeiche :26";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372031, 0_BG080090"} +58;"Omniflo Weiche";"0000";"OFWeiche :27";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372047"} +59;"Omniflo Weiche";"0000";"OFWeiche :28";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "1", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372048"} +60;"Omniflo Weiche";"0000";"OFWeiche :29";"F/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372050"} +61;"Omniflo Weiche";"0000";"OFWeiche :30";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Einzelweiche", "Richtung": "2", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372051"} +62;"Omniflo Weiche";"0000";"OFWeiche :3";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372100"} +63;"Omniflo Weiche";"0000";"OFWeiche :4";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372101"} +64;"Omniflo Weiche";"0000";"OFWeiche :5";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG090090, 834372101"} +65;"Omniflo Weiche";"0000";"OFWeiche :6";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372101, 0_BG090090"} +66;"Omniflo Weiche";"0000";"OFWeiche :7";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG090090, 834372101, 0_BG090090"} +67;"Omniflo Weiche";"0000";"OFWeiche :8";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372103"} +68;"Omniflo Weiche";"0000";"OFWeiche :9";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372104"} +69;"Omniflo Weiche";"0000";"OFWeiche :10";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG190090, 834372104"} +70;"Omniflo Weiche";"0000";"OFWeiche :11";"G/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372104, 0_BG190090"} +71;"Omniflo Weiche";"0000";"OFWeiche :12";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG190090, 834372104, 0_BG190090"} +72;"Omniflo Weiche";"0000";"OFWeiche :13";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372106"} +73;"Omniflo Weiche";"0000";"OFWeiche :14";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372107"} +74;"Omniflo Weiche";"0000";"OFWeiche :15";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372109"} +75;"Omniflo Weiche";"0000";"OFWeiche :16";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372110"} +76;"Omniflo Weiche";"0000";"OFWeiche :17";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG080090, 834372110"} +77;"Omniflo Weiche";"0000";"OFWeiche :18";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372110, 0_BG080090"} +78;"Omniflo Weiche";"0000";"OFWeiche :19";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG080090, 834372110, 0_BG080090"} +79;"Omniflo Weiche";"0000";"OFWeiche :20";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372115"} +80;"Omniflo Weiche";"0000";"OFWeiche :21";"H/A";1;"";"";"";"unverbunden";{"Weichentyp": "Doppelweiche", "Richtung": "3", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372116"} +81;"Omniflo Weiche";"0000";"OFWeiche :3";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372200"} +82;"Omniflo Weiche";"0000";"OFWeiche :4";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372201"} +83;"Omniflo Weiche";"0000";"OFWeiche :5";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG090090, 834372201"} +84;"Omniflo Weiche";"0000";"OFWeiche :6";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372201, 0_BG090090"} +85;"Omniflo Weiche";"0000";"OFWeiche :7";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG090090, 834372201, 0_BG090090"} +86;"Omniflo Weiche";"0000";"OFWeiche :8";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372203"} +87;"Omniflo Weiche";"0000";"OFWeiche :9";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372204"} +88;"Omniflo Weiche";"0000";"OFWeiche :10";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG190090, 834372204"} +89;"Omniflo Weiche";"0000";"OFWeiche :11";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372204, 0_BG190090"} +90;"Omniflo Weiche";"0000";"OFWeiche :12";"I/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 45.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG190090, 834372204, 0_BG190090"} +91;"Omniflo Weiche";"0000";"OFWeiche :13";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372206"} +92;"Omniflo Weiche";"0000";"OFWeiche :14";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372207"} +93;"Omniflo Weiche";"0000";"OFWeiche :15";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372209"} +94;"Omniflo Weiche";"0000";"OFWeiche :16";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372210"} +95;"Omniflo Weiche";"0000";"OFWeiche :17";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG080090, 834372210"} +96;"Omniflo Weiche";"0000";"OFWeiche :18";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372210, 0_BG080090"} +97;"Omniflo Weiche";"0000";"OFWeiche :19";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG080090, 834372210, 0_BG080090"} +98;"Omniflo Weiche";"0000";"OFWeiche :20";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372215"} +99;"Omniflo Weiche";"0000";"OFWeiche :21";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Dreiwegeweiche", "Richtung": "7", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372216"} +100;"Omniflo Weiche";"0000";"OFWeiche :1";"J/A";1;"";"";"";"unverbunden";{"Weichentyp": "Deltaweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372400"} +101;"Omniflo Weiche";"0000";"OFWeiche :2";"K/A";1;"";"";"";"unverbunden";{"Weichentyp": "Deltaweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372403"} +102;"Omniflo Weiche";"0000";"OFWeiche :3";"K/A";1;"";"";"";"unverbunden";{"Weichentyp": "Deltaweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372404"} +103;"Omniflo Weiche";"0000";"OFWeiche :4";"K/A";1;"";"";"";"unverbunden";{"Weichentyp": "Deltaweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG071090, 834372404, 0_BG071090"} +104;"Omniflo Weiche";"0000";"OFWeiche :5";"K/A";1;"";"";"";"unverbunden";{"Weichentyp": "Deltaweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "0_BG071090, 834372404"} +105;"Omniflo Weiche";"0000";"OFWeiche :6";"K/A";1;"";"";"";"unverbunden";{"Weichentyp": "Deltaweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372404, 0_BG071090"} +106;"Omniflo Weiche";"0000";"OFWeiche :7";"K/A";1;"";"";"";"unverbunden";{"Weichentyp": "Deltaweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372401"} +107;"Omniflo Weiche";"0000";"OFWeiche :1";"K/A";1;"";"";"";"unverbunden";{"Weichentyp": "Sternweiche", "Richtung": "3", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372420"} +108;"Omniflo Sum";"autogenerated_of_json";"Omniflo sum";"";1;"";"";"";"";{"Anzahl Bögen": 27, "Anzahl Weichengrundkörper": 0, "Anzahl Einwegweichen": 30, "Anzahl Deltaweichen": 7, "Anzahl Doppelweichen und Dreiwegeweichen": 42, "Anzahl Sternweichen": 1, "Gesamtlänge AP110": 0.0, "Gesamtlänge AP60": 0.0} diff --git a/tests/test_omniflo.py b/tests/test_omniflo.py index 7f927dd..ee3fee4 100644 --- a/tests/test_omniflo.py +++ b/tests/test_omniflo.py @@ -107,7 +107,7 @@ class TestOmnifloExportUnit: out_dir = _output_dir() os.makedirs(out_dir, exist_ok=True) csv_path = os.path.join(out_dir, "omniflo_export.csv") - header = "Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;Nachbarn;Merkmale" + header = "Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingbox;Nachbarn;Fehler;Merkmale" with open(csv_path, "w", encoding="utf-8") as f: f.write(header + "\n") for item in self.items: diff --git a/tests/test_run_all.lsp b/tests/test_run_all.lsp index 4e20b03..6abbbc6 100644 --- a/tests/test_run_all.lsp +++ b/tests/test_run_all.lsp @@ -146,7 +146,7 @@ namen befehl datei export-fn new-doc out-path dwg-pfad dxf-pfad old-json test-result old-filenames csv-name sivas-name csv-pfad - sivas-pfad csv-ok sivas-ok) + sivas-pfad csv-ok sivas-ok old-filedia) (setq tests-pfad (strcat (getenv "DXFMAKRO") "/tests")) (setq tests-out-dir (strcat tests-pfad "/output")) @@ -267,7 +267,15 @@ (princ (strcat "\n DWG gespeichert: " dwg-pfad)) ) ((and save-fmt (= (strcase save-fmt) "DXF")) + ;; FILEDIA=0 erzwingen: sonst oeffnet "_.DXFOUT" den nativen + ;; Speichern-Dialog (blockiert im Skriptlauf) statt die + ;; Kommandozeilen-Prompts (Dateiname/Genauigkeit) zu nutzen - + ;; das brachte den nachfolgenden vla-close aus dem Takt + ;; (siehe Kontroll-Modus-Zweig weiter unten fuer Details). + (setq old-filedia (getvar "FILEDIA")) + (setvar "FILEDIA" 0) (command "_.DXFOUT" out-path 6) + (setvar "FILEDIA" old-filedia) (princ (strcat "\n DXF gespeichert: " out-path ".dxf")) ) (T @@ -343,7 +351,16 @@ (setq dwg-pfad (strcat out-path ".dwg")) (setq dxf-pfad (strcat out-path ".dxf")) (vla-saveas new-doc dwg-pfad) + ;; FILEDIA=0 erzwingen: sonst oeffnet "_.DXFOUT" den nativen + ;; Speichern-Dialog statt der Kommandozeilen-Prompts - der + ;; Skriptlauf haengt dann in einem offenen Dialog fest, und + ;; der nachfolgende vla-close (auf dem noch "belegten" + ;; Dokument) bricht mit "bad argument type <0>" ab, weil + ;; new-doc dabei ungueltig wird. + (setq old-filedia (getvar "FILEDIA")) + (setvar "FILEDIA" 0) (command "_.DXFOUT" out-path 6) + (setvar "FILEDIA" old-filedia) (vla-close new-doc :vlax-false) (if (findfile dwg-pfad) (vl-file-delete dwg-pfad)) (setq new-doc (vla-open (vla-get-documents app) dxf-pfad))