363 lines
15 KiB
Common Lisp
363 lines
15 KiB
Common Lisp
;; ============================================================
|
|
;; 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: aus den EXPORTIERTEN Bloecken (dieselbe Blockmenge, die
|
|
;; csv:collect-export-blocks in export.lsp fuer EXPORTCSV sammelt - siehe
|
|
;; plq-export-bbox), NICHT die Zeichnungs-Extents (EXTMIN/EXTMAX). Ursprung
|
|
;; (Index 1) UND obere Grenze kommen BEIDE aus der tatsaechlichen Bounding-Box
|
|
;; jedes Blocks (csv:get-bbox, dieselbe wie bbox_columns()/
|
|
;; planquadrat_column()/_bbox_min() in lib/export_csv.py bzw.
|
|
;; lib/export_planquadrat.py), NICHT aus dem reinen Einfuegepunkt: bei einem
|
|
;; gedrehten oder exzentrisch eingefuegten Block (z.B. ein um 90 Grad
|
|
;; gedrehter Kreisel, dessen Insertpunkt an einem Rand statt der Mitte liegt)
|
|
;; kann das Bounding-Box-Zentrum weit vom Einfuegepunkt abweichen - Ursprung
|
|
;; und Zellzuordnung MUESSEN auf derselben Referenz beruhen, sonst driften sie
|
|
;; auseinander (realer Bug: ein Kreisel landete dadurch in der CSV-Spalte
|
|
;; "F/3-G/13" statt der laut Zeichnung korrekten Spalte A). Reine
|
|
;; Hilfsgeometrie (Kreisel-Umfahrungsboegen als eigene Linien, Texte, das
|
|
;; Planquadrat-Raster selbst) zaehlt zu EXTMIN/EXTMAX, gehoert aber zu keinem
|
|
;; Export-Block - das BricsCAD-Raster muss daher auf derselben Blockmenge wie
|
|
;; der CSV-Export rechnen, sonst landet ein Bauteil im CSV in einer anderen
|
|
;; Spalte/Zeile als im Raster in der Zeichnung.
|
|
;; Der Bereich wird 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) und ueberschreiben den automatisch ermittelten
|
|
;; Ursprung. Fallback auf EXTMIN/EXTMAX, falls keine exportfaehigen Bloecke in
|
|
;; der Zeichnung stehen.
|
|
;;
|
|
;; 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))
|
|
)
|
|
|
|
;; Ursprung + Ausdehnung aus den EXPORTIERTEN Bloecken ermitteln - dieselbe
|
|
;; Blockmenge, die csv:collect-export-blocks (export.lsp) fuer EXPORTCSV
|
|
;; sammelt. Der reine EXTMIN/EXTMAX der Zeichnung (alle Entities, auch
|
|
;; Hilfsgeometrie wie Kreisel-Umfahrungsboegen) weicht davon ab und fuehrte zu
|
|
;; einem im BricsCAD-Raster verschobenen Planquadrat gegenueber der CSV-Spalte
|
|
;; - siehe cfg/export.cfg [Planquadrate] und den Hinweis oben in der
|
|
;; Moduldoku. Sowohl Ursprung als auch obere Grenze kommen aus der
|
|
;; tatsaechlichen Bounding-Box (csv:get-bbox, dieselbe wie
|
|
;; bbox_columns()/planquadrat_column()/_bbox_min() in lib/export_csv.py bzw.
|
|
;; lib/export_planquadrat.py), NICHT aus dem reinen Einfuegepunkt: bei einem
|
|
;; gedrehten oder exzentrisch eingefuegten Block (z.B. ein um 90 Grad
|
|
;; gedrehter Kreisel, dessen Insertpunkt an einem Rand statt der Mitte liegt)
|
|
;; kann das BBox-Zentrum weit vom Einfuegepunkt abweichen - Ursprung und
|
|
;; Zellzuordnung MUESSEN auf derselben Referenz beruhen, sonst driften sie
|
|
;; auseinander (genau der Bug, der zur Einfuehrung von plq-export-bbox
|
|
;; fuehrte). Fallback auf den Einfuegepunkt (Gruppencode 10) nur, wenn
|
|
;; csv:get-bbox fuer einen Block scheitert (z.B. auf eingefrorenem Layer).
|
|
;; Rueckgabe: Liste (xmin ymin xmax ymax) oder nil, wenn keine Bloecke.
|
|
(defun plq-export-bbox ( / ss i ename ed pt bbox xmin ymin xmax ymax)
|
|
(setq ss (csv:collect-export-blocks))
|
|
(if ss
|
|
(progn
|
|
(setq i 0)
|
|
(while (setq ename (ssname ss i))
|
|
(setq ed (entget ename))
|
|
(setq pt (cdr (assoc 10 ed)))
|
|
(setq bbox (csv:get-bbox ename))
|
|
(if bbox
|
|
(progn
|
|
(setq xmin (if xmin (min xmin (- (nth 0 bbox) (/ (nth 3 bbox) 2.0)))
|
|
(- (nth 0 bbox) (/ (nth 3 bbox) 2.0))))
|
|
(setq ymin (if ymin (min ymin (- (nth 1 bbox) (/ (nth 4 bbox) 2.0)))
|
|
(- (nth 1 bbox) (/ (nth 4 bbox) 2.0))))
|
|
(setq xmax (if xmax (max xmax (+ (nth 0 bbox) (/ (nth 3 bbox) 2.0)))
|
|
(+ (nth 0 bbox) (/ (nth 3 bbox) 2.0))))
|
|
(setq ymax (if ymax (max ymax (+ (nth 1 bbox) (/ (nth 4 bbox) 2.0)))
|
|
(+ (nth 1 bbox) (/ (nth 4 bbox) 2.0))))
|
|
)
|
|
(if pt
|
|
(progn
|
|
(setq xmin (if xmin (min xmin (car pt)) (car pt)))
|
|
(setq ymin (if ymin (min ymin (cadr pt)) (cadr pt)))
|
|
(setq xmax (if xmax (max xmax (car pt)) (car pt)))
|
|
(setq ymax (if ymax (max ymax (cadr pt)) (cadr pt)))
|
|
)
|
|
)
|
|
)
|
|
(setq i (1+ i))
|
|
)
|
|
)
|
|
)
|
|
(if xmin (list xmin ymin xmax ymax))
|
|
)
|
|
|
|
;; 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 bbox 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 UND ein alter
|
|
;; Planquadrat-Block verfaelscht nicht die Bloecke-BBox unten
|
|
;; (Raster-Linien/-Texte zaehlen ohnehin nicht zu den Export-
|
|
;; Blockmustern, aber so ist es unabhaengig davon sauber).
|
|
(plq-block-entfernen)
|
|
|
|
;; Referenzbereich: dieselbe Blockmenge wie EXPORTCSV
|
|
;; (csv:collect-export-blocks, export.lsp) - siehe plq-export-bbox.
|
|
;; Fallback auf die Zeichnungs-Extents (EXTMIN/EXTMAX), falls keine
|
|
;; exportfaehigen Bloecke in der Zeichnung stehen.
|
|
(setq bbox (plq-export-bbox))
|
|
(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))
|
|
(if bbox (nth 0 bbox) (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))
|
|
(if bbox (nth 1 bbox) (cadr ext-min))
|
|
))
|
|
|
|
(setq x0 x-origin)
|
|
(setq y0 y-origin)
|
|
|
|
;; Anzahl Spalten/Zeilen: mind. 1, sonst so viele volle Schritte,
|
|
;; bis der Referenzbereich (mind.) abgedeckt ist - 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 (/ (- (if bbox (nth 2 bbox) (car ext-max)) x0) x-step)))))
|
|
(setq n-y (max 1 (fix (+ 0.999999 (/ (- (if bbox (nth 3 bbox) (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)
|