diff --git a/Lisp/Gefaellestrecke.lsp b/Lisp/Gefaellestrecke.lsp index 1f59e4a..6e195e6 100644 --- a/Lisp/Gefaellestrecke.lsp +++ b/Lisp/Gefaellestrecke.lsp @@ -332,6 +332,22 @@ ) ) +;; --- KS-Rahmen aus Fahrtrichtungsvektor (Fallback wenn vf_core nicht geladen) --- +(if (null (car (atoms-family 1 '("MAKE-FRAME-FROM-DIR")))) + (defun make-frame-from-dir (P xu-unit / hlen yu zu) + (setq hlen (sqrt (+ (* (car xu-unit)(car xu-unit)) + (* (cadr xu-unit)(cadr xu-unit))))) + (setq yu + (if (> hlen 1e-6) + (list (/ (- (cadr xu-unit)) hlen) (/ (car xu-unit) hlen) 0.0) + '(1.0 0.0 0.0))) + (setq zu + (list (- (* (cadr xu-unit)(caddr yu)) (* (caddr xu-unit)(cadr yu))) + (- (* (caddr xu-unit)(car yu)) (* (car xu-unit)(caddr yu))) + (- (* (car xu-unit)(cadr yu)) (* (cadr xu-unit)(car yu))))) + (list P xu-unit yu zu)) +) + ;; --- Linie/Polylinie-Endpunkte lesen --- (if (null (car (atoms-family 1 '("GET-LINE-START-END-POINTS")))) (defun get-line-start-end-points (msg / ent obj obj-name sp ep) @@ -775,20 +791,19 @@ ) ;; Alle Segmente des Linienzugs einfuegen. -;; segmente: Ergebnis von gf-analysiere-kette -;; grade: Gefaellewinkel in Grad -;; startpunkt: 3D-Einfuegepunkt des ersten Blocks -;; -;; Reihenfolge bei Bogen: -;; ... Staustrecke (Linie) → Separator am Ende der Linie → Gefaellebogen ... -(defun gf-linienzug-einfuegen (segmente grade startpunkt / - aktuell i n seg naechstes - typ hz laenge bwinkel bseite blockname) - (setq aktuell startpunkt) +;; segmente : Ergebnis von gf-analysiere-kette +;; grade : Gefaellewinkel in Grad +;; startframe : Vollstaendiger Rahmen (P xu yu zu) am Kettenanfang +;; Rueckgabe : Vollstaendiger Rahmen (P xu yu zu) am Kettenende +(defun gf-linienzug-einfuegen (segmente grade startframe / + aktuell-frame i n seg naechstes + typ hz laenge bwinkel bseite blockname + rad-h rad-v xu-incl endpunkt) + (setq aktuell-frame startframe) (setq n (length segmente)) (setq i 0) (while (< i n) - (setq seg (nth i segmente)) + (setq seg (nth i segmente)) (setq naechstes (if (< (1+ i) n) (nth (1+ i) segmente) nil)) (setq typ (car seg)) (setq hz (cadr seg)) @@ -801,9 +816,16 @@ ": Staustrecke L=" (rtos laenge 2 1) " mm" " hz=" (rtos hz 2 1) grad-zeichen " v=" (rtos grade 2 2) grad-zeichen)) - (setq aktuell + (setq endpunkt (gf-insert-hz-incl-scaled - "Staustrecke_SP_1000_mm" aktuell laenge hz grade)) + "Staustrecke_SP_1000_mm" (car aktuell-frame) laenge hz grade)) + ;; Ausgangsrahmen: geneigte Fahrtrichtung + (setq rad-h (* (float hz) (/ pi 180.0))) + (setq rad-v (* (float grade) (/ pi 180.0))) + (setq xu-incl (list (* (cos rad-h)(cos rad-v)) + (* (sin rad-h)(cos rad-v)) + (- (sin rad-v)))) + (setq aktuell-frame (make-frame-from-dir endpunkt xu-incl)) ;; Separator am Ende dieser Linie, falls naechstes Segment ein Bogen ist (if (and naechstes (= (car naechstes) "Bogen")) (progn @@ -811,20 +833,20 @@ ": Separator 300mm (vor Bogen)" " hz=" (rtos hz 2 1) grad-zeichen " v=" (rtos grade 2 2) grad-zeichen)) - (setq aktuell + (setq endpunkt (gf-insert-hz-with-ks - "Staustrecke_Separator_SP_300_mm" aktuell hz grade 300 0)) + "Staustrecke_Separator_SP_300_mm" (car aktuell-frame) hz grade 300 0)) + (setq aktuell-frame (make-frame-from-dir endpunkt xu-incl)) ) ) ) ((= typ "Bogen") (setq blockname (gf-bogen-blockname bwinkel bseite)) - ;; Gefaellebogen (nur Hz-Rotation, Block hat eigene 3D-Geometrie) (princ (strcat "\n\n" (itoa (1+ i)) "/" (itoa n) ": " blockname " hz=" (rtos hz 2 1) grad-zeichen)) - (setq aktuell - (gf-insert-gefaellebogen-by-ks blockname aktuell hz)) + ;; Gefaellebogen: KS_EIN an aktuellem Rahmen ausrichten (volle 3D-Rotation) + (setq aktuell-frame (insert-block-ks-to-ks blockname aktuell-frame)) ) ) (setq i (1+ i)) @@ -832,8 +854,7 @@ (princ "\n\n=========================================") (princ "\n>>> Linienzug-Gefaellestrecke eingefuegt! <<<") (princ "\n=========================================") - aktuell -) + aktuell-frame) ;; Listenelement an Position idx durch val ersetzen. (defun gf-replace-nth (lst idx val / i result) @@ -873,10 +894,12 @@ entry-hz exit-hz first-idx last-idx neu-l chz shz as-target - aktuell-pt nach-aus-pt + aktuell-pt aktuell-frame nach-aus-pt gf-nummer last-ent L-gf-str delta-l-gf laengen-liste first-l l-item - bL90 bL60 bL30 bR90 bR60 bR30 n-bogen-gf) + bL90 bL60 bL30 bR90 bR60 bR30 n-bogen-gf + rad-h-as rad-v-as xu-entry + sep-endpunkt rad-h-es rad-v-es xu-exit sep-frame) (princ "\n\n>>> MODUS 3: Linienzug auswaehlen <<<") (princ "\nBitte alle Linien (LINE) und Boegen (ARC) des Pfades auswaehlen,") (princ "\ndann ENTER druecken:") @@ -1068,19 +1091,33 @@ (setq aktuell-pt (gf-insert-gefaellebogen-by-ks as-block as-target entry-hz)) (setq nach-aus-pt aktuell-pt) - ;; Linienzug mit Gefaellebogen und Separatoren (gekuerzte Laengen) - (setq aktuell-pt (gf-linienzug-einfuegen segmente grade aktuell-pt)) + ;; Eingangsrahmen nach AS-Element: Position + geneigte Fahrtrichtung + (setq rad-h-as (* (float entry-hz) (/ pi 180.0))) + (setq rad-v-as (* (float grade) (/ pi 180.0))) + (setq xu-entry (list (* (cos rad-h-as)(cos rad-v-as)) + (* (sin rad-h-as)(cos rad-v-as)) + (- (sin rad-v-as)))) + (setq aktuell-frame (make-frame-from-dir aktuell-pt xu-entry)) + + ;; Linienzug mit Gefaellebogen und Separatoren (Frame-basiert) + (setq aktuell-frame (gf-linienzug-einfuegen segmente grade aktuell-frame)) ;; Separator vor EIN-Element (princ "\n>>> Separator vor EIN-Element") - (setq aktuell-pt + (setq sep-endpunkt (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" - aktuell-pt exit-hz grade 300 0)) + (car aktuell-frame) exit-hz grade 300 0)) + ;; Ausgangsrahmen nach Separator fuer ES-Element + (setq rad-h-es (* (float exit-hz) (/ pi 180.0))) + (setq rad-v-es (* (float grade) (/ pi 180.0))) + (setq xu-exit (list (* (cos rad-h-es)(cos rad-v-es)) + (* (sin rad-h-es)(cos rad-v-es)) + (- (sin rad-v-es)))) + (setq sep-frame (make-frame-from-dir sep-endpunkt xu-exit)) - ;; EIN-Element mit Austrittsrichtung ausrichten (Rz um exit-hz) - (princ (strcat "\n>>> EIN-Element: " es-block - " (hz=" (rtos exit-hz 2 1) grad-zeichen ")")) - (gf-insert-gefaellebogen-by-ks es-block aktuell-pt exit-hz) + ;; EIN-Element: KS_EIN an vollstaendigem Rahmen ausrichten (KS-zu-KS) + (princ (strcat "\n>>> EIN-Element: " es-block)) + (insert-block-ks-to-ks es-block sep-frame) ;; --- GF_N-Block erstellen --- diff --git a/Lisp/KreiselInsert.lsp b/Lisp/KreiselInsert.lsp index 7825e8a..252279a 100644 --- a/Lisp/KreiselInsert.lsp +++ b/Lisp/KreiselInsert.lsp @@ -19,8 +19,9 @@ ;; DXFM_DIM sicher lesen (type-Guard gegen nicht-String Rueckgabewerte) (setq *ki-dxfm-dim* (getenv "DXFM_DIM")) (if (not (= (type *ki-dxfm-dim*) 'STR)) (setq *ki-dxfm-dim* "3D")) -;; Block-Pfad: primaer aus DXFMAKRO + DXFM_DIM, dann *ssg-lisp-pfad*-Heuristik -(setq block-pfad +;; Modul-eigener Block-Pfad (nicht in globalem block-pfad speichern, +;; da GF/VF stets 3D-Pfad benoetigen, KI aber DXFM_DIM-abhaengig) +(setq *block-path* (cond ((and (getenv "DXFMAKRO") (= (type (getenv "DXFMAKRO")) 'STR)) (strcat (vl-string-right-trim "/" (vl-string-translate "\\" "/" (getenv "DXFMAKRO"))) @@ -34,7 +35,6 @@ nil) ) ) -(setq *block-path* block-pfad) ;; ssg_core laden falls noch nicht geschehen (Schutz bei direktem Laden ohne ssg-ensure) (if (null (car (atoms-family 1 '("SSG-CFG-OR")))) @@ -401,10 +401,10 @@ ) ;; AN8 Kreis (Antriebsstation) bei (radius, 0) - (command "_.INSERT" (strcat block-pfad "AN8.dwg") (list radius 0.0 0.0) 1 1 0) + (command "_.INSERT" (strcat *block-path* "AN8.dwg") (list radius 0.0 0.0) 1 1 0) ;; SP8 Kreis (Spannstation) bei (radius+abstand, 0) - (command "_.INSERT" (strcat block-pfad "SP8.dwg") (list (+ radius abstand) 0.0 0.0) 1 1 0) + (command "_.INSERT" (strcat *block-path* "SP8.dwg") (list (+ radius abstand) 0.0 0.0) 1 1 0) ;; Tangenten auf Layer S_LP (ssg-make-layer "S_LP" "7" T) @@ -1288,6 +1288,6 @@ (princ "\n>>> KREISELINSERT v7.0 geladen <<<") (princ "\n>>> Befehle: KreiselInsert, KreiselConnect, KreiselRedraw,") (princ "\n KreiselEdit, KreiselQuick, KreiselParams, ILS_Eckrad") -(if block-pfad (princ (strcat "\n Block-Pfad: " block-pfad))) +(if *block-path* (princ (strcat "\n Block-Pfad: " *block-path*))) (princ "\n=========================================") (princ) diff --git a/Lisp/vf_core.lsp b/Lisp/vf_core.lsp index 8692a91..9ed9c06 100644 --- a/Lisp/vf_core.lsp +++ b/Lisp/vf_core.lsp @@ -156,6 +156,81 @@ (cadr item)))) ks-rel)) +;; ============================================================ +;; TEIL 4b: KS-FRAME MATHEMATIK +;; ============================================================ + +;; 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)))))) + +;; 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)) +;; Rueckgabe: (P xu yu zu) - Ursprung + 3 normierte Einheitsvektoren +(defun ks-frame-extract (ks-raw / origin x-end y-end z-end) + (setq origin (car ks-raw) + x-end (cadr ks-raw) + y-end (caddr ks-raw) + z-end (cadddr ks-raw)) + (list origin + (vec3-normalize (list (- (car x-end)(car origin)) + (- (cadr x-end)(cadr origin)) + (- (caddr x-end)(caddr origin)))) + (vec3-normalize (list (- (car y-end)(car origin)) + (- (cadr y-end)(cadr origin)) + (- (caddr y-end)(caddr origin)))) + (vec3-normalize (list (- (car z-end)(car origin)) + (- (cadr z-end)(cadr origin)) + (- (caddr z-end)(caddr origin)))))) + +;; KS-Rahmen aus normiertem Fahrtrichtungsvektor mit horizontaler Senkrechtachse +;; Rueckgabe: (P xu yu zu) +;; Konvention: yu = horizontal senkrecht zu xu (links der Fahrtrichtung) +;; zu = xu x yu (senkrecht zur Gurtoberflaeche, nach oben) +(defun make-frame-from-dir (P xu-unit / hlen yu zu) + (setq hlen (sqrt (+ (* (car xu-unit)(car xu-unit)) + (* (cadr xu-unit)(cadr xu-unit))))) + (setq yu + (if (> hlen 1e-6) + (list (/ (- (cadr xu-unit)) hlen) + (/ (car xu-unit) hlen) + 0.0) + '(1.0 0.0 0.0))) + (setq zu (vec3-cross xu-unit yu)) + (list P xu-unit yu zu)) + ;; ============================================================ ;; TEIL 5: KS_EIN/KS_AUS EXTRAKTION ;; ============================================================ @@ -395,6 +470,77 @@ ) ) +;; Fuegt Block ein und richtet KS_EIN am Ziel-Rahmen aus (volle 3D-Rotation). +;; target-frame : (P xt yt zt) - Ziel-Rahmen, z.B. KS_AUS des Vorgaenger-Elements +;; Rueckgabe : (P xu yu zu) - KS_AUS-Rahmen des eingefuegten Blocks +(defun insert-block-ks-to-ks (blockname target-frame / + block-obj ks-data ks-ein-raw ks-aus-raw + f-ein f-aus P-t xt yt zt + P-ein xe ye ze P-aus xu-aus yu-aus zu-aus + R R-Pein R-Paus tx ty tz T4 + P-out xu-out yu-out zu-out) + (ensure-block-loaded blockname) + (if (not (tblsearch "BLOCK" blockname)) + (progn + (princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek")) + (exit))) + ;; Ziel-Rahmen auspacken + (setq P-t (car target-frame) + xt (cadr target-frame) + yt (caddr target-frame) + zt (cadddr target-frame)) + ;; Block am Ursprung einfuegen (Rotation=0, Massstab=1) + (setq block-obj (vla-InsertBlock modelspace + (vlax-3D-point '(0 0 0)) + blockname 1.0 1.0 1.0 0)) + ;; KS_EIN und KS_AUS extrahieren (nutzt Cache nach erstem Aufruf) + (setq ks-data (extract-ks-from-block block-obj)) + (setq ks-ein-raw (cadr (assoc "KS_EIN" ks-data))) + (setq ks-aus-raw (cadr (assoc "KS_AUS" ks-data))) + (if (not (and ks-ein-raw ks-aus-raw)) + (progn + (princ (strcat "\n FEHLER: KS_EIN/KS_AUS fehlen in '" blockname "'")) + (vla-Delete block-obj) + (exit))) + ;; Normierte Rahmen (P xu yu zu) aus rohen KS-Daten berechnen + (setq f-ein (ks-frame-extract ks-ein-raw) + f-aus (ks-frame-extract ks-aus-raw)) + (setq P-ein (car f-ein) + xe (cadr f-ein) + ye (caddr f-ein) + ze (cadddr f-ein)) + (setq P-aus (car f-aus) + xu-aus (cadr f-aus) + yu-aus (caddr f-aus) + zu-aus (cadddr f-aus)) + ;; Rotationsmatrix: R * xe = xt, R * ye = yt, R * ze = zt + (setq R (mat3-from-frames xt yt zt xe ye ze)) + ;; Translation: t = P_target - R * P_ein + (setq R-Pein (mat3-mul-vec3 R P-ein)) + (setq tx (- (car P-t) (car R-Pein)) + ty (- (cadr P-t) (cadr R-Pein)) + tz (- (caddr P-t) (caddr R-Pein))) + ;; 4x4-Transformationsmatrix aufbauen und auf Block anwenden + (setq T4 (vlax-tmatrix + (list (list (car (car R)) (cadr (car R)) (caddr (car R)) tx) + (list (car (cadr R)) (cadr (cadr R)) (caddr (cadr R)) ty) + (list (car (caddr R)) (cadr (caddr R)) (caddr (caddr R)) tz) + (list 0.0 0.0 0.0 1.0)))) + (vla-TransformBy block-obj T4) + ;; Ausgabe-Rahmen fuer KS_AUS mathematisch berechnen (kein Re-Extrahieren noetig) + (setq R-Paus (mat3-mul-vec3 R P-aus)) + (setq P-out (list (+ (car R-Paus) tx) + (+ (cadr R-Paus) ty) + (+ (caddr R-Paus) tz))) + (setq xu-out (mat3-mul-vec3 R xu-aus) + yu-out (mat3-mul-vec3 R yu-aus) + zu-out (mat3-mul-vec3 R zu-aus)) + (princ (strcat "\n '" blockname "' eingefuegt" + "\n KS_AUS: X=" (rtos (car P-out) 2 2) + " Y=" (rtos (cadr P-out) 2 2) + " Z=" (rtos (caddr P-out) 2 2))) + (list P-out xu-out yu-out zu-out)) + (defun insert-inclined-scaled-block (blockname startpunkt laenge winkel / rad matrix block-obj endpunkt scale) (if (<= laenge 0.1) diff --git a/data/ils/2D/AS_Element_30_links.dwg b/data/ils/2D/AS_Element_30_links.dwg new file mode 100644 index 0000000..c2e059e Binary files /dev/null and b/data/ils/2D/AS_Element_30_links.dwg differ diff --git a/data/ils/2D/AS_Element_30_rechts.dwg b/data/ils/2D/AS_Element_30_rechts.dwg new file mode 100644 index 0000000..f5e217b Binary files /dev/null and b/data/ils/2D/AS_Element_30_rechts.dwg differ diff --git a/data/ils/2D/AS_Element_90_links.dwg b/data/ils/2D/AS_Element_90_links.dwg index 1b5f810..24b1fd2 100644 Binary files a/data/ils/2D/AS_Element_90_links.dwg and b/data/ils/2D/AS_Element_90_links.dwg differ diff --git a/data/ils/2D/AS_Element_90_rechts.dwg b/data/ils/2D/AS_Element_90_rechts.dwg index dd5271b..c3eed68 100644 Binary files a/data/ils/2D/AS_Element_90_rechts.dwg and b/data/ils/2D/AS_Element_90_rechts.dwg differ diff --git a/data/ils/2D/ES_Element_30_links.dwg b/data/ils/2D/ES_Element_30_links.dwg index 3de534e..e7a490b 100644 Binary files a/data/ils/2D/ES_Element_30_links.dwg and b/data/ils/2D/ES_Element_30_links.dwg differ diff --git a/data/ils/2D/ES_Element_30_rechts.dwg b/data/ils/2D/ES_Element_30_rechts.dwg index 4bf9678..508a71b 100644 Binary files a/data/ils/2D/ES_Element_30_rechts.dwg and b/data/ils/2D/ES_Element_30_rechts.dwg differ diff --git a/data/ils/2D/ES_Element_90_links.dwg b/data/ils/2D/ES_Element_90_links.dwg index 407d733..e34f884 100644 Binary files a/data/ils/2D/ES_Element_90_links.dwg and b/data/ils/2D/ES_Element_90_links.dwg differ diff --git a/data/ils/2D/ES_Element_90_rechts.dwg b/data/ils/2D/ES_Element_90_rechts.dwg index 862e43c..929fd1f 100644 Binary files a/data/ils/2D/ES_Element_90_rechts.dwg and b/data/ils/2D/ES_Element_90_rechts.dwg differ diff --git a/data/ils/2D/Scanner.dwg b/data/ils/2D/Scanner.dwg new file mode 100644 index 0000000..053e9c5 Binary files /dev/null and b/data/ils/2D/Scanner.dwg differ diff --git a/data/ils/2D/Separator_SP.dwg b/data/ils/2D/Separator_SP.dwg index e4fdbb6..1885a22 100644 Binary files a/data/ils/2D/Separator_SP.dwg and b/data/ils/2D/Separator_SP.dwg differ diff --git a/data/ils/3D/AS_Element_30_links.dwg b/data/ils/3D/AS_Element_30_links.dwg index 5411b96..be83b8f 100644 Binary files a/data/ils/3D/AS_Element_30_links.dwg and b/data/ils/3D/AS_Element_30_links.dwg differ diff --git a/data/ils/3D/AS_Element_30_rechts.dwg b/data/ils/3D/AS_Element_30_rechts.dwg index e95bd96..dab1179 100644 Binary files a/data/ils/3D/AS_Element_30_rechts.dwg and b/data/ils/3D/AS_Element_30_rechts.dwg differ diff --git a/data/ils/3D/AS_Element_90_links.dwg b/data/ils/3D/AS_Element_90_links.dwg index 7f842b8..a00f80e 100644 Binary files a/data/ils/3D/AS_Element_90_links.dwg and b/data/ils/3D/AS_Element_90_links.dwg differ diff --git a/data/ils/3D/AS_Element_90_rechts.dwg b/data/ils/3D/AS_Element_90_rechts.dwg index 4af8377..47a57db 100644 Binary files a/data/ils/3D/AS_Element_90_rechts.dwg and b/data/ils/3D/AS_Element_90_rechts.dwg differ diff --git a/data/ils/3D/ES_Element_30_links.dwg b/data/ils/3D/ES_Element_30_links.dwg index a3044fa..133fa38 100644 Binary files a/data/ils/3D/ES_Element_30_links.dwg and b/data/ils/3D/ES_Element_30_links.dwg differ diff --git a/data/ils/3D/ES_Element_30_rechts.dwg b/data/ils/3D/ES_Element_30_rechts.dwg index e37b7d0..6b56b80 100644 Binary files a/data/ils/3D/ES_Element_30_rechts.dwg and b/data/ils/3D/ES_Element_30_rechts.dwg differ diff --git a/data/ils/3D/ES_Element_90_links.dwg b/data/ils/3D/ES_Element_90_links.dwg index d77d764..906cab9 100644 Binary files a/data/ils/3D/ES_Element_90_links.dwg and b/data/ils/3D/ES_Element_90_links.dwg differ diff --git a/data/ils/3D/ES_Element_90_rechts.dwg b/data/ils/3D/ES_Element_90_rechts.dwg index d2b3b90..51f0373 100644 Binary files a/data/ils/3D/ES_Element_90_rechts.dwg and b/data/ils/3D/ES_Element_90_rechts.dwg differ diff --git a/doc/KS-Frame-Architektur.md b/doc/KS-Frame-Architektur.md new file mode 100644 index 0000000..eedd3b4 --- /dev/null +++ b/doc/KS-Frame-Architektur.md @@ -0,0 +1,108 @@ +# KS-Frame-Architektur — Aufbaulogik + +## Kernidee + +Jeder 3D-Block enthaelt eingebettete **KS_EIN**- und **KS_AUS**-Teilbloecke +(Koordinatensystem-Marker). Statt Winkel und Position manuell zu berechnen, +wird die Kette der Bloecke rein mathematisch verknuepft: + +``` +KS_AUS(n) ──► KS_EIN(n+1) ──► Block(n+1) eingefuegt ──► KS_AUS(n+1) ──► ... +``` + +Jeder **Frame** = `(P xu yu zu)` — Ursprung + 3 normierte Einheitsvektoren +(Fahrtrichtung, links-senkrecht, hoch). + +--- + +## Schritt 1 — Mathematisches Fundament (`vf_core.lsp`) + +Reine Hilfsfunktionen ohne Seiteneffekte: + +| Funktion | Eingabe → Ausgabe | +|---|---| +| `ks-frame-extract` | Rohdaten `(origin x-end y-end z-end)` → normierter Frame `(P xu yu zu)` | +| `vec3-normalize` | Vektor → Einheitsvektor | +| `vec3-cross` | (a, b) → Kreuzprodukt | +| `mat3-mul-vec3` | 3×3-Matrix × Vektor | +| `mat3-from-frames` | `(xt yt zt, xe ye ze)` → Rotationsmatrix R mit `R*xe=xt` | +| `make-frame-from-dir` | Punkt + Richtungsvektor → vollstaendiger Frame (yu=links-horizontal, zu=hoch) | + +--- + +## Schritt 2 — Kernfunktion `insert-block-ks-to-ks` (`vf_core.lsp`) + +```lisp +(insert-block-ks-to-ks blockname target-frame) → KS_AUS-frame +``` + +Ablauf intern: + +1. Block bei `(0 0 0)` einfuegen (Rohzustand) +2. KS_EIN und KS_AUS aus Block extrahieren +3. Rotationsmatrix berechnen: `R = mat3-from-frames(xt yt zt, xe ye ze)` +4. Translation: `t = P_target − R × P_EIN` +5. 4×4-Transformationsmatrix `T4` aufbauen und auf Block anwenden via `vla-TransformBy` +6. KS_AUS-Frame mathematisch mitrotieren (kein zweites Extrahieren noetig) + +Das ist die einzige Funktion, die alle spaetere Module brauchen. + +--- + +## Schritt 3 — Gefaellestrecke Modus 3 (`Gefaellestrecke.lsp`) + +Ersetzt die alte positions-basierte Einfuegung durch Frame-Kettung: + +**Vorher**: `aktuell-pt` (nur 2D-Punkt) + manuelle Winkelrechnung +**Nachher**: `aktuell-frame` (vollstaendiger 3D-Frame) propagiert durch die +gesamte Streckenkette + +- Linie-Segment: `make-frame-from-dir(endpunkt, xu-incl)` → neuer Frame +- Bogen-Segment: `insert-block-ks-to-ks(blockname, aktuell-frame)` → gibt + direkt den Folge-Frame zurueck + +--- + +## Schritt 4 — VarioFoerderer (`vf_standard.lsp` / `vf_etage.lsp`) + +Gleiche Umstellung wie Schritt 3, aber fuer gerade Foerderstrecken: + +- `insert-block-by-ks` und `insert-rotated-block-with-ks` → ersetzt durch + `insert-block-ks-to-ks` +- `variofoerderer-einfuegen` und `vf-etage-einfuegen`: `startpunkt` → `startframe` + +--- + +## Warum diese Reihenfolge? + +``` +Schritt 1: Fundament legen (keine Abhaengigkeiten) + ↓ +Schritt 2: Kernfunktion auf Fundament aufsetzen + ↓ +Schritt 3: Gefaellestrecke zuerst — komplexer (3D-Neigung + Boegen) + ↓ +Schritt 4: VarioFoerderer — einfacher (nur ebene Kurven) +``` + +--- + +## Zusammenfassung in einem Satz + +Die bisherige positionsbasierte Block-Einfuegung (Punkt + Winkel) wurde +durch eine vollstaendige **3D-Frame-Kettung ueber +KS_EIN/KS_AUS-Koordinatensysteme** ersetzt, sodass beliebige raeumliche +Orientierungen korrekt durch die gesamte VarioFoerderer- und +Gefaellestrecke-Anlage propagiert werden. + +--- + +## Betroffene Dateien + +| Datei | Aenderung | +|---|---| +| `Lisp/vf_core.lsp` | Schritt 1 + 2: neue Hilfsfunktionen und `insert-block-ks-to-ks` | +| `Lisp/Gefaellestrecke.lsp` | Schritt 3: Modus-3-Kette auf Frame-Basis umgestellt | +| `Lisp/vf_standard.lsp` | Schritt 4: VarioFoerderer auf Frame-Basis umgestellt | +| `Lisp/vf_etage.lsp` | Schritt 4: Etagen-VarioFoerderer auf Frame-Basis umgestellt | +| `Lisp/KreiselInsert.lsp` | Bugfix: `block-pfad`-Kontamination behoben (2D/3D-Konflikt) |