From f87260c60568c17b48fda8a6176b803c2357dc3f Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Thu, 2 Jul 2026 14:06:05 +0200 Subject: [PATCH] .cfg Parser hinzu implementieren lassen. Spezifische Omniflo export routine die syncron in Lisp lief entfernt --- CLAUDE.md | 2 +- Lisp/Gefaellestrecke.lsp | 1 + Lisp/OmniModulInsert.lsp | 130 +--------------- Lisp/export.lsp | 316 +++++++-------------------------------- Lisp/ssg_core.lsp | 80 ++++++++++ Lisp/ssg_id.lsp | 2 +- Lisp/vf_core.lsp | 3 +- 7 files changed, 147 insertions(+), 387 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 72729aa..f833cc5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -92,7 +92,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `KreiselInsert.lsp` | KreiselInsert, KreiselConnect, KreiselRedraw, KreiselQuick, KreiselEdit, KreiselParams, KreiselLabelSetup, KreiselLabelPos, KreiselLabelHoehe, ILS_Eckrad | ILS Kreisel und Eckrad komplett in AutoLISP | | `VarioFoerderer.lsp` | FOERDERANLAGE | Vario-Foerderanlagen Generator | | `Gefaellestrecke.lsp` | GEFAELLESTRECKE | Gefaelle-Foerderanlage (AUS -> Staustrecke skaliert -> Separator -> EIN) | -| `export.lsp` | EXPORTSIVAS, EXPORTCSV, OMNI_EXPORT, OMNI_UPDATE_ATTRIBS | JSON-Sammlung und Export (Python-Aufruf oder LISP-nativ) | +| `export.lsp` | EXPORTSIVAS, EXPORTCSV, OMNI_UPDATE_ATTRIBS | JSON-Sammlung und Python-Export (Omniflo-Merkmale/Sum-Zeile via lib/export_csv.py) | | `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W*_*, OMNI_AP60/AP110, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen, Edit-Dialog | | `SSG_LIB_Commands.lsp` | ILS_BTMT_*, ILS_ETF_*, ILS_K*_*, ILS_GK*_*, SSG_BLOCKEDIT | Dummy-Befehle fuer Menue + Doppelklick/Kontextmenue-Dispatcher | | `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) | diff --git a/Lisp/Gefaellestrecke.lsp b/Lisp/Gefaellestrecke.lsp index 4659e57..1483cd2 100644 --- a/Lisp/Gefaellestrecke.lsp +++ b/Lisp/Gefaellestrecke.lsp @@ -1353,6 +1353,7 @@ ("GF_Bogen_R_90" "0") ("GF_Bogen_R_60" "0") ("GF_Bogen_R_30" "0") + ("ID" "") ) ) diff --git a/Lisp/OmniModulInsert.lsp b/Lisp/OmniModulInsert.lsp index 2830ef3..bf09020 100644 --- a/Lisp/OmniModulInsert.lsp +++ b/Lisp/OmniModulInsert.lsp @@ -15,129 +15,11 @@ ;; ============================================================ -;; --- Datei zeilenweise einlesen --- -(defun omni:read-file-lines (datei / f zeile ergebnis) - (setq f (open datei "r")) - (if (null f) - (progn - (princ (strcat "\n[OMNI] FEHLER: Datei nicht gefunden: " datei)) - nil - ) - (progn - (setq ergebnis nil) - (while (setq zeile (read-line f)) - (setq ergebnis (cons zeile ergebnis)) - ) - (close f) - (reverse ergebnis) - ) - ) -) - - -;; --- Whitespace und Komma am Ende einer Zeile entfernen --- -(defun omni:trim (s / len ch) - (setq s (vl-string-trim " \t\r\n" s)) - (setq len (strlen s)) - (if (and (> len 0) (= (substr s len 1) ",")) - (setq s (substr s 1 (1- len))) - ) - (vl-string-trim " \t\r\n" s) -) - - -;; --- JSON-Wert parsen (String, Zahl, null) --- -(defun omni:parse-value (val-str / len) - (setq val-str (omni:trim val-str)) - (cond - ((= val-str "null") nil) - ((= (substr val-str 1 1) "\"") - ;; String: Anfuehrungszeichen entfernen - (setq len (strlen val-str)) - (if (and (> len 1) (= (substr val-str len 1) "\"")) - (substr val-str 2 (- len 2)) - val-str - ) - ) - (T - ;; Zahl - (if (vl-string-search "." val-str) - (atof val-str) - (atoi val-str) - ) - ) - ) -) - - -;; --- Eine Key-Value-Zeile parsen -> dotted pair oder nil --- -(defun omni:parse-kv-line (zeile / pos key rest val) - (setq zeile (omni:trim zeile)) - ;; Muss mit " beginnen (Key) - (if (and (> (strlen zeile) 0) (= (substr zeile 1 1) "\"")) - (progn - ;; Key extrahieren: zweites Anfuehrungszeichen finden - ;; vl-string-search ist 0-basiert, substr ist 1-basiert - (setq pos (vl-string-search "\"" zeile 1)) - (if pos - (progn - (setq key (substr zeile 2 (1- pos))) - ;; Rest nach dem schliessenden " extrahieren - (setq rest (substr zeile (+ pos 2))) - ;; ":" im Rest finden - (setq pos (vl-string-search ":" rest)) - (if pos - (progn - (setq val (substr rest (+ pos 2))) - (cons key (omni:parse-value val)) - ) - ) - ) - ) - ) - ) -) - - -;; --- JSON-Array von flachen Objekten parsen --- -(defun omni:parse-json-array (zeilen / in-obj obj ergebnis zeile kv trimmed) - (setq in-obj nil - obj nil - ergebnis nil - ) - (foreach zeile zeilen - (setq trimmed (omni:trim zeile)) - (cond - ;; Objekt-Start - ((= trimmed "{") - (setq in-obj T - obj nil - ) - ) - ;; Objekt-Ende - ((or (= trimmed "}") (= trimmed "},")) - (if (and in-obj obj) - (setq ergebnis (cons (reverse obj) ergebnis)) - ) - (setq in-obj nil) - ) - ;; Key-Value-Zeile innerhalb eines Objekts - (in-obj - (setq kv (omni:parse-kv-line zeile)) - (if kv (setq obj (cons kv obj))) - ) - ) - ) - (reverse ergebnis) -) - - ;; --- JSON-Datei laden und als Liste von Alists zurueckgeben --- -(defun omni:load-json (datei / zeilen) - (setq zeilen (omni:read-file-lines datei)) - (if zeilen - (omni:parse-json-array zeilen) - ) +;; Duenner Wrapper um den zentralen JSON-Parser aus ssg_core.lsp +;; (ssg-load-json), damit fuer alle Module derselbe Parser-Standard gilt. +(defun omni:load-json (datei) + (ssg-load-json datei) ) @@ -245,8 +127,10 @@ ;; eintrag = Assoziationsliste (Rueckgabe von omni:get-bogen etc.) ;; key = Schluesselname z.B. "Radius" ;; Beispiel: (omni:val (omni:get-bogen 821104025) "Radius") -> 550 +;; Duenner Wrapper um ssg-val (ssg_core.lsp), damit fuer alle Module +;; derselbe Alist-Zugriffsstandard gilt. (defun omni:val (eintrag key) - (cdr (assoc key eintrag)) + (ssg-val eintrag key) ) diff --git a/Lisp/export.lsp b/Lisp/export.lsp index 7f12314..d87de21 100644 --- a/Lisp/export.lsp +++ b/Lisp/export.lsp @@ -4,10 +4,44 @@ ;; Enthaelt: ;; - JSON-Sammler (csv:collect-export-blocks, csv:run-export) ;; - Python-basierter Export: EXPORTSIVAS, EXPORTCSV -;; - LISP-basierter Omniflo-Export: OMNI_EXPORT +;; +;; Alle Blockname-Muster und Datei-/Skriptnamen dieses Moduls sind +;; zentral in cfg/export.cfg (INI-Style, Abschnitte [blockpattern] +;; und [filenames]) deklariert und werden beim Laden des Moduls +;; einmalig eingelesen (export:load-cfg). ;; ============================================================ +;; --- Export-Konfiguration aus cfg/export.cfg laden --- +;; Nutzt den zentralen INI-Parser aus ssg_core.lsp (ssg-load-ini / ssg-ini-get / +;; ssg-ini-list), damit fuer alle Module derselbe .cfg-Standard gilt. +(defun export:load-cfg ( / cfg-pfad) + (setq cfg-pfad (strcat (getenv "DXFM_CFG") "/export.cfg")) + (setq *export-cfg* (ssg-load-ini cfg-pfad)) + (if (null *export-cfg*) + (princ (strcat "\n[export] WARNUNG: " cfg-pfad " nicht gefunden/leer, verwende Vorgaben.")) + ) + (princ) +) + +;; --- Einzelwert aus *export-cfg* lesen, mit Fallback --- +;; section = "blockpattern" oder "filenames" +(defun export:cfg (section key default) + (ssg-ini-get *export-cfg* section key default) +) + +;; --- Muster aus [blockpattern] als normalisierter wcmatch-String --- +;; key = Config-Key, z.B. "pattern_kreisel" +;; default-str = Fallback-Wert als kommagetrennter String, falls Config fehlt +;; Rueckgabe: kommagetrennter String ohne Leerzeichen, z.B. "KR_*,KREISEL_*" +(defun export:pattern (key default-str) + (ssg-ini-list *export-cfg* "blockpattern" key default-str) +) + +;; Beim Laden des Moduls einmalig einlesen (Lazy-Loading via ssg-ensure "export") +(export:load-cfg) + + ;; --- String fuer JSON escapen (Anfuehrungszeichen/Backslash) --- ;; Konvertiert nicht-String-Werte (z.B. T, nil, Zahlen) defensiv in String. (defun csv:json-escape (s) @@ -84,6 +118,7 @@ ;; AP110* = Omniflo Geraden ;; Omniflo Boegen/Weichen = rein numerische Blocknamen (SivasNr) ;; Vario* = VarioFoerderer-Bloecke +;; GF_* = Gefaellestrecke Compound-Bloecke ;; Gibt Auswahlsatz zurueck oder nil. (defun csv:collect-export-blocks ( / ss-all ss-out i ename ed bname) (setq ss-all (ssget "X" (list (cons 0 "INSERT")))) @@ -95,11 +130,12 @@ (setq ed (entget ename)) (setq bname (cdr (assoc 2 ed))) (if (or - (wcmatch bname "KR_*,KREISEL_*,ECKRAD_*") - (wcmatch (strcase bname) "AP110*,AP_110*") - (wcmatch bname "Vario*,Staustrecke*,AUS_Element*,EIN_Element*") + (wcmatch bname (export:pattern "pattern_kreisel" "KR_*,KREISEL_*,ECKRAD_*")) + (wcmatch (strcase bname) (export:pattern "pattern_gerade" "AP110*,AP_110*")) + (wcmatch bname (export:pattern "pattern_strecke" + "Vario*,Staustrecke*,AUS_Element*,EIN_Element*,VF_*,GF_*")) ;; Rein numerische Namen = Omniflo SivasNr (Boegen/Weichen) - (wcmatch bname "#*") + (wcmatch bname (export:pattern "pattern_numerisch" "#*")) ) (ssadd ename ss-out) ) @@ -124,7 +160,7 @@ (setq bname (cdr (assoc 2 ed))) (setq teileart (csv:get-attrib ename "TEILEART")) (if (or teileart - (wcmatch (strcase bname) "AP110*,AP_110*")) + (wcmatch (strcase bname) (export:pattern "pattern_gerade" "AP110*,AP_110*"))) (progn (omni:set-hoehe-attrib ename) (omni:set-drehung-attrib ename) @@ -163,7 +199,8 @@ (princ (strcat "\n[" label "] " (itoa count) " Bloecke gefunden.")) ;; JSON-Datei zusammenbauen - (setq out-pfad (strcat (getenv "DXFM_RESULTS") "/export_raw.json")) + (setq out-pfad (strcat (getenv "DXFM_RESULTS") "/" + (export:cfg "filenames" "raw_json_datei" "export_raw.json"))) (setq fh (open out-pfad "w")) (if (null fh) (progn @@ -191,7 +228,7 @@ (if (findfile py-skript) (progn (setq ergebnis-pfad (strcat (getenv "DXFM_RESULTS") "/" csv-name)) - (setq cmd (strcat "python \"" py-skript "\"" + (setq cmd (strcat (export:cfg "filenames" "python_exe" "python") " \"" py-skript "\"" " \"" out-pfad "\"" " \"" (getenv "DXFM_DATA") "\"" " \"" ergebnis-pfad "\"")) @@ -211,22 +248,21 @@ ;; --- EXPORTSIVAS: Sivas-spezifischer CSV-Export mit Summierungszeilen --- (defun c:EXPORTSIVAS () - (csv:run-export "EXPORTSIVAS" "export_sivas.py" "export_sivas.csv") + (csv:run-export "EXPORTSIVAS" + (export:cfg "filenames" "sivas_script" "export_sivas.py") + (export:cfg "filenames" "sivas_csv" "export_sivas.csv")) ) ;; --- EXPORTCSV: Einfache Item-Liste aller Bloecke (ohne Summierung) --- (defun c:EXPORTCSV () - (csv:run-export "EXPORTCSV" "export_csv.py" "export.csv") + (csv:run-export "EXPORTCSV" + (export:cfg "filenames" "csv_script" "export_csv.py") + (export:cfg "filenames" "csv_csv" "export.csv")) ) ;; ============================================================ -;; LISP-basierter Omniflo-Export (ohne Python) -;; -;; Erkennt Omniflo Bloecke anhand Attribute: -;; TEILEART = "Omniflo Kurve" -> Bogen -;; TEILEART = "Omniflo Weiche" -> Weiche -;; Blockname AP110* -> Gerade +;; OMNIFLO HOEHE/DREHUNG AKTUALISIEREN ;; ============================================================ ;; --- Attribut-Wert eines INSERT-Blocks nach Tag lesen --- @@ -249,249 +285,6 @@ atag ) - -;; --- Omniflo-Block klassifizieren --- -;; Gibt "bogen", "weiche", "gerade" oder nil zurueck -(defun csv:omni-classify (ename bname / teileart) - (setq teileart (csv:get-attrib ename "TEILEART")) - (cond - ((and teileart (= teileart "Omniflo Kurve")) "bogen") - ((and teileart (= teileart "Omniflo Weiche")) "weiche") - ((wcmatch (strcase bname) "AP110*,AP_110*") "gerade") - (t nil) - ) -) - - -;; --- Weichen-Subtyp fuer Omniflo Sum Zaehlung bestimmen --- -(defun csv:omni-weichensubtyp (ename / wtyp beschr) - (setq wtyp (csv:get-attrib ename "WEICHENTYP")) - (setq beschr (csv:get-attrib ename "BESCHR")) - (if (null wtyp) (setq wtyp "")) - (if (null beschr) (setq beschr "")) - (cond - ((vl-string-search "WEICHENK" (strcase beschr)) "weichenkoerper") - ((= wtyp "Einzelweiche") "einzelweiche") - ((= wtyp "Doppelweiche") "doppelweiche") - ((= wtyp "Dreiwegeweiche") "dreiwegeweiche") - ((= wtyp "Deltaweiche") "deltaweiche") - ((= wtyp "Dreifachweiche") "deltaweiche") - ((= wtyp "Sternweiche") "sternweiche") - ((vl-string-search "DELTA" (strcase beschr)) "deltaweiche") - ((vl-string-search "STAR" (strcase beschr)) "sternweiche") - (t "einzelweiche") - ) -) - - -;; --- Merkmale-JSON fuer einen Bogen bauen --- -(defun csv:omni-bogen-merkmale (ename rotation / winkel radius sivasnr hoehe drehung) - (setq winkel (or (csv:get-attrib ename "WINKEL") "0")) - (setq radius (or (csv:get-attrib ename "RADIUS") "0")) - (setq sivasnr (or (csv:get-attrib ename "ARTINR") "")) - (setq hoehe (or (csv:get-attrib ename "HOEHE") (ssg-cfg-or "omniflo" "default_hoehe" "2000"))) - (setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1))) - (strcat "{\"Kurvenwinkel\":" winkel - ",\"Radius\":" radius - ",\"H\\u00f6he\":\"" (csv:json-escape hoehe) "\"" - ",\"Drehung\":" drehung - ",\"SivasNummer\":\"" (csv:json-escape sivasnr) "\"}") -) - - -;; --- Merkmale-JSON fuer eine Weiche bauen --- -(defun csv:omni-weiche-merkmale (ename rotation / wtyp winkel sivasnr tef-str hoehe drehung) - (setq wtyp (or (csv:get-attrib ename "WEICHENTYP") "Einzelweiche")) - (setq winkel (or (csv:get-attrib ename "WINKEL") "0")) - (setq sivasnr (or (csv:get-attrib ename "ARTINR") "")) - (setq tef-str (csv:get-attrib ename "SIVASNR_TEF")) - (setq hoehe (or (csv:get-attrib ename "HOEHE") (ssg-cfg-or "omniflo" "default_hoehe" "2000"))) - (setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1))) - (strcat "{\"Weichentyp\":\"" (csv:json-escape wtyp) "\"" - ",\"Richtung\":\"False\"" - ",\"Weichenwinkel\":" winkel - ",\"H\\u00f6he\":\"" (csv:json-escape hoehe) "\"" - ",\"Drehung\":" drehung - ",\"Antrieb Kurve\":" (if (and tef-str (> (strlen tef-str) 0)) "true" "false") - ",\"SivasNummer\":\"" (csv:json-escape sivasnr) "\"}") -) - - -;; --- Merkmale-JSON fuer eine Gerade bauen --- -(defun csv:omni-gerade-merkmale (ename rotation / laenge hoehe drehung) - (setq laenge (csv:get-attrib ename "LAENGE")) - (if (null laenge) (setq laenge (csv:get-attrib ename "A"))) - (if (null laenge) (setq laenge (ssg-cfg-or "omniflo" "default_gerade_laenge" "2000"))) - (setq hoehe (or (csv:get-attrib ename "HOEHE") (ssg-cfg-or "omniflo" "default_hoehe" "2000"))) - (setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1))) - (strcat "{\"Anzahl der Separatoren\":\"0\"" - ",\"L\\u00e4nge in Meter\":\"" (csv:json-escape (rtos (/ (atof laenge) (ssg-cfg-or "infrastruktur" "mm_pro_meter" 1000.0)) 2 2)) "\"" - ",\"Winkel\":\"0\"" - ",\"Anzahl der Scanner\":0" - ",\"H\\u00f6he oben\":\"" (csv:json-escape hoehe) "\"" - ",\"H\\u00f6he unten\":\"" (csv:json-escape hoehe) "\"" - ",\"Drehung\":" drehung - ",\"SivasNummer\":\"\"}") -) - - -;; --- Omniflo Sum Zeile bauen --- -(defun csv:omni-sum-zeile (elem-nr cnt-boegen cnt-wk cnt-einzel cnt-delta cnt-doppel cnt-stern len-ap110 len-ap60) - (strcat (itoa elem-nr) - ";\"Omniflo Sum\";\"autogenerated_of_json\";\"Omniflo sum\";1;" - "{\"Anzahl B\\u00f6gen\":" (itoa cnt-boegen) - ",\"Anzahl Weichengrundk\\u00f6rper\":" (itoa cnt-wk) - ",\"Anzahl Einwegweichen\":" (itoa cnt-einzel) - ",\"Anzahl Deltaweichen\":" (itoa cnt-delta) - ",\"Anzahl Doppelweichen und Dreiwegeweichen\":" (itoa cnt-doppel) - ",\"Anzahl Sternweichen\":" (itoa cnt-stern) - ",\"Gesamtl\\u00e4nge AP110\":" (rtos len-ap110 2 1) - ",\"Gesamtl\\u00e4nge AP60\":" (rtos len-ap60 2 1) - "}") -) - - - -;; ============================================================ -;; C:OMNI_EXPORT - Omniflo-Elemente zaehlen und als CSV exportieren -;; Rein LISP-basiert, kein Python noetig. -;; ============================================================ -(defun c:OMNI_EXPORT ( / ss-all i ename ed bname rotation typ - elem-nr cnt-boegen cnt-weichen cnt-geraden - cnt-wk cnt-einzel cnt-delta cnt-doppel cnt-stern - len-ap110 len-ap60 laenge-str - fh out-pfad lines subtyp merkmale) - - ;; Vor dem Export: IDs aller Bloecke sicherstellen und Duplikate korrigieren - (princ "\n[OMNI_EXPORT] Pruefe und vergebe IDs...") - (ssg-id-check-all) - ;; Vor dem Export HOEHE/DREHUNG aller Omniflo-Elemente aktualisieren - (princ "\n[OMNI_EXPORT] Aktualisiere Hoehe/Drehung...") - (omni:update-all-attribs) - (princ "\n[OMNI_EXPORT] Sammle Omniflo-Elemente...") - (setq ss-all (ssget "X" (list (cons 0 "INSERT")))) - (if (null ss-all) - (progn (princ "\n[OMNI_EXPORT] Keine INSERT-Bloecke in der Zeichnung.") (princ)) - (progn - (setq elem-nr 0) - (setq cnt-boegen 0 cnt-weichen 0 cnt-geraden 0) - (setq cnt-wk 0 cnt-einzel 0 cnt-delta 0 cnt-doppel 0 cnt-stern 0) - (setq len-ap110 0.0 len-ap60 0.0) - (setq lines '()) - - (setq i 0) - (while (setq ename (ssname ss-all i)) - (setq ed (entget ename)) - (setq bname (cdr (assoc 2 ed))) - (setq rotation (cdr (assoc 50 ed))) - (if (null rotation) (setq rotation 0.0)) - (setq rotation (* (/ rotation pi) 180.0)) - - (setq typ (csv:omni-classify ename bname)) - - (cond - ((= typ "bogen") - (setq elem-nr (1+ elem-nr)) - (setq cnt-boegen (1+ cnt-boegen)) - (setq merkmale (csv:omni-bogen-merkmale ename rotation)) - (setq lines (cons - (strcat (itoa elem-nr) - ";\"Omniflo Kurve\"" - ";\"" (or (csv:get-attrib ename "ID") "0000") "\"" - ";\"" (strcat "OFBogen :" (itoa cnt-boegen)) "\"" - ";1" - ";" merkmale) - lines)) - ) - - ((= typ "weiche") - (setq elem-nr (1+ elem-nr)) - (setq cnt-weichen (1+ cnt-weichen)) - (setq subtyp (csv:omni-weichensubtyp ename)) - (cond - ((= subtyp "weichenkoerper") (setq cnt-wk (1+ cnt-wk))) - ((= subtyp "einzelweiche") (setq cnt-einzel (1+ cnt-einzel))) - ((= subtyp "deltaweiche") (setq cnt-delta (1+ cnt-delta))) - ((= subtyp "sternweiche") (setq cnt-stern (1+ cnt-stern))) - (t (setq cnt-doppel (1+ cnt-doppel))) - ) - (setq merkmale (csv:omni-weiche-merkmale ename rotation)) - (setq lines (cons - (strcat (itoa elem-nr) - ";\"Omniflo Weiche\"" - ";\"" (or (csv:get-attrib ename "ID") "0000") "\"" - ";\"" (strcat "OFWeiche :" (itoa cnt-weichen)) "\"" - ";1" - ";" merkmale) - lines)) - ) - - ((= typ "gerade") - (setq elem-nr (1+ elem-nr)) - (setq cnt-geraden (1+ cnt-geraden)) - (setq laenge-str (csv:get-attrib ename "LAENGE")) - (if (null laenge-str) (setq laenge-str (csv:get-attrib ename "A"))) - (if (and laenge-str (> (strlen laenge-str) 0)) - (setq len-ap110 (+ len-ap110 (atof laenge-str))) - (setq len-ap110 (+ len-ap110 (float (atoi (ssg-cfg-or "omniflo" "default_gerade_laenge" "2000"))))) - ) - (setq merkmale (csv:omni-gerade-merkmale ename rotation)) - (setq lines (cons - (strcat (itoa elem-nr) - ";\"Omniflo Gerade\"" - ";\"" (or (csv:get-attrib ename "ID") "0000") "\"" - ";\"" (strcat "OFGerade :" (itoa cnt-geraden)) "\"" - ";1" - ";" merkmale) - lines)) - ) - ) - - (setq i (1+ i)) - ) - - (princ (strcat "\n[OMNI_EXPORT] Gefunden: " - (itoa cnt-boegen) " Boegen, " - (itoa cnt-weichen) " Weichen, " - (itoa cnt-geraden) " Geraden")) - - (if (= elem-nr 0) - (princ "\n[OMNI_EXPORT] Keine Omniflo-Elemente gefunden.") - (progn - (setq out-pfad (strcat (getenv "DXFM_RESULTS") "/omniflo_export.csv")) - (setq fh (open out-pfad "w")) - (if (null fh) - (princ (strcat "\n[OMNI_EXPORT] FEHLER: Kann Datei nicht oeffnen: " out-pfad)) - (progn - (write-line "Elementnummer;TeileArt;TeileId;Bezeichnung;Anzahl;Merkmale" fh) - (foreach ln (reverse lines) - (write-line ln fh) - ) - (write-line - (csv:omni-sum-zeile (1+ elem-nr) - cnt-boegen cnt-wk cnt-einzel cnt-delta cnt-doppel cnt-stern - len-ap110 len-ap60) - fh) - (close fh) - (princ (strcat "\n[OMNI_EXPORT] CSV geschrieben: " out-pfad)) - (princ (strcat "\n[OMNI_EXPORT] Omniflo Sum: " - (itoa cnt-boegen) " Boegen, " - (itoa (+ cnt-einzel cnt-doppel cnt-delta cnt-stern cnt-wk)) " Weichen, " - (rtos len-ap110 2 0) " mm AP110")) - ) - ) - ) - ) - ) - ) - (princ) -) - - -;; ============================================================ -;; OMNIFLO HOEHE/DREHUNG AKTUALISIEREN -;; ============================================================ - ;; --- Hoehe eines Omniflo-Blocks aus der Zeichnung ermitteln --- ;; Liest z-Koordinate des Einfuegepunkts. ;; Falls der Block KS_EIN, KS_AUS oder K1-K4 enthaelt, @@ -512,7 +305,8 @@ (if (= (cdr (assoc 0 sub-ed)) "INSERT") (progn (setq sub-bname (strcase (cdr (assoc 2 sub-ed)))) - (if (wcmatch sub-bname "KS_EIN,KS_AUS,K1,K2,K3,K4") + (if (wcmatch sub-bname + (export:pattern "pattern_ks_subblocks" "KS_EIN,KS_AUS,K1,K2,K3,K4")) (progn (setq sub-pt (cdr (assoc 10 sub-ed))) (setq z-list (cons (if (caddr sub-pt) (caddr sub-pt) 0.0) z-list)) @@ -576,7 +370,7 @@ ;; Nur Omniflo-Elemente (erkennbar an TEILEART-Attribut oder AP110-Blockname) (setq teileart (csv:get-attrib ename "TEILEART")) (if (or teileart - (wcmatch (strcase bname) "AP110*,AP_110*")) + (wcmatch (strcase bname) (export:pattern "pattern_gerade" "AP110*,AP_110*"))) (progn (omni:set-hoehe-attrib ename) (omni:set-drehung-attrib ename) diff --git a/Lisp/ssg_core.lsp b/Lisp/ssg_core.lsp index 20eaf1f..85072ca 100644 --- a/Lisp/ssg_core.lsp +++ b/Lisp/ssg_core.lsp @@ -750,5 +750,85 @@ ) +;; ============================================================ +;; INI-STYLE CONFIG-PARSER (Standard fuer alle cfg/*.cfg-Dateien) +;; +;; Format: +;; [Abschnitt] +;; Key = Wert (einzelner Wert) +;; Key = Wert1, Wert2, Wert3 (kommagetrennte Liste, z.B. fuer wcmatch) +;; # Kommentar / Leerzeile werden ignoriert +;; +;; Verwendung: +;; (setq cfg (ssg-load-ini pfad)) +;; (ssg-ini-get cfg "sektion" "key" "default") +;; (ssg-ini-list cfg "sektion" "key" "a,b,c") ; normalisiert zu "a,b,c" (wcmatch-tauglich) +;; ============================================================ + +;; Zeilen einer .cfg-Datei in verschachtelte Alist parsen. +;; Rueckgabe: (("sektion" ("key" . "wert") ...) ...) +(defun ssg-ini-parse-lines (zeilen / ergebnis section sec-data trimmed pos key val) + (setq ergebnis nil section nil sec-data nil) + (foreach zeile zeilen + (setq trimmed (vl-string-trim " \t\r\n" zeile)) + (cond + ;; Leerzeile oder Kommentar + ((or (= trimmed "") (= (substr trimmed 1 1) "#")) nil) + ;; Abschnitt: [name] + ((and (= (substr trimmed 1 1) "[") + (= (substr trimmed (strlen trimmed) 1) "]")) + (if section + (setq ergebnis (cons (cons section (reverse sec-data)) ergebnis))) + (setq section (substr trimmed 2 (- (strlen trimmed) 2))) + (setq sec-data nil) + ) + ;; Key=Wert + ((and section (setq pos (vl-string-search "=" trimmed))) + (setq key (vl-string-trim " \t" (substr trimmed 1 pos))) + (setq val (vl-string-trim " \t" (substr trimmed (+ pos 2)))) + (setq sec-data (cons (cons key val) sec-data)) + ) + ) + ) + (if section + (setq ergebnis (cons (cons section (reverse sec-data)) ergebnis))) + (reverse ergebnis) +) + +;; .cfg-Datei laden und als verschachtelte Alist zurueckgeben, oder nil. +(defun ssg-load-ini (cfg-datei / zeilen) + (setq zeilen (ssg-read-file-lines cfg-datei)) + (if zeilen (ssg-ini-parse-lines zeilen)) +) + +;; Einzelwert aus geladener INI-Alist lesen, mit Fallback. +;; ini-data = Rueckgabe von ssg-load-ini +(defun ssg-ini-get (ini-data section key default / sec-data val) + (setq sec-data (cdr (assoc section ini-data))) + (setq val (if sec-data (cdr (assoc key sec-data)))) + (if (and val (> (strlen val) 0)) val default) +) + +;; Kommagetrennten Wert aus geladener INI-Alist lesen und normalisieren +;; (Leerzeichen um Kommas entfernen, leere Teile verwerfen). +;; default-str = Fallback als kommagetrennter String, falls Config/Key fehlt. +;; Rueckgabe: kommagetrennter String, z.B. "KR_*,KREISEL_*" (wcmatch-tauglich) +(defun ssg-ini-list (ini-data section key default-str / raw teile ergebnis item first) + (setq raw (ssg-ini-get ini-data section key default-str)) + (setq teile (ssg-cfg-split-comma raw)) + (setq ergebnis "" first T) + (foreach item teile + (setq item (vl-string-trim " \t" item)) + (if (> (strlen item) 0) + (progn + (setq ergebnis (if first item (strcat ergebnis "," item))) + (setq first nil) + ) + ) + ) + ergebnis +) + + (prompt "\nssg_core.lsp geladen.") (princ) diff --git a/Lisp/ssg_id.lsp b/Lisp/ssg_id.lsp index df19ac2..ccbf232 100644 --- a/Lisp/ssg_id.lsp +++ b/Lisp/ssg_id.lsp @@ -42,7 +42,7 @@ (if (or (wcmatch bname "KR_*,KREISEL_*,ECKRAD_*") (wcmatch (strcase bname) "AP110*,AP_110*,AP60*,AP_60*,APG110*") - (wcmatch bname "Vario*,Staustrecke*,AUS_Element*,EIN_Element*") + (wcmatch bname "Vario*,Staustrecke*,AUS_Element*,EIN_Element*,VF_*,GF_*") (wcmatch bname "#*") ) (ssadd ename ss-out) diff --git a/Lisp/vf_core.lsp b/Lisp/vf_core.lsp index 7581eba..795cd74 100644 --- a/Lisp/vf_core.lsp +++ b/Lisp/vf_core.lsp @@ -114,7 +114,8 @@ ("VF_Bogen_A_30" "0") ("VF_Bogen_I_90" "0") ("VF_Bogen_I_60" "0") - ("VF_Bogen_I_30" "0"))) + ("VF_Bogen_I_30" "0") + ("ID" ""))) ;; ============================================================ ;; TEIL 4: HILFSFUNKTIONEN