From d4260acb458d7b3ecc3efaf6f4a3b8e8ef0d006d Mon Sep 17 00:00:00 2001 From: Samer Ayadi Date: Fri, 18 Sep 2026 10:25:19 +0200 Subject: [PATCH] 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. --- Lisp/export.lsp | 84 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/Lisp/export.lsp b/Lisp/export.lsp index 0cae115..eed4dce 100644 --- a/Lisp/export.lsp +++ b/Lisp/export.lsp @@ -297,28 +297,35 @@ ) ;; --- Lokalen Punkt (relativ zum Block-Ursprung) unter Beruecksichtigung der -;; Eltern-Rotation (reine Z-Drehung um den Einfuegepunkt) in Weltkoordinaten -;; umrechnen. Rueckgabe: (x y z) --- -(defun csv:local-to-world (parent-pt parent-rot-rad local-pt / c s lx ly lz pz) - (setq c (cos parent-rot-rad) s (sin parent-rot-rad)) - (setq lx (car local-pt) ly (cadr local-pt)) +;; VOLLEN 3D-Orientierung des Elternblocks in Weltkoordinaten umrechnen --- +;; parent-R = volle 3x3-Rotationsmatrix (mat3-* in ssg_core.lsp), nicht nur +;; ein Z-Drehwinkel: ein Elternblock kann selbst eine gekippte Extrusion +;; tragen (z.B. ein Separator-Proxy, der aus dem geneigten Abschnitt einer +;; 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 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 - (+ (car parent-pt) (- (* lx c) (* ly s))) - (+ (cadr parent-pt) (+ (* lx s) (* ly c))) - (+ pz lz) + (+ (car parent-pt) (car rot-pt)) + (+ (cadr parent-pt) (cadr rot-pt)) + (+ pz (caddr rot-pt)) ) ) ;; --- K1-K4-Koordinatensysteme eines Blocks als Positions-Strings lesen --- -;; ename = Entity-Name des platzierten INSERT (Omniflo Bogen/Weiche/Gerade). -;; pt/rot-rad = bereits ermittelte Welt-Position/-Rotation (radiant) des -;; Eltern-INSERT (siehe csv:block-to-json), keine erneute Abfrage. +;; ename = Entity-Name des platzierten INSERT (Omniflo Bogen/Weiche/Gerade). +;; pt/parent-R = bereits ermittelte Welt-Position/volle 3x3-Orientierung des +;; Eltern-INSERT (siehe csv:block-to-json), keine erneute Abfrage. ;; Sucht in der Block-DEFINITION (wie omni:get-block-hoehe) nach direkten -;; Sub-INSERTs "K1".."K4" und rechnet deren lokale Position ueber die -;; Eltern-Rotation (reine Z-Drehung) in Weltkoordinaten um. Es wird nur die -;; POSITION kodiert (12-Zeichen-String, csv:trans-encode) - keine Rotation. +;; Sub-INSERTs "K1".."K4" und rechnet deren lokale Position ueber die volle +;; Eltern-Orientierung in Weltkoordinaten um (csv:local-to-world). Es wird +;; nur die POSITION kodiert (12-Zeichen-String, csv:trans-encode) - keine +;; Rotation. ;; Zusaetzlich werden Strecken-Koordinatensysteme KS_EIN->K1 und KS_AUS->K2 ;; (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 @@ -336,8 +343,16 @@ ;; Umrechnung landete K2 tief unterhalb statt oberhalb des Elements (realer ;; 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 -;; auf die alte reine Uebernahme - unveraendertes Verhalten dort. -(defun csv:get-k-kos-strings (ename pt rot-rad / ed bname blk-tbl sub-ent sub-ed +;; auf die alte reine Uebernahme - unveraendertes Verhalten dort. Denselben +;; 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 target is-real result) (setq ed (entget ename)) @@ -374,7 +389,7 @@ (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-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 (cons target (csv:trans-encode @@ -505,14 +520,17 @@ (setq ed (entget ename)) (setq bname (cdr (assoc 2 ed))) (setq result nil) - ;; Beide Enden im Wrapper-Frame holen und in Weltkoordinaten (reine - ;; Z-Drehung) umrechnen. AS traegt das KS_EIN, ES das KS_AUS - jeweils aus - ;; dem RICHTIGEN Element (csv:vfgf-ks-loc; beide Elemente fuehren beide - ;; KS-Typen). + ;; Beide Enden im Wrapper-Frame holen und in Weltkoordinaten umrechnen. + ;; VF_n/GF_n-Wrapper stehen an ihrem eigenen top-level INSERT immer flach + ;; (Extrusion (0 0 1) - siehe csv:sep-proxies-erzeugen), darum genuegt hier + ;; 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 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 es-loc (setq es-world (csv:local-to-world pt rot-rad es-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 (mat3-rz rot-rad) es-loc))) ;; Eingang/Ausgang festlegen (siehe Richtung im Kopfkommentar). (cond ;; GF: Richtung ueber die Hoehe - hoeheres Z = Eingang, tieferes Z = Ausgang. @@ -631,7 +649,8 @@ ;; "k1".."k4" (KOS-Strings der Koordinatensysteme im Block, siehe ;; csv:get-k-kos-strings) werden immer geschrieben, unabhaengig von ;; 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 zuordnung-fix-json zuordnung-fix-eintrag sepliste-json sepliste-app sepliste sepliste-teile sepliste-first) @@ -642,12 +661,27 @@ (setq rotation (cdr (assoc 50 ed))) (setq handle (cdr (assoc 5 ed))) (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 insert-quat (csv:z-angle-to-quat (* (/ rotation pi) 180.0))) (setq insert-kos (csv:kos-encode (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))) - (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 ;; (Anfang/Ende ueber Laenge + Rotation) synthetisieren, damit sie im Export ;; wie echte Anschluss-Koordinatensysteme erscheinen und in der Nachbar-