fix: Ab/Auf VF Kettenende nutzt ersten Winkel-Solve statt fehleranfaelliger zweiter Loesung,fix: fehlende Separator-Reservierung vor ES-Element im Kettenende-Solve ergaenzt ,Stufe 3 (Winkel+Horizontal-Fuellstueck) fuer VF-Linienzug Modus 1 ergaenzt

This commit is contained in:
Yuelin Wang
2026-09-16 09:08:59 +02:00
parent 551f2808d7
commit 143a4e7999
5 changed files with 690 additions and 167 deletions
+148 -20
View File
@@ -214,6 +214,44 @@
;; ============================================================
;; TEIL 4: WINKELBERECHNUNG
;; ============================================================
;; Laengen-/Hoehenbilanz (A/B) fuer EINEN Kandidatenwinkel des S-Bogens -
;; die Vektorzerlegung, die vf-winkel-solve danach nach L_GF/L_VF aufloest.
;; Ausgelagert aus berechne-alle-winkel (frueher inline dupliziert), damit
;; vfl-stufe3-winkel-horizontal (vf_linienzug.lsp - fixiert L_GF statt es zu
;; loesen) dieselbe Bilanz ohne Code-Duplikation nutzen kann.
;; mass1/mass2: (get-bogen-mass bogen-auf/-ab winkel), vom Aufrufer schon
;; richtungsabhaengig zugeordnet (Auf: mass1=auf, mass2=ab; Ab: umgekehrt).
;; entry-dx/entry-dz: Fussabdruck eines evtl. vorgeschalteten Uebergangsbogens
;; (schon-flach-Fall), sonst 0.0. Rueckgabe: (list A B), oder nil wenn
;; mass1/mass2 fehlen (Bogen bei diesem Winkel nicht verfuegbar).
(defun vf-winkel-AB (winkel richtung mass1 mass2 deltaL deltaH feste-hz
entry-dx entry-dz abs-dz-AUS abs-dz-EIN sin3 cos3 /
rad5 rad7 bogen-x1 bogen-z1 bogen-x2 bogen-z2 A B)
(if (or (null mass1) (null mass2))
nil
(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 A (- deltaL aus-dx ein-dx bogen-x1 bogen-x2
(* feste-hz cos3) entry-dx))
(if (= richtung "Auf")
(setq B (+ deltaH abs-dz-AUS abs-dz-EIN (abs entry-dz)
(- bogen-z1) (- bogen-z2)
(* feste-hz sin3)))
(setq B (+ (- deltaH abs-dz-AUS abs-dz-EIN (abs entry-dz)
(* feste-hz sin3))
bogen-z1 bogen-z2))
)
(list A B)
)
)
)
;; feste-hz: horizontales Budget der festen Elemente (Umlenk+Motor+Separatoren).
;; nil => Standardwert FESTE_HORIZONTAL (1600, Standard-VF mit 2 Separatoren).
;; Der Linienzug uebergibt 1300 (nur 1 Separator am Einlauf, siehe vf_linienzug).
@@ -229,9 +267,9 @@
;; Aufrufer, die immer von der 3-Grad-Basis starten).
(defun berechne-alle-winkel (deltaL deltaH richtung feste-hz schon-flach /
winkel-list ergebnis-liste A B cos3 sin3
bogen-x1 bogen-z1 bogen-x2 bogen-z2
ab-erg
abs-dz-AUS abs-dz-EIN L_GF L_VF cosα sinα
winkel-eff cosEff sinEff rad5 rad7
winkel-eff cosEff sinEff
winkel mass1 mass2 gueltig entry-mass entry-dx entry-dz
best-winkel best-L_GF best-L_VF)
@@ -272,31 +310,17 @@
(setq mass2 (get-bogen-mass bogen-auf winkel))
)
)
(if (or (null mass1) (null mass2))
(setq ab-erg (vf-winkel-AB winkel richtung mass1 mass2 deltaL deltaH feste-hz
entry-dx entry-dz abs-dz-AUS abs-dz-EIN sin3 cos3))
(if (null ab-erg)
(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 A (car ab-erg) B (cadr ab-erg))
(setq cosα (cos (* winkel (/ pi 180.0)))
sinα (sin (* winkel (/ pi 180.0))))
(setq A (- deltaL aus-dx ein-dx bogen-x1 bogen-x2
(* feste-hz cos3) entry-dx))
(setq winkel-eff (if (= richtung "Auf") (- winkel *vfk-gefaelle-winkel*) (+ winkel *vfk-gefaelle-winkel*)))
(setq cosEff (cos (* winkel-eff (/ pi 180.0)))
sinEff (sin (* winkel-eff (/ pi 180.0))))
(if (= richtung "Auf")
(setq B (+ deltaH abs-dz-AUS abs-dz-EIN (abs entry-dz)
(- bogen-z1) (- bogen-z2)
(* feste-hz sin3)))
(setq B (+ (- deltaH abs-dz-AUS abs-dz-EIN (abs entry-dz)
(* feste-hz sin3))
bogen-z1 bogen-z2))
)
(setq ergebnis-liste
(cons (vf-winkel-solve winkel richtung A B sinα cosEff sinEff sin3 cos3)
ergebnis-liste))
@@ -398,6 +422,110 @@
)
)
;; Stufe 3 (Fallback fuer vfl-winkel-stufe-entscheidung, vf_linienzug.lsp):
;; gewinkelter S-Bogen (Tabellenwinkel) UND horizontales Fuellstueck
;; kombiniert, wenn WEDER Stufe 1 (reiner Tabellenwinkel) NOCH Stufe 2
;; (berechne-horizontale-mitte, reine Horizontale) eine gueltige Loesung
;; liefern. GF wird FIX auf *vfl-gf-min-laenge* gesetzt (Konvention wie die
;; "climber"-Randbedingung in Modus 2/3) statt wie in Stufe 1 simultan
;; geloest - aus der Hoehenbilanz bleibt dann genau L_VF, aus der
;; Laengenbilanz der Rest als L_hor (horizontales Fuellstueck vor ODER nach
;; dem S-Bogen - Position waehlt der Anwender, siehe vfl-winkel-stufe-
;; entscheidung).
;;
;; Herleitung: vf-winkel-solve loest fuer einen Kandidatenwinkel implizit
;; das 2x2-System (durch Ruecksubstitution der dortigen Cramer-Loesung
;; rekonstruiert, winkel-eff=winkel-*vfk-gefaelle-winkel* fuer "Auf"):
;; cos3*L_GF + cosEff*L_VF = A (Laengenbilanz)
;; -sin3*L_GF + sinEff*L_VF = B (Hoehenbilanz)
;; Mit L_GF fix ergibt die Hoehenbilanz L_VF, die Laengenbilanz danach L_hor.
;;
;; Das Fuellstueck braucht sein EIGENES 3-Grad-Uebergangsbogenpaar (auf_3+
;; ab_3, wie in berechne-horizontale-mitte) - dieser Fussabdruck ist NICHT
;; gratis und wird hier VORAB von A/B abgezogen, sonst wiederholt sich der
;; reale dZ-Fehler aus der Historie (siehe Kommentar bei vfl-winkel-stufe-
;; entscheidung, vf_linienzug.lsp).
;;
;; Absichtlich eng gehalten (kein Blackbox-Rateversuch):
;; - Nur "Auf" implementiert. "Ab" faellt laut bestehendem Kommentar bei
;; vfl-winkel-stufe-entscheidung fast immer schon unter Stufe 2 - ohne
;; einen konkreten Bedarfsfall bleibt der "Ab"-Zweig hier ein
;; dokumentiertes TODO statt einer ungetesteten Vermutung.
;; - schon-flach NICHT unterstuetzt: welcher der beiden Uebergangsboegen
;; (Fuellstueck oder S-Bogen) dabei entfallen wuerde, haengt von der -
;; zum Zeitpunkt der Berechnung noch unbekannten - Position (vor/nach)
;; ab. Stufe 3 liefert in diesem Fall bewusst KEIN Ergebnis statt eine
;; der beiden Moeglichkeiten zu raten.
;;
;; Rueckgabe: (list winkel L_GF L_VF L_hor gueltig) beim ersten (flachsten)
;; Kandidatenwinkel mit L_VF>=0 UND L_hor>=0, sonst (list nil nil nil nil nil).
(defun vfl-stufe3-winkel-horizontal (deltaL deltaH richtung feste-hz schon-flach /
winkel-list mass-f1 mass-f2 sin3 cos3
bogen-x1f bogen-z1f bogen-x2f bogen-z2f
A-frei B-frei mass1 mass2 ab-erg A B
winkel-eff sinEff cosEff gf-min
L_GF L_VF L_hor winkel treffer)
(if (or (/= richtung "Auf") schon-flach)
(list nil nil nil nil nil)
(progn
(setq gf-min (if (and (boundp '*vfl-gf-min-laenge*) *vfl-gf-min-laenge*)
*vfl-gf-min-laenge* 400.0))
(setq sin3 (sin (* *vfk-gefaelle-winkel* (/ pi 180.0)))
cos3 (cos (* *vfk-gefaelle-winkel* (/ pi 180.0))))
(setq mass-f1 (get-bogen-mass bogen-auf (fix *vfk-gefaelle-winkel*)))
(setq mass-f2 (get-bogen-mass bogen-ab (fix *vfk-gefaelle-winkel*)))
(if (or (null mass-f1) (null mass-f2))
(list nil nil nil nil nil)
(progn
;; Fuellstueck-Uebergangsboegen (unabhaengig vom Kandidatenwinkel):
;; Bogen1 (auf_3, Eintritt bei 3 Grad, wie in berechne-horizontale-
;; mitte), Bogen2 (ab_3, Eintritt bei 0 Grad - keine Rotation noetig).
(setq bogen-x1f (+ (* (car mass-f1) cos3) (* (caddr mass-f1) sin3)))
(setq bogen-z1f (+ (* (- (car mass-f1)) sin3) (* (caddr mass-f1) cos3)))
(setq bogen-x2f (car mass-f2))
(setq bogen-z2f (caddr mass-f2))
(setq winkel-list (ssg-cfg-or "vario" "bogen_winkel"
'(3 6 9 12 15 18 21 27 33 39 45 51)))
(setq L_GF gf-min treffer nil)
(foreach winkel winkel-list
(if (not treffer)
(progn
(setq mass1 (get-bogen-mass bogen-auf winkel))
(setq mass2 (get-bogen-mass bogen-ab winkel))
(setq ab-erg (vf-winkel-AB winkel richtung mass1 mass2 deltaL deltaH
feste-hz 0.0 0.0 (abs aus-dz) (abs ein-dz) sin3 cos3))
(if ab-erg
(progn
(setq A (car ab-erg) B (cadr ab-erg))
;; Fuellstueck-Fussabdruck vorab abziehen - siehe
;; Kopfkommentar (NICHT gratis).
(setq A-frei (- A bogen-x1f bogen-x2f))
(setq B-frei (- B bogen-z1f bogen-z2f))
(setq winkel-eff (- winkel *vfk-gefaelle-winkel*))
(setq sinEff (sin (* winkel-eff (/ pi 180.0)))
cosEff (cos (* winkel-eff (/ pi 180.0))))
(if (> (abs sinEff) 0.0001)
(progn
(setq L_VF (/ (+ B-frei (* sin3 L_GF)) sinEff))
(setq L_hor (- A-frei (* cos3 L_GF) (* cosEff L_VF)))
(if (and (numberp L_VF) (numberp L_hor)
(>= L_VF 0.0) (>= L_hor 0.0))
(setq treffer (list winkel L_GF L_VF L_hor T))
)
)
)
)
)
)
)
)
(if treffer treffer (list nil nil nil nil nil))
)
)
)
)
)
;; ============================================================
;; TEIL 5: BERECHNE-WRAPPER (Schnittstelle fuer Registry)
;; ============================================================