[FIX] VF/GF K1/K2-Export: KS_EIN/KS_AUS aus dem RICHTIGEN AS/ES-Element

csv:vfgf-k-kos-strings suchte KS_EIN/KS_AUS flach ueber den GANZEN VF_n/GF_n-
Wrapper. Da sowohl das AS_Element als auch das ES_Element JEWEILS ein KS_EIN
UND ein KS_AUS fuehren (siehe check_hoehen.lsp ch-measure-vfgf), lieferte die
flache Suche zwei Treffer und (car ...) griff den falschen: K2 (ES) landete
auf dem KS_AUS des AS_Elements, also auf der Anfangs-/linken Seite statt am
ES-Ende. Fuer results/vario.dxf standen K1 und K2 dadurch beide nahe x=0.

Neue Helferfunktion csv:vfgf-ks-loc: erst das passende Element (AS_ELEMENT*
bzw. ES_ELEMENT*) suchen, dann NUR IN DESSEN Blockdefinition das KS
(KS_EIN fuer K1, KS_AUS fuer K2) und ueber die Weltlage des Elements
(world-pt/R-world/Skalierung) in den Wrapper-Frame transformieren -
gleiche zweistufige Logik wie ch-measure-vfgf. Am vario-Testfall verifiziert:
K1 (AS) bei VF-x=0, K2 (ES) bei VF-x=15000 (rechtes Ende).

