fix: Etage-Solver bilanziert Ein-/Auslauf auf der Hauptachse statt im Blocksystem

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>
This commit is contained in:
2026-10-09 18:01:22 +02:00
parent b7b1df25b9
commit 3116e639eb
5 changed files with 270 additions and 33 deletions
+220 -33
View File
@@ -310,10 +310,145 @@
)
)
;; ============================================================
;; 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 /
(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
@@ -322,7 +457,8 @@
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)
schraeg-hz-rad schraeg-cos schraeg-z
budget rand-dx rand-dz)
(if (not *etage-lib-initialized*)
(progn
@@ -335,6 +471,26 @@
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)))
@@ -379,34 +535,59 @@
(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
(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
(* 2.0 feste-gesamt-cos)))
;; B: vertikaler Rest (Vorzeichen analog Standard)
;; 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 (= richtung "Auf")
(setq B (+ deltaH
abs-dz-AUS
abs-dz-EIN
(* 2.0 schraeg-z)
(* 2.0 abs-dz-GEF)
(- bogen-z1)
(- bogen-z2)
(* 2.0 feste-gesamt-sin)))
(setq B (+ (- deltaH
abs-dz-AUS
abs-dz-EIN
(* 2.0 schraeg-z)
(* 2.0 abs-dz-GEF)
(* 2.0 feste-gesamt-sin))
bogen-z1
bogen-z2))
(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)
@@ -469,7 +650,7 @@
(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)
(berechne-winkel-etage deltaL deltaH richtung seite)
)
;; ============================================================
@@ -523,11 +704,12 @@
;; GF laeuft in dieser Richtung weiter (Frame-Verkettung wie im Linienzug).
(setq as-hz (+ hz (- (cadr as-ksinfo) (car as-ksinfo))))
;; 2. Staustrecke 400mm (folgt der AS-Richtung as-hz, 3 Grad vert, KS_EIN)
;; 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
400 as-hz *vfk-gefaelle-winkel*))
*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))))
@@ -669,10 +851,15 @@
(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*)
400.0))
*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)
+8
View File
@@ -193,6 +193,14 @@
;; etage-foerderanlage-einfuegen (vf_etage.lsp).
(if (null *vfk-etage-auslauf-min-clamp*) (setq *vfk-etage-auslauf-min-clamp* 50.0))
;; Feste Einlauf-Staustrecke (mm) des Etage-Typs: Schritt 2 in
;; etage-foerderanlage-einfuegen, direkt hinter dem AS-Element. Das
;; Gegenstueck am Auslauf (Schritt 13) ist NICHT fest, sondern wird aus der
;; Quer-Bilanz bestimmt (etage-rand-budget), damit das ES-KS_AUS
;; querversatzfrei auf der Hauptachse landet. Dient zugleich als Rueckfallwert
;; fuer diese Auslaufstrecke, wenn der Auslauf nicht schwenkt (Quer-Rate 0).
(if (null *vfk-etage-stau-ein*) (setq *vfk-etage-stau-ein* 400.0))
;; Mindest-2D-Laenge (mm) eines Pfad-Segments (LINE-Laenge bzw. ARC-Sehne),
;; das der Linienzug-Modus 2/3 aus einer Objektauswahl akzeptiert. Kuerzere
;; Objekte sind Geister-/Artefakt-Elemente (z.B. ein von einer Rechteck-Auswahl
+2
View File
@@ -354,6 +354,8 @@
"vfe-gefaellebogen-links-mass": "\n Gefaellebogen links: dx=%1 dz=%2 mm",
"vfe-gefaellebogen-rechts-mass": "\n Gefaellebogen rechts: dx=%1 dz=%2 mm",
"vfe-gefaellebogen-seite-dx": "\n Gefaellebogen %1: dx=%2 mm",
"vfe-rand-budget": "\n Rand-Budget: Einlauf=%1 mm Auslauf=%2 mm (Auslauf-Staustrecke %3 mm)",
"vfe-rand-budget-fallback": "\n WARNUNG: Rand-Budget nicht ermittelbar (Block oder KS fehlt) - Rueckfall auf Naeherung, Laenge kann abweichen.",
"vfe-hz-rot-status": "\n HzRot %1 hz=%2 v=%3 -> Z=%4",
"vfe-hz-rotks-status": "\n HzRotKS %1 hz=%2 -> Z=%3",
"vfe-hz-scaleks-status": "\n HzScaleKS %1 %2mm hz=%3 -> Z=%4",
+2
View File
@@ -354,6 +354,8 @@
"vfe-gefaellebogen-links-mass": "\n Slope arc left: dx=%1 dz=%2 mm",
"vfe-gefaellebogen-rechts-mass": "\n Slope arc right: dx=%1 dz=%2 mm",
"vfe-gefaellebogen-seite-dx": "\n Slope arc %1: dx=%2 mm",
"vfe-rand-budget": "\n Edge budget: inlet=%1 mm outlet=%2 mm (outlet queue section %3 mm)",
"vfe-rand-budget-fallback": "\n WARNING: edge budget unavailable (block or CS missing) - falling back to approximation, length may deviate.",
"vfe-hz-rot-status": "\n HzRot %1 hz=%2 v=%3 -> Z=%4",
"vfe-hz-rotks-status": "\n HzRotKS %1 hz=%2 -> Z=%3",
"vfe-hz-scaleks-status": "\n HzScaleKS %1 %2mm hz=%3 -> Z=%4",
+38
View File
@@ -308,6 +308,43 @@
)
;; ------------------------------------------------------------
;; TESTS: vf_etage.lsp - Projektion der Randstuecke auf die Hauptachse
;; ------------------------------------------------------------
;; etage-laengs/-quer zerlegen einen um d gedreht eingebauten Blockvektor
;; (vx vy) in Laengs- und Queranteil bezogen auf die Hauptachse. Sie sind der
;; Kern von etage-rand-budget und damit der korrigierten Laengenbilanz.
(defun tu-tests-etage ( / _hp _vx _vy _l _q)
(princ "\n[vf_etage]")
(setq _hp (/ pi 2.0))
;; d=0: Block liegt schon auf der Hauptachse -> unveraendert
(tu-eqf "etage-laengs/d0" 250.0 (etage-laengs 250.0 67.0 0.0))
(tu-eqf "etage-quer/d0" 67.0 (etage-quer 250.0 67.0 0.0))
;; d=+90 Grad: Block-X zeigt quer, Block-Y entgegen der Hauptachse
(tu-eqf "etage-laengs/d+90" -67.0 (etage-laengs 250.0 67.0 _hp))
(tu-eqf "etage-quer/d+90" 250.0 (etage-quer 250.0 67.0 _hp))
;; REGRESSION (Nutzer-Befund 2026-10-09): das AS_Element_30 hat ein-ang=90
;; Grad, wird also mit d=-90 Grad eingebaut. Auf der Hauptachse landet dann
;; die Block-Y-Komponente (486.1), NICHT die Block-X-Komponente (209.7).
;; Der alte Solver nahm vx und verfehlte die Kettenlaenge um ~990 mm.
(tu-eqf "etage-laengs/AS-d-90-nimmt-vy" 486.1 (etage-laengs 209.7 486.1 (- _hp)))
(tu-eqf "etage-quer/AS-d-90" -209.7 (etage-quer 209.7 486.1 (- _hp)))
;; dito ES_Element_30 (ein-ang=120, Auslauf-Schwenk 30 -> d=-90)
(tu-eqf "etage-laengs/ES-d-90-nimmt-vy" 525.29 (etage-laengs -242.6 525.29 (- _hp)))
(tu-eqf "etage-quer/ES-d-90" 242.6 (etage-quer -242.6 525.29 (- _hp)))
;; Drehung ist laengentreu: laengs^2 + quer^2 = vx^2 + vy^2 (fuer jedes d)
(setq _vx 209.7 _vy 486.1)
(setq _l (etage-laengs _vx _vy 0.9) _q (etage-quer _vx _vy 0.9))
(tu-eqf "etage-laengs/quer-laengentreu"
(+ (* _vx _vx) (* _vy _vy))
(+ (* _l _l) (* _q _q)))
)
;; ------------------------------------------------------------
;; TESTS: export.lsp - CSV/KOS-Kodierung
;; ------------------------------------------------------------
@@ -1707,6 +1744,7 @@
(princ "\n================================================================")
(foreach fn '("tu-tests-core" "tu-tests-lang" "tu-tests-id" "tu-tests-vfcore"
"tu-tests-etage"
"tu-tests-export" "tu-tests-gf" "tu-tests-omni" "tu-tests-kreisel"
"tu-tests-sepliste" "tu-tests-json" "tu-tests-geruest"
"tu-tests-sepscan" "tu-tests-vfl-segs" "tu-tests-vfl-abbruch"