Omniflo-Streckenzug-Test + skriptfaehige Aluprofil-Geraden
Neuer Test: 4 Geraden -> 180-Grad-Kurve (4x 45-Grad-Bogen) -> 4 Geraden als lueckenlos verketteter Streckenzug (U-Form). - testdata/omniflo_strecke_tests.json: 12 Elemente mit berechneter, verketteter Platzierung (x, y, drehung, x_ende, y_ende, Bogen-Mittelpunkt) - test_omniflo_strecke.py: Geometrie-Validierung ohne BricsCAD (Struktur, Katalog-Abgleich, Verkettung, Kurvensumme 180 Grad, gemeinsamer Mittelpunkt) - test_omniflo_strecke.lsp: C:TEST_OMNIFLO_STRECKE baut die Strecke auf - alltests.json/README.md: Test registriert und dokumentiert OmniModulInsert.lsp: omni:insert-block in skriptfaehigen Kern omni:make-gerade + omni:read-src-attribs aufgeteilt. Der Kern erzeugt eine Aluprofil-Gerade non-interaktiv aus zwei Punkten (kein getpoint/ssg-start), sodass der Test echte Gerade-Bloecke statt nackter Linien baut. Interaktives Verhalten von omni:insert-block bleibt unveraendert (Vorschau-Text, Laengenpruefung). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+135
-92
@@ -497,24 +497,142 @@
|
||||
;;
|
||||
;; blockname = Profiltyp (z.B. "AP60", "AP110", "APG110")
|
||||
;; laengemax = Maximale Fahrstreckenlaenge in mm
|
||||
;; --- Quell-Attribute einer Aluprofil-.dwg lesen (mit ID-Feld) ---
|
||||
;; blockname = Profiltyp (z.B. "AP60", "AP110", "APG110")
|
||||
;; Rueckgabe: Attribut-Alist (mit angehaengtem leeren "ID"-Feld) oder nil,
|
||||
;; wenn *block-path* fehlt oder die Quell-.dwg keine Attribute hat.
|
||||
(defun omni:read-src-attribs (blockname / srcAttribs)
|
||||
(if (and (boundp '*block-path*) *block-path*)
|
||||
(progn
|
||||
(setq srcAttribs (ssg-attrib-read-dwg (strcat *block-path* blockname ".dwg")))
|
||||
(if (and srcAttribs (not (assoc "ID" srcAttribs)))
|
||||
(setq srcAttribs (append srcAttribs (list (cons "ID" ""))))
|
||||
)
|
||||
)
|
||||
)
|
||||
srcAttribs
|
||||
)
|
||||
|
||||
|
||||
;; --- Aluprofil-Gerade non-interaktiv aus zwei Punkten erzeugen ---
|
||||
;;
|
||||
;; Skriptfaehiger Kern von omni:insert-block: baut aus zwei bekannten
|
||||
;; Punkten (Anfang pt, Ende pt2) den Compound-Block (Linie + ATTDEFs) und
|
||||
;; fuegt ihn ein. Fuehrt KEINE Nutzerabfrage und KEIN ssg-start/ssg-end aus -
|
||||
;; der Aufrufer sichert die Umgebung und setzt OSMODE/ATTREQ/ATTDIA=0.
|
||||
;;
|
||||
;; blockname = Profiltyp (z.B. "AP110")
|
||||
;; pt / pt2 = Anfangs-/Endpunkt (Liste x y [z])
|
||||
;; srcAttribs = Quell-Attribute (Alist) oder nil (dann Block ohne ATTDEFs)
|
||||
;; textHeight / textGap = Textparameter
|
||||
;; textEnt = optionaler, bereits erzeugter Vorschau-Text (Tag 1 = blockname);
|
||||
;; nil -> wird hier erzeugt
|
||||
;; Rueckgabe: Entity-Name des eingefuegten INSERT-Blocks oder nil.
|
||||
(defun omni:make-gerade (blockname pt pt2 srcAttribs textHeight textGap textEnt /
|
||||
laenge laengeStr dx dy angle angleDeg
|
||||
perpX perpY textPt ed lastEnt ss e bname blockEnt
|
||||
attribs attribDefs)
|
||||
(setq laenge (distance (list (car pt) (cadr pt))
|
||||
(list (car pt2) (cadr pt2))))
|
||||
(setq laengeStr (rtos laenge 2 0))
|
||||
(setq dx (- (car pt2) (car pt))
|
||||
dy (- (cadr pt2) (cadr pt)))
|
||||
(setq angle (atan dy dx))
|
||||
(setq angleDeg (* (/ 180.0 pi) angle))
|
||||
|
||||
;; 1. Vorschau-Text erzeugen, falls nicht vom Aufrufer uebergeben
|
||||
(if (null textEnt)
|
||||
(progn
|
||||
(entmake (list '(0 . "TEXT")
|
||||
(cons 8 (getvar "CLAYER"))
|
||||
(cons 10 (list (car pt) (cadr pt)
|
||||
(if (caddr pt) (caddr pt) 0.0)))
|
||||
(cons 40 textHeight)
|
||||
(cons 1 blockname)
|
||||
'(50 . 0.0)))
|
||||
(setq textEnt (entlast))
|
||||
)
|
||||
)
|
||||
(setq lastEnt textEnt)
|
||||
|
||||
;; 2. Compound-Block: Linie bei (0,0)..(laenge,0) + ATTDEFs aus Quell-Attributen
|
||||
(command "_.LINE" (list 0.0 0.0) (list laenge 0.0) "")
|
||||
(setq attribDefs (ssg-attrib-alist-to-defs srcAttribs))
|
||||
(ssg-attrib-make-defs attribDefs 50.0)
|
||||
|
||||
;; Neue Entities einsammeln (alles nach textEnt)
|
||||
(setq ss (ssadd))
|
||||
(setq e (entnext lastEnt))
|
||||
(while e (ssadd e ss) (setq e (entnext e)))
|
||||
|
||||
;; Block mit eindeutigem Zeitstempel-Namen erzeugen
|
||||
(setq bname (strcat blockname "_" (ssg-timestamp)))
|
||||
;; Falls Name schon existiert, Suffix anhaengen
|
||||
(if (tblsearch "BLOCK" bname)
|
||||
(setq bname (strcat bname "_" (itoa (fix (* (getvar "CDATE") 1000000)))))
|
||||
)
|
||||
;; Objektfang aus: sonst kann _.INSERT den Einfuegepunkt pt auf ein Objekt
|
||||
;; umfangen (z.B. den Text bei pt) und die Hoehe verfaelschen.
|
||||
(setvar "OSMODE" 0)
|
||||
(command "_.-BLOCK" bname (list 0.0 0.0 0.0) ss "")
|
||||
|
||||
;; Block einfuegen (ATTREQ/ATTDIA bereits auf 0)
|
||||
(command "_.INSERT" bname pt 1 1 angleDeg)
|
||||
(setq blockEnt (entlast))
|
||||
|
||||
;; 3. Attribute setzen: Quell-Werte + LAENGE/A aktualisieren
|
||||
(setq attribs srcAttribs)
|
||||
(if (assoc "LAENGE" attribs)
|
||||
(setq attribs (subst (cons "LAENGE" laengeStr)
|
||||
(assoc "LAENGE" attribs) attribs))
|
||||
(setq attribs (cons (cons "LAENGE" laengeStr) attribs))
|
||||
)
|
||||
(if (assoc "A" attribs)
|
||||
(setq attribs (subst (cons "A" laengeStr)
|
||||
(assoc "A" attribs) attribs))
|
||||
(setq attribs (cons (cons "A" laengeStr) attribs))
|
||||
)
|
||||
(ssg-attrib-set-on blockEnt attribs)
|
||||
|
||||
;; 4. Text oberhalb der Linie positionieren, um Linienwinkel drehen,
|
||||
;; Inhalt mit Laenge ergaenzen
|
||||
(setq perpX (* (- (sin angle)) textGap)
|
||||
perpY (* (cos angle) textGap))
|
||||
(setq textPt (list (+ (car pt) perpX)
|
||||
(+ (cadr pt) perpY)
|
||||
(if (caddr pt) (caddr pt) 0.0)))
|
||||
(setq ed (entget textEnt))
|
||||
(setq ed (subst (cons 10 textPt) (assoc 10 ed) ed))
|
||||
(if (assoc 50 ed)
|
||||
(setq ed (subst (cons 50 angle) (assoc 50 ed) ed))
|
||||
(setq ed (append ed (list (cons 50 angle))))
|
||||
)
|
||||
(setq ed (subst (cons 1 (strcat blockname " L=" laengeStr))
|
||||
(assoc 1 ed) ed))
|
||||
(entmod ed)
|
||||
(entupd textEnt)
|
||||
|
||||
;; 5. Eindeutige ID zuweisen
|
||||
(if (and blockEnt (atoms-family 1 '("ssg-id-generate")))
|
||||
(ssg-id-generate blockEnt)
|
||||
)
|
||||
|
||||
(princ (ssg-textf "omni-insert-block-eingefuegt" (list bname laengeStr)))
|
||||
blockEnt
|
||||
)
|
||||
|
||||
|
||||
;; Aluprofil-Fahrstrecke interaktiv einfuegen (siehe Ablaufbeschreibung oben).
|
||||
;; Fragt Einfuege- und Endpunkt ab und delegiert die Blockerzeugung an
|
||||
;; omni:make-gerade.
|
||||
(defun omni:insert-block (blockname laengemax /
|
||||
pt pt2 laenge laengeStr
|
||||
dx dy angle angleDeg
|
||||
textEnt textHeight textGap
|
||||
perpX perpY textPt ed
|
||||
lastEnt ss e bname blockEnt
|
||||
srcAttribs attribDefs attribs
|
||||
ok)
|
||||
pt pt2 laenge textEnt textHeight textGap srcAttribs ok)
|
||||
|
||||
(setq textHeight (ssg-cfg-or "omniflo" "text_height" 100.0))
|
||||
(setq textGap (ssg-cfg-or "omniflo" "text_gap" 20.0))
|
||||
|
||||
;; 0. Attribute aus der Quell-.dwg lesen (vor ssg-start, da eigene INSERT/ERASE)
|
||||
(setq srcAttribs (ssg-attrib-read-dwg (strcat *block-path* blockname ".dwg")))
|
||||
;; ID-Attribut hinzufuegen falls noch nicht vorhanden
|
||||
(if (and srcAttribs (not (assoc "ID" srcAttribs)))
|
||||
(setq srcAttribs (append srcAttribs (list (cons "ID" ""))))
|
||||
)
|
||||
(setq srcAttribs (omni:read-src-attribs blockname))
|
||||
(if (null srcAttribs)
|
||||
(progn (princ (ssg-text "omni-insert-keine-attribute")) nil)
|
||||
(progn
|
||||
@@ -533,7 +651,7 @@
|
||||
(setvar "ATTREQ" 0)
|
||||
(setvar "ATTDIA" 0)
|
||||
|
||||
;; 1. Text horizontal am Einfuegepunkt erzeugen
|
||||
;; Vorschau-Text horizontal am Einfuegepunkt (waehrend Endpunktwahl)
|
||||
(entmake (list '(0 . "TEXT")
|
||||
(cons 8 (getvar "CLAYER"))
|
||||
(cons 10 (list (car pt) (cadr pt)
|
||||
@@ -543,13 +661,13 @@
|
||||
'(50 . 0.0)))
|
||||
(setq textEnt (entlast))
|
||||
|
||||
;; 2. Endpunkt fuer Fahrstrecke abfragen (Schleife bei Ueberschreitung)
|
||||
;; Endpunkt fuer Fahrstrecke abfragen (Schleife bei Ueberschreitung)
|
||||
(setq ok nil)
|
||||
(while (not ok)
|
||||
(setq pt2 (getpoint pt (ssg-text "omni-prompt-endpunkt-fahrstrecke")))
|
||||
(if (null pt2)
|
||||
(progn
|
||||
;; Abbruch: Text loeschen
|
||||
;; Abbruch: Vorschau-Text loeschen
|
||||
(command "_.ERASE" textEnt "")
|
||||
(princ (ssg-text "omni-abbruch-omni"))
|
||||
(setq ok T pt nil)
|
||||
@@ -561,83 +679,8 @@
|
||||
(alert (ssg-textf "omni-laenge-ueberschritten"
|
||||
(list (rtos laenge 2 0) (rtos laengemax 2 0))))
|
||||
(progn
|
||||
(setq laengeStr (rtos laenge 2 0))
|
||||
(setq dx (- (car pt2) (car pt))
|
||||
dy (- (cadr pt2) (cadr pt)))
|
||||
(setq angle (atan dy dx))
|
||||
(setq angleDeg (* (/ 180.0 pi) angle))
|
||||
|
||||
;; 3. Compound-Block: Linie bei (0,0) + ATTDEFs aus Quell-Attributen
|
||||
(setq lastEnt textEnt)
|
||||
|
||||
;; Linie von Ursprung bis (laenge, 0)
|
||||
(command "_.LINE" (list 0.0 0.0) (list laenge 0.0) "")
|
||||
|
||||
;; ATTDEFs aus Quell-Attributen erzeugen
|
||||
(setq attribDefs (ssg-attrib-alist-to-defs srcAttribs))
|
||||
(ssg-attrib-make-defs attribDefs 50.0)
|
||||
|
||||
;; Neue Entities einsammeln (alles nach textEnt)
|
||||
(setq ss (ssadd))
|
||||
(setq e (entnext lastEnt))
|
||||
(while e (ssadd e ss) (setq e (entnext e)))
|
||||
|
||||
;; Block mit eindeutigem Zeitstempel-Namen erzeugen
|
||||
(setq bname (strcat blockname "_" (ssg-timestamp)))
|
||||
;; Falls Name schon existiert, Suffix anhaengen
|
||||
(if (tblsearch "BLOCK" bname)
|
||||
(setq bname (strcat bname "_" (itoa (fix (* (getvar "CDATE") 1000000)))))
|
||||
)
|
||||
;; Objektfang aus: sonst kann _.INSERT den Einfuegepunkt pt
|
||||
;; auf ein Objekt umfangen (z.B. den Text bei pt) und die
|
||||
;; Hoehe verfaelschen. OSMODE via ssg-start gesichert.
|
||||
(setvar "OSMODE" 0)
|
||||
(command "_.-BLOCK" bname (list 0.0 0.0 0.0) ss "")
|
||||
|
||||
;; Block einfuegen (ATTREQ/ATTDIA bereits auf 0)
|
||||
(command "_.INSERT" bname pt 1 1 angleDeg)
|
||||
|
||||
(setq blockEnt (entlast))
|
||||
|
||||
;; 4. Attribute setzen: Quell-Werte + LAENGE/A aktualisieren
|
||||
(setq attribs srcAttribs)
|
||||
(if (assoc "LAENGE" attribs)
|
||||
(setq attribs (subst (cons "LAENGE" laengeStr)
|
||||
(assoc "LAENGE" attribs) attribs))
|
||||
(setq attribs (cons (cons "LAENGE" laengeStr) attribs))
|
||||
)
|
||||
(if (assoc "A" attribs)
|
||||
(setq attribs (subst (cons "A" laengeStr)
|
||||
(assoc "A" attribs) attribs))
|
||||
(setq attribs (cons (cons "A" laengeStr) attribs))
|
||||
)
|
||||
(ssg-attrib-set-on blockEnt attribs)
|
||||
|
||||
;; 5. Text aktualisieren: oberhalb der Linie positionieren,
|
||||
;; um Linienwinkel drehen, Inhalt mit Laenge ergaenzen
|
||||
(setq perpX (* (- (sin angle)) textGap)
|
||||
perpY (* (cos angle) textGap))
|
||||
(setq textPt (list (+ (car pt) perpX)
|
||||
(+ (cadr pt) perpY)
|
||||
(if (caddr pt) (caddr pt) 0.0)))
|
||||
|
||||
(setq ed (entget textEnt))
|
||||
(setq ed (subst (cons 10 textPt) (assoc 10 ed) ed))
|
||||
(if (assoc 50 ed)
|
||||
(setq ed (subst (cons 50 angle) (assoc 50 ed) ed))
|
||||
(setq ed (append ed (list (cons 50 angle))))
|
||||
)
|
||||
(setq ed (subst (cons 1 (strcat blockname " L=" laengeStr))
|
||||
(assoc 1 ed) ed))
|
||||
(entmod ed)
|
||||
(entupd textEnt)
|
||||
|
||||
;; Eindeutige ID zuweisen
|
||||
(if (and blockEnt (atoms-family 1 '("ssg-id-generate")))
|
||||
(ssg-id-generate blockEnt)
|
||||
)
|
||||
|
||||
(princ (ssg-textf "omni-insert-block-eingefuegt" (list bname laengeStr)))
|
||||
(omni:make-gerade blockname pt pt2 srcAttribs
|
||||
textHeight textGap textEnt)
|
||||
(setq ok T)
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user