Fix Weltposition/K1-K4 fuer top-level Bloecke mit gekippter Extrusion

csv:block-to-json las Gruppe-10/-50 eines exportierten Blocks direkt als
flache Welt-x/y + Z-Drehwinkel. Ein top-level Separator-Proxy, der ueber
ssg-collect-nested-inserts aus dem geneigten ("Auf") Abschnitt einer
VF-/GF-Kette neu zusammengesetzt wird (csv:sep-proxies-erzeugen), kann
dabei selbst eine echt gekippte Extrusion (Gruppe 210) tragen - Gruppe-10
ist dann OCS-lokal, nicht Welt. Dadurch landeten "x"/"y"/"z" und darueber
K1/K2 (csv:get-k-kos-strings) an einem falschen, am Vorzeichen gespiegelten
Weltpunkt (beobachtet: Separator :4/6/8/10/12 in HundM05, K1 exakt am
Vorzeichen von X/Y gespiegelt weit ausserhalb der eigenen Boundingbox -
deshalb kein K-Kreuz in sps_skel/HundM05_bbs.svg trotz gefuelltem K1 in
der CSV).

csv:block-to-json wandelt pt jetzt erst per Arbitrary Axis Algorithm
(mat3-ocs-matrix) in echte Weltkoordinaten um und reicht die volle
3x3-Orientierung (mat3-from-normal-rotation) statt eines Z-Drehwinkels an
csv:get-k-kos-strings/csv:local-to-world weiter. csv:local-to-world nimmt
entsprechend eine Matrix statt eines Winkels; csv:vfgf-k-kos-strings ruft
es weiterhin mit reiner Rz-Matrix (VF_n/GF_n-Wrapper stehen an ihrem
top-level INSERT dokumentiert immer flach). Fuer Extrusion=(0 0 1) (der
Normalfall) reduziert sich alles exakt auf das bisherige Verhalten.
This commit is contained in:
Samer Ayadi
2026-09-18 10:25:19 +02:00
parent 923af4335a
commit d4260acb45
+59 -25
View File
@@ -297,28 +297,35 @@
) )
;; --- Lokalen Punkt (relativ zum Block-Ursprung) unter Beruecksichtigung der ;; --- Lokalen Punkt (relativ zum Block-Ursprung) unter Beruecksichtigung der
;; Eltern-Rotation (reine Z-Drehung um den Einfuegepunkt) in Weltkoordinaten ;; VOLLEN 3D-Orientierung des Elternblocks in Weltkoordinaten umrechnen ---
;; umrechnen. Rueckgabe: (x y z) --- ;; parent-R = volle 3x3-Rotationsmatrix (mat3-* in ssg_core.lsp), nicht nur
(defun csv:local-to-world (parent-pt parent-rot-rad local-pt / c s lx ly lz pz) ;; ein Z-Drehwinkel: ein Elternblock kann selbst eine gekippte Extrusion
(setq c (cos parent-rot-rad) s (sin parent-rot-rad)) ;; tragen (z.B. ein Separator-Proxy, der aus dem geneigten Abschnitt einer
(setq lx (car local-pt) ly (cadr local-pt)) ;; VF-/GF-Kette neu zusammengesetzt wurde, siehe csv:block-to-json) - eine
;; reine Z-Drehung wuerde dessen Sub-Koordinatensysteme (K1-K4/KS_EIN/
;; KS_AUS) an einen falschen, teils gespiegelten Weltpunkt legen. Fuer einen
;; flachen Elternblock (Extrusion (0 0 1)) ist parent-R = Rz(rotation) und
;; das Ergebnis identisch zur frueheren reinen Z-Drehung. Rueckgabe: (x y z).
(defun csv:local-to-world (parent-pt parent-R local-pt / lz pz rot-pt)
(setq lz (if (caddr local-pt) (caddr local-pt) 0.0)) (setq lz (if (caddr local-pt) (caddr local-pt) 0.0))
(setq pz (if (caddr parent-pt) (caddr parent-pt) 0.0)) (setq pz (if (caddr parent-pt) (caddr parent-pt) 0.0))
(setq rot-pt (mat3-mul-vec3 parent-R (list (car local-pt) (cadr local-pt) lz)))
(list (list
(+ (car parent-pt) (- (* lx c) (* ly s))) (+ (car parent-pt) (car rot-pt))
(+ (cadr parent-pt) (+ (* lx s) (* ly c))) (+ (cadr parent-pt) (cadr rot-pt))
(+ pz lz) (+ pz (caddr rot-pt))
) )
) )
;; --- K1-K4-Koordinatensysteme eines Blocks als Positions-Strings lesen --- ;; --- K1-K4-Koordinatensysteme eines Blocks als Positions-Strings lesen ---
;; ename = Entity-Name des platzierten INSERT (Omniflo Bogen/Weiche/Gerade). ;; ename = Entity-Name des platzierten INSERT (Omniflo Bogen/Weiche/Gerade).
;; pt/rot-rad = bereits ermittelte Welt-Position/-Rotation (radiant) des ;; pt/parent-R = bereits ermittelte Welt-Position/volle 3x3-Orientierung des
;; Eltern-INSERT (siehe csv:block-to-json), keine erneute Abfrage. ;; Eltern-INSERT (siehe csv:block-to-json), keine erneute Abfrage.
;; Sucht in der Block-DEFINITION (wie omni:get-block-hoehe) nach direkten ;; Sucht in der Block-DEFINITION (wie omni:get-block-hoehe) nach direkten
;; Sub-INSERTs "K1".."K4" und rechnet deren lokale Position ueber die ;; Sub-INSERTs "K1".."K4" und rechnet deren lokale Position ueber die volle
;; Eltern-Rotation (reine Z-Drehung) in Weltkoordinaten um. Es wird nur die ;; Eltern-Orientierung in Weltkoordinaten um (csv:local-to-world). Es wird
;; POSITION kodiert (12-Zeichen-String, csv:trans-encode) - keine Rotation. ;; nur die POSITION kodiert (12-Zeichen-String, csv:trans-encode) - keine
;; Rotation.
;; Zusaetzlich werden Strecken-Koordinatensysteme KS_EIN->K1 und KS_AUS->K2 ;; Zusaetzlich werden Strecken-Koordinatensysteme KS_EIN->K1 und KS_AUS->K2
;; (inkl. der KSYS_-Varianten, siehe ks-normalize-name in vf_core.lsp) gemappt, ;; (inkl. der KSYS_-Varianten, siehe ks-normalize-name in vf_core.lsp) gemappt,
;; sofern kein echter K1/K2 am Block vorhanden ist (echte K-Bloecke haben ;; sofern kein echter K1/K2 am Block vorhanden ist (echte K-Bloecke haben
@@ -336,8 +343,16 @@
;; Umrechnung landete K2 tief unterhalb statt oberhalb des Elements (realer ;; Umrechnung landete K2 tief unterhalb statt oberhalb des Elements (realer
;; Bug, sichtbar in der Materialfluss-Draufsicht sps_skel/HundM05_bbs.svg). ;; Bug, sichtbar in der Materialfluss-Draufsicht sps_skel/HundM05_bbs.svg).
;; Fuer Extrusion=(0 0 1) (Normalfall, z.B. KS_EIN) reduziert sich das exakt ;; Fuer Extrusion=(0 0 1) (Normalfall, z.B. KS_EIN) reduziert sich das exakt
;; auf die alte reine Uebernahme - unveraendertes Verhalten dort. ;; auf die alte reine Uebernahme - unveraendertes Verhalten dort. Denselben
(defun csv:get-k-kos-strings (ename pt rot-rad / ed bname blk-tbl sub-ent sub-ed ;; Grund hat parent-R als VOLLE Matrix statt eines Z-Drehwinkels: ein
;; Elternblock (z.B. ein Separator-Proxy, ueber ssg-collect-nested-inserts
;; aus dem geneigten Abschnitt einer VF-/GF-Kette neu zusammengesetzt) kann
;; selbst eine gekippte Extrusion tragen - eine reine Z-Drehung des Eltern-
;; INSERT legte dessen K1/K2 dann an einen falschen, teils gespiegelten
;; Weltpunkt (realer Bug: K1 landete beim Vorzeichen von X/Y gespiegelt weit
;; ausserhalb der eigenen Boundingbox, sichtbar als fehlendes K-Kreuz in
;; sps_skel/HundM05_bbs.svg trotz gefuelltem K1 in der CSV).
(defun csv:get-k-kos-strings (ename pt parent-R / ed bname blk-tbl sub-ent sub-ed
sub-bname sub-pt sub-extrusion sub-pt-real world-pt sub-bname sub-pt sub-extrusion sub-pt-real world-pt
target is-real result) target is-real result)
(setq ed (entget ename)) (setq ed (entget ename))
@@ -374,7 +389,7 @@
(setq sub-pt (list (car sub-pt) (cadr sub-pt) 0.0))) (setq sub-pt (list (car sub-pt) (cadr sub-pt) 0.0)))
(setq sub-extrusion (cond ((cdr (assoc 210 sub-ed))) ('(0.0 0.0 1.0)))) (setq sub-extrusion (cond ((cdr (assoc 210 sub-ed))) ('(0.0 0.0 1.0))))
(setq sub-pt-real (mat3-mul-vec3 (mat3-ocs-matrix sub-extrusion) sub-pt)) (setq sub-pt-real (mat3-mul-vec3 (mat3-ocs-matrix sub-extrusion) sub-pt))
(setq world-pt (csv:local-to-world pt rot-rad sub-pt-real)) (setq world-pt (csv:local-to-world pt parent-R sub-pt-real))
(setq result (cons (setq result (cons
(cons target (cons target
(csv:trans-encode (csv:trans-encode
@@ -505,14 +520,17 @@
(setq ed (entget ename)) (setq ed (entget ename))
(setq bname (cdr (assoc 2 ed))) (setq bname (cdr (assoc 2 ed)))
(setq result nil) (setq result nil)
;; Beide Enden im Wrapper-Frame holen und in Weltkoordinaten (reine ;; Beide Enden im Wrapper-Frame holen und in Weltkoordinaten umrechnen.
;; Z-Drehung) umrechnen. AS traegt das KS_EIN, ES das KS_AUS - jeweils aus ;; VF_n/GF_n-Wrapper stehen an ihrem eigenen top-level INSERT immer flach
;; dem RICHTIGEN Element (csv:vfgf-ks-loc; beide Elemente fuehren beide ;; (Extrusion (0 0 1) - siehe csv:sep-proxies-erzeugen), darum genuegt hier
;; KS-Typen). ;; weiterhin die reine Z-Drehungsmatrix (mat3-rz) statt der vollen
;; Elternorientierung, die csv:get-k-kos-strings inzwischen braucht (siehe
;; dort). AS traegt das KS_EIN, ES das KS_AUS - jeweils aus dem RICHTIGEN
;; Element (csv:vfgf-ks-loc; beide Elemente fuehren beide KS-Typen).
(setq as-loc (csv:vfgf-ks-loc bname "AS_ELEMENT*" "KS_EIN,KSYS_EIN")) (setq as-loc (csv:vfgf-ks-loc bname "AS_ELEMENT*" "KS_EIN,KSYS_EIN"))
(setq es-loc (csv:vfgf-ks-loc bname "ES_ELEMENT*" "KS_AUS,KSYS_AUS")) (setq es-loc (csv:vfgf-ks-loc bname "ES_ELEMENT*" "KS_AUS,KSYS_AUS"))
(if as-loc (setq as-world (csv:local-to-world pt rot-rad as-loc))) (if as-loc (setq as-world (csv:local-to-world pt (mat3-rz rot-rad) as-loc)))
(if es-loc (setq es-world (csv:local-to-world pt rot-rad es-loc))) (if es-loc (setq es-world (csv:local-to-world pt (mat3-rz rot-rad) es-loc)))
;; Eingang/Ausgang festlegen (siehe Richtung im Kopfkommentar). ;; Eingang/Ausgang festlegen (siehe Richtung im Kopfkommentar).
(cond (cond
;; GF: Richtung ueber die Hoehe - hoeheres Z = Eingang, tieferes Z = Ausgang. ;; GF: Richtung ueber die Hoehe - hoeheres Z = Eingang, tieferes Z = Ausgang.
@@ -631,7 +649,8 @@
;; "k1".."k4" (KOS-Strings der Koordinatensysteme im Block, siehe ;; "k1".."k4" (KOS-Strings der Koordinatensysteme im Block, siehe
;; csv:get-k-kos-strings) werden immer geschrieben, unabhaengig von ;; csv:get-k-kos-strings) werden immer geschrieben, unabhaengig von
;; include-bbox -- Kodierung ueber csv:kos-encode (siehe dort). ;; include-bbox -- Kodierung ueber csv:kos-encode (siehe dort).
(defun csv:block-to-json (ename include-bbox / ed blk-name layer pt rotation handle attribs bbox bbox-json (defun csv:block-to-json (ename include-bbox / ed blk-name layer pt rotation extrusion R-world
handle attribs bbox bbox-json
insert-quat insert-kos k-list warnung-json warnung-eintrag insert-quat insert-kos k-list warnung-json warnung-eintrag
zuordnung-fix-json zuordnung-fix-eintrag sepliste-json sepliste-app sepliste zuordnung-fix-json zuordnung-fix-eintrag sepliste-json sepliste-app sepliste
sepliste-teile sepliste-first) sepliste-teile sepliste-first)
@@ -642,12 +661,27 @@
(setq rotation (cdr (assoc 50 ed))) (setq rotation (cdr (assoc 50 ed)))
(setq handle (cdr (assoc 5 ed))) (setq handle (cdr (assoc 5 ed)))
(if (null rotation) (setq rotation 0.0)) (if (null rotation) (setq rotation 0.0))
(if (null (caddr pt)) (setq pt (list (car pt) (cadr pt) 0.0)))
;; Gruppe 10 ist OCS-lokal zur EIGENEN Extrusion dieses INSERT (Gruppe
;; 210) - fuer die allermeisten Bloecke (0 0 1) = Welt, aber ein Separator-
;; Proxy, der ueber ssg-collect-nested-inserts aus dem geneigten Abschnitt
;; einer VF-/GF-Kette neu zusammengesetzt wurde (csv:sep-proxies-erzeugen),
;; kann eine echt gekippte Extrusion tragen. Erst in echte Weltkoordinaten/
;; -orientierung umrechnen (Arbitrary Axis Algorithm, ssg_core.lsp), bevor
;; irgendetwas darauf aufbaut - sonst zeigt "x"/"y"/"z" (und darueber K1-K4,
;; siehe csv:get-k-kos-strings) einen falschen, teils spiegelverkehrten
;; Weltpunkt (realer Bug: Separator :4/6/8/10/12 in HundM05, K1 landete am
;; Vorzeichen gespiegelt weit ausserhalb der eigenen Boundingbox). Fuer
;; Extrusion=(0 0 1) reduziert sich das exakt auf die alte Uebernahme.
(setq extrusion (cond ((cdr (assoc 210 ed))) ('(0.0 0.0 1.0))))
(setq pt (mat3-mul-vec3 (mat3-ocs-matrix extrusion) pt))
(setq R-world (mat3-from-normal-rotation extrusion rotation))
(setq attribs (csv:read-attribs ename)) (setq attribs (csv:read-attribs ename))
(setq insert-quat (csv:z-angle-to-quat (* (/ rotation pi) 180.0))) (setq insert-quat (csv:z-angle-to-quat (* (/ rotation pi) 180.0)))
(setq insert-kos (csv:kos-encode (setq insert-kos (csv:kos-encode
(car pt) (cadr pt) (if (caddr pt) (caddr pt) 0.0) (car pt) (cadr pt) (if (caddr pt) (caddr pt) 0.0)
(nth 0 insert-quat) (nth 1 insert-quat) (nth 2 insert-quat) (nth 3 insert-quat))) (nth 0 insert-quat) (nth 1 insert-quat) (nth 2 insert-quat) (nth 3 insert-quat)))
(setq k-list (csv:get-k-kos-strings ename pt rotation)) (setq k-list (csv:get-k-kos-strings ename pt R-world))
;; Omniflo-Geraden fuehren keine echten K-Bloecke - K1/K2 aus der Geometrie ;; Omniflo-Geraden fuehren keine echten K-Bloecke - K1/K2 aus der Geometrie
;; (Anfang/Ende ueber Laenge + Rotation) synthetisieren, damit sie im Export ;; (Anfang/Ende ueber Laenge + Rotation) synthetisieren, damit sie im Export
;; wie echte Anschluss-Koordinatensysteme erscheinen und in der Nachbar- ;; wie echte Anschluss-Koordinatensysteme erscheinen und in der Nachbar-