Die gebaute Etage-Kette endete 987.63 mm zu weit (X) und 3.46 mm zu hoch (Z).
Der Fehlbetrag lag vollstaendig im Ein-/Auslauf: der Solver reservierte dort
1177.87 mm, real verbraucht die Kette 2165.09 mm.
Zwei Ursachen:
(a) vf-element-masse liefert KS_EIN->KS_AUS im BLOCK-Koordinatensystem. AS
und ES werden aber um (hz - ein-ang) gedreht eingebaut - beim
AS_Element_30 ist ein-ang = 90 Grad, dadurch landet die Block-Y-
Komponente auf der Hauptachse. Bilanziert wurde die Block-X-Komponente:
AS 209.7 statt real 486.10, ES -242.6 statt real 525.29.
(b) Die Auslauf-Staustrecke wurde fix mit 400 mm budgetiert, ist seit dem
Umbau "Auslauf RUECKWAERTS vom ES gerechnet" aber variabel (im Testfall
334 mm). Daraus die 3.46 mm Resthoehe.
Fix: neue Funktion etage-rand-budget (seite) rechnet Einlauf (Schritte 1-4)
und Auslauf (12-15) exakt so, wie etage-foerderanlage-einfuegen sie baut,
inklusive analytisch vorab bestimmtem L-exit. Kern sind die reinen,
hz-unabhaengigen Projektionen etage-laengs/etage-quer. Die alte Naeherung
bleibt als Fallback, falls ein Block fehlt.
Damit faellt auch die bisherige Annahme, Laengentreue und seitliche
Fluchtung des ES-KS_AUS seien nicht gleichzeitig loesbar: die Bauschritte
5-11 laufen auf der Hauptachse und tragen nichts zur Quer-Bilanz bei,
L-exit ist deshalb von L_GF/L_VF unabhaengig und vor dem Solve bestimmbar.
Weiter: Konstante *vfk-etage-stau-ein* (400 mm) ersetzt die nackte Zahl an
beiden Stellen; zwei neue lang-Keys (de+en, Paritaet 1095/1095); neuer
Regressionsblock tu-tests-etage in tests/test_unit.lsp mit dem AS/ES-Fall
(Suite 520/520 gruen).
In BricsCAD verifiziert: Soll-Endpunkt (11804.31, 3039.64, 4256.5) exakt
getroffen, Abweichung 0.00 mm in allen drei Achsen.
Offen: bei korrekter Bilanz bleiben im Testfall bei 33 Grad nur 16.13 mm
fuer beide GF-Strecken. Eine Mindest-GF-Laenge als Gueltigkeitskriterium
der Winkelwahl ist noch nicht eingebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
969 lines
45 KiB
Common Lisp
969 lines
45 KiB
Common Lisp
;; ============================================================
|
||
;; VF_ETAGE - Etage VarioFoerderer (Typ: "etage")
|
||
;; Version: 26.0
|
||
;; Abhaengigkeit: vf_core.lsp muss zuerst geladen sein
|
||
;; Geometrie: AS/ES 30 Grad, direkt uebereinander (60 Grad Hz-Winkel)
|
||
;; 15-Schritt-Einfuegung
|
||
;; ============================================================
|
||
|
||
;; Sicherstellen, dass vf_core.lsp geladen ist. Pfad zentral ueber ssg_core
|
||
;; (ssg-lisp-verzeichnis), mit Inline-Fallback falls ssg_core hier noch nicht
|
||
;; geladen ist (nur relevant beim isolierten Einzel-Laden dieser Datei).
|
||
(if (not (car (atoms-family 1 '("VF-TYP-REGISTRIEREN"))))
|
||
(progn
|
||
(setq *vf-etage-core-pfad*
|
||
(if (car (atoms-family 1 '("SSG-LISP-VERZEICHNIS")))
|
||
(ssg-lisp-verzeichnis)
|
||
(cond
|
||
((getenv "DXFM_LISP") (vl-string-translate "\\" "/" (getenv "DXFM_LISP")))
|
||
((and (boundp '*ssg-lisp-pfad*) *ssg-lisp-pfad*) *ssg-lisp-pfad*)
|
||
(t nil))))
|
||
(if *vf-etage-core-pfad*
|
||
(load (strcat *vf-etage-core-pfad* "/vf_core.lsp"))
|
||
(progn
|
||
(princ (ssg-text "vfe-warn-lisp-pfad"))
|
||
(exit)
|
||
)
|
||
)
|
||
)
|
||
)
|
||
|
||
;; ============================================================
|
||
;; TEIL 1: ETAGE-SPEZIFISCHE GLOBALE VARIABLEN
|
||
;; ============================================================
|
||
(setq etage-aus-dx nil etage-aus-dz nil)
|
||
(setq etage-ein-dx nil etage-ein-dz nil)
|
||
(setq etage-gef-dx nil etage-gef-dy nil etage-gef-dz nil)
|
||
(setq etage-gef-dx-rechts nil etage-gef-dz-rechts nil)
|
||
(setq etage-gef-dx-links nil etage-gef-dz-links nil)
|
||
(setq *etage-lib-initialized* nil)
|
||
|
||
(setq FESTE_ETAGE_MITTE 1000)
|
||
(setq ETAGE_SCHRAEG_LAENGE 700)
|
||
;; Schwenkwinkel der Ein-/Auslauf-Schraegsektionen: 30 Grad (AS_30/ES_30 +
|
||
;; 30-Grad-Gefaellebogen). War frueher 60. Nur noch im Laengen-/Hoehen-Budget
|
||
;; berechne-winkel-etage (schraeg-cos) verwendet; die fruehere absolute
|
||
;; hz-Platzierung wurde durch Frame-Verkettung (cur-hz) ersetzt.
|
||
(setq ETAGE_HZ_WINKEL 30)
|
||
|
||
;; ============================================================
|
||
;; TEIL 2: BIBLIOTHEK INITIALISIEREN (ETAGE-SPEZIFISCH)
|
||
;; ============================================================
|
||
(defun init-bibliothek-etage ( / temp-obj ks-data ks-ein-pos ks-aus-pos
|
||
gefaelle-blockname as30-blk es30-blk m)
|
||
(if (and *etage-lib-initialized* (not (tblsearch "BLOCK" (ssg-ils-blockname "AS_Element_30_rechts"))))
|
||
(setq *etage-lib-initialized* nil))
|
||
(if *etage-lib-initialized*
|
||
(progn (princ (ssg-text "vfe-bib-bereits-init")) t)
|
||
(progn
|
||
(princ (ssg-text "vfe-bib-initialisiere"))
|
||
|
||
;; Standard-Bogen-Daten laden (bogen-auf/bogen-ab benoetigt)
|
||
(if (not *lib-initialized*)
|
||
(init-bibliothek)
|
||
)
|
||
|
||
;; AS_30_rechts Masse extrahieren (KS_EIN->KS_AUS (dx dy dz) via vf-element-masse)
|
||
(princ (ssg-text "vfe-extrahiere-as30"))
|
||
(setq as30-blk (ensure-block-loaded "AS_Element_30_rechts"))
|
||
(ensure-block-loaded "AS_Element_30_links")
|
||
(setq m (if (tblsearch "BLOCK" as30-blk) (vf-element-masse "AS_Element_30_rechts")))
|
||
(if m
|
||
(progn
|
||
(setq etage-aus-dx (car m) etage-aus-dz (caddr m))
|
||
(princ (ssg-textf "vfe-as30-mass" (list (rtos etage-aus-dx 2 1) (rtos etage-aus-dz 2 1))))
|
||
)
|
||
(progn
|
||
(princ (ssg-text (if (tblsearch "BLOCK" as30-blk) "vfe-warn-ks-fehlt-standard" "vfe-warn-block-as30-fehlt")))
|
||
(setq etage-aus-dx *vfk-etage-as-fallback-dx* etage-aus-dz *vfk-etage-as-fallback-dz*)
|
||
)
|
||
)
|
||
|
||
;; ES_30_rechts Masse extrahieren
|
||
(princ (ssg-text "vfe-extrahiere-es30"))
|
||
(setq es30-blk (ensure-block-loaded "ES_Element_30_rechts"))
|
||
(ensure-block-loaded "ES_Element_30_links")
|
||
(setq m (if (tblsearch "BLOCK" es30-blk) (vf-element-masse "ES_Element_30_rechts")))
|
||
(if m
|
||
(progn
|
||
(setq etage-ein-dx (car m) etage-ein-dz (caddr m))
|
||
(princ (ssg-textf "vfe-es30-mass" (list (rtos etage-ein-dx 2 1) (rtos etage-ein-dz 2 1))))
|
||
)
|
||
(progn
|
||
(princ (ssg-text (if (tblsearch "BLOCK" es30-blk) "vfe-warn-ks-fehlt-standard" "vfe-warn-block-es30-fehlt")))
|
||
(setq etage-ein-dx *vfk-etage-es-fallback-dx* etage-ein-dz *vfk-etage-es-fallback-dz*)
|
||
)
|
||
)
|
||
|
||
;; Gefaellebogen_links_30 Masse extrahieren
|
||
(setq gefaelle-blockname "Gefaellebogen_links_30_R500")
|
||
(princ (ssg-textf "vfe-extrahiere-block-mass" (list gefaelle-blockname)))
|
||
(setq gefaelle-blockname (ensure-block-loaded gefaelle-blockname))
|
||
(setq m (if (tblsearch "BLOCK" gefaelle-blockname) (vf-element-masse "Gefaellebogen_links_30_R500")))
|
||
(if m
|
||
(setq etage-gef-dx-links (car m) etage-gef-dz-links (caddr m))
|
||
(progn
|
||
(princ (ssg-text (if (tblsearch "BLOCK" gefaelle-blockname) "vfe-warn-kein-ks-links" "vfe-warn-block-fehlt-links")))
|
||
(setq etage-gef-dx-links 0.0 etage-gef-dz-links *vfk-etage-gefaellebogen-fallback-dz*)
|
||
)
|
||
)
|
||
(princ (ssg-textf "vfe-gefaellebogen-links-mass" (list (rtos etage-gef-dx-links 2 2) (rtos etage-gef-dz-links 2 2))))
|
||
|
||
;; Gefaellebogen_rechts_30 Masse extrahieren
|
||
(setq gefaelle-blockname "Gefaellebogen_rechts_30_R500")
|
||
(princ (ssg-textf "vfe-extrahiere-block-mass" (list gefaelle-blockname)))
|
||
(setq gefaelle-blockname (ensure-block-loaded gefaelle-blockname))
|
||
(setq m (if (tblsearch "BLOCK" gefaelle-blockname) (vf-element-masse "Gefaellebogen_rechts_30_R500")))
|
||
(if m
|
||
(setq etage-gef-dx-rechts (car m) etage-gef-dz-rechts (caddr m))
|
||
(progn
|
||
(princ (ssg-text (if (tblsearch "BLOCK" gefaelle-blockname) "vfe-warn-kein-ks-rechts" "vfe-warn-block-fehlt-rechts")))
|
||
(setq etage-gef-dx-rechts 0.0 etage-gef-dz-rechts *vfk-etage-gefaellebogen-fallback-dz*)
|
||
)
|
||
)
|
||
(princ (ssg-textf "vfe-gefaellebogen-rechts-mass" (list (rtos etage-gef-dx-rechts 2 2) (rtos etage-gef-dz-rechts 2 2))))
|
||
|
||
(setq *etage-lib-initialized* t)
|
||
(princ (ssg-text "vfe-bib-init-erfolg"))
|
||
t
|
||
)
|
||
)
|
||
)
|
||
|
||
;; ============================================================
|
||
;; TEIL 3: EINFUEGEFUNKTIONEN MIT KOMBINIERTER HZ+VERT ROTATION
|
||
;; ============================================================
|
||
;; Transformationsmatrix: Rz(hz) * Ry(vert)
|
||
;; [ cos(hz)*cos(vert) -sin(hz) cos(hz)*sin(vert) ]
|
||
;; [ sin(hz)*cos(vert) cos(hz) sin(hz)*sin(vert) ]
|
||
;; [ -sin(vert) 0 cos(vert) ]
|
||
|
||
;; HINWEIS: insert-hz-incl-scaled-block wurde entfernt (2026-09-18) - toter Code,
|
||
;; kein Aufrufer im Repo. Die verbleibenden drei insert-hz-*-Funktionen bleiben,
|
||
;; weil sie sich in der Platzierungssemantik (KS_EIN vs. Block-Ursprung) bzw. der
|
||
;; Skalierung+KS+Vertikale-Kombination von den ssg_ks_insert-Primitiven
|
||
;; unterscheiden und ein Ersatz die Geometrie verschoebe (byte-genaue Pruefung).
|
||
|
||
(defun insert-hz-rotated-block-with-ks (blockname startpunkt hz-winkel vert-winkel block-dx block-dz /
|
||
rad-hz rad-vert chz shz cv sv
|
||
matrix block-obj endpunkt)
|
||
(setq rad-hz (* (float hz-winkel) (/ pi 180.0)))
|
||
(setq rad-vert (* (float vert-winkel) (/ pi 180.0)))
|
||
(setq chz (cos rad-hz) shz (sin rad-hz))
|
||
(setq cv (cos rad-vert) sv (sin rad-vert))
|
||
(setq blockname (ensure-block-loaded blockname))
|
||
(if (not (tblsearch "BLOCK" blockname))
|
||
(progn
|
||
(princ (ssg-textf "vfe-block-fehlt-abbruch" (list blockname)))
|
||
(exit)
|
||
)
|
||
)
|
||
(setq block-obj (vla-InsertBlock modelspace
|
||
(vlax-3D-point '(0 0 0)) blockname 1.0 1.0 1.0 0))
|
||
;; Einzelteil auf die eigene Ebene der Blockdefinition legen - wie in den
|
||
;; Zwillingen in ssg_ks_insert.lsp; hier fehlte der Aufruf bisher.
|
||
(ssg-ils-block-auf-ebene block-obj blockname)
|
||
(setq matrix (vf-rot-matrix chz shz cv sv))
|
||
(vla-TransformBy block-obj (vlax-tmatrix matrix))
|
||
(vla-Move block-obj (vlax-3D-point '(0 0 0)) (vlax-3D-point startpunkt))
|
||
(setq endpunkt (list
|
||
(+ (car startpunkt) (+ (* block-dx chz cv) (* block-dz chz sv)))
|
||
(+ (cadr startpunkt) (+ (* block-dx shz cv) (* block-dz shz sv)))
|
||
(+ (caddr startpunkt) (+ (* (- sv) block-dx) (* cv block-dz)))))
|
||
(princ (ssg-textf "vfe-hz-rot-status"
|
||
(list blockname
|
||
(strcat (rtos hz-winkel 2 0) (chr 176))
|
||
(strcat (rtos vert-winkel 2 0) (chr 176))
|
||
(rtos (caddr endpunkt) 2 1))))
|
||
endpunkt
|
||
)
|
||
|
||
(defun insert-hz-rotated-block-by-ks (blockname startpunkt hz-winkel vert-winkel /
|
||
rad-hz rad-vert chz shz cv sv
|
||
temp-obj block-obj ks-data ks-ein ks-aus
|
||
p-ein p-aus p-ein-rot p-aus-rot
|
||
offset ausgang)
|
||
(setq blockname (ensure-block-loaded blockname))
|
||
(if (not (tblsearch "BLOCK" blockname))
|
||
(progn
|
||
(princ (ssg-textf "vfe-block-fehlt-abbruch" (list blockname)))
|
||
(exit)
|
||
)
|
||
)
|
||
(setq rad-hz (* (float hz-winkel) (/ pi 180.0)))
|
||
(setq rad-vert (* (float vert-winkel) (/ pi 180.0)))
|
||
(setq chz (cos rad-hz) shz (sin rad-hz))
|
||
(setq cv (cos rad-vert) sv (sin rad-vert))
|
||
;; KS-Positionen aus Cache (Block bei 0 Grad am Ursprung)
|
||
(setq temp-obj (vla-InsertBlock modelspace (vlax-3D-point '(0 0 0)) blockname 1.0 1.0 1.0 0))
|
||
(setq ks-data (extract-ks-from-block temp-obj))
|
||
(if (not (vlax-erased-p temp-obj)) (vla-Delete temp-obj))
|
||
(setq ks-ein (cadr (assoc "KS_EIN" ks-data)))
|
||
(setq ks-aus (cadr (assoc "KS_AUS" ks-data)))
|
||
;; Block einfuegen und rotieren
|
||
(setq block-obj (vla-InsertBlock modelspace (vlax-3D-point '(0 0 0)) blockname 1.0 1.0 1.0 0))
|
||
;; Einzelteil auf die eigene Ebene der Blockdefinition legen - wie in den
|
||
;; Zwillingen in ssg_ks_insert.lsp; hier fehlte der Aufruf bisher.
|
||
(ssg-ils-block-auf-ebene block-obj blockname)
|
||
(vla-TransformBy block-obj (vlax-tmatrix (vf-rot-matrix chz shz cv sv)))
|
||
(if (and ks-ein ks-aus)
|
||
(progn
|
||
(setq p-ein (car ks-ein))
|
||
(setq p-aus (car ks-aus))
|
||
;; Rotation auf KS-Punkte anwenden: p' = Rz(hz)*Ry(vert) * p
|
||
(setq p-ein-rot
|
||
(list (+ (* chz cv (car p-ein)) (- (* shz (cadr p-ein))) (* chz sv (caddr p-ein)))
|
||
(+ (* shz cv (car p-ein)) (* chz (cadr p-ein)) (* shz sv (caddr p-ein)))
|
||
(+ (* (- sv) (car p-ein)) (* cv (caddr p-ein)))))
|
||
(setq p-aus-rot
|
||
(list (+ (* chz cv (car p-aus)) (- (* shz (cadr p-aus))) (* chz sv (caddr p-aus)))
|
||
(+ (* shz cv (car p-aus)) (* chz (cadr p-aus)) (* shz sv (caddr p-aus)))
|
||
(+ (* (- sv) (car p-aus)) (* cv (caddr p-aus)))))
|
||
;; Block verschieben: rotiertes KS_EIN auf startpunkt
|
||
(vla-Move block-obj
|
||
(vlax-3D-point p-ein-rot)
|
||
(vlax-3D-point startpunkt))
|
||
(setq offset (list (- (car startpunkt) (car p-ein-rot))
|
||
(- (cadr startpunkt) (cadr p-ein-rot))
|
||
(- (caddr startpunkt) (caddr p-ein-rot))))
|
||
(setq ausgang (list (+ (car p-aus-rot) (car offset))
|
||
(+ (cadr p-aus-rot) (cadr offset))
|
||
(+ (caddr p-aus-rot) (caddr offset))))
|
||
(princ (ssg-textf "vfe-hz-rotks-status"
|
||
(list blockname
|
||
(strcat (rtos hz-winkel 2 0) (chr 176))
|
||
(rtos (caddr ausgang) 2 1))))
|
||
ausgang
|
||
)
|
||
(progn
|
||
(princ (ssg-textf "vfe-ks-fehlt-startpunkt" (list blockname)))
|
||
startpunkt
|
||
)
|
||
)
|
||
)
|
||
|
||
(defun insert-hz-scaled-block-by-ks (blockname startpunkt laenge hz-winkel vert-winkel /
|
||
rad-hz rad-vert chz shz cv sv scale
|
||
temp-obj block-obj ks-data ks-ein ks-aus
|
||
p-ein p-aus p-ein-s p-aus-s
|
||
p-ein-rot p-aus-rot offset ausgang)
|
||
(setq blockname (ensure-block-loaded blockname))
|
||
(if (not (tblsearch "BLOCK" blockname))
|
||
(progn
|
||
(princ (ssg-textf "vfe-block-fehlt-abbruch" (list blockname)))
|
||
(exit)
|
||
)
|
||
)
|
||
(setq scale (/ (float laenge) 1000.0))
|
||
(setq rad-hz (* (float hz-winkel) (/ pi 180.0)))
|
||
(setq rad-vert (* (float vert-winkel) (/ pi 180.0)))
|
||
(setq chz (cos rad-hz) shz (sin rad-hz))
|
||
(setq cv (cos rad-vert) sv (sin rad-vert))
|
||
;; KS bei Massstab 1
|
||
(setq temp-obj (vla-InsertBlock modelspace (vlax-3D-point '(0 0 0)) blockname 1.0 1.0 1.0 0))
|
||
(setq ks-data (extract-ks-from-block temp-obj))
|
||
(if (not (vlax-erased-p temp-obj)) (vla-Delete temp-obj))
|
||
(setq ks-ein (cadr (assoc "KS_EIN" ks-data)))
|
||
(setq ks-aus (cadr (assoc "KS_AUS" ks-data)))
|
||
;; Block mit XScale einfuegen und rotieren
|
||
(setq block-obj (vla-InsertBlock modelspace (vlax-3D-point '(0 0 0)) blockname scale 1.0 1.0 0))
|
||
;; Einzelteil auf die eigene Ebene der Blockdefinition legen - wie in den
|
||
;; Zwillingen in ssg_ks_insert.lsp; hier fehlte der Aufruf bisher.
|
||
(ssg-ils-block-auf-ebene block-obj blockname)
|
||
(vla-TransformBy block-obj (vlax-tmatrix (vf-rot-matrix chz shz cv sv)))
|
||
(if (and ks-ein ks-aus)
|
||
(progn
|
||
(setq p-ein (car ks-ein))
|
||
(setq p-aus (car ks-aus))
|
||
;; X-Skalierung anwenden
|
||
(setq p-ein-s (list (* scale (car p-ein)) (cadr p-ein) (caddr p-ein)))
|
||
(setq p-aus-s (list (* scale (car p-aus)) (cadr p-aus) (caddr p-aus)))
|
||
;; Rotation: p' = Rz(hz)*Ry(vert) * p
|
||
(setq p-ein-rot
|
||
(list (+ (* chz cv (car p-ein-s)) (- (* shz (cadr p-ein-s))) (* chz sv (caddr p-ein-s)))
|
||
(+ (* shz cv (car p-ein-s)) (* chz (cadr p-ein-s)) (* shz sv (caddr p-ein-s)))
|
||
(+ (* (- sv) (car p-ein-s)) (* cv (caddr p-ein-s)))))
|
||
(setq p-aus-rot
|
||
(list (+ (* chz cv (car p-aus-s)) (- (* shz (cadr p-aus-s))) (* chz sv (caddr p-aus-s)))
|
||
(+ (* shz cv (car p-aus-s)) (* chz (cadr p-aus-s)) (* shz sv (caddr p-aus-s)))
|
||
(+ (* (- sv) (car p-aus-s)) (* cv (caddr p-aus-s)))))
|
||
;; Block verschieben
|
||
(vla-Move block-obj
|
||
(vlax-3D-point p-ein-rot)
|
||
(vlax-3D-point startpunkt))
|
||
(setq offset (list (- (car startpunkt) (car p-ein-rot))
|
||
(- (cadr startpunkt) (cadr p-ein-rot))
|
||
(- (caddr startpunkt) (caddr p-ein-rot))))
|
||
(setq ausgang (list (+ (car p-aus-rot) (car offset))
|
||
(+ (cadr p-aus-rot) (cadr offset))
|
||
(+ (caddr p-aus-rot) (caddr offset))))
|
||
(princ (ssg-textf "vfe-hz-scaleks-status"
|
||
(list blockname (rtos laenge 2 0)
|
||
(strcat (rtos hz-winkel 2 0) (chr 176))
|
||
(rtos (caddr ausgang) 2 1))))
|
||
ausgang
|
||
)
|
||
(progn
|
||
(princ (ssg-textf "vfe-ks-fehlt-startpunkt" (list blockname)))
|
||
startpunkt
|
||
)
|
||
)
|
||
)
|
||
|
||
;; ============================================================
|
||
;; TEIL 3b: RAND-BUDGET (EINLAUF / AUSLAUF)
|
||
;; ============================================================
|
||
;; Die Etage-Kette wird VON BEIDEN ENDEN ZUR MITTE gerechnet: deltaL/deltaH
|
||
;; sind der Abstand AS-KS_EIN -> ES-KS_AUS (Nutzer-Vorgabe 2026-10-09).
|
||
;; Einlauf (Schritte 1-4) und Auslauf (Schritte 12-15 in
|
||
;; etage-foerderanlage-einfuegen) sind damit FESTE Randstuecke, deren
|
||
;; Verbrauch der Solver exakt kennen muss; frei ist nur der Mittelteil
|
||
;; (L_GF/L_VF).
|
||
;;
|
||
;; Warum nicht mehr schlicht (car (vf-element-masse ...)) wie frueher:
|
||
;; vf-element-masse liefert KS_EIN->KS_AUS im BLOCK-Koordinatensystem. AS und
|
||
;; ES werden aber um (bezugs-hz - ein-ang) gedreht eingebaut - beim
|
||
;; AS_Element_30 ist ein-ang 90 Grad, dadurch landet die Block-Y-Komponente
|
||
;; (vy) auf der Hauptachse und die Block-X-Komponente (vx) quer dazu. Der
|
||
;; alte Code zog vx von deltaL ab und verfehlte die Laenge um rund 990 mm
|
||
;; (realer Bug, Nutzer-Befund 2026-10-09: Soll-X 12179.96, gebaut 13167.59;
|
||
;; AS real 486.10 statt 209.70, ES real 525.29 statt -242.60).
|
||
;;
|
||
;; Die Projektion auf die Hauptachse ist hz-UNABHAENGIG: ein um
|
||
;; theta = (bezugs-hz - ein-ang) gedreht eingebauter Blockvektor (vx vy)
|
||
;; liefert mit d = (theta - hz)
|
||
;; laengs = vx*cos(d) - vy*sin(d)
|
||
;; quer = vx*sin(d) + vy*cos(d)
|
||
;; und d besteht nur aus blockinternen Winkeln. Darum braucht diese Funktion
|
||
;; kein hz und gilt fuer jede Hauptrichtung.
|
||
;;
|
||
;; Rueckgabe-Alist (nil, wenn ein Block fehlt - Aufrufer faellt dann auf die
|
||
;; alte Naeherung zurueck):
|
||
;; "ein-dx"/"ein-dz" : Laengen-/Hoehenverbrauch Einlauf (dz negativ = fallend)
|
||
;; "aus-dx"/"aus-dz" : dito Auslauf
|
||
;; "l-exit" : variable Auslauf-Staustrecke (Schritt 13). NICHT fest
|
||
;; 400 mm, sondern so gewaehlt, dass ES-KS_AUS
|
||
;; querversatzfrei auf der Hauptachse landet - dieselbe
|
||
;; Bedingung, die etage-foerderanlage-einfuegen loest
|
||
;; (dort aus den realen Punkten gemessen). Wer die
|
||
;; Einfuegereihenfolge aendert, muss BEIDE Stellen
|
||
;; nachziehen.
|
||
;; Laengs-/Queranteil eines um d (rad) gedrehten Blockvektors (vx vy) bezogen
|
||
;; auf die Hauptachse. Reine Rechnung, in tests/test_unit.lsp getestet.
|
||
(defun etage-laengs (vx vy d) (- (* vx (cos d)) (* vy (sin d))))
|
||
(defun etage-quer (vx vy d) (+ (* vx (sin d)) (* vy (cos d))))
|
||
|
||
(defun etage-rand-budget (seite / as-blk es-blk gef-blk
|
||
as-i es-i gef-i as-m es-m gef-m
|
||
grad c3 s3 sep stau-ein
|
||
a-as d-as a-es a-gef d-gef
|
||
vx-as vy-as vx-es vy-es vx-gef vy-gef
|
||
d1 d23 d4 d12 d1314 d15
|
||
ein-dx ein-dz quer-fix quer-rate l-exit
|
||
aus-dx aus-dz)
|
||
(if (not *etage-lib-initialized*) (init-bibliothek-etage))
|
||
(setq as-blk (strcat "AS_Element_30_" seite)
|
||
es-blk (strcat "ES_Element_30_" seite))
|
||
;; Gefaellebogen auf der GEGENSEITE des AS-Elements - exakt die Wahl, die
|
||
;; etage-foerderanlage-einfuegen trifft (dort gleicher Ausdruck).
|
||
(setq gef-blk (if (= seite "rechts")
|
||
"Gefaellebogen_links_30_R500"
|
||
"Gefaellebogen_rechts_30_R500"))
|
||
(setq as-i (vf-element-ks-info as-blk)
|
||
es-i (vf-element-ks-info es-blk)
|
||
gef-i (vf-element-ks-info gef-blk)
|
||
as-m (vf-element-masse as-blk)
|
||
es-m (vf-element-masse es-blk)
|
||
gef-m (vf-element-masse gef-blk))
|
||
(if (or (null as-i) (null es-i) (null gef-i)
|
||
(null as-m) (null es-m) (null gef-m))
|
||
nil
|
||
(progn
|
||
(setq grad (/ pi 180.0))
|
||
(setq c3 (cos (* *vfk-gefaelle-winkel* grad))
|
||
s3 (sin (* *vfk-gefaelle-winkel* grad))
|
||
sep *vfk-separator-laenge*
|
||
stau-ein *vfk-etage-stau-ein*)
|
||
;; ein-ang und Schwenk (aus-ang - ein-ang) je Block
|
||
(setq a-as (car as-i) d-as (- (cadr as-i) (car as-i))
|
||
a-es (car es-i)
|
||
a-gef (car gef-i) d-gef (- (cadr gef-i) (car gef-i)))
|
||
(setq vx-as (caddr as-i) vy-as (cadddr as-i)
|
||
vx-es (caddr es-i) vy-es (cadddr es-i)
|
||
vx-gef (caddr gef-i) vy-gef (cadddr gef-i))
|
||
;; Richtungsdifferenzen d = (Einbau-hz - hz) je Bauschritt, in rad.
|
||
;; cur-hz laeuft: hz -> (hz + d-as) ab Schritt 2 -> zurueck auf hz ab
|
||
;; Schritt 5 (der Einlaufbogen dreht um d-gef = -d-as) -> (hz + d-gef)
|
||
;; ab Schritt 13.
|
||
(setq d1 (* (- a-as) grad) ; 1 AS-Element
|
||
d23 (* d-as grad) ; 2 Staustrecke, 3 Separator
|
||
d4 (* (- d-as a-gef) grad) ; 4 Gefaellebogen Anfang
|
||
d12 (* (- a-gef) grad) ; 12 Gefaellebogen Ende
|
||
d1314 (* d-gef grad) ; 13 Staustrecke, 14 Separator
|
||
d15 (* (- d-gef a-es) grad)) ; 15 ES-Element
|
||
;; Fuer Strecken der Laenge L bei 3 Grad Neigung gilt
|
||
;; laengs = L*c3*cos(d), quer = L*c3*sin(d).
|
||
;; --- Einlauf: AS + Staustrecke 400 + Separator + Gefaellebogen
|
||
(setq ein-dx (+ (etage-laengs vx-as vy-as d1)
|
||
(* stau-ein c3 (cos d23))
|
||
(* sep c3 (cos d23))
|
||
(etage-laengs vx-gef vy-gef d4)))
|
||
(setq ein-dz (+ (caddr as-m)
|
||
(- (* stau-ein s3))
|
||
(- (* sep s3))
|
||
(caddr gef-m)))
|
||
;; --- Auslauf: Gefaellebogen + L-exit + Separator + ES
|
||
;; L-exit aus der Quer-Bilanz: alle Querbeitraege muessen sich zu 0
|
||
;; addieren, damit ES-KS_AUS auf der Hauptachse landet. Die Schritte
|
||
;; 5-11 laufen auf der Hauptachse und tragen NICHTS zu quer bei - darum
|
||
;; ist L-exit von L_GF/L_VF unabhaengig und hier schon bestimmbar.
|
||
(setq quer-fix (+ (etage-quer vx-as vy-as d1)
|
||
(* stau-ein c3 (sin d23))
|
||
(* sep c3 (sin d23))
|
||
(etage-quer vx-gef vy-gef d4)
|
||
(etage-quer vx-gef vy-gef d12)
|
||
(* sep c3 (sin d1314))
|
||
(etage-quer vx-es vy-es d15)))
|
||
(setq quer-rate (* c3 (sin d1314)))
|
||
(setq l-exit (if (> (abs quer-rate) 1e-6)
|
||
(/ (- quer-fix) quer-rate)
|
||
*vfk-etage-stau-ein*))
|
||
(if (< l-exit *vfk-etage-auslauf-min-clamp*)
|
||
(setq l-exit *vfk-etage-auslauf-min-clamp*))
|
||
(setq aus-dx (+ (etage-laengs vx-gef vy-gef d12)
|
||
(* l-exit c3 (cos d1314))
|
||
(* sep c3 (cos d1314))
|
||
(etage-laengs vx-es vy-es d15)))
|
||
(setq aus-dz (+ (caddr gef-m)
|
||
(- (* l-exit s3))
|
||
(- (* sep s3))
|
||
(caddr es-m)))
|
||
(list (cons "ein-dx" ein-dx) (cons "ein-dz" ein-dz)
|
||
(cons "aus-dx" aus-dx) (cons "aus-dz" aus-dz)
|
||
(cons "l-exit" l-exit))
|
||
)
|
||
)
|
||
)
|
||
|
||
;; ============================================================
|
||
;; TEIL 4: WINKELBERECHNUNG (ETAGE)
|
||
;; ============================================================
|
||
(defun berechne-winkel-etage (deltaL deltaH richtung seite /
|
||
winkel-list ergebnis-liste A B cos3 sin3
|
||
bogen-x1 bogen-z1 bogen-x2 bogen-z2
|
||
abs-dz-AUS abs-dz-EIN abs-dz-GEF
|
||
L_GF L_VF cosα sinα
|
||
winkel-eff cosEff sinEff rad5 rad7
|
||
winkel mass1 mass2 gueltig
|
||
best-winkel best-L_GF best-L_VF
|
||
feste-gesamt-cos feste-gesamt-sin
|
||
schraeg-hz-rad schraeg-cos schraeg-z
|
||
budget rand-dx rand-dz)
|
||
|
||
(if (not *etage-lib-initialized*)
|
||
(progn
|
||
(alert (ssg-text "vfe-alert-bib-nicht-init"))
|
||
(exit)
|
||
)
|
||
)
|
||
|
||
(setq abs-dz-AUS (abs etage-aus-dz)
|
||
abs-dz-EIN (abs etage-ein-dz)
|
||
abs-dz-GEF (abs etage-gef-dz))
|
||
|
||
;; Rand-Budget (Einlauf + Auslauf) exakt so, wie die Kette gebaut wird.
|
||
;; Faellt NUR zurueck, wenn ein Block fehlt - dann greift die alte
|
||
;; Naeherung, damit das Verhalten ohne Bibliothek unveraendert bleibt.
|
||
(setq budget (etage-rand-budget seite))
|
||
(if budget
|
||
(progn
|
||
(setq rand-dx (+ (cdr (assoc "ein-dx" budget)) (cdr (assoc "aus-dx" budget))))
|
||
;; dz der Randstuecke ist negativ (fallend); das Budget zaehlt Betraege.
|
||
(setq rand-dz (- (+ (cdr (assoc "ein-dz" budget)) (cdr (assoc "aus-dz" budget)))))
|
||
(princ (ssg-textf "vfe-rand-budget"
|
||
(list (rtos (cdr (assoc "ein-dx" budget)) 2 2)
|
||
(rtos (cdr (assoc "aus-dx" budget)) 2 2)
|
||
(rtos (cdr (assoc "l-exit" budget)) 2 1))))
|
||
)
|
||
(progn
|
||
(princ (ssg-text "vfe-rand-budget-fallback"))
|
||
(setq rand-dx nil rand-dz nil)
|
||
)
|
||
)
|
||
|
||
(setq winkel-list *vfk-bogen-winkel*)
|
||
(setq ergebnis-liste '())
|
||
(setq cos3 (cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))
|
||
sin3 (sin (* *vfk-gefaelle-winkel* (/ pi 180.0))))
|
||
|
||
(setq feste-gesamt-cos (* FESTE_ETAGE_MITTE cos3))
|
||
(setq feste-gesamt-sin (* FESTE_ETAGE_MITTE sin3))
|
||
(setq schraeg-hz-rad (* (float ETAGE_HZ_WINKEL) (/ pi 180.0)))
|
||
(setq schraeg-cos (* (cos schraeg-hz-rad) cos3))
|
||
|
||
(princ "\n\n=========================================")
|
||
(princ (ssg-text "vfe-berechnung-header"))
|
||
(princ "\n=========================================")
|
||
(princ (ssg-textf "vfe-delta-info" (list (rtos deltaL 2 2) (rtos deltaH 2 2) richtung)))
|
||
|
||
(foreach winkel winkel-list
|
||
(if (= richtung "Auf")
|
||
(progn
|
||
(setq mass1 (get-bogen-mass bogen-auf winkel))
|
||
(setq mass2 (get-bogen-mass bogen-ab winkel))
|
||
)
|
||
(progn
|
||
(setq mass1 (get-bogen-mass bogen-ab winkel))
|
||
(setq mass2 (get-bogen-mass bogen-auf winkel))
|
||
)
|
||
)
|
||
(if (or (null mass1) (null mass2))
|
||
(progn
|
||
(princ (ssg-textf "vfe-bogen-nicht-vorhanden" (list (strcat (itoa winkel) (chr 176)))))
|
||
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
|
||
)
|
||
(progn
|
||
(setq rad5 (* *vfk-gefaelle-winkel* (/ pi 180.0)))
|
||
(setq rad7 (* (float (if (= richtung "Auf") (- *vfk-gefaelle-winkel* winkel) (+ winkel *vfk-gefaelle-winkel*)))
|
||
(/ pi 180.0)))
|
||
(setq bogen-x1 (+ (* (car mass1) (cos rad5)) (* (caddr mass1) (sin rad5))))
|
||
(setq bogen-z1 (+ (* (- (car mass1)) (sin rad5)) (* (caddr mass1) (cos rad5))))
|
||
(setq bogen-x2 (+ (* (car mass2) (cos rad7)) (* (caddr mass2) (sin rad7))))
|
||
(setq bogen-z2 (+ (* (- (car mass2)) (sin rad7)) (* (caddr mass2) (cos rad7))))
|
||
(setq cosα (cos (* winkel (/ pi 180.0)))
|
||
sinα (sin (* winkel (/ pi 180.0))))
|
||
(setq winkel-eff (if (= richtung "Auf") (- winkel 3) (+ winkel 3)))
|
||
(setq cosEff (cos (* winkel-eff (/ pi 180.0)))
|
||
sinEff (sin (* winkel-eff (/ pi 180.0))))
|
||
;; A: horizontaler Rest nach Abzug aller festen Teile.
|
||
;; feste-gesamt-cos/-sin (FESTE_ETAGE_MITTE=1000 = Umlenkstation+
|
||
;; Motorstation KOMBINIERT, vf_konstanten.lsp) tritt genau EINMAL in
|
||
;; der Kette auf (die eine mittlere Sektion zwischen den beiden
|
||
;; Vertikalboegen, Schritte 6+10 in etage-foerderanlage-einfuegen).
|
||
;; Der fruehere Faktor 2.0 reservierte sie doppelt - behoben
|
||
;; 2026-10-08 (52.34 mm = FESTE_ETAGE_MITTE*sin(3 Grad)).
|
||
;;
|
||
;; rand-dx/rand-dz kommen aus etage-rand-budget und ersetzen die
|
||
;; frueheren Naeherungen (etage-aus-dx + etage-ein-dx +
|
||
;; 2*ETAGE_SCHRAEG_LAENGE*schraeg-cos + 2*etage-gef-dx). Die waren in
|
||
;; der Laenge um rund 990 mm daneben, weil sie die BLOCK-X-Komponente
|
||
;; von AS/ES verwendeten statt deren Anteil auf der Hauptachse, und
|
||
;; die Auslauf-Staustrecke fest mit 400 mm statt variabel ansetzten
|
||
;; (siehe Kommentar bei etage-rand-budget).
|
||
(setq schraeg-z (* ETAGE_SCHRAEG_LAENGE sin3))
|
||
(if rand-dx
|
||
(setq A (- deltaL rand-dx bogen-x1 bogen-x2 feste-gesamt-cos))
|
||
(setq A (- deltaL
|
||
etage-aus-dx
|
||
etage-ein-dx
|
||
(* 2.0 ETAGE_SCHRAEG_LAENGE schraeg-cos)
|
||
(* 2.0 etage-gef-dx)
|
||
bogen-x1
|
||
bogen-x2
|
||
feste-gesamt-cos))
|
||
)
|
||
;; B: vertikaler Rest (Vorzeichen analog Standard)
|
||
(if rand-dz
|
||
(if (= richtung "Auf")
|
||
(setq B (+ deltaH rand-dz feste-gesamt-sin
|
||
(- bogen-z1) (- bogen-z2)))
|
||
(setq B (+ (- deltaH rand-dz feste-gesamt-sin)
|
||
bogen-z1 bogen-z2))
|
||
)
|
||
(if (= richtung "Auf")
|
||
(setq B (+ deltaH
|
||
abs-dz-AUS
|
||
abs-dz-EIN
|
||
(* 2.0 schraeg-z)
|
||
(* 2.0 abs-dz-GEF)
|
||
(- bogen-z1)
|
||
(- bogen-z2)
|
||
feste-gesamt-sin))
|
||
(setq B (+ (- deltaH
|
||
abs-dz-AUS
|
||
abs-dz-EIN
|
||
(* 2.0 schraeg-z)
|
||
(* 2.0 abs-dz-GEF)
|
||
feste-gesamt-sin)
|
||
bogen-z1
|
||
bogen-z2))
|
||
)
|
||
)
|
||
(setq ergebnis-liste
|
||
(cons (vf-winkel-solve winkel richtung A B sinα cosEff sinEff sin3 cos3)
|
||
ergebnis-liste))
|
||
)
|
||
)
|
||
)
|
||
(setq ergebnis-liste (reverse ergebnis-liste))
|
||
|
||
(princ "\n\n=================================================================================")
|
||
(princ (ssg-text "vfe-ergebnistabelle-header"))
|
||
(princ "\n=================================================================================")
|
||
(princ (ssg-text "vfe-tabelle-spalten"))
|
||
(princ "\n=================================================================================")
|
||
|
||
(setq best-winkel nil best-L_GF nil best-L_VF nil)
|
||
(foreach item ergebnis-liste
|
||
(setq winkel (car item)
|
||
L_GF (cadr item)
|
||
L_VF (caddr item)
|
||
gueltig (cadddr item))
|
||
(if (and (numberp L_GF) (numberp L_VF))
|
||
(progn
|
||
(princ (ssg-textf "vfe-tabelle-zeile"
|
||
(list (strcat (itoa winkel) (chr 176)) (fmt L_GF) (fmt L_VF))))
|
||
(if gueltig
|
||
(progn
|
||
(princ (ssg-text "vfe-status-gueltig"))
|
||
(if (or (null best-winkel) (< winkel best-winkel))
|
||
(setq best-winkel winkel best-L_GF L_GF best-L_VF L_VF)
|
||
)
|
||
)
|
||
(princ (ssg-text "vfe-status-ungueltig"))
|
||
)
|
||
)
|
||
(princ (ssg-textf "vfe-tabelle-zeile-fehler" (list (strcat (itoa winkel) (chr 176)))))
|
||
)
|
||
)
|
||
(princ "\n=================================================================================")
|
||
(if best-winkel
|
||
(princ (ssg-textf "vfe-empfohlener-winkel" (list (strcat (itoa best-winkel) (chr 176)))))
|
||
(princ (ssg-text "vfe-kein-winkel-gefunden"))
|
||
)
|
||
(list best-winkel best-L_GF best-L_VF ergebnis-liste)
|
||
)
|
||
|
||
;; ============================================================
|
||
;; TEIL 5: BERECHNE-WRAPPER (Schnittstelle fuer Registry)
|
||
;; ============================================================
|
||
;; Initialisiert Etage-Bibliothek, aktiviert Gefaellebogen-Masse
|
||
;; passend zur gewaehlten Seite (benoetigt fuer Geometrieberechnung).
|
||
(defun berechne-etage (deltaL deltaH richtung seite)
|
||
(init-bibliothek-etage)
|
||
(if (= seite "rechts")
|
||
(progn
|
||
(setq etage-gef-dx etage-gef-dx-rechts)
|
||
(setq etage-gef-dz etage-gef-dz-rechts))
|
||
(progn
|
||
(setq etage-gef-dx etage-gef-dx-links)
|
||
(setq etage-gef-dz etage-gef-dz-links))
|
||
)
|
||
(princ (ssg-textf "vfe-gefaellebogen-seite-dx" (list seite (rtos etage-gef-dx 2 2))))
|
||
(berechne-winkel-etage deltaL deltaH richtung seite)
|
||
)
|
||
|
||
;; ============================================================
|
||
;; TEIL 6: EINFUEGEN (15 Schritte, ohne VF_*-Block-Erstellung)
|
||
;; ============================================================
|
||
;; Gibt endpunkt zurueck.
|
||
;; VF_*-Block-Erstellung erfolgt zentral im Dispatcher (vf_core.lsp).
|
||
;; hz: Richtung der Hauptlinie (Default 0 = horizontal/X). AS-KS_EIN und
|
||
;; ES-KS_AUS liegen koaxial auf dieser Linie; die Kette wird frame-verkettet
|
||
;; aufgebaut (cur-hz laeuft durch, Boegen drehen um ihren gemessenen Schwenk).
|
||
(defun etage-foerderanlage-einfuegen (deltaL deltaH richtung
|
||
best-winkel L_GF1 L_GF2 L_VF
|
||
startpunkt seite hz
|
||
/ aktueller-punkt bogen-name endpunkt
|
||
bogen-mass bogen-dx bogen-dz
|
||
as-block es-block gefaelle-blockname
|
||
as-hz as-ksinfo
|
||
cur-hz bogen-info es-info
|
||
perp-sin perp-cos p2b-perp es-place-rad
|
||
es-wx es-wy es-perp perp-rate L-exit)
|
||
(setq aktueller-punkt startpunkt)
|
||
;; hz = Richtung der Hauptlinie (AS-KS_EIN / ES-KS_AUS liegen darauf).
|
||
;; Default 0 (horizontal), falls der Aufrufer nichts uebergibt.
|
||
(if (null hz) (setq hz 0.0))
|
||
(setq hz (float hz))
|
||
(setq as-block (strcat "AS_Element_30_" seite))
|
||
(setq es-block (strcat "ES_Element_30_" seite))
|
||
;; Gefaellebogen auf der GEGENSEITE des AS-Elements (Nutzer-Vorgabe
|
||
;; 2026-07-21): AS links -> Boegen rechts, AS rechts -> Boegen links.
|
||
;; Beide Etage-Boegen nutzen dieselbe (Gegen-)Seite.
|
||
(setq gefaelle-blockname
|
||
(if (= seite "rechts")
|
||
"Gefaellebogen_links_30_R500"
|
||
"Gefaellebogen_rechts_30_R500"
|
||
))
|
||
;; Sentinel: Bibliothek neu initialisieren wenn Bloecke fehlen
|
||
(if (and *etage-lib-initialized* (not (tblsearch "BLOCK" (ssg-ils-blockname "AS_Element_30_rechts"))))
|
||
(setq *etage-lib-initialized* nil))
|
||
(if (not *etage-lib-initialized*) (init-bibliothek-etage))
|
||
|
||
;; 1. AS_30 - KS_EIN koaxial zur Hauptlinie (hz) ausrichten.
|
||
;; vf-element-ks-info liefert (ein-ang aus-ang vx vy): ein-ang/aus-ang sind die
|
||
;; Ebenen-Winkel der KS_EIN- bzw. KS_AUS-Achse IM BLOCK (bei Einbau-Rotation 0).
|
||
;; Platzierungs-hz = (hz - ein-ang) dreht die KS_EIN-Achse von ein-ang auf hz
|
||
;; -> KS_EIN liegt koaxial auf der Hauptlinie (Abnahmekriterium).
|
||
(princ (ssg-textf "vfe-step1-as30" (list as-block)))
|
||
(setq as-ksinfo (vf-element-ks-info as-block))
|
||
(setq aktueller-punkt
|
||
(insert-block-by-ks as-block aktueller-punkt (- hz (car as-ksinfo))))
|
||
;; KS_AUS-Richtung (absolut) = hz + Schwenk (aus-ang - ein-ang); die folgende
|
||
;; GF laeuft in dieser Richtung weiter (Frame-Verkettung wie im Linienzug).
|
||
(setq as-hz (+ hz (- (cadr as-ksinfo) (car as-ksinfo))))
|
||
|
||
;; 2. Staustrecke (fest, folgt der AS-Richtung as-hz, 3 Grad vert, KS_EIN).
|
||
;; Dieselbe Konstante bilanziert etage-rand-budget als Einlauf-Anteil.
|
||
(princ (ssg-textf "vfe-step2" (list (rtos as-hz 2 1))))
|
||
(setq aktueller-punkt
|
||
(insert-hz-scaled-block-by-ks "Staustrecke_SP_1000_mm" aktueller-punkt
|
||
*vfk-etage-stau-ein* as-hz *vfk-gefaelle-winkel*))
|
||
|
||
;; 3. Separator (folgt der AS-Richtung as-hz, 3 Grad vert)
|
||
(princ (ssg-textf "vfe-step3" (list (rtos as-hz 2 1))))
|
||
(setq aktueller-punkt
|
||
(insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
|
||
as-hz *vfk-gefaelle-winkel* *vfk-separator-laenge* 0))
|
||
|
||
;; Ab hier laufende Richtung cur-hz mitfuehren (frame-verkettet). Start =
|
||
;; KS_AUS-Richtung des AS (as-hz). Jeder Gefaellebogen dreht cur-hz um seinen
|
||
;; gemessenen Schwenk (Vorzeichen/Seite kommen aus dem Block).
|
||
(setq cur-hz as-hz)
|
||
|
||
;; 4. Gefaellebogen Anfang (verkettet: KS_EIN auf cur-hz, dann cur-hz drehen)
|
||
(setq bogen-info (vf-element-ks-info gefaelle-blockname))
|
||
(princ (ssg-textf "vfe-step4" (list gefaelle-blockname (rtos cur-hz 2 1))))
|
||
(setq aktueller-punkt
|
||
(insert-hz-rotated-block-by-ks gefaelle-blockname aktueller-punkt
|
||
(- cur-hz (car bogen-info)) 0))
|
||
(setq cur-hz (+ cur-hz (- (cadr bogen-info) (car bogen-info))))
|
||
|
||
;; 5. L_GF1 (3 Grad geneigt)
|
||
(if (> L_GF1 0.1)
|
||
(progn
|
||
(princ (ssg-textf "vfe-step5-strecke" (list (rtos L_GF1 2 2))))
|
||
(setq aktueller-punkt
|
||
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF1 *vfk-gefaelle-winkel* cur-hz))
|
||
)
|
||
(princ (ssg-text "vfe-step5-skip"))
|
||
)
|
||
|
||
;; 6. Umlenkstation (3 Grad geneigt)
|
||
(princ (ssg-text "vfe-step6"))
|
||
(setq aktueller-punkt
|
||
(insert-rotated-block-with-ks (strcat "Vario_Umlenkstation_500mm_" (vf-motorseite-aktuell)) aktueller-punkt *vfk-gefaelle-winkel* *vfk-stations-laenge* 0 cur-hz))
|
||
|
||
;; 7. 1. Vertikalbogen (3 Grad geneigt)
|
||
(if (= richtung "Auf")
|
||
(progn
|
||
(setq bogen-name (strcat "Vario_Bogen_auf_" (itoa best-winkel) "_TEF_rechts"))
|
||
(setq bogen-mass (get-bogen-mass bogen-auf best-winkel))
|
||
)
|
||
(progn
|
||
(setq bogen-name (strcat "Vario_Bogen_ab_" (itoa best-winkel) "_TEF_rechts"))
|
||
(setq bogen-mass (get-bogen-mass bogen-ab best-winkel))
|
||
)
|
||
)
|
||
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
|
||
(princ (ssg-textf "vfe-step7" (list bogen-name)))
|
||
(setq aktueller-punkt
|
||
(insert-rotated-block-with-ks bogen-name aktueller-punkt *vfk-gefaelle-winkel* bogen-dx bogen-dz cur-hz))
|
||
|
||
;; 8. Variable Strecke L_VF
|
||
(if (> L_VF 0.1)
|
||
(progn
|
||
(if (= richtung "Auf")
|
||
(progn
|
||
(princ (ssg-textf "vfe-step8-auf" (list (itoa (- (- best-winkel 3))) (rtos L_VF 2 2))))
|
||
(setq aktueller-punkt
|
||
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
|
||
L_VF (- (- best-winkel 3)) cur-hz))
|
||
)
|
||
(progn
|
||
(princ (ssg-textf "vfe-step8-ab" (list (itoa (+ best-winkel 3)) (rtos L_VF 2 2))))
|
||
(setq aktueller-punkt
|
||
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
|
||
L_VF (+ best-winkel 3) cur-hz))
|
||
)
|
||
)
|
||
)
|
||
(princ (ssg-text "vfe-step8-skip"))
|
||
)
|
||
|
||
;; 9. 2. Vertikalbogen
|
||
(if (= richtung "Auf")
|
||
(progn
|
||
(setq bogen-name (strcat "Vario_Bogen_ab_" (itoa best-winkel) "_TEF_rechts"))
|
||
(setq bogen-mass (get-bogen-mass bogen-ab best-winkel))
|
||
)
|
||
(progn
|
||
(setq bogen-name (strcat "Vario_Bogen_auf_" (itoa best-winkel) "_TEF_rechts"))
|
||
(setq bogen-mass (get-bogen-mass bogen-auf best-winkel))
|
||
)
|
||
)
|
||
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
|
||
(if (= richtung "Auf")
|
||
(progn
|
||
(princ (ssg-textf "vfe-step9-bogen" (list bogen-name (itoa (- 3 best-winkel)))))
|
||
(setq aktueller-punkt
|
||
(insert-rotated-block-with-ks bogen-name aktueller-punkt
|
||
(- 3 best-winkel) bogen-dx bogen-dz cur-hz))
|
||
)
|
||
(progn
|
||
(princ (ssg-textf "vfe-step9-bogen" (list bogen-name (itoa (+ best-winkel 3)))))
|
||
(setq aktueller-punkt
|
||
(insert-rotated-block-with-ks bogen-name aktueller-punkt
|
||
(+ best-winkel 3) bogen-dx bogen-dz cur-hz))
|
||
)
|
||
)
|
||
|
||
;; 10. Motorstation (3 Grad geneigt)
|
||
(princ (ssg-text "vfe-step10"))
|
||
(setq aktueller-punkt
|
||
(insert-rotated-block-with-ks (strcat "Vario_Motorstation_500mm_" (vf-motorseite-aktuell)) aktueller-punkt *vfk-gefaelle-winkel* *vfk-stations-laenge* 0 cur-hz))
|
||
|
||
;; 11. L_GF2 (3 Grad geneigt)
|
||
(if (> L_GF2 0.1)
|
||
(progn
|
||
(princ (ssg-textf "vfe-step11-gf2" (list (rtos L_GF2 2 2))))
|
||
(setq aktueller-punkt
|
||
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF2 *vfk-gefaelle-winkel* cur-hz))
|
||
)
|
||
(princ (ssg-text "vfe-step11-skip"))
|
||
)
|
||
|
||
;; 12. Gefaellebogen Ende (verkettet: KS_EIN auf cur-hz, dann cur-hz drehen)
|
||
(setq bogen-info (vf-element-ks-info gefaelle-blockname))
|
||
(princ (ssg-textf "vfe-step12" (list gefaelle-blockname (rtos cur-hz 2 1))))
|
||
(setq aktueller-punkt
|
||
(insert-block-by-ks gefaelle-blockname aktueller-punkt (- cur-hz (car bogen-info))))
|
||
(setq cur-hz (+ cur-hz (- (cadr bogen-info) (car bogen-info))))
|
||
|
||
;; --- Auslauf RUECKWAERTS vom ES gerechnet (analog Linienzug Modus 2):
|
||
;; die Auslauf-Staustrecke wird variabel, sodass das ES-KS_AUS OHNE
|
||
;; seitlichen Versatz auf der Hauptachse landet. Reihenfolge (Nutzer-Vorgabe):
|
||
;; Staustrecke -> Separator -> ES.
|
||
(setq es-info (vf-element-ks-info es-block))
|
||
;; perp = Einheitsvektor senkrecht zur Hauptlinie hz: (-sin hz, cos hz)
|
||
(setq perp-sin (sin (* hz (/ pi 180.0)))
|
||
perp-cos (cos (* hz (/ pi 180.0))))
|
||
;; seitliche Lage nach Bogen2 (perp-Abstand des aktuellen Punkts zu startpunkt)
|
||
(setq p2b-perp (+ (* (- (car aktueller-punkt) (car startpunkt)) (- perp-sin))
|
||
(* (- (cadr aktueller-punkt) (cadr startpunkt)) perp-cos)))
|
||
;; ES-Eigenversatz KS_EIN->KS_AUS (Block vx/vy) in Auslaufrichtung gedreht -> perp
|
||
(setq es-place-rad (* (- cur-hz (car es-info)) (/ pi 180.0)))
|
||
(setq es-wx (- (* (caddr es-info) (cos es-place-rad)) (* (cadddr es-info) (sin es-place-rad))))
|
||
(setq es-wy (+ (* (caddr es-info) (sin es-place-rad)) (* (cadddr es-info) (cos es-place-rad))))
|
||
(setq es-perp (+ (* es-wx (- perp-sin)) (* es-wy perp-cos)))
|
||
;; perp-Auslenkung pro Laengeneinheit bei cur-hz (Neigung 3 Grad)
|
||
(setq perp-rate (* (cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))
|
||
(sin (* (- cur-hz hz) (/ pi 180.0)))))
|
||
;; Loesen: p2b-perp + (L_exit + 300)*perp-rate + es-perp = 0
|
||
;; ACHTUNG: etage-rand-budget loest dieselbe Bedingung rein analytisch
|
||
;; vorab, damit der Solver den Auslauf korrekt bilanziert. Hier wird
|
||
;; p2b-perp aus den REALEN Punkten gemessen (numerisch genauer); beide
|
||
;; Wege muessen denselben Wert liefern. Wer die Schrittfolge oder die
|
||
;; Quer-Bilanz aendert, zieht BEIDE Stellen nach.
|
||
(setq L-exit
|
||
(if (> (abs perp-rate) 1e-6)
|
||
(- (/ (- (+ p2b-perp es-perp)) perp-rate) *vfk-separator-laenge*)
|
||
*vfk-etage-stau-ein*))
|
||
(if (< L-exit *vfk-etage-auslauf-min-clamp*) (setq L-exit *vfk-etage-auslauf-min-clamp*)) ; Schutz gegen negative/zu kurze GF
|
||
|
||
;; 13. Auslauf-Staustrecke (variabel, folgt cur-hz, 3 Grad vert, KS_EIN)
|
||
(princ (ssg-textf "vfe-step13" (list (rtos L-exit 2 1) (rtos cur-hz 2 1))))
|
||
(setq aktueller-punkt
|
||
(insert-hz-scaled-block-by-ks "Staustrecke_SP_1000_mm" aktueller-punkt
|
||
L-exit cur-hz *vfk-gefaelle-winkel*))
|
||
|
||
;; 14. Separator (verkettet, folgt cur-hz, 3 Grad vert)
|
||
(princ (ssg-textf "vfe-step14" (list (rtos cur-hz 2 1))))
|
||
(setq aktueller-punkt
|
||
(insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
|
||
cur-hz *vfk-gefaelle-winkel* *vfk-separator-laenge* 0))
|
||
|
||
;; 15. ES_30 (verkettet: KS_EIN auf cur-hz; KS_AUS auf der Hauptlinie)
|
||
(princ (ssg-textf "vfe-step15" (list es-block (rtos cur-hz 2 1))))
|
||
(setq endpunkt
|
||
(insert-block-by-ks es-block aktueller-punkt (- cur-hz (car es-info))))
|
||
|
||
(princ "\n\n=========================================")
|
||
(princ (ssg-text "vfe-eingefuegt"))
|
||
endpunkt
|
||
)
|
||
|
||
;; ============================================================
|
||
;; TEIL 7: DCL-DIALOG (Neuanlage + Edit)
|
||
;; ============================================================
|
||
;; Der Etage-Typ nutzt dieselben Dialoge wie der Standard-Typ
|
||
;; (vfs-dialog-eingabe-basis / vfs-dialog-winkel-verteilung in vf_standard.lsp).
|
||
;; Unterschiede zum Standard-Ablauf: Berechnung ueber berechne-etage (braucht
|
||
;; seite), Einfuegung ueber etage-foerderanlage-einfuegen, KEINE horizontale
|
||
;; Zwischenstrecke (Winkel-Sentinel 0). XDATA-Marker "etage".
|
||
|
||
;; Duenner Wrapper auf den gemeinsamen vf-dialog-berechnen-einfuegen (vf_core).
|
||
;; Etage = OHNE horizontale Zwischenstrecke (horizontal-p nil).
|
||
(defun vfe-etage-dialog-berechnen-einfuegen (vf-nummer deltaL deltaH richtung startpunkt hz seite
|
||
winkel-prefill geruest-einzelmodul geruest-typ)
|
||
(vf-dialog-berechnen-einfuegen "etage" vf-nummer deltaL deltaH richtung startpunkt hz seite
|
||
winkel-prefill geruest-einzelmodul geruest-typ nil))
|
||
|
||
;; Neuanlage (Menue/Konsole -> Dialog): Startpunkt (X/Y) picken, Basis-Dialog,
|
||
;; dann gemeinsame Berechnung/Winkel-Dialog/Einfuegung.
|
||
;; Analog vfs-standard-dialog-ablauf in vf_standard.lsp.
|
||
(defun vfe-etage-dialog-ablauf (vf-nummer)
|
||
(vf-dialog-ablauf "etage" vf-nummer nil))
|
||
|
||
;; Edit eines bestehenden Etage-VF-Blocks (VF_n mit SSG_VF_EDIT-XDATA "etage").
|
||
;; Wird von c:VARIOFOERDERER_EDIT (vf_standard.lsp) per Typ-Dispatch gerufen und
|
||
;; laeuft innerhalb der dort geoeffneten ssg-start-Sitzung. Liest Parameter aus
|
||
;; XDATA/Attributen, zeigt sie vorbelegt und baut bei OK am selben Startpunkt neu
|
||
;; auf. Analog dem Standard-Edit-Body in c:VARIOFOERDERER_EDIT.
|
||
(defun vfe-edit-ent (ent / ed bname startpunkt attribs xd
|
||
deltaL deltaH richtung z-start hz seite dim
|
||
eingabe vf-nummer best-winkel-attr L_GF_m-teile
|
||
prefill-basis prefill-winkel basis-lesung
|
||
geruest-einzelmodul geruest-typ motorseite)
|
||
(setq ed (entget ent))
|
||
(setq bname (cdr (assoc 2 ed)))
|
||
(setq xd (vfs-xdata-lesen ent))
|
||
;; Bau-Parameter + prefill-basis lesen (gemeinsame Leseroutine in
|
||
;; vf_standard.lsp, siehe vfs-edit-basis-lesen). Etage-Defaults: deltaH "0",
|
||
;; Seite "links".
|
||
(setq basis-lesung (vfs-edit-basis-lesen ent xd "0" "links"))
|
||
(setq prefill-basis (cdr (assoc "prefill-basis" basis-lesung)))
|
||
(setq attribs (cdr (assoc "attribs" basis-lesung)))
|
||
(setq startpunkt (cdr (assoc "startpunkt" basis-lesung)))
|
||
(setq hz (cdr (assoc "hz" basis-lesung)))
|
||
(setq z-start (cdr (assoc "z-start" basis-lesung)))
|
||
|
||
(setq eingabe (vfs-dialog-eingabe-basis prefill-basis))
|
||
(if (null eingabe)
|
||
(princ (ssg-text "vfc-vorgang-abgebrochen"))
|
||
(progn
|
||
(vf-basis-eingabe-entpacken eingabe)
|
||
(setq startpunkt (list (car startpunkt) (cadr startpunkt) z-start))
|
||
|
||
(setq best-winkel-attr (atoi (cond ((cdr (assoc "VF_WINKEL" attribs))) ("0"))))
|
||
(setq L_GF_m-teile (ssg-cfg-split-comma (cond ((cdr (assoc "L_GF_m" attribs))) ("0.0,0.0"))))
|
||
(setq prefill-winkel
|
||
(list (cons "winkel" best-winkel-attr)
|
||
(cons "verteilung-idx" "3")
|
||
(cons "lgf1" (* 1000.0 (atof (car L_GF_m-teile))))))
|
||
|
||
(setq *ssg-ils-dim* dim)
|
||
(setq *vf-motorseite* motorseite)
|
||
(entdel ent)
|
||
(setq vf-nummer (vf-next-number))
|
||
(vfe-etage-dialog-berechnen-einfuegen vf-nummer deltaL deltaH richtung
|
||
startpunkt hz seite prefill-winkel geruest-einzelmodul geruest-typ)
|
||
(setq *ssg-ils-dim* nil)
|
||
(setq *vf-motorseite* nil)
|
||
(princ (ssg-textf "vfs-edit-neu-aufgebaut" (list bname)))
|
||
)
|
||
)
|
||
)
|
||
|
||
;; ============================================================
|
||
;; REGISTRIERUNG
|
||
;; ============================================================
|
||
(vf-typ-registrieren
|
||
"etage"
|
||
'berechne-etage
|
||
'etage-foerderanlage-einfuegen
|
||
(ssg-text "vfc-typ-etage-beschreibung"))
|
||
|
||
(princ)
|