;; ============================================================ ;; DrawPlanquadrate.lsp - Planquadrat-Raster in die Zeichnung zeichnen ;; ;; Zeichnet auf Hoehe Z=0 senkrechte Linien (konstantes X) und waagerechte ;; Linien (konstantes Y) im Abstand der aktiven Planquadrat-Konfiguration aus ;; cfg/export.cfg ([Planquadrate] section=... -> [Planquadrate_AN] o.ae., ;; siehe export:cfg/export:load-cfg in export.lsp) - dieselbe Konfiguration, ;; nach der export_planquadrat.py (lib/) das Planquadrat eines Bauteils fuer ;; den CSV-Export berechnet. Am linken Rand steht je Zeile, am unteren Rand ;; je Spalte die zugehoerige Zaehlung (alphabetisch oder numerisch, je nach ;; x_description/y_description). ;; ;; Bereich: die aktuellen Zeichnungs-Extents (EXTMIN/EXTMAX), aber IMMER auf ;; ein ganzzahliges Vielfaches der Schrittweite ab dem Ursprung aufgerundet - ;; das Raster bildet also stets ein GESCHLOSSENES Rechteck: jede senkrechte ;; Linie endet exakt auf der letzten waagerechten und umgekehrt (kein ;; "Ueberstand" einzelner Linien ueber die letzte volle Zeile/Spalte hinaus). ;; x_origin/y_origin aus [Planquadrate] legen die Koordinate von Index 1 fest ;; (wie im CSV-Export); sind sie leer, faellt der Ursprung auf EXTMIN zurueck ;; (= kleinstes X/Y der Zeichnung, analog zur Auto-Ermittlung in ;; export_planquadrat.resolve_origins). ;; ;; Das fertige Raster (Linien + Beschriftungstexte) wird zu EINEM Block ;; (*plq-blockname*) zusammengefasst und bei (0,0,0) eingefuegt - dadurch ;; laesst sich das gesamte Planquadrat mit einem Klick auswaehlen/loeschen. ;; Bei jedem Aufruf wird ein evtl. vorhandener Planquadrat-Block zuerst ;; entfernt (DELETE_PLANQUADRATE-Logik) und danach neu gezeichnet - ;; wiederholte Aufrufe erzeugen also keine Dubletten. ;; ;; Befehle: ;; DRAW_PLANQUADRATE - Raster zeichnen/neu aufbauen ;; DELETE_PLANQUADRATE - Raster-Block entfernen (inkl. Blockdefinition) ;; PLANQUADRATE_TOGGLE - "Planquadrate an/aus": zeichnet, falls noch kein ;; Block in der Zeichnung ist, sonst loescht es ihn ;; (Menue: Konfiguration) ;; ============================================================ (vl-load-com) ;; Name der zusammenfassenden Blockdefinition. Fest (keine laufende Nummer): ;; es gibt je Zeichnung immer hoechstens ein Planquadrat-Raster. (setq *plq-blockname* "ZZ_PLANQUADRATE") ;; --- Layer fuer das Planquadrat-Raster --- ;; cfg/layer.cfg [allgemein] Key "planquadrate"; ohne Eintrag Fallback-Name. (defun plq-layer ( / lay) (setq lay (ssg-layer-anlegen "planquadrate" T)) (if (null lay) (progn (setq lay "ZZ_Planquadrate") (ssg-make-layer lay "8" T) ) ) lay ) ;; Alle INSERTs des Planquadrat-Blocks in der Zeichnung loeschen und die ;; Blockdefinition entfernen (PURGE) - macht die Zeichnung frei fuer einen ;; sauberen Neuaufbau bzw. ist die komplette Logik von DELETE_PLANQUADRATE. ;; Rueckgabe: Anzahl geloeschter INSERTs. (defun plq-block-entfernen ( / ss i n) (setq n 0) (if (tblsearch "BLOCK" *plq-blockname*) (progn (setq ss (ssget "X" (list (cons 0 "INSERT") (cons 2 *plq-blockname*)))) (if ss (progn (setq i 0) (while (< i (sslength ss)) (entdel (ssname ss i)) (setq i (1+ i)) (setq n (1+ n)) ) ) ) (command "_-PURGE" "_B" *plq-blockname* "_N") ) ) n ) ;; 1-basierten Index in eine Buchstaben-Bezeichnung wandeln (1=A, 26=Z, ;; 27=AA, ... wie Excel-Spalten) - Gegenstueck zu _index_to_alpha in ;; lib/export_planquadrat.py. (defun plq-index-alpha (n / result rest) (setq result "") (while (> n 0) (setq rest (rem (1- n) 26)) (setq result (strcat (chr (+ 65 rest)) result)) (setq n (/ (- n 1 rest) 26)) ) result ) ;; Label fuer einen 1-basierten Index, alpha-p = T -> Buchstaben, sonst Zahl. (defun plq-label (n alpha-p) (if alpha-p (plq-index-alpha n) (itoa n)) ) ;; Inline-Kommentar (" # ...") von einem Config-Wert abschneiden. Der ;; gemeinsame INI-Parser (ssg-ini-get/ssg-load-ini, ssg_core.lsp) behandelt ;; nur ganze Zeilen ab "#" als Kommentar - die [Planquadrate_*]-Sektionen in ;; cfg/export.cfg nutzen aber INLINE-Kommentare hinter x_description/ ;; y_description (z.B. "alphabetisch # Buchstaben, ..."), analog zu ;; lib/export_blockpatterns.py (configparser mit inline_comment_prefixes). (defun plq-strip-comment (s / pos) (setq pos (vl-string-search "#" s)) (if pos (vl-string-trim " \t" (substr s 1 pos)) (vl-string-trim " \t" s)) ) ;; Zeichnet eine Linie auf dem aktuellen Layer. (defun plq-line (p1 p2) (entmake (list '(0 . "LINE") (cons 10 p1) (cons 11 p2) )) ) ;; Zeichnet einen zentrierten Text an insertPoint. (defun plq-text (str insertPoint hoehe) (entmake (list '(0 . "TEXT") (cons 10 insertPoint) (cons 40 hoehe) (cons 1 str) (cons 50 0.0) '(72 . 1) '(73 . 2) (cons 11 insertPoint) )) ) ;; ============================================================ ;; DRAW_PLANQUADRATE - Raster zeichnen/neu aufbauen ;; ============================================================ (defun c:DRAW_PLANQUADRATE ( / section x-step x-alpha y-step y-alpha ext-min ext-max x-origin y-origin x0 y0 x1 y1 lay hoehe n-x n-y i x y label textabstand lastEnt ss e) (ssg-start "DRAW_PLANQUADRATE" '(("OSMODE"))) (setvar "OSMODE" 0) (if (null *export-cfg*) (export:load-cfg)) (setq section (export:cfg "Planquadrate" "section" "")) (if (or (null section) (= section "")) (princ (ssg-text "plq-keine-konfiguration")) (progn (setq x-step (* 1000.0 (atof (export:cfg section "x_step" "1")))) (setq y-step (* 1000.0 (atof (export:cfg section "y_step" "1")))) (setq x-alpha (wcmatch (strcase (substr (plq-strip-comment (export:cfg section "x_description" "numerisch")) 1 5)) "ALPHA*")) (setq y-alpha (wcmatch (strcase (substr (plq-strip-comment (export:cfg section "y_description" "numerisch")) 1 5)) "ALPHA*")) (if (or (<= x-step 0.0) (<= y-step 0.0)) (princ (ssg-text "plq-ungueltige-schrittweite")) (progn ;; Vorhandenes Raster zuerst entfernen (Block + Definition) - ;; wiederholte Aufrufe erzeugen so keine Dubletten. (plq-block-entfernen) (setq ext-min (getvar "EXTMIN")) (setq ext-max (getvar "EXTMAX")) (setq x-origin (export:cfg "Planquadrate" "x_origin" "")) (setq x-origin (if (and x-origin (/= x-origin "")) (* 1000.0 (atof x-origin)) (car ext-min))) (setq y-origin (export:cfg "Planquadrate" "y_origin" "")) (setq y-origin (if (and y-origin (/= y-origin "")) (* 1000.0 (atof y-origin)) (cadr ext-min))) (setq x0 x-origin) (setq y0 y-origin) ;; Anzahl Spalten/Zeilen: mind. 1, sonst so viele volle Schritte, ;; bis die Zeichnungs-Extents (mind.) abgedeckt sind - AUFGERUNDET, ;; damit x1/y1 exakt auf einem Rasterschritt liegen. Damit endet ;; JEDE senkrechte Linie exakt auf der letzten waagerechten (bei ;; y1) und jede waagerechte exakt auf der letzten senkrechten (bei ;; x1) - das Raster bildet immer ein geschlossenes Rechteck. (setq n-x (max 1 (fix (+ 0.999999 (/ (- (car ext-max) x0) x-step))))) (setq n-y (max 1 (fix (+ 0.999999 (/ (- (cadr ext-max) y0) y-step))))) (setq x1 (+ x0 (* n-x x-step))) (setq y1 (+ y0 (* n-y y-step))) (setq lay (plq-layer)) (setq hoehe (atof (export:cfg "Planquadrate" "text_hoehe_mm" "300"))) (setq textabstand (* hoehe 1.5)) ;; Letztes Entity VOR dem Zeichnen merken, um danach per entnext ;; genau die neu erzeugten Objekte einzusammeln (wie ;; kreisel-make-label/draw-module in KreiselInsert.lsp). (setq lastEnt (entlast)) ;; Senkrechte Linien (konstantes X) + Spalten-Beschriftung unten. (setq i 0) (while (<= i n-x) (setq x (+ x0 (* i x-step))) (plq-line (list x y0 0.0) (list x y1 0.0)) (if (< i n-x) (progn (setq label (plq-label (1+ i) x-alpha)) (plq-text label (list (+ x (/ x-step 2.0)) (- y0 textabstand) 0.0) hoehe) ) ) (setq i (1+ i)) ) ;; Waagerechte Linien (konstantes Y) + Zeilen-Beschriftung links. (setq i 0) (while (<= i n-y) (setq y (+ y0 (* i y-step))) (plq-line (list x0 y 0.0) (list x1 y 0.0)) (if (< i n-y) (progn (setq label (plq-label (1+ i) y-alpha)) (plq-text label (list (- x0 textabstand) (+ y (/ y-step 2.0)) 0.0) hoehe) ) ) (setq i (1+ i)) ) ;; --- Neu erzeugte Entities einsammeln und zu einem Block zusammenfassen --- (setq ss (ssadd)) (if (null lastEnt) (setq e (entnext)) (setq e (entnext lastEnt))) (while e (ssadd e ss) (setq e (entnext e)) ) (if (> (sslength ss) 0) (progn (command "_.-BLOCK" *plq-blockname* (list 0.0 0.0 0.0) ss "") (command "_.INSERT" *plq-blockname* (list 0.0 0.0 0.0) 1 1 0) ) ) (princ (ssg-textf "plq-fertig" (list (itoa n-x) (itoa n-y) lay))) ) ) ) ) (ssg-end) (princ) ) ;; ============================================================ ;; DELETE_PLANQUADRATE - Raster-Block entfernen ;; ============================================================ (defun c:DELETE_PLANQUADRATE ( / n) (ssg-start "DELETE_PLANQUADRATE" nil) (setq n (plq-block-entfernen)) (if (> n 0) (princ (ssg-textf "plq-geloescht" (list (itoa n)))) (princ (ssg-text "plq-nichts-zu-loeschen")) ) (ssg-end) (princ) ) ;; ============================================================ ;; PLANQUADRATE_TOGGLE - "Planquadrate an/aus": zeichnet das Raster, falls ;; noch keines in der Zeichnung existiert, sonst entfernt es das bestehende. ;; ============================================================ (defun c:PLANQUADRATE_TOGGLE ( / vorhanden) (setq vorhanden (and (tblsearch "BLOCK" *plq-blockname*) (ssget "X" (list (cons 0 "INSERT") (cons 2 *plq-blockname*))))) (if vorhanden (c:DELETE_PLANQUADRATE) (c:DRAW_PLANQUADRATE) ) (princ) ) (princ "\n>>> DrawPlanquadrate.lsp geladen. Befehle: DRAW_PLANQUADRATE, DELETE_PLANQUADRATE, PLANQUADRATE_TOGGLE") (princ)