diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index 525b97c..769ad5e 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -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) diff --git a/dcl/vf_linienzug_wizard.dcl b/dcl/vf_linienzug_wizard.dcl index b2ea51a..6447aea 100644 --- a/dcl/vf_linienzug_wizard.dcl +++ b/dcl/vf_linienzug_wizard.dcl @@ -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. diff --git a/lang/de_DE.json b/lang/de_DE.json index 87e74ca..db14b41 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -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.", diff --git a/lang/en_GB.json b/lang/en_GB.json index 7c6797b..d3e1744 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -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.",