Behebt zugleich die Ursache der ausgefallenen Ein-/Ausschleus-Kollision
(export_neighbors.py testet die AS/ES-Box an K1/K2 gegen die Kreisel).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-04 20:46:59 +02:00
parent ea69ffdd9c
commit 7eff324056
+63 -20
View File
@@ -381,6 +381,50 @@
) )
) )
;; --- KS-Position eines VF/GF-Wrappers ueber das RICHTIGE Element ---
;; bname = Blockname des VF_n/GF_n-Wrappers.
;; elem-pat = Muster des KS-tragenden Teilbloecks ("AS_ELEMENT*" bzw.
;; "ES_ELEMENT*", Grossschreibung - wcmatch ist unempfindlich).
;; ks-pat = Muster des gesuchten Koordinatensystems ("KS_EIN,KSYS_EIN"
;; bzw. "KS_AUS,KSYS_AUS").
;; Warum zwei Ebenen: das AS_Element UND das ES_Element eines VF_n fuehren
;; JEWEILS ein KS_EIN UND ein KS_AUS (siehe check_hoehen.lsp ch-measure-vfgf).
;; Ein flaches (ssg-collect-nested-inserts bname "KS_AUS") ueber den GANZEN
;; Wrapper lieferte darum zwei Treffer und (car ...) griff den falschen (den
;; des AS_Elements) - K2/ES landete auf der falschen (Anfangs-)Seite. Darum
;; ERST das passende Element (AS/ES) suchen und NUR IN DESSEN Blockdefinition
;; das KS. Die KS-Position wird durch die Weltlage des Elements (world-pt/
;; R-world/Skalierung aus dem Element-Record) in das Koordinatensystem der
;; Wrapper-Blockdefinition transformiert - dieselbe Verkettung wie in
;; ssg-collect-nested-inserts-rel (OCS ist in den Records bereits aufgeloest).
;; Rueckgabe: (x y z) im Wrapper-Definitionsframe, oder nil wenn nicht gefunden.
(defun csv:vfgf-ks-loc (bname elem-pat ks-pat / elem-hits elem-rec elem-bname
elem-pt elem-R elem-sx elem-sy elem-sz ks-hits ks-loc
scaled)
(setq elem-hits (ssg-collect-nested-inserts bname elem-pat))
(if elem-hits
(progn
(setq elem-rec (car elem-hits))
(setq elem-bname (strcase (cdr (assoc 2 (entget (car elem-rec))))))
;; Nur das KS INNERHALB dieser Element-Blockdefinition (nicht im Wrapper).
(setq ks-hits (ssg-collect-nested-inserts elem-bname ks-pat))
(if ks-hits
(progn
(setq elem-pt (cadr elem-rec))
(setq elem-R (caddr elem-rec))
(setq elem-sx (nth 3 elem-rec) elem-sy (nth 4 elem-rec) elem-sz (nth 5 elem-rec))
(setq ks-loc (cadr (car ks-hits))) ;; KS-Pos im Element-Frame
(setq scaled (list (* elem-sx (car ks-loc))
(* elem-sy (cadr ks-loc))
(* elem-sz (caddr ks-loc))))
;; Element-Weltlage (im Wrapper-Frame) + rotierte KS-Position.
(mapcar '+ elem-pt (mat3-mul-vec3 elem-R scaled))
)
)
)
)
)
;; --- K1 (AS/KS_EIN) / K2 (ES/KS_AUS) eines VF_n/GF_n-Wrappers ableiten --- ;; --- K1 (AS/KS_EIN) / K2 (ES/KS_AUS) eines VF_n/GF_n-Wrappers ableiten ---
;; ename = Entity-Name des platzierten VF_n/GF_n-INSERT. ;; ename = Entity-Name des platzierten VF_n/GF_n-INSERT.
;; pt/rot-rad = Welt-Einfuegepunkt/-Rotation (radiant) des Wrappers (siehe ;; pt/rot-rad = Welt-Einfuegepunkt/-Rotation (radiant) des Wrappers (siehe
@@ -388,43 +432,42 @@
;; VF/GF-Wrapper fuehren - anders als Omniflo-Boegen - KEINE direkten K1-K4- ;; VF/GF-Wrapper fuehren - anders als Omniflo-Boegen - KEINE direkten K1-K4-
;; oder KS-Sub-INSERTs; ihre Streckenenden stecken je EINE Ebene tiefer: ;; oder KS-Sub-INSERTs; ihre Streckenenden stecken je EINE Ebene tiefer:
;; KS_EIN im AS_Element*, KS_AUS im ES_Element* (siehe check_hoehen.lsp, ;; KS_EIN im AS_Element*, KS_AUS im ES_Element* (siehe check_hoehen.lsp,
;; extract-ks-from-block-raw). ssg-collect-nested-inserts findet diese ;; extract-ks-from-block-raw). csv:vfgf-ks-loc holt die KS-Position aus dem
;; verschachtelten INSERTs mit ihrer Platzierung RELATIV zur Wrapper- ;; JEWEILS zugehoerigen Element (nicht flach aus dem ganzen Wrapper - beide
;; Blockdefinition (ename/(x y z)/... - der zweite Eintrag ist der Ursprung ;; Elemente tragen beide KS-Typen). Der so ermittelte Punkt (Wrapper-Frame)
;; des KS-INSERTs, also die AS-/ES-Position). Der lokale Punkt wird ueber die ;; wird ueber die Wrapper-Weltlage (reine Z-Drehung) in Weltkoordinaten
;; Wrapper-Weltlage (reine Z-Drehung) in Weltkoordinaten gedreht und wie K1-K4 ;; gedreht und wie K1-K4 als reiner Positions-String (csv:trans-encode)
;; als reiner Positions-String (csv:trans-encode) exportiert. Damit hat auch ;; exportiert. Damit hat auch eine Strecke K1 (AS) und K2 (ES) fuer die
;; eine Strecke K1 (AS) und K2 (ES) fuer die Python-Kollisionspruefung ;; Python-Kollisionspruefung (export_neighbors.py: Schleuselemente +
;; (export_neighbors.py: Schleuselemente + Kreisel-Kollision ueber die AS/ES- ;; Kreisel-Kollision ueber die AS/ES-Position mit fester BBox statt der
;; Position mit fester BBox statt der ganzen Wrapper-Box). ;; ganzen Wrapper-Box).
;; Rueckgabe wie csv:get-k-kos-strings: (("K1" . str) ("K2" . str)) - nur die ;; Rueckgabe wie csv:get-k-kos-strings: (("K1" . str) ("K2" . str)) - nur die
;; tatsaechlich gefundenen Enden. ;; tatsaechlich gefundenen Enden.
(defun csv:vfgf-k-kos-strings (ename pt rot-rad / ed bname as-hits es-hits result (defun csv:vfgf-k-kos-strings (ename pt rot-rad / ed bname loc world result)
loc world)
(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)
;; KS-INSERTs (KS_EIN/KS_AUS bzw. KSYS_-Varianten) direkt im AS_Element/ ;; K1 = KS_EIN aus dem AS_Element, K2 = KS_AUS aus dem ES_Element. Die
;; ES_Element suchen. wcmatch ist Gross/Klein-unempfindlich fuer Blocknamen. ;; Element-Zuordnung ist zwingend (jedes Element traegt beide KS-Typen,
(setq as-hits (ssg-collect-nested-inserts bname "KS_EIN,KSYS_EIN")) ;; siehe csv:vfgf-ks-loc). Ergebnis-Frame -> Weltlage ueber die reine
(setq es-hits (ssg-collect-nested-inserts bname "KS_AUS,KSYS_AUS")) ;; Z-Drehung des Wrappers (csv:local-to-world).
(if as-hits (setq loc (csv:vfgf-ks-loc bname "AS_ELEMENT*" "KS_EIN,KSYS_EIN"))
(if loc
(progn (progn
(setq loc (cadr (car as-hits)))
(setq world (csv:local-to-world pt rot-rad loc)) (setq world (csv:local-to-world pt rot-rad loc))
(setq result (cons (cons "K1" (setq result (cons (cons "K1"
(csv:trans-encode (car world) (cadr world) (caddr world))) result)) (csv:trans-encode (car world) (cadr world) (caddr world))) result))
) )
) )
(if es-hits (setq loc (csv:vfgf-ks-loc bname "ES_ELEMENT*" "KS_AUS,KSYS_AUS"))
(if loc
(progn (progn
(setq loc (cadr (car es-hits)))
(setq world (csv:local-to-world pt rot-rad loc)) (setq world (csv:local-to-world pt rot-rad loc))
(setq result (cons (cons "K2" (setq result (cons (cons "K2"
(csv:trans-encode (car world) (cadr world) (caddr world))) result)) (csv:trans-encode (car world) (cadr world) (caddr world))) result))
) )
) )
result (reverse result)
) )