fix: VF-Linienzug Modus 1 Option 6 und Modus 2 - mehrere Solver- und Dialog-Bugs behoben

- Modus 2 Hauptbug: Motorstation+GF2 nutzen jetzt den bereits im Winkel-Solve
  geplanten Wert (br-gf2-exp) statt einer zweiten, unabhaengigen Loesung aus
  gemessener Resthoehe - behebt Laengs-/Querversatz am Kettenende.
- Modus 2 Bug C: Separator/ES-Hoehenreservierung (vfl3-dback/z-junction) auch
  bei "Motorstation ohne ES" korrigiert (vorher nur bei komplett offenem Ende).
- Modus 2 Bug D: fehlender Separator/ES-Laengsanteil im Solve-Budget bei
  Einzel-Kletterer ohne flache Zone (hor-pairs=0) ergaenzt, ausschliesslich
  ueber das Laengenbudget (nicht ueber feste-hz, sonst Hoehen-Doppelzaehlung).
- Modus 1 Option 6 ("Neue Linie BIS Kettenende"): Vorzeichenfehler bei der
  Separator/ES-Hoehenreservierung fuer Richtung "Auf" behoben (musste addiert
  statt subtrahiert werden).
- Vario_Kette_Merge: VF_WINKEL-Attribut liest den Winkel jetzt direkt aus dem
  Blockname statt aus einer ungenauen Chord-Messung ueber den ganzen
  S-Bogen-Tripel (verwaesserte den Winkel Richtung 3-Grad-Basis).
- ES-/AS-Element-Winkel-Dialog: neuer schlanker Dialog ohne die dort nie
  gueltige "60 Grad"-Option (statt nur ausgegraut).
- Modus 2 Lauf-Abschluss-Dialog: roher i18n-Key statt uebersetztem Text
  behoben; Option 3 ("Motorstation + ES-Element") ausgeblendet, wenn die
  Upfront-ES-Frage bereits mit "Nein" beantwortet wurde.

