Files
dxfmakros/Lisp/OmniModulInsert.lsp
T

1683 lines
55 KiB
Common Lisp

;; ============================================================
;; OMNIFLO JSON-DATEN LADEN UND ABFRAGEN
;; Liest omniflo_boegen.json und omniflo_weichen.json ein.
;; Daten werden als Listen von Assoziationslisten gespeichert.
;;
;; Globale Variablen:
;; *OMNI-BOEGEN* - Liste aller Boegen-Eintraege
;; *OMNI-WEICHEN* - Liste aller Weichen-Eintraege
;;
;; Funktionen:
;; (omni:load-data) - Beide JSON-Dateien laden
;; (omni:get-bogen sivasid) - Bogen-Info zu einer SivasId
;; (omni:get-weiche sivasid) - Weichen-Info zu einer SivasId
;; (omni:filter lst key wert) - Eintraege nach Key/Wert filtern
;; ============================================================
;; --- JSON-Datei laden und als Liste von Alists zurueckgeben ---
;; 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)
)
;; --- Beide Datensaetze laden ---
(defun omni:load-data ( / data-pfad f-boegen f-weichen)
(setq data-pfad (getenv "DXFM_DATA"))
(if (null data-pfad)
(progn
(princ (ssg-text "omni-fehler-dxfm-data"))
nil
)
(progn
;; Boegen laden
(setq f-boegen (strcat data-pfad "/json/omniflo_boegen.json"))
(setq *OMNI-BOEGEN* (omni:load-json f-boegen))
(if *OMNI-BOEGEN*
(princ (strcat "\n[OMNI] " (itoa (length *OMNI-BOEGEN*)) " Boegen geladen."))
(princ (strcat "\n[OMNI] WARNUNG: Keine Boegen geladen aus " f-boegen))
)
;; Weichen laden
(setq f-weichen (strcat data-pfad "/json/omniflo_weichen.json"))
(setq *OMNI-WEICHEN* (omni:load-json f-weichen))
(if *OMNI-WEICHEN*
(princ (strcat "\n[OMNI] " (itoa (length *OMNI-WEICHEN*)) " Weichen geladen."))
(princ (strcat "\n[OMNI] WARNUNG: Keine Weichen geladen aus " f-weichen))
)
T
)
)
)
;; --- SivasId zu String konvertieren (fuer Vergleich) ---
(defun omni:sivasid-to-str (id)
(cond
((= (type id) 'STR) id)
((= (type id) 'INT) (itoa id))
((= (type id) 'REAL) (itoa (fix id)))
(T "")
)
)
;; --- Eintrag anhand SivasId in einer Liste suchen ---
(defun omni:get-by-sivasid (lst sivasid / such-str eintrag sivasnr gefunden)
(setq such-str (omni:sivasid-to-str sivasid))
(setq gefunden nil)
(foreach eintrag lst
(if (null gefunden)
(progn
(setq sivasnr (cdr (assoc "Sivasnr" eintrag)))
(if (= (omni:sivasid-to-str sivasnr) such-str)
(setq gefunden eintrag)
)
)
)
)
gefunden
)
;; --- Bogen anhand SivasId abfragen ---
;; Rueckgabe: Assoziationsliste mit allen Eigenschaften oder nil
;; Beispiel: (omni:get-bogen 821104025)
;; -> (("Sivasnr" . 821104025) ("ProfilTyp" . "APB 110 R 550/22,5...") ...)
(defun omni:get-bogen (sivasid)
(if (null *OMNI-BOEGEN*) (omni:load-data))
(omni:get-by-sivasid *OMNI-BOEGEN* sivasid)
)
;; --- Weiche anhand SivasId abfragen ---
;; Rueckgabe: Assoziationsliste mit allen Eigenschaften oder nil
;; Beispiel: (omni:get-weiche 834372001)
;; -> (("Sivasnr" . 834372001) ("ProfilTyp" . "WEICHE S 45...") ...)
(defun omni:get-weiche (sivasid)
(if (null *OMNI-WEICHEN*) (omni:load-data))
(omni:get-by-sivasid *OMNI-WEICHEN* sivasid)
)
;; --- Eintraege nach beliebigem Key/Wert filtern ---
;; lst = *OMNI-BOEGEN* oder *OMNI-WEICHEN*
;; key = Schluesselname z.B. "KurvenWinkel"
;; wert = Gesuchter Wert z.B. 45
;; Rueckgabe: Liste aller passenden Eintraege
;;
;; Beispiel: (omni:filter *OMNI-BOEGEN* "KurvenWinkel" 45)
;; -> Liste aller 45-Grad-Boegen
;; Beispiel: (omni:filter *OMNI-WEICHEN* "WeichenTyp" "Doppelweiche")
;; -> Liste aller Doppelweichen
(defun omni:filter (lst key wert / eintrag val ergebnis)
(setq ergebnis nil)
(foreach eintrag lst
(setq val (cdr (assoc key eintrag)))
(if (equal val wert)
(setq ergebnis (cons eintrag ergebnis))
)
)
(reverse ergebnis)
)
;; --- Aehnlichkeit zweier ProfilTyp-Texte ---
;; Anzahl gleicher Zeichen an gleicher Position minus Laengendifferenz.
;; Gegenstuecke unterscheiden sich im Katalog nur in einzelnen Zeichen
;; ("45-L-" / "45-R-", "MIT M" / "MIT P", "L1S" / "R1S"), darum bewertet das
;; ohne schemaabhaengiges Zerlegen die passende Weiche am hoechsten.
;; Kein String auf einer Seite -> 0.
(defun omni:profil-aehnlichkeit (a b / la lb n)
(if (and (= (type a) 'STR) (= (type b) 'STR))
(progn
(setq la (vl-string->list a)
lb (vl-string->list b)
n 0)
(while (and la lb)
(if (= (car la) (car lb)) (setq n (1+ n)))
(setq la (cdr la) lb (cdr lb))
)
(- n (abs (- (strlen a) (strlen b))))
)
0
)
)
;; --- Vorwahl-Index fuer ein Dialog-Dropdown ---
;; ziel = Katalog-Eintrag, der vorgewaehlt werden soll (z.B. das per
;; Doppelklick bearbeitete Bauteil oder die bisherige Auswahl)
;; liste = aktuell angezeigte Eintraege
;; Rueckgabe: Index des Eintrags mit gleicher Sivasnr, sonst des Eintrags mit
;; dem aehnlichsten ProfilTyp (Gleichstand: erster); nil ohne Ziel/Liste.
(defun omni:vorwahl-index (ziel liste / nr profil i idx best wert)
(if (and ziel liste)
(progn
(setq nr (omni:sivasid-to-str (cdr (assoc "Sivasnr" ziel)))
i 0)
(if (/= nr "")
(foreach e liste
(if (and (null idx)
(= (omni:sivasid-to-str (cdr (assoc "Sivasnr" e))) nr))
(setq idx i))
(setq i (1+ i))
)
)
(if (null idx)
(progn
(setq profil (cdr (assoc "ProfilTyp" ziel))
i 0)
(foreach e liste
(setq wert (omni:profil-aehnlichkeit profil (cdr (assoc "ProfilTyp" e))))
(if (or (null best) (> wert best))
(setq best wert idx i))
(setq i (1+ i))
)
)
)
idx
)
)
)
;; --- Einzelnen Wert aus einem Eintrag lesen ---
;; 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)
(ssg-val eintrag key)
)
;; --- SivasNummern aller Boegen fuer einen bestimmten Winkel ---
;; winkel = KurvenWinkel z.B. 90, 45, 22.5
;; Rueckgabe: Liste von SivasIds (gemischt INT/STR)
;; Beispiel: (omni:boegen-ids 45) -> (821104021 821104026 "821104026+0_B10071" ...)
(defun omni:boegen-ids (winkel / lst eintrag ergebnis)
(if (null *OMNI-BOEGEN*) (omni:load-data))
(setq ergebnis nil)
(foreach eintrag *OMNI-BOEGEN*
(if (equal (cdr (assoc "KurvenWinkel" eintrag)) winkel)
(setq ergebnis (cons (cdr (assoc "Sivasnr" eintrag)) ergebnis))
)
)
(reverse ergebnis)
)
;; --- SivasNummern aller Boegen, gruppiert nach Winkel ---
;; Rueckgabe: Assoziationsliste ((180 . (id ...)) (90 . (id ...)) ...)
;; Beispiel: (omni:boegen-ids-alle)
;; -> ((180 821104043) (90 821104022 821104030 ...) (67.5 ...) (45 ...) (22.5 ...))
(defun omni:boegen-ids-alle ()
(list
(cons 180 (omni:boegen-ids 180))
(cons 90 (omni:boegen-ids 90))
(cons 67.5 (omni:boegen-ids 67.5))
(cons 45 (omni:boegen-ids 45))
(cons 22.5 (omni:boegen-ids 22.5))
)
)
;; --- SivasNummern von Weichen nach Winkel und WeichenTyp ---
;; winkel = KurvenWinkel z.B. 90, 45
;; weichentyp = "Einzelweiche", "Doppelweiche", "Dreiwegeweiche"
;; Beispiel: (omni:weichen-ids 90 "Einzelweiche")
(defun omni:weichen-ids (winkel weichentyp / eintrag ergebnis)
(if (null *OMNI-WEICHEN*) (omni:load-data))
(setq ergebnis nil)
(foreach eintrag *OMNI-WEICHEN*
(if (and (equal (cdr (assoc "KurvenWinkel" eintrag)) winkel)
(= (cdr (assoc "WeichenTyp" eintrag)) weichentyp)
)
(setq ergebnis (cons (cdr (assoc "Sivasnr" eintrag)) ergebnis))
)
)
(reverse ergebnis)
)
;; --- SivasNummern von Weichenkombinationen (Delta/Star) ---
;; typ = "DELTA" oder "STAR"
;; Filtert anhand ProfilTyp-Inhalt
(defun omni:weichen-kombi-ids (typ / eintrag ergebnis profil)
(if (null *OMNI-WEICHEN*) (omni:load-data))
(setq ergebnis nil)
(foreach eintrag *OMNI-WEICHEN*
(setq profil (cdr (assoc "ProfilTyp" eintrag)))
(if (and profil (vl-string-search typ profil))
(setq ergebnis (cons (cdr (assoc "Sivasnr" eintrag)) ergebnis))
)
)
(reverse ergebnis)
)
;; --- Alle Weichen-SivasNummern gruppiert ---
;; Rueckgabe: Assoziationsliste nach Kategorie
;; Beispiel: (omni:weichen-ids-alle)
;; -> (("W90-Einfach" id1 id2 ...)
;; ("W90-Doppel" ...)
;; ...
;; ("WKomb-Delta" ...)
;; ("WKomb-Star" ...))
(defun omni:weichen-ids-alle ()
(list
;; 90 Grad
(cons "W90-Einfach" (omni:weichen-ids 90 "Einzelweiche"))
(cons "W90-Doppel" (omni:weichen-ids 90 "Doppelweiche"))
(cons "W90-Dreiwege" (omni:weichen-ids 90 "Dreiwegeweiche"))
;; 45 Grad
(cons "W45-Einfach" (omni:weichen-ids 45 "Einzelweiche"))
(cons "W45-Doppel" (omni:weichen-ids 45 "Doppelweiche"))
(cons "W45-Dreiwege" (omni:weichen-ids 45 "Dreiwegeweiche"))
;; Parallel (KurvenWinkel = 0)
(cons "WP-Einfach" (omni:weichen-ids 0 "Einzelweiche"))
(cons "WP-Doppel" (omni:weichen-ids 0 "Doppelweiche"))
(cons "WP-Dreiwege" (omni:weichen-ids 0 "Dreiwegeweiche"))
;; Weichenkoerper (KurvenWinkel = 22.5)
(cons "WK-Einfach" (omni:weichen-ids 22.5 "Einzelweiche"))
(cons "WK-Doppel" (omni:weichen-ids 22.5 "Doppelweiche"))
(cons "WK-Dreiwege" (omni:weichen-ids 22.5 "Dreiwegeweiche"))
;; Weichenkombinationen
(cons "WKomb-Delta" (omni:weichen-kombi-ids "DELTA"))
(cons "WKomb-Star" (omni:weichen-kombi-ids "STAR"))
)
)
;; --- BricsCAD-Befehl: Daten laden ---
(defun c:OMNI_LOAD ()
(omni:load-data)
(princ)
)
;; --- BricsCAD-Befehl: Bogen-Info anzeigen ---
(defun c:OMNI_INFO_BOGEN ( / id eintrag)
(if (null *OMNI-BOEGEN*) (omni:load-data))
(setq id (getstring T (ssg-text "omni-info-bogen-prompt")))
(if (= id "") (princ (ssg-text "omni-abbruch"))
(progn
;; Versuch als Zahl, dann als String
(setq eintrag (omni:get-bogen (if (/= (atoi id) 0) (atoi id) id)))
(if eintrag
(progn
(princ (ssg-textf "omni-bogen-info-profiltyp" (list (omni:sivasid-to-str (omni:val eintrag "ProfilTyp")))))
(princ (ssg-textf "omni-bogen-info-radius" (list (itoa (fix (omni:val eintrag "Radius"))))))
(princ (ssg-textf "omni-bogen-info-kurvenwinkel" (list (rtos (omni:val eintrag "KurvenWinkel") 2 1))))
(princ (ssg-textf "omni-bogen-info-breite" (list (itoa (fix (omni:val eintrag "Breite"))))))
(princ (ssg-textf "omni-bogen-info-laenge" (list (itoa (fix (omni:val eintrag "Länge"))))))
(princ (ssg-textf "omni-bogen-info-antriebsart" (list (itoa (fix (omni:val eintrag "Antriebsart"))))))
)
(princ (ssg-textf "omni-bogen-nicht-gefunden" (list id)))
)
)
)
(princ)
)
;; --- BricsCAD-Befehl: Weichen-Info anzeigen ---
(defun c:OMNI_INFO_WEICHE ( / id eintrag wkl)
(if (null *OMNI-WEICHEN*) (omni:load-data))
(setq id (getstring T (ssg-text "omni-info-weiche-prompt")))
(if (= id "") (princ (ssg-text "omni-abbruch"))
(progn
(setq eintrag (omni:get-weiche (if (/= (atoi id) 0) (atoi id) id)))
(if eintrag
(progn
(princ (ssg-textf "omni-weiche-info-profiltyp" (list (omni:sivasid-to-str (omni:val eintrag "ProfilTyp")))))
(princ (ssg-textf "omni-weiche-info-weichentyp" (list (omni:sivasid-to-str (omni:val eintrag "WeichenTyp")))))
(setq wkl (omni:val eintrag "KurvenWinkel"))
(princ (ssg-textf "omni-weiche-info-kurvenwinkel" (list (if (= (type wkl) 'INT) (itoa wkl) (rtos wkl 2 1)))))
(princ (ssg-textf "omni-weiche-info-schaltungstyp" (list (omni:sivasid-to-str (omni:val eintrag "Schaltungstyp")))))
(princ (ssg-textf "omni-weiche-info-breite" (list (itoa (fix (omni:val eintrag "Breite"))))))
(princ (ssg-textf "omni-weiche-info-laenge" (list (itoa (fix (omni:val eintrag "Länge"))))))
(princ (ssg-textf "omni-weiche-info-kurvenrichtung" (list (itoa (fix (omni:val eintrag "KurvenRichtung"))))))
(if (omni:val eintrag "WeichenkörperLänge")
(princ (ssg-textf "omni-weiche-info-wklaenge" (list (rtos (omni:val eintrag "WeichenkörperLänge") 2 1))))
)
)
(princ (ssg-textf "omni-weiche-nicht-gefunden" (list id)))
)
)
)
(princ)
)
;; ============================================================
;; OMNIFLO BOGEN-DIALOG
;; Generischer Dialog fuer Bogen-Auswahl nach Winkel
;; ============================================================
;; --- Detail-Felder im Dialog aktualisieren ---
;; Wird bei Dropdown-Aenderung aufgerufen (action_tile callback)
(defun omni:bogen-dlg-update (idx-str / idx eintrag wkl)
(setq idx (atoi idx-str))
(setq eintrag (nth idx *OMNI-DLG-BOEGEN*))
(if eintrag
(progn
(set_tile "val_sivasnr"
(omni:sivasid-to-str (omni:val eintrag "Sivasnr")))
(setq wkl (omni:val eintrag "KurvenWinkel"))
(set_tile "val_winkel"
(if (= (type wkl) 'INT) (strcat (itoa wkl) " Grad")
(strcat (rtos wkl 2 1) " Grad")
)
)
(set_tile "val_radius"
(itoa (fix (omni:val eintrag "Radius"))))
(set_tile "val_breite"
(itoa (fix (omni:val eintrag "Breite"))))
(set_tile "val_laenge"
(itoa (fix (omni:val eintrag "Länge"))))
)
)
)
;; --- Bogen-Auswahl-Dialog oeffnen ---
;; winkel = KurvenWinkel (90, 67.5, 45, 22.5, 180)
;; init-hoehe / init-drehung = Vorbelegung (optional, fuer Edit-Modus)
;; profiltyp = optionales Praefix zum Filtern des ProfilTyp-Textes,
;; z.B. "APB 60" oder "APB 110" (nil = keine Einschraenkung)
;; Rueckgabe: (eintrag hoehe drehung) oder nil bei Abbruch
;; Vorwahl: *omni-dlg-vorwahl* (von OMNI_EDIT gesetzt) wird vorgewaehlt.
(defun omni:bogen-dialog (winkel init-hoehe init-drehung profiltyp / dcl-pfad dat boegen-liste
profil-liste ergebnis dlg-hoehe profil idx)
(if (null *OMNI-BOEGEN*) (omni:load-data))
;; Defaults
;; Hinweis: init-drehung wird nicht mehr verwendet - die Drehung wird nach
;; dem Einfuegen interaktiv abgefragt (omni:insert-dxf mit drehung=nil).
(if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
;; Boegen nach Winkel filtern
(setq boegen-liste (omni:filter *OMNI-BOEGEN* "KurvenWinkel" winkel))
;; Optional zusaetzlich nach ProfilTyp-Praefix filtern (z.B. "APB 60")
(if profiltyp
(setq boegen-liste
(vl-remove-if-not
'(lambda (e)
(setq profil (cdr (assoc "ProfilTyp" e)))
(and profil (= (vl-string-search profiltyp profil) 0))
)
boegen-liste
)
)
)
(if (null boegen-liste)
(progn
(alert (ssg-textf "omni-bogen-keine-gefunden"
(list
(strcat
(if (= (type winkel) 'INT) (itoa winkel) (rtos winkel 2 1))
(ssg-text "omni-grad")
)
(if profiltyp (strcat " (" profiltyp ")") "")
)
))
nil
)
(progn
;; In globaler Variable fuer Dialog-Callbacks speichern
(setq *OMNI-DLG-BOEGEN* boegen-liste)
;; ProfilTyp-Liste fuer Dropdown aufbauen
(setq profil-liste
(mapcar '(lambda (e) (cdr (assoc "ProfilTyp" e))) boegen-liste))
;; DCL laden
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/omniflo_boegen.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "omniflo_boegen" dat))
(progn (alert (ssg-text "omni-bogen-dialog-ladefehler")) nil)
(progn
;; Dropdown befuellen
(start_list "bogenart")
(mapcar 'add_list profil-liste)
(end_list)
;; Beim Edit (OMNI_EDIT) das bearbeitete Bauteil vorwaehlen
(setq idx (omni:vorwahl-index *omni-dlg-vorwahl* boegen-liste))
(if (null idx) (setq idx 0))
(set_tile "bogenart" (itoa idx))
;; Hoehe initialisieren (Drehung erfolgt interaktiv nach dem Einfuegen)
(set_tile "val_hoehe" init-hoehe)
;; Startwerte anzeigen
(omni:bogen-dlg-update (itoa idx))
;; Callback bei Dropdown-Aenderung
(action_tile "bogenart" "(omni:bogen-dlg-update $value)")
;; OK/Abbrechen
(action_tile "accept"
(strcat
"(setq ergebnis (atoi (get_tile \"bogenart\")))"
"(setq dlg-hoehe (get_tile \"val_hoehe\"))"
"(done_dialog 1)"))
(action_tile "cancel" "(done_dialog 0)")
(start_dialog)
(unload_dialog dat)
;; Gewaehlten Eintrag mit Hoehe zurueckgeben (drehung=nil -> interaktiv)
(if ergebnis
(list (nth ergebnis *OMNI-DLG-BOEGEN*) dlg-hoehe nil)
nil
)
)
)
)
)
)
;; ============================================================
;; OMNIFLO MODUL-BEFEHLE
;; ============================================================
;; --- Omniflo / Boegen ---
(defun c:OMNI_APB60_90 ( / dlg-result)
(setq dlg-result (omni:bogen-dialog 90 nil nil "APB 60"))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
(defun c:OMNI_APB_630_90 ( / dlg-result)
(setq dlg-result (omni:bogen-dialog 90 nil nil "APB 110"))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
(defun c:OMNI_APB_550_675 ( / dlg-result)
(setq dlg-result (omni:bogen-dialog 67.5 nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
(defun c:OMNI_APB_630_45 ( / dlg-result)
(setq dlg-result (omni:bogen-dialog 45 nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
(defun c:OMNI_APB_550_225 ( / dlg-result)
(setq dlg-result (omni:bogen-dialog 22.5 nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
(defun c:OMNI_APB_650_180 ( / dlg-result)
(setq dlg-result (omni:bogen-dialog 180 nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
;; ============================================================
;; OMNIFLO WEICHEN-DIALOG
;; Generischer Dialog fuer Weichen-Auswahl nach Winkel/Typ
;; mit Filter fuer Schaltungstyp und Richtung
;; ============================================================
;; --- Standard-Weichentypen eines Winkel-Dialogs ---
;; Einzel-, Doppel- und Dreiwegeweiche eines Winkels stehen in EINEM Dialog,
;; unterschieden ueber die Radiogruppe "Richtung" (KurvenRichtung 1/2/3/7).
;; Delta-/Stern-/Weichenbatterie bleiben eigene Dialoge - Deltaweichen tragen
;; ebenfalls KurvenRichtung 3/7 und duerfen darum nicht in diese Liste.
(setq *omni-weichen-std-typen* '("Einzelweiche" "Doppelweiche" "Dreiwegeweiche"))
;; --- KurvenRichtung -> Radiobutton der Richtungsgruppe ---
;; Katalog: 1 = links, 2 = rechts, 3 = Doppel, 7 = Dreiwege.
(setq *omni-weichen-richtungen*
'(("1" . "ri_links") ("2" . "ri_rechts") ("3" . "ri_doppel") ("7" . "ri_dreiwege")))
;; kr = KurvenRichtung als String; Rueckgabe Tile-Key oder nil (unbekannt)
(defun omni:weichen-richtung-key (kr)
(cdr (assoc kr *omni-weichen-richtungen*))
)
;; --- Basisliste eines Weichen-Dialogs (reiner Kern) ---
;; lst = Weichenkatalog
;; winkel = KurvenWinkel oder nil (alle Winkel)
;; weichentyp = WeichenTyp-String, Liste von WeichenTypen oder nil (alle)
;; breite = Breite oder nil (z.B. Delta 1400/700 vs. 1600/800)
(defun omni:weichen-basis-liste (lst winkel weichentyp breite / typen)
(if winkel (setq lst (omni:filter lst "KurvenWinkel" winkel)))
(if weichentyp
(progn
(setq typen (if (listp weichentyp) weichentyp (list weichentyp)))
(setq lst (vl-remove-if-not
'(lambda (e) (member (cdr (assoc "WeichenTyp" e)) typen))
lst))
)
)
(if breite
(setq lst (vl-remove-if-not
'(lambda (e) (= (cdr (assoc "Breite" e)) breite))
lst))
)
lst
)
;; --- Aktuelle Filterwerte aus Radio-Buttons lesen ---
(defun omni:weichen-get-filter ( / sch ri paar)
(setq sch "alle")
(if (= (get_tile "sch_m") "1") (setq sch "M"))
(if (= (get_tile "sch_p") "1") (setq sch "P"))
(setq ri "alle")
(foreach paar *omni-weichen-richtungen*
(if (= (get_tile (cdr paar)) "1") (setq ri (car paar)))
)
(list sch ri)
)
;; --- Gefilterte Weichen-Liste aufbauen ---
;; basis-liste = alle Weichen fuer den gewaehlten Winkel/Typ
;; sch-filter = "M", "P" oder "alle"
;; ri-filter = KurvenRichtung "1", "2", "3", "7" oder "alle"
(defun omni:weichen-filter-liste (basis-liste sch-filter ri-filter / eintrag sch kr ergebnis)
(setq ergebnis nil)
(foreach eintrag basis-liste
(setq sch (cdr (assoc "Schaltungstyp" eintrag)))
(setq kr (cdr (assoc "KurvenRichtung" eintrag)))
(if (and
(or (= sch-filter "alle") (= sch sch-filter))
(or (= ri-filter "alle")
(= (omni:sivasid-to-str kr) ri-filter))
)
(setq ergebnis (cons eintrag ergebnis))
)
)
(reverse ergebnis)
)
;; --- Dropdown mit gefilterter Liste neu befuellen ---
;; Die bisher angezeigte Weiche (*omni-dlg-weiche-akt*) bleibt gewaehlt, wenn sie
;; den Filter passiert; sonst wird ihr Gegenstueck (aehnlichster ProfilTyp)
;; gewaehlt - ein Klick auf "Rechts" macht aus 45-L-400/750 MIT M also
;; 45-R-400/750 MIT M statt des ersten Listeneintrags.
(defun omni:weichen-dlg-refresh ( / filter sch-f ri-f gefiltert profil-liste idx)
(setq filter (omni:weichen-get-filter))
(setq sch-f (car filter))
(setq ri-f (cadr filter))
(setq gefiltert (omni:weichen-filter-liste *OMNI-DLG-WEICHEN-BASIS* sch-f ri-f))
(setq *OMNI-DLG-WEICHEN* gefiltert)
;; Dropdown neu befuellen
(setq profil-liste
(mapcar '(lambda (e) (cdr (assoc "ProfilTyp" e))) gefiltert))
(start_list "profiltyp")
(mapcar 'add_list profil-liste)
(end_list)
;; Bisherige Weiche bzw. ihr Gegenstueck anzeigen (falls vorhanden)
(if gefiltert
(progn
(setq idx (omni:vorwahl-index *omni-dlg-weiche-akt* gefiltert))
(if (null idx) (setq idx 0))
(set_tile "profiltyp" (itoa idx))
(omni:weichen-dlg-update (itoa idx))
)
(progn
(set_tile "val_sivasnr" "---")
(set_tile "val_winkel" "---")
(set_tile "val_breite" "---")
(set_tile "val_laenge" "---")
)
)
)
;; --- Detail-Felder im Weichen-Dialog aktualisieren ---
;; Fehlende Werte (null im Katalog, z.B. Weichenbatterien ohne KurvenWinkel/
;; Breite/Laenge) werden als "---" angezeigt.
(defun omni:weichen-dlg-update (idx-str / idx eintrag wkl br lg)
(setq idx (atoi idx-str))
(setq eintrag (nth idx *OMNI-DLG-WEICHEN*))
(if eintrag
(progn
;; Merken fuer den naechsten Filterwechsel (omni:weichen-dlg-refresh)
(setq *omni-dlg-weiche-akt* eintrag)
(set_tile "val_sivasnr"
(omni:sivasid-to-str (omni:val eintrag "Sivasnr")))
(setq wkl (omni:val eintrag "KurvenWinkel"))
(set_tile "val_winkel"
(cond
((= (type wkl) 'INT) (strcat (itoa wkl) " Grad"))
((numberp wkl) (strcat (rtos wkl 2 1) " Grad"))
(T "---")
)
)
(setq br (omni:val eintrag "Breite"))
(setq lg (omni:val eintrag "Länge"))
(set_tile "val_breite" (if (numberp br) (itoa (fix br)) "---"))
(set_tile "val_laenge" (if (numberp lg) (itoa (fix lg)) "---"))
)
)
)
;; --- Weichen-Auswahl-Dialog oeffnen ---
;; winkel = KurvenWinkel (90, 45, 0, 22.5)
;; weichentyp = WeichenTyp-String, Liste von WeichenTypen (z.B.
;; *omni-weichen-std-typen*) oder nil fuer alle
;; init-hoehe / init-drehung = Vorbelegung (optional, fuer Edit-Modus)
;; Rueckgabe: (eintrag hoehe drehung) oder nil bei Abbruch
;; Vorwahl: *omni-dlg-vorwahl* (von OMNI_EDIT gesetzt) wird vorgewaehlt, die
;; Filter Schaltung/Richtung stehen dann auf dessen Werten.
;; Richtungs-Buttons ohne passenden Katalogeintrag werden ausgegraut.
(defun omni:weichen-dialog (winkel weichentyp init-hoehe init-drehung breite / dcl-pfad dat basis-liste
ergebnis dlg-hoehe sch kr key paar vorhanden)
(if (null *OMNI-WEICHEN*) (omni:load-data))
;; Defaults
;; Hinweis: init-drehung wird nicht mehr verwendet - die Drehung wird nach
;; dem Einfuegen interaktiv abgefragt (omni:insert-dxf mit drehung=nil).
(if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
;; Weichen nach Winkel, WeichenTyp(en) und Breite eingrenzen
(setq basis-liste (omni:weichen-basis-liste *OMNI-WEICHEN* winkel weichentyp breite))
(if (null basis-liste)
(progn
(alert (ssg-textf "omni-weiche-keine-gefunden"
(list
(cond
((null winkel) (ssg-text "omni-alle-winkel"))
((= (type winkel) 'INT) (strcat (itoa winkel) (ssg-text "omni-grad")))
(T (strcat (rtos winkel 2 1) (ssg-text "omni-grad")))
)
(cond
((null weichentyp) "")
((listp weichentyp) (strcat " / " (ssg-join weichentyp ", ")))
(T (strcat " / " weichentyp))
)
)
))
nil
)
(progn
;; Basis-Liste und gefilterte Liste in globalen Variablen speichern
(setq *OMNI-DLG-WEICHEN-BASIS* basis-liste)
(setq *OMNI-DLG-WEICHEN* basis-liste)
;; DCL laden
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/omniflo_weichen.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "omniflo_weichen" dat))
(progn (alert (ssg-text "omni-weiche-dialog-ladefehler")) nil)
(progn
;; Richtungen ohne Katalogeintrag ausgrauen (z.B. Weichenbatterie:
;; kein Doppel/Dreiwege, Stern: kein Links/Rechts); "Alle" bleibt.
(setq vorhanden
(mapcar '(lambda (e) (omni:sivasid-to-str (cdr (assoc "KurvenRichtung" e))))
basis-liste))
(foreach paar *omni-weichen-richtungen*
(if (not (member (car paar) vorhanden))
(mode_tile (cdr paar) 1))
)
;; Beim Edit (OMNI_EDIT, *omni-dlg-vorwahl*) die Filter auf Schaltung/
;; Richtung des Bauteils stellen; ohne Vorwahl bleibt "Alle".
(setq *omni-dlg-weiche-akt* *omni-dlg-vorwahl*)
(if *omni-dlg-vorwahl*
(progn
(setq sch (cdr (assoc "Schaltungstyp" *omni-dlg-vorwahl*)))
(setq kr (omni:sivasid-to-str (cdr (assoc "KurvenRichtung" *omni-dlg-vorwahl*))))
(cond ((= sch "M") (set_tile "sch_m" "1"))
((= sch "P") (set_tile "sch_p" "1")))
(if (setq key (omni:weichen-richtung-key kr))
(set_tile key "1"))
)
)
;; Dropdown befuellen und Weiche waehlen (vorgewaehltes Bauteil bzw.
;; ohne Vorwahl der erste Eintrag)
(omni:weichen-dlg-refresh)
;; Hoehe initialisieren (Drehung erfolgt interaktiv nach dem Einfuegen)
(set_tile "val_hoehe" init-hoehe)
;; Callback bei Dropdown-Aenderung
(action_tile "profiltyp" "(omni:weichen-dlg-update $value)")
;; Callbacks fuer Filter-Radio-Buttons (alle loesen Refresh aus)
(action_tile "sch_alle" "(omni:weichen-dlg-refresh)")
(action_tile "sch_m" "(omni:weichen-dlg-refresh)")
(action_tile "sch_p" "(omni:weichen-dlg-refresh)")
(action_tile "ri_alle" "(omni:weichen-dlg-refresh)")
(foreach paar *omni-weichen-richtungen*
(action_tile (cdr paar) "(omni:weichen-dlg-refresh)"))
;; OK/Abbrechen
(action_tile "accept"
(strcat
"(setq ergebnis (atoi (get_tile \"profiltyp\")))"
"(setq dlg-hoehe (get_tile \"val_hoehe\"))"
"(done_dialog 1)"))
(action_tile "cancel" "(done_dialog 0)")
(start_dialog)
(unload_dialog dat)
;; Gewaehlten Eintrag mit Hoehe zurueckgeben (drehung=nil -> interaktiv)
(if ergebnis
(list (nth ergebnis *OMNI-DLG-WEICHEN*) dlg-hoehe nil)
nil
)
)
)
)
)
)
;; ============================================================
;; OMNIFLO DXF-BLOCK EINFUEGEN
;; Fuegt eine DXF-Datei aus data/omniflo/ als Block ein.
;; Der Benutzer waehlt den Einfuegepunkt und Drehwinkel.
;; ============================================================
;; --- Omniflo-Quelldatei fuer eine SivasNr aufloesen ---
;; Sucht sivasnr-str.dxf, dann .dwg im aktuellen DXFM_OMNIFLO-Ordner
;; (data/omniflo/<DXFM_DIM>/). Omniflo-Bloecke liegen - anders als die
;; ILS-Bloecke in data/ils (Dimensionssuffix _2D/_3D im Dateinamen, flach in
;; EINEM Ordner) - in GETRENNTEN Ordnern data/omniflo/2D/ und .../3D/ ohne
;; Dimensionssuffix im Namen. Ist der 3D-Datensatz (noch) unvollstaendig
;; (Stand 2026: nur BTMT-Beladung als 3D-DWG vorhanden), faellt diese
;; Funktion auf den jeweils ANDEREN Dimensionsordner zurueck, statt mit
;; "DXF nicht gefunden" abzubrechen - mit Warnmeldung, da das Ergebnis dann
;; nicht die gewuenschte Dimension ist. Rueckgabe: Dateipfad oder nil.
(defun omni:omniflo-datei-finden (sivasnr-str omniflo-pfad / dxf-pfad partner-pfad partner-dim basis pfad-norm)
(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 (findfile dxf-pfad)
dxf-pfad
(progn
;; Fallback: anderer Dimensionsordner (2D<->3D), falls die gewuenschte
;; Dimension fuer dieses Element (noch) nicht vorliegt. DXFM_OMNIFLO
;; kommt aus setenv.bat mit Backslashes (%DXFMAKRO%\data\omniflo\%DIM%) -
;; vor der Suche auf Forward-Slash normalisieren.
(setq pfad-norm (vl-string-translate "\\" "/" omniflo-pfad))
(setq partner-dim (cond ((vl-string-search "/3D" pfad-norm) "2D")
((vl-string-search "/2D" pfad-norm) "3D")
(t nil)))
(if partner-dim
(progn
(setq basis (substr pfad-norm 1 (- (strlen pfad-norm) 2)))
(setq partner-pfad (strcat basis partner-dim "/" sivasnr-str ".dxf"))
(if (and (not (findfile partner-pfad))
(findfile (strcat basis partner-dim "/" sivasnr-str ".dwg")))
(setq partner-pfad (strcat basis partner-dim "/" sivasnr-str ".dwg"))
)
(if (findfile partner-pfad)
(progn
(princ (ssg-textf "omni-fallback-andere-dim" (list sivasnr-str partner-dim)))
partner-pfad
)
nil
)
)
nil
)
)
)
)
;; --- DXF-Datei als Block einfuegen ---
;; sivasnr-str = SivasNr als String (Dateiname ohne .dxf)
;; hoehe = Hoehe in mm als String (wird als HOEHE-Attribut gesetzt)
;; drehung = Drehwinkel in Grad als String (Block-Rotation)
;; Rueckgabe: Einfuegepunkt oder nil bei Abbruch
(defun omni:insert-dxf (sivasnr-str hoehe drehung / dxf-pfad omniflo-pfad)
(setq omniflo-pfad (getenv "DXFM_OMNIFLO"))
(if (null omniflo-pfad)
(progn
(princ (ssg-text "omni-fehler-dxfm-omniflo"))
nil
)
(progn
(setq dxf-pfad (omni:omniflo-datei-finden sivasnr-str omniflo-pfad))
(if (not dxf-pfad)
(progn
(princ (ssg-textf "omni-fehler-dxf-nicht-gefunden" (list (strcat omniflo-pfad "/" sivasnr-str ".dxf"))))
nil
)
(omni:insert-datei dxf-pfad sivasnr-str hoehe drehung)
)
)
)
)
;; --- Block-Datei (DXF/DWG) interaktiv einfuegen ---
;; dxf-pfad = vollstaendiger Pfad der Blockdatei (bereits auf Existenz geprueft)
;; name = Anzeigename/Blockname fuer Meldung und Layer-Vorgabe
;; hoehe, drehung wie omni:insert-dxf
;; Rueckgabe: Einfuegepunkt oder nil bei Abbruch
(defun omni:insert-datei (dxf-pfad name hoehe drehung / angleDeg
drehung-anzeige blockEnt attribs layer-name ed pt10 zval zdelta)
(ssg-start "OMNI DXF Insert" '(("ATTREQ") ("ATTDIA")))
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
;; Absolute Z-Hoehe fuer den Einfuegepunkt bestimmen
(setq zval (if (and hoehe (/= hoehe "")) (atof hoehe) 0.0))
;; Interaktives Einfuegen mit Live-Vorschau am Mauszeiger:
;; dxf-pfad -> Block aus Datei definieren/waehlen
;; 1. 'pause -> Einfuegepunkt; Objekt haengt sichtbar am Cursor und
;; verschiebt sich mit der Maus (erster Klick positioniert)
;; "" "" -> X-/Y-Massstab = 1
;; Drehung -> aus Dialog fest, sonst 2. 'pause: Objekt dreht sich
;; beim Ziehen sichtbar mit, zweiter Klick beendet
(if drehung
(progn
(setq angleDeg (atof drehung))
(setq drehung-anzeige drehung)
(command "_.INSERT" dxf-pfad pause "" "" angleDeg)
)
(command "_.INSERT" dxf-pfad pause "" "" pause)
)
;; INSERT vollstaendig abschliessen (bei Bedarf weitere Eingabe zulassen)
(while (> (getvar "CMDACTIVE") 0) (command pause))
(setq blockEnt (entlast))
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
(progn
(setq ed (entget blockEnt))
;; Tatsaechlich per Maus gesetzte Drehung ermitteln (interaktiv)
(if (null drehung)
(progn
(setq angleDeg (* (cdr (assoc 50 ed)) (/ 180.0 pi)))
(setq drehung-anzeige (rtos angleDeg 2 1))
)
)
;; Z-Hoehe absolut anwenden: Block (inkl. Attribute) per MOVE um
;; die Differenz zum aktuellen Einfuegepunkt-Z verschieben. Osnap
;; beim interaktiven Einfuegen kann eine abweichende Z-Lage liefern,
;; daher Differenz statt fixem Wert (vgl. GF-Z-Versatz-Bug).
;; Explizite Koordinaten unterliegen keinem Objektfang.
(setq pt10 (cdr (assoc 10 ed)))
(setq zdelta (- zval (caddr pt10)))
(if (/= zdelta 0.0)
(command "_.MOVE" blockEnt "" (list 0.0 0.0 0.0) (list 0.0 0.0 zdelta))
)
;; HOEHE und DREHUNG Attribute setzen
(ssg-attrib-set-on blockEnt
(list (cons "HOEHE" (if hoehe hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
(cons "DREHUNG" drehung-anzeige)))
;; Layer aus der Block-Vorgabe (LAYER-Attribut) setzen
(setq attribs (ssg-attrib-read blockEnt))
(setq layer-name (ssg-block-layer-vorgabe blockEnt name attribs))
)
)
;; Fallback fuer Anzeige, falls keine Drehung ermittelt wurde
(if (null drehung-anzeige)
(setq drehung-anzeige (rtos (if angleDeg angleDeg 0.0) 2 1))
)
;; Eindeutige ID zuweisen
(if (and blockEnt (atoms-family 1 '("ssg-id-generate")))
(ssg-id-generate blockEnt)
)
(princ (ssg-textf "omni-dxf-eingefuegt"
(list
name
(if hoehe hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))
drehung-anzeige
(if layer-name (strcat " Layer=" layer-name) "")
)))
(ssg-end)
;; Rueckgabe: tatsaechlicher Einfuegepunkt
(if blockEnt (cdr (assoc 10 (entget blockEnt))))
)
;; --- Eintrag aus Dialog-Ergebnis einfuegen ---
;; dlg-result = (eintrag hoehe drehung) aus omni:bogen-dialog / omni:weichen-dialog
(defun omni:insert-from-entry (dlg-result / eintrag hoehe drehung sivasnr-str)
(if dlg-result
(progn
(setq eintrag (car dlg-result))
(setq hoehe (cadr dlg-result))
(setq drehung (caddr dlg-result))
(setq sivasnr-str (omni:sivasid-to-str (omni:val eintrag "Sivasnr")))
(princ (ssg-textf "omni-einfuegen-info"
(list (omni:val eintrag "ProfilTyp") sivasnr-str)))
(omni:insert-dxf sivasnr-str hoehe drehung)
)
)
)
;; ============================================================
;; OMNIFLO WEICHEN-BEFEHLE
;; ============================================================
;; Je Winkel EIN Dialog mit Einzel-, Doppel- und Dreiwegeweichen; der Typ wird
;; ueber die Radiogruppe "Richtung" gewaehlt (Links/Rechts/Doppel/Dreiwege).
;; Ersetzt die frueheren OMNI_W<winkel>_Einfach/_Doppel/_Dreiwege.
(defun omni:weichen-befehl (winkel / dlg-result)
(setq dlg-result (omni:weichen-dialog winkel *omni-weichen-std-typen* nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
;; --- Omniflo / Weichen 90 Grad ---
(defun c:OMNI_W90 () (omni:weichen-befehl 90))
;; --- Omniflo / Weichen 45 Grad ---
(defun c:OMNI_W45 () (omni:weichen-befehl 45))
;; --- Omniflo / Weichen Parallel (KurvenWinkel 0) ---
(defun c:OMNI_WP () (omni:weichen-befehl 0))
;; --- Omniflo / Weichenkoerper (KurvenWinkel 22.5) ---
(defun c:OMNI_WK () (omni:weichen-befehl 22.5))
;; --- Omniflo / Weichenkombinationen ---
(defun c:OMNI_WKomb_Delta_1400 ( / dlg-result)
(setq dlg-result (omni:weichen-dialog nil "Deltaweiche" nil nil 1400))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_WKomb_Delta_1600 ( / dlg-result)
(setq dlg-result (omni:weichen-dialog nil "Deltaweiche" nil nil 1600))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_WKomb_Star ( / dlg-result)
(setq dlg-result (omni:weichen-dialog nil "Sternweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
;; ============================================================
;; OMNIFLO ELEMENT BEARBEITEN
;; Selektiertes Omniflo-Element erneut im Dialog oeffnen,
;; Typ/Hoehe/Drehung aendern und Block ersetzen.
;; ============================================================
(defun c:OMNI_EDIT ( / ss sel ent ed attribs bname
artinr hoehe drehung rotation
typ eintrag winkel weichentyp
dlg-result new-eintrag new-hoehe new-drehung
basePoint sivasnr-str dxf-pfad data-pfad angleDeg blockEnt
layer-name such)
;; Implied Selection pruefen
(setq ss (ssget "I"))
(if (and ss (= (sslength ss) 1)
(= (cdr (assoc 0 (entget (ssname ss 0)))) "INSERT"))
(setq ent (ssname ss 0))
)
(ssg-start "Omniflo bearbeiten" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
(setvar "OSMODE" 0)
;; 1. Block auswaehlen (falls nicht vorselektiert)
(if (null ent)
(progn
(setq sel (entsel (ssg-text "omni-edit-prompt-auswahl")))
(if sel (setq ent (car sel)))
)
)
(if (null ent) (progn (ssg-end) (exit)))
(setq ed (entget ent))
(if (/= (cdr (assoc 0 ed)) "INSERT")
(progn (ssg-emsg (ssg-text "omni-edit-kein-block")) (ssg-end) (exit))
)
;; 2. Bestehende Attribute lesen
(setq attribs (ssg-attrib-read ent))
(setq bname (cdr (assoc 2 ed)))
(setq basePoint (cdr (assoc 10 ed)))
(setq rotation (* (/ 180.0 pi) (cdr (assoc 50 ed))))
;; ARTINR = SivasNr, TEILEART = Typ-Erkennung
(setq artinr (cdr (assoc "ARTINR" attribs)))
(setq hoehe (cdr (assoc "HOEHE" attribs)))
(setq drehung (cdr (assoc "DREHUNG" attribs)))
;; Fallbacks
(if (null hoehe) (setq hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
(if (null drehung) (setq drehung (rtos rotation 2 1)))
;; 3. Typ bestimmen: Bogen oder Weiche
(if (null *OMNI-BOEGEN*) (omni:load-data))
(setq typ nil)
(setq eintrag nil)
;; Zuerst in Boegen suchen
(if artinr
(progn
(setq eintrag (omni:get-bogen (if (/= (atoi artinr) 0) (atoi artinr) artinr)))
(if eintrag (setq typ "bogen"))
)
)
;; Falls nicht gefunden, in Weichen suchen
(if (and (null eintrag) artinr)
(progn
(setq eintrag (omni:get-weiche (if (/= (atoi artinr) 0) (atoi artinr) artinr)))
(if eintrag (setq typ "weiche"))
)
)
;; Auch ueber Blockname versuchen (= SivasNr)
(if (null eintrag)
(progn
(setq eintrag (omni:get-bogen (if (/= (atoi bname) 0) (atoi bname) bname)))
(if eintrag (setq typ "bogen"))
)
)
(if (null eintrag)
(progn
(setq eintrag (omni:get-weiche (if (/= (atoi bname) 0) (atoi bname) bname)))
(if eintrag (setq typ "weiche"))
)
)
;; 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)
(progn
(ssg-emsg (ssg-text "omni-edit-kein-element"))
(ssg-end)
(exit)
)
)
;; 4. Dialog oeffnen mit vorhandenen Werten; das bearbeitete Bauteil wird
;; ueber *omni-dlg-vorwahl* im Dropdown vorgewaehlt (danach zuruecksetzen,
;; damit die Menuebefehle wieder ohne Vorwahl starten).
(setq dlg-result nil)
(setq *omni-dlg-vorwahl* eintrag)
(cond
((= typ "bogen")
(setq winkel (cdr (assoc "KurvenWinkel" eintrag)))
(setq dlg-result (omni:bogen-dialog winkel hoehe drehung nil))
)
((= typ "ladeschleife")
(setq dlg-result (omni:ladeschleifen-dialog nil hoehe))
)
(T
(setq winkel (cdr (assoc "KurvenWinkel" eintrag)))
(setq weichentyp (cdr (assoc "WeichenTyp" eintrag)))
;; Einzel/Doppel/Dreiwege teilen sich einen Dialog - Wechsel ueber "Richtung"
(if (member weichentyp *omni-weichen-std-typen*)
(setq weichentyp *omni-weichen-std-typen*))
(setq dlg-result (omni:weichen-dialog winkel weichentyp hoehe drehung nil))
)
)
(setq *omni-dlg-vorwahl* nil)
(if (null dlg-result)
(progn (princ (ssg-text "omni-abbruch")) (ssg-end) (exit))
)
;; 5. Neuen Eintrag und Werte extrahieren
;; Drehung: Dialog liefert keine Drehung mehr (interaktiv beim Neu-Einfuegen);
;; beim Edit wird die bestehende Blockdrehung beibehalten. Quelle ist die
;; tatsaechliche Geometrie (rotation = Gruppe 50 in Grad, immer numerisch),
;; nicht das DREHUNG-Attribut (kann fehlen/kein Zahl-String sein -> (atof T)).
(setq new-eintrag (car dlg-result))
(setq new-hoehe (cadr dlg-result))
(setq new-drehung (rtos rotation 2 1))
(setq sivasnr-str (omni:sivasid-to-str (omni:val new-eintrag "Sivasnr")))
;; 6. DXF-Datei pruefen (gleiche Aufloesung inkl. 2D/3D-Fallback wie in
;; omni:insert-dxf, siehe omni:omniflo-datei-finden)
(setq dxf-pfad (omni:omniflo-datei-finden sivasnr-str (getenv "DXFM_OMNIFLO")))
(if (not dxf-pfad)
(progn
(ssg-emsg (ssg-textf "omni-edit-dxf-nicht-gefunden"
(list (strcat (getenv "DXFM_OMNIFLO") "/" sivasnr-str ".dxf"))))
(ssg-end)
(exit)
)
)
;; 7. Alten Block loeschen und neuen einfuegen
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
(command "_.ERASE" ent "")
(setq angleDeg (if new-drehung (atof new-drehung) 0.0))
;; Hoehe als Z-Koordinate auf den Einfuegepunkt anwenden
(if (and new-hoehe (/= new-hoehe ""))
(setq basePoint (list (car basePoint) (cadr basePoint) (atof new-hoehe)))
)
(command "_.INSERT" dxf-pfad basePoint "" "" angleDeg)
(setq blockEnt (entlast))
;; Attribute setzen
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
(progn
(ssg-attrib-set-on blockEnt
(list (cons "HOEHE" (if new-hoehe new-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
(cons "DREHUNG" (if new-drehung new-drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))))
;; Layer aus der Block-Vorgabe (LAYER-Attribut) setzen (wie omni:insert-dxf)
(setq attribs (ssg-attrib-read blockEnt))
(setq layer-name (ssg-block-layer-vorgabe blockEnt sivasnr-str attribs))
)
)
(princ (ssg-textf "omni-edit-aktualisiert"
(list
sivasnr-str
(if new-hoehe new-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))
(if new-drehung new-drehung (ssg-cfg-or "omniflo" "default_drehung" "0"))
)))
(ssg-end)
(princ)
)
;; --- Omniflo / Anbaugruppen, Scanner, Stopper ---
;; Feste TEF-Bauteile ohne Sivas-Auswahl: Datei liegt direkt unter DXFM_OMNIFLO,
;; wird per omni:insert-dxf am gewaehlten Einfuegepunkt ohne Drehung eingefuegt.
(defun c:OMNI_STOPPER ()
(omni:insert-dxf "827062022" nil nil)
(princ)
)
(defun c:OMNI_SCANNER ()
(omni:insert-dxf "Scanner" nil nil)
(princ)
)
(defun c:OMNI_BUERSTENBREMSE ()
(omni:insert-dxf "827064041" nil nil)
(princ)
)
;; --- Omniflo / Türlösungen Schwenkschienen ---
;; Feste TEF-Bauteile ohne Sivas-Auswahl: Datei liegt direkt unter DXFM_OMNIFLO,
;; wird per omni:insert-dxf am gewaehlten Einfuegepunkt ohne Drehung eingefuegt.
(defun c:OMNI_SCHW_400_R ()
(omni:insert-dxf "824604002" nil nil)
(princ)
)
(defun c:OMNI_SCHW_400_L ()
(omni:insert-dxf "824604001" nil nil)
(princ)
)
(defun c:OMNI_SCHW_400_R_SENSORIK ()
(omni:insert-dxf "824604012" nil nil)
(princ)
)
(defun c:OMNI_SCHW_400_L_SENSORIK ()
(omni:insert-dxf "824604011" nil nil)
(princ)
)
;; --- Omniflo / Weichenbatterien ---
;; Fertige Weichenbatterien, DWG = ARTINR (aktuell nur in data/omniflo/2D,
;; omni:omniflo-datei-finden faellt bei 3D darauf zurueck). Menuetexte (BESCHR)
;; und Nummern aus data/omniflo/weichenbatterien_artinr_quelle.dxf. Der
;; Doppelklick (OMNI_EDIT) findet sie im Weichen-Katalog omniflo_weichen.json
;; unter WeichenTyp "Weichenbatterie" (Richtung/Schaltung umstellbar).
(defun c:OMNI_WB_834372536 ()
(omni:insert-dxf "834372536" nil nil)
(princ)
)
(defun c:OMNI_WB_834372537 ()
(omni:insert-dxf "834372537" nil nil)
(princ)
)
(defun c:OMNI_WB_834372512 ()
(omni:insert-dxf "834372512" nil nil)
(princ)
)
(defun c:OMNI_WB_834372513 ()
(omni:insert-dxf "834372513" nil nil)
(princ)
)
(defun c:OMNI_WB_834372524 ()
(omni:insert-dxf "834372524" nil nil)
(princ)
)
(defun c:OMNI_WB_834372525 ()
(omni:insert-dxf "834372525" nil nil)
(princ)
)
(defun c:OMNI_WB_834372500 ()
(omni:insert-dxf "834372500" nil nil)
(princ)
)
(defun c:OMNI_WB_834372501 ()
(omni:insert-dxf "834372501" nil nil)
(princ)
)
(defun c:OMNI_WB_834372539 ()
(omni:insert-dxf "834372539" nil nil)
(princ)
)
(defun c:OMNI_WB_834372540 ()
(omni:insert-dxf "834372540" nil nil)
(princ)
)
(defun c:OMNI_WB_834372515 ()
(omni:insert-dxf "834372515" nil nil)
(princ)
)
(defun c:OMNI_WB_834372516 ()
(omni:insert-dxf "834372516" nil nil)
(princ)
)
(defun c:OMNI_WB_834372527 ()
(omni:insert-dxf "834372527" nil nil)
(princ)
)
(defun c:OMNI_WB_834372528 ()
(omni:insert-dxf "834372528" nil nil)
(princ)
)
(defun c:OMNI_WB_834372503 ()
(omni:insert-dxf "834372503" nil nil)
(princ)
)
(defun c:OMNI_WB_834372504 ()
(omni:insert-dxf "834372504" nil nil)
(princ)
)
;; --- Omniflo / TEF Elemente ---
;; Feste TEF-Bauteile ohne Sivas-Auswahl: Datei liegt direkt unter DXFM_OMNIFLO,
;; wird per omni:insert-dxf am gewaehlten Einfuegepunkt ohne Drehung eingefuegt.
(defun c:OMNI_TEF_UmlenkR ()
(omni:insert-dxf "Umlenkspannst_TEF_rechts" nil nil)
(princ)
)
(defun c:OMNI_TEF_UmlenkL ()
(omni:insert-dxf "Umlenkspannst_TEF_links" nil nil)
(princ)
)
(defun c:OMNI_TEF_AntriebL ()
(omni:insert-dxf "0_B10010" nil nil)
(princ)
)
(defun c:OMNI_TEF_AntriebR ()
(omni:insert-dxf "0_B10020" nil nil)
(princ)
)
(defun c:OMNI_TEF_Gerade ()
(omni:insert-dxf "0_B10030" nil nil)
(princ)
)
;; --- Omniflo / KettenFoerderer ---
;; Der Platzhalter c:OMNI_KettenFoerderer (reiner Dummy, gab nur "[DUMMY]
;; KettenFoerderer" aus und war im Menue ausgegraut) wurde entfernt: der
;; Kettenfoerderer ist seit 2026-10-22 als eigene Baugruppe umgesetzt, der
;; Menueeintrag zeigt jetzt auf (ssg-ensure "KettenFoerderer") KETTENFOERDERER
;; (Lisp/KettenFoerderer.lsp). Damit war der Dummy toter Code - auf ihn verwies
;; nur noch der Menueeintrag selbst.
;; --- 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
;; Vorwahl: *omni-dlg-vorwahl* (von OMNI_EDIT gesetzt) wird vorgewaehlt.
(defun omni:ladeschleifen-dialog (profiltyp init-hoehe / liste dat ergebnis dlg-hoehe profil idx)
(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)
;; Beim Edit (OMNI_EDIT) das bearbeitete Bauteil vorwaehlen
(setq idx (omni:vorwahl-index *omni-dlg-vorwahl* liste))
(if (null idx) (setq idx 0))
(set_tile "ladeschleife" (itoa idx))
(set_tile "val_hoehe" init-hoehe)
(omni:ladeschleife-dlg-update (itoa idx))
(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 ---
;; Verbinder-Bloecke liegen dimensionsunabhaengig als DWG in
;; data/omniflo/Verbinder (nicht unter DXFM_OMNIFLO = data/omniflo/<DIM>).
;; Einfuegen wie die festen TEF-Bauteile ueber omni:insert-datei: Punkt und
;; Drehung interaktiv, Layer aus dem LAYER-Attribut, ID per ssg-id-generate.
;; Befehl -> DWG-Name steht direkt im jeweiligen c:OMNI_TV_*-Befehl.
;; Pfad der Verbinder-DWG aus Datenverzeichnis + Dateiname (ohne .dwg)
(defun omni:verbinder-pfad (data-pfad datei)
(strcat (vl-string-right-trim "/" (vl-string-translate "\\" "/" data-pfad))
"/omniflo/Verbinder/" datei ".dwg")
)
;; Verbinder-DWG interaktiv einfuegen. Rueckgabe: Einfuegepunkt oder nil
(defun omni:insert-verbinder (datei / data-pfad pfad)
(setq data-pfad (getenv "DXFM_DATA"))
(cond
((null data-pfad)
(princ (ssg-text "omni-fehler-dxfm-data"))
nil)
((not (findfile (setq pfad (omni:verbinder-pfad data-pfad datei))))
(princ (ssg-textf "omni-fehler-dxf-nicht-gefunden" (list pfad)))
nil)
(t (omni:insert-datei pfad datei nil nil))
)
)
(defun c:OMNI_TV_W_W ()
(omni:insert-verbinder "TV_W-W_kpl")
(princ)
)
(defun c:OMNI_TV_W_AP110 ()
(omni:insert-verbinder "TV_W-AP110_kpl")
(princ)
)
(defun c:OMNI_TV_W_AP60 ()
(omni:insert-verbinder "TV_W-AP60_oben")
(princ)
)
(defun c:OMNI_TV_W_AP60_KPL ()
(omni:insert-verbinder "TV_W-AP60_kpl")
(princ)
)
(defun c:OMNI_TV_W_AP110_W ()
(omni:insert-verbinder "TV_W-AP110-W_kpl")
(princ)
)
(defun c:OMNI_TV_80 ()
(omni:insert-verbinder "TV_80_kpl")
(princ)
)
(defun c:OMNI_TV_50 ()
(omni:insert-verbinder "TV_50_kpl")
(princ)
)
(defun c:OMNI_TV_ENDPLATTE ()
(omni:insert-verbinder "VB_ENDP_AP")
(princ)
)
(defun c:OMNI_TV_ANSCHLAG ()
(omni:insert-verbinder "VB_ENDP_AP_Spulenzug")
(princ)
)
(defun c:OMNI_TV_A_AP110_AP60 ()
(omni:insert-verbinder "TV_AP110-AP60_kpl")
(princ)
)
(defun c:OMNI_TV_A_AP60_ST ()
(omni:insert-verbinder "TV_AP60-ST_kpl")
(princ)
)
(defun c:OMNI_TV_A_AP110_ST ()
(omni:insert-verbinder "TV_AP110-ST_kpl")
(princ)
)
(defun c:OMNI_TV_SW_II_SW_SW ()
(omni:insert-verbinder "TV_SW-SW")
(princ)
)
(defun c:OMNI_TV_SW_III_AP110_SW ()
(omni:insert-verbinder "TV_SW-AP110-SW")
(princ)
)
(defun c:OMNI_TV_W_AP60_KPL ()
(omni:insert-verbinder "TV_W-AP60_kpl")
(princ)
)
(defun c:OMNI_TV_SW_I_AP110 ()
(omni:insert-verbinder "TV_SW_I_SW-AP110")
(princ)
)
(defun c:OMNI_TV_SW_IV_AP60 ()
(omni:insert-verbinder "TV_SW_IV_SW-AP60")
(princ)
)
(defun c:OMNI_TV_SW_IV_ST ()
(omni:insert-verbinder "TV_SW_IV_SW-ST")
(princ)
)
(defun c:OMNI_TV_MUFFE ()
(omni:insert-verbinder "VB_Muffe")
(princ)
)
;; --- Omniflo / Boegen fuer Weichen ---
(defun c:OMNI_APBW_R400_45_140 ()
(princ "\n[DUMMY] APB 110 R400/45 140 nur fuer Delta")
(princ)
)
(defun c:OMNI_APBW_R550_45_194 ()
(princ "\n[DUMMY] APB 110 R550/45 194 nur fuer Delta")
(princ)
)
(defun c:OMNI_APBW_R550_225_360 ()
(princ "\n[DUMMY] APBW 110 R550/22,5 360x248,5")
(princ)
)
(defun c:OMNI_APBW_R550_225_410A ()
(princ "\n[DUMMY] APBW 110 R550/22,5 410x298,5")
(princ)
)
(defun c:OMNI_APBW_R550_225_410B ()
(princ "\n[DUMMY] APBW 110 R550/22,5 410x78,5")
(princ)
)
(defun c:OMNI_APBW_R550_225_410C ()
(princ "\n[DUMMY] APBW 110 R550/22,5 410x98,5")
(princ)
)
(defun c:OMNI_APBW_R550_675_360 ()
(princ "\n[DUMMY] APBW 110 R550/67,5 360x598,5")
(princ)
)
(defun c:OMNI_APBW_R400_675_260 ()
(princ "\n[DUMMY] APBW 110 R400/67,5 260x398,5")
(princ)
)
(defun c:OMNI_APBW_R550_45_77 ()
(princ "\n[DUMMY] APBW 110 R550/45 77x160")
(princ)
)
(defun c:OMNI_APBW_R550_675_125 ()
(princ "\n[DUMMY] APBW 110 R550/67,5 125x83,5")
(princ)
)
(defun c:OMNI_APBW_R750_90_200 ()
(princ "\n[DUMMY] APBW 110 R750/90 200x290")
(princ)
)
(defun c:OMNI_APBW_R650_90_300 ()
(princ "\n[DUMMY] APBW 110 R650/90 300x190")
(princ)
)
(defun c:OMNI_APBW_R550_675_208 ()
(princ "\n[DUMMY] APBW 110 R550/67,5 208x347")
(princ)
)
(defun c:OMNI_APBW_R550_675_58 ()
(princ "\n[DUMMY] APBW 110 R550/67,5 58x497")
(princ)
)