diff --git a/Lisp/vf_core.lsp b/Lisp/vf_core.lsp index 9b45dc1..b17af32 100644 --- a/Lisp/vf_core.lsp +++ b/Lisp/vf_core.lsp @@ -546,6 +546,43 @@ (* (atan (cadr (cadr fe)) (car (cadr fe))) (/ 180.0 pi))) 90.0)))) +;; Neigungs-Aenderung (Grad) eines Elements: Winkel von KS_EIN.xu nach +;; KS_AUS.xu ausserhalb der XY-Ebene (Steigung/Gefaelle), direkt aus dem Block +;; gemessen - Gegenstueck zu vf-element-plan-turn (das nur die XY-Ebene +;; misst). Genutzt fuer Faelle, in denen ein Element NICHT mit der +;; angenommenen *vfk-gefaelle-winkel*-Neigung weitergebaut werden soll, +;; sondern mit der REALEN, am Block gemessenen Neigung (Nutzer-Vorgabe +;; 2026-09-13, NUR fuer vfl-qc-linie-mit-gf-uform - siehe dortiger +;; Kommentar; alle anderen Aufrufer bleiben bei der angenommenen Neigung). +;; WICHTIG: dieselbe Vorzeichen-Konvention wie frame->hz-winkel (vf_core.lsp) +;; - "winkel" = atan(-xu.z, horiz), NICHT atan(xu.z, horiz) - positiv heisst +;; FALLEND (xu zeigt nach unten, negatives Welt-Z), damit der Rueckgabewert +;; direkt (ohne weiteres Vorzeichen-Umdenken) als winkel-Parameter fuer +;; vfl-insert-gf-segment/vfl-acc-gf-seg verwendet werden kann - ohne die +;; Negation kam beim BricsCAD-Test ein KLETTERNDES statt fallendes E1 heraus +;; (Nutzer-Befund 2026-09-13: reale Neigung maass -3 Grad, ergab ohne +;; Vorzeichen-Fix ein steigendes statt fallendes Element). +;; Fallback 0.0 (keine Neigungsaenderung), falls der Block fehlt. +(defun vf-element-plan-neigung (blockname / temp-obj ks-data fe fa xu-e xu-a horiz-e horiz-a) + (setq blockname (ensure-block-loaded blockname)) + (if (not (tblsearch "BLOCK" blockname)) + 0.0 + (progn + (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 fe (ks-frame-extract (cadr (assoc "KS_EIN" ks-data)))) + (setq fa (ks-frame-extract (cadr (assoc "KS_AUS" ks-data)))) + (if (and fe fa) + (progn + (setq xu-e (cadr fe) xu-a (cadr fa)) + (setq horiz-e (sqrt (+ (* (car xu-e) (car xu-e)) (* (cadr xu-e) (cadr xu-e))))) + (setq horiz-a (sqrt (+ (* (car xu-a) (car xu-a)) (* (cadr xu-a) (cadr xu-a))))) + (- (* (atan (- (caddr xu-a)) horiz-a) (/ 180.0 pi)) + (* (atan (- (caddr xu-e)) horiz-e) (/ 180.0 pi)))) + 0.0)))) + ;; KS-Info eines Elements (im Block, Einbau-Rotation 0): ;; Rueckgabe (ein-ang aus-ang vx vy) ;; ein-ang / aus-ang : Ebenen-Winkel (Grad) von KS_EIN.xu bzw. KS_AUS.xu @@ -1148,6 +1185,8 @@ (action_tile "accept" "(setq gmodus (cond ((= (get_tile \"modus_2\") \"1\") 2) ((= (get_tile \"modus_3\") \"1\") 3) + ((= (get_tile \"modus_4\") \"1\") 4) + ((= (get_tile \"modus_5\") \"1\") 5) (t 1))) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") @@ -1169,6 +1208,12 @@ ;; ============================================================ ;; TEIL 12: DISPATCHER c:VarioFoerderer ;; ============================================================ +;; Erzwungener QC-Modus (Linienzug-Modus 4/5, vfc-dialog-linienzug-modus- +;; waehlen/Konsolen-Fallback unten): "4"/"5" waehrend des naechsten +;; vf-linienzug-modus-Laufs, sonst nil. Von vf-linienzug-modus (vf_linienzug. +;; lsp, spaeter geladen) gelesen/geleert - globale Vorab-Deklaration hier, +;; damit sie unabhaengig von der Lade-Reihenfolge existiert. +(if (not (boundp '*vfl-forciere-qc-modus*)) (setq *vfl-forciere-qc-modus* nil)) (defun c:VarioFoerderer ( / typ-eintr anlage-typ berechne-fn einfuege-fn eingabe deltaL deltaH richtung startpunkt seite hz eingabe-modus ergebnis ergebnis-liste gueltige-winkel @@ -1248,7 +1293,9 @@ (princ (ssg-text "vfc-linienzug-modus-1")) (princ (ssg-text "vfc-linienzug-modus-2")) (princ (ssg-text "vfc-linienzug-modus-3")) - (setq wahl (getint (ssg-text "prompt-wahl-1-2-3"))) + (princ (ssg-text "vfc-linienzug-modus-4")) + (princ (ssg-text "vfc-linienzug-modus-5")) + (setq wahl (getint (ssg-text "prompt-wahl-1-5"))) ) ) (if (not zurueck-zu-typ) @@ -1267,6 +1314,7 @@ ;; Hochziehen ein reiner Bugfix. Setzt zugleich *vfl-seg-glied-letzte* ;; zurueck, das sonst vom Vorlauf stehenbleibt. (vfl-journal-reset) + (setq *vfl-forciere-qc-modus* (cond ((= wahl 4) "4") ((= wahl 5) "5") (t nil))) (cond ((= wahl 2) (vf-linienzug-modus2)) ((= wahl 3) (vf-linienzug-modus3)) (t (vf-linienzug-modus))) diff --git a/Lisp/vf_konstanten.lsp b/Lisp/vf_konstanten.lsp index 9ee5599..cba3082 100644 --- a/Lisp/vf_konstanten.lsp +++ b/Lisp/vf_konstanten.lsp @@ -144,6 +144,14 @@ ;; traegt den Wert weiterhin zusaetzlich im String - dort unangetastet). (if (null *vfk-separator-laenge*) (setq *vfk-separator-laenge* 300.0)) +;; "QC Linie mit GF" / "QC Linie mit GF und U-Form" (Lisp/vf_linienzug.lsp, +;; vfl-qc-linie-mit-gf/-uform): reine Vorschlagswerte fuer die Ein-/Auslauf- +;; Geradenstuecke bzw. die feste U-Form-Zwischenstrecke - alle drei bleiben +;; Nutzereingaben (getreal mit diesem Default), keine harten Konstanten. +(if (null *vfk-qc-einlauf-laenge*) (setq *vfk-qc-einlauf-laenge* 1000.0)) +(if (null *vfk-qc-u-fest-laenge*) (setq *vfk-qc-u-fest-laenge* 400.0)) +(if (null *vfk-qc-fallend-anteil-default*) (setq *vfk-qc-fallend-anteil-default* 0.5)) + ;; Mindestlaenge (mm) fuer eine VF-Einheit (Umlenk+Motor = 2x ;; *vfk-stations-laenge*). Aktiv referenziert in vf_linienzug.lsp ;; (vfl-vf-entscheidung, vfl-vf-machbar-p, vfl-segment-entscheidung, diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index 42e09fd..230c32c 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -812,6 +812,33 @@ ) (princ)) +;; Nur Winkel (30/90), OHNE Seite - fuer "QC Linie mit GF" (vfl-qc-linie- +;; mit-gf): deren ES-Seite = AS-Seite ist bereits erzwungen, eine Seiten- +;; Frage im selben Dialog waere irrefuehrend. Schiebt "90"/"30" (den +;; AUFGELOESTEN Wert, kein Index - vf-frage-element-winkel wird beim +;; Pending-Konsum NICHT mehr durchlaufen) in die Pending-Queue. +(defun vflw-gruppe-qc-winkel-impl (kopf-key / dat ergebnis gwinkel) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_qc_winkel" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text kopf-key))) + (action_tile "accept" + "(setq gwinkel (if (= (get_tile \"winkel_30\") \"1\") \"30\" \"90\")) + (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (action_tile "back" "(done_dialog 2)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (cond + ((= ergebnis 1) (vflw-pending-push-all (list gwinkel))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + ;; ------------------------------------------------------------ ;; Gruppe "Vario-Kurve": Winkel(90/60/30) + Seite + Variante(aussen/innen). ;; Reihenfolge/Journal: vfl-menu-winkel (Winkel als ECHTER Wert 90/60/30, als @@ -934,6 +961,7 @@ (action_tile "accept" "(setq gwahl (cond ((= (get_tile \"modus_hoehe\") \"1\") \"2\") ((= (get_tile \"modus_steigend\") \"1\") \"3\") + ((= (get_tile \"modus_qc\") \"1\") \"4\") (t \"1\"))) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") @@ -1460,7 +1488,13 @@ ;; (wahl_gfbogen usw.), waehrend die Umrechnung auf die richtige Positions- ;; Nummer hier im Callback passiert (kettenanfang: 1:1: 1-6; sonst: Slot 2 ;; entfaellt, alles ab Slot 3 ruecktr um 1 nach vorn). -(defun vflw-gruppe-naechstes-element-impl (kettenanfang / dat ergebnis slot gwahl) +;; familie: bei Kettenanfang das Ergebnis der KS_AUS-Erkennung ("GF"/"VF"/nil) +;; - eindeutig als VF erkannt (Startpunkt liegt auf einer bestehenden +;; VF-Kette) macht "GF-Bogen"/"Neue Linie: GF" als DIREKTE Fortsetzung keinen +;; Sinn (kein GF-Baustein wird an dieser Stelle einfach an ein VF-Teil +;; angeflanscht) - diese beiden Optionen werden dann ausgegraut. "Neue Linie +;; BIS Kettenende" bleibt immer waehlbar (hat ihre eigene GF/VF-Erkennung). +(defun vflw-gruppe-naechstes-element-impl (kettenanfang familie / dat ergebnis slot gwahl) (setq dat (load_dialog (vflw-dcl-pfad))) (if (not (new_dialog "vflw_naechstes_element" dat)) (if (and dat (>= dat 0)) (unload_dialog dat)) @@ -1468,6 +1502,11 @@ (set_tile "kopf" (vflw-clean (ssg-text "vfl-naechstes-element-header"))) (set_tile "wahl_liniegf" "1") (if (not kettenanfang) (mode_tile "wahl_variokurve" 1)) + (if (and kettenanfang (equal familie "VF")) + (progn + (mode_tile "wahl_gfbogen" 1) + (mode_tile "wahl_liniegf" 1) + (set_tile "wahl_variokurve" "1"))) (action_tile "accept" "(setq slot (cond ((= (get_tile \"wahl_gfbogen\") \"1\") 1) ((= (get_tile \"wahl_variokurve\") \"1\") 2) @@ -1852,6 +1891,32 @@ ;; als gueltig (-> kind), nil als Abbruch (-> "NIL"). Fuer Faelle, in denen die ;; Gueltigkeit strenger geprueft werden muss (z.B. vfl-in-string: "" ist ein ;; gueltiger String), siehe vfl-in-value-p. +;; Generisches Echo der Antwort auf JEDE vfl-in-*-Frage (Nutzerwunsch: nach +;; jeder Konsolen-/Wizard-Frage soll sichtbar sein, was gewaehlt wurde) - +;; zentral in vfl-in-value/-value-p verankert (statt an jeder Aufrufstelle +;; einzeln), deckt dadurch ALLE Fragen ab, auch kuenftige. Bei einer Menue- +;; Frage (vfl-menu/-menu-int, *vflw-menu-optionen* gesetzt - dynamisch aus +;; deren eigener '/'-Deklaration sichtbar) wird die Antwort, falls sie als +;; 1-basierter Index in die Options-Liste passt, zum Options-Text aufgeloest +;; (vflw-clean entfernt das "\n N - "-Praefix); sonst (z.B. vfl-menu-winkel +;; mit einem echten Winkelwert statt Index, oder eine freie Texteingabe wie +;; der AS-/ES-Winkel "90"/"30") wird der Rohwert gezeigt. Nur STR/INT +;; (echte Auswahl-Antworten) - REAL (Hoehen/Laengen/Winkel-Zahlen) und +;; PT/DL (Punktwahl) werden NICHT echot, das Ergebnis zeigt sich ohnehin +;; ueber die nachfolgende Bau-/KS_AUS-Ausgabe. +(defun vfl-echo-antwort (kind v / idx label) + (if (and v (member kind '("STR" "INT"))) + (progn + (setq label nil) + (if (and *vflw-menu-optionen* + (setq idx (if (= kind "INT") v (atoi v))) + (>= idx 1) (<= idx (length *vflw-menu-optionen*))) + (setq label (vflw-clean (nth (1- idx) *vflw-menu-optionen*)))) + (vfl-echo-wahl (if label label (if (= kind "STR") v (vl-princ-to-string v)))) + ) + ) +) + (defun vfl-in-value (kind livefn / popped v) ;; Zentraler Abbruch-Trigger fuer den "Zurueck"/"Abbrechen"-Button (siehe ;; vfl-modus-abbruch-sichern): EIN Check hier deckt vfl-in-point/-string/ @@ -1874,6 +1939,7 @@ (setq popped (vfl-headless-notausgang kind))) (if popped (setq v (car popped)) (setq v (apply livefn nil))))) (vfl-journal-record (if v kind "NIL") v) + (vfl-echo-antwort kind v) v) ;; Variante mit explizitem Gueltig-Praedikat (fuer vfl-in-string: "" ist gueltig). @@ -1892,6 +1958,7 @@ (setq popped (vfl-headless-notausgang kind))) (if popped (setq v (car popped)) (setq v (apply livefn nil))))) (vfl-journal-record (if (apply gueltig-p (list v)) kind "NIL") v) + (vfl-echo-antwort kind v) v) ;; --- String-Hilfen (generisch, Trenner beliebig) --- @@ -2527,7 +2594,7 @@ (setq aus-dx 0.0 aus-dz 0.0) (setq res (vfl-waehle-winkel - (nth 3 (berechne-alle-winkel deltaL deltaH richtung *vfl-feste-horizontal*)))) + (nth 3 (berechne-alle-winkel deltaL deltaH richtung *vfl-feste-horizontal* nil)))) (setq aus-dx save-ausdx aus-dz save-ausdz) res) @@ -2553,12 +2620,17 @@ ;; Gebraucht von vfl-vf-machbar-p fuer die Sondierung in vfl-vf-min-deltah, ;; die viele Testwerte durchprobiert (dort wuerde die Tabellenausgabe von ;; berechne-alle-winkel die Konsole zuspammen). -(defun vfl-winkel-machbar-p (deltaL deltaH richtung feste-hz / +(defun vfl-winkel-machbar-p (deltaL deltaH richtung feste-hz schon-flach / winkel-list cos3 sin3 mass1 mass2 rad5 rad7 bogen-x1 bogen-z1 bogen-x2 bogen-z2 cosa sina A B winkel-eff cosEff sinEff L_GF L_VF - abs-dz-AUS abs-dz-EIN gefunden) + abs-dz-AUS abs-dz-EIN gefunden entry-mass entry-dx entry-dz) (if (null feste-hz) (setq feste-hz FESTE_HORIZONTAL)) + (setq entry-dx 0.0 entry-dz 0.0) + (if schon-flach + (progn + (setq entry-mass (get-bogen-mass bogen-ab (fix *vfk-gefaelle-winkel*))) + (setq entry-dx (car entry-mass) entry-dz (caddr entry-mass)))) (setq abs-dz-AUS (abs aus-dz) abs-dz-EIN (abs ein-dz)) (setq winkel-list (ssg-cfg-or "vario" "bogen_winkel" '(3 6 9 12 15 18 21 27 33 39 45 51))) @@ -2584,14 +2656,14 @@ (setq bogen-z2 (+ (* (- (car mass2)) (sin rad7)) (* (caddr mass2) (cos rad7)))) (setq cosa (cos (* winkel (/ pi 180.0))) sina (sin (* winkel (/ pi 180.0)))) - (setq A (- deltaL aus-dx ein-dx bogen-x1 bogen-x2 (* feste-hz cos3))) + (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 (- bogen-z1) (- bogen-z2) + (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 (* feste-hz sin3)) + (setq B (+ (- deltaH abs-dz-AUS abs-dz-EIN (abs entry-dz) (* feste-hz sin3)) bogen-z1 bogen-z2))) (if (> (abs sina) 0.0001) (progn @@ -2627,7 +2699,7 @@ ((= richtung "Auf") (setq save-ausdx aus-dx save-ausdz aus-dz) (setq aus-dx 0.0 aus-dz 0.0) - (setq ergebnis (vfl-winkel-machbar-p deltaL deltaH "Auf" *vfl-feste-horizontal*)) + (setq ergebnis (vfl-winkel-machbar-p deltaL deltaH "Auf" *vfl-feste-horizontal* nil)) (setq aus-dx save-ausdx aus-dz save-ausdz) ergebnis) (t @@ -2637,7 +2709,7 @@ (progn (setq save-ausdx aus-dx save-ausdz aus-dz) (setq aus-dx 0.0 aus-dz 0.0) - (setq ergebnis (vfl-winkel-machbar-p deltaL deltaH "Ab" *vfl-feste-horizontal*)) + (setq ergebnis (vfl-winkel-machbar-p deltaL deltaH "Ab" *vfl-feste-horizontal* nil)) (setq aus-dx save-ausdx aus-dz save-ausdz) ergebnis))) ) @@ -2723,6 +2795,23 @@ (princ) ) +;; Konsolen-Echo der aktuellen Kettenposition (X/Y/Z) - nach jedem gebauten +;; Kettenglied aufgerufen, damit der Nutzer ohne Attribut-Blick sofort sieht, +;; wo die Kette gerade steht (Wunsch nach durchgaengigem Fortschritts-Echo, +;; analog zu vfl-echo-endpunkt-hoehe). +(defun vfl-echo-position (pt) + (princ (ssg-textf "vfl-echo-position" + (list (rtos (car pt) 2 2) (rtos (cadr pt) 2 2) (rtos (caddr pt) 2 2)))) + (princ) +) + +;; Konsolen-Echo der getroffenen Menue-Auswahl (Label-Text statt nur "1"/"2"), +;; damit ein Log/Protokoll nachvollziehbar bleibt, was gewaehlt wurde. +(defun vfl-echo-wahl (label) + (princ (ssg-textf "vfl-echo-wahl" (list label))) + (princ) +) + ;; Wie vfl-vf-machbar-p, aber fuer das Budget von vfl-body-zerlegung ;; (Kettenende-Modus, "Ja - Motorstation setzen, Kettenende festlegen"): ;; feste-hz=800 (nur Motor+Separator, KEIN Umlenk-/AS-Anteil) statt @@ -2732,23 +2821,35 @@ ;; GF nur beim natuerlichen ~3-Grad-Fall weiter unten). aus-dx/aus-dz werden ;; wie im Original immer genullt (nicht nur bedingt wie bei vfl-vf-machbar-p), ;; da der Abschluss-Koerper nie einen AS-Fussabdruck traegt. -(defun vfl-body-machbar-p (deltaL deltaH richtung / horizontal-info save-ausdx save-ausdz ergebnis) +;; Reserviertes Fest-Budget am Kettenende: Motor+Separator (800), AUSSER kein +;; ES gewuenscht - dann baut vfl-insert-es-element (das den Separator +;; MITBRINGT) gar nicht erst, also darf auch kein Separator reserviert werden +;; (sonst bleibt die Kette um dessen Laenge hinter dem Zielpunkt zurueck - +;; realer Bug, siehe vfl-body-zerlegung). +(defun vfl-body-budget (es-gewuenscht) + (if es-gewuenscht + *vfk-feste-horizontal-kettenende* + (- *vfk-feste-horizontal-kettenende* *vfk-separator-laenge*))) + +(defun vfl-body-machbar-p (deltaL deltaH richtung es-gewuenscht schon-flach / + horizontal-info save-ausdx save-ausdz ergebnis budget) (if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek)) + (setq budget (vfl-body-budget es-gewuenscht)) (setq save-ausdx aus-dx save-ausdz aus-dz) (setq aus-dx 0.0 aus-dz 0.0) (setq ergebnis (cond - ((< deltaL *vfk-kettenende-mindestlaenge*) nil) + ((< deltaL budget) nil) ((< deltaH 1.0) - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" nil)) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" schon-flach)) (and horizontal-info (caddr horizontal-info) t)) ((= richtung "Auf") - (vfl-winkel-machbar-p deltaL deltaH "Auf" *vfk-feste-horizontal-kettenende*)) + (vfl-winkel-machbar-p deltaL deltaH "Auf" budget schon-flach)) (t - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" nil)) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" schon-flach)) (if (and horizontal-info (caddr horizontal-info)) t - (vfl-winkel-machbar-p deltaL deltaH "Ab" *vfk-feste-horizontal-kettenende*))) + (vfl-winkel-machbar-p deltaL deltaH "Ab" budget schon-flach))) ) ) (setq aus-dx save-ausdx aus-dz save-ausdz) @@ -2757,12 +2858,12 @@ ;; Wie vfl-vf-min-deltah, aber mit vfl-body-machbar-p (Budget von ;; vfl-body-zerlegung statt vfl-vf-entscheidung). -(defun vfl-body-min-deltah (deltaL richtung / schritt grenze h gefunden) +(defun vfl-body-min-deltah (deltaL richtung es-gewuenscht schon-flach / schritt grenze h gefunden) (setq schritt 10.0) (setq grenze (/ deltaL *vfk-gefaelle-winkel*)) (setq h schritt gefunden nil) (while (and (not gefunden) (<= h grenze)) - (if (vfl-body-machbar-p deltaL h richtung) + (if (vfl-body-machbar-p deltaL h richtung es-gewuenscht schon-flach) (setq gefunden h) (setq h (+ h schritt))) ) @@ -2770,13 +2871,13 @@ ) ;; Wie vfl-vf-hoehe-vorschlaege, aber fuer vfl-body-abschluss (Kettenende- -;; Modus): nutzt vfl-body-min-deltah (800mm-Budget) statt vfl-vf-min-deltah -;; (1300mm-Budget) - sonst wuerde ein Vorschlag als baubar erscheinen, der es -;; am Kettenende (kleineres Budget: nur Motor+Separator, kein Umlenk-Anteil) -;; tatsaechlich nicht ist. -(defun vfl-body-hoehe-vorschlaege (p-aktuell-z deltaL / min-ab min-auf) - (setq min-ab (vfl-body-min-deltah deltaL "Ab")) - (setq min-auf (vfl-body-min-deltah deltaL "Auf")) +;; Modus): nutzt vfl-body-min-deltah (800mm-Budget, 500mm ohne ES) statt +;; vfl-vf-min-deltah (1300mm-Budget) - sonst wuerde ein Vorschlag als baubar +;; erscheinen, der es am Kettenende (kleineres Budget: nur Motor+Separator, +;; kein Umlenk-Anteil) tatsaechlich nicht ist. +(defun vfl-body-hoehe-vorschlaege (p-aktuell-z deltaL es-gewuenscht schon-flach / min-ab min-auf) + (setq min-ab (vfl-body-min-deltah deltaL "Ab" es-gewuenscht schon-flach)) + (setq min-auf (vfl-body-min-deltah deltaL "Auf" es-gewuenscht schon-flach)) (list (if min-ab (- p-aktuell-z min-ab) nil) (if min-auf (+ p-aktuell-z min-auf) nil)) @@ -3105,13 +3206,20 @@ ;; Genereller Uebergang zwischen zwei Basis-Neigungen (0/+3/-3 Grad, ;; Vorzeichenkonvention wie frame->hz-winkel: positiv=fallend, negativ= -;; steigend). Die Bibliothek kennt nur einen 3-Grad-Bogen gegenueber FLACH -;; (0 Grad) - ein Wechsel zwischen der fallenden (+3) und der steigenden (-3) -;; Basis braucht daher IMMER zwei Boegen ueber 0 als Zwischenhalt. "auf"- -;; Boegen senken die Neigung numerisch (Richtung steigend), "ab"-Boegen -;; erhoehen sie (Richtung fallend) - siehe vfl-nach-3grad/vfl-hor-koerper- -;; bauen, deren Uebergaenge hier verallgemeinert werden. Ist kein Uebergang -;; noetig (Start-/Zielbasis identisch), no-op. +;; steigend) MIT DER VF-BIBLIOTHEK (Vario_Bogen_*_TEF_rechts, init- +;; bibliothek) - fuer Uebergaenge VOR/IN einer VF-Baugruppe (vfs-vf-koerper/ +;; Motorstation), wo der Bogen ohnehin als VF-Familie zaehlt. Reine GF- +;; Kontexte (Linie-GF) nutzen stattdessen vfl-gf-bogen-uebergang (GF-eigene +;; Bloecke, siehe dort) - aktuell KEIN Aufrufer mehr hier im Code, aber als +;; Baustein fuer die dokumentierte Luecke in vfl-body-abschluss-bauen +;; (steigender Frame-Eintritt vor einem VF-Koerper) bewusst nicht entfernt. +;; Die VF-Bibliothek kennt nur einen 3-Grad-Bogen gegenueber FLACH (0 Grad) - +;; ein Wechsel zwischen der fallenden (+3) und der steigenden (-3) Basis +;; braucht daher IMMER zwei Boegen ueber 0 als Zwischenhalt. "auf"-Boegen +;; senken die Neigung numerisch (Richtung steigend), "ab"-Boegen erhoehen sie +;; (Richtung fallend) - siehe vfl-nach-3grad/vfl-hor-koerper-bauen, deren +;; Uebergaenge hier verallgemeinert werden. Ist kein Uebergang noetig (Start- +;; /Zielbasis identisch), no-op. ;; Rueckgabe: (neuer-frame fussabdruck-summe) - fussabdruck-summe (mm, auf hz ;; projiziert) muss der Aufrufer von der geplanten Restlaenge/Zielstrecke ;; abziehen. @@ -3172,6 +3280,873 @@ (list frame summe) ) +;; ------------------------------------------------------------------ +;; GF-eigene Vertikalboegen (Nutzer-Vorgabe): 8 dedizierte Bloecke in +;; data/ils - Vario_Bogen_ab/auf_3/6_rechts (OHNE "_TEF_", das Suffix der +;; VF-Bibliothek). Zweck: reine GF-Uebergaenge (Linie-GF: Einstieg aus der +;; aktuellen Kettenneigung, Ausstieg vor ES/AS) sollen NICHT laenger die +;; VF-Bogen-Bibliothek (bogen-ab/bogen-auf, init-bibliothek) mitbenutzen - +;; die Bloecke tragen dadurch ihre eigene GF-Familie in vfl-kette-typ statt +;; als VF ("BOGENAUF"/"BOGENAB") erkannt zu werden, und ein KS_AUS-Scan am +;; Kettenanfang klassifiziert eine Kette, die mit einem dieser Boegen endet, +;; weiterhin korrekt als GF. Eigener Satz Globals/Init, damit KEINE +;; Abhaengigkeit zu vf_standard.lsp/init-bibliothek entsteht (ensure-block- +;; loaded/vf-element-masse sind bereits generische ssg_ks_insert.lsp/ +;; vf_core.lsp-Helfer, keine VF-spezifischen). +(setq *gf-bogen-auf* nil *gf-bogen-ab* nil *gf-bogen-lib-initialized* nil) + +(defun vfl-gf-bogen-init ( / bname m) + (if (not *gf-bogen-lib-initialized*) + (progn + (setq *gf-bogen-auf* nil *gf-bogen-ab* nil) + (foreach w '(3 6) + (setq bname (strcat "Vario_Bogen_auf_" (itoa w) "_rechts")) + (if (tblsearch "BLOCK" (ensure-block-loaded bname)) + (progn + (setq m (vf-element-masse bname)) + (if m (setq *gf-bogen-auf* (cons (cons w m) *gf-bogen-auf*)) + (princ (ssg-textf "vfl-gf-bogen-ks-fehlt" (list bname))))) + (princ (ssg-textf "vfl-gf-bogen-block-fehlt" (list bname)))) + (setq bname (strcat "Vario_Bogen_ab_" (itoa w) "_rechts")) + (if (tblsearch "BLOCK" (ensure-block-loaded bname)) + (progn + (setq m (vf-element-masse bname)) + (if m (setq *gf-bogen-ab* (cons (cons w m) *gf-bogen-ab*)) + (princ (ssg-textf "vfl-gf-bogen-ks-fehlt" (list bname))))) + (princ (ssg-textf "vfl-gf-bogen-block-fehlt" (list bname)))) + ) + (setq *gf-bogen-auf* (reverse *gf-bogen-auf*) *gf-bogen-ab* (reverse *gf-bogen-ab*)) + (setq *gf-bogen-lib-initialized* t) + ) + ) +) + +;; Wie vfl-bogen-uebergang, aber fuer reine GF-Kontexte (Linie-GF: Einstieg +;; aus der aktuellen Kettenneigung VOR dem GF-Segment, Ausstieg VOR ES/AS) - +;; nutzt die GF-eigenen Vertikalboegen (siehe oben) statt der VF-Bibliothek. +;; WICHTIG: der 6-Grad-Sprung (steigend<->fallend) braucht dadurch NUR EINEN +;; dedizierten 6-Grad-Bogen statt zwei 3-Grad-Boegen ueber 0 als Zwischenhalt +;; (vfl-bogen-uebergang) - kuerzer und geometrisch sauberer, sobald die +;; passenden 6-Grad-Bloecke vorhanden sind (Nutzer-Vorgabe 2026-09-12). +;; Rueckgabe: (neuer-frame fussabdruck-summe), wie vfl-bogen-uebergang. +(defun vfl-gf-bogen-uebergang (frame ziel-winkel / t0 basis-ziel hz pt m summe) + (vfl-gf-bogen-init) + (setq hz (car (frame->hz-winkel frame))) + (setq t0 (cadr (frame->hz-winkel frame))) + (setq t0 (cond ((< (abs t0) *vfk-frame-flach-toleranz*) 0) + ((< t0 0) (- (fix *vfk-gefaelle-winkel*))) + (t (fix *vfk-gefaelle-winkel*)))) + (setq basis-ziel (cond ((< (abs ziel-winkel) *vfl-gf-winkel-toleranz*) 0) + ((< ziel-winkel 0) (- (fix *vfk-gefaelle-winkel*))) + (t (fix *vfk-gefaelle-winkel*)))) + (setq summe 0.0) + (cond + ((= t0 basis-ziel) (list frame summe)) + ;; 6 Grad in einem Zug: steigend<->fallend, EIN dedizierter Bogen. + ((and (/= t0 0) (/= basis-ziel 0)) + (if (> t0 0) + (progn + (setq m (get-bogen-mass *gf-bogen-auf* 6)) + (princ (ssg-text "vfl-gf-bogen-auf6-uebergang")) + (setq pt (insert-rotated-block-with-ks "Vario_Bogen_auf_6_rechts" (car frame) + (fix *vfk-gefaelle-winkel*) (car m) (caddr m) hz))) + (progn + (setq m (get-bogen-mass *gf-bogen-ab* 6)) + (princ (ssg-text "vfl-gf-bogen-ab6-uebergang")) + (setq pt (insert-rotated-block-with-ks "Vario_Bogen_ab_6_rechts" (car frame) + (- (fix *vfk-gefaelle-winkel*)) (car m) (caddr m) hz))) + ) + (setq summe (vfl-projiziere-distanz (car frame) pt hz)) + (list (make-frame-from-dir pt (hz-winkel->xu hz basis-ziel)) summe)) + ;; 3 Grad: flach -> geneigt oder geneigt -> flach, EIN 3-Grad-Bogen. + (t + (if (= t0 0) + (if (> basis-ziel 0) + (progn + (setq m (get-bogen-mass *gf-bogen-ab* 3)) + (princ (ssg-text "vfl-gf-bogen-ab3-uebergang")) + (setq pt (insert-rotated-block-with-ks "Vario_Bogen_ab_3_rechts" (car frame) + 0 (car m) (caddr m) hz))) + (progn + (setq m (get-bogen-mass *gf-bogen-auf* 3)) + (princ (ssg-text "vfl-gf-bogen-auf3-uebergang")) + (setq pt (insert-rotated-block-with-ks "Vario_Bogen_auf_3_rechts" (car frame) + 0 (car m) (caddr m) hz)))) + (if (> t0 0) + (progn + (setq m (get-bogen-mass *gf-bogen-auf* 3)) + (princ (ssg-text "vfl-gf-bogen-auf3-uebergang")) + (setq pt (insert-rotated-block-with-ks "Vario_Bogen_auf_3_rechts" (car frame) + (fix *vfk-gefaelle-winkel*) (car m) (caddr m) hz))) + (progn + (setq m (get-bogen-mass *gf-bogen-ab* 3)) + (princ (ssg-text "vfl-gf-bogen-ab3-uebergang")) + (setq pt (insert-rotated-block-with-ks "Vario_Bogen_ab_3_rechts" (car frame) + (- (fix *vfk-gefaelle-winkel*)) (car m) (caddr m) hz)))) + ) + (setq summe (vfl-projiziere-distanz (car frame) pt hz)) + (list (make-frame-from-dir pt (hz-winkel->xu hz basis-ziel)) summe)) + ) +) + +;; ECHTE Neigungs-Fortsetzung UEBER die von vfl-gf-bogen-uebergang +;; unterstuetzten Zustaende (flach/+3/-3) hinaus - z.B. steigend-3 -> +;; steigend-6 (oder mit grad=6 weiter -> steigend-9) und zurueck. +;; vfl-gf-bogen-uebergang selbst kennt NUR Uebergaenge zu/von flach (der +;; 3-Grad-Fall) bzw. zwischen +3/-3 (der kombinierte 6-Grad-Fall) - fuer eine +;; WEITERE Neigungs-Aenderung AUSGEHEND von einem bereits geneigten Zustand +;; (z.B. Option 5's S bei 6 oder 9 statt 3 Grad, Nutzer-Vorgabe 2026-09-13: +;; ECHTE Bausteine statt rein rechnerischem Ruecksprung) wird derselbe rohe +;; insert-rotated-block-with-ks-Aufruf wie dort direkt genutzt, nur mit einer +;; von 0/+3/-3 abweichenden "eingehende-neigung" als Rotationsparameter - +;; "Vario_Bogen_auf_3/6_rechts"/"_ab_3/6_rechts" sind generische Bloecke mit +;; einem FIXEN eigenen Bogen (grad=3 oder 6), ihre Projektion funktioniert +;; fuer JEDEN eingehenden Rotationswinkel, nicht nur die drei von +;; vfl-gf-bogen-uebergang klassifizierten Zustaende. +;; richtung="auf": eingehende-neigung -> eingehende-neigung-grad (steiler +;; steigend bzw. weniger fallend). richtung="ab": eingehende-neigung -> +;; eingehende-neigung+grad (steiler fallend bzw. weniger steigend). +(defun vfl-gf-bogen-weiter (frame richtung eingehende-neigung grad / m blockname pt hz exit-neigung) + (vfl-gf-bogen-init) + (setq hz (car (frame->hz-winkel frame))) + (if (= richtung "auf") + (progn + (setq m (get-bogen-mass *gf-bogen-auf* grad)) + (setq blockname (strcat "Vario_Bogen_auf_" (itoa grad) "_rechts")) + (setq exit-neigung (- eingehende-neigung grad))) + (progn + (setq m (get-bogen-mass *gf-bogen-ab* grad)) + (setq blockname (strcat "Vario_Bogen_ab_" (itoa grad) "_rechts")) + (setq exit-neigung (+ eingehende-neigung grad))) + ) + (setq pt (insert-rotated-block-with-ks blockname (car frame) eingehende-neigung (car m) (caddr m) hz)) + (make-frame-from-dir pt (hz-winkel->xu hz exit-neigung)) +) + +;; Verkettet mehrere vfl-gf-bogen-weiter-Schritte, um eine BELIEBIGE +;; Neigungs-Erweiterung (Vielfaches von 3 Grad) mit MOEGLICHST WENIGEN +;; Bausteinen zu erreichen (moeglichst viele 6-Grad-Bloecke, ein 3-Grad-Block +;; fuer den Rest) - Option 5's dynamische Winkelwahl (Nutzer-Vorgabe +;; 2026-09-13: "gegebene Laenge -> passenden Winkel waehlen" statt einem +;; einzigen fest verdrahteten Winkel). extra-grad=0 (S bei nur 3 Grad, der +;; symmetrische Grundfall) baut nichts und gibt frame unveraendert zurueck. +;; richtung wie vfl-gf-bogen-weiter ("auf"/"ab"); eingehende-neigung ist der +;; Startwert VOR der Erweiterung (z.B. -3 fuer "auf"). +(defun vfl-gf-bogen-erweitern (frame richtung eingehende-neigung extra-grad / rest neigung-jetzt) + (setq rest extra-grad) + (setq neigung-jetzt eingehende-neigung) + (while (>= rest 6) + (setq frame (vfl-gf-bogen-weiter frame richtung neigung-jetzt 6)) + (setq neigung-jetzt (if (= richtung "auf") (- neigung-jetzt 6) (+ neigung-jetzt 6))) + (setq rest (- rest 6)) + ) + (if (= rest 3) + (setq frame (vfl-gf-bogen-weiter frame richtung neigung-jetzt 3)) + ) + frame +) + +;; 2D-Rotation eines LOKALEN (dx,dy)-Versatzes (KS_EIN->KS_AUS eines Blocks +;; bei Rotation 0, siehe vf-element-masse) um einen WELT-Richtungswinkel +;; (Grad) - dieselbe Rz(hz)-Rotationsformel wie in insert-block-ks-to-ks/ +;; insert-rotated-block-with-ks, hier eigenstaendig fuer eine Vorab- +;; Berechnung OHNE Insert. Rueckgabe: (welt-dx welt-dy). +(defun vfl-rot2d (dx dy hz-grad / rad) + (setq rad (* (float hz-grad) (/ pi 180.0))) + (list (- (* dx (cos rad)) (* dy (sin rad))) + (+ (* dx (sin rad)) (* dy (cos rad))))) + +;; 2D-Kreuzprodukt (ax,ay) x (bx,by) = ax*by - ay*bx. Fuer eine Gerade durch +;; P0 mit Richtungsvektor d_ref gilt fuer einen Punkt P: (P-P0) x d_ref = 0 +;; genau dann, wenn P auf der Geraden liegt. +(defun vfl-kreuz2d (ax ay bx by) (- (* ax by) (* ay bx))) + +;; Weltposition eines benannten KS-Markers ("KS_EIN"/"KS_AUS") eines BEREITS +;; in der Zeichnung platzierten Blocks - wie vfl-kette-ks-aus-richtung, aber +;; fuer einen beliebigen KS-Namen und ohne die Richtung (nur der Punkt wird +;; gebraucht). Ueber eine skalierungsneutrale KOPIE gemessen (das Original +;; bleibt unangetastet in der Zeichnung stehen). Rueckgabe: Weltpunkt oder +;; nil, falls der Marker nicht gefunden wurde. +;; Hintergrund (Nutzer-Befund 2026-09-12): bei AS_Element/ES_Element liegt +;; KS_EIN/KS_AUS aus mechanischen Gruenden (Drehteller-Anschluss) seitlich +;; versetzt vom Block-URSPRUNG - insert-block-mixed-to-ks fluchtet bewusst +;; den Ursprung (nicht KS_EIN) auf den Kettenpunkt (siehe dortiger +;; Kommentar). Der geklickte Startpunkt ist darum NICHT identisch mit +;; KS_EIN - fuer die Kolinearitaets-Referenzgerade in vfl-qc-linie-mit-gf +;; wird das ECHTE, gemessene KS_EIN gebraucht, nicht der rohe Klickpunkt. +(defun vfl-block-ks-punkt (block-obj ks-name / copyobj ksdata p) + (setq copyobj (vla-Copy block-obj)) + (vla-put-XScaleFactor copyobj 1.0) + (vla-put-YScaleFactor copyobj 1.0) + (vla-put-ZScaleFactor copyobj 1.0) + (setq ksdata (extract-ks-from-block-raw copyobj)) + (if (not (vlax-erased-p copyobj)) (vl-catch-all-apply 'vla-Delete (list copyobj))) + (setq p (if (assoc ks-name ksdata) (car (cadr (assoc ks-name ksdata))) nil)) + p +) + +;; ------------------------------------------------------------------ +;; "QC Linie mit GF" (Option 4 der gf-laenge-modus-Frage, Nutzer-Vorgabe +;; 2026-09-12, Geometrie danach nach BricsCAD-Test komplett ueberarbeitet): +;; automatisch berechnete Auf-Ab-GF-Kette, die auf derselben +;; Hoehe endet, auf der sie beginnt - AS -> fallend-GF -> 30-Grad-Bogen -> +;; [fallend-GF -> 6-Grad-Bogen auf -> steigend-GF -> 6-Grad-Bogen ab -> +;; fallend-GF] -> 30-Grad-Bogen (Gegenseite) -> fallend-GF -> ES. Die beiden +;; fallenden Mittelstuecke (vor/nach dem Steig-Stueck) werden als EIN +;; gemeinsamer Unbekannter F_total behandelt (Nutzer-Vorgabe, aufgeteilt +;; nach einem waehlbaren Anteil) - vfl-gf-auf-ab-solve loest F_total und das +;; steigende Mittelstueck S aus der vorgegebenen Mittelteil-Gesamtlaenge und +;; der geforderten Netto-Hoehenaenderung (hier immer 0, da AS/ES auf +;; derselben Hoehe liegen sollen). +;; +;; Weltmass-Formel wie insert-rotated-block-with-ks (ssg_ks_insert.lsp): +;; world_dx = dx*cos(rot) + dz*sin(rot) (horizontal, entlang hz) +;; world_dz = -dx*sin(rot) + dz*cos(rot) (Hoehenaenderung) +;; rot=+gefaelle-winkel fuer den "auf"-Bogen (Einstieg fallend), rot= +;; -gefaelle-winkel fuer den "ab"-Bogen (Einstieg steigend) - siehe +;; vfl-gf-bogen-uebergang, das dieselben Tabellen beim tatsaechlichen Bau +;; verwendet. +;; Rueckgabe: (f-total s gueltig ziel-laenge-min) - f-total/s als horizontale +;; Laengen (wie deltaL bei vfl-insert-gf-segment), gueltig=nil bei negativem +;; Ergebnis (Mittelteil-Vorgabe geometrisch nicht baubar). ziel-laenge-min ist +;; in diesem Fall die kleinste Gesamtlaenge, mit der f-total UND s beide >= 0 +;; wuerden (Nutzer-Vorgabe 2026-09-13: als Vorschlag in der Fehlermeldung +;; ausgeben) - hergeleitet aus a=f-total+s, c=s-f-total (a,c wie unten): damit +;; beide >=0 sind, muss a >= |c| gelten, also ziel-laenge-horiz >= fix-dx+|c|. +(defun vfl-gf-auf-ab-solve (ziel-laenge-horiz ziel-hoehe-delta / + rad3 tan3 m-auf m-ab dx-auf dz-auf dx-ab dz-ab + fix-dx fix-dz a b c f-total s gueltig ziel-laenge-min) + (vfl-gf-bogen-init) + (setq rad3 (* (float (fix *vfk-gefaelle-winkel*)) (/ pi 180.0))) + (setq tan3 (/ (sin rad3) (cos rad3))) + (setq m-auf (get-bogen-mass *gf-bogen-auf* 6)) + (setq m-ab (get-bogen-mass *gf-bogen-ab* 6)) + (setq dx-auf (car m-auf) dz-auf (caddr m-auf)) + (setq dx-ab (car m-ab) dz-ab (caddr m-ab)) + ;; Fixterme: zwei Separatoren (300mm, fallend) + die zwei 6-Grad-Boegen, + ;; jeweils per obiger Rotationsformel ins hz-Frame transformiert. + (setq fix-dx (+ (* 2.0 *vfk-separator-laenge* (cos rad3)) + (* (cos rad3) (+ dx-auf dx-ab)) + (* (sin rad3) (- dz-auf dz-ab)))) + (setq fix-dz (+ (* -2.0 *vfk-separator-laenge* (sin rad3)) + (* (sin rad3) (- dx-ab dx-auf)) + (* (cos rad3) (+ dz-auf dz-ab)))) + (setq a (- ziel-laenge-horiz fix-dx)) + (setq b (- ziel-hoehe-delta fix-dz)) + (setq c (/ b tan3)) + (setq s (/ (+ a c) 2.0)) + (setq f-total (/ (- a c) 2.0)) + (setq gueltig (and (>= f-total -0.01) (>= s -0.01))) + (setq ziel-laenge-min (+ fix-dx (abs c))) + (list f-total s gueltig ziel-laenge-min) +) + +;; Ablauf/Bau von Option 4. Nutzt die dynamisch (AutoLISP-typisch) sichtbaren +;; Lokalvariablen des Aufrufers vf-linienzug-modus (frame, p-aktuell, +;; as-vorhanden, as-seite, kettenanfang, fertig, es-seite, anzahl-gf, ...) - +;; wie alle anderen wahl-Zweige dort auch. Setzt am Ende frame/p-aktuell auf +;; den ES-Ausgang und fertig=t; der gemeinsame Rest des Hauptloops (Segment- +;; XDATA, Echo, Block-Erstellung) laeuft danach unveraendert weiter. +(defun vfl-qc-linie-mit-gf ( / as-w as-s theta-ref as-turn es-turn + bogen-turn-30-r bogen-turn-30-l bogen-turn-90-r bogen-turn-90-l + bogen-seite bogen-winkel bogen-turn-echt + b-noetig tol hz0 hz1 hz2 e1 e1-brutto e2 anteil ziel-laenge + loesung f-total s gueltig fa fb hz-jetzt + erg-bogen soll-hoehe ist-hoehe antwort + rad3 tan3 + p0x p0y px py vx vy esx esy dref-x dref-y + hz1-rad hz2-rad zaehler nenner abweichung + checkpoint p0-real h-aussen-rest theta-ref-rad + probe-checkpoint probe-frame probe-frame2 + bg2x bg2y bg2z esz acc-gfbogen-save acc-sep-save) + (if (not kettenanfang) + (princ (ssg-text "vfl-qc-nur-kettenanfang")) + (progn + ;; --- AS-Winkel/-Seite: wiederverwenden, falls am Kettenanfang schon + ;; entschieden (Regelfall) - sonst (Nutzer hatte "Kein AS-Element" + ;; gewaehlt) hier eine eigene, minimale Nachfrage, da diese Option + ;; konzeptionell IMMER mit einem AS beginnt. + (if as-vorhanden + (progn (setq as-w (vfl-as-winkel)) (setq as-s as-seite)) + (progn + (if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-qc-winkel-impl (list "vf-winkel-aus-header"))) + (princ (ssg-text "vf-winkel-aus-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) + (setq as-w (vfl-in-value "STR" + (function (lambda () (vf-frage-element-winkel "vf-winkel-aus-header"))))) + (setq *vfl-as-winkel* as-w) + (princ (ssg-text "vfl-aus-seite-header")) + (princ (ssg-text "gf-seite-links")) + (princ (ssg-text "gf-seite-rechts")) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1 + "vfl-aus-seite-header")) + (setq as-s (if (= antwort "2") "rechts" "links")) + (setq as-seite as-s) + (vf-set-as-masse as-w as-s) + (setq as-vorhanden t) + ) + ) + ;; --- Richtung waehlen (Nutzer-Vorgabe 2026-09-12): die Gerade, auf + ;; der KS_EIN des AS-Elements UND (nach dem ganzen Umweg) KS_AUS des + ;; ES-Elements liegen sollen - per Mausklick wie ueberall sonst im + ;; Linienzug (vfl-in-richtung, auf das 30-Grad-Weltraster gesnappt). + ;; p0x/p0y (das REFERENZ-KS_EIN fuer die Kolinearitaets-Pruefung) sind + ;; hier einfach der gepickte Punkt selbst - fuer DIESE Option wird + ;; AS_Element unten bewusst MIT KS_EIN (nicht mit dem Block-Ursprung) + ;; auf den Klickpunkt gefluchtet (Nutzer-Vorgabe 2026-09-12: der + ;; Klickpunkt soll die reale Anlagenplanung, z.B. Kreisel-Anschluss, + ;; exakt treffen). + (setq theta-ref (vfl-in-richtung p-aktuell (ssg-text "vfl-qc-prompt-richtung"))) + (if (null theta-ref) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) + ;; Echter Grundriss-Schwenk des AS-Elements (KEINE Annahme "30 bzw. 90 + ;; Grad genau" - die reale Blockgeometrie entscheidet, siehe + ;; vf-element-plan-turn) - die gewaehlte Richtung ist die EINTRITTS- + ;; Achse (KS_EIN), die tatsaechliche Fahrtrichtung danach (hz0, KS_AUS) + ;; liegt um diesen Schwenk verdreht. + (setq as-turn (vf-element-plan-turn (strcat "AS_Element_" as-w "_" as-s))) + (setq hz0 (+ theta-ref as-turn)) + ;; --- Mengengeruest abfragen --- + ;; E1 ist die GESAMTE Strecke vom AS-Austritt bis zum ersten 30-Grad- + ;; Bogen INKLUSIVE des dazwischenliegenden 300mm-Separators (Nutzer- + ;; Korrektur 2026-09-12: vorher kam der Separator ZUSAETZLICH oben + ;; drauf, die Kette wurde dadurch laenger als eingegeben) - die reine + ;; GF-Geradenstrecke ist E1 MINUS des Separator-Horizontalanteils. + (setq rad3 (* (float (fix *vfk-gefaelle-winkel*)) (/ pi 180.0))) + (setq e1-brutto (vfl-in-real (ssg-textf "vfl-qc-prompt-e1" (list (rtos *vfk-qc-einlauf-laenge* 2 0))))) + (if (null e1-brutto) (setq e1-brutto *vfk-qc-einlauf-laenge*)) + (setq e1 (- e1-brutto (* *vfk-separator-laenge* (cos rad3)))) + (setq ziel-laenge (vfl-in-real (ssg-text "vfl-qc-prompt-gesamtlaenge-mittelteil"))) + (setq anteil (vfl-in-real (ssg-textf "vfl-qc-prompt-anteil" (list (rtos *vfk-qc-fallend-anteil-default* 2 2))))) + (if (null anteil) (setq anteil *vfk-qc-fallend-anteil-default*)) + ;; E2 (Laenge 2. Bogen -> ES) wird NICHT gefragt (Nutzer-Vorgabe + ;; 2026-09-12): sobald Winkel und alle anderen Laengen feststehen, ist + ;; sie die einzige verbleibende Freiheit, um die Kette exakt auf + ;; theta-ref zurueckzufuehren - siehe die Geraden-Gleichung weiter + ;; unten (nach dem 2. Bogen, ueber vfl-kreuz2d). + (if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-qc-winkel-impl (list "vf-winkel-ein-header"))) + (princ (ssg-text "vf-winkel-ein-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) + (setq *vfl-es-winkel* + (vfl-in-value "STR" + (function (lambda () (vf-frage-element-winkel "vf-winkel-ein-header"))))) + (setq es-seite as-s) ; Nutzer-Vorgabe: ES-Seite = AS-Seite, keine Frage + (vf-set-es-masse *vfl-es-winkel* es-seite) + ;; --- Bogen-Seite UND -Winkel HERLEITEN (keine Frage, Nutzer-Vorgabe + ;; 2026-09-12): beide Boegen benutzen DIESELBE Seite UND denselben + ;; Winkel. Damit die Kette am Ende wieder auf theta-ref liegt, muss der + ;; Boegen-Schwenk b die Gleichung as-turn + 2*b + es-turn = 0 + ;; erfuellen - b wird daraus hergeleitet und gegen die vier real + ;; vorhandenen Bogen-Varianten (30/90 Grad x links/rechts - AS/ES + ;; koennen laut Nutzer-Vorgabe nur 30 oder 90 Grad sein, mehr braucht + ;; es daher nicht) geprueft (kein Raten); passt keine, ist die + ;; Winkel-Kombination nicht schliessbar. + (setq es-turn (vf-element-plan-turn (strcat "ES_Element_" *vfl-es-winkel* "_" es-seite))) + (setq bogen-turn-30-r (vf-element-plan-turn "Gefaellebogen_rechts_30_R500")) + (setq bogen-turn-30-l (vf-element-plan-turn "Gefaellebogen_links_30_R500")) + (setq bogen-turn-90-r (vf-element-plan-turn "Gefaellebogen_rechts_90_R500")) + (setq bogen-turn-90-l (vf-element-plan-turn "Gefaellebogen_links_90_R500")) + (setq b-noetig (/ (- (+ as-turn es-turn)) 2.0)) + (setq tol 2.0) + (setq bogen-seite nil bogen-winkel nil) + (cond + ((< (abs (- bogen-turn-30-r b-noetig)) tol) (setq bogen-seite "rechts" bogen-winkel 30)) + ((< (abs (- bogen-turn-30-l b-noetig)) tol) (setq bogen-seite "links" bogen-winkel 30)) + ((< (abs (- bogen-turn-90-r b-noetig)) tol) (setq bogen-seite "rechts" bogen-winkel 90)) + ((< (abs (- bogen-turn-90-l b-noetig)) tol) (setq bogen-seite "links" bogen-winkel 90)) + ) + (if (null bogen-seite) + (princ (ssg-textf "vfl-qc-bogen-nicht-schliessbar" + (list (rtos as-turn 2 1) (rtos es-turn 2 1) (rtos b-noetig 2 1)))) + (progn + (setq bogen-turn-echt + (cond + ((and (= bogen-seite "rechts") (= bogen-winkel 30)) bogen-turn-30-r) + ((and (= bogen-seite "links") (= bogen-winkel 30)) bogen-turn-30-l) + ((and (= bogen-seite "rechts") (= bogen-winkel 90)) bogen-turn-90-r) + (T bogen-turn-90-l))) + (setq rad3 (* (float (fix *vfk-gefaelle-winkel*)) (/ pi 180.0))) + (setq tan3 (/ (sin rad3) (cos rad3))) + (setq dref-x (cos (* (float theta-ref) (/ pi 180.0)))) + (setq dref-y (sin (* (float theta-ref) (/ pi 180.0)))) + ;; --- AS + E1 + Sep + 1. Bogen JETZT SCHON WIRKLICH BAUEN (nicht erst + ;; nach der Hoehenbilanz) - Grund (Nutzer-Befund 2026-09-12): + ;; Gefaellebogen-Bloecke haengen an einem BEREITS 3-Grad-geneigten + ;; Rahmen - ihre reale Positions-/Hoehenwirkung liess sich per Formel + ;; nicht zuverlaessig vorhersagen (siehe vfl-gf-auf-ab-solve-Historie); + ;; MESSEN nach echtem Bau ist robuster als eine weitere Rotationsformel + ;; zu vertrauen. Faellt die Kette hinterher als "nicht baubar" durch, + ;; wird diese Teil-Geometrie ueber checkpoint/vfl-loesche-seit wieder + ;; entfernt. + ;; AS-Einfuegung fuer diese Option BEWUSST NICHT ueber + ;; vfl-insert-as-element (das fluchtet den Block-URSPRUNG auf den + ;; Kettenpunkt, siehe dortiger Kommentar - Mittelachsen-Konvention der + ;; UEBRIGEN Linie-GF-Zweige) - Nutzer-Vorgabe 2026-09-12 fuer DIESE + ;; Option: der Klickpunkt soll die reale Anlagenplanung exakt treffen + ;; (z.B. Anschluss an einen Kreisel), darum wird hier KS_EIN direkt + ;; (xy-ref/z-ref="KS_EIN") auf den Klickpunkt gefluchtet - p0-real ist + ;; dadurch einfach der Klickpunkt selbst, keine Nachmessung mehr noetig. + (setq checkpoint (vf-lastent-ohne-attribute)) + (setq p0-real p-aktuell) + (setq p0x (car p0-real) p0y (cadr p0-real)) + (setq theta-ref-rad (* (float theta-ref) (/ pi 180.0))) + (setq frame (insert-block-mixed-to-ks + (strcat "AS_Element_" as-w "_" as-s) + (make-frame-from-dir p-aktuell (list (cos theta-ref-rad) (sin theta-ref-rad) 0.0)) + (caddr p-aktuell) "KS_EIN" "KS_EIN")) + (setq p-aktuell (car frame)) + (setq soll-hoehe (caddr p-aktuell)) + (princ (ssg-textf "vfl-qc-ks-ein-gemessen" + (list (rtos p0x 2 2) (rtos p0y 2 2) (rtos (caddr p0-real) 2 2)))) + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt e1 (fix *vfk-gefaelle-winkel*))) + (vfl-acc-gf-seg (/ e1 (cos rad3)) (fix *vfk-gefaelle-winkel*)) + (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-insert-separator frame)) + (setq frame (vfl-insert-gf-bogen-block frame bogen-winkel bogen-seite)) + (setq hz1 (car (frame->hz-winkel frame))) + (setq hz2 (+ hz1 bogen-turn-echt)) + ;; --- 2. Bogen UND Separator+ES werden HIER PROBEWEISE an der + ;; AKTUELLEN Stelle (nach dem 1. Bogen) eingefuegt, ihre reale + ;; Wirkung gemessen, dann wieder geloescht (Nutzer-Log 2026-09-12: + ;; trotz mehrerer Korrekturrunden an der Formel-Schaetzung blieb eine + ;; Rest-Abweichung - die Division im E2-Solve kann jeden + ;; verbleibenden Schaetzfehler stark verstaerken, wenn hz2 nah an + ;; theta-ref liegt. ECHT MESSEN statt einer vierten Formel-Korrektur). + ;; Gueltig, weil sowohl der 2. Bogen als auch Separator+ES NUR von der + ;; ANKUNFTS-ORIENTIERUNG abhaengen (hz1 bzw. die daraus resultierende + ;; hz2), nicht von der Position - die Probe an dieser Stelle liefert + ;; also exakt dieselbe relative Wirkung wie der spaetere echte Bau + ;; nach Fa/S/Fb (dieselbe Orientierung, nur eine andere Position). Das + ;; Mittelteil (Fa+Sep+Bogen6auf+S+Bogen6ab+Fb+Sep) hat als GANZES per + ;; Definition die horizontale Laenge ziel-laenge (Nutzer-Eingabe) - + ;; IMMER, unabhaengig von der spaeteren F_total/S-Aufteilung (beide + ;; Teile liegen auf derselben Fahrtrichtung hz1) - daher genuegt fuer + ;; die Position vor der Probe ein einfacher ziel-laenge-Vorschub. + (setq hz1-rad (* (float hz1) (/ pi 180.0))) + ;; vfl-insert-gf-bogen-block/vfl-insert-es-element zaehlen intern in + ;; *vfl-acc-gfbogen*/*vfl-acc-separator* mit (fuer die spaeteren + ;; GF_Bogen_L/R_xx- bzw. Separator-Attribute) - die Probe darf diese + ;; Zaehler NICHT dauerhaft verfaelschen, darum sichern/zuruecksetzen. + (setq acc-gfbogen-save *vfl-acc-gfbogen* acc-sep-save *vfl-acc-separator*) + (setq probe-checkpoint (vf-lastent-ohne-attribute)) + (setq probe-frame (vfl-insert-gf-bogen-block frame bogen-winkel bogen-seite)) + (setq hz2 (car (frame->hz-winkel probe-frame))) + (setq bg2x (- (car (car probe-frame)) (car (car frame)))) + (setq bg2y (- (cadr (car probe-frame)) (cadr (car frame)))) + (setq bg2z (- (caddr (car probe-frame)) (caddr (car frame)))) + (setq probe-frame2 (vfl-insert-es-element "GF" probe-frame hz2 (fix *vfk-gefaelle-winkel*) + (caddr (car probe-frame)) es-seite)) + (setq esx (- (car (car probe-frame2)) (car (car probe-frame)))) + (setq esy (- (cadr (car probe-frame2)) (cadr (car probe-frame)))) + (setq esz (- (caddr (car probe-frame2)) (caddr (car probe-frame)))) + (vfl-loesche-seit probe-checkpoint) + (setq *vfl-acc-gfbogen* acc-gfbogen-save *vfl-acc-separator* acc-sep-save) + (setq hz2-rad (* (float hz2) (/ pi 180.0))) + (setq px (+ (car (car frame)) (* ziel-laenge (cos hz1-rad)) bg2x)) + (setq py (+ (cadr (car frame)) (* ziel-laenge (sin hz1-rad)) bg2y)) + (setq vx (- px p0x) vy (- py p0y)) + (setq zaehler (- (+ (vfl-kreuz2d vx vy dref-x dref-y) + (vfl-kreuz2d esx esy dref-x dref-y)))) + (setq nenner (vfl-kreuz2d (cos hz2-rad) (sin hz2-rad) dref-x dref-y)) + (setq e2 (/ zaehler nenner)) + (if (< e2 1.0) + (progn + (princ (ssg-textf "vfl-qc-e2-negativ" (list (rtos e2 2 0)))) + (vfl-loesche-seit checkpoint)) + (progn + ;; --- Ziel-Hoehenaenderung des Mittelteils: AS+E1+Sep+1.Bogen sind + ;; bereits ECHT gebaut (frame traegt die reale Hoehe nach dem 1. + ;; Bogen) - kein Formel-Risiko mehr fuer diesen Teil. WICHTIG: die + ;; Referenz fuer "gleiche Hoehe" ist KS_EIN des AS-Elements (Z des + ;; Klickpunkts, siehe insert-block-mixed-to-ks z-ref="KS_EIN"), NICHT + ;; soll-hoehe (= AS's KS_AUS-Hoehe, direkt nach dem Bau gemessen) - + ;; genau wie bei der X/Y-Referenzgerade weiter oben. AS hat einen + ;; ECHTEN, von Null verschiedenen KS_EIN->KS_AUS-Hoehenanteil (aus-dz, + ;; Nutzer-Korrektur vom Sitzungsbeginn) - der muss hier separat wieder + ;; hinzugerechnet werden (die reale Frame-Messung ab soll-hoehe + ;; deckt nur "AS-KS_AUS bis nach 1.Bogen" ab, nicht "AS-KS_EIN bis + ;; AS-KS_AUS"). bg2z/esz sind die oben ECHT GEMESSENEN Hoehenanteile + ;; des 2. Bogens bzw. von Separator+ES (Probe-Bau) - kein + ;; Formel-Risiko mehr. Es fehlt nur noch E2 selbst (reine Gerade, + ;; E2*tan3 exakt). + (setq h-aussen-rest + (+ aus-dz + (- (caddr (car frame)) soll-hoehe) + bg2z + (- (* e2 tan3)) + esz)) + ;; --- Solver: F_total/S aus vorgegebener Mittelteil-Gesamtlaenge und + ;; der noch fehlenden Hoehenaenderung (Rest bis Gesamtbilanz=0) --- + (setq loesung (vfl-gf-auf-ab-solve ziel-laenge (- h-aussen-rest))) + (setq f-total (nth 0 loesung) s (nth 1 loesung) gueltig (nth 2 loesung)) + (if (not gueltig) + (progn + (princ (ssg-textf "vfl-qc-nicht-baubar" (list (rtos f-total 2 0) (rtos s 2 0) (rtos (nth 3 loesung) 2 0)))) + (vfl-loesche-seit checkpoint)) + (progn + (setq fa (* f-total anteil)) + (setq fb (- f-total fa)) + ;; --- Rest WIRKLICH bauen (physische Reihenfolge; AS/E1/Sep/1. + ;; Bogen sind bereits gebaut, frame steht auf dessen Ausgang) --- + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt fa (fix *vfk-gefaelle-winkel*))) + (vfl-acc-gf-seg (/ fa (cos rad3)) (fix *vfk-gefaelle-winkel*)) + (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-insert-separator frame)) + (setq erg-bogen (vfl-gf-bogen-uebergang frame (- (fix *vfk-gefaelle-winkel*)))) + (setq frame (car erg-bogen)) + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt s (- (fix *vfk-gefaelle-winkel*)))) + (vfl-acc-gf-seg (/ s (cos rad3)) (- (fix *vfk-gefaelle-winkel*))) + (setq anzahl-gf (1+ anzahl-gf)) + (setq erg-bogen (vfl-gf-bogen-uebergang frame (fix *vfk-gefaelle-winkel*))) + (setq frame (car erg-bogen)) + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt fb (fix *vfk-gefaelle-winkel*))) + (vfl-acc-gf-seg (/ fb (cos rad3)) (fix *vfk-gefaelle-winkel*)) + (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-insert-separator frame)) + (setq frame (vfl-insert-gf-bogen-block frame bogen-winkel bogen-seite)) + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt e2 (fix *vfk-gefaelle-winkel*))) + (vfl-acc-gf-seg (/ e2 (cos rad3)) (fix *vfk-gefaelle-winkel*)) + (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-insert-es-element "GF" frame hz-jetzt (fix *vfk-gefaelle-winkel*) + (caddr (car frame)) es-seite)) + (setq p-aktuell (car frame)) + (setq letzter-typ "GF") + (setq ist-hoehe (caddr p-aktuell)) + (setq abweichung (vfl-kreuz2d (- (car p-aktuell) p0x) (- (cadr p-aktuell) p0y) dref-x dref-y)) + (princ (ssg-textf "vfl-qc-erfolg" + (list (rtos soll-hoehe 2 1) (rtos ist-hoehe 2 1) (rtos abweichung 2 1)))) + (setq fertig t) + ) + ) + ) + ) + ) + ) + ) + ) +) + +;; ------------------------------------------------------------------ +;; "QC Linie mit GF und U-Form" (Option 5 der gf-laenge-modus-Frage, +;; Nutzer-Vorgabe 2026-09-13, nach mehreren Praezisierungsrunden - inkl. echter +;; BricsCAD-Tests): wie vfl-qc-linie-mit-gf (Option 4), aber statt EINES +;; 30/90-Grad-Bogens ein kompletter U-Turn ueber ZWEI 90-Grad-GF- +;; Horizontalboegen (dieselbe Seite = GEGENSEITE der AS-Seite, zusammen ~180 +;; Grad Wende) mit einer festen Zwischenstrecke dazwischen. E1, die feste +;; Zwischenstrecke, beide 90-Grad-Bogen behalten dabei durchgehend die +;; aktuelle 3-Grad-Neigung bei (wie ueberall sonst in Linie-GF) - eine +;; probeweise horizontale (0 Grad) Variante wurde getestet und wieder +;; verworfen (Nutzer-Korrektur 2026-09-13). +;; AS/ES-Winkel sind fest 90 Grad, nur die Seite ist waehlbar. E1 UND die +;; Referenzrichtung werden in EINEM Klick bestimmt (vfl-in-abstand) - der +;; Klickpunkt markiert den Start des 1. Bogens, Separator-Laenge wird intern +;; abgezogen (wie Option 4: Klickpunkt = exakter Bogen-Start). AS wird mit +;; xy-ref/z-ref="KS_EIN" eingefuegt (Klickpunkt = KS_EIN exakt). theta-ref +;; (die Klick-Richtung) ist E1's Fahrtrichtung, NICHT AS's Eintrittsachse - +;; AS's KS_EIN-Achse (eintritt-hz = theta-ref - as-turn) steht bei einem +;; echten 90-Grad-Element senkrecht dazu und ist die Baseline, auf die ES am +;; Ende EXAKT zurueckkehren muss (Nutzer-Vorgabe, 3. Praezisierungsrunde: +;; erzwungen, nicht mehr nur informativ wie urspruenglich). +;; Mittelteil (Nutzer-Vorgabe 2026-09-13, finale Struktur nach mehreren +;; Praezisierungsrunden): nach dem 2. (horizontalen) Bogen direkt Fa +;; (fallend, STANDARD 3 Grad, UNBEKANNT) + Sep -> Uebergang fallend-> +;; steigend (auf_6, STANDARD - Fa/Sep garantieren sauber 3 Grad davor) -> +;; ECHTE Zusatz-Neigung auf -9 Grad (zweiter Vario_Bogen_auf_6-Baustein, +;; vfl-gf-bogen-weiter) -> S (steigend, 9 Grad - STEILER als Fa, UNBEKANNT, +;; Nutzer-Vorgabe: je steiler S, desto kleiner kann E1 gewaehlt werden) -> +;; ECHTE Rueckkehr auf -3 Grad (zweiter Vario_Bogen_ab_6-Baustein) -> +;; Uebergang steigend->fallend (ab_6, STANDARD) -> ES (mit automatisch +;; gebuendeltem Separator). Fa UND S sind BEIDE Unbekannte, geloest aus +;; einem 2x2-System: Hoehenbilanz (S*tan9-Fa*tan3=D) UND Lage-Bilanz/ +;; Kolinearitaet zur Baseline (Fa+S=T, Kreuzprodukt-Gleichung wie Option 4's +;; E2-Loesung, inkl. dem Fixterm des Separators zwischen Fa und dem +;; auf_6-Uebergang). Der komplette Rest (Uebergang auf_6+Zusatz-auf_6+ +;; Zusatz-ab_6+ab_6+Sep+ES) haengt nur von der Ankunfts-Orientierung ab +;; (nicht von Fa/S selbst) - sein GESAMTER Hoehen- UND Lage-Beitrag (mit +;; Fa=S=0) wird darum per Probe-Bau+Messen VORAB ermittelt (dasselbe Prinzip +;; wie bei Option 4), danach Fa/S direkt geloest und alles ECHT gebaut. Die +;; asymmetrische Neigung (Fa bei 3, S bei 9 statt beide bei 3) macht Fa/S +;; erst ueber E1 steuerbar - bei identischen Winkeln waeren D und T +;; rechnerisch gleich empfindlich auf alle Laengen-Eingaben, das +;; Gleichungssystem also nicht ueber Nutzereingaben beeinflussbar (Fa+S=T +;; haengt NIE von den Neigungswinkeln ab, nur die Hoehenbilanz tut es - +;; erst der Winkel-Unterschied entkoppelt beide Gleichungen genug, um +;; ueberhaupt eine Loesung ueber E1/Zwischenstrecke anzusteuern). +(defun vfl-qc-linie-mit-gf-uform ( / as-w as-s bogen-seite theta-ref as-turn eintritt-hz + hz-jetzt e1 e1-brutto erg-abstand fest-laenge + e1-neigung e1-neigung-rad + s fa d-hoehe t-lage gueltig sep-dx-planar sep-dz + s-winkel extra-grad rad-s tan-s versuche + tan-e1neigung d-fa-de1 e1-vorschlag + soll-hoehe ist-hoehe rad3 tan3 + p0x p0y dref-x dref-y theta-ref-rad + checkpoint p0-real h-aussen-rest hoehe-vor-fa + p2x p2y hz2 hz2-rad fixedx fixedy dx-fix dy-fix + probe-checkpoint probe-frame-a probe-frame-b probe-frame-c dz-fix + acc-gfbogen-save acc-sep-save + abweichung antwort erg-bogen) + (if (not kettenanfang) + (princ (ssg-text "vfl-qc-uform-nur-kettenanfang")) + (progn + ;; --- AS-Seite: wiederverwenden, falls am Kettenanfang schon + ;; entschieden - Winkel wird IMMER auf 90 erzwungen (Nutzer-Vorgabe), + ;; unabhaengig davon, was bei der allgemeinen AS-Frage evtl. schon + ;; gewaehlt wurde (vf-set-as-masse wird darum hier IMMER erneut mit "90" + ;; aufgerufen, auch wenn as-vorhanden schon t war). + (princ (ssg-text "vfl-qc-uform-winkel-fix")) + (if as-vorhanden + (setq as-s as-seite) + (progn + (princ (ssg-text "vfl-aus-seite-header")) + (princ (ssg-text "gf-seite-links")) + (princ (ssg-text "gf-seite-rechts")) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1 + "vfl-aus-seite-header")) + (setq as-s (if (= antwort "2") "rechts" "links")) + (setq as-seite as-s) + (setq as-vorhanden t) + ) + ) + (setq as-w "90") + (vf-set-as-masse as-w as-s) + ;; Bogen-Seite = GEGENSEITE der AS-Seite (Nutzer-Korrektur 2026-09-13, + ;; nach BricsCAD-Test: mit bogen-seite=as-s lief der U-Turn in die + ;; falsche Richtung zurueck - die AS-Drehteller-Seite und die + ;; GF-Bogen-Seite sind entgegengesetzt konventioniert). + (setq bogen-seite (if (= as-s "links") "rechts" "links")) + (setq rad3 (* (float (fix *vfk-gefaelle-winkel*)) (/ pi 180.0))) + (setq tan3 (/ (sin rad3) (cos rad3))) + ;; rad-s/tan-s (S's Neigung) werden weiter unten PRO WINKEL-KANDIDAT neu + ;; berechnet (dynamische Winkelwahl, Nutzer-Vorgabe 2026-09-13) - Fa + ;; faellt immer bei 3 Grad, VOR S (asymmetrische Neigung fuer Fa/S, je + ;; steiler S desto kleiner kann E1 werden). + ;; --- Richtung UND E1-Laenge in EINEM Klick (Nutzer-Vorgabe + ;; 2026-09-13): der Klickpunkt markiert den Start des 1. 90-Grad-Bogens; + ;; Separator-Laenge wird intern abgezogen, damit der Bogen exakt dort + ;; beginnt (wie Option 4's Klickpunkt=KS_EIN-Prinzip). --- + (setq erg-abstand (vfl-in-abstand p-aktuell nil (ssg-text "vfl-qc-uform-prompt-richtung-e1"))) + (if (null erg-abstand) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) + (setq e1-brutto (car erg-abstand) theta-ref (cdr erg-abstand)) + ;; Konsolen-Echo (Nutzer-Vorgabe 2026-09-13): anders als bei einem + ;; Zahl-Dialog zeigt ein reiner Klick den erfassten Wert nicht von + ;; selbst an - wie bei vfl-echo-endpunkt-hoehe/vfl-echo-position wird + ;; das Ergebnis darum explizit ausgegeben. + (princ (ssg-textf "vfl-qc-uform-e1-echo" (list (rtos e1-brutto 2 0) (rtos theta-ref 2 1)))) + (setq as-turn (vf-element-plan-turn (strcat "AS_Element_" as-w "_" as-s))) + ;; --- E1-Neigung: NICHT die angenommene *vfk-gefaelle-winkel* (3 Grad), + ;; sondern die REALE, am AS-Block gemessene Neigungsaenderung KS_EIN-> + ;; KS_AUS (Nutzer-Vorgabe 2026-09-13, NUR fuer diese Option - siehe + ;; vf-element-plan-neigung-Kommentar). E1 schliesst damit exakt an AS's + ;; echten KS_AUS an, ohne kuenstlichen Neigungssprung. Als Nebeneffekt + ;; (Nutzer-Befund) wird dadurch Fa/S ueber E1 steuerbar - bei E1-Neigung + ;; = 3 Grad waeren D (Hoehenbilanz) und T (Lagebilanz) rechnerisch exakt + ;; gleich empfindlich auf E1, Fa haette also NICHT ueber E1 korrigiert + ;; werden koennen. + (setq e1-neigung (vf-element-plan-neigung (strcat "AS_Element_" as-w "_" as-s))) + (setq e1-neigung-rad (* (float e1-neigung) (/ pi 180.0))) + (princ (ssg-textf "vfl-qc-uform-e1-neigung-echo" (list (rtos e1-neigung 2 2)))) + ;; Separator-Abzug mit e1-neigung (nicht rad3) - der Separator erbt die + ;; Neigung des vorangehenden Segments (E1), nicht die feste 3 Grad. + (setq e1 (- e1-brutto (* *vfk-separator-laenge* (cos e1-neigung-rad)))) + ;; --- Restliches Mengengeruest --- + (setq fest-laenge (vfl-in-real (ssg-textf "vfl-qc-prompt-u-fest-laenge" (list (rtos *vfk-qc-u-fest-laenge* 2 0))))) + (if (null fest-laenge) (setq fest-laenge *vfk-qc-u-fest-laenge*)) + (setq es-seite as-s) ; Nutzer-Vorgabe: ES-Seite = AS-Seite, keine Frage + (vf-set-es-masse "90" es-seite) ; ES-Winkel ebenfalls fest 90, keine Frage + ;; --- AS wirklich bauen (Klickpunkt = KS_EIN, wie Option 4) --- + ;; WICHTIG (Nutzer-Korrektur 2026-09-13): theta-ref ist die gewuenschte + ;; FAHRTRICHTUNG von E1 (der Klick misst e1-brutto entlang theta-ref, + ;; siehe vfl-in-abstand) - das ist AS's AUSTRITTS-Richtung (KS_AUS), + ;; NICHT die Eintritts-Achse (KS_EIN)! AS_Element_90 dreht intern um + ;; as-turn (gemessen, nicht angenommen) - die KS_EIN-Achse muss darum + ;; um as-turn ZURUECKgedreht werden (eintritt-hz = theta-ref - as-turn), + ;; damit KS_AUS nach dem Bau exakt auf theta-ref zeigt. Bei einem + ;; echten 90-Grad-Bogen bedeutet das: die KS_EIN-Achse steht senkrecht + ;; zur gewaehlten Richtung. + (setq eintritt-hz (- theta-ref as-turn)) + ;; Referenzgerade (Baseline), zu der ES am Ende EXAKT zurueckkehren soll + ;; (Nutzer-Vorgabe 2026-09-13, 3. Runde: erzwungen, nicht mehr nur + ;; informativ), ist AS's EINTRITTS-Achse (eintritt-hz, senkrecht zu + ;; theta-ref) - NICHT theta-ref selbst (das ist E1's Fahrtrichtung). + (setq dref-x (cos (* (float eintritt-hz) (/ pi 180.0)))) + (setq dref-y (sin (* (float eintritt-hz) (/ pi 180.0)))) + (setq checkpoint (vf-lastent-ohne-attribute)) + (setq p0-real p-aktuell) + (setq p0x (car p0-real) p0y (cadr p0-real)) + (setq theta-ref-rad (* (float eintritt-hz) (/ pi 180.0))) + (setq frame (insert-block-mixed-to-ks + (strcat "AS_Element_" as-w "_" as-s) + (make-frame-from-dir p-aktuell (list (cos theta-ref-rad) (sin theta-ref-rad) 0.0)) + (caddr p-aktuell) "KS_EIN" "KS_EIN")) + (setq p-aktuell (car frame)) + (setq soll-hoehe (caddr p-aktuell)) + (princ (ssg-textf "vfl-qc-ks-ein-gemessen" + (list (rtos p0x 2 2) (rtos p0y 2 2) (rtos (caddr p0-real) 2 2)))) + ;; --- E1 + Sep bei e1-neigung (REAL gemessen, NICHT der festen 3-Grad- + ;; Annahme - siehe Kommentar oben), danach 1. Bogen, feste + ;; Zwischenstrecke, 2. Bogen bei der jetzt aktuellen Neigung (Bogen/ + ;; Zwischenstrecke sind neigungs-agnostisch, "erhalten die aktuelle + ;; Neigung") - ALLES strikt sequenziell ECHT gebaut. --- + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt e1 e1-neigung)) + (vfl-acc-gf-seg (/ e1 (cos e1-neigung-rad)) e1-neigung) + (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-insert-separator frame)) + ;; --- Rein rechnerischer Ruecksprung auf EXAKT 3 Grad (Nutzer-Vorgabe + ;; 2026-09-13): e1-neigung ist die REALE AS-Neigung, oft ein "krummer" + ;; Wert, keiner der beiden Zustaende (flach/3 Grad), die die + ;; Uebergangs-Bogen-Bibliothek kennt - ein spaeterer Uebergang auf + ;; steigend (fuer Bogen-auf-6) wuerde sonst falsch klassifiziert + ;; (Nutzer-Befund: "auf_3" statt "auf_6" im Log). Position/Fahrtrichtung + ;; bleiben unveraendert, nur die Neigung wird auf *vfk-gefaelle-winkel* + ;; gesetzt - wie jeder GF-Geraden-Uebergang (vfl-insert-gf-segment endet + ;; ja ebenfalls immer mit genau der uebergebenen winkel, kein + ;; Uebergangs-Baustein noetig) --- + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (make-frame-from-dir (car frame) (hz-winkel->xu hz-jetzt (fix *vfk-gefaelle-winkel*)))) + (setq frame (vfl-insert-gf-bogen-block frame 90 bogen-seite)) + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt fest-laenge (fix *vfk-gefaelle-winkel*))) + (vfl-acc-gf-seg (/ fest-laenge (cos rad3)) (fix *vfk-gefaelle-winkel*)) + (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-insert-gf-bogen-block frame 90 bogen-seite)) + ;; --- Nochmaliger rein rechnerischer Ruecksprung auf EXAKT 3 Grad NACH + ;; Bogen2 (Nutzer-Befund 2026-09-13: die Gefaellebogen_..._90_R500- + ;; Bloecke geben ihre eigene, REAL gemessene KS_AUS-Neigung zurueck - + ;; die weicht leicht von der eingehenden Neigung ab und fiel dann in + ;; die "flach"-Toleranz von vfl-gf-bogen-uebergang, was die PROBE + ;; direkt betrifft: die Probe ruft vfl-gf-bogen-uebergang naemlich MIT + ;; dem rohen frame direkt nach Bogen2 auf, NOCH BEVOR Fa gebaut wird - + ;; Fa's eigene Neigungs-Korrektur (explizites winkel=3) kommt fuer die + ;; Probe also zu spaet. Position (car frame) bleibt unveraendert, nur + ;; die Neigung wird hart auf *vfk-gefaelle-winkel* gesetzt - dasselbe + ;; Prinzip wie beim E1-Fix weiter oben. --- + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (make-frame-from-dir (car frame) (hz-winkel->xu hz-jetzt (fix *vfk-gefaelle-winkel*)))) + (setq hoehe-vor-fa (caddr (car frame))) + (setq p2x (car (car frame)) p2y (cadr (car frame))) + (setq hz2 (car (frame->hz-winkel frame))) + (setq hz2-rad (* (float hz2) (/ pi 180.0))) + ;; --- Dynamische Winkelwahl (Nutzer-Vorgabe 2026-09-13: "gegebene + ;; Laenge -> passenden Winkel waehlen" statt einem einzigen fest + ;; verdrahteten Winkel): S beginnt beim symmetrischen Grundfall (3 + ;; Grad, extra-grad=0) und wird in 3-Grad-Schritten steiler (6, 9, + ;; 12, ...), bis Fa/S beide baubar sind (>=0) - der FLACHSTE passende + ;; Winkel wird automatisch gewaehlt. Jede Erweiterung nutzt ECHTE + ;; Bausteine (vfl-gf-bogen-erweitern: moeglichst viele 6-Grad-, ein + ;; 3-Grad-Rest-Baustein). Je Kandidat: Probe-Bau+Messen (wie Option 4) + ;; von Bogen-auf-6 + Erweiterung + Rueckkehr + Bogen-ab-6 + Sep+ES + ;; (Fa=S=0) - ihr GESAMTER Hoehen- UND Lage-Beitrag haengt nur von der + ;; Ankunfts-Orientierung ab (hz2), nicht von Fa/S. Fa (fallend, VOR S, + ;; 3 Grad) und S (steigend, NACH Fa, s-winkel) sind die beiden + ;; Unbekannten in einem 2x2-System: Hoehenbilanz (S*tan(s-winkel)- + ;; Fa*tan3=D) UND Lage-Bilanz (Fa+S=T, Kolinearitaet zur Baseline + ;; eintritt-hz/dref). --- + ;; --- Separator ZWISCHEN Fa und dem auf_6-Uebergang: die Probe beginnt + ;; DIREKT bei p2 (ohne Fa/Sep) - Fa selbst steckt schon in der Gleichung + ;; (S-Fa), aber der Separator NACH Fa hat eine EIGENE, FESTE (vom + ;; Nutzer nicht beeinflussbare) Horizontal-/Hoehenwirkung, die sonst + ;; NIRGENDS mitgezaehlt wuerde (Bug-Fund 2026-09-13: realer Test lief + ;; durch, aber deltaX/deltaZ zur Baseline waren NICHT null). Analog zu + ;; Option 4's fix-dx/fix-dz (vfl-gf-auf-ab-solve) wird sein Fussabdruck + ;; hier explizit ergaenzt. --- + (setq sep-dx-planar (* *vfk-separator-laenge* (cos rad3))) + (setq sep-dz (* *vfk-separator-laenge* (sin rad3))) + (setq s-winkel (fix *vfk-gefaelle-winkel*)) + (setq versuche 0 gueltig nil) + (while (and (not gueltig) (< versuche 10)) + (setq extra-grad (- s-winkel (fix *vfk-gefaelle-winkel*))) + (setq rad-s (* (float s-winkel) (/ pi 180.0))) + (setq tan-s (/ (sin rad-s) (cos rad-s))) + (setq acc-gfbogen-save *vfl-acc-gfbogen* acc-sep-save *vfl-acc-separator*) + (setq probe-checkpoint (vf-lastent-ohne-attribute)) + (setq probe-frame-a (car (vfl-gf-bogen-uebergang frame (- (fix *vfk-gefaelle-winkel*))))) + (setq probe-frame-a (vfl-gf-bogen-erweitern probe-frame-a "auf" (- (fix *vfk-gefaelle-winkel*)) extra-grad)) + (setq probe-frame-a (vfl-gf-bogen-erweitern probe-frame-a "ab" (- s-winkel) extra-grad)) + (setq probe-frame-b (car (vfl-gf-bogen-uebergang probe-frame-a (fix *vfk-gefaelle-winkel*)))) + (setq probe-frame-c (vfl-insert-es-element "GF" probe-frame-b (car (frame->hz-winkel probe-frame-b)) + (fix *vfk-gefaelle-winkel*) (caddr (car probe-frame-b)) es-seite)) + (setq dz-fix (- (caddr (car probe-frame-c)) hoehe-vor-fa)) + (setq dx-fix (- (car (car probe-frame-c)) p2x)) + (setq dy-fix (- (cadr (car probe-frame-c)) p2y)) + (vfl-loesche-seit probe-checkpoint) + (setq *vfl-acc-gfbogen* acc-gfbogen-save *vfl-acc-separator* acc-sep-save) + (setq h-aussen-rest (+ aus-dz (- hoehe-vor-fa soll-hoehe) dz-fix (- sep-dz))) + (setq d-hoehe (- h-aussen-rest)) + (setq fixedx (+ p2x dx-fix) fixedy (+ p2y dy-fix)) + (setq t-lage (- (/ (- (vfl-kreuz2d (- fixedx p0x) (- fixedy p0y) dref-x dref-y)) + (vfl-kreuz2d (cos hz2-rad) (sin hz2-rad) dref-x dref-y)) + sep-dx-planar)) + (setq s (/ (+ d-hoehe (* t-lage tan3)) (+ tan3 tan-s))) + (setq fa (- t-lage s)) + (setq gueltig (and (>= s -0.01) (>= fa -0.01))) + (if (not gueltig) (setq s-winkel (+ s-winkel (fix *vfk-gefaelle-winkel*)))) + (setq versuche (1+ versuche)) + ) + (princ (ssg-textf "vfl-qc-uform-fa-s-echo" (list (rtos fa 2 0) (rtos s 2 0) (itoa s-winkel)))) + (if (not gueltig) + (progn + ;; --- Mindest-E1-Vorschlag (Nutzer-Vorgabe 2026-09-13, analog zu + ;; Option 4's Mindest-Gesamtlaenge): d(Fa)/d(E1) ist EXAKT konstant + ;; (haengt nur von s-winkel/e1-neigung ab, nicht von E1 selbst) - + ;; die Korrektur ist damit kein Schaetzwert, sondern eine exakte + ;; algebraische Aufloesung nach E1, bei der Fa (mit dem STEILSTEN + ;; probierten S-Winkel, hier also der beste erreichbare Fall) genau + ;; 0 wird. --- + (setq tan-e1neigung (/ (sin e1-neigung-rad) (cos e1-neigung-rad))) + (setq d-fa-de1 (/ (- tan-s tan-e1neigung) (+ tan3 tan-s))) + (setq e1-vorschlag (if (> d-fa-de1 0.0001) (+ e1-brutto (/ (- fa) d-fa-de1)) nil)) + (if e1-vorschlag + (princ (ssg-textf "vfl-qc-uform-fa-s-negativ-e1" (list (rtos fa 2 0) (rtos s 2 0) (rtos e1-vorschlag 2 0)))) + (princ (ssg-textf "vfl-qc-uform-fa-s-negativ" (list (rtos fa 2 0) (rtos s 2 0)))) + ) + (vfl-loesche-seit checkpoint)) + (progn + (setq extra-grad (- s-winkel (fix *vfk-gefaelle-winkel*))) + ;; --- Fa ECHT bauen (fallend, STANDARD 3 Grad, VOR S) + Sep --- + (setq frame (vfl-insert-gf-segment (car frame) hz2 fa (fix *vfk-gefaelle-winkel*))) + (vfl-acc-gf-seg (/ fa (cos rad3)) (fix *vfk-gefaelle-winkel*)) + (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-insert-separator frame)) + ;; --- Uebergang fallend->steigend (auf_6, STANDARD - Fa/Sep + ;; garantieren sauber 3 Grad davor) --- + (setq erg-bogen (vfl-gf-bogen-uebergang frame (- (fix *vfk-gefaelle-winkel*)))) + (setq frame (car erg-bogen)) + ;; --- S bei s-winkel Grad (dynamisch gewaehlt): die zusaetzliche + ;; Neigung wird mit ECHTEN Bausteinen erreicht (vfl-gf-bogen- + ;; erweitern, siehe dort). --- + (setq frame (vfl-gf-bogen-erweitern frame "auf" (- (fix *vfk-gefaelle-winkel*)) extra-grad)) + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt s (- s-winkel))) + (vfl-acc-gf-seg (/ s (cos rad-s)) (- s-winkel)) + (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-gf-bogen-erweitern frame "ab" (- s-winkel) extra-grad)) + (setq erg-bogen (vfl-gf-bogen-uebergang frame (fix *vfk-gefaelle-winkel*))) + (setq frame (car erg-bogen)) + (setq hz-jetzt (car (frame->hz-winkel frame))) + (setq frame (vfl-insert-es-element "GF" frame hz-jetzt (fix *vfk-gefaelle-winkel*) + (caddr (car frame)) es-seite)) + (setq p-aktuell (car frame)) + (setq letzter-typ "GF") + (setq ist-hoehe (caddr p-aktuell)) + (setq abweichung (vfl-kreuz2d (- (car p-aktuell) p0x) (- (cadr p-aktuell) p0y) dref-x dref-y)) + (princ (ssg-textf "vfl-qc-erfolg" + (list (rtos soll-hoehe 2 1) (rtos ist-hoehe 2 1) (rtos abweichung 2 1)))) + (setq fertig t) + ) + ) + ) + ) +) + ;; Horizontales Sub-Segment bauen. Die flache Zone (0 Grad) wird NICHT mehr ;; automatisch mit ab_3 auf die 3-Grad-Basis zurueckgefuehrt - das Stueck ENDET ;; FLACH. Der ab_3-Uebergang kommt erst, wenn ein 3-Grad-Element folgt @@ -3312,7 +4287,7 @@ ;; Separator-Einbau). Im Wizard-Modus zeigt sie SELBST den Dialog ;; (vflw_kettenende, radio-basiert) und legt die Antwort in die Pending- ;; Queue - analog zu vfl-frage-ist-endpunkt. -(defun vfl-frage-ist-kettenende ( / dat ergebnis gwahl) +(defun vfl-frage-ist-kettenende ( / dat ergebnis gwahl antwort) (princ (ssg-text "vfl-ist-kettenende-header")) (princ (ssg-text "vfl-kettenende-opt-ja-es")) (princ (ssg-text "vfl-kettenende-opt-ja-ohne-es")) @@ -3342,11 +4317,12 @@ ) ) ) - (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") (list (ssg-text "vfl-kettenende-opt-ja-es") (ssg-text "vfl-kettenende-opt-ja-ohne-es") (ssg-text "vfl-kettenende-opt-nein")) 3 "vfl-ist-kettenende-header")) + antwort) ;; --- Horizontaler Koerper: Frage-Schale (Name unveraendert) --- ;; Fragt Separator vor/nach und - im Ziel-Modus - "Ist der Endpunkt der @@ -3537,7 +4513,7 @@ ;; horizontale-mitte eingerechnet) bleibt dabei unveraendert. ((= richtung "Auf") (princ (ssg-text "vfl-stufe1-start")) - (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Auf" feste-hz)))) + (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Auf" feste-hz schon-flach)))) (if wahl (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) (progn @@ -3569,7 +4545,7 @@ ;; Verzweigung unten und zum "Auf"-Fallback oben. ((> winkel-natuerlich *vfk-gefaelle-winkel*) (princ (ssg-text "vfl-stufe1-start")) - (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Ab" feste-hz)))) + (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Ab" feste-hz schon-flach)))) (if wahl (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) (progn @@ -3587,19 +4563,22 @@ (progn (vfl-diag-add (ssg-text "vfl-stufe2-ungueltig")) (princ (ssg-text "vfl-stufe1-start")) - (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Ab" feste-hz)))) + (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Ab" feste-hz schon-flach)))) (if wahl (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) (list nil nil nil nil))))))))) ;; Budget-Globals zuruecksetzen (setq aus-dx save-ausdx aus-dz save-ausdz FESTE_HORIZONTAL save-feste) res) -;; Duenner Wrapper: eigene Mindestlaenge (kuerzer als Motor+Separator = kein +;; Duenner Wrapper: eigene Mindestlaenge (kuerzer als das Budget = kein ;; Abschluss baubar), sonst delegiert an vfl-winkel-stufe-entscheidung mit dem -;; Kettenende-Budget. -(defun vfl-body-zerlegung (deltaL deltaH richtung schon-flach) - (if (< deltaL *vfk-kettenende-mindestlaenge*) +;; Kettenende-Budget. es-gewuenscht=nil senkt das Budget von 800 (Motor+ +;; Separator) auf 500 (nur Motor) - siehe vfl-body-budget. +(defun vfl-body-zerlegung (deltaL deltaH richtung schon-flach es-gewuenscht / + budget) + (setq budget (vfl-body-budget es-gewuenscht)) + (if (< deltaL budget) (list nil nil nil nil) - (vfl-winkel-stufe-entscheidung deltaL deltaH richtung schon-flach *vfk-feste-horizontal-kettenende*))) + (vfl-winkel-stufe-entscheidung deltaL deltaH richtung schon-flach budget))) ;; Fragt Zielpunkt (XY) + Zielhoehe (Z) ab, zerlegt den Rest (vfl-body- ;; zerlegung, Standard-Logik) und baut den Koerper VOR dem Motor: gewinkeltes @@ -3621,7 +4600,7 @@ ;; werden hier nicht gebraucht. es-gewuenscht wirkt beim Aufrufer, der ;; ein-dx/ein-dz um den Aufruf herum nullt (kein ES-Fussabdruck reservieren); ;; letzt-hz wurde nur einer wirkungslosen Zuweisung zugefuehrt (siehe unten). -(defun vfl-body-abschluss-bauen (frame p-umlenk dL hzn hn schon-flach / +(defun vfl-body-abschluss-bauen (frame p-umlenk dL hzn hn schon-flach es-gewuenscht / dH richtn rad3 dec typ w lgf lvf gf2 cnt p0 tx ty letzt-hz antwort-gf2) (setq dH (- hn (caddr (car frame)))) @@ -3630,7 +4609,7 @@ (setq rad3 (* (float (ssg-cfg-or "vario" "gefaelle_winkel" 3)) (/ pi 180.0))) (princ (ssg-textf "vfl-kettenende-modus-ziel" (list (rtos dL 2 0) (rtos dH 2 0) richtn))) - (setq dec (vfl-body-zerlegung dL dH richtn schon-flach)) + (setq dec (vfl-body-zerlegung dL dH richtn schon-flach es-gewuenscht)) (setq typ (nth 0 dec) w (nth 1 dec) lgf (nth 2 dec) lvf (nth 3 dec)) (if (null typ) (progn @@ -3676,6 +4655,14 @@ ;; Frame noch flach (schon-flach, aber ein echter Winkel w<>0 ;; noetig), wird hier genau EINMAL konvertiert - kein Vorgriff mehr ;; am Funktionsanfang, daher kein doppeltes Bogenpaar. + ;; BEKANNTE LUECKE: vfl-nach-3grad deckt nur flach->fallend (0->+3) + ;; ab. Kommt der Frame hier STEIGEND an (-3 Grad, z.B. direkt nach + ;; einer per Zweig C gebauten steigenden GF OHNE zwischenzeitliches + ;; Kettenende), waere ein 6-Grad-Uebergang (vfl-bogen-uebergang, + ;; wie im Linie-GF-Abschluss) noetig, den es hier noch NICHT gibt - + ;; der Frame bliebe faelschlich steigend, vfs-vf-koerper baut dann + ;; auf falscher Basis. schon-flach deckt nur den (haeufigeren) + ;; flachen Fall ab (siehe berechne-alle-winkel/entry-dx/entry-dz). ((and (= typ "VF") lvf (> lvf 1.0)) (setq frame (vfl-nach-3grad frame)) (setq frame (vfl-frame-3grad (vfs-vf-koerper (car frame) richtn w lvf hzn) hzn)) @@ -3726,7 +4713,7 @@ ;; die gemessene Laenge und die aktuelle Kettenhoehe. Darum in dieser ;; Reihenfolge: flache Zone abschliessen -> Laenge messen -> Vorschlaege ;; berechnen -> Zielhoehe fragen -> bauen. -(defun vfl-body-abschluss (frame letzt-hz p-umlenk / +(defun vfl-body-abschluss (frame letzt-hz p-umlenk es-gewuenscht / linie-mess dL hzn hn schon-flach ergebnis dH richtn hoehe-vorschlaege hoehe-ab hoehe-auf hoehe-fallback) ;; Schon-flach VOR jeder Konvertierung feststellen - NICHT mehr blind auf @@ -3746,7 +4733,7 @@ ;; von vfl-body-zerlegung sofort als "nicht baubar" abgelehnt (kleineres ;; Budget als vfl-vf-entscheidung: nur Motor+Separator, 800mm statt ;; 1300mm) - siehe vfl-body-hoehe-vorschlaege/vfl-body-machbar-p. - (setq hoehe-vorschlaege (vfl-body-hoehe-vorschlaege (caddr (car frame)) dL)) + (setq hoehe-vorschlaege (vfl-body-hoehe-vorschlaege (caddr (car frame)) dL es-gewuenscht schon-flach)) (setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege)) (setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr (car frame)))) (vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf) @@ -3759,7 +4746,7 @@ (list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) (ssg-textf "vfl-prompt-hoehe-kettenende" (list (rtos hoehe-fallback 2 1)))))) (if (null hn) (setq hn hoehe-fallback)) - (setq ergebnis (vfl-body-abschluss-bauen frame p-umlenk dL hzn hn schon-flach)) + (setq ergebnis (vfl-body-abschluss-bauen frame p-umlenk dL hzn hn schon-flach es-gewuenscht)) ;; Klare Rueckmeldung statt nur der einfachen Bau-Fehlermeldung (die ;; steht schon in vfl-body-abschluss-bauen): die tatsaechlich gewaehlte ;; Zielhoehe + Strecke nennen, UND (falls vorhanden) die bereits VOR der @@ -3955,7 +4942,7 @@ (setq es-seite (vfl-frage-es-seite t)) (progn (setq save-eindx ein-dx save-eindz ein-dz) (setq ein-dx 0.0 ein-dz 0.0))) - (setq res3 (vfl-body-abschluss frame letzt-hz p-umlenk)) + (setq res3 (vfl-body-abschluss frame letzt-hz p-umlenk es-gewuenscht)) (if (not es-gewuenscht) (setq ein-dx save-eindx ein-dz save-eindz)) (if res3 @@ -4446,7 +5433,7 @@ (defun vfl-kette-typ-familie (typ) (cond ((member typ '("WRAPPER" "KURVE" "UMLENK" "MOTOR" "BOGENAUF" "BOGENAB")) "VF") - ((member typ '("GFBOGEN")) "GF") + ((member typ '("GFBOGEN" "GFVERTBOGEN")) "GF") (t nil) ) ) @@ -4872,7 +5859,8 @@ eingang-laenge winkel-hoehen-erg bogen-mass fest-drop fest-laenge eingang-fertig linie-ende-familie linie-ende-untermodus - res3 save-eindx save-eindz es-gewuenscht) + res3 save-eindx save-eindz es-gewuenscht + startpunkt-familie gf-kettenende-antwort) ;; "Zurueck"/"Abbrechen"-Flag ganz am Anfang zuruecksetzen (auch schon vor ;; der ersten Praeambel-Frage) - sonst wuerde ein von einem VORHERIGEN Lauf ;; noch gesetztes Flag (z.B. nach "Abbrechen") den allerersten vfl-in-*- @@ -4970,15 +5958,35 @@ (if (null start-hoehe) (setq start-hoehe (caddr startpunkt))) (setq startpunkt (list (car startpunkt) (cadr startpunkt) start-hoehe)) - (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-as-impl (list "vfl-as-setzen-frage"))) - (princ (ssg-text "vfl-as-setzen-frage")) - (princ (ssg-text "vfl-ja")) - (princ (ssg-text "vfl-as-nein")) - (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") - (list (ssg-text "vfl-ja") (ssg-text "vfl-as-nein")) 1 - "vfl-as-setzen-frage")) - (setq as-vorhanden (/= antwort "2")) + ;; Startpunkt-Erkennung VOR der AS-Frage: liegt der Punkt auf dem KS_AUS + ;; EINES beliebigen bestehenden Kettenbausteins (GF ODER VF, beliebiges + ;; Segment), ist ein AS-Element ueberfluessig - die Kette knuepft direkt + ;; an. WICHTIG: der Gate ist bewusst "erg gefunden", NICHT "Familie + ;; aufgeloest" - viele Bausteine (Staustrecke_SP_1000_mm/Separator) sind + ;; per Blockname allein GF/VF-uneindeutig (vfl-kette-typ-familie liefert + ;; dafuer nil), zaehlen aber trotzdem eindeutig als "hier steht schon ein + ;; Kettenbaustein" - genau dieser Fall (Kettenende = ein gewoehnliches + ;; GF-Geradenstueck) fragte bisher faelschlich noch nach dem AS-Element. + ;; startpunkt-familie bleibt nil in diesem uneindeutigen Fall; die Meldung + ;; faellt dann auf einen neutralen Text zurueck (kein falsches "GF"/"VF"). + ;; Nur wenn GAR KEIN KS_AUS in Toleranz gefunden wurde, wird wie bisher + ;; gefragt. + (setq erg (vfl-ks-aus-hz-an-punkt startpunkt)) + (setq startpunkt-familie (if erg (vfl-kette-typ-familie (cdr erg)) nil)) + (if erg + (progn + (princ (ssg-textf "vfl-as-auto-erkannt" (list (if startpunkt-familie startpunkt-familie (ssg-text "vfl-familie-neutral"))))) + (setq as-vorhanden nil)) + (progn + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-as-impl (list "vfl-as-setzen-frage"))) + (princ (ssg-text "vfl-as-setzen-frage")) + (princ (ssg-text "vfl-ja")) + (princ (ssg-text "vfl-as-nein")) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-as-nein")) 1 + "vfl-as-setzen-frage")) + (setq as-vorhanden (/= antwort "2")))) ;; *vfl-as-winkel*/*vfl-es-winkel* sind Globals (fuer vfl-as-winkel/-es-winkel- ;; Zugriff aus AS-/ES-Einfuegefunktionen) und muessen pro Kette zurueckgesetzt ;; werden - sonst wuerde ein WINKEL_AS-Attribut den Wert der VORHERIGEN Kette @@ -5009,6 +6017,14 @@ (setq letzter-typ nil fertig nil frame nil) (setq anzahl-gf 0 anzahl-vf 0) (vfl-acc-reset) + ;; *vfl-journal* wurde bisher NIRGENDS zurueckgesetzt (vfl-journal-reset war + ;; definiert, aber toter Code) - bei MEHREREN Ketten in derselben BricsCAD- + ;; Sitzung blieben die Eintraege der vorigen Kette(n) im globalen Journal + ;; stehen und wurden der naechsten Kette per (cons ...) VORANgestellt. Real + ;; beobachteter Bug: eine fremde Kette (anderer Test/Bau) landete mit in der + ;; XDATA der aktuellen Kette, mit Fehlfunktionen in der Attribut-/XDATA- + ;; Erzeugung (u.a. "bad argument type ... at [itoa]"). + (vfl-journal-reset) (while (not fertig) ;; --- Naechstes Element bestimmen --- @@ -5024,7 +6040,7 @@ ;; der Nutzer legt den Segmenttyp direkt fest, keine Geometrie-Automatik ;; mehr wie bei "Neue Linie BIS Kettenende" (die bleibt unveraendert und ;; nutzt weiterhin vfl-segment-entscheidung). - (princ (ssg-text "vfl-naechstes-element-header")) + (if (not *vfl-forciere-qc-modus*) (princ (ssg-text "vfl-naechstes-element-header"))) (setq linie-ende-modus nil) ;; Glied-Checkpoint am Iterationskopf setzen; Label wird nach der Auswahl ;; nachgetragen (vfl-journal-steplabel), damit jedes Glied seine eigene @@ -5036,8 +6052,18 @@ ;; Ketten eines vorherigen INSERTs konsistent uebersprungen werden. (setq seg-lastEnt (vf-lastent-ohne-attribute)) (vfl-journal-mark "?") + ;; Erzwungener QC-Modus (Linienzug-Modus 4/5 im Typ-Dispatcher + ;; c:VarioFoerderer, *vfl-forciere-qc-modus* = "4"/"5"): das Menue + ;; "Naechstes Element waehlen" komplett ueberspringen - diese Ketten + ;; bestehen IMMER nur aus dem einen "Linie-GF"-Glied (QC baut AS bis ES + ;; selbst und setzt fertig). Nur am allerersten Glied wirksam (kettenanfang); + ;; das Consumer-seitige Zuruecksetzen erfolgt in vfl-qc-linie-mit-gf. + (if *vfl-forciere-qc-modus* + (setq wahl "Linie-GF") + (progn (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-naechstes-element-impl (list (null frame)))) + (vl-catch-all-apply 'vflw-gruppe-naechstes-element-impl + (list (null frame) (if (null frame) startpunkt-familie nil)))) (if frame (progn (princ (ssg-text "vfl-menu-gf-bogen-1")) @@ -5088,7 +6114,10 @@ (t "Linie-GF"))) ; "3" oder leer ) ) + )) ;; Ende (progn ...) / (if *vfl-forciere-qc-modus* ...) ;; Segmenttyp steht fest -> Glied-Label nachtragen (fuer die Edit-Liste). + ;; Die Auswahl selbst wurde bereits automatisch echot (vfl-echo-antwort, + ;; zentral in vfl-in-value/-value-p verankert). (vfl-journal-steplabel wahl) (progn @@ -5265,16 +6294,66 @@ ;; steigende GF (Sonderfall, Zweig C, KEIN Separator), sonst (Default ;; "1") Endpunkt waehlen (Zweig A, heutiges Verhalten + Separator). (setq gf-laenge-modus "1") - (if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-gf-laenge-modus-impl nil)) - (princ (ssg-text "vfl-gf-laenge-modus-header")) - (princ (ssg-text "vfl-gf-laenge-modus-opt-endpunkt")) - (princ (ssg-text "vfl-gf-laenge-modus-opt-hoehe")) - (princ (ssg-text "vfl-gf-laenge-modus-opt-steigend")) - (setq gf-laenge-modus (vfl-menu (ssg-text "prompt-wahl-1-2") - (list (ssg-text "vfl-gf-laenge-modus-opt-endpunkt") - (ssg-text "vfl-gf-laenge-modus-opt-hoehe") - (ssg-text "vfl-gf-laenge-modus-opt-steigend")) 1 - "vfl-gf-laenge-modus-header")) + ;; Erzwungener QC-Modus (Linienzug-Modus 4/5 im Typ-Dispatcher + ;; c:VarioFoerderer, *vfl-forciere-qc-modus*): Frage komplett + ;; ueberspringen, gf-laenge-modus direkt auf den erzwungenen Wert + ;; setzen. Flag NACH Verbrauch zuruecksetzen (gilt nur fuer dieses + ;; eine, erste Glied). + (if *vfl-forciere-qc-modus* + (progn + (setq gf-laenge-modus *vfl-forciere-qc-modus*) + (setq *vfl-forciere-qc-modus* nil) + ) + (progn + (if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-gf-laenge-modus-impl nil)) + (princ (ssg-text "vfl-gf-laenge-modus-header")) + (princ (ssg-text "vfl-gf-laenge-modus-opt-endpunkt")) + (princ (ssg-text "vfl-gf-laenge-modus-opt-hoehe")) + (princ (ssg-text "vfl-gf-laenge-modus-opt-steigend")) + (princ (ssg-text "vfl-gf-laenge-modus-opt-qc")) + (setq gf-laenge-modus (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-gf-laenge-modus-opt-endpunkt") + (ssg-text "vfl-gf-laenge-modus-opt-hoehe") + (ssg-text "vfl-gf-laenge-modus-opt-steigend") + (ssg-text "vfl-gf-laenge-modus-opt-qc")) 1 + "vfl-gf-laenge-modus-header")) + ) + ) + ;; Option 4 ("QC Linie mit GF"): eigenstaendiger, vollstaendig + ;; berechneter AS->ES-Ablauf (vfl-qc-linie-mit-gf) - baut Kettenende + ;; SELBST (setzt fertig direkt), braucht daher NICHT die gemeinsame + ;; Kettenende-/ES-Vorfrage und NICHT den Zweig-A/B/C-Abschluss unten + ;; (der von einer normal weiterlaufenden GF ausgeht). Nur am echten + ;; Kettenanfang sinnvoll (braucht eine eigene AS-Seite) - siehe Gate + ;; in vfl-qc-linie-mit-gf. Option 5 ("QC Linie mit GF und U-Form", + ;; vfl-qc-linie-mit-gf-uform) funktioniert nach demselben Muster - + ;; ebenfalls eigenstaendig, baut Kettenende selbst. + (cond + ((= gf-laenge-modus "4") (vfl-qc-linie-mit-gf)) + ((= gf-laenge-modus "5") (vfl-qc-linie-mit-gf-uform)) + (t + (progn + ;; NEU: Kettenende/ES JETZT fragen - VOR der Laengen-/Gefaelle- + ;; Berechnung -, damit ein gewuenschtes ES-Element (Antwort "1") mit + ;; seinem echten Fussabdruck (ein-dx/ein-dz, ueber vf-set-as-masse- + ;; Gegenstueck vfl-es-masse-setzen INNERHALB von vfl-frage-es-seite + ;; gesetzt) SOFORT von der Ziel-Laenge/-Hoehe abgezogen wird (siehe die + ;; drei Zweige unten) - statt es nach dem fertigen Bau nur noch + ;; anzuhaengen, wodurch die Kette bisher um genau diesen Fussabdruck + ;; ueber den gepickten Punkt/die Zielhoehe hinausschoss. Analog zur + ;; Separator VOR/NACH-Reservierung, die schon vorher erfolgt. + ;; gf-kettenende-antwort wird im gemeinsamen Abschluss unten + ;; wiederverwendet statt die Frage dort ein zweites Mal zu stellen. + ;; BEKANNTE RESTUNGENAUIGKEIT (Zweig C, steigend): der Ausgleichsbogen + ;; zurueck auf die fallende Basis (vfl-bogen-uebergang im Abschluss, + ;; NACH dem Bau dieser GF) hat einen eigenen Fussabdruck, der hier + ;; NICHT mitgerechnet wird (analoge Luecke zu vfl-nach-3grad am + ;; Kettenende, siehe dortiger Kommentar) - die ein-dx/ein-dz-Reservierung + ;; unten ist daher fuer Zweig C eine Naeherung, kein exakter Treffer. + (setq gf-kettenende-antwort (vfl-frage-ist-kettenende)) + (setq es-seite nil) + (if (= gf-kettenende-antwort "1") + (setq es-seite (vfl-frage-es-seite nil))) (cond ((= gf-laenge-modus "3") ;; --- Zweig C: Steigende GF (Sonderfall, bis gf-max-winkel Grad) --- @@ -5310,6 +6389,10 @@ (list (rtos (caddr p-aktuell) 2 1))))) (if (null hoehe-neu) (setq hoehe-neu (caddr p-aktuell))) (setq deltaH (- hoehe-neu (caddr p-aktuell))) + ;; ES-Fussabdruck (Hoehen-Anteil) VORAB reservieren, siehe + ;; Kommentar bei gf-kettenende-antwort oben. + (if (= gf-kettenende-antwort "1") + (setq deltaH (max 0.0 (- deltaH (abs ein-dz))))) (if (< deltaH 0.0) (progn (vfl-meldung (ssg-text "vfl-alert-gf-steigend-falsche-richtung")) @@ -5356,6 +6439,10 @@ (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) ) ) + ;; ES-Fussabdruck VORAB reservieren, siehe Kommentar bei + ;; gf-kettenende-antwort oben. + (if (= gf-kettenende-antwort "1") + (setq deltaL (- deltaL (abs ein-dx)))) (if (< deltaL 1.0) (princ (ssg-text "vfl-fehler-linie-zu-kurz")) (progn @@ -5402,6 +6489,15 @@ (setq sep-nach-gf (= (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 2 "vfl-sep-nach-gf-frage") "1")) + ;; ES-Element (vfl-insert-es-element) bringt seinen eigenen + ;; Separator VOR dem ES-Block schon mit - ein zusaetzlicher + ;; Separator NACH waere ein zweiter, direkt anschliessender + ;; Separator (real beobachteter Bug). gf-kettenende-antwort steht + ;; schon vor dieser Frage fest (siehe oben). + (if (and sep-nach-gf (= gf-kettenende-antwort "1")) + (progn + (vfl-meldung (ssg-text "vfl-sep-nach-durch-es-ueberschrieben")) + (setq sep-nach-gf nil))) (setq sep-anzahl (+ (if sep-vor-gf 1 0) (if sep-nach-gf 1 0))) (setq gf-ok t) (setq hoehe-neu @@ -5421,6 +6517,10 @@ (progn (if (> sep-anzahl 0) (setq deltaH (max 0.0 (- deltaH (* sep-anzahl *vfk-separator-laenge* (sin rad3)))))) + ;; ES-Fussabdruck VORAB reservieren, siehe Kommentar bei + ;; gf-kettenende-antwort oben. + (if (= gf-kettenende-antwort "1") + (setq deltaH (max 0.0 (- deltaH (abs ein-dz))))) (if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-gefaelle-impl (list (vfl-gf-hoehe-vorschlag (caddr p-aktuell)) t nil))) @@ -5497,9 +6597,19 @@ (setq sep-nach-gf (= (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 2 "vfl-sep-nach-gf-frage") "1")) + ;; ES-Element bringt seinen eigenen Separator VOR dem + ;; ES-Block schon mit - siehe Kommentar im Zweig B oben. + (if (and sep-nach-gf (= gf-kettenende-antwort "1")) + (progn + (vfl-meldung (ssg-text "vfl-sep-nach-durch-es-ueberschrieben")) + (setq sep-nach-gf nil))) (setq sep-anzahl (+ (if sep-vor-gf 1 0) (if sep-nach-gf 1 0))) (if (> sep-anzahl 0) (setq deltaL (- deltaL (* sep-anzahl *vfk-separator-laenge* (cos rad3))))) + ;; ES-Fussabdruck VORAB reservieren, siehe Kommentar bei + ;; gf-kettenende-antwort oben. + (if (= gf-kettenende-antwort "1") + (setq deltaL (- deltaL (abs ein-dx)))) (if (< deltaL 1.0) (progn (princ (ssg-text "vfl-fehler-linie-zu-kurz")) (setq gf-ok nil))) (if gf-ok @@ -5581,21 +6691,21 @@ ;; --- Gemeinsamer Abschluss fuer ALLE drei Zweige --- (if gf-ok (progn - ;; Uebergangsbogen(n) einfuegen, falls die aktuelle Frame-Neigung - ;; nicht zur Ziel-Neigung dieser Linie passt: noetig fuer den - ;; Steigend-Sonderfall (Zweig C, winkel < 0) UND falls der - ;; VORGAENGER eine steigende GF war und jetzt normal (Zweig A/B) - ;; weitergebaut wird. Im unveraenderten Normalfall (Vorgaenger- - ;; Neigung bereits 0/+3, Ziel +3 wie bisher) ist die Bedingung - ;; falsch - kein Verhaltensunterschied zu vorher. - (if (or (< winkel 0.0) (< (cadr (frame->hz-winkel frame)) (- *vfl-gf-winkel-toleranz*))) - (progn - (setq erg-bogen (vfl-bogen-uebergang frame winkel)) - (setq frame (car erg-bogen)) - (setq deltaL (- deltaL (cadr erg-bogen))) - (if (< deltaL 1.0) - (progn (princ (ssg-text "vfl-fehler-linie-zu-kurz")) (setq gf-ok nil))) - ) + ;; Uebergangsbogen(n) IMMER pruefen (vfl-gf-bogen-uebergang ist ein + ;; No-Op, wenn die aktuelle Frame-Neigung schon zur Ziel-Neigung + ;; passt - eigene Pruefung intern via t0=basis-ziel). Frueher nur + ;; fuer den Steigend-Sonderfall (winkel<0) und "Vorgaenger war + ;; steigend" ausgeloest - das uebersah reale Faelle wie flach-> + ;; fallend (z.B. nach einem horizontalen GF-Stueck) und fallend-> + ;; flach (z.B. vor einem horizontalen GF-Stueck), die genauso einen + ;; Bogen brauchen (Nutzer-Befund 2026-09-12: fehlende 3-Grad-Boegen + ;; zwischen Separator/fallender GF und einer horizontalen GF). + (progn + (setq erg-bogen (vfl-gf-bogen-uebergang frame winkel)) + (setq frame (car erg-bogen)) + (setq deltaL (- deltaL (cadr erg-bogen))) + (if (< deltaL 1.0) + (progn (princ (ssg-text "vfl-fehler-linie-zu-kurz")) (setq gf-ok nil))) ) (if gf-ok (progn @@ -5635,33 +6745,36 @@ (setq p-aktuell (car frame)) ) ) - (setq antwort (vfl-frage-ist-kettenende)) + ;; Kettenende/ES: BEREITS vor der Laengen-/Gefaelle-Berechnung + ;; erfragt (gf-kettenende-antwort/es-seite oben) - hier NICHT + ;; nochmal fragen (waere doppelt journalisiert und ein-dx/ + ;; ein-dz wurden dort schon fuer die Reservierung genutzt). (cond - ((= antwort "1") + ((= gf-kettenende-antwort "1") ;; ES-Element-Hardware gibt es nur fuer die Anfahrt auf der ;; STANDARD Fallend-Basis (+gefaelle-winkel) - kommt die - ;; Kette hier steigend an (Zweig C, winkel < 0), fehlt sonst - ;; der Rueckweg-Bogen und das ES-Element wuerde in einer - ;; physisch nicht existierenden "steigend"-Orientierung - ;; angehaengt. vfl-bogen-uebergang ist bei einer bereits - ;; fallenden Ankunft ein No-Op. - (if (< winkel 0.0) - (progn - (setq erg-bogen (vfl-bogen-uebergang frame *vfk-gefaelle-winkel*)) - (setq frame (car erg-bogen)) - (setq winkel *vfk-gefaelle-winkel*) - ) - ) - (setq es-seite (vfl-frage-es-seite nil)) + ;; Kette hier steigend ODER FLACH an (z.B. Zweig C mit + ;; winkel=0), fehlt sonst der Uebergangsbogen und das + ;; ES-Element wuerde in der falschen Orientierung + ;; angehaengt. IMMER pruefen (nicht nur bei winkel<0) - + ;; vfl-gf-bogen-uebergang ist bei einer bereits fallenden + ;; Ankunft ein No-Op (Nutzer-Befund 2026-09-12: horizontal + ;; vor ES fehlte der 3-Grad-Bogen). + (setq erg-bogen (vfl-gf-bogen-uebergang frame *vfk-gefaelle-winkel*)) + (setq frame (car erg-bogen)) + (setq winkel *vfk-gefaelle-winkel*) (setq frame (vfl-insert-es-element "GF" frame hz-neu winkel (caddr (car frame)) es-seite)) (setq fertig t)) - ((= antwort "2") (setq fertig t)) + ((= gf-kettenende-antwort "2") (setq fertig t)) ) ) ) ) ) + ) ;; Ende (progn ...) Zweig A/B/C (gf-laenge-modus <> "4"/"5") + ) ;; Ende (t ...) + ) ;; Ende (cond (gf-laenge-modus "4"/"5"/sonst) ...) ) ;; --- Neue Linie: Ab/Auf VF (Nutzer legt den Typ explizit fest) --- @@ -5877,7 +6990,7 @@ (if es-gewuenscht (setq es-seite (vfl-frage-es-seite t)) (progn (setq save-eindx ein-dx save-eindz ein-dz) (setq ein-dx 0.0 ein-dz 0.0))) - (setq res3 (vfl-body-abschluss frame (car (frame->hz-winkel frame)) (car frame))) + (setq res3 (vfl-body-abschluss frame (car (frame->hz-winkel frame)) (car frame) es-gewuenscht)) (if (not es-gewuenscht) (setq ein-dx save-eindx ein-dz save-eindz)) (if (null res3) (if dbg-an @@ -6130,6 +7243,9 @@ ;; noch frei in der Zeichnung liegen (vor dem -BLOCK-Sweep in ;; vfl-block-erstellen unten). (vl-catch-all-apply 'vfl-segment-xdata-sichern (list seg-lastEnt wahl)) + ;; Fortschritts-Echo: aktuelle Kettenposition nach diesem Glied (egal + ;; welcher wahl-Zweig lief) - siehe vfl-echo-position. + (vfl-echo-position p-aktuell) ) ) @@ -7381,7 +8497,7 @@ ;; terminale AS/ES-Masse fuer die mittige Bruecke ausblenden (Save/Restore) (setq o-adx aus-dx o-adz aus-dz o-eix ein-dx o-eiz ein-dz) (setq aus-dx 0.0 aus-dz 0.0 ein-dx 0.0 ein-dz 0.0) - (setq res (berechne-alle-winkel span (abs dH-signiert) richtung fh)) + (setq res (berechne-alle-winkel span (abs dH-signiert) richtung fh nil)) (setq aus-dx o-adx aus-dz o-adz ein-dx o-eix ein-dz o-eiz) (setq winkel (car res)) (if winkel (list winkel (cadr res) (caddr res) richtung) nil)) @@ -7492,7 +8608,7 @@ (setq richtung (if (< dH-signiert 0) "Auf" "Ab")) (setq o-adx aus-dx o-adz aus-dz o-eix ein-dx o-eiz ein-dz) (setq aus-dx 0.0 aus-dz 0.0 ein-dx 0.0 ein-dz 0.0) - (setq res (berechne-alle-winkel span (abs dH-signiert) richtung feste)) + (setq res (berechne-alle-winkel span (abs dH-signiert) richtung feste nil)) (setq aus-dx o-adx aus-dz o-adz ein-dx o-eix ein-dz o-eiz) (setq wahl (vfl-waehle-winkel (nth 3 res))) (if wahl (list (car wahl) (cadr wahl) (caddr wahl) richtung) nil)) @@ -7925,6 +9041,10 @@ (setq vfl-nummer (vf-next-number)) (setq lastEnt (vf-lastent-ohne-attribute)) (vfl-acc-reset) + ;; Siehe Kommentar bei vf-linienzug-modus: *vfl-journal* wurde bisher nie + ;; zurueckgesetzt und konnte Eintraege einer vorigen Kette (Modus 1 ODER 2) + ;; in dieselbe Sitzung hineintragen. + (vfl-journal-reset) (setq anzahl-gf 0 anzahl-vf 0 frame nil) ;; --- Abbruch-Sicherung ab hier scharf (analog Modus 1, siehe dortiger ;; Kommentar) - Phase A (oben) baut noch keine Geometrie, ein Abbruch @@ -8425,6 +9545,14 @@ ;; Bausteintyp aus dem Blocknamen ableiten. Scanner/Separator_SP (manuelle ;; Sensor-Bloecke, siehe count_sep_scan.lsp) gehoeren NICHT zur Kette selbst ;; und tauchen hier bewusst nicht auf. +;; VF- vs. GF-Vertikalboegen: BEIDE Familien teilen den Praefix +;; "Vario_Bogen_auf/ab_" - die VF-Bibliothek (init-bibliothek, Winkel 3-51) +;; traegt zusaetzlich "_TEF_" im Namen, die GF-eigenen Boegen (nur 3/6 Grad, +;; data/ils/Vario_Bogen_ab/auf_3/6_rechts.dwg, siehe vfl-gf-bogen-init) NICHT - +;; die "_TEF_"-Pruefung MUSS daher vor der generischen Pruefung stehen (cond +;; nimmt den ERSTEN Treffer). Damit erkennt ein KS_AUS-Scan (vfl-ks-aus-hz-an- +;; punkt/vfl-kette-typ-familie) eine mit einem GF-eigenen Bogen endende Kette +;; weiterhin korrekt als GF-Familie, nicht als VF. (defun vfl-kette-typ (bname) (cond ((wcmatch bname "VF_*") "WRAPPER") @@ -8434,8 +9562,10 @@ ((wcmatch bname "Vario_Kurve_*") "KURVE") ((wcmatch bname "Vario_Umlenkstation_*") "UMLENK") ((wcmatch bname "Vario_Motorstation_*") "MOTOR") - ((wcmatch bname "Vario_Bogen_auf_*") "BOGENAUF") - ((wcmatch bname "Vario_Bogen_ab_*") "BOGENAB") + ((wcmatch bname "Vario_Bogen_auf_*_TEF_*") "BOGENAUF") + ((wcmatch bname "Vario_Bogen_ab_*_TEF_*") "BOGENAB") + ((wcmatch bname "Vario_Bogen_auf_*") "GFVERTBOGEN") + ((wcmatch bname "Vario_Bogen_ab_*") "GFVERTBOGEN") ((wcmatch bname "Staustrecke_SP_1000_mm*") "STRECKE") ((wcmatch bname "Staustrecke_Separator_SP_300_mm*") "SEP") (t "UNBEKANNT") diff --git a/data/ils/Vario_Bogen_ab_3_rechts_2D.dwg b/data/ils/Vario_Bogen_ab_3_rechts_2D.dwg new file mode 100644 index 0000000..e8118f8 Binary files /dev/null and b/data/ils/Vario_Bogen_ab_3_rechts_2D.dwg differ diff --git a/data/ils/Vario_Bogen_ab_3_rechts_3D.dwg b/data/ils/Vario_Bogen_ab_3_rechts_3D.dwg new file mode 100644 index 0000000..0181e52 Binary files /dev/null and b/data/ils/Vario_Bogen_ab_3_rechts_3D.dwg differ diff --git a/data/ils/Vario_Bogen_ab_6_rechts_2D.dwg b/data/ils/Vario_Bogen_ab_6_rechts_2D.dwg new file mode 100644 index 0000000..3dd070d Binary files /dev/null and b/data/ils/Vario_Bogen_ab_6_rechts_2D.dwg differ diff --git a/data/ils/Vario_Bogen_ab_6_rechts_3D.dwg b/data/ils/Vario_Bogen_ab_6_rechts_3D.dwg new file mode 100644 index 0000000..5deb624 Binary files /dev/null and b/data/ils/Vario_Bogen_ab_6_rechts_3D.dwg differ diff --git a/data/ils/Vario_Bogen_auf_3_rechts_2D.dwg b/data/ils/Vario_Bogen_auf_3_rechts_2D.dwg new file mode 100644 index 0000000..1d0c330 Binary files /dev/null and b/data/ils/Vario_Bogen_auf_3_rechts_2D.dwg differ diff --git a/data/ils/Vario_Bogen_auf_3_rechts_3D.dwg b/data/ils/Vario_Bogen_auf_3_rechts_3D.dwg new file mode 100644 index 0000000..2825383 Binary files /dev/null and b/data/ils/Vario_Bogen_auf_3_rechts_3D.dwg differ diff --git a/data/ils/Vario_Bogen_auf_6_rechts_2D.dwg b/data/ils/Vario_Bogen_auf_6_rechts_2D.dwg new file mode 100644 index 0000000..922fe99 Binary files /dev/null and b/data/ils/Vario_Bogen_auf_6_rechts_2D.dwg differ diff --git a/data/ils/Vario_Bogen_auf_6_rechts_3D.dwg b/data/ils/Vario_Bogen_auf_6_rechts_3D.dwg new file mode 100644 index 0000000..51d81cf Binary files /dev/null and b/data/ils/Vario_Bogen_auf_6_rechts_3D.dwg differ diff --git a/dcl/variofoerderer.dcl b/dcl/variofoerderer.dcl index 7b33694..ef475a9 100644 --- a/dcl/variofoerderer.dcl +++ b/dcl/variofoerderer.dcl @@ -79,6 +79,14 @@ vfc_linienzug_modus : dialog { key = "modus_3"; label = "3D-Objekte stueckweise (Vorwaerts-Nachbau, in Arbeit)"; } + : radio_button { + key = "modus_4"; + label = "QC Linie mit GF (automatische Auf-Ab-Berechnung)"; + } + : radio_button { + key = "modus_5"; + label = "QC Linie mit GF und U-Form"; + } } // "Zurueck" springt hier sinnvoll zur Anlagen-Typ-Frage zurueck (siehe diff --git a/dcl/vf_linienzug_wizard.dcl b/dcl/vf_linienzug_wizard.dcl index c30a310..b2ea51a 100644 --- a/dcl/vf_linienzug_wizard.dcl +++ b/dcl/vf_linienzug_wizard.dcl @@ -219,6 +219,36 @@ vflw_winkel_seite : dialog { } } +// 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. +vflw_qc_winkel : 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"; } + } + } + + : 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; } + } +} + // Vario-Kurve: Winkel + Seite + Variante (aussen/innen) in einem Bildschirm. // Radio-Buttons statt Dropdown, Labels fest deutsch. vflw_variokurve : dialog { @@ -330,6 +360,7 @@ vflw_gf_laenge_modus : dialog { : radio_button { key = "modus_endpunkt"; label = "Endpunkt waehlen (Laenge ergibt sich)"; value = "1"; } : radio_button { key = "modus_hoehe"; label = "Zielhoehe festlegen (Laenge wird berechnet)"; } : radio_button { key = "modus_steigend"; label = "Steigende GF (Sonderfall, bis 3 Grad)"; } + : radio_button { key = "modus_qc"; label = "QC Linie mit GF (automatische Auf-Ab-Berechnung)"; } } } diff --git a/lang/de_DE.json b/lang/de_DE.json index f9e0b35..399d01f 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -6,6 +6,11 @@ "vfl-abgebrochen": "\nAbgebrochen.", "vfl-as-setzen-frage": "\n\nAS-Element setzen?", "vfl-as-nein": "\n 2 - Nein (Kette beginnt direkt mit GF/VF am Startpunkt)", + "vfl-as-auto-erkannt": "\n>>> Startpunkt liegt auf KS_AUS einer bestehenden %1-Kette - kein AS-Element noetig.", + "vfl-familie-neutral": "GF/VF", + "vfl-sep-nach-durch-es-ueberschrieben": "\n>>> Separator NACH ignoriert - das ES-Element bringt beim Kettenende bereits seinen eigenen Separator mit (sonst zwei Separatoren hintereinander).", + "vfl-echo-position": "\n>>> Position: X=%1 Y=%2 Z=%3", + "vfl-echo-wahl": "\n>>> Gewaehlt: %1", "vfl-aus-seite-header": "\n\nAUS-Element (AS_Element_*) - Seite waehlen:", "vfl-naechstes-element-header": "\n\nNaechstes Element waehlen:", "vfl-menu-gf-bogen-1": "\n 1 - GF-Bogen (horizontale Kurve)", @@ -48,6 +53,28 @@ "vfl-gf-laenge-modus-opt-endpunkt": "\n 1 - Endpunkt waehlen (Laenge ergibt sich)", "vfl-gf-laenge-modus-opt-hoehe": "\n 2 - Zielhoehe festlegen (Laenge wird berechnet)", "vfl-gf-laenge-modus-opt-steigend": "\n 3 - Steigende GF (Sonderfall, bis 3 Grad)", + "vfl-gf-laenge-modus-opt-qc": "\n 4 - QC Linie mit GF (automatische Auf-Ab-Berechnung)", + "vfl-qc-nur-kettenanfang": "\nFEHLER: 'QC Linie mit GF' ist nur am Kettenanfang moeglich (braucht eine eigene AS-Seite) - bitte anderen Modus waehlen.", + "vfl-qc-prompt-richtung": "\n\nRichtung waehlen (Gerade, auf der AS-Eintritt und ES-Austritt liegen sollen) - Punkt in Fahrtrichtung anklicken: ", + "vfl-qc-ks-ein-gemessen": "\n>>> AS KS_EIN (Referenzgerade) gemessen: X=%1 Y=%2 Z=%3", + "vfl-qc-ks-ein-nicht-gemessen": "\nWARNUNG: KS_EIN des AS-Elements konnte nicht gemessen werden - falle auf den Klickpunkt zurueck (Referenzgerade evtl. ungenau).", + "vfl-qc-prompt-e1": "\nFallend-GF Einlauf, inkl. Separator (mm) [%1]: ", + "vfl-qc-prompt-e2": "\nLaenge fallend-GF Auslauf nach dem zweiten 30-Grad-Bogen (mm) [%1]: ", + "vfl-qc-prompt-gesamtlaenge-mittelteil": "\nGesamtlaenge Mittelteil, ohne Ein-/Auslauf (mm): ", + "vfl-qc-prompt-anteil": "\nAnteil 1. Fallend-Stueck an F_total (0.0-1.0) [%1]: ", + "vfl-qc-nicht-baubar": "\nFEHLER: Diese Mittelteil-Laenge ist mit dieser Aufteilung nicht baubar (F_total=%1mm, S=%2mm - negativ). Bitte groessere Gesamtlaenge waehlen (mindestens ca. %3 mm).", + "vfl-qc-bogen-nicht-schliessbar": "\nFEHLER: Diese AS-/ES-Winkel-Kombination (AS-Schwenk=%1 Grad, ES-Schwenk=%2 Grad, benoetigter Bogen-Schwenk=%3 Grad) ist weder mit einem 30- noch mit einem 90-Grad-Bogen auf die Ausgangsgerade zurueckzufuehren. Bitte AS-/ES-Winkel anpassen (z.B. beide gleich waehlen).", + "vfl-qc-e2-negativ": "\nFEHLER: Die berechnete Laenge zwischen dem 2. Bogen und dem ES-Element ist nicht baubar (%1 mm). Bitte E1, Gesamtlaenge Mittelteil oder Anteil anpassen.", + "vfl-qc-erfolg": "\n>>> QC-Kette gebaut. Soll-Hoehe (AS-Austritt)=%1 Ist-Hoehe (ES-Austritt)=%2 Abweichung von der Ausgangsgeraden=%3mm", + "vfl-qc-uform-nur-kettenanfang": "\nFEHLER: 'QC Linie mit GF und U-Form' ist nur am Kettenanfang moeglich (braucht eine eigene AS-Seite) - bitte anderen Modus waehlen.", + "vfl-qc-uform-winkel-fix": "\nHinweis: AS-/ES-Winkel sind bei dieser Option fest auf 90 Grad (nur die Seite ist waehlbar).", + "vfl-qc-prompt-u-fest-laenge": "\nFeste Zwischenstrecke zwischen den beiden 90-Grad-Boegen (mm) [%1]: ", + "vfl-qc-uform-prompt-richtung-e1": "\n\nStartpunkt des 1. 90-Grad-Bogens anklicken (legt Fahrtrichtung UND Laenge des fallenden GF-Einlaufs inkl. Separator fest): ", + "vfl-qc-uform-e1-echo": "\n>>> E1 (inkl. Separator)=%1mm Richtung=%2 Grad", + "vfl-qc-uform-e1-neigung-echo": "\n>>> E1-Neigung (real an AS gemessen, KS_EIN->KS_AUS)=%1 Grad", + "vfl-qc-uform-fa-s-echo": "\n>>> Berechnet: Fa (fallend, 3 Grad, vor S)=%1mm S (steigend, %3 Grad, automatisch gewaehlt)=%2mm", + "vfl-qc-uform-fa-s-negativ": "\nFEHLER: Fa/S auch mit steileren S-Neigungswinkeln (bis 30 Grad probiert) nicht baubar (zuletzt Fa=%1mm S=%2mm). Bitte E1 oder die feste Zwischenstrecke anpassen.", + "vfl-qc-uform-fa-s-negativ-e1": "\nFEHLER: Fa/S auch mit steileren S-Neigungswinkeln (bis 30 Grad probiert) nicht baubar (zuletzt Fa=%1mm S=%2mm). Mindest-E1 (inkl. Separator) fuer den steilsten Winkel: ca. %3 mm.", "vfl-prompt-neigungswinkel-laenge-berechnet": "\nNeigungswinkel (Grad, 0 < Winkel <= %1) [%1] (deltaL wird berechnet und eingefuegt): ", "vfl-prompt-neigungswinkel-steigend": "\nSteigungswinkel (Grad, 0 <= Winkel <= %1, 0 = flach) [%1]: ", "vfl-alert-winkel-ungueltig-steigend": "Steigungswinkel ungueltig: %1 Grad. Erlaubt: 0 <= Winkel <= %2 Grad.", @@ -296,8 +323,8 @@ "vfc-block-einfuegepunkt": "\n Block-Einfuegepunkt: X=%1 Y=%2 Z=%3", "vfc-block-eingefuegt-ksaus": "\n '%1' eingefuegt\n KS_AUS: X=%2 Y=%3 Z=%4", "vfc-delta-l-h-richtung": "\n %1L=%2 mm %1H=%3 mm Fahrtrichtung=%4%5", - "vfc-endpunkt-xyz": "\n Endpunkt: X=%1 Y=%2 Z=%3", - "vfc-endpunkt-xyz-dxdz": "\n Endpunkt: X=%1 Y=%2 Z=%3 (dx=%4 dz=%5)", + "vfc-endpunkt-xyz": "\n KS_AUS: X=%1 Y=%2 Z=%3", + "vfc-endpunkt-xyz-dxdz": "\n KS_AUS: X=%1 Y=%2 Z=%3 (dx=%4 dz=%5)", "vfc-fahrtrichtung-ergebnis": "\n>>> Fahrtrichtung: %1%2", "vfc-fehler-block-datei-fehlt": "\n FEHLER: Block-Datei nicht gefunden: %1", "vfc-fehler-block-nicht-in-bibliothek": "\n FEHLER: Block '%1' nicht in Bibliothek", @@ -557,6 +584,12 @@ "vfl-abgebrochen-kein-ziel": "\n Abgebrochen - kein Zielpunkt gewaehlt.", "vfl-bogen-ab3-uebergang": "\n\nVario_Bogen_ab_3 (Uebergang horizontal -> 3 Grad)", "vfl-bogen-auf3-uebergang": "\n\nVario_Bogen_auf_3 (Uebergang 3 Grad -> horizontal)", + "vfl-gf-bogen-ab3-uebergang": "\n\nGF-Bogen Vario_Bogen_ab_3 (Uebergang horizontal -> 3 Grad, GF-eigen)", + "vfl-gf-bogen-auf3-uebergang": "\n\nGF-Bogen Vario_Bogen_auf_3 (Uebergang 3 Grad -> horizontal, GF-eigen)", + "vfl-gf-bogen-auf6-uebergang": "\n\nGF-Bogen Vario_Bogen_auf_6 (Uebergang fallend -> steigend, 6 Grad, GF-eigen)", + "vfl-gf-bogen-ab6-uebergang": "\n\nGF-Bogen Vario_Bogen_ab_6 (Uebergang steigend -> fallend, 6 Grad, GF-eigen)", + "vfl-gf-bogen-block-fehlt": "\n[GF-Bogen] Block '%1' nicht gefunden - siehe data/ils.", + "vfl-gf-bogen-ks-fehlt": "\n[GF-Bogen] KS_EIN/KS_AUS in '%1' fehlt oder unlesbar.", "vfl-gf-verteilung-ganz-einlauf": "\n 2 - Gesamte Staustrecke am Einlauf (GF1), kein GF2", "vfl-gf-verteilung-haelfte": "\n 1 - 1/2GF am Ausgang (GF2), 1/2GF am Einlauf (GF1)", "vfl-gf-verteilung-header": "\n\nStaustrecke (GF) - Verteilung waehlen:", @@ -885,6 +918,10 @@ "vfc-linienzug-modus-1": "\n 1 - Manuelle Eingabe (Punkte klicken)", "vfc-linienzug-modus-2": "\n 2 - 3D-Objekte + Ziel-Hoehe (Randwert-Solver, fertig)", "vfc-linienzug-modus-3": "\n 3 - 3D-Objekte stueckweise (Vorwaerts-Nachbau, in Arbeit)", + "vfc-linienzug-modus-4": "\n 4 - QC Linie mit GF (automatische Auf-Ab-Berechnung)", + "vfc-linienzug-modus-5": "\n 5 - QC Linie mit GF und U-Form", + "prompt-wahl-1-5": "\nIhre Wahl (1/2/3/4/5) [1]: ", + "vfl-qc-uform-nicht-implementiert": "\nFEHLER: 'QC Linie mit GF und U-Form' ist noch nicht implementiert - bitte Option 4 oder einen anderen Modus waehlen.", "vfc-typ-standard-beschreibung": "Standard VarioFoerderer (AS/ES 90 Grad, horizontal versetzt)", "vfc-typ-etage-beschreibung": "Etage VarioFoerderer (AS/ES 30 Grad, direkt uebereinander)", "vfc-typ-linienzug-beschreibung": "3D-Linienzug (gemischte GF/VF-Kette; Modus 1 manuell / Modus 2 Ziel-Hoehe fertig / Modus 3 stueckweise in Arbeit)", diff --git a/lang/en_GB.json b/lang/en_GB.json index 8c2bac1..5c99e72 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -6,6 +6,11 @@ "vfl-abgebrochen": "\nCancelled.", "vfl-as-setzen-frage": "\n\nPlace AS element?", "vfl-as-nein": "\n 2 - No (chain starts directly with GF/VF at the start point)", + "vfl-as-auto-erkannt": "\n>>> Start point lies on the KS_AUS of an existing %1 chain - no AS element needed.", + "vfl-familie-neutral": "GF/VF", + "vfl-sep-nach-durch-es-ueberschrieben": "\n>>> Separator AFTER ignored - the ES element already brings its own separator at the chain end (otherwise two separators in a row).", + "vfl-echo-position": "\n>>> Position: X=%1 Y=%2 Z=%3", + "vfl-echo-wahl": "\n>>> Selected: %1", "vfl-aus-seite-header": "\n\nOUT element (AS_Element_*) - select side:", "vfl-naechstes-element-header": "\n\nSelect next element:", "vfl-menu-gf-bogen-1": "\n 1 - GF arc (horizontal curve)", @@ -48,6 +53,28 @@ "vfl-gf-laenge-modus-opt-endpunkt": "\n 1 - Pick end point (length results from it)", "vfl-gf-laenge-modus-opt-hoehe": "\n 2 - Set target height (length will be calculated)", "vfl-gf-laenge-modus-opt-steigend": "\n 3 - Rising GF (special case, up to 3 degrees)", + "vfl-gf-laenge-modus-opt-qc": "\n 4 - QC line with GF (automatic up/down calculation)", + "vfl-qc-nur-kettenanfang": "\nERROR: 'QC line with GF' is only possible at the chain start (needs its own AS side) - please choose a different mode.", + "vfl-qc-prompt-richtung": "\n\nChoose direction (line on which AS entry and ES exit shall lie) - click a point in the travel direction: ", + "vfl-qc-ks-ein-gemessen": "\n>>> AS KS_EIN (reference line) measured: X=%1 Y=%2 Z=%3", + "vfl-qc-ks-ein-nicht-gemessen": "\nWARNING: could not measure the AS element's KS_EIN - falling back to the clicked point (reference line may be inaccurate).", + "vfl-qc-prompt-e1": "\nDescending GF entry, incl. separator (mm) [%1]: ", + "vfl-qc-prompt-e2": "\nLength of descending GF exit after the second 30-degree bend (mm) [%1]: ", + "vfl-qc-prompt-gesamtlaenge-mittelteil": "\nTotal middle section length, w/o entry/exit (mm): ", + "vfl-qc-prompt-anteil": "\nShare of 1st descending piece of F_total (0.0-1.0) [%1]: ", + "vfl-qc-nicht-baubar": "\nERROR: This middle-section length cannot be built with this split (F_total=%1mm, S=%2mm - negative). Please choose a larger total length (at least approx. %3 mm).", + "vfl-qc-bogen-nicht-schliessbar": "\nERROR: This AS/ES angle combination (AS turn=%1 deg, ES turn=%2 deg, required bend turn=%3 deg) cannot be closed back onto the reference line with either a 30- or a 90-degree bend. Please adjust the AS/ES angles (e.g. choose the same for both).", + "vfl-qc-e2-negativ": "\nERROR: The computed length between the 2nd bend and the ES element is not buildable (%1 mm). Please adjust E1, the middle section total length, or the share.", + "vfl-qc-erfolg": "\n>>> QC chain built. Target height (AS exit)=%1 Actual height (ES exit)=%2 Deviation from reference line=%3mm", + "vfl-qc-uform-nur-kettenanfang": "\nERROR: 'QC line with GF and U-shape' is only possible at the chain start (needs its own AS side) - please choose a different mode.", + "vfl-qc-uform-winkel-fix": "\nNote: AS/ES angles are fixed at 90 degrees for this option (only the side is selectable).", + "vfl-qc-prompt-u-fest-laenge": "\nFixed section between the two 90-degree bends (mm) [%1]: ", + "vfl-qc-uform-prompt-richtung-e1": "\n\nClick the start point of the 1st 90-degree bend (sets travel direction AND the descending GF entry length incl. separator): ", + "vfl-qc-uform-e1-echo": "\n>>> E1 (incl. separator)=%1mm direction=%2 deg", + "vfl-qc-uform-e1-neigung-echo": "\n>>> E1 slope (measured on AS, KS_EIN->KS_AUS)=%1 deg", + "vfl-qc-uform-fa-s-echo": "\n>>> Computed: Fa (descending, 3 deg, before S)=%1mm S (rising, %3 deg, auto-selected)=%2mm", + "vfl-qc-uform-fa-s-negativ": "\nERROR: Fa/S not buildable even with steeper S angles (tried up to 30 degrees) - last try Fa=%1mm S=%2mm. Please adjust E1 or the fixed section.", + "vfl-qc-uform-fa-s-negativ-e1": "\nERROR: Fa/S not buildable even with steeper S angles (tried up to 30 degrees) - last try Fa=%1mm S=%2mm. Minimum E1 (incl. separator) for the steepest angle: approx. %3 mm.", "vfl-prompt-neigungswinkel-laenge-berechnet": "\nIncline angle (degrees, 0 < angle <= %1) [%1] (deltaL will be calculated and inserted): ", "vfl-prompt-neigungswinkel-steigend": "\nRising angle (degrees, 0 <= angle <= %1, 0 = level) [%1]: ", "vfl-alert-winkel-ungueltig-steigend": "Rising angle invalid: %1 degrees. Allowed: 0 <= angle <= %2 degrees.", @@ -296,8 +323,8 @@ "vfc-block-einfuegepunkt": "\n Block insertion point: X=%1 Y=%2 Z=%3", "vfc-block-eingefuegt-ksaus": "\n '%1' inserted\n KS_AUS: X=%2 Y=%3 Z=%4", "vfc-delta-l-h-richtung": "\n %1L=%2 mm %1H=%3 mm Travel direction=%4%5", - "vfc-endpunkt-xyz": "\n End point: X=%1 Y=%2 Z=%3", - "vfc-endpunkt-xyz-dxdz": "\n End point: X=%1 Y=%2 Z=%3 (dx=%4 dz=%5)", + "vfc-endpunkt-xyz": "\n KS_AUS: X=%1 Y=%2 Z=%3", + "vfc-endpunkt-xyz-dxdz": "\n KS_AUS: X=%1 Y=%2 Z=%3 (dx=%4 dz=%5)", "vfc-fahrtrichtung-ergebnis": "\n>>> Travel direction: %1%2", "vfc-fehler-block-datei-fehlt": "\n ERROR: block file not found: %1", "vfc-fehler-block-nicht-in-bibliothek": "\n ERROR: block '%1' not in library", @@ -557,6 +584,12 @@ "vfl-abgebrochen-kein-ziel": "\n Cancelled - no target point selected.", "vfl-bogen-ab3-uebergang": "\n\nVario_Bogen_ab_3 (transition horizontal -> 3 degrees)", "vfl-bogen-auf3-uebergang": "\n\nVario_Bogen_auf_3 (transition 3 degrees -> horizontal)", + "vfl-gf-bogen-ab3-uebergang": "\n\nGF bogen Vario_Bogen_ab_3 (transition horizontal -> 3 degrees, GF-only)", + "vfl-gf-bogen-auf3-uebergang": "\n\nGF bogen Vario_Bogen_auf_3 (transition 3 degrees -> horizontal, GF-only)", + "vfl-gf-bogen-auf6-uebergang": "\n\nGF bogen Vario_Bogen_auf_6 (transition falling -> rising, 6 degrees, GF-only)", + "vfl-gf-bogen-ab6-uebergang": "\n\nGF bogen Vario_Bogen_ab_6 (transition rising -> falling, 6 degrees, GF-only)", + "vfl-gf-bogen-block-fehlt": "\n[GF bogen] Block '%1' not found - see data/ils.", + "vfl-gf-bogen-ks-fehlt": "\n[GF bogen] KS_EIN/KS_AUS in '%1' missing or unreadable.", "vfl-gf-verteilung-ganz-einlauf": "\n 2 - Entire buffer section at inlet (GF1), no GF2", "vfl-gf-verteilung-haelfte": "\n 1 - 1/2 GF at outlet (GF2), 1/2 GF at inlet (GF1)", "vfl-gf-verteilung-header": "\n\nBuffer section (GF) - choose distribution:", @@ -885,6 +918,10 @@ "vfc-linienzug-modus-1": "\n 1 - Manual entry (click points)", "vfc-linienzug-modus-2": "\n 2 - 3D objects + target height (boundary-value solver, finished)", "vfc-linienzug-modus-3": "\n 3 - 3D objects step by step (forward reconstruction, work in progress)", + "vfc-linienzug-modus-4": "\n 4 - QC line with GF (automatic up/down calculation)", + "vfc-linienzug-modus-5": "\n 5 - QC line with GF and U-shape", + "prompt-wahl-1-5": "\nYour choice (1/2/3/4/5) [1]: ", + "vfl-qc-uform-nicht-implementiert": "\nERROR: 'QC line with GF and U-shape' is not yet implemented - please choose option 4 or a different mode.", "vfc-typ-standard-beschreibung": "Standard VarioFoerderer (AS/ES 90 degrees, offset horizontally)", "vfc-typ-etage-beschreibung": "Etage VarioFoerderer (AS/ES 30 degrees, directly stacked)", "vfc-typ-linienzug-beschreibung": "3D line path (mixed GF/VF chain; mode 1 manual / mode 2 target height finished / mode 3 step by step work in progress)",