;; ============================================================ ;; HwPlanung.lsp - Hardware-Planung (Menue "HW Planung") ;; ;; Ziel der Ausgabe: vor jedem Erzeugungsbefehl fragt der Dialog ;; dcl/hw_ausgabe.dcl (hw-ausgabe-waehlen), wohin: ;; - aktuelle Zeichnung: Python schreibt eine einheitenlose Zwischendatei ;; _HW_tmp.dxf, die als Block bei 0,0 eingefuegt und aufgeloest wird ;; (hw-in-aktuelle-zeichnung); die fruehere Ausgabe (XDATA SSG_HW_MF bzw. ;; SSG_HW_SYM) wird danach entfernt ;; - bestehende Datei ergaenzen (Dateiauswahl) ;; - neue Datei (Name, Ordner DXFM_RESULTS) ;; In einer Datei ersetzt jeder Befehl nur seinen eigenen Anteil - was der ;; Anwender dort ergaenzt (Renamer-Rahmen, Polylinien), bleibt erhalten. ;; ;; HW_MATERIALFLUSS ("Materialfluss erzeugen", in der Ursprungszeichnung): ;; EXPORTCSV -> lib/hw_materialfluss.py zeichnet Kreisel-Rechtecke in ;; Drehrichtung, Strecken-Polylinien AS -> Separatoren -> ES, Weichen und ;; Be-/Entladungen auf die HW_*-Layer der _HW.dxf. ;; ;; HW_SYMBOLE ("Symbole erzeugen", in der Ursprungszeichnung): sucht die ;; Mechanik-Bauteile nach cfg/io_regeln.json (auch verschachtelt in ;; VF_n/GF_n/KREISEL_n), schreibt den Symbolplan als JSON und laesst ;; lib/hw_symbole.py die Symbole in die _HW.dxf setzen - deren Aussehen und ;; Attribute stehen in cfg/hw_symbole.json (keine Symbol-Bibliothek). Die Geraete-ID ist noch eine VORLAGE (z.B. MB1@@@) - ;; nummeriert wird erst mit HW_NUMMERIEREN, entlang der Rahmen/Polylinien, ;; die der Anwender in der _HW.dxf zieht. Einzelbefehle HW_SYM_VENTILE usw. ;; ;; HW_NUMMERIEREN ("Symbole nummerieren", in der geoeffneten _HW.dxf): ;; speichert die Zeichnung, laesst lib/create_numbers.py (Renamer-Bereiche, ;; cfg/enumerate.cfg) die Nummern berechnen und traegt sie in die offene ;; Zeichnung ein. ;; ;; Setzt export.lsp voraus (laedt die MNL vor). ;; ============================================================ (setq *hw-skript* "hw_materialfluss.py") (setq *hw-sym-skript* "hw_symbole.py") (setq *hw-num-skript* "create_numbers.py") ;; XDATA der erzeugten Objekte (gesetzt von lib/hw_materialfluss.py bzw. ;; lib/hw_symbole.py) - daran erkennt hw-alte-ausgabe die fruehere Ausgabe (setq *hw-mf-app* "SSG_HW_MF") (setq *hw-sym-app* "SSG_HW_SYM") ;; Letzte Wahl im Ausgabe-Dialog (modus datei name), je Sitzung (if (not (boundp '*hw-ausgabe-letzt*)) (setq *hw-ausgabe-letzt* nil)) ;; Geraeteart -> Praefix (Einzelbefehle unten, noch nicht im Menue) (setq *hw-sym-arten* '(("ventile" "MB") ("sensoren" "BG") ("motoren" "MA") ("motorschutz" "FC") ("encoder" "GF") ("scanner" "BX"))) ;; ------------------------------------------------------------ ;; Reine Kerne (tests/test_unit.lsp, tu-tests-hw) ;; ------------------------------------------------------------ ;; Name der Ausgabedatei aus dem Zeichnungsnamen: "Mubea.dwg" -> "Mubea_HW.dxf" (defun hw-dxf-name (dwgname) (strcat (vl-filename-base dwgname) "_HW.dxf") ) ;; Zahl fuer JSON, unabhaengig von DIMZIN/LUPREC (rtos wuerde bei DIMZIN- ;; Unterdrueckung der fuehrenden Null ".5" liefern - kein gueltiges JSON). ;; Auf 0.001 gerundet: (hw-json-zahl -12.5) -> "-12.500" (defun hw-json-zahl (x / n r s) (setq n (fix (+ (* (abs x) 1000.0) 0.5)) r (itoa (rem n 1000))) (while (< (strlen r) 3) (setq r (strcat "0" r))) (setq s (strcat (itoa (/ n 1000)) "." r)) (if (and (< x 0.0) (> n 0)) (strcat "-" s) s) ) (defun hw-json-text (s) (strcat "\"" (ssg-json-escape s) "\"") ) ;; Rollen-Objekt zum Rollennamen (defun hw-sym-rolle (regeln name / erg) (foreach r (ssg-json-get regeln "rollen") (if (and (null erg) (= (ssg-json-get r "rolle") name)) (setq erg r))) erg ) ;; Rollennamen eines Bauteils - je Eintrag in "benoetigt" die erste Alternative (defun hw-sym-bauteil-rollen (bauteil) (mapcar 'car (ssg-json-get bauteil "benoetigt")) ) ;; wcmatch-Muster aller Mechanik-Bloecke (gross, kommagetrennt) (defun hw-sym-muster (regeln / muster) (foreach b (ssg-json-get regeln "bauteile") (setq muster (append muster (ssg-json-get b "bloecke")))) (strcase (ssg-join muster ",")) ) ;; Bauteil-Objekt zum Blocknamen (erster Treffer) oder nil (defun hw-sym-bauteil-fuer-block (regeln blockname / erg) (foreach b (ssg-json-get regeln "bauteile") (if (and (null erg) (wcmatch (strcase blockname) (strcase (ssg-join (ssg-json-get b "bloecke") ",")))) (setq erg b))) erg ) ;; Symbol (Blockname) einer Rolle, ggf. abhaengig vom Blocknamen des Bauteils ;; (block_nach_name, z.B. Vario-Motorstation rechts -> Motor VARIO rechts) (defun hw-sym-block-fuer (rolle bauteil-blockname / erg) (foreach v (ssg-json-get rolle "block_nach_name") (if (and (null erg) (wcmatch (strcase bauteil-blockname) (strcase (ssg-json-get v "muster")))) (setq erg (ssg-json-get v "block")))) (cond (erg) ((ssg-json-get rolle "block"))) ) ;; IO-Vorlage eines Symbols: Praefix + io_vorlage, z.B. "MB" + "1@@@" -> "MB1@@@" (defun hw-sym-io-vorlage (regeln praefix) (strcat praefix (cond ((ssg-json-get regeln "io_vorlage")) ("1@@@"))) ) ;; Zielpunkt eines Bauteils in der _HW.dxf: flach (Z = 0) - die _HW.dxf ist ;; ein Grundriss, die Nummerierung arbeitet in XY. (defun hw-sym-ziel (pt) (list (car pt) (cadr pt) 0.0) ) ;; Plan aus Bauteil-Instanzen. instanz = (bauteil blockname pt key). ;; Rueckgabe: Liste von Records, je Rolle in der Reihenfolge von "benoetigt" ;; (= Stapelfolge der Symbole am Bauteil, erstes oben): ;; (praefix io-vorlage symbolblock zielpunkt rolle key bauteilname) ;; Den Einfuegepunkt rechnet lib/hw_symbole.py aus dem Zielpunkt und der ;; Symbolgeometrie (Marke REALE_POSITION auf dem Ziel, ohne Ueberlappung). (defun hw-sym-plan (regeln instanzen / erg rolle) (foreach ins instanzen (foreach name (hw-sym-bauteil-rollen (car ins)) (if (setq rolle (hw-sym-rolle regeln name)) (setq erg (cons (list (ssg-json-get rolle "praefix") (hw-sym-io-vorlage regeln (ssg-json-get rolle "praefix")) (hw-sym-block-fuer rolle (nth 1 ins)) (hw-sym-ziel (nth 2 ins)) name (nth 3 ins) (ssg-json-get (car ins) "bauteil")) erg))))) (reverse erg) ) ;; Sortierung der Instanzen: Bauteil-Reihenfolge im Regelwerk, dann x, dann y (defun hw-sym-instanzen-sortieren (regeln instanzen / bauteile) (setq bauteile (mapcar '(lambda (b) (ssg-json-get b "bauteil")) (ssg-json-get regeln "bauteile"))) ;; Rang vorab anhaengen (rang . instanz), sortieren, wieder abnehmen (mapcar 'cdr (vl-sort (mapcar '(lambda (ins) (cons (vl-position (ssg-json-get (car ins) "bauteil") bauteile) ins)) instanzen) '(lambda (a b) (cond ((/= (car a) (car b)) (< (car a) (car b))) ((not (equal (car (nth 3 a)) (car (nth 3 b)) 0.5)) (< (car (nth 3 a)) (car (nth 3 b)))) (t (< (cadr (nth 3 a)) (cadr (nth 3 b)))))))) ) ;; Symbolplan als JSON-Zeilen fuer lib/hw_symbole.py. praefixe = die ;; Geraetearten, die dieser Lauf einfuegt bzw. ersetzt; der Plan selbst ist ;; immer vollstaendig, damit die Lage nicht davon abhaengt. (defun hw-sym-plan->json (praefixe plan / zeilen) (setq zeilen (mapcar '(lambda (r) (strcat " {\"praefix\": " (hw-json-text (nth 0 r)) ", \"io\": " (hw-json-text (nth 1 r)) ", \"block\": " (hw-json-text (nth 2 r)) ", \"x\": " (hw-json-zahl (car (nth 3 r))) ", \"y\": " (hw-json-zahl (cadr (nth 3 r))) ", \"rolle\": " (hw-json-text (nth 4 r)) ", \"key\": " (hw-json-text (nth 5 r)) ", \"bauteil\": " (hw-json-text (nth 6 r)) "}")) plan)) (append (list "{" (strcat " \"praefixe\": [" (ssg-join (mapcar 'hw-json-text praefixe) ", ") "],") " \"symbole\": [") (if zeilen (append (mapcar '(lambda (z) (strcat z ",")) (reverse (cdr (reverse zeilen)))) (list (last zeilen)))) (list " ]" "}")) ) ;; Name einer neuen Ausgabedatei: Leerzeichen am Rand und eine Endung .dxf ;; werden entfernt (" Anlage_HW.DXF " -> "Anlage_HW") (defun hw-name-ohne-dxf (name / n) (setq n (vl-string-trim " " (cond (name) ("")))) (if (wcmatch (strcase n) "*.DXF") (substr n 1 (- (strlen n) 4)) n) ) ;; Gueltiger Dateiname: nicht leer, keine Pfad- oder Sonderzeichen (defun hw-name-gueltig-p (name / n) (setq n (hw-name-ohne-dxf name)) (and (> (strlen n) 0) (not (wcmatch n "*[\\/:`*?\"<>|]*"))) ) (defun hw-neu-pfad (ordner name) (strcat ordner "/" (hw-name-ohne-dxf name) ".dxf") ) ;; Eingaben des Ausgabe-Dialogs pruefen. datei-da / neu-da = ob die gewaehlte ;; bzw. die neue Datei schon existiert. Rueckgabe: nil oder ssg-text-Key. (defun hw-ausgabe-pruefen (modus datei-da name neu-da) (cond ((= modus "ergaenzen") (if datei-da nil "hw-aus-datei-fehlt")) ((= modus "neu") (cond ((not (hw-name-gueltig-p name)) "hw-aus-name-ungueltig") (neu-da "hw-aus-name-existiert"))) ((= modus "aktuell") nil) (t "hw-aus-datei-fehlt")) ) ;; Nummerierung uebertragen: passt ein Eintrag aus der create_numbers-Info ;; (old_value + Einfuegepunkt) auf ein Attribut? pos/wert aus der Zeichnung. (defun hw-num-eintrag-p (eintrag wert pos / p) (setq p (ssg-json-get eintrag "position")) (and (= (ssg-json-get eintrag "old_value") wert) (equal (ssg-json-get p "x") (car pos) 0.01) (equal (ssg-json-get p "y") (cadr pos) 0.01)) ) ;; ------------------------------------------------------------ ;; Gemeinsam: Ausgabeordner und Python-Aufruf ;; ------------------------------------------------------------ ;; DXFM_RESULTS, ausser waehrend TEST_EXPORT_ALL (*export-test-override*) (defun hw-ausgabe-ordner ( / d) (setq d (if *export-test-override* *export-test-override* (getenv "DXFM_RESULTS"))) (if (and d (not (vl-file-directory-p d))) (vl-mkdir d)) d ) ;; Python-Skript aus DXFM_LIB synchron ausfuehren, Log nach DXFM_LOG. ;; Rueckgabe: Exitcode (0 = ok) oder nil, wenn gar nicht gestartet. ;; ok-codes = Exitcodes, die KEIN Python-Fehler sind (create_numbers endet ;; mit 1, wenn es Planungsfehler meldet - die stehen in seiner Fehlerdatei). (defun hw-python (label skript args log-name ok-codes / log-pfad rc) (setq log-pfad (strcat (cond ((getenv "DXFM_LOG")) ((hw-ausgabe-ordner))) "/" log-name)) (setq rc (export:run-python (export:python-exe) (strcat (getenv "DXFM_LIB") "/" skript) args log-pfad)) (if (null rc) (princ (ssg-textf "exp-python-call-failed" (list label)))) (export:log-ausgeben log-pfad 15) (if (and rc (not (member rc (cons 0 ok-codes)))) (princ (ssg-textf "exp-python-error" (list label rc log-pfad)))) rc ) (defun hw-umgebung-ok-p (label) (if (getenv "DXFM_LIB") T (progn (princ (ssg-textf "exp-dxfm-lib-missing" (list label))) nil)) ) ;; ------------------------------------------------------------ ;; Ausgabeziel: Dialog dcl/hw_ausgabe.dcl ;; ------------------------------------------------------------ (defun hw-ausgabe-modus-tiles (modus) (mode_tile "datei" (if (= modus "ergaenzen") 0 1)) (mode_tile "waehlen" (if (= modus "ergaenzen") 0 1)) (mode_tile "name" (if (= modus "neu") 0 1)) ) ;; OK-Knopf: Eingaben pruefen, bei Fehler im Dialog bleiben. Arbeitet auf den ;; Variablen von hw-ausgabe-waehlen (modus datei name ordner pfad - AutoLISP ;; bindet dynamisch, der Rueckruf laeuft waehrend dessen start_dialog). (defun hw-ausgabe-ok ( / fehler) (setq modus (get_tile "modus") datei (get_tile "datei") name (get_tile "name")) (setq fehler (hw-ausgabe-pruefen modus (if (and (/= datei "") (findfile datei)) T) name (if (findfile (hw-neu-pfad ordner name)) T))) (if fehler (set_tile "error" (ssg-text fehler)) (progn (setq pfad (cond ((= modus "aktuell") (strcat ordner "/" (vl-filename-base (getvar "DWGNAME")) "_HW_tmp.dxf")) ((= modus "ergaenzen") datei) (t (hw-neu-pfad ordner name)))) (done_dialog 1))) ) ;; Ziel der Ausgabe erfragen. aktion = Text oben im Dialog. ;; Rueckgabe: (modus pfad) mit modus "aktuell"/"ergaenzen"/"neu" - bei ;; "aktuell" ist pfad die Zwischendatei - oder nil bei Abbruch. Ohne GUI ;; (automatische Tests): Standarddatei _HW.dxf, anlegen oder ergaenzen. (defun hw-ausgabe-waehlen (aktion / ordner modus datei name pfad dcl dat r f erg weiter) (setq ordner (hw-ausgabe-ordner)) (cond ((not (ssg-gui-p)) (list "ergaenzen" (strcat ordner "/" (hw-dxf-name (getvar "DWGNAME"))))) ((or (null (getenv "DXFM_DCL")) (not (findfile (setq dcl (strcat (getenv "DXFM_DCL") "/hw_ausgabe.dcl")))) (< (setq dat (load_dialog dcl)) 0)) (princ (ssg-textf "hw-aus-dcl-fehlt" (list (cond (dcl) ("hw_ausgabe.dcl"))))) nil) (t (setq modus (cond ((car *hw-ausgabe-letzt*)) ("neu")) datei (cond ((cadr *hw-ausgabe-letzt*)) ((strcat ordner "/" (hw-dxf-name (getvar "DWGNAME"))))) name (cond ((caddr *hw-ausgabe-letzt*)) ((vl-filename-base (hw-dxf-name (getvar "DWGNAME"))))) weiter T) (while weiter (if (not (new_dialog "hw_ausgabe" dat)) (setq weiter nil) (progn (set_tile "aktion" aktion) (set_tile "modus" modus) (set_tile "datei" datei) (set_tile "name" name) (set_tile "ordner" (ssg-textf "hw-aus-ordner" (list ordner))) (hw-ausgabe-modus-tiles modus) (action_tile "modus" "(setq modus $value) (hw-ausgabe-modus-tiles modus) (set_tile \"error\" \"\")") ;; getfiled geht nicht aus einem Rueckruf: Dialog schliessen, ;; waehlen, Dialog neu zeigen (action_tile "waehlen" "(setq datei (get_tile \"datei\") name (get_tile \"name\")) (done_dialog 2)") (action_tile "accept" "(hw-ausgabe-ok)") (action_tile "cancel" "(done_dialog 0)") (setq r (start_dialog)) (cond ((= r 2) (if (setq f (getfiled (ssg-text "hw-aus-waehlen") (if (and (/= datei "") (findfile datei)) datei (strcat ordner "/")) "dxf" 0)) (setq datei f modus "ergaenzen"))) ((= r 1) (setq weiter nil erg (list modus pfad))) (t (setq weiter nil)))))) (unload_dialog dat) (if erg (setq *hw-ausgabe-letzt* (list modus datei name))) erg)) ) ;; Zieldatei fuer Python vorbereiten: die Zwischendatei der aktuellen ;; Zeichnung wird jedesmal frisch angelegt. Rueckgabe: Pfad. (defun hw-ziel-pfad (ziel) (if (and (= (car ziel) "aktuell") (findfile (cadr ziel))) (vl-file-delete (cadr ziel))) (cadr ziel) ) ;; Zusatzargumente fuer Python: Zwischendatei ohne Einheit (sonst skaliert ;; BricsCAD sie beim Einfuegen in eine Zeichnung mit anderer Einheit) (defun hw-zusatz-args (ziel) (if (= (car ziel) "aktuell") '("--einheitenlos")) ) ;; Fruehere Ausgabe in der aktuellen Zeichnung: alle Objekte mit XDATA app, ;; bei praefixe nur die, deren erster 1000er-Wert (Praefix) darin steht. (defun hw-alte-ausgabe (app praefixe / ss i e xd erg) (if (setq ss (ssget "_X" (list (list -3 (list app))))) (progn (setq i 0) (while (setq e (ssname ss i)) (setq xd (cdr (assoc app (cdr (assoc -3 (entget e (list app))))))) (if (or (null praefixe) (member (cdr (assoc 1000 xd)) praefixe)) (setq erg (cons e erg))) (setq i (1+ i))))) erg ) ;; Zwischendatei als Block bei 0,0 einfuegen und aufloesen; erst wenn das ;; geklappt hat, die fruehere Ausgabe (alte) loeschen. Rueckgabe: T/nil. (defun hw-in-aktuelle-zeichnung (pfad alte / doc obj teile blk leer) (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))) (setq obj (vl-catch-all-apply 'vla-InsertBlock (list (vla-get-ModelSpace doc) (vlax-3D-point '(0 0 0)) pfad 1.0 1.0 1.0 0.0))) (if (vl-catch-all-error-p obj) nil (progn ;; Leere Zwischendatei (HW_SYM_LOESCHEN, keine Bauteile): nichts ;; aufzuloesen - ein Explode wuerde scheitern, gilt aber als Erfolg (setq blk (vl-catch-all-apply 'vla-Item (list (vla-get-Blocks doc) (vl-filename-base pfad)))) (setq leer (and (not (vl-catch-all-error-p blk)) (= (vla-get-Count blk) 0))) (if (not leer) (setq teile (vl-catch-all-apply 'vla-Explode (list obj)))) (vla-Delete obj) (if (not (vl-catch-all-error-p blk)) (vl-catch-all-apply 'vla-Delete (list blk))) (if (vl-catch-all-error-p teile) nil (progn (foreach e alte (if (entget e) (entdel e))) (vl-file-delete pfad) T)))) ) ;; Ergebnis eines erfolgreichen Python-Laufs melden bzw. in die aktuelle ;; Zeichnung uebernehmen. app/praefixe: welche fruehere Ausgabe ersetzt wird. (defun hw-ergebnis-uebernehmen (ziel app praefixe meldung / alte) (if (= (car ziel) "aktuell") (progn (setq alte (hw-alte-ausgabe app praefixe)) (if (hw-in-aktuelle-zeichnung (cadr ziel) alte) (princ (ssg-textf "hw-fertig-aktuell" (list (itoa (length alte))))) (princ (ssg-textf "hw-aktuell-fehler" (list (cadr ziel)))))) (princ (ssg-textf meldung (list (cadr ziel))))) ) ;; ------------------------------------------------------------ ;; MATERIALFLUSS ;; ------------------------------------------------------------ (defun c:HW_MATERIALFLUSS ( / label ziel out-dir csv-pfad dxf-pfad) (setq label "HW_MATERIALFLUSS") (if (and (hw-umgebung-ok-p label) (setq ziel (hw-ausgabe-waehlen (ssg-text "hw-aus-materialfluss")))) (progn (setq out-dir (hw-ausgabe-ordner)) (setq csv-pfad (strcat out-dir "/" (export:dwg-praefix) (export:filename "csv_csv"))) (setq dxf-pfad (hw-ziel-pfad ziel)) ;; Alte CSV entfernen - sonst wuerde nach einem gescheiterten Export ;; still die Skizze aus dem vorigen Stand gezeichnet. (if (findfile csv-pfad) (vl-file-delete csv-pfad)) (c:EXPORTCSV) (if (not (findfile csv-pfad)) (princ (ssg-textf "hw-csv-fehlt" (list csv-pfad))) (if (equal 0 (hw-python label *hw-skript* (append (list csv-pfad dxf-pfad) (hw-zusatz-args ziel)) "hw_materialfluss.log" nil)) (hw-ergebnis-uebernehmen ziel *hw-mf-app* nil "hw-fertig"))))) (princ) ) ;; ------------------------------------------------------------ ;; SYMBOLE ERZEUGEN (HW_SYMBOLE + Einzelbefehle je Geraeteart) ;; ------------------------------------------------------------ (defun hw-sym-regeln-laden ( / pfad regeln) (setq pfad (strcat (cond ((getenv "DXFM_CFG")) ("")) "/io_regeln.json")) (setq regeln (if (findfile pfad) (ssg-json-laden pfad))) (if (null regeln) (princ (ssg-textf "hw-sym-regeln-fehlt" (list pfad)))) regeln ) ;; Alle Bauteile der Ursprungszeichnung: top-level INSERTs und in VF_n/GF_n/ ;; KREISEL_n verschachtelte Mechanik-Bloecke (Weltlage ueber ;; csv:wrapper-welt-records, export.lsp). Katalogsymbole (ILS_*) werden ;; nicht durchsucht. Rueckgabe: sortierte Liste (bauteil blockname pt key). (defun hw-sym-bauteile-sammeln (regeln / muster ss i ename ed name bt erg) (setq muster (hw-sym-muster regeln)) (if (setq ss (ssget "_X" '((0 . "INSERT") (410 . "Model")))) (progn (setq i 0) (while (setq ename (ssname ss i)) (setq ed (entget ename) name (cdr (assoc 2 ed))) (cond ((wcmatch (strcase name) muster) (if (setq bt (hw-sym-bauteil-fuer-block regeln name)) (setq erg (cons (list bt name (trans (cdr (assoc 10 ed)) ename 0) (cdr (assoc 5 ed))) erg)))) ((not (wcmatch (strcase name) "ILS_*,`**")) (foreach rec (csv:wrapper-welt-records ename muster) (if (setq bt (hw-sym-bauteil-fuer-block regeln (nth 2 rec))) (setq erg (cons (list bt (nth 2 rec) (nth 3 rec) (strcat (cdr (assoc 5 ed)) "/" (cdr (assoc 5 (entget (nth 1 rec)))))) erg)))))) (setq i (1+ i))))) (hw-sym-instanzen-sortieren regeln erg) ) (defun hw-sym-zaehlen (schluessel alist / alt) (setq alt (assoc schluessel alist)) (if alt (subst (cons schluessel (1+ (cdr alt))) alt alist) (cons (cons schluessel 1) alist)) ) ;; Symbolplan als JSON schreiben und hw_symbole.py die Symbole der ;; angegebenen Praefixe ins gewaehlte Ziel setzen lassen (nil = alle Praefixe ;; des Regelwerks). mit-bauteilen = nil -> leerer Plan (nur entfernen). (defun hw-sym-erzeugen (praefixe mit-bauteilen / label regeln instanzen plan out-dir json-pfad dxf-pfad sym-pfad fh bt-zahl ziel) (setq label "HW_SYMBOLE") (if (and (hw-umgebung-ok-p label) (setq regeln (hw-sym-regeln-laden)) (setq ziel (hw-ausgabe-waehlen (ssg-text "hw-aus-symbole")))) (progn (if (null praefixe) (foreach r (ssg-json-get regeln "rollen") (if (not (member (ssg-json-get r "praefix") praefixe)) (setq praefixe (append praefixe (list (ssg-json-get r "praefix"))))))) (if mit-bauteilen (progn (setq instanzen (hw-sym-bauteile-sammeln regeln)) (if (null instanzen) (princ (ssg-text "hw-sym-keine-bauteile"))) (foreach ins instanzen (setq bt-zahl (hw-sym-zaehlen (ssg-json-get (car ins) "bauteil") bt-zahl))) (foreach z (reverse bt-zahl) (princ (ssg-textf "hw-sym-bauteile" (list (car z) (itoa (cdr z)))))) (setq plan (hw-sym-plan regeln instanzen)))) (setq out-dir (hw-ausgabe-ordner) json-pfad (strcat out-dir "/" (vl-filename-base (getvar "DWGNAME")) "_hw_symbole.json") dxf-pfad (hw-ziel-pfad ziel) sym-pfad (strcat (cond ((getenv "DXFM_CFG")) ("")) "/hw_symbole.json")) (if (not (setq fh (open json-pfad "w"))) (princ (ssg-textf "exp-file-open-error" (list label json-pfad))) (progn (foreach z (hw-sym-plan->json praefixe plan) (write-line z fh)) (close fh) (if (equal 0 (hw-python label *hw-sym-skript* (append (list json-pfad dxf-pfad "--symbole" sym-pfad) (hw-zusatz-args ziel)) "hw_symbole.log" nil)) (hw-ergebnis-uebernehmen ziel *hw-sym-app* praefixe "hw-fertig-symbole")))))) (princ) ) (defun hw-sym-art (art) (hw-sym-erzeugen (cdr (assoc art *hw-sym-arten*)) T) ) ;; Menue: HW Planung -> Symbole erzeugen (defun c:HW_SYMBOLE () (hw-sym-erzeugen nil T)) ;; Einzelbefehle je Geraeteart - noch nicht im Menue, zum schrittweisen ;; Erzeugen und Pruefen. Jeder ersetzt in der _HW.dxf nur die Symbole ;; seiner Art. (defun c:HW_SYM_VENTILE () (hw-sym-art "ventile")) (defun c:HW_SYM_SENSOREN () (hw-sym-art "sensoren")) (defun c:HW_SYM_MOTOREN () (hw-sym-art "motoren")) (defun c:HW_SYM_MOTORSCHUTZ () (hw-sym-art "motorschutz")) (defun c:HW_SYM_ENCODER () (hw-sym-art "encoder")) (defun c:HW_SYM_SCANNER () (hw-sym-art "scanner")) ;; Alle erzeugten Symbole aus dem gewaehlten Ziel entfernen (defun c:HW_SYM_LOESCHEN () (hw-sym-erzeugen nil nil)) ;; ------------------------------------------------------------ ;; NUMMERIEREN (in der geoeffneten _HW.dxf) ;; ------------------------------------------------------------ ;; Nummern aus der create_numbers-Info in die offene Zeichnung eintragen: ;; jedes Attribut mit '@', dessen Wert und Einfuegepunkt zu einem Eintrag ;; passen, bekommt new_value. Rueckgabe: Anzahl geaenderter Attribute. (defun hw-num-anwenden (eintraege / ss i e pos obj ed wert treffer n) (setq n 0) (if (setq ss (ssget "_X" '((0 . "INSERT") (66 . 1) (410 . "Model")))) (progn (setq i 0) (while (setq e (ssname ss i)) (setq pos (cdr (assoc 10 (entget e)))) (setq obj (entnext e)) (while (and obj (= (cdr (assoc 0 (setq ed (entget obj)))) "ATTRIB")) (setq wert (cdr (assoc 1 ed))) (if (vl-string-search "@" wert) (progn (setq treffer nil) (foreach z eintraege (if (and (null treffer) (hw-num-eintrag-p z wert pos)) (setq treffer z))) (if treffer (progn (entmod (subst (cons 1 (ssg-json-get treffer "new_value")) (assoc 1 ed) ed)) (setq n (1+ n)))))) (setq obj (entnext obj))) (entupd e) (setq i (1+ i))))) n ) (defun c:HW_NUMMERIEREN ( / label pfad basis info-pfad fehler-pfad rc info n) (setq label "HW_NUMMERIEREN") (setq pfad (strcat (getvar "DWGPREFIX") (getvar "DWGNAME"))) (cond ((not (hw-umgebung-ok-p label))) ((or (= (getvar "DWGTITLED") 0) (/= (strcase (vl-filename-extension pfad)) ".DXF")) (princ (ssg-textf "hw-num-kein-dxf" (list (getvar "DWGNAME"))))) (t ;; create_numbers liest die Datei von der Platte - erst speichern (command "_.QSAVE") (setq basis (strcat (getvar "DWGPREFIX") (vl-filename-base pfad)) info-pfad (strcat basis "_nummern.json") fehler-pfad (strcat basis "_nummern_fehler.json")) (foreach f (list info-pfad fehler-pfad) (if (findfile f) (vl-file-delete f))) ;; --dryrun: create_numbers schreibt keine DXF, nur die Info - die ;; Nummern werden hier in die OFFENE Zeichnung eingetragen. (setq rc (hw-python label *hw-num-skript* (list "--filename" pfad "--dryrun" "--info" info-pfad "--errorfile" fehler-pfad) "hw_nummerieren.log" '(1))) (if (and rc (setq info (if (findfile info-pfad) (ssg-json-laden info-pfad)))) (progn (setq n (hw-num-anwenden (ssg-json-get info "renamed_symbols"))) (princ (ssg-textf "hw-num-ergebnis" (list (itoa n)))))) (if (findfile fehler-pfad) (princ (ssg-textf "hw-num-fehler" (list fehler-pfad)))))) (princ) ) (princ "\n>>> HwPlanung.lsp geladen") (princ)