[MERGE] export Konflikt gelöst

This commit is contained in:
Simon Hensch
2026-09-28 14:11:09 +02:00
18 changed files with 672 additions and 385 deletions
+6 -5
View File
File diff suppressed because one or more lines are too long
+144 -5
View File
@@ -964,6 +964,11 @@
) )
(progn (progn
(setq dxf-pfad (strcat omniflo-pfad "/" sivasnr-str ".dxf")) (setq dxf-pfad (strcat omniflo-pfad "/" sivasnr-str ".dxf"))
;; Fallback: manche Elemente (z.B. Ladeschleifen) liegen nur als DWG vor
(if (and (not (findfile dxf-pfad))
(findfile (strcat omniflo-pfad "/" sivasnr-str ".dwg")))
(setq dxf-pfad (strcat omniflo-pfad "/" sivasnr-str ".dwg"))
)
(if (not (findfile dxf-pfad)) (if (not (findfile dxf-pfad))
(progn (progn
(princ (ssg-textf "omni-fehler-dxf-nicht-gefunden" (list dxf-pfad))) (princ (ssg-textf "omni-fehler-dxf-nicht-gefunden" (list dxf-pfad)))
@@ -1230,7 +1235,7 @@
typ eintrag winkel weichentyp typ eintrag winkel weichentyp
dlg-result new-eintrag new-hoehe new-drehung dlg-result new-eintrag new-hoehe new-drehung
basePoint sivasnr-str dxf-pfad data-pfad angleDeg blockEnt basePoint sivasnr-str dxf-pfad data-pfad angleDeg blockEnt
layer-name) layer-name such)
;; Implied Selection pruefen ;; Implied Selection pruefen
(setq ss (ssget "I")) (setq ss (ssget "I"))
@@ -1307,6 +1312,20 @@
) )
) )
;; Zuletzt in Ladeschleifen suchen (ARTINR, dann Blockname)
(if (null eintrag)
(progn
(if (null *OMNI-LADESCHLEIFEN*) (omni:load-ladeschleifen))
(foreach such (list artinr bname)
(if (and such (null eintrag))
(setq eintrag (omni:get-by-sivasid *OMNI-LADESCHLEIFEN*
(if (/= (atoi such) 0) (atoi such) such)))
)
)
(if eintrag (setq typ "ladeschleife"))
)
)
(if (null eintrag) (if (null eintrag)
(progn (progn
(ssg-emsg (ssg-text "omni-edit-kein-element")) (ssg-emsg (ssg-text "omni-edit-kein-element"))
@@ -1317,12 +1336,15 @@
;; 4. Dialog oeffnen mit vorhandenen Werten ;; 4. Dialog oeffnen mit vorhandenen Werten
(setq dlg-result nil) (setq dlg-result nil)
(if (= typ "bogen") (cond
(progn ((= typ "bogen")
(setq winkel (cdr (assoc "KurvenWinkel" eintrag))) (setq winkel (cdr (assoc "KurvenWinkel" eintrag)))
(setq dlg-result (omni:bogen-dialog winkel hoehe drehung nil)) (setq dlg-result (omni:bogen-dialog winkel hoehe drehung nil))
) )
(progn ((= typ "ladeschleife")
(setq dlg-result (omni:ladeschleifen-dialog nil hoehe))
)
(T
(setq winkel (cdr (assoc "KurvenWinkel" eintrag))) (setq winkel (cdr (assoc "KurvenWinkel" eintrag)))
(setq weichentyp (cdr (assoc "WeichenTyp" eintrag))) (setq weichentyp (cdr (assoc "WeichenTyp" eintrag)))
(setq dlg-result (omni:weichen-dialog winkel weichentyp hoehe drehung nil)) (setq dlg-result (omni:weichen-dialog winkel weichentyp hoehe drehung nil))
@@ -1343,8 +1365,12 @@
(setq new-drehung (rtos rotation 2 1)) (setq new-drehung (rtos rotation 2 1))
(setq sivasnr-str (omni:sivasid-to-str (omni:val new-eintrag "Sivasnr"))) (setq sivasnr-str (omni:sivasid-to-str (omni:val new-eintrag "Sivasnr")))
;; 6. DXF-Datei pruefen ;; 6. DXF-Datei pruefen (Fallback DWG wie in omni:insert-dxf)
(setq dxf-pfad (strcat (getenv "DXFM_OMNIFLO") "/" sivasnr-str ".dxf")) (setq dxf-pfad (strcat (getenv "DXFM_OMNIFLO") "/" sivasnr-str ".dxf"))
(if (and (not (findfile dxf-pfad))
(findfile (strcat (getenv "DXFM_OMNIFLO") "/" sivasnr-str ".dwg")))
(setq dxf-pfad (strcat (getenv "DXFM_OMNIFLO") "/" sivasnr-str ".dwg"))
)
(if (not (findfile dxf-pfad)) (if (not (findfile dxf-pfad))
(progn (progn
(ssg-emsg (ssg-textf "omni-edit-dxf-nicht-gefunden" (list dxf-pfad))) (ssg-emsg (ssg-textf "omni-edit-dxf-nicht-gefunden" (list dxf-pfad)))
@@ -1446,6 +1472,119 @@
(princ) (princ)
) )
;; --- Omniflo / Ladeschleifen ---
;; Datenbasis: data/json/omniflo_ladeschleifen.json. Die Beschreibungen
;; enthalten Kommas, daher der rekursive Parser ssg-json-laden statt des
;; zeilenbasierten ssg-load-json (siehe ssg_core.lsp).
;; Ladeschleifen-Daten laden (in *OMNI-LADESCHLEIFEN*)
(defun omni:load-ladeschleifen ( / data-pfad datei)
(setq data-pfad (getenv "DXFM_DATA"))
(if (null data-pfad)
(progn (princ (ssg-text "omni-fehler-dxfm-data")) nil)
(progn
(setq datei (strcat data-pfad "/json/omniflo_ladeschleifen.json"))
(setq *OMNI-LADESCHLEIFEN* (ssg-json-laden datei))
(if *OMNI-LADESCHLEIFEN*
(princ (strcat "\n[OMNI] " (itoa (length *OMNI-LADESCHLEIFEN*)) " Ladeschleifen geladen."))
(princ (strcat "\n[OMNI] WARNUNG: Keine Ladeschleifen geladen aus " datei))
)
*OMNI-LADESCHLEIFEN*
)
)
)
;; Zahl als Ganzzahl-String fuer die Dialoganzeige ("" wenn kein Zahlwert)
(defun omni:zahl-str (v)
(if (numberp v) (itoa (fix v)) "")
)
;; Detail-Felder im Ladeschleifen-Dialog aktualisieren (action_tile callback)
(defun omni:ladeschleife-dlg-update (idx-str / eintrag)
(setq eintrag (nth (atoi idx-str) *OMNI-DLG-LADESCHLEIFEN*))
(if eintrag
(progn
(set_tile "val_sivasnr" (omni:sivasid-to-str (omni:val eintrag "Sivasnr")))
(set_tile "val_profiltyp" (omni:sivasid-to-str (omni:val eintrag "ProfilTyp")))
(set_tile "val_laenge" (omni:zahl-str (omni:val eintrag "Laenge")))
)
)
)
;; Ladeschleifen-Auswahl-Dialog oeffnen
;; profiltyp = Praefix zum Filtern des ProfilTyp, z.B. "AP 110" (nil = alle)
;; init-hoehe = Vorbelegung Hoehe (nil = Default aus cfg)
;; Rueckgabe: (eintrag hoehe nil) wie omni:bogen-dialog, oder nil bei Abbruch
(defun omni:ladeschleifen-dialog (profiltyp init-hoehe / liste dat ergebnis dlg-hoehe profil)
(if (null *OMNI-LADESCHLEIFEN*) (omni:load-ladeschleifen))
(if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
(setq liste *OMNI-LADESCHLEIFEN*)
(if profiltyp
(setq liste
(vl-remove-if-not
'(lambda (e)
(setq profil (cdr (assoc "ProfilTyp" e)))
(and (= (type profil) 'STR) (= (vl-string-search profiltyp profil) 0))
)
liste
)
)
)
(if (null liste)
(progn
(alert (ssg-textf "omni-ladeschleife-keine-gefunden"
(list (if profiltyp (strcat " (" profiltyp ")") ""))))
nil
)
(progn
(setq *OMNI-DLG-LADESCHLEIFEN* liste)
(setq dat (load_dialog (strcat (getenv "DXFM_DCL") "/omniflo_ladeschleifen.dcl")))
(if (not (new_dialog "omniflo_ladeschleifen" dat))
(progn (alert (ssg-text "omni-ladeschleife-dialog-ladefehler")) nil)
(progn
(start_list "ladeschleife")
(mapcar '(lambda (e) (add_list (omni:sivasid-to-str (omni:val e "Beschreibung")))) liste)
(end_list)
(set_tile "ladeschleife" "0")
(set_tile "val_hoehe" init-hoehe)
(omni:ladeschleife-dlg-update "0")
(action_tile "ladeschleife" "(omni:ladeschleife-dlg-update $value)")
(action_tile "accept"
(strcat
"(setq ergebnis (atoi (get_tile \"ladeschleife\")))"
"(setq dlg-hoehe (get_tile \"val_hoehe\"))"
"(done_dialog 1)"))
(action_tile "cancel" "(done_dialog 0)")
(start_dialog)
(unload_dialog dat)
(if ergebnis
(list (nth ergebnis *OMNI-DLG-LADESCHLEIFEN*) dlg-hoehe nil)
)
)
)
)
)
)
(defun c:OMNI_LADESCHLEIFE_AP110 ( / dlg-result)
(setq dlg-result (omni:ladeschleifen-dialog "AP 110" nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-ladeschleife"))
)
(princ)
)
;; --- Omniflo / Verbinder --- ;; --- Omniflo / Verbinder ---
(defun c:OMNI_TV_W_W () (defun c:OMNI_TV_W_W ()
(princ "\n[DUMMY] TV W-W kpl") (princ "\n[DUMMY] TV W-W kpl")
+1
View File
@@ -571,6 +571,7 @@ AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbind
| Boegen | `OMNI_APB_630_90`, `OMNI_APB_550_675`, `OMNI_APB_630_45`, `OMNI_APB_550_225`, `OMNI_APB_650_180` | Omniflo-Boegen ueber DCL-Dialog einfuegen | | Boegen | `OMNI_APB_630_90`, `OMNI_APB_550_675`, `OMNI_APB_630_45`, `OMNI_APB_550_225`, `OMNI_APB_650_180` | Omniflo-Boegen ueber DCL-Dialog einfuegen |
| Weichen | `OMNI_W90_*`, `OMNI_W45_*`, `OMNI_WP_*`, `OMNI_WK_*`, `OMNI_WKomb_*` | Omniflo-Weichen (Einfach/Doppel/Dreiwege, Delta, Stern) | | Weichen | `OMNI_W90_*`, `OMNI_W45_*`, `OMNI_WP_*`, `OMNI_WK_*`, `OMNI_WKomb_*` | Omniflo-Weichen (Einfach/Doppel/Dreiwege, Delta, Stern) |
| Geraden | `OMNI_AP60`, `OMNI_AP110`, `OMNI_APG110` | Omniflo-Geradenstuecke | | Geraden | `OMNI_AP60`, `OMNI_AP110`, `OMNI_APG110` | Omniflo-Geradenstuecke |
| Ladeschleifen | `OMNI_LADESCHLEIFE_AP110` | Ladeschleife aus `omniflo_ladeschleifen.json` ueber DCL-Dialog (`dcl/omniflo_ladeschleifen.dcl`) einfuegen; Daten per `ssg-json-laden` (Beschreibungen enthalten Kommas). Blockdatei `<Sivasnr>.dwg` unter `DXFM_OMNIFLO` (`omni:insert-dxf` faellt auf `.dwg` zurueck, wenn keine `.dxf` existiert). Per `OMNI_EDIT` editierbar |
| TEF ⚠️ | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade`, `OMNI_KettenFoerderer` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) | | TEF ⚠️ | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade`, `OMNI_KettenFoerderer` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) |
| Transferwagen ⚠️ | `OMNI_TV_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) | | Transferwagen ⚠️ | `OMNI_TV_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) |
| Bogenweichen ⚠️ | `OMNI_APBW_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) | | Bogenweichen ⚠️ | `OMNI_APBW_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) |
+65 -1
View File
@@ -104,6 +104,32 @@
(if (car (atoms-family 1 '("DBG-SCHALTER-SET"))) (if (car (atoms-family 1 '("DBG-SCHALTER-SET")))
(dbg-schalter-set "csv_leave_proxies" (if an 1 0)))) (dbg-schalter-set "csv_leave_proxies" (if an 1 0))))
;; --- Bloecke auf gefrorenen Layern vom Export ausschliessen ---
;; Standard an (T). Nur GEFRORENE Layer zaehlen (ssg-ent-layer-gefroren-p,
;; ssg_layer.lsp) - ausgeschaltete Layer werden weiter exportiert. Bedienbar
;; im Dialog CSV_EXPORT_KONFIG. Wirkt in csv:collect-export-blocks auf den
;; Block selbst UND - ueber *csv-ausschluss-enames* - auf die Hilfsobjekte
;; (Separator-/Element-Kopien, Einheiten-/AS-ES-Marker) eines gefrorenen
;; VF_n/GF_n-Wrappers, die auf eigenen Layern liegen.
(if (not (boundp '*csv-gefrorene-ausschliessen*)) (setq *csv-gefrorene-ausschliessen* T))
(defun csv:gefrorene-ausschliessen-p () (if *csv-gefrorene-ausschliessen* T nil))
(defun csv:gefrorene-ausschliessen-setzen (an)
(setq *csv-gefrorene-ausschliessen* (if an T nil)))
;; Hilfsobjekte (car eines Records), deren Wrapper (nth 1) gefroren-fn
;; erfuellt. records = Record-Listen der Form (hilfsobjekt wrapper ...), wie
;; sie csv:sep-proxies-erzeugen, csv:element-proxies-erzeugen,
;; csv:asmark-aktualisieren und csv:ketten-verarbeiten liefern.
;; gefroren-fn = Praedikat auf den Wrapper. Reine Listenlogik, file-frei
;; testbar (tests/test_unit.lsp).
(defun csv:hilfskopien-ausschluss (records gefroren-fn / result)
(foreach rec records
(if (and (car rec) (nth 1 rec) (apply gefroren-fn (list (nth 1 rec))))
(setq result (cons (car rec) result))))
(reverse result)
)
(setq *csv-ausschluss-enames* nil)
;; --- Feste Datei-/Skriptnamen dieses Moduls (keine Config, direkt im Code) --- ;; --- Feste Datei-/Skriptnamen dieses Moduls (keine Config, direkt im Code) ---
(setq *export-filenames* (setq *export-filenames*
@@ -2353,8 +2379,13 @@
;; GeruestInsert.lsp). Wie BTMT eigenstaendig und von keinem anderen ;; GeruestInsert.lsp). Wie BTMT eigenstaendig und von keinem anderen
;; Element mitgezaehlt - export_csv.py UND export_sivas.py fuehren sie ;; Element mitgezaehlt - export_csv.py UND export_sivas.py fuehren sie
;; beide als eigene TeileArt-Zeilen. ;; beide als eigene TeileArt-Zeilen.
;; Bloecke auf GEFRORENEN Layern (und die Hilfsobjekte gefrorener VF_n/GF_n)
;; werden ausgelassen, solange *csv-gefrorene-ausschliessen* an ist (Standard,
;; Dialog CSV_EXPORT_KONFIG); ausgeschaltete Layer zaehlen nicht als gefroren.
;; Gibt Auswahlsatz zurueck oder nil. ;; Gibt Auswahlsatz zurueck oder nil.
(defun csv:collect-export-blocks ( / ss-all ss-out i ename ed bname ist-nested-element) (defun csv:collect-export-blocks ( / ss-all ss-out i ename ed bname ist-nested-element
gefroren n-gefroren)
(setq n-gefroren 0)
(setq ss-all (ssget "X" (list (cons 0 "INSERT")))) (setq ss-all (ssget "X" (list (cons 0 "INSERT"))))
(if (null ss-all) (setq ss-out nil) (if (null ss-all) (setq ss-out nil)
(progn (progn
@@ -2376,7 +2407,16 @@
(setq ist-nested-element (setq ist-nested-element
(and (not (csv:export-alle-elemente-p)) (and (not (csv:export-alle-elemente-p))
(wcmatch bname (csv:pattern-nested-element)))) (wcmatch bname (csv:pattern-nested-element))))
;; Gefrorener Layer (Schalter *csv-gefrorene-ausschliessen*): der
;; Block selbst liegt darauf, oder er ist Hilfsobjekt eines
;; gefrorenen VF_n/GF_n (*csv-ausschluss-enames*, csv:export-vorbereiten).
(setq gefroren
(and (csv:gefrorene-ausschliessen-p)
(or (ssg-ent-layer-gefroren-p ename)
(member ename *csv-ausschluss-enames*))))
(if gefroren (setq n-gefroren (1+ n-gefroren)))
(if (and (not ist-nested-element) (if (and (not ist-nested-element)
(not gefroren)
(or (or
(wcmatch bname (export:pattern "pattern_kreisel" "KR_*,KREISEL_*,ECKRAD_*")) (wcmatch bname (export:pattern "pattern_kreisel" "KR_*,KREISEL_*,ECKRAD_*"))
(wcmatch (strcase bname) (export:pattern "pattern_gerade" "AP110*,AP_110*")) (wcmatch (strcase bname) (export:pattern "pattern_gerade" "AP110*,AP_110*"))
@@ -2404,6 +2444,8 @@
(if (= (sslength ss-out) 0) (setq ss-out nil)) (if (= (sslength ss-out) 0) (setq ss-out nil))
) )
) )
(if (> n-gefroren 0)
(princ (ssg-textf "exp-gefroren-ausgelassen" (list (itoa n-gefroren)))))
ss-out ss-out
) )
@@ -2459,6 +2501,9 @@
;; Stand eines frueheren Laufs verwerfen: Baustein-Geometrie der ;; Stand eines frueheren Laufs verwerfen: Baustein-Geometrie der
;; Stellvertreter, Anmeldungen fuer reservierte IDs (csv:res-merken), ;; Stellvertreter, Anmeldungen fuer reservierte IDs (csv:res-merken),
;; geordnete Ketten (csv:kette-von), sepliste-Stellvertreter. ;; geordnete Ketten (csv:kette-von), sepliste-Stellvertreter.
(setq *csv-ausschluss-enames* nil)
;; Baustein-Geometrie der Stellvertreter (Separator-Kopie, AS-/ES-Marker)
;; wird beim Erzeugen neu gemerkt - Stand eines frueheren Laufs verwerfen.
(setq *csv-baustein-by-handle* nil) (setq *csv-baustein-by-handle* nil)
(setq *csv-res-sammlung* nil) (setq *csv-res-sammlung* nil)
(setq *csv-ketten* nil) (setq *csv-ketten* nil)
@@ -2489,6 +2534,22 @@
;; 4. Restnummerierung + Duplikat-Korrektur. ssg-id-check-all ermittelt ;; 4. Restnummerierung + Duplikat-Korrektur. ssg-id-check-all ermittelt
;; zuerst das globale Maximum der vergebenen IDs (Phase 0) und nummeriert ;; zuerst das globale Maximum der vergebenen IDs (Phase 0) und nummeriert
;; erst danach - neue IDs liegen damit ueber jeder vorhandenen. ;; erst danach - neue IDs liegen damit ueber jeder vorhandenen.
;; Hilfsobjekte gefrorener Wrapper merken: sie liegen auf eigenen Layern,
;; der Wrapper-Layer allein haelt sie daher nicht aus dem Export heraus
;; (Auswertung in csv:collect-export-blocks). Erzeugt werden sie trotzdem,
;; damit IDs und AS/ES-Marker ueber Laeufe stabil bleiben.
(setq *csv-ausschluss-enames*
(if (csv:gefrorene-ausschliessen-p)
(csv:hilfskopien-ausschluss
(append sep-proxies asmarks element-proxies unitmarks)
'ssg-ent-layer-gefroren-p)))
;; Vor dem Export: IDs aller Bloecke sicherstellen und Duplikate korrigieren.
;; Erst hier - also erst nachdem ALLE Kopien aus allen Wrapper-Bloecken
;; stehen - wird ueberhaupt eine ID vergeben. ssg-id-check-all ermittelt
;; dabei zuerst das globale Maximum der bereits vergebenen IDs (Phase 0)
;; und nummeriert die noch ID-losen Kopien erst danach - sonst bekaemen sie
;; IDs, die die Wrapper (VF_n/GF_n/Kreisel) selbst schon tragen.
(princ (ssg-textf "exp-check-ids" (list label)))
(ssg-id-check-all) (ssg-id-check-all)
;; IDs aller temporaeren Kettenobjekte als reservierte IDs am Wrapper ;; IDs aller temporaeren Kettenobjekte als reservierte IDs am Wrapper
;; ablegen - der naechste Export gibt sie ihnen zurueck (csv:res-merken). ;; ablegen - der naechste Export gibt sie ihnen zurueck (csv:res-merken).
@@ -2678,6 +2739,7 @@
(csv:hilfskopien-loeschen asmarks "exp-art-ases") (csv:hilfskopien-loeschen asmarks "exp-art-ases")
(csv:hilfskopien-loeschen element-proxies "exp-art-element") (csv:hilfskopien-loeschen element-proxies "exp-art-element")
(csv:hilfskopien-loeschen unitmarks "exp-art-einheit") (csv:hilfskopien-loeschen unitmarks "exp-art-einheit")
(setq *csv-ausschluss-enames* nil)
(princ) (princ)
) )
@@ -2723,6 +2785,7 @@
(if eintrag (setq idx eintrag)) (if eintrag (setq idx eintrag))
(set_tile "modus" (itoa idx)) (set_tile "modus" (itoa idx))
(set_tile "hilfskopien_behalten" (if (csv:hilfskopien-behalten-p) "1" "0")) (set_tile "hilfskopien_behalten" (if (csv:hilfskopien-behalten-p) "1" "0"))
(set_tile "gefrorene_ausschliessen" (if (csv:gefrorene-ausschliessen-p) "1" "0"))
) )
(defun csv:export-konfig-accept ( / idx modus) (defun csv:export-konfig-accept ( / idx modus)
@@ -2730,6 +2793,7 @@
(setq modus (car (nth idx *csv-export-konfig-modi*))) (setq modus (car (nth idx *csv-export-konfig-modi*)))
(if modus (csv:export-modus-setzen modus)) (if modus (csv:export-modus-setzen modus))
(csv:hilfskopien-behalten-setzen (= (get_tile "hilfskopien_behalten") "1")) (csv:hilfskopien-behalten-setzen (= (get_tile "hilfskopien_behalten") "1"))
(csv:gefrorene-ausschliessen-setzen (= (get_tile "gefrorene_ausschliessen") "1"))
) )
(defun c:CSV_EXPORT_KONFIG () (defun c:CSV_EXPORT_KONFIG ()
+18
View File
@@ -56,6 +56,24 @@
) )
) )
;; Layer gefroren? (nur Frieren, NICHT Ausschalten - anders als
;; ssg-layer-visible-p). Rueckgabe: T wenn der Layer existiert und gefroren
;; ist (Bit 0 in Gruppe 70), sonst nil. Genutzt vom Export
;; (csv:collect-export-blocks, export.lsp).
(defun ssg-layer-gefroren-p (lay-name / entry)
(setq entry (if lay-name (tblsearch "LAYER" lay-name)))
(if entry
(= (logand (cdr (assoc 70 entry)) 1) 1)
)
)
;; Liegt die Entity ename auf einem gefrorenen Layer (Gruppe 8)?
(defun ssg-ent-layer-gefroren-p (ename)
(if ename
(ssg-layer-gefroren-p (cdr (assoc 8 (entget ename))))
)
)
;; Pruefen ob Objekt-Layer der aktive Layer ist (Schutz vor Ausschalten) ;; Pruefen ob Objekt-Layer der aktive Layer ist (Schutz vor Ausschalten)
;; lay-name = zu pruefender Layer; ist-gruppe = T wenn Gruppen-Layer ;; lay-name = zu pruefender Layer; ist-gruppe = T wenn Gruppen-Layer
;; Rueckgabe: T wenn sicher (nicht aktiver Layer), nil wenn Problem ;; Rueckgabe: T wenn sicher (nicht aktiver Layer), nil wenn Problem
+4 -1
View File
@@ -56,7 +56,9 @@ SSG_LIB
│ │ ├── Antriebst. links → OMNI_TEF_AntriebL │ │ ├── Antriebst. links → OMNI_TEF_AntriebL
│ │ ├── Antriebst. rechts → OMNI_TEF_AntriebR │ │ ├── Antriebst. rechts → OMNI_TEF_AntriebR
│ │ └── TEF Gerade → OMNI_TEF_Gerade │ │ └── TEF Gerade → OMNI_TEF_Gerade
│ └── KettenFoerderer → OMNI_KettenFoerderer │ ├── KettenFoerderer → OMNI_KettenFoerderer
│ └── Ladeschleifen
│ └── AP 110 → OMNI_LADESCHLEIFE_AP110
├── Konfiguration ├── Konfiguration
│ ├── Umschalten 2D und 3D → SSG_DIM_SWITCH │ ├── Umschalten 2D und 3D → SSG_DIM_SWITCH
│ └── Sprache → SSG_SPRACHE │ └── Sprache → SSG_SPRACHE
@@ -100,6 +102,7 @@ Einfuegen von Omniflo-Standardkomponenten (Boegen, Geraden, Weichen, TEF-Element
| `OMNI_WKomb_Delta_1400/1600, OMNI_WKomb_Star` | Weichenkombinationen einfuegen | | `OMNI_WKomb_Delta_1400/1600, OMNI_WKomb_Star` | Weichenkombinationen einfuegen |
| `OMNI_TEF_*` | TEF-Elemente einfuegen (Umlenk-/Antriebsstationen, Gerade) | | `OMNI_TEF_*` | TEF-Elemente einfuegen (Umlenk-/Antriebsstationen, Gerade) |
| `OMNI_KettenFoerderer` | Kettenfoerderer einfuegen | | `OMNI_KettenFoerderer` | Kettenfoerderer einfuegen |
| `OMNI_LADESCHLEIFE_AP110` | Ladeschleife (AP 110) ueber DCL-Dialog einfuegen |
### VarioFoerderer.lsp - Foerderanlage Generator (v24.4) ### VarioFoerderer.lsp - Foerderanlage Generator (v24.4)
Binary file not shown.
Binary file not shown.
+7 -1
View File
@@ -2,7 +2,8 @@
// csv_export_konfig.dcl - CSV-Export Konfiguration (c:CSV_EXPORT_KONFIG, // csv_export_konfig.dcl - CSV-Export Konfiguration (c:CSV_EXPORT_KONFIG,
// export.lsp). Steuert *csv-export-modus* (Combobox mit drei sich // export.lsp). Steuert *csv-export-modus* (Combobox mit drei sich
// gegenseitig ausschliessenden Eintraegen) sowie den Debug-Schalter // gegenseitig ausschliessenden Eintraegen) sowie den Debug-Schalter
// csv_leave_proxies (Hilfskopien nach dem Export stehen lassen). // csv_leave_proxies (Hilfskopien nach dem Export stehen lassen) und
// *csv-gefrorene-ausschliessen* (gefrorene Layer nicht exportieren).
// //
// popup_list statt radio_column: set_tile/get_tile auf einer // popup_list statt radio_column: set_tile/get_tile auf einer
// boxed_radio_column liefern/erwarten den KEY des gewaehlten radio_button // boxed_radio_column liefern/erwarten den KEY des gewaehlten radio_button
@@ -23,6 +24,11 @@ csv_export_konfig : dialog {
width = 55; width = 55;
} }
: toggle {
key = "gefrorene_ausschliessen";
label = "Bloecke auf gefrorenen Layern nicht exportieren";
}
spacer; spacer;
: boxed_column { : boxed_column {
+47
View File
@@ -0,0 +1,47 @@
// ============================================================
// omniflo_ladeschleifen.dcl - Ladeschleifen-Auswahl Dialog fuer Omniflo
// Zeigt die Ladeschleifen aus omniflo_ladeschleifen.json mit Details an.
// ============================================================
omniflo_ladeschleifen : dialog {
label = "Omniflo Ladeschleife Auswahl";
: row {
: popup_list {
key = "ladeschleife";
label = "Ladeschleife:";
width = 50;
}
: edit_box {
key = "val_sivasnr";
label = "SivasNr:";
width = 22;
is_enabled = false;
}
}
: row {
: edit_box {
key = "val_profiltyp";
label = "Profiltyp:";
width = 16;
is_enabled = false;
}
: edit_box {
key = "val_laenge";
label = "Laenge:";
width = 16;
is_enabled = false;
}
}
: row {
: edit_box {
key = "val_hoehe";
label = "Hoehe (mm):";
edit_width = 10;
}
}
ok_cancel;
}
+4
View File
@@ -478,6 +478,9 @@
"kreisel-warn-core-fehlt": "\n[KreiselInsert] WARNUNG: ssg_core.lsp nicht gefunden - Standardwerte.", "kreisel-warn-core-fehlt": "\n[KreiselInsert] WARNUNG: ssg_core.lsp nicht gefunden - Standardwerte.",
"omni-abbruch": "\nAbgebrochen.", "omni-abbruch": "\nAbgebrochen.",
"omni-abbruch-bogen": "\n[BOGEN] Abgebrochen.", "omni-abbruch-bogen": "\n[BOGEN] Abgebrochen.",
"omni-abbruch-ladeschleife": "\n[LADESCHLEIFE] Abgebrochen.",
"omni-ladeschleife-dialog-ladefehler": "Ladeschleifen-Dialog konnte nicht geladen werden.",
"omni-ladeschleife-keine-gefunden": "Keine Ladeschleifen%1 gefunden.",
"omni-abbruch-omni": "\n[OMNI] Abgebrochen.", "omni-abbruch-omni": "\n[OMNI] Abgebrochen.",
"omni-abbruch-weiche": "\n[WEICHE] Abgebrochen.", "omni-abbruch-weiche": "\n[WEICHE] Abgebrochen.",
"omni-bogen-dialog-ladefehler": "Bogen-Dialog konnte nicht geladen werden.", "omni-bogen-dialog-ladefehler": "Bogen-Dialog konnte nicht geladen werden.",
@@ -713,6 +716,7 @@
"exp-unitmark-bilanz": "\n[EXPORT] Foerder-/Gefaelleeinheiten: %1 Proxy(s) erzeugt, %2 alte entfernt.", "exp-unitmark-bilanz": "\n[EXPORT] Foerder-/Gefaelleeinheiten: %1 Proxy(s) erzeugt, %2 alte entfernt.",
"exp-kette-luecke": "\n[EXPORT] WARNUNG: Kette '%1' reisst ab (kein K1 auf dem letzten K2) - %2 Baustein(e) als eigene Teilkette weitergefuehrt, Einheitengrenzen dort pruefen.", "exp-kette-luecke": "\n[EXPORT] WARNUNG: Kette '%1' reisst ab (kein K1 auf dem letzten K2) - %2 Baustein(e) als eigene Teilkette weitergefuehrt, Einheitengrenzen dort pruefen.",
"exp-hilfskopien-behalten": "\n[EXPORT] csv_leave_proxies=1: %1 %2 bleiben in der Zeichnung (Abschalten: (dbg-schalter-off \"csv_leave_proxies\"))", "exp-hilfskopien-behalten": "\n[EXPORT] csv_leave_proxies=1: %1 %2 bleiben in der Zeichnung (Abschalten: (dbg-schalter-off \"csv_leave_proxies\"))",
"exp-gefroren-ausgelassen": "\n[EXPORT] %1 Bloecke auf gefrorenen Layern nicht exportiert (abschaltbar in CSV_EXPORT_KONFIG).",
"exp-art-separator": "Separator-Kopie(n)", "exp-art-separator": "Separator-Kopie(n)",
"exp-art-element": "Element-Kopie(n)", "exp-art-element": "Element-Kopie(n)",
"exp-art-einheit": "Einheiten-Proxy(s)", "exp-art-einheit": "Einheiten-Proxy(s)",
+4
View File
@@ -478,6 +478,9 @@
"kreisel-warn-core-fehlt": "\n[KreiselInsert] WARNING: ssg_core.lsp not found - using defaults.", "kreisel-warn-core-fehlt": "\n[KreiselInsert] WARNING: ssg_core.lsp not found - using defaults.",
"omni-abbruch": "\nCancelled.", "omni-abbruch": "\nCancelled.",
"omni-abbruch-bogen": "\n[ARC] Cancelled.", "omni-abbruch-bogen": "\n[ARC] Cancelled.",
"omni-abbruch-ladeschleife": "\n[LOADING LOOP] Cancelled.",
"omni-ladeschleife-dialog-ladefehler": "Loading loop dialog could not be loaded.",
"omni-ladeschleife-keine-gefunden": "No loading loops%1 found.",
"omni-abbruch-omni": "\n[OMNI] Cancelled.", "omni-abbruch-omni": "\n[OMNI] Cancelled.",
"omni-abbruch-weiche": "\n[SWITCH] Cancelled.", "omni-abbruch-weiche": "\n[SWITCH] Cancelled.",
"omni-bogen-dialog-ladefehler": "Arc dialog could not be loaded.", "omni-bogen-dialog-ladefehler": "Arc dialog could not be loaded.",
@@ -713,6 +716,7 @@
"exp-unitmark-bilanz": "\n[EXPORT] Conveyor/gravity units: %1 proxy(s) created, %2 old ones removed.", "exp-unitmark-bilanz": "\n[EXPORT] Conveyor/gravity units: %1 proxy(s) created, %2 old ones removed.",
"exp-kette-luecke": "\n[EXPORT] WARNING: chain '%1' is broken (no K1 at the last K2) - %2 element(s) continued as a separate sub-chain, check the unit boundaries there.", "exp-kette-luecke": "\n[EXPORT] WARNING: chain '%1' is broken (no K1 at the last K2) - %2 element(s) continued as a separate sub-chain, check the unit boundaries there.",
"exp-hilfskopien-behalten": "\n[EXPORT] csv_leave_proxies=1: %1 %2 remain in the drawing (switch off: (dbg-schalter-off \"csv_leave_proxies\"))", "exp-hilfskopien-behalten": "\n[EXPORT] csv_leave_proxies=1: %1 %2 remain in the drawing (switch off: (dbg-schalter-off \"csv_leave_proxies\"))",
"exp-gefroren-ausgelassen": "\n[EXPORT] %1 blocks on frozen layers not exported (can be switched off in CSV_EXPORT_KONFIG).",
"exp-art-separator": "separator copy(ies)", "exp-art-separator": "separator copy(ies)",
"exp-art-element": "element copy(ies)", "exp-art-element": "element copy(ies)",
"exp-art-einheit": "unit proxy(ies)", "exp-art-einheit": "unit proxy(ies)",
+49 -188
View File
@@ -14,7 +14,8 @@ Neues CSV-Format:
- IDs: kommaseparierte Liste der ID-Attribute aller Bloecke der Zeile - IDs: kommaseparierte Liste der ID-Attribute aller Bloecke der Zeile
(eigene Spalte, nicht mehr Teil des details-JSON). (eigene Spalte, nicht mehr Teil des details-JSON).
- Omniflo Bogen/Weiche: gruppiert nach SivasNummer, Anzahl summiert - Omniflo (TEILEART "Omniflo ..."): je Nummer aus dem ARTINR-Attribut
(kommagetrennt) eine Zeile, Anzahl summiert; TEF-Teile als "Omniflo TEF"
- Omniflo Gerade: gruppiert nach ARTINR-Attribut, Laenge[mm] summiert - Omniflo Gerade: gruppiert nach ARTINR-Attribut, Laenge[mm] summiert
- ILS 2.0 Kreisel: gruppiert nach Kreiselart+Abstand+Anzahl Separatoren/ - ILS 2.0 Kreisel: gruppiert nach Kreiselart+Abstand+Anzahl Separatoren/
Scanner/Rampen, Anzahl summiert Scanner/Rampen, Anzahl summiert
@@ -34,7 +35,8 @@ Aufruf:
Argumente: Argumente:
export_raw.json - JSON-Datei mit allen INSERT-Entities aus der Zeichnung export_raw.json - JSON-Datei mit allen INSERT-Entities aus der Zeichnung
data_dir - Pfad zum data/-Verzeichnis (mit json/ Unterordner) data_dir - Pfad zum data/-Verzeichnis (derzeit ungenutzt, bleibt
fuer den Aufrufer export.lsp erhalten)
output.csv - Ziel-CSV-Datei (reine Merkmalnummern, fuer den output.csv - Ziel-CSV-Datei (reine Merkmalnummern, fuer den
Sivas-Import) Sivas-Import)
@@ -71,47 +73,11 @@ def load_json(path):
return json.load(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 classify_weiche(eintrag):
"""Bestimmt den Weichen-Subtyp fuer die ILS-Automation-Zaehlung."""
wt = eintrag.get("WeichenTyp", "")
profil = eintrag.get("ProfilTyp", "")
if "WEICHENKOERPER" in profil.upper():
return "weichenkoerper"
if wt == "Einzelweiche":
return "einzelweiche"
if wt in ("Doppelweiche", "Dreiwegeweiche"):
return "doppelweiche"
if wt in ("Deltaweiche", "Dreifachweiche") or "DELTA" in profil.upper():
return "deltaweiche"
if wt == "Sternweiche" or "STAR" in profil.upper():
return "sternweiche"
return "einzelweiche"
def get_id(block): def get_id(block):
"""Liest das eindeutige ID-Attribut eines Blocks (von ssg-id-check-all vergeben).""" """Liest das eindeutige ID-Attribut eines Blocks (von ssg-id-check-all vergeben)."""
return block.get("attribs", {}).get("ID", "") return block.get("attribs", {}).get("ID", "")
def format_sivasnr(sivasnr):
"""
Wandelt einen "+"-separierten Sivasnr-Wert (Rohformat aus den JSON-Katalogen,
dort weiterhin benoetigt fuer Dateinamen-Referenzen) in eine reine
kommaseparierte Liste fuer die Ausgabe (CSV/Block-Attribut) um.
"""
return ", ".join(p.strip() for p in str(sivasnr).split("+") if p.strip())
# --- Sivas-Merkmalnummern: Anzeigetexte, die nicht 1:1 aus dem Attribut # --- Sivas-Merkmalnummern: Anzeigetexte, die nicht 1:1 aus dem Attribut
# uebernommen werden koennen (Attribute bleiben ASCII, siehe CLAUDE.md- # uebernommen werden koennen (Attribute bleiben ASCII, siehe CLAUDE.md-
# Konvention "Alle Texte in Dateien ohne Umlaute" - Sivas erwartet aber die # Konvention "Alle Texte in Dateien ohne Umlaute" - Sivas erwartet aber die
@@ -218,42 +184,6 @@ def gefaellestrecke_signature(block):
) )
def expand_tef_components(sivasnr_parts, sivasnr_tef):
"""Ersetzt "0_BG*"-Platzhalter-Teile in sivasnr_parts durch die dahinter
liegenden echten TEF-Sivasnummern (Katalogfeld SivasnrTEF).
"0_BG*"-Werte im Sivasnr-Rohwert (z.B. "834372404+0_BG071090") sind KEINE
echten Sivasnummern, sondern reine Blocknamen-Platzhalter fuer eine TEF-
Baugruppe aus mehreren realen Teilen - "0_BG071090" steht z.B. fuer die
drei echten Teile "0_B10071"+"0_B10090"+"0_B10090" (siehe SivasnrTEF im
Katalog, omniflo_weichen.json/omniflo_boegen.json). Ohne diese Aufloesung
wuerde "0_BG071090" selbst als (nicht existente) Sivasnummer gezaehlt und
die echten Teile (u.a. 0_B10071) fehlten in der Summierung.
Reale TEF-Einzelteile, die bereits direkt im Sivasnr-Rohwert stehen
(Praefix "0_B", aber nicht "0_BG", z.B. "821104026+0_B10071"), sind schon
echte Sivasnummern und werden unveraendert uebernommen.
Bei mehreren "0_BG*"-Platzhaltern im selben Rohwert (TEF beidseitig) wird
SivasnrTEF zu gleichen Teilen aufgeteilt - der Katalog listet die Teile
je Seite hintereinander in SivasnrTEF.
"""
bg_count = sum(1 for p in sivasnr_parts if p.startswith("0_BG"))
if bg_count == 0:
return list(sivasnr_parts)
tef_parts = [p.strip() for p in str(sivasnr_tef or "").split("+") if p.strip()]
chunk_size = len(tef_parts) // bg_count if bg_count else 0
expanded = []
tef_index = 0
for part in sivasnr_parts:
if part.startswith("0_BG"):
expanded.extend(tef_parts[tef_index:tef_index + chunk_size])
tef_index += chunk_size
else:
expanded.append(part)
return expanded
def parse_float_list(csv_str): def parse_float_list(csv_str):
"""Kommagetrennten Attribut-String (z.B. L_GF_m) in Liste von floats.""" """Kommagetrennten Attribut-String (z.B. L_GF_m) in Liste von floats."""
out = [] out = []
@@ -443,17 +373,21 @@ ILS_SIVASNR = {
} }
def process_blocks(blocks, lookup): def process_blocks(blocks):
""" """
Verarbeitet alle Bloecke. Verarbeitet alle Bloecke.
Omniflo-Elemente werden ueber das TEILEART-Attribut ("Omniflo ...")
erkannt, ihre Sivas-Nummern kommen - wie beim Geruest - ausschliesslich
aus dem ARTINR-Attribut (kommagetrennt, TEF-Teile dort bereits
aufgeloest). Ein Katalog-Lookup ueber den Blocknamen findet nicht statt.
Rueckgabe: Rueckgabe:
items - Liste der CSV-Zeilen als Dicts items - Liste der CSV-Zeilen als Dicts
counters - Zaehler fuer ILS-Automation-Summierungszeile counters - Zaehler fuer ILS-Automation-Summierungszeile
""" """
# Gruppen: sivasnr_str -> {anzahl, ids} # Omniflo: artinr -> {teileart, anzahl, ids}
bogen_groups = {} # sivasnr -> dict omniflo_groups = {}
weiche_groups = {} # sivasnr -> dict
# Gerade: artinr_str -> {anzahl, laenge_mm_total, ids} # Gerade: artinr_str -> {anzahl, laenge_mm_total, ids}
gerade_groups = {} gerade_groups = {}
kreisel_list = [] # Liste von blocks kreisel_list = [] # Liste von blocks
@@ -467,14 +401,6 @@ def process_blocks(blocks, lookup):
geruest_list = [] # Liste von GR_-Geruest-Baugruppenbloecken, je einer Zeile geruest_list = [] # Liste von GR_-Geruest-Baugruppenbloecken, je einer Zeile
counters = { counters = {
"anzahl_boegen": 0,
"anzahl_weichenkoerper": 0,
"anzahl_einzelweichen": 0,
"anzahl_deltaweichen": 0,
"anzahl_doppel_dreiwegeweichen": 0,
"anzahl_sternweichen": 0,
"gesamtlaenge_ap110": 0.0,
"gesamtlaenge_ap60": 0.0,
"anzahl_kreisel": 0, "anzahl_kreisel": 0,
"anzahl_kreisel_pinband": 0, "anzahl_kreisel_pinband": 0,
"sep_kreisel_pin": 0, "sep_kreisel_pin": 0,
@@ -544,76 +470,9 @@ def process_blocks(blocks, lookup):
counters["anzahl_geruest"] += 1 counters["anzahl_geruest"] += 1
continue continue
# --- Omniflo Bogen oder Weiche (erkannt via Katalog) ---
if bname in lookup:
typ, eintrag = lookup[bname]
sivasnr_raw = eintrag.get("Sivasnr", bname)
sivasnr_parts = [p.strip() for p in str(sivasnr_raw).split("+")]
has_tef = any(p.startswith("0_B") for p in sivasnr_parts)
block_id = get_id(block)
if typ == "bogen":
if has_tef and len(sivasnr_parts) > 1:
# Multi-Komponenten: jede Komponente separat gruppieren
# ("0_BG*"-Platzhalter werden ueber SivasnrTEF in ihre
# echten Einzelteile aufgeloest, siehe expand_tef_components)
expanded_parts = expand_tef_components(sivasnr_parts, eintrag.get("SivasnrTEF"))
for i, comp_sivasnr in enumerate(expanded_parts):
comp_id = f"{block_id}.t{i+1}"
if comp_sivasnr not in bogen_groups:
bogen_groups[comp_sivasnr] = {"anzahl": 0, "ids": []}
bogen_groups[comp_sivasnr]["anzahl"] += 1
bogen_groups[comp_sivasnr]["ids"].append(comp_id)
else:
# Normal: alle als eine Komponente
sivasnr = format_sivasnr(sivasnr_raw)
if sivasnr not in bogen_groups:
bogen_groups[sivasnr] = {"anzahl": 0, "ids": []}
bogen_groups[sivasnr]["anzahl"] += 1
bogen_groups[sivasnr]["ids"].append(block_id)
counters["anzahl_boegen"] += 1
elif typ == "weiche":
subtyp = classify_weiche(eintrag)
if has_tef and len(sivasnr_parts) > 1:
# Multi-Komponenten: jede Komponente separat gruppieren
# ("0_BG*"-Platzhalter werden ueber SivasnrTEF in ihre
# echten Einzelteile aufgeloest, siehe expand_tef_components)
expanded_parts = expand_tef_components(sivasnr_parts, eintrag.get("SivasnrTEF"))
for i, comp_sivasnr in enumerate(expanded_parts):
comp_id = f"{block_id}.t{i+1}"
if comp_sivasnr.startswith("0_B"):
# TEF-Komponente (Bogen) in bogen_groups
if comp_sivasnr not in bogen_groups:
bogen_groups[comp_sivasnr] = {"anzahl": 0, "ids": []}
bogen_groups[comp_sivasnr]["anzahl"] += 1
bogen_groups[comp_sivasnr]["ids"].append(comp_id)
else:
# Weichen-Komponente in weiche_groups
if comp_sivasnr not in weiche_groups:
weiche_groups[comp_sivasnr] = {"anzahl": 0, "ids": []}
weiche_groups[comp_sivasnr]["anzahl"] += 1
weiche_groups[comp_sivasnr]["ids"].append(comp_id)
else:
# Normal: alle als eine Komponente
sivasnr = format_sivasnr(sivasnr_raw)
if sivasnr not in weiche_groups:
weiche_groups[sivasnr] = {"anzahl": 0, "ids": []}
weiche_groups[sivasnr]["anzahl"] += 1
weiche_groups[sivasnr]["ids"].append(block_id)
if subtyp == "einzelweiche":
counters["anzahl_einzelweichen"] += 1
elif subtyp in ("doppelweiche", "dreiwegeweiche"):
counters["anzahl_doppel_dreiwegeweichen"] += 1
elif subtyp == "deltaweiche":
counters["anzahl_deltaweichen"] += 1
elif subtyp == "sternweiche":
counters["anzahl_sternweichen"] += 1
elif subtyp == "weichenkoerper":
counters["anzahl_weichenkoerper"] += 1
continue
# --- Omniflo Gerade (AP110) --- # --- Omniflo Gerade (AP110) ---
# VOR dem allgemeinen Omniflo-Zweig: Geraden tragen ggf. ebenfalls
# TEILEART "Omniflo ...", brauchen aber die Laengensumme.
if matches_any(bname, BLOCKPATTERNS.get("pattern_gerade", [])): if matches_any(bname, BLOCKPATTERNS.get("pattern_gerade", [])):
attribs = block.get("attribs", {}) attribs = block.get("attribs", {})
artinr = attribs.get("ARTINR", "") artinr = attribs.get("ARTINR", "")
@@ -628,7 +487,33 @@ def process_blocks(blocks, lookup):
gerade_groups[key]["anzahl"] += 1 gerade_groups[key]["anzahl"] += 1
gerade_groups[key]["laenge_mm"] += laenge gerade_groups[key]["laenge_mm"] += laenge
gerade_groups[key]["ids"].append(get_id(block)) gerade_groups[key]["ids"].append(get_id(block))
counters["gesamtlaenge_ap110"] += laenge continue
# --- Omniflo-Element (Bogen, Weiche, Ladeschleife, TEF, ...) ---
# Erkennung ueber TEILEART, Sivas-Nummern aus ARTINR - wie beim
# Geruest eine Zeile je Nummer, hier aber ueber ALLE Bloecke
# gruppiert. Die DWGs fuehren TEF-Teile bereits aufgeloest im ARTINR
# (z.B. "834372002, 0_B10090, 0_B10090"). TEF-Teile ("0_B*") laufen
# unter "Omniflo TEF", damit dasselbe Teil aus Bogen und Weiche EINE
# Zeile bleibt.
attribs = block.get("attribs", {})
teileart = attribs.get("TEILEART", "")
if teileart.startswith("Omniflo"):
artinr_list = [a.strip() for a in attribs.get("ARTINR", "").split(",") if a.strip()]
block_id = get_id(block)
if not artinr_list:
print(f"[export_sivas] WARNUNG: Omniflo-Block {bname} (ID {block_id}) "
f"ohne ARTINR - nicht exportiert.", file=sys.stderr)
continue
for i, artinr in enumerate(artinr_list):
comp_id = f"{block_id}.t{i+1}" if len(artinr_list) > 1 else block_id
if artinr not in omniflo_groups:
omniflo_groups[artinr] = {
"teileart": "Omniflo TEF" if artinr.startswith("0_B") else teileart,
"anzahl": 0, "ids": [],
}
omniflo_groups[artinr]["anzahl"] += 1
omniflo_groups[artinr]["ids"].append(comp_id)
continue continue
# --- ILS Eckrad (vor Kreisel pruefen: pattern_kreisel schliesst # --- ILS Eckrad (vor Kreisel pruefen: pattern_kreisel schliesst
@@ -695,27 +580,10 @@ def process_blocks(blocks, lookup):
items = [] items = []
nr = 1 nr = 1
for sivasnr, g in bogen_groups.items(): for sivasnr, g in omniflo_groups.items():
teileart = "TEF Bogen" if str(sivasnr).startswith("0_B") else "Omniflo Bogen"
items.append({ items.append({
"nr": nr, "nr": nr,
"teileart": teileart, "teileart": g["teileart"],
"sivasnr": sivasnr,
"sivasnr_quoted": False,
"bezeichnung": "",
"dispgruppe": 10,
"anzahl": g["anzahl"],
"laenge_mm": "",
"ids": g["ids"],
"details": {},
})
nr += 1
for sivasnr, g in weiche_groups.items():
teileart = "TEF Weiche" if str(sivasnr).startswith("0_B") else "Omniflo Weiche"
items.append({
"nr": nr,
"teileart": teileart,
"sivasnr": sivasnr, "sivasnr": sivasnr,
"sivasnr_quoted": False, "sivasnr_quoted": False,
"bezeichnung": "", "bezeichnung": "",
@@ -842,7 +710,7 @@ def process_blocks(blocks, lookup):
# ILS_SIVASNR - JEDE Artikelnummer bekommt ihre EIGENE Sivas-Zeile (Sivas # ILS_SIVASNR - JEDE Artikelnummer bekommt ihre EIGENE Sivas-Zeile (Sivas
# kennt nur eine Sivasnr je Zeile), gleiche Artikelnummern INNERHALB # kennt nur eine Sivasnr je Zeile), gleiche Artikelnummern INNERHALB
# derselben Baugruppe werden dabei zu einer Zeile mit anzahl>1 # derselben Baugruppe werden dabei zu einer Zeile mit anzahl>1
# zusammengefasst (wie bogen_groups/weiche_groups oben). Die volle # zusammengefasst (wie omniflo_groups oben). Die volle
# LAENGE der Baugruppe steht auf JEDER so entstandenen Zeile - Sivas hat # LAENGE der Baugruppe steht auf JEDER so entstandenen Zeile - Sivas hat
# kein Konzept einer "gemeinsamen" Laenge ueber mehrere Zeilen hinweg. # kein Konzept einer "gemeinsamen" Laenge ueber mehrere Zeilen hinweg.
for block in geruest_list: for block in geruest_list:
@@ -1026,22 +894,15 @@ def main():
sys.exit(1) sys.exit(1)
raw_json_path = sys.argv[1] raw_json_path = sys.argv[1]
data_dir = sys.argv[2] # sys.argv[2] (data_dir) wird derzeit nicht gebraucht - Omniflo-Nummern
# kommen aus ARTINR, nicht mehr aus dem Katalog. Argument bleibt fuer
# den Aufrufer (export.lsp) bestehen.
output_csv = sys.argv[3] output_csv = sys.argv[3]
blocks = load_json(raw_json_path) blocks = load_json(raw_json_path)
boegen_path = os.path.join(data_dir, "json", "omniflo_boegen.json") print(f"[export_sivas] {len(blocks)} Bloecke geladen.")
weichen_path = os.path.join(data_dir, "json", "omniflo_weichen.json")
boegen = load_json(boegen_path) if os.path.exists(boegen_path) else [] items, _ = process_blocks(blocks)
weichen = load_json(weichen_path) if os.path.exists(weichen_path) else []
lookup = build_lookup(boegen, weichen)
print(f"[export_sivas] {len(blocks)} Bloecke geladen, "
f"{len(boegen)} Boegen, {len(weichen)} Weichen im Katalog.")
items, _ = process_blocks(blocks, lookup)
header = "Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];IDs;details" header = "Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];IDs;details"
with open(output_csv, "w", encoding="utf-8") as f: with open(output_csv, "w", encoding="utf-8") as f:
+195 -183
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -75,6 +75,7 @@
[Scanner]^C^C(ssg-ensure "OmniModulInsert") OMNI_SCANNER [Scanner]^C^C(ssg-ensure "OmniModulInsert") OMNI_SCANNER
[<-Bürstenbremse]^C^C(ssg-ensure "OmniModulInsert") OMNI_BUERSTENBREMSE [<-Bürstenbremse]^C^C(ssg-ensure "OmniModulInsert") OMNI_BUERSTENBREMSE
[~KettenFoerderer]^C^C(ssg-ensure "OmniModulInsert") OMNI_KettenFoerderer [~KettenFoerderer]^C^C(ssg-ensure "OmniModulInsert") OMNI_KettenFoerderer
[Ladeschleifen]^C^C(ssg-ensure "OmniModulInsert") OMNI_LADESCHLEIFE_AP110
[->Verbinder] [->Verbinder]
[~TV W-W kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_W [~TV W-W kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_W
[~TV W-AP110 kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110 [~TV W-AP110 kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110
+1 -1
View File
@@ -78,7 +78,7 @@ class TestSivasSchliesstAus:
_block("Eingang_2D", "0050"), _block("Eingang_2D", "0050"),
_block("Ausgang_3D", "0051"), _block("Ausgang_3D", "0051"),
] ]
items, counters = export_sivas.process_blocks(blocks, lookup={}) items, counters = export_sivas.process_blocks(blocks)
arten = {it.get("teileart", "") for it in items} arten = {it.get("teileart", "") for it in items}
assert "Eingang" not in arten assert "Eingang" not in arten
+103
View File
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
test_export_sivas_omniflo.py - Omniflo-Zeilen im Sivas-Export.
Laeuft komplett ohne BricsCAD (reine Python-Logik).
Omniflo-Elemente werden ueber das TEILEART-Attribut erkannt, ihre Sivas-
Nummern kommen - wie beim Geruest - ausschliesslich aus dem ARTINR-Attribut
(kommagetrennt, TEF-Teile dort bereits aufgeloest). Kein Katalog-Lookup.
"""
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
import export_sivas # noqa: E402
def _block(block_name, teileid, teileart=None, artinr=None, **extra):
attribs = {"ID": teileid}
if teileart is not None:
attribs["TEILEART"] = teileart
if artinr is not None:
attribs["ARTINR"] = artinr
attribs.update(extra)
return {"block_name": block_name, "x": 0.0, "y": 0.0, "z": 0.0,
"rotation": 0.0, "attribs": attribs}
def _zeilen(blocks):
items, _ = export_sivas.process_blocks(blocks)
return {it["sivasnr"]: it for it in items}
def test_einfache_teile_je_nummer_eine_zeile():
zeilen = _zeilen([
_block("834372027", "0001", "Omniflo Einzelweiche", "834372027"),
_block("834372027", "0002", "Omniflo Einzelweiche", "834372027"),
_block("821104033", "0003", "Omniflo Bogen", "821104033"),
])
assert zeilen["834372027"]["teileart"] == "Omniflo Einzelweiche"
assert zeilen["834372027"]["anzahl"] == 2
assert zeilen["834372027"]["ids"] == ["0001", "0002"]
assert zeilen["821104033"]["teileart"] == "Omniflo Bogen"
assert zeilen["821104033"]["anzahl"] == 1
def test_mehrteilige_weiche_mit_tef():
zeilen = _zeilen([
_block("834372002+0_BG090090", "0010", "Omniflo Einzelweiche",
"834372002, 0_B10090, 0_B10090"),
])
assert zeilen["834372002"]["anzahl"] == 1
assert zeilen["834372002"]["ids"] == ["0010.t1"]
assert zeilen["0_B10090"]["teileart"] == "Omniflo TEF"
assert zeilen["0_B10090"]["anzahl"] == 2
assert zeilen["0_B10090"]["ids"] == ["0010.t2", "0010.t3"]
def test_tef_teil_aus_bogen_und_weiche_in_einer_zeile():
items, _ = export_sivas.process_blocks([
_block("821104025+0_B10090", "0020", "Omniflo Bogen", "821104025, 0_B10090"),
_block("834372002+0_BG090090", "0021", "Omniflo Einzelweiche",
"834372002, 0_B10090, 0_B10090"),
])
tef = [it for it in items if it["sivasnr"] == "0_B10090"]
assert len(tef) == 1
assert tef[0]["anzahl"] == 3
def test_ladeschleife_wird_exportiert():
zeilen = _zeilen([
_block("824331125", "0030", "Omniflo Ladeschleife", "824331125"),
])
assert zeilen["824331125"]["teileart"] == "Omniflo Ladeschleife"
def test_omniflo_ohne_artinr_warnt_und_fehlt(capsys):
items, _ = export_sivas.process_blocks([
_block("834372027", "0040", "Omniflo Einzelweiche", ""),
])
assert items == []
assert "ohne ARTINR" in capsys.readouterr().err
def test_block_ohne_teileart_wird_ignoriert():
items, _ = export_sivas.process_blocks([
_block("Scanner", "0050", artinr=""),
_block("827064041", "0051", artinr="827064041"),
])
assert items == []
def test_geruest_unveraendert():
zeilen = _zeilen([
_block("GR_Saeulen_20260928112449", "0060", "Geruest Saeule 2 Zoll",
"821006051,821004201,825002022,825002022", LAENGE="2500"),
])
assert zeilen["825002022"]["anzahl"] == 2
assert zeilen["825002022"]["teileart"] == "Geruest Saeule 2 Zoll"
assert zeilen["825002022"]["ids"] == ["0060"]
assert zeilen["825002022"]["dispgruppe"] == 20
+23
View File
@@ -539,6 +539,29 @@
(tu-eq "csv:export-modus-setzen/ungueltig-ignoriert" "separator_track" *csv-export-modus*) (tu-eq "csv:export-modus-setzen/ungueltig-ignoriert" "separator_track" *csv-export-modus*)
(csv:export-modus-setzen _modus-alt) (csv:export-modus-setzen _modus-alt)
;; --- Gefrorene Layer: Schalter + Hilfskopien-Ausschluss (file-frei) ---
;; Records (hilfsobjekt wrapper ...) mit Symbolen als Stand-ins fuer
;; Entities; das Praedikat ersetzt ssg-ent-layer-gefroren-p.
(setq _gef-alt (csv:gefrorene-ausschliessen-p))
(csv:gefrorene-ausschliessen-setzen T)
(tu-true "csv:gefrorene-ausschliessen/an" (csv:gefrorene-ausschliessen-p))
(csv:gefrorene-ausschliessen-setzen nil)
(tu-nil "csv:gefrorene-ausschliessen/aus" (csv:gefrorene-ausschliessen-p))
(csv:gefrorene-ausschliessen-setzen _gef-alt)
(setq _gef-recs '((sep1 vf1 "SEP") (sep2 vf2 "SEP") (mark1 vf1 "AS") (unit1 gf1 "E" 1)))
(tu-eq "csv:hilfskopien-ausschluss/wrapper-vf1-gefroren" '(sep1 mark1)
(csv:hilfskopien-ausschluss _gef-recs (function (lambda (w) (eq w 'vf1)))))
(tu-eq "csv:hilfskopien-ausschluss/zwei-wrapper" '(sep2 unit1)
(csv:hilfskopien-ausschluss _gef-recs
(function (lambda (w) (member w '(vf2 gf1))))))
(tu-nil "csv:hilfskopien-ausschluss/nichts-gefroren"
(csv:hilfskopien-ausschluss _gef-recs (function (lambda (w) nil))))
(tu-nil "csv:hilfskopien-ausschluss/leere-liste"
(csv:hilfskopien-ausschluss nil (function (lambda (w) T))))
(tu-nil "csv:hilfskopien-ausschluss/record-ohne-wrapper"
(csv:hilfskopien-ausschluss '((sep1)) (function (lambda (w) T))))
) )