Alle Fixes einzeln in BricsCAD nachgestellt und bestaetigt (dX/dZ exakt).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Yuelin Wang
2026-09-18 17:46:30 +02:00
co-authored by Claude Sonnet 5
parent d9eb41f4d1
commit 797afe48b4
4 changed files with 244 additions and 78 deletions
+197 -72
View File
@@ -788,23 +788,37 @@
;; damit Journal/Log selbsterklaerend sind. GF-Bogen legt Zahlen ab (vom
;; vfl-menu-winkel/vfl-in-value als "INT" journalisiert), ES Strings "90"/"30".
(defun vflw-gruppe-winkel-seite-impl (kopf-key winkel-optionen winkel-werte /
dat dcl-pfad ergebnis gwinkel-grad gseite)
dat dcl-pfad ergebnis gwinkel-grad gseite
mit-60 dlg-name)
;; 60 Grad ist NUR beim GF-Bogen/Vario-Kurve eine gueltige Option - bei
;; AS/ES (winkel-werte immer nur ("90" "30")) waere ein staendig
;; ausgegrautes "60 Grad" verwirrend, daher ein eigener 2-Optionen-Dialog
;; OHNE die Kachel statt mode_tile-Deaktivierung (siehe DCL-Kommentar).
(setq mit-60 (vfl-winkel-in-liste-p 60 winkel-werte))
(setq dlg-name (if mit-60 "vflw_winkel_seite" "vflw_winkel_seite_30_90"))
(setq dat (load_dialog (vflw-dcl-pfad)))
(if (not (new_dialog "vflw_winkel_seite" dat))
(if (not (new_dialog dlg-name dat))
(if (and dat (>= dat 0)) (unload_dialog dat))
(progn
(set_tile "kopf" (vflw-clean (ssg-text kopf-key)))
(if (not (vfl-winkel-in-liste-p 30 winkel-werte)) (mode_tile "winkel_30" 1))
(if (not (vfl-winkel-in-liste-p 60 winkel-werte)) (mode_tile "winkel_60" 1))
(if (not (vfl-winkel-in-liste-p 90 winkel-werte)) (mode_tile "winkel_90" 1))
(if mit-60
(progn
(if (not (vfl-winkel-in-liste-p 30 winkel-werte)) (mode_tile "winkel_30" 1))
(if (not (vfl-winkel-in-liste-p 90 winkel-werte)) (mode_tile "winkel_90" 1))
)
)
(set_tile (strcat "winkel_" (itoa (vfl-winkel-als-zahl (car winkel-werte)))) "1")
(set_tile "seite_links" "1")
(action_tile "accept"
"(setq gwinkel-grad (cond ((= (get_tile \"winkel_30\") \"1\") 30)
((= (get_tile \"winkel_60\") \"1\") 60)
(t 90)))
(setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\"))
(done_dialog 1)")
(if mit-60
"(setq gwinkel-grad (cond ((= (get_tile \"winkel_30\") \"1\") 30)
((= (get_tile \"winkel_60\") \"1\") 60)
(t 90)))
(setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\"))
(done_dialog 1)"
"(setq gwinkel-grad (if (= (get_tile \"winkel_30\") \"1\") 30 90))
(setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\"))
(done_dialog 1)"))
(action_tile "cancel" "(done_dialog 0)")
(action_tile "back" "(done_dialog 2)")
(setq ergebnis (start_dialog))
@@ -1267,13 +1281,17 @@
;; "1"=ohne Motorstation (offenes Ende) / "2"=Motorstation setzen (kein ES) /
;; "3"=Motorstation + ES-Element (Kettenende). Plain ok_cancel wie alle
;; anderen Modus-2-Segment-Dialoge - kein Zurueck/Abbrechen-Mechanismus.
(defun vflw-m2-lauf-abschluss-impl (kopf-txt / dat ergebnis gwahl)
;; es-frueh-abgelehnt: die Upfront-Frage ("ES-Element setzen?") wurde bereits
;; mit "Nein" beantwortet - Option 3 dann deaktivieren, sonst widerspricht sie
;; der schon getroffenen Entscheidung (Nutzer-Feedback).
(defun vflw-m2-lauf-abschluss-impl (kopf-txt es-frueh-abgelehnt / dat ergebnis gwahl)
(setq dat (load_dialog (vflw-dcl-pfad)))
(if (not (new_dialog "vflw_m2_lauf_abschluss" dat))
(if (and dat (>= dat 0)) (unload_dialog dat))
(progn
(set_tile "kopf" (vflw-clean kopf-txt))
(set_tile "abschluss_motor" "1")
(if es-frueh-abgelehnt (mode_tile "abschluss_motor_es" 1))
(action_tile "accept"
"(setq gwahl (cond ((= (get_tile \"abschluss_offen\") \"1\") \"1\")
((= (get_tile \"abschluss_motor_es\") \"1\") \"3\")
@@ -7533,16 +7551,37 @@
;; ist das exakte Ende der Kette NACH Separator + ES-Element.
;; Deren Footprint (Separator 300 mm bei ~3 Grad + ES-Element
;; ein-dx/ein-dz) muss vom baubaren GF/VF-Segment reserviert
;; (abgezogen) werden, damit das ES-Element genau am Zielpunkt
;; endet. Naeherung: Separator-Neigung = 3 Grad (Auslauf).
;; werden, damit das ES-Element genau am Zielpunkt endet.
;; Naeherung: Separator-Neigung = 3 Grad (Auslauf).
;; LAENGE: reiner Budget-Verbrauch, IMMER abziehen (Separator+ES
;; nehmen unabhaengig von der Richtung ein Stueck der Gesamt-
;; Spannweite weg).
;; HOEHE: Separator+ES senken IMMER ab (Ausgleichsprinzip,
;; unabhaengig von "Auf"/"Ab"). Bei "Ab" darf man das wie
;; bisher von deltaH ABZIEHEN (Kletterer+GF muessen dann
;; entsprechend WENIGER absinken, der Rest erledigt der
;; Schwanz). Bei "Auf" ist das GENAU VERKEHRT: der Schwanz
;; senkt NACH dem Solve nochmal ab, also muss Kletterer+GF
;; VORHER entsprechend MEHR steigen, um das wieder
;; auszugleichen - hier muss ADDIERT werden. Exakt dieselbe
;; Auf/Ab-Asymmetrie wie in berechne-alle-winkel selbst
;; (dort +feste-hz*sin3 bei Auf, -feste-hz*sin3 bei Ab -
;; siehe vf_standard.lsp). Realer Bug (falsches Vorzeichen
;; bei "Auf"): ES landete ca. 2*(Separator+ES-Hoehe) zu tief
;; (Livetest 2026-09-18, Abweichung 161mm bei Separator*sin3+
;; |ein-dz| = 15.7+65 = 80.7mm - genau die Haelfte).
(if linie-ende-modus
(progn
(setq rad3 (* (float (ssg-cfg-or "vario" "gefaelle_winkel" 3))
(/ pi 180.0)))
(setq deltaL (max 1.0 (- deltaL (* *vfk-separator-laenge* (cos rad3))
(abs (if ein-dx ein-dx 0.0)))))
(setq deltaH (max 0.0 (- deltaH (* *vfk-separator-laenge* (sin rad3))
(abs (if ein-dz ein-dz 0.0)))))
(setq deltaH
(if (= richtung "Auf")
(+ deltaH (* *vfk-separator-laenge* (sin rad3))
(abs (if ein-dz ein-dz 0.0)))
(max 0.0 (- deltaH (* *vfk-separator-laenge* (sin rad3))
(abs (if ein-dz ein-dz 0.0))))))
(princ (ssg-textf "vfl-info-kettenende-footprint"
(list (rtos deltaL 2 0) (rtos deltaH 2 0))))
)
@@ -7908,11 +7947,10 @@
dat dcl-pfad ergebnis gwinkel gseite)
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/vf_linienzug_wizard.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "vflw_winkel_seite" dat))
(if (not (new_dialog "vflw_winkel_seite_30_90" dat))
(progn (if (and dat (>= dat 0)) (unload_dialog dat))
(alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) nil)
(progn
(mode_tile "winkel_60" 1)
(set_tile "kopf" (ssg-text kopf-key))
(set_tile (if (= vor-winkel-str "30") "winkel_30" "winkel_90") "1")
(set_tile (if (= vor-seite-code "2") "seite_rechts" "seite_links") "1")
@@ -9103,21 +9141,19 @@
(setq wahl (vfl-waehle-winkel (nth 3 res)))
(if wahl (list (car wahl) (cadr wahl) (caddr wahl) richtung) nil))
;; Letzte Fueller-Laenge so, dass der Endpunkt auf der ES-KS_AUS-Achse liegt.
;; pt = Fueller-Start (flach 0 Grad), seg-hz = letzte Richtung, es-block = ES-Block,
;; gf2 = erwartete GF2-Laenge, rad3 = 3 Grad (rad). Modell: der Schwanz (Fueller +
;; ab_3 + Motor + GF2 + Separator + ES) verschiebt sich starr entlang seg-hz.
;; KS_AUS = pt + (fill + C)*dp + perp-es*np
;; C = 196 (ab_3) + (Motor 500 + GF2 + Sep 300)*cos3 + along-es
;; Achse u_a = seg-hz + (KS_AUS.xu - KS_EIN.xu)_Block ; (Endpunkt-KS_AUS)*n_a=0 -> fill
(defun vfl3-es-fueller (pt endp seg-hz es-block gf2 rad3 /
info theta dpx dpy npx npy phi vx vy vwx vwy
along-es perp-es ua na-x na-y cc dp-na np-na ep-na)
;; ES-Element-Fussabdruck ENTLANG/QUER zu einer Fahrtrichtung seg-hz (Welt-
;; Komponenten), aus der REALEN Blockgeometrie (vf-element-ks-info) berechnet.
;; Kernstueck von vfl3-es-fueller, hier ausgelagert, damit AUCH die feste-vf-
;; Berechnung in vf-linienzug-modus2 (Fall hor-pairs=0, OHNE flache
;; Zone/vfl3-es-fueller) denselben Wert nutzen kann, statt den ES-Laengsanteil
;; im Laengenbudget des Solvers stillschweigend zu vergessen (realer Bug:
;; Kette ueberschoss um ungefaehr along-es+Separator, siehe dortiger Kommentar).
;; Rueckgabe: (list along-es perp-es) oder nil, wenn der Block nicht lesbar
;; ist (Aufrufer faellt dann auf eine grobe Naeherung zurueck).
(defun vfl3-es-vektor (es-block seg-hz / info theta dpx dpy npx npy phi vx vy vwx vwy)
(setq info (vf-element-ks-info es-block))
(if (null info)
(- (+ (* (- (car endp) (car pt)) (cos (* seg-hz (/ pi 180.0))))
(* (- (cadr endp) (cadr pt)) (sin (* seg-hz (/ pi 180.0)))))
(+ 196.0 (* (+ *vfk-feste-horizontal-kettenende* gf2) (cos rad3)))) ; Fallback: Along-Naeherung
nil
(progn
(setq theta (* seg-hz (/ pi 180.0)))
(setq dpx (cos theta) dpy (sin theta)) ; seg-hz Richtung
@@ -9126,8 +9162,32 @@
(setq vx (caddr info) vy (cadddr info))
(setq vwx (- (* vx (cos phi)) (* vy (sin phi)))) ; V_es (Welt)
(setq vwy (+ (* vx (sin phi)) (* vy (cos phi))))
(setq along-es (+ (* vwx dpx) (* vwy dpy)))
(setq perp-es (+ (* vwx npx) (* vwy npy)))
(list (+ (* vwx dpx) (* vwy dpy)) (+ (* vwx npx) (* vwy npy)))
)
)
)
;; Letzte Fueller-Laenge so, dass der Endpunkt auf der ES-KS_AUS-Achse liegt.
;; pt = Fueller-Start (flach 0 Grad), seg-hz = letzte Richtung, es-block = ES-Block,
;; gf2 = erwartete GF2-Laenge, rad3 = 3 Grad (rad). Modell: der Schwanz (Fueller +
;; ab_3 + Motor + GF2 + Separator + ES) verschiebt sich starr entlang seg-hz.
;; KS_AUS = pt + (fill + C)*dp + perp-es*np
;; C = 196 (ab_3) + (Motor 500 + GF2 + Sep 300)*cos3 + along-es
;; Achse u_a = seg-hz + (KS_AUS.xu - KS_EIN.xu)_Block ; (Endpunkt-KS_AUS)*n_a=0 -> fill
(defun vfl3-es-fueller (pt endp seg-hz es-block gf2 rad3 /
vek theta dpx dpy npx npy info
along-es perp-es ua na-x na-y cc dp-na np-na ep-na)
(setq vek (vfl3-es-vektor es-block seg-hz))
(if (null vek)
(- (+ (* (- (car endp) (car pt)) (cos (* seg-hz (/ pi 180.0))))
(* (- (cadr endp) (cadr pt)) (sin (* seg-hz (/ pi 180.0)))))
(+ 196.0 (* (+ *vfk-feste-horizontal-kettenende* gf2) (cos rad3)))) ; Fallback: Along-Naeherung
(progn
(setq info (vf-element-ks-info es-block))
(setq theta (* seg-hz (/ pi 180.0)))
(setq dpx (cos theta) dpy (sin theta)) ; seg-hz Richtung
(setq npx (- (sin theta)) npy (cos theta)) ; senkrecht zu seg-hz
(setq along-es (car vek) perp-es (cadr vek))
(setq ua (* (+ seg-hz (- (cadr info) (car info))) (/ pi 180.0))) ; KS_AUS-Achse
(setq na-x (- (sin ua)) na-y (cos ua)) ; senkrecht zur KS_AUS-Achse
(setq cc (+ 196.0 (* (+ *vfk-feste-horizontal-kettenende* gf2) (cos rad3)) along-es))
@@ -9151,7 +9211,7 @@
hoehe-bis soll-ende ist-ende old-error vfl-ins
vf-run-member carrier-idx kv-variante seg-hz letzt-koerper-hz
vf-first-line vf-last-line climber-span mid-hor
z-aftermotor gf2-drop gf2-planar br-lvf this-lvf
br-lvf this-lvf
nach-kurve nach-vf sep-vor-gf sep-nach-gf
n-climb n-hor target-climb winkel-list
fdz fdx wslope lvf planar-len ang-diff best-diff w
@@ -9159,9 +9219,10 @@
nonclimber-cnt nkurve kurve-chords run-span
hor-koerper-len hor-pairs flat-p flat-zone-erste fill-len wahl3
rad3v feste-vf dH-adj dir-x dir-y fill-D end-hz
es-vek-fix es-along-fix
gf-total br-gf-mode br-gf2-exp filler-A-len filler-a-done
as-vorhanden es-vorhanden dbg-an dbg-old-error
m2-lauf-antwort m2-offenes-ende
m2-lauf-antwort m2-offenes-ende es-frueh-abgelehnt
m2-front-antwort m2-offener-anfang m2-kein-gf1-vorne entry-fixed)
(princ "\n\n=========================================")
(princ (ssg-text "vfl-m3-titel"))
@@ -9489,7 +9550,7 @@
(princ (ssg-text "vfl-m3-lauf-anfang-opt-umlenk"))
(princ (ssg-text "vfl-m3-lauf-anfang-opt-umlenk-gf1"))
(if (vfl-wizard-aktiv)
(vl-catch-all-apply 'vflw-m2-lauf-anfang-impl (list "vfl-m3-lauf-anfang-header")))
(vl-catch-all-apply 'vflw-m2-lauf-anfang-impl (list (ssg-text "vfl-m3-lauf-anfang-header"))))
(setq m2-front-antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3")
(list (ssg-text "vfl-m3-lauf-anfang-opt-offen")
(ssg-text "vfl-m3-lauf-anfang-opt-umlenk")
@@ -9509,22 +9570,34 @@
(setq m2-offenes-ende nil)
(if (= vf-ende (1- n))
(progn
;; es-frueh-abgelehnt: die Upfront-Frage ("ES-Element setzen?", vor der
;; Segment-Klassifizierung) wurde bereits mit "Nein" beantwortet - dann
;; hier NICHT nochmal die volle 3-Optionen-Auswahl anbieten (verwirrend,
;; siehe Nutzer-Feedback: Option 3 widerspricht der schon getroffenen
;; Entscheidung). Console UND Wizard bekommen dieselbe reduzierte Liste.
(setq es-frueh-abgelehnt (not es-vorhanden))
(princ (ssg-text "vfl-m3-lauf-abschluss-header"))
(princ (ssg-text "vfl-m3-lauf-abschluss-opt-offen"))
(princ (ssg-text "vfl-m3-lauf-abschluss-opt-motor"))
(princ (ssg-text "vfl-m3-lauf-abschluss-opt-motor-es"))
(if (not es-frueh-abgelehnt) (princ (ssg-text "vfl-m3-lauf-abschluss-opt-motor-es")))
(if (vfl-wizard-aktiv)
(vl-catch-all-apply 'vflw-m2-lauf-abschluss-impl (list "vfl-m3-lauf-abschluss-header")))
(setq m2-lauf-antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def2")
(list (ssg-text "vfl-m3-lauf-abschluss-opt-offen")
(ssg-text "vfl-m3-lauf-abschluss-opt-motor")
(ssg-text "vfl-m3-lauf-abschluss-opt-motor-es")) 2
(vl-catch-all-apply 'vflw-m2-lauf-abschluss-impl
(list (ssg-text "vfl-m3-lauf-abschluss-header") es-frueh-abgelehnt)))
(setq m2-lauf-antwort (vfl-menu (ssg-text (if es-frueh-abgelehnt
"vfl-prompt-wahl-1-2-def2"
"vfl-prompt-wahl-1-3-def2"))
(if es-frueh-abgelehnt
(list (ssg-text "vfl-m3-lauf-abschluss-opt-offen")
(ssg-text "vfl-m3-lauf-abschluss-opt-motor"))
(list (ssg-text "vfl-m3-lauf-abschluss-opt-offen")
(ssg-text "vfl-m3-lauf-abschluss-opt-motor")
(ssg-text "vfl-m3-lauf-abschluss-opt-motor-es"))) 2
"vfl-m3-lauf-abschluss-header"))
(cond
((= m2-lauf-antwort "1")
(setq es-vorhanden nil m2-offenes-ende t)
(princ (ssg-text "vfl-m3-lauf-abschluss-offen-hinweis")))
((= m2-lauf-antwort "3")
((and (= m2-lauf-antwort "3") (not es-frueh-abgelehnt))
(setq es-vorhanden t)
(if (null es-seite) (setq es-seite (vfl-frage-es-seite nil))))
(t (setq es-vorhanden nil)))))
@@ -9645,10 +9718,16 @@
;; --- B2: Back-Abstieg -> Junction; Kletterer + Horizontal-Mitte bestimmen ---
(setq z-junction (+ (float end-hoehe)
(vfl3-dback plan (1+ vf-ende) n last-line ein)))
;; Offenes Ende (kein Motor/Separator/ES danach): vfl3-dback's Tail-Naeherung
;; (reserviert IMMER einen Separator+ES-Fussabdruck) ist hier falsch - die
;; Zielhoehe fuer den Loeser ist exakt end-hoehe.
(if m2-offenes-ende (setq z-junction (float end-hoehe)))
;; Offenes Ende (kein Motor/Separator/ES danach) ODER Motor+GF2 OHNE ES
;; danach (Lauf-Abschluss "Motorstation", es-vorhanden nil - Motor selbst
;; ist bereits ueber dH-adj/*vfk-bruecke-korrektur* separat eingerechnet,
;; siehe Phase B weiter unten): vfl3-dback's Tail-Naeherung (reserviert
;; IMMER einen Separator+ES-Fussabdruck) ist in BEIDEN Faellen falsch - die
;; Zielhoehe fuer den Loeser ist exakt end-hoehe. Realer Bug, bis dahin nur
;; fuer m2-offenes-ende behandelt: "Motorstation ohne ES" fiel durch dieselbe
;; Luecke und bekam einen unkorrigierten Hoehenfehler in Groesse des
;; faelschlich angenommenen Separator+ES-Abstiegs.
(if (or m2-offenes-ende (not es-vorhanden)) (setq z-junction (float end-hoehe)))
(setq dH-bruecke (- z-front z-junction))
;; Modell: EIN Vario mit Horizontal-Mitte. Nur VF-Geraden, die LANG GENUG sind
;; (Vertikalboegen brauchen viel Platz), tragen die Hoehe (Kletterer, gleicher
@@ -9709,15 +9788,42 @@
(cond (m2-offener-anfang 0.0)
(m2-kein-gf1-vorne *vfk-stations-laenge*)
(t (+ *vfk-stations-laenge* *vfk-separator-laenge*))))
(setq es-along-fix 0.0)
(if (> hor-pairs 0)
(setq feste-vf entry-fixed
dH-adj (- dH-bruecke (+ (* *vfk-stations-laenge* (sin rad3v)) *vfk-bruecke-korrektur*))) ; Motor + auf_3/ab_3
(setq feste-vf (+ entry-fixed (if m2-offenes-ende 0.0 *vfk-stations-laenge*)) dH-adj dH-bruecke))
(progn
;; OHNE flache Zone gibt es KEIN vfl3-es-fueller, das den Separator+ES-
;; Laengsanteil selbststaendig gegen den echten Zielpunkt korrigiert -
;; beide fehlten hier bislang komplett im Laengenbudget des Solvers
;; (realer Bug: die Kette ueberschoss um ungefaehr Separator+along-es,
;; am ES-Turn als Querabweichung zur KS_AUS-Achse sichtbar geworden).
;; WICHTIG: NUR die Laenge korrigieren, NICHT ueber feste-vf/dH-adj -
;; feste-vf fliesst in berechne-alle-winkel per sin(3°) AUCH in die
;; Hoehenbilanz ein, waehrend die reale Hoehe von Separator+ES bereits
;; VOLLSTAENDIG ueber z-junction/vfl3-dback erfasst ist (Separator dort
;; per tan(3°), ES-Eigenhoehe per ein-dz - siehe dortiger Kommentar).
;; Ueber feste-vf haette das die Hoehe ein zweites Mal (und fuer
;; along-es sogar physikalisch falsch, da along-es keinen sin(3°)-
;; Hoehenanteil hat) veraendert - realer Folgefehler beim ersten
;; Test dieses Fixes (dZ=38.6mm, vorher exakt 0).
(setq feste-vf (+ entry-fixed (if m2-offenes-ende 0.0 *vfk-stations-laenge*))
dH-adj dH-bruecke)
(if es-vorhanden
(progn
(setq es-vek-fix (vfl3-es-vektor
(strcat "ES_Element_" (vfl-es-winkel) "_" es-seite)
(cadr (nth vf-ende plan))))
(setq es-along-fix
(+ (* *vfk-separator-laenge* (cos rad3v)) (if es-vek-fix (car es-vek-fix) 0.0)))))))
;; Offenes Ende (m2-offenes-ende): kein Motor wird gebaut, die obige
;; Motor-Abstiegs-Korrektur darf dann NICHT abgezogen werden - der Solver
;; soll die volle dH-bruecke exakt treffen (Ziel = z-junction = end-hoehe).
(if m2-offenes-ende (setq dH-adj dH-bruecke))
(setq wahl3 (vfl3-waehle-winkel climber-span dH-adj feste-vf))
;; es-along-fix (reine Laenge, siehe oben) NUR aus dem Laengenbudget (span)
;; abziehen - NICHT aus feste-vf, sonst floss es faelschlich ueber sin(3°)
;; auch in die Hoehenbilanz ein (siehe Kommentar oben).
(setq wahl3 (vfl3-waehle-winkel (- climber-span es-along-fix) dH-adj feste-vf))
(if (null wahl3)
(progn
;; Stufe 2: KEIN Tabellenwinkel passt (der/die Kletterer sind bei JEDER
@@ -9869,23 +9975,27 @@
(setq frame (make-frame-from-dir pt (hz-winkel->xu letzt-koerper-hz 0.0)))
(progn
(if flat-p (progn (setq pt (vfl3-flach-aus pt letzt-koerper-hz)) (setq flat-p nil))) ; zurueck 3 Grad
;; Motorstation (ohne GF2)
(setq pt (vfs-vf-exit pt 0.0 letzt-koerper-hz nil))
;; Motorstation + GF2 in EINEM Schritt mit dem im Solve (vfl3-waehle-
;; winkel/GF-Verteilung, siehe br-gf2-exp oben) bereits geplanten Wert -
;; NICHT mehr unabhaengig aus der gemessenen Resthoehe neu herleiten.
;; Die alte Zwei-Loesungen-Variante (Motor mit L_GF2=0.0, GF2 danach aus
;; z-aftermotor/z-junction gemessen) widersprach der Fueller-Position
;; (fill-len, vfl3-es-fueller), die bereits br-gf2-exp als GF2-Laenge
;; angenommen hatte - jede Differenz zwischen den beiden GF2-Werten
;; verschob das Kettenende entlang der Fahrtrichtung (realer Bug:
;; "letztes Segment baut zu lang"). Identische Fehlerklasse wie der
;; bereits behobene Modus-1-Bug (vfl-body-abschluss, siehe Memory
;; project_vf_einheit_ist_endpunkt_reihenfolge).
;; Bekannte Restunsicherheit: *vfk-bruecke-korrektur* (vf_konstanten.lsp,
;; empirischer Fixwert fuer Motor+auf_3/ab_3) bestimmt indirekt die
;; Genauigkeit von br-gf2-exp - sollte trotzdem noch ein kleiner
;; Hoehen-Restfehler auftreten (nicht das urspruengliche Laengs-
;; Ueberschiessen), ist dieser Fixwert der erste Verdaechtige.
(setq pt (vfs-vf-exit pt br-gf2-exp letzt-koerper-hz nil))
(setq *vfl-acc-motorseite* (append *vfl-acc-motorseite* (list "rechts")))
;; GF2 = gemessener exakter Hoehen-Ausgleich (Abstieg bis zur Junction)
(setq z-aftermotor (caddr pt))
(setq gf2-drop (- z-aftermotor z-junction))
(if (< gf2-drop 0.0)
(progn
(vfl-meldung (ssg-textf "vfl-m3-warnung-gf2-negativ" (list (rtos (- gf2-drop) 2 1))))
(setq gf2-drop 0.0)))
(setq gf2-planar (/ gf2-drop (/ (sin (* *vfk-gefaelle-winkel* (/ pi 180.0))) (cos (* *vfk-gefaelle-winkel* (/ pi 180.0))))))
(if (> gf2-planar 0.1)
(progn
(princ (ssg-textf "vfl-m3-gf2-ausgleich" (list (rtos gf2-planar 2 1))))
(setq frame (vfl-insert-gf-segment pt letzt-koerper-hz gf2-planar (fix *vfk-gefaelle-winkel*)))
(vfl-acc-gf-seg (/ gf2-planar (cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))) (fix *vfk-gefaelle-winkel*)))
(setq frame (vfl-frame-3grad pt letzt-koerper-hz)))))
(if (> br-gf2-exp 0.1)
(vfl-acc-gf-seg (/ br-gf2-exp (cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))) (fix *vfk-gefaelle-winkel*)))
(setq frame (vfl-frame-3grad pt letzt-koerper-hz))))
(setq hz letzt-koerper-hz)
;; --- B4: BACK-Lauf bauen (Segmente vf-ende+1 .. n-1) ---
@@ -10280,7 +10390,8 @@
;; Rueckgabe: (list attribut-alist typ-str).
(defun vfl-kette-baue-attribute (kette neuer-bname chain-start chain-end /
rec typ bname anzahl-vf phase entry-info gemessen betrag richtung
as-seite es-seite as-winkel es-winkel delta-l erster letzter ergebnis typ-str)
as-seite es-seite as-winkel es-winkel delta-l erster letzter ergebnis typ-str
bname-winkel)
(vfl-acc-reset)
(setq anzahl-vf 0)
(setq phase "gf")
@@ -10344,13 +10455,27 @@
(if (null entry-info)
(setq entry-info rec) ; erster Bogen des Koerper-Tripels
(progn
;; Zweiter Bogen schliesst das Tripel. Neigung/Richtung ueber die
;; ECHTE Geometrie messen (Anfang des ersten bis Ende des zweiten
;; Bogens) - die Blocknamen allein sind fuer den 3-Grad/horizontal-
;; Fall mehrdeutig (beide nutzen "auf_3"/"ab_3", vfs-vf-koerper).
(setq gemessen (vfl-kette-neigung (vfl-kette-rec-ein entry-info) (vfl-kette-rec-aus rec)))
(setq betrag (vfl-kette-round (abs gemessen)))
(setq richtung (if (< gemessen 0.0) "Auf" "Ab"))
;; Winkel bevorzugt DIREKT aus dem Blocknamen des ersten Bogens
;; lesen (z.B. "Vario_Bogen_auf_15_TEF_rechts" -> "15") - fuer
;; jeden echten Tabellenwinkel > 3 Grad eindeutig. NUR bei "3"
;; bleibt eine Messung noetig, weil auf_3/ab_3 SOWOHL fuer einen
;; echten 3-Grad-S-Bogen ALS AUCH fuer die Stufe-2-Horizontal-
;; Mitte (winkel=0, vfs-vf-koerper-Sonderfall) verwendet werden.
;; Die vorherige Chord-Messung (Anfang Bogen1 bis Ende Bogen2)
;; verwaesserte bei echten S-Boegen >3 Grad den gemessenen
;; Winkel Richtung der 3-Grad-Basis (gewichteter Mittelwert ueber
;; Bogen1+Gerade+Bogen2 statt des reinen Geraden-Winkels) - realer
;; Bug: 15 Grad im Modell wurden nach Vario_Kette_Merge zu 11
;; Grad (Livetest 2026-09-18).
(setq bname-winkel (vfl-kette-teil (vfl-kette-rec-bname entry-info) 3))
(if (and bname-winkel (/= bname-winkel "3"))
(progn
(setq betrag (atoi bname-winkel))
(setq richtung (if (wcmatch (vfl-kette-rec-bname entry-info) "*_auf_*") "Auf" "Ab")))
(progn
(setq gemessen (vfl-kette-neigung (vfl-kette-rec-ein entry-info) (vfl-kette-rec-aus rec)))
(setq betrag (vfl-kette-round (abs gemessen)))
(setq richtung (if (< gemessen 0.0) "Auf" "Ab"))))
(vfl-acc-vf-seg richtung betrag
(distance (vfl-kette-rec-aus entry-info) (vfl-kette-rec-ein rec)))
(setq entry-info nil)
+45 -4
View File
@@ -181,10 +181,12 @@ vflw_as : dialog {
}
}
// Winkel + Seite. Wiederverwendet fuer GF-Bogen (3 Winkel-Optionen: 30/60/90)
// UND ES-Element am Kettenende (2 Winkel-Optionen: 90/30 - dort wird
// "winkel_60" per mode_tile deaktiviert, siehe vflw-gruppe-winkel-seite-impl/
// vfl-glied-as-es-dialog). Radio-Buttons statt Dropdown, Labels fest deutsch.
// Winkel (30/60/90) + Seite - fuer GF-Bogen, wo alle drei Winkel geometrisch
// gueltig sind. Fuer AS-/ES-Element (wo 60 Grad NIE gueltig ist) stattdessen
// vflw_winkel_seite_30_90 verwenden (siehe vflw-gruppe-winkel-seite-impl/
// vfl-glied-as-es-dialog) - eine staendig ausgegraute, nie waehlbare Option
// verwirrt mehr als sie nutzt, daher ein eigener schlankerer Dialog statt
// mode_tile-Deaktivierung. Radio-Buttons statt Dropdown, Labels fest deutsch.
vflw_winkel_seite : dialog {
label = "VarioFoerderer Assistent";
@@ -219,6 +221,45 @@ vflw_winkel_seite : dialog {
}
}
// Winkel (NUR 30/90, kein 60) + Seite - fuer AS-/ES-Element, wo 60 Grad
// geometrisch nie eine gueltige Option ist (anders als GF-Bogen/Vario-Kurve,
// siehe vflw_winkel_seite). Tile-Keys bewusst identisch zu vflw_winkel_seite
// (winkel_30/winkel_90/seite_links/seite_rechts), damit vflw-gruppe-winkel-
// seite-impl/vfl-glied-as-es-dialog denselben set_tile/get_tile-Code fuer
// beide Dialoge nutzen koennen.
vflw_winkel_seite_30_90 : dialog {
label = "VarioFoerderer Assistent";
: column {
: text {
key = "kopf";
label = "";
width = 60;
}
: boxed_radio_column {
label = "Winkel:";
key = "winkel";
: radio_button { key = "winkel_30"; label = "30 Grad"; }
: radio_button { key = "winkel_90"; label = "90 Grad"; value = "1"; }
}
: boxed_radio_column {
label = "Seite:";
key = "seite";
: radio_button { key = "seite_links"; label = "Links"; value = "1"; }
: radio_button { key = "seite_rechts"; label = "Rechts"; }
}
}
: row {
alignment = centered;
: button { key = "back"; label = "Zurueck"; fixed_width = true; width = 12; }
spacer;
: button { key = "accept"; label = "Ok Weiter"; is_default = true; fixed_width = true; width = 12; }
spacer;
: button { key = "cancel"; label = "Abbrechen"; is_cancel = true; fixed_width = true; width = 12; }
}
}
// Nur Winkel (30/90 Grad), OHNE Seite - fuer "QC Linie mit GF" (Option 4),
// deren AS-/ES-Seite ausserhalb dieses Dialogs feststeht (ES-Seite = AS-
// Seite, keine eigene Frage). Radio-Buttons statt Dropdown.
+1 -1
View File
@@ -231,7 +231,7 @@
"vfl-m3-vert-halb": "1/2 GF1 + 1/2 GF2",
"vfl-m3-vert-ganz": "alles GF1",
"vfl-m3-vert-auslauf": "alles GF2 (Auslauf)",
"vfl-m3-vario-ergebnis": "\n -> Vario %1 (%2), L_VF %3 mm, GF gesamt %4 mm, Verteilung %5 (GF2-Rest = Mess-Feinkorrektur)",
"vfl-m3-vario-ergebnis": "\n -> Vario %1 (%2), L_VF %3 mm, GF gesamt %4 mm, Verteilung %5",
"vfl-m3-warnung-gf2-negativ": "\n WARNUNG: Koerper klettert zu wenig - GF2<0 (fehlen %1 mm). Winkel zu flach; dZ nicht exakt.",
"vfl-m3-gf2-ausgleich": "\n GF2 (gemessener Ausgleich): L=%1 mm",
"vfl-m3-kurve-back-uebersprungen": "\n >>> [M3a] Vario-Kurve im Back-Lauf - uebersprungen.",
+1 -1
View File
@@ -231,7 +231,7 @@
"vfl-m3-vert-halb": "1/2 GF1 + 1/2 GF2",
"vfl-m3-vert-ganz": "all GF1",
"vfl-m3-vert-auslauf": "all GF2 (outlet)",
"vfl-m3-vario-ergebnis": "\n -> Vario %1 (%2), L_VF %3 mm, GF total %4 mm, distribution %5 (GF2 remainder = measured fine correction)",
"vfl-m3-vario-ergebnis": "\n -> Vario %1 (%2), L_VF %3 mm, GF total %4 mm, distribution %5",
"vfl-m3-warnung-gf2-negativ": "\n WARNING: body climbs too little - GF2<0 (missing %1 mm). Angle too shallow; dZ not exact.",
"vfl-m3-gf2-ausgleich": "\n GF2 (measured compensation): L=%1 mm",
"vfl-m3-kurve-back-uebersprungen": "\n >>> [M3a] Vario curve in back run - skipped.",