[FIX] Weltposition verpackter Separator_SP-Symbole bei gekippten Ketten

ssg-collect-nested-inserts-rel/csv:sep-proxies-erzeugen nahmen bislang eine
reine Z-Drehung ohne OCS-/Extrusionsrichtung an. Fuer die um den Gefaelle-/
Neigungswinkel gekippte Staustrecke/Separator-Kette (Gefaellestrecke.lsp,
vf_standard.lsp) ist das falsch: die eingebettete Separator_SP-Weltposition
blieb dadurch unabhaengig von der gewaehlten Fahrtrichtung eingefroren.

Fix generalisiert die Rotationskomposition auf volle 3x3-Matrizen (Arbitrary
Axis Algorithm fuer die Extrusion, neue mat3-*-Helfer in ssg_core.lsp statt
vf_core.lsp, da ssg_core immer vor jedem Feature-Modul geladen ist). Fuer
flache Elemente (Extrusion (0 0 1)) reduziert sich das exakt auf die alte
reine Z-Drehung - kein Verhaltensunterschied dort.

Verifiziert per Python/ezdxf-Nachbau des neuen Algorithmus gegen die drei
real gebauten Testzeichnungen (data/gf.dxf, data/gf_north.dxf,
data/gf_south.dxf): liefert jetzt fuer alle drei Fahrtrichtungen exakt die
unabhaengig berechnete Grundwahrheit statt eines eingefrorenen Werts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 12:42:10 +02:00
parent e12a25785f
commit 29b7bf1a10
3 changed files with 220 additions and 80 deletions
+52 -22
View File
@@ -630,9 +630,9 @@
;; Kopie gesetzt werden kann (csv:sep-proxies-zuordnung-setzen). Die ;; Kopie gesetzt werden kann (csv:sep-proxies-zuordnung-setzen). Die
;; proxy-enames dienen ausserdem csv:sep-proxies-loeschen nach dem Export. ;; proxy-enames dienen ausserdem csv:sep-proxies-loeschen nach dem Export.
(defun csv:sep-proxies-erzeugen ( / ms ss-all i ename ed bname nested pt rotation (defun csv:sep-proxies-erzeugen ( / ms ss-all i ename ed bname nested pt rotation
psx psy psz c si rec nested-ent nested-bname extrusion0 R0 psx psy psz rec nested-ent nested-bname
local-pt nested-rot lx ly lz world-pt local-pt R-nested R-final scaled-pt rot-pt world-pt
block-obj proxy-liste) T4 block-obj xform-fehler proxy-liste)
(setq ss-all (ssget "X" (list (cons 0 "INSERT")))) (setq ss-all (ssget "X" (list (cons 0 "INSERT"))))
(if ss-all (if ss-all
(progn (progn
@@ -649,25 +649,43 @@
(if nested (if nested
(progn (progn
(setq pt (cdr (assoc 10 ed))) (setq pt (cdr (assoc 10 ed)))
(if (null (caddr pt)) (setq pt (list (car pt) (cadr pt) 0.0)))
(setq rotation (cond ((cdr (assoc 50 ed))) (0.0))) (setq rotation (cond ((cdr (assoc 50 ed))) (0.0)))
;; Extrusion des Wrapper-INSERTs selbst beruecksichtigen statt
;; reine Z-Drehung anzunehmen - GF_n/VF_n stehen zwar bisher immer
;; flach (Extrusion (0 0 1)), aber mat3-from-normal-rotation
;; reduziert sich dafuer ohnehin exakt auf Rz(rotation), kostet
;; also nichts und macht den Code robust falls sich das aendert.
(setq extrusion0 (cond ((cdr (assoc 210 ed))) ('(0.0 0.0 1.0))))
(setq R0 (mat3-from-normal-rotation extrusion0 rotation))
(setq psx (cond ((cdr (assoc 41 ed))) (1.0))) (setq psx (cond ((cdr (assoc 41 ed))) (1.0)))
(setq psy (cond ((cdr (assoc 42 ed))) (1.0))) (setq psy (cond ((cdr (assoc 42 ed))) (1.0)))
(setq psz (cond ((cdr (assoc 43 ed))) (1.0))) (setq psz (cond ((cdr (assoc 43 ed))) (1.0)))
(setq c (cos rotation) si (sin rotation))
(foreach rec nested (foreach rec nested
(setq nested-ent (nth 0 rec)) (setq nested-ent (nth 0 rec))
(setq local-pt (nth 1 rec)) (setq local-pt (nth 1 rec))
(setq nested-rot (nth 2 rec)) (setq R-nested (nth 2 rec))
(setq nested-bname (cdr (assoc 2 (entget nested-ent)))) (setq nested-bname (cdr (assoc 2 (entget nested-ent))))
(setq lx (* psx (car local-pt)) (setq scaled-pt (list (* psx (car local-pt))
ly (* psy (cadr local-pt)) (* psy (cadr local-pt))
lz (* psz (caddr local-pt))) (* psz (caddr local-pt))))
(setq world-pt (setq rot-pt (mat3-mul-vec3 R0 scaled-pt))
(list (+ (car pt) (- (* lx c) (* ly si))) (setq world-pt (list (+ (car pt) (car rot-pt))
(+ (cadr pt) (+ (* lx si) (* ly c))) (+ (cadr pt) (cadr rot-pt))
(+ (cond ((caddr pt)) (0.0)) lz))) (+ (caddr pt) (caddr rot-pt))))
;; Rotation fuer vla-InsertBlock in RADIANT (ActiveX-Konvention, (setq R-final (mat3-mul-mat3 R0 R-nested))
;; anders als der Grad-Winkel von "command _.INSERT"). ;; Volle 3D-Orientierung statt bisher nur eines Z-Drehwinkels:
;; ein einzelner Skalar-Drehwinkel kann eine Kippung ausserhalb
;; der XY-Ebene (Gefaellestrecke-/VF-Neigung) gar nicht
;; darstellen. Deshalb - wie insert-block-ks-to-ks (vf_core.lsp)
;; - am Ursprung mit Rotation=0 einfuegen und die komplette
;; Lage (Drehung UND Verschiebung) in EINER vla-TransformBy
;; anwenden, statt Rotation als vla-InsertBlock-Parameter.
(setq T4 (vlax-tmatrix
(list (list (car (car R-final)) (cadr (car R-final)) (caddr (car R-final)) (car world-pt))
(list (car (cadr R-final)) (cadr (cadr R-final)) (caddr (cadr R-final)) (cadr world-pt))
(list (car (caddr R-final)) (cadr (caddr R-final)) (caddr (caddr R-final)) (caddr world-pt))
(list 0.0 0.0 0.0 1.0))))
;; Gekapselt, weil hier - anders als beim frueheren festen ;; Gekapselt, weil hier - anders als beim frueheren festen
;; 1.0/1.0/1.0 - die tatsaechlichen Skalierungsfaktoren ;; 1.0/1.0/1.0 - die tatsaechlichen Skalierungsfaktoren
;; durchgereicht werden: ein einzelner Sonderfall (entartete ;; durchgereicht werden: ein einzelner Sonderfall (entartete
@@ -676,17 +694,29 @@
;; eine Kopie ausfallen lassen - mit Meldung, welcher Block. ;; eine Kopie ausfallen lassen - mit Meldung, welcher Block.
(setq block-obj (setq block-obj
(vl-catch-all-apply 'vla-InsertBlock (vl-catch-all-apply 'vla-InsertBlock
(list ms (vlax-3D-point world-pt) nested-bname (list ms (vlax-3D-point '(0.0 0.0 0.0)) nested-bname
(csv:skalierung-oder-eins (* psx (nth 3 rec))) (csv:skalierung-oder-eins (* psx (nth 3 rec)))
(csv:skalierung-oder-eins (* psy (nth 4 rec))) (csv:skalierung-oder-eins (* psy (nth 4 rec)))
(csv:skalierung-oder-eins (* psz (nth 5 rec))) (csv:skalierung-oder-eins (* psz (nth 5 rec)))
(+ rotation nested-rot)))) 0.0)))
(if (vl-catch-all-error-p block-obj) (cond
(princ (ssg-textf "exp-sep-proxy-fehler" ((vl-catch-all-error-p block-obj)
(list nested-bname bname (princ (ssg-textf "exp-sep-proxy-fehler"
(vl-catch-all-error-message block-obj)))) (list nested-bname bname
(setq proxy-liste (vl-catch-all-error-message block-obj)))))
(cons (cons (vlax-vla-object->ename block-obj) ename) proxy-liste)) (t
(setq xform-fehler (vl-catch-all-apply 'vla-TransformBy (list block-obj T4)))
(if (vl-catch-all-error-p xform-fehler)
(progn
(princ (ssg-textf "exp-sep-proxy-fehler"
(list nested-bname bname
(vl-catch-all-error-message xform-fehler))))
(vl-catch-all-apply 'vla-Delete (list block-obj))
)
(setq proxy-liste
(cons (cons (vlax-vla-object->ename block-obj) ename) proxy-liste))
)
)
) )
) )
) )
+159 -22
View File
@@ -201,6 +201,112 @@
) )
;; ------------------------------------------------------------
;; 3x3-VEKTOR-/MATRIXHELFER (allgemein, dependency-frei)
;; ------------------------------------------------------------
;; Hier statt in vf_core.lsp, weil ssg-collect-nested-inserts-rel (weiter
;; unten in diesem Modul) sie ebenfalls braucht und dieses Modul IMMER vor
;; jedem Feature-Modul (inkl. vf_core.lsp) geladen ist - siehe MNL-Ladeliste.
;; vf_core.lsp (insert-block-ks-to-ks/insert-block-mixed-to-ks) nutzt
;; dieselben Definitionen unveraendert weiter.
;; Vektorkreuzprodukt a x b
(defun vec3-cross (a b)
(list (- (* (cadr a)(caddr b)) (* (caddr a)(cadr b)))
(- (* (caddr a)(car b)) (* (car a)(caddr b)))
(- (* (car a)(cadr b)) (* (cadr a)(car b)))))
;; Vektor auf Einheitslaenge normieren
(defun vec3-normalize (v / len)
(setq len (vec-length v))
(if (> len 1e-10)
(list (/ (car v) len) (/ (cadr v) len) (/ (caddr v) len))
'(1.0 0.0 0.0)))
;; 3x3-Rotationsmatrix (Zeilenliste) mal 3D-Vektor
(defun mat3-mul-vec3 (R v / r0 r1 r2)
(setq r0 (car R) r1 (cadr R) r2 (caddr R))
(list (+ (* (car r0)(car v)) (* (cadr r0)(cadr v)) (* (caddr r0)(caddr v)))
(+ (* (car r1)(car v)) (* (cadr r1)(cadr v)) (* (caddr r1)(caddr v)))
(+ (* (car r2)(car v)) (* (cadr r2)(cadr v)) (* (caddr r2)(caddr v)))))
;; Rotationsmatrix R sodass: R*xe=xt, R*ye=yt, R*ze=zt
;; (xt yt zt) = Ziel-Achsen; (xe ye ze) = Quell-Achsen (je normierte Einheitsvektoren)
;; Formel: R = M_target * M_source^T
;; R[i][j] = xt[i]*xe[j] + yt[i]*ye[j] + zt[i]*ze[j]
(defun mat3-from-frames (xt yt zt xe ye ze)
(list
(list (+ (* (car xt)(car xe)) (* (car yt)(car ye)) (* (car zt)(car ze)))
(+ (* (car xt)(cadr xe)) (* (car yt)(cadr ye)) (* (car zt)(cadr ze)))
(+ (* (car xt)(caddr xe)) (* (car yt)(caddr ye)) (* (car zt)(caddr ze))))
(list (+ (* (cadr xt)(car xe)) (* (cadr yt)(car ye)) (* (cadr zt)(car ze)))
(+ (* (cadr xt)(cadr xe)) (* (cadr yt)(cadr ye)) (* (cadr zt)(cadr ze)))
(+ (* (cadr xt)(caddr xe)) (* (cadr yt)(caddr ye)) (* (cadr zt)(caddr ze))))
(list (+ (* (caddr xt)(car xe)) (* (caddr yt)(car ye)) (* (caddr zt)(car ze)))
(+ (* (caddr xt)(cadr xe)) (* (caddr yt)(cadr ye)) (* (caddr zt)(cadr ze)))
(+ (* (caddr xt)(caddr xe)) (* (caddr yt)(caddr ye)) (* (caddr zt)(caddr ze))))))
;; --- 3x3-Matrizenprodukt A*B (beide als Zeilenlisten wie mat3-from-frames) ---
;; Spalten von B einzeln mit A multiplizieren (mat3-mul-vec3), Ergebnis-Matrix
;; aus den 3 Ergebnis-Spalten wieder ueber mat3-from-frames zusammensetzen
;; (mit Einheitsvektoren als Quell-Achsen baut das eine Matrix AUS Spalten -
;; siehe mat3-from-normal-rotation, das denselben Trick nutzt).
(defun mat3-mul-mat3 (A B / b-col0 b-col1 b-col2)
(setq b-col0 (list (caar B) (car (cadr B)) (car (caddr B))))
(setq b-col1 (list (cadar B) (cadr (cadr B)) (cadr (caddr B))))
(setq b-col2 (list (caddar B) (caddr (cadr B)) (caddr (caddr B))))
(mat3-from-frames
(mat3-mul-vec3 A b-col0) (mat3-mul-vec3 A b-col1) (mat3-mul-vec3 A b-col2)
'(1.0 0.0 0.0) '(0.0 1.0 0.0) '(0.0 0.0 1.0))
)
;; --- OCS-Basis (Arbitrary Axis Algorithm) aus einer Extrusionsrichtung ---
;; normal = Extrusionsvektor (DXF-Gruppe 210/220/230, Laenge beliebig).
;; Rueckgabe: (ax ay az) - normierte OCS-Achsen, az = normiertes normal.
;; Standardalgorithmus (Autodesk "Arbitrary Axis Algorithm"): Referenzachse
;; ist Welt-Y, wenn normal nahe der Welt-Z-Achse liegt, sonst Welt-Z - damit
;; bleibt ax*ay*az immer ein wohldefiniertes, rechtshaendiges Dreibein, auch
;; wenn normal selbst (fast) mit der jeweiligen Referenzachse zusammenfaellt.
(defun mat3-ocs-basis (normal / n wy-ref ax ay)
(setq n (vec3-normalize normal))
(setq wy-ref
(if (and (< (abs (car n)) (/ 1.0 64.0)) (< (abs (cadr n)) (/ 1.0 64.0)))
'(0.0 1.0 0.0)
'(0.0 0.0 1.0)))
(setq ax (vec3-normalize (vec3-cross wy-ref n)))
(setq ay (vec3-normalize (vec3-cross n ax)))
(list ax ay n)
)
;; --- OCS-Basis als 3x3-Matrix (Spalten = ax ay az aus mat3-ocs-basis) ---
;; Rechnet einen OCS-lokalen Punkt/Vektor (z.B. die rohe INSERT-Gruppe 10
;; eines gekippten Elements) in echte lokale Koordinaten der Elternebene um:
;; (mat3-mul-vec3 (mat3-ocs-matrix normal) ocs-punkt).
(defun mat3-ocs-matrix (normal / basis)
(setq basis (mat3-ocs-basis normal))
(mat3-from-frames (car basis) (cadr basis) (caddr basis)
'(1.0 0.0 0.0) '(0.0 1.0 0.0) '(0.0 0.0 1.0))
)
;; --- Reine Z-Drehungsmatrix Rz(winkel), winkel in Radiant ---
(defun mat3-rz (winkel / c s)
(setq c (cos winkel) s (sin winkel))
(mat3-from-frames (list c s 0.0) (list (- s) c 0.0) '(0.0 0.0 1.0)
'(1.0 0.0 0.0) '(0.0 1.0 0.0) '(0.0 0.0 1.0))
)
;; --- Volle 3x3-Rotationsmatrix aus Extrusion + Drehwinkel (DXF-Gruppen 210/50) ---
;; normal = Extrusionsvektor, rotation = Drehwinkel in Radiant.
;; = OCS-Basis(normal) * Rz(rotation): erst die eigene Z-Drehung IN der
;; (evtl. gekippten) OCS-Ebene, dann diese Ebene selbst in die Elternebene
;; kippen. Fuer normal=(0 0 1) ist mat3-ocs-matrix die Einheitsmatrix, das
;; Ergebnis reduziert sich also exakt auf Rz(rotation) - fuer bereits flache
;; Elemente aendert sich damit nichts am bisherigen Verhalten.
(defun mat3-from-normal-rotation (normal rotation)
(mat3-mul-mat3 (mat3-ocs-matrix normal) (mat3-rz rotation))
)
;; ------------------------------------------------------------ ;; ------------------------------------------------------------
;; BENUTZER-ABFRAGEN ;; BENUTZER-ABFRAGEN
;; ------------------------------------------------------------ ;; ------------------------------------------------------------
@@ -960,13 +1066,14 @@
;; steckt. ;; steckt.
;; ;;
;; Rueckgabe: Liste von Treffer-Records, oder nil. Ein Record ist ;; Rueckgabe: Liste von Treffer-Records, oder nil. Ein Record ist
;; (ename (x y z) rot-rad sx sy sz) ;; (ename (x y z) R sx sy sz)
;; mit der Platzierung des Treffers RELATIV zur abgefragten Blockdefinition ;; mit der Platzierung des Treffers RELATIV zur abgefragten Blockdefinition
;; bname - ueber alle Verschachtelungsebenen hinweg aufsummiert (Position, ;; bname - ueber alle Verschachtelungsebenen hinweg aufsummiert (Position,
;; Z-Drehung und Skalierung). Der Aufrufer muss also nur noch die Platzierung ;; volle 3D-Rotationsmatrix R und Skalierung). Der Aufrufer muss also nur
;; des top-level INSERT daraufrechnen. Der rohe Einfuegepunkt aus ;; noch die Platzierung des top-level INSERT daraufrechnen. Der rohe
;; (entget ename) ist bei mehr als einer Ebene NICHT verwendbar - er gilt nur ;; Einfuegepunkt aus (entget ename) ist bei mehr als einer Ebene NICHT
;; innerhalb der unmittelbaren Zwischen-Blockdefinition. ;; verwendbar - er gilt nur innerhalb der unmittelbaren Zwischen-
;; Blockdefinition.
;; ;;
;; Kein Selection-Set: die Entities sind nicht Space-resident und damit fuer ;; Kein Selection-Set: die Entities sind nicht Space-resident und damit fuer
;; ssadd nicht sicher verwendbar. Sie bleiben ueber entget normal lesbar ;; ssadd nicht sicher verwendbar. Sie bleiben ueber entget normal lesbar
@@ -974,30 +1081,47 @@
;; eigene Bounding-Box (vla-getboundingbox) liefert fuer sie keine sinnvollen ;; eigene Bounding-Box (vla-getboundingbox) liefert fuer sie keine sinnvollen
;; Weltkoordinaten. ;; Weltkoordinaten.
(defun ssg-collect-nested-inserts (bname pattern) (defun ssg-collect-nested-inserts (bname pattern)
(ssg-collect-nested-inserts-rel bname pattern '(0.0 0.0 0.0) 0.0 1.0 1.0 1.0) (ssg-collect-nested-inserts-rel bname pattern '(0.0 0.0 0.0)
'((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
1.0 1.0 1.0)
) )
;; --- Rekursions-Rumpf mit mitgefuehrter Platzierung --- ;; --- Rekursions-Rumpf mit mitgefuehrter Platzierung ---
;; basis-pt/basis-rot/bsx/bsy/bsz = Platzierung der gerade durchsuchten ;; basis-pt/basis-R/bsx/bsy/bsz = Platzierung der gerade durchsuchten
;; Blockdefinition im Koordinatensystem des URSPRUENGLICH abgefragten Blocks. ;; Blockdefinition im Koordinatensystem des URSPRUENGLICH abgefragten Blocks.
;; Auf jeder Ebene wird der Einfuegepunkt des Sub-INSERT erst mit der ;; Auf jeder Ebene wird der Einfuegepunkt des Sub-INSERT erst mit der
;; Skalierung, dann mit der Drehung der Ebene darueber verrechnet und ;; Skalierung, dann mit der Rotation der Ebene darueber verrechnet und
;; aufaddiert - genau das fehlte frueher: die Rekursion gab die Entities ;; aufaddiert - genau das fehlte frueher: die Rekursion gab die Entities
;; tieferer Ebenen mit ihrer ROH-Position aus der jeweiligen Zwischen- ;; tieferer Ebenen mit ihrer ROH-Position aus der jeweiligen Zwischen-
;; Blockdefinition zurueck. Zwei Separatoren, die in zwei verschieden ;; Blockdefinition zurueck. Zwei Separatoren, die in zwei verschieden
;; platzierten Zwischenbloecken an derselben lokalen Stelle sitzen, landeten ;; platzierten Zwischenbloecken an derselben lokalen Stelle sitzen, landeten
;; dadurch auf exakt derselben Weltposition (und damit beim falschen Carrier). ;; dadurch auf exakt derselben Weltposition (und damit beim falschen Carrier).
;; ;;
;; Modellannahme wie im uebrigen Export (csv:local-to-world): reine ;; basis-R ist eine VOLLE 3x3-Rotationsmatrix (mat3-* oben in diesem Modul),
;; Z-Drehung, keine OCS-/Extrusionsrichtung. Fuer die Wrapper-Ketten ;; keine reine Z-Drehung mehr: ein Sub-INSERT, dessen Extrusionsrichtung
;; VF_n/GF_n/KREISEL_n trifft das zu. ;; (DXF-Gruppe 210) von der Welt-Z-Achse abweicht - z.B. die um den
(defun ssg-collect-nested-inserts-rel (bname pattern basis-pt basis-rot bsx bsy bsz ;; Gefaellewinkel gekippte Staustrecke/Separator-Kette in
;; Gefaellestrecke.lsp/vf_standard.lsp (ssg-rot-matrix-zy, Rz(hz)*Ry(-vert))
;; - hat seinen eigenen Einfuegepunkt (Gruppe 10) NICHT in den gewoehnlichen
;; lokalen XYZ-Koordinaten der Elterndefinition, sondern relativ zu SEINER
;; EIGENEN, gekippten OCS-Ebene (Arbitrary Axis Algorithm). Die fruehere
;; reine Z-Drehung ignorierte das komplett und lieferte fuer gekippte Ketten
;; einen falschen, von der tatsaechlichen Fahrtrichtung unabhaengigen
;; ("eingefrorenen") Weltpunkt. mat3-ocs-matrix wandelt die rohe OCS-lokale
;; Gruppe-10 in echte lokale Koordinaten um, bevor sie mit der Eltern-
;; Rotation weiterverrechnet wird; mat3-from-normal-rotation liefert die
;; volle 3D-Orientierung des Sub-INSERTs selbst (fuer die naechste
;; Rekursionsebene bzw. den Treffer-Record). Fuer Extrusion=(0 0 1) (der
;; Normalfall, z.B. Kreisel/Eckrad) reduziert sich beides exakt auf die alte
;; reine Z-Drehung - unveraendertes Verhalten dort.
(defun ssg-collect-nested-inserts-rel (bname pattern basis-pt basis-R bsx bsy bsz
/ blk-tbl sub-ent sub-ed sub-bname loc-pt / blk-tbl sub-ent sub-ed sub-bname loc-pt
rot sx sy sz c si lx ly lz wx wy wz result) extrusion rot sx sy sz ocs-mat loc-pt-real
scaled-pt rot-pt R-local R-world world-pt
result)
(setq blk-tbl (tblsearch "BLOCK" bname)) (setq blk-tbl (tblsearch "BLOCK" bname))
(if blk-tbl (if blk-tbl
(progn (progn
(setq c (cos basis-rot) si (sin basis-rot))
(setq sub-ent (entnext (cdr (assoc -2 blk-tbl)))) (setq sub-ent (entnext (cdr (assoc -2 blk-tbl))))
(while sub-ent (while sub-ent
(setq sub-ed (entget sub-ent)) (setq sub-ed (entget sub-ent))
@@ -1005,23 +1129,36 @@
(progn (progn
(setq sub-bname (cdr (assoc 2 sub-ed))) (setq sub-bname (cdr (assoc 2 sub-ed)))
(setq loc-pt (cdr (assoc 10 sub-ed))) (setq loc-pt (cdr (assoc 10 sub-ed)))
(if (null (caddr loc-pt))
(setq loc-pt (list (car loc-pt) (cadr loc-pt) 0.0)))
(setq rot (cond ((cdr (assoc 50 sub-ed))) (0.0))) (setq rot (cond ((cdr (assoc 50 sub-ed))) (0.0)))
(setq extrusion (cond ((cdr (assoc 210 sub-ed))) ('(0.0 0.0 1.0))))
(setq sx (cond ((cdr (assoc 41 sub-ed))) (1.0))) (setq sx (cond ((cdr (assoc 41 sub-ed))) (1.0)))
(setq sy (cond ((cdr (assoc 42 sub-ed))) (1.0))) (setq sy (cond ((cdr (assoc 42 sub-ed))) (1.0)))
(setq sz (cond ((cdr (assoc 43 sub-ed))) (1.0))) (setq sz (cond ((cdr (assoc 43 sub-ed))) (1.0)))
(setq lx (* bsx (car loc-pt)) ;; Gruppe-10 ist OCS-lokal (relativ zu diesem Sub-INSERTs EIGENER
ly (* bsy (cadr loc-pt)) ;; Extrusion) - erst in echte lokale Koordinaten der aktuell
lz (* bsz (cond ((caddr loc-pt)) (0.0)))) ;; durchsuchten Blockdefinition umrechnen, dann skalieren, dann
(setq wx (+ (car basis-pt) (- (* lx c) (* ly si))) ;; mit der Eltern-Matrix in Weltkoordinaten drehen/verschieben.
wy (+ (cadr basis-pt) (+ (* lx si) (* ly c))) (setq ocs-mat (mat3-ocs-matrix extrusion))
wz (+ (caddr basis-pt) lz)) (setq loc-pt-real (mat3-mul-vec3 ocs-mat loc-pt))
(setq scaled-pt (list (* bsx (car loc-pt-real))
(* bsy (cadr loc-pt-real))
(* bsz (caddr loc-pt-real))))
(setq rot-pt (mat3-mul-vec3 basis-R scaled-pt))
(setq world-pt (list (+ (car basis-pt) (car rot-pt))
(+ (cadr basis-pt) (cadr rot-pt))
(+ (caddr basis-pt) (caddr rot-pt))))
;; Volle 3D-Orientierung dieses Sub-INSERTs in Weltkoordinaten.
(setq R-local (mat3-from-normal-rotation extrusion rot))
(setq R-world (mat3-mul-mat3 basis-R R-local))
(if (wcmatch sub-bname pattern) (if (wcmatch sub-bname pattern)
(setq result (cons (list sub-ent (list wx wy wz) (+ basis-rot rot) (setq result (cons (list sub-ent world-pt R-world
(* bsx sx) (* bsy sy) (* bsz sz)) (* bsx sx) (* bsy sy) (* bsz sz))
result)) result))
(setq result (append result (setq result (append result
(ssg-collect-nested-inserts-rel sub-bname pattern (ssg-collect-nested-inserts-rel sub-bname pattern
(list wx wy wz) (+ basis-rot rot) world-pt R-world
(* bsx sx) (* bsy sy) (* bsz sz)))) (* bsx sx) (* bsy sy) (* bsz sz))))
) )
) )
+9 -36
View File
@@ -119,42 +119,15 @@
;; ============================================================ ;; ============================================================
;; TEIL 4b: KS-FRAME MATHEMATIK ;; TEIL 4b: KS-FRAME MATHEMATIK
;; ============================================================ ;; ============================================================
;; vec3-cross/vec3-normalize/mat3-mul-vec3/mat3-from-frames (und die
;; Vektorkreuzprodukt a x b ;; OCS-/Extrusions-Helfer mat3-mul-mat3/mat3-ocs-basis/mat3-ocs-matrix/
(defun vec3-cross (a b) ;; mat3-rz/mat3-from-normal-rotation) sitzen in ssg_core.lsp, nicht hier:
(list (- (* (cadr a)(caddr b)) (* (caddr a)(cadr b))) ;; ssg-collect-nested-inserts-rel (Export-Zuordnung verpackter Separatoren)
(- (* (caddr a)(car b)) (* (car a)(caddr b))) ;; braucht sie ebenfalls und ist ein CORE-Modul, das IMMER vor vf_core.lsp
(- (* (car a)(cadr b)) (* (cadr a)(car b))))) ;; geladen ist - vf_core.lsp selbst ist nur ein Feature-Modul (nicht jede
;; Zeichnung laedt VarioFoerderer). Damit beide Seiten dieselbe, einzige
;; Vektor auf Einheitslaenge normieren ;; Definition nutzen, wohnen die allgemeinen Vektor-/Matrix-Helfer im immer
(defun vec3-normalize (v / len) ;; geladenen Core (wie ssg-rot-matrix-zy schon dort wohnt) statt hier.
(setq len (vec-length v))
(if (> len 1e-10)
(list (/ (car v) len) (/ (cadr v) len) (/ (caddr v) len))
'(1.0 0.0 0.0)))
;; 3x3-Rotationsmatrix (Zeilenliste) mal 3D-Vektor
(defun mat3-mul-vec3 (R v / r0 r1 r2)
(setq r0 (car R) r1 (cadr R) r2 (caddr R))
(list (+ (* (car r0)(car v)) (* (cadr r0)(cadr v)) (* (caddr r0)(caddr v)))
(+ (* (car r1)(car v)) (* (cadr r1)(cadr v)) (* (caddr r1)(caddr v)))
(+ (* (car r2)(car v)) (* (cadr r2)(cadr v)) (* (caddr r2)(caddr v)))))
;; Rotationsmatrix R sodass: R*xe=xt, R*ye=yt, R*ze=zt
;; (xt yt zt) = Ziel-Achsen; (xe ye ze) = Quell-Achsen (je normierte Einheitsvektoren)
;; Formel: R = M_target * M_source^T
;; R[i][j] = xt[i]*xe[j] + yt[i]*ye[j] + zt[i]*ze[j]
(defun mat3-from-frames (xt yt zt xe ye ze)
(list
(list (+ (* (car xt)(car xe)) (* (car yt)(car ye)) (* (car zt)(car ze)))
(+ (* (car xt)(cadr xe)) (* (car yt)(cadr ye)) (* (car zt)(cadr ze)))
(+ (* (car xt)(caddr xe)) (* (car yt)(caddr ye)) (* (car zt)(caddr ze))))
(list (+ (* (cadr xt)(car xe)) (* (cadr yt)(car ye)) (* (cadr zt)(car ze)))
(+ (* (cadr xt)(cadr xe)) (* (cadr yt)(cadr ye)) (* (cadr zt)(cadr ze)))
(+ (* (cadr xt)(caddr xe)) (* (cadr yt)(caddr ye)) (* (cadr zt)(caddr ze))))
(list (+ (* (caddr xt)(car xe)) (* (caddr yt)(car ye)) (* (caddr zt)(car ze)))
(+ (* (caddr xt)(cadr xe)) (* (caddr yt)(cadr ye)) (* (caddr zt)(cadr ze)))
(+ (* (caddr xt)(caddr xe)) (* (caddr yt)(caddr ye)) (* (caddr zt)(caddr ze))))))
;; Normierter KS-Rahmen aus rohen KS-Daten (origin x-end y-end z-end) ;; Normierter KS-Rahmen aus rohen KS-Daten (origin x-end y-end z-end)
;; Eingabe: Teilliste aus extract-ks-from-block-raw, z.B. (cadr (assoc "KS_EIN" ks-data)) ;; Eingabe: Teilliste aus extract-ks-from-block-raw, z.B. (cadr (assoc "KS_EIN" ks-data))