diff --git a/Lisp/Gefaellestrecke.lsp b/Lisp/Gefaellestrecke.lsp index 9a31d24..ba362cb 100644 --- a/Lisp/Gefaellestrecke.lsp +++ b/Lisp/Gefaellestrecke.lsp @@ -776,6 +776,9 @@ ;; AUS-Element: 30/90 (vor Seite), dann Seite (vor Winkelberechnung, da die ;; Laengenanpassung von der AS/ES-Masse abhaengt). Masse fuer Variante setzen. + (princ (ssg-text "vf-winkel-aus-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) (setq gf-as-winkel (vf-frage-element-winkel "vf-winkel-aus-header")) (princ (ssg-text "gf-seite-aus-header")) (princ (ssg-text "gf-seite-links")) @@ -785,6 +788,9 @@ (vf-set-as-masse gf-as-winkel as-seite) ;; EIN-Element: 30/90 + Seite + (princ (ssg-text "vf-winkel-ein-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) (setq gf-es-winkel (vf-frage-element-winkel "vf-winkel-ein-header")) (princ (ssg-text "gf-seite-ein-header")) (princ (ssg-text "gf-seite-links")) @@ -1760,6 +1766,9 @@ (setq winkel (float winkel)) ;; AUS-Element: 30/90 + Seite + (princ (ssg-text "vf-winkel-aus-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) (setq gf-as-winkel (vf-frage-element-winkel "vf-winkel-aus-header")) (princ (ssg-text "gf-seite-aus-header")) (princ (ssg-text "gf-seite-links")) @@ -1768,6 +1777,9 @@ (setq as-seite (if (= antwort "2") "rechts" "links")) ;; EIN-Element: 30/90 + Seite + (princ (ssg-text "vf-winkel-ein-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) (setq gf-es-winkel (vf-frage-element-winkel "vf-winkel-ein-header")) (princ (ssg-text "gf-seite-ein-header")) (princ (ssg-text "gf-seite-links")) diff --git a/Lisp/vf_core.lsp b/Lisp/vf_core.lsp index c9537d4..9b45dc1 100644 --- a/Lisp/vf_core.lsp +++ b/Lisp/vf_core.lsp @@ -598,9 +598,14 @@ ;; "vf-winkel-ein-header"). Rueckgabe: "30" oder "90" (Default 90). ;; Wizard: nutzt vflw-wahl (dcl/vf_linienzug_wizard.dcl, definiert in ;; vf_linienzug.lsp) falls dieses Modul geladen und *vfl-wizard-mode* aktiv -;; ist - sonst (oder bei jedem Fehler) unveraendert die Konsolen-Fragen -;; (princ + getstring, de/en ueber ssg-text). Gemeinsam genutzt von -;; Gefaellestrecke.lsp UND vf_linienzug.lsp. +;; ist - sonst (oder bei jedem Fehler) unveraendert die Konsolen-Frage +;; (getstring, de/en ueber ssg-text). Gemeinsam genutzt von Gefaellestrecke.lsp +;; UND vf_linienzug.lsp. Druckt selbst KEINE Kopfzeile/Optionstexte mehr (das +;; macht immer der AUFRUFER, unconditional, VOR diesem Aufruf) - sonst fehlt +;; die Kopfzeile in der Konsole genau dann, wenn ein vfl-in-value-Wrapper den +;; Wert bereits aus der Pending-Queue/dem Journal-Replay liest und diese +;; Funktion dadurch gar nicht erst aufgerufen wird (Inkonsistenz Dialog vs. +;; Konsole, siehe Aufrufer in vf_linienzug.lsp/Gefaellestrecke.lsp). (defun vf-frage-element-winkel (headerkey / antwort) ;; Wizard-Dialog nur, wenn Wizard-Modus aktiv, vflw-wahl geladen UND die GUI ;; global nicht abgeschaltet ist (Tests: (ssg-gui-aus)) - sonst Konsole/getstring. @@ -615,12 +620,7 @@ (if (or (vl-catch-all-error-p antwort) (null antwort) (= antwort "")) (setq antwort "1")) ) - (progn - (princ (ssg-text headerkey)) - (princ (ssg-text "vf-winkel-90")) - (princ (ssg-text "vf-winkel-30")) - (setq antwort (getstring (ssg-text "prompt-wahl-1-2"))) - ) + (setq antwort (getstring (ssg-text "prompt-wahl-1-2"))) ) (if (= antwort "2") "30" "90")) @@ -972,7 +972,7 @@ (setq horizontal-info nil) (if (and horizontal-p (= richtung "Ab")) (progn - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" nil)) (if (and horizontal-info (caddr horizontal-info)) (setq ergebnis-liste (append ergebnis-liste (list (list 0 (car horizontal-info) (cadr horizontal-info) T)))) @@ -1078,6 +1078,94 @@ ) ) +;; ============================================================ +;; TEIL 11b: DIALOG-AUSWAHL FUER TYP/LINIENZUG-MODUS (Radio-Buttons) +;; ============================================================ +;; Ersetzen die beiden Konsolen-Listen am Anfang von c:VarioFoerderer durch +;; Radio-Button-Dialoge (dcl/variofoerderer.dcl, vfc_typ/vfc_linienzug_modus) +;; - alle Optionen sofort sichtbar statt Dropdown. WICHTIG: Radio-Button- +;; Labels sind im DCL fest auf Deutsch einprogrammiert (set_tile kann das +;; Label eines radio_button nicht setzen, nur den Zustand - siehe DCL- +;; Kommentar). Beide Funktionen geben deshalb nur dann etwas anderes als nil +;; zurueck, wenn GUI erlaubt ist (Tests: ssg-gui-aus) UND Deutsch aktiv ist - +;; sonst faellt der Aufrufer automatisch auf die alte, vollstaendig +;; uebersetzte Konsolen-Liste zurueck (unveraendert im Code stehen +;; geblieben). Rueckgabe jeweils: Ergebnis bei OK, 'ABBRUCH bei Cancel, nil +;; wenn der Dialog gar nicht erst gezeigt werden konnte/durfte. +;; "Zurueck" hat an dieser allerersten Frage der ganzen Anlage nichts, wohin es +;; zurueckspringen koennte - wird daher lokal aufgeloest: der Dialog wird +;; einfach erneut gezeigt (kein Sonderfall fuer den Aufrufer noetig). +(defun vfc-dialog-typ-waehlen ( / dcl-pfad dat gtyp ergebnis fertig) + (if (and (or (not (car (atoms-family 1 '("SSG-GUI-P")))) (ssg-gui-p)) + (= *ssg-lang* "de_DE") + (equal (mapcar 'car *vf-typ-registry*) '("standard" "etage" "linienzug"))) + (progn + (setq fertig nil) + (while (not fertig) + (setq fertig t) + (setq dcl-pfad (strcat (getenv "DXFM_DCL") "/variofoerderer.dcl")) + (setq dat (load_dialog dcl-pfad)) + (if (not (new_dialog "vfc_typ" dat)) + (progn (if (and dat (>= dat 0)) (unload_dialog dat)) (setq ergebnis nil)) + (progn + (set_tile "typ_standard" "1") + (action_tile "accept" + "(setq gtyp (cond ((= (get_tile \"typ_etage\") \"1\") \"etage\") + ((= (get_tile \"typ_linienzug\") \"1\") \"linienzug\") + (t \"standard\"))) + (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) (setq ergebnis gtyp)) + ((= ergebnis 2) (setq fertig nil)) ;; Zurueck: Dialog erneut zeigen + (t (setq ergebnis 'ABBRUCH)) + ) + ) + ) + ) + ergebnis + ) + nil + ) +) + +;; "Zurueck" springt zur Anlagen-Typ-Frage zurueck - Rueckgabe 'ZURUECK, vom +;; Aufrufer (c:VarioFoerderer) ausgewertet (dort erneuter Aufruf von +;; vfc-dialog-typ-waehlen statt hier lokal aufzuloesen). +(defun vfc-dialog-linienzug-modus-waehlen ( / dcl-pfad dat gmodus ergebnis) + (if (and (or (not (car (atoms-family 1 '("SSG-GUI-P")))) (ssg-gui-p)) + (= *ssg-lang* "de_DE")) + (progn + (setq dcl-pfad (strcat (getenv "DXFM_DCL") "/variofoerderer.dcl")) + (setq dat (load_dialog dcl-pfad)) + (if (not (new_dialog "vfc_linienzug_modus" dat)) + (progn (if (and dat (>= dat 0)) (unload_dialog dat)) nil) + (progn + (set_tile "modus_1" "1") + (action_tile "accept" + "(setq gmodus (cond ((= (get_tile \"modus_2\") \"1\") 2) + ((= (get_tile \"modus_3\") \"1\") 3) + (t 1))) + (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) gmodus) + ((= ergebnis 2) 'ZURUECK) + (t 'ABBRUCH) + ) + ) + ) + ) + nil + ) +) + ;; ============================================================ ;; TEIL 12: DISPATCHER c:VarioFoerderer ;; ============================================================ @@ -1088,7 +1176,7 @@ best-winkel L_GF L_GF1 L_GF2 L_VF idx eintrag wahl antwort verteilung-modus n-scanner vf-nummer hoehe-von hoehe-bis lastEnt - staustrecke-basis vf-insert) + staustrecke-basis vf-insert dlg-typ dlg-modus zurueck-zu-typ) (princ "\n=========================================") (princ (ssg-text "vfc-banner-titel")) @@ -1102,61 +1190,90 @@ ) ) - (if (and *vf-vorauswahl-typ* (assoc *vf-vorauswahl-typ* *vf-typ-registry*)) - (progn - (setq typ-eintr (assoc *vf-vorauswahl-typ* *vf-typ-registry*)) - (princ (ssg-textf "vfc-typ-vorgewaehlt" (list *vf-vorauswahl-typ*))) - (setq *vf-vorauswahl-typ* nil) - ) - (progn - (setq *vf-vorauswahl-typ* nil) - (princ (ssg-text "vfc-anlagen-typ-header")) - (setq idx 1) - (foreach eintr *vf-typ-registry* - (princ (ssg-textf "vfc-typ-option" (list idx (nth 3 eintr)))) - (setq idx (1+ idx)) + ;; Aeussere Schleife nur wegen "Zurueck" bei der Linienzug-Modus-Frage + ;; (springt zurueck zur Anlagen-Typ-Frage) - fuer Standard/Etage bleibt + ;; zurueck-zu-typ immer nil, die Schleife laeuft dann genau einmal. + (setq zurueck-zu-typ t) + (while zurueck-zu-typ + (setq zurueck-zu-typ nil) + (if (and *vf-vorauswahl-typ* (assoc *vf-vorauswahl-typ* *vf-typ-registry*)) + (progn + (setq typ-eintr (assoc *vf-vorauswahl-typ* *vf-typ-registry*)) + (princ (ssg-textf "vfc-typ-vorgewaehlt" (list *vf-vorauswahl-typ*))) + (setq *vf-vorauswahl-typ* nil) + ) + (progn + (setq *vf-vorauswahl-typ* nil) + (setq dlg-typ (vfc-dialog-typ-waehlen)) + (cond + ((eq dlg-typ 'ABBRUCH) (exit)) + (dlg-typ (setq typ-eintr (assoc dlg-typ *vf-typ-registry*))) + (t + ;; Dialog nicht verfuegbar/nicht erlaubt (GUI aus, andere Sprache, + ;; abweichende Registry) - alte Konsolen-Liste unveraendert. + (princ (ssg-text "vfc-anlagen-typ-header")) + (setq idx 1) + (foreach eintr *vf-typ-registry* + (princ (ssg-textf "vfc-typ-option" (list idx (nth 3 eintr)))) + (setq idx (1+ idx)) + ) + (setq wahl (getint (ssg-textf "vfc-prompt-wahl-1-n" + (list (length *vf-typ-registry*))))) + (if (or (null wahl) (< wahl 1) (> wahl (length *vf-typ-registry*))) + (setq wahl 1)) + (setq typ-eintr (nth (1- wahl) *vf-typ-registry*)) + ) + ) ) - (setq wahl (getint (ssg-textf "vfc-prompt-wahl-1-n" - (list (length *vf-typ-registry*))))) - (if (or (null wahl) (< wahl 1) (> wahl (length *vf-typ-registry*))) - (setq wahl 1)) - (setq typ-eintr (nth (1- wahl) *vf-typ-registry*)) ) - ) - (setq anlage-typ (nth 0 typ-eintr)) - (setq berechne-fn (nth 1 typ-eintr)) - (setq einfuege-fn (nth 2 typ-eintr)) - (princ (ssg-textf "vfc-typ-gewaehlt" (list anlage-typ))) + (setq anlage-typ (nth 0 typ-eintr)) + (setq berechne-fn (nth 1 typ-eintr)) + (setq einfuege-fn (nth 2 typ-eintr)) + (princ (ssg-textf "vfc-typ-gewaehlt" (list anlage-typ))) - ;; Sonderfall "linienzug": eigener Befehlsablauf (interaktive Mehrsegment- - ;; Kette mit gemischten GF/VF-Segmenten), passt nicht in das berechne-fn/ - ;; einfuege-fn-Schema fuer ein einzelnes durchgehendes Segment - siehe - ;; vf_linienzug.lsp. Dispatcht hier direkt und beendet den Standard-Ablauf. - (if (= anlage-typ "linienzug") - (progn - (princ (ssg-text "vfc-linienzug-modus-header")) - (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"))) - ;; Konsolen-Nummer -> interne Funktion: - ;; 2 = fertiger Ziel-Hoehe-Modus (intern vf-linienzug-modus2) - ;; 3 = alter Vorwaerts-Nachbau (intern vf-linienzug-modus3, wird umgebaut) - ;; 1/Default = frische manuelle Eingabe. Ein abgebrochener Bau bleibt als - ;; VF_n-Block stehen und wird per Doppelklick fortgesetzt/editiert - ;; (vfl-edit-ent), kein separater Menuepunkt noetig. - ;; Journal-Reset gilt fuer JEDEN frischen Bau, nicht nur Modus 1: Modus 2 - ;; schreibt sein Journal ebenfalls als XDATA (Marker "linienzug2"), erbte - ;; ohne Reset aber die Eintraege des Vorlaufs als Praefix - ein spaeterer - ;; Doppelklick spielte dann fremde Eingaben vor. Die Edit-/Konvertier-Pfade - ;; laufen nie hier durch (sie setzen ihre Queue selbst), darum ist das - ;; Hochziehen ein reiner Bugfix. Setzt zugleich *vfl-seg-glied-letzte* - ;; zurueck, das sonst vom Vorlauf stehenbleibt. - (vfl-journal-reset) - (cond ((= wahl 2) (vf-linienzug-modus2)) - ((= wahl 3) (vf-linienzug-modus3)) - (t (vf-linienzug-modus))) - (exit) + ;; Sonderfall "linienzug": eigener Befehlsablauf (interaktive Mehrsegment- + ;; Kette mit gemischten GF/VF-Segmenten), passt nicht in das berechne-fn/ + ;; einfuege-fn-Schema fuer ein einzelnes durchgehendes Segment - siehe + ;; vf_linienzug.lsp. Dispatcht hier direkt und beendet den Standard-Ablauf. + (if (= anlage-typ "linienzug") + (progn + (setq dlg-modus (vfc-dialog-linienzug-modus-waehlen)) + (cond + ((eq dlg-modus 'ABBRUCH) (exit)) + ((eq dlg-modus 'ZURUECK) (setq zurueck-zu-typ t)) + (dlg-modus (setq wahl dlg-modus)) + (t + ;; Dialog nicht verfuegbar/nicht erlaubt - alte Konsolen-Liste. + (princ (ssg-text "vfc-linienzug-modus-header")) + (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"))) + ) + ) + (if (not zurueck-zu-typ) + (progn + ;; Konsolen-Nummer -> interne Funktion: + ;; 2 = fertiger Ziel-Hoehe-Modus (intern vf-linienzug-modus2) + ;; 3 = alter Vorwaerts-Nachbau (intern vf-linienzug-modus3, wird umgebaut) + ;; 1/Default = frische manuelle Eingabe (Journal vorher zuruecksetzen). Ein + ;; abgebrochener Bau bleibt als VF_n-Block stehen und wird per Doppelklick + ;; fortgesetzt/editiert (vfl-edit-ent), kein separater Menuepunkt noetig. + ;; Journal-Reset gilt fuer JEDEN frischen Bau, nicht nur Modus 1: Modus 2 + ;; schreibt sein Journal ebenfalls als XDATA (Marker "linienzug2"), erbte + ;; ohne Reset aber die Eintraege des Vorlaufs als Praefix - ein spaeterer + ;; Doppelklick spielte dann fremde Eingaben vor. Die Edit-/Konvertier-Pfade + ;; laufen nie hier durch (sie setzen ihre Queue selbst), darum ist das + ;; Hochziehen ein reiner Bugfix. Setzt zugleich *vfl-seg-glied-letzte* + ;; zurueck, das sonst vom Vorlauf stehenbleibt. + (vfl-journal-reset) + (cond ((= wahl 2) (vf-linienzug-modus2)) + ((= wahl 3) (vf-linienzug-modus3)) + (t (vf-linienzug-modus))) + (exit) + ) + ) + ) ) ) @@ -1223,7 +1340,7 @@ ;; Bibliothek ist durch den berechne-fn-Aufruf oben bereits initialisiert. (if (and (= anlage-typ "standard") (= richtung "Ab")) (progn - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" nil)) (if (and horizontal-info (caddr horizontal-info)) (progn (setq ergebnis-liste diff --git a/Lisp/vf_konstanten.lsp b/Lisp/vf_konstanten.lsp index dba406c..9ee5599 100644 --- a/Lisp/vf_konstanten.lsp +++ b/Lisp/vf_konstanten.lsp @@ -271,6 +271,11 @@ ;; Wert geometrisch herleiten laesst statt empirisch fixiert zu bleiben. (if (null *vfk-bruecke-korrektur*) (setq *vfk-bruecke-korrektur* 10.48)) +;; Konstruktions-Obergrenze (mm) fuer die Gesamtlaenge eines zusammen- +;; haengenden VF-Laufs (Modus 2, vf-linienzug-modus2) - reiner Hinweis beim +;; Ueberschreiten, kein Abbruch. Aktiv referenziert. +(if (null *vfk-vf-laenge-max*) (setq *vfk-vf-laenge-max* 25000.0)) + (setq *vfk-konstanten-geladen* t) (princ "\nvf_konstanten geladen.") (princ) diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index 82c47df..9a59f92 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -612,11 +612,14 @@ (set_tile "kopf" (vflw-clean prompt)) (action_tile "accept" "(setq dlg-wert (get_tile \"wert\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") + (action_tile "back" "(done_dialog 2)") (setq ergebnis (start_dialog)) (unload_dialog dat) - (if (and (= ergebnis 1) dlg-wert (> (strlen dlg-wert) 0)) - (atof dlg-wert) - nil)))) + (cond + ((and (= ergebnis 1) dlg-wert (> (strlen dlg-wert) 0)) (atof dlg-wert)) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck") nil) + ((= ergebnis 0) (setq *vfl-wizard-abbruch-grund* "abbrechen") nil) + (t nil))))) (defun vflw-zahl (prompt / r) (setq r (vl-catch-all-apply 'vflw-zahl-impl (list prompt))) (if (vl-catch-all-error-p r) (getreal prompt) r)) @@ -639,9 +642,13 @@ (set_tile "opts" (itoa (max 0 (1- (if default-idx default-idx 1))))) (action_tile "accept" "(setq dlg-opt (get_tile \"opts\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") + (action_tile "back" "(done_dialog 2)") (setq ergebnis (start_dialog)) (unload_dialog dat) - (if (= ergebnis 1) (itoa (1+ (atoi dlg-opt))) "")))) + (cond + ((= ergebnis 1) (itoa (1+ (atoi dlg-opt)))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck") "") + (t (setq *vfl-wizard-abbruch-grund* "abbrechen") ""))))) (defun vflw-wahl (prompt optionen default-idx / r) (setq r (vl-catch-all-apply 'vflw-wahl-impl (list prompt optionen default-idx))) (if (vl-catch-all-error-p r) "" r)) @@ -684,6 +691,8 @@ (action_tile "pick" "(done_dialog 2)") (action_tile "accept" "(setq gwert (get_tile \"wert\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") + ;; Code 3 statt 2 - 2 ist hier schon durch "Punkt waehlen..." belegt. + (action_tile "back" "(done_dialog 3)") (setq ergebnis (start_dialog)) (unload_dialog dat) (cond @@ -697,7 +706,8 @@ (setq fertig t) (if (and gpunkt gwert (> (strlen gwert) 0)) (vflw-pending-push-all (list gpunkt (atof gwert))))) - (t (setq fertig t))) + ((= ergebnis 3) (setq fertig t) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq fertig t) (setq *vfl-wizard-abbruch-grund* "abbrechen"))) ) ) ) @@ -719,35 +729,35 @@ (progn (set_tile "kopf" (vflw-clean (ssg-text kopf-key))) (set_tile "setzen" "1") - (start_list "winkel") - (add_list (vflw-clean (ssg-text "vf-winkel-90"))) - (add_list (vflw-clean (ssg-text "vf-winkel-30"))) - (end_list) - (set_tile "winkel" "0") - (start_list "seite") - (add_list (vflw-clean (ssg-text "gf-seite-links"))) - (add_list (vflw-clean (ssg-text "gf-seite-rechts"))) - (end_list) - (set_tile "seite" "0") + (set_tile "winkel_90" "1") + (set_tile "seite_links" "1") (action_tile "setzen" - "(mode_tile \"winkel\" (if (= (get_tile \"setzen\") \"1\") 0 1)) - (mode_tile \"seite\" (if (= (get_tile \"setzen\") \"1\") 0 1))") + "(mode_tile \"winkel_90\" (if (= (get_tile \"setzen\") \"1\") 0 1)) + (mode_tile \"winkel_30\" (if (= (get_tile \"setzen\") \"1\") 0 1)) + (mode_tile \"seite_links\" (if (= (get_tile \"setzen\") \"1\") 0 1)) + (mode_tile \"seite_rechts\" (if (= (get_tile \"setzen\") \"1\") 0 1))") (action_tile "accept" "(setq gsetzen (get_tile \"setzen\")) - (setq gwinkel (get_tile \"winkel\")) - (setq gseite (get_tile \"seite\")) + (setq gwinkel (if (= (get_tile \"winkel_30\") \"1\") \"30\" \"90\")) + (setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") + (action_tile "back" "(done_dialog 2)") (setq ergebnis (start_dialog)) (unload_dialog dat) - (if (= ergebnis 1) - (if (= gsetzen "1") - ;; Winkel-Slot wird von vfl-in-value (AS-Winkel, ueber - ;; vf-frage-element-winkel) konsumiert - der erwartet direkt - ;; "30"/"90", NICHT den Auswahl-Index wie beim Seite-Slot. - (vflw-pending-push-all - (list "1" (if (= gwinkel "1") "30" "90") (if (= gseite "1") "2" "1"))) - (vflw-pending-push-all (list "2")))))) + (cond + ((= ergebnis 1) + (if (= gsetzen "1") + ;; Winkel-Slot wird von vfl-in-value (AS-Winkel, ueber + ;; vf-frage-element-winkel) konsumiert - der erwartet direkt + ;; "30"/"90", NICHT den Auswahl-Index wie beim Seite-Slot. + (vflw-pending-push-all (list "1" gwinkel gseite)) + (vflw-pending-push-all (list "2")))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) (princ)) ;; ------------------------------------------------------------ @@ -759,31 +769,42 @@ ;; wird IMMER als echter Wert in die Pending-Queue geschrieben (nie als Index), ;; damit Journal/Log selbsterklaerend sind. GF-Bogen legt Zahlen ab (vom ;; vfl-menu-winkel/vfl-in-value als "INT" journalisiert), ES Strings "90"/"30". -(defun vflw-gruppe-winkel-seite-impl (kopf-key winkel-optionen winkel-werte / dat dcl-pfad ergebnis gwinkel gseite) +(defun vflw-gruppe-winkel-seite-impl (kopf-key winkel-optionen winkel-werte / + dat dcl-pfad ergebnis gwinkel-grad gseite) (setq dat (load_dialog (vflw-dcl-pfad))) (if (not (new_dialog "vflw_winkel_seite" dat)) (if (and dat (>= dat 0)) (unload_dialog dat)) (progn (set_tile "kopf" (vflw-clean (ssg-text kopf-key))) - (start_list "winkel") - (foreach o winkel-optionen (add_list (vflw-clean o))) - (end_list) - (set_tile "winkel" "0") - (start_list "seite") - (add_list (vflw-clean (ssg-text "gf-seite-links"))) - (add_list (vflw-clean (ssg-text "gf-seite-rechts"))) - (end_list) - (set_tile "seite" "0") + (if (not (vfl-winkel-in-liste-p 30 winkel-werte)) (mode_tile "winkel_30" 1)) + (if (not (vfl-winkel-in-liste-p 60 winkel-werte)) (mode_tile "winkel_60" 1)) + (if (not (vfl-winkel-in-liste-p 90 winkel-werte)) (mode_tile "winkel_90" 1)) + (set_tile (strcat "winkel_" (itoa (vfl-winkel-als-zahl (car winkel-werte)))) "1") + (set_tile "seite_links" "1") (action_tile "accept" - "(setq gwinkel (get_tile \"winkel\")) (setq gseite (get_tile \"seite\")) (done_dialog 1)") + "(setq gwinkel-grad (cond ((= (get_tile \"winkel_30\") \"1\") 30) + ((= (get_tile \"winkel_60\") \"1\") 60) + (t 90))) + (setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\")) + (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") + (action_tile "back" "(done_dialog 2)") (setq ergebnis (start_dialog)) (unload_dialog dat) - (if (= ergebnis 1) - (vflw-pending-push-all - (list - (nth (atoi gwinkel) winkel-werte) - (if (= gseite "1") "2" "1")))))) + (cond + ((= ergebnis 1) + ;; Original-Eintrag aus winkel-werte uebernehmen (nicht den nackten + ;; Grad-Wert) - erhaelt den Typ (INT fuer GF-Bogen, STR fuer ES). + (vflw-pending-push-all + (list (car (vl-remove-if-not + (function (lambda (w) (= (vfl-winkel-als-zahl w) gwinkel-grad))) + winkel-werte)) + gseite))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) (princ)) ;; ------------------------------------------------------------ @@ -797,37 +818,27 @@ (if (and dat (>= dat 0)) (unload_dialog dat)) (progn (set_tile "kopf" (vflw-clean (ssg-text "vfl-variokurve-winkel-header"))) - ;; Winkel-Reihenfolge vereinheitlicht auf 30/60/90 (wie GF-Bogen); - ;; Default 90 -> Listenposition 2. - (start_list "winkel") - (add_list (vflw-clean (ssg-text "vfl-opt3-30grad"))) - (add_list (vflw-clean (ssg-text "vfl-opt2-60grad"))) - (add_list (vflw-clean (ssg-text "vfl-opt1-90grad"))) - (end_list) - (set_tile "winkel" "2") - (start_list "seite") - (add_list (vflw-clean (ssg-text "gf-seite-links"))) - (add_list (vflw-clean (ssg-text "gf-seite-rechts"))) - (end_list) - (set_tile "seite" "0") - (start_list "variante") - (add_list (vflw-clean (ssg-text "vfl-variante-aussen"))) - (add_list (vflw-clean (ssg-text "vfl-variante-innen"))) - (end_list) - (set_tile "variante" "1") + (set_tile "winkel_90" "1") + (set_tile "seite_links" "1") + (set_tile "variante_innen" "1") (action_tile "accept" - "(setq gwinkel (get_tile \"winkel\")) - (setq gseite (get_tile \"seite\")) - (setq gvariante (get_tile \"variante\")) + "(setq gwinkel (cond ((= (get_tile \"winkel_30\") \"1\") 30) + ((= (get_tile \"winkel_60\") \"1\") 60) + (t 90))) + (setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\")) + (setq gvariante (if (= (get_tile \"variante_innen\") \"1\") \"2\" \"1\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") + (action_tile "back" "(done_dialog 2)") (setq ergebnis (start_dialog)) (unload_dialog dat) - (if (= ergebnis 1) - (vflw-pending-push-all - (list (nth (atoi gwinkel) *vfk-gf-bogen-winkel*) - (if (= gseite "1") "2" "1") - (if (= gvariante "1") "2" "1")))))) + (cond + ((= ergebnis 1) (vflw-pending-push-all (list gwinkel gseite gvariante))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) (princ)) ;; ------------------------------------------------------------ @@ -839,38 +850,114 @@ ;; vfl-in-abstand) - dessen Z-Konzept existiert nicht mehr, "Hoehe" hier ist ;; ein eigener, unabhaengiger Zahlenwert. Original-Reihenfolge/-Journal ab hier: ;; vfl-in-string (Modus), danach vfl-in-real (Winkel ODER Hoehe). -(defun vflw-gruppe-gefaelle-impl (hoehe-default / dat dcl-pfad ergebnis gmodus gwert winkel-default) +;; nur-winkel: T fuer den "Zielhoehe zuerst festlegen"-Zweig von "Neue Linie: +;; GF" (Zielhoehe ist dort BEREITS fix, deltaL wird erst aus Winkel+Hoehe +;; berechnet) - "Gegebene Hoehe" ergibt dann keinen Sinn mehr und wird per +;; mode_tile gesperrt, der Hinweistext zeigt stattdessen, dass deltaL +;; berechnet wird. Konventionswahl dieses Projekts (siehe vf-linienzug-modus, +;; wahl="Linie-GF"): Option "1" = Hoehe, Option "2" = Winkel - Hoehe ist +;; daher hier Default, nicht der DCL-eigene value="1" bei modus_winkel. +(defun vflw-gruppe-gefaelle-impl (hoehe-default nur-winkel / dat dcl-pfad ergebnis gmodus gwert winkel-default) (setq winkel-default (ssg-cfg-or "vario" "gefaelle_winkel" 3)) (setq dat (load_dialog (vflw-dcl-pfad))) (if (not (new_dialog "vflw_gefaelle" dat)) (if (and dat (>= dat 0)) (unload_dialog dat)) (progn (set_tile "kopf" (vflw-clean (ssg-text "vfl-gefaelle-festlegen-header"))) - (start_list "modus") - (add_list (vflw-clean (ssg-text "vfl-gefaelle-opt-hoehe"))) - (add_list (vflw-clean (ssg-text "vfl-gefaelle-opt-winkel"))) - (end_list) - (set_tile "modus" "0") - (set_tile "wlabel" "Zielhoehe (Z, mm):") - (set_tile "wert" (rtos hoehe-default 2 1)) + (if nur-winkel + (progn + (set_tile "modus_winkel" "1") + (set_tile "wlabel" "Neigungswinkel (Grad):") + (set_tile "wert" (rtos (float winkel-default) 2 1)) + (mode_tile "modus_hoehe" 1) + (set_tile "hinweis" (ssg-text "vfl-gf-hinweis-laenge-berechnet"))) + (progn + (set_tile "modus_hoehe" "1") + (set_tile "wlabel" "Zielhoehe (Z, mm):") + (set_tile "wert" (rtos hoehe-default 2 1)))) ;; Wertfeld MUSS beim Moduswechsel mit umschalten - sonst steht dort ;; nach dem Wechsel noch der Wert des vorherigen Modus (Hoehe/Winkel ;; sind nicht dieselbe Groesse, ein stehengebliebener Hoehenwert waere ;; als Neigungswinkel unsinnig). - (action_tile "modus" - "(if (= (get_tile \"modus\") \"0\") - (progn (set_tile \"wlabel\" \"Zielhoehe (Z, mm):\") - (set_tile \"wert\" (rtos hoehe-default 2 1))) - (progn (set_tile \"wlabel\" \"Neigungswinkel (Grad):\") - (set_tile \"wert\" (rtos (float winkel-default) 2 1))))") + (action_tile "modus_hoehe" + "(set_tile \"wlabel\" \"Zielhoehe (Z, mm):\") + (set_tile \"wert\" (rtos hoehe-default 2 1))") + (action_tile "modus_winkel" + "(set_tile \"wlabel\" \"Neigungswinkel (Grad):\") + (set_tile \"wert\" (rtos (float winkel-default) 2 1))") (action_tile "accept" - "(setq gmodus (get_tile \"modus\")) (setq gwert (get_tile \"wert\")) (done_dialog 1)") + "(setq gmodus (if (= (get_tile \"modus_winkel\") \"1\") \"2\" \"1\")) + (setq gwert (get_tile \"wert\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") + (action_tile "back" "(done_dialog 2)") (setq ergebnis (start_dialog)) (unload_dialog dat) - (if (= ergebnis 1) - (vflw-pending-push-all - (list (if (= gmodus "1") "2" "1") (atof gwert)))))) + (cond + ((= ergebnis 1) + (if nur-winkel + (vflw-pending-push-all (list (atof gwert))) + (vflw-pending-push-all (list gmodus (atof gwert))))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; "Neue Linie: GF" - Vorfrage "Wie soll die Laenge bestimmt werden?" +;; (Endpunkt/Zielhoehe/Steigende GF). Die verschachtelte Unterfrage bei +;; Zweig C (Endpunkt vs. Zielhoehe, nur 2 Optionen) zeigt bewusst KEINEN +;; eigenen Wizard-Dialog - der 3-Optionen-Dialog hier waere dort irrefuehrend +;; (dritte Kachel "Steigend" existiert in diesem Kontext gar nicht mehr). +(defun vflw-gruppe-gf-laenge-modus-impl ( / dat ergebnis gwahl) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_gf_laenge_modus" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-gf-laenge-modus-header"))) + (action_tile "accept" + "(setq gwahl (cond ((= (get_tile \"modus_hoehe\") \"1\") \"2\") + ((= (get_tile \"modus_steigend\") \"1\") \"3\") + (t \"1\"))) + (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 gwahl))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; "Neue Linie: GF" - Separator VOR/NACH (2 Ja/Nein-Toggles in einem +;; Bildschirm). Siehe dcl/vf_linienzug_wizard.dcl (vflw_sep_gf). +(defun vflw-gruppe-sep-gf-impl ( / dat ergebnis gsepvor gsepnach) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_sep_gf" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-sep-gf-header"))) + (set_tile "sepvor" "0") + (set_tile "sepnach" "0") + (action_tile "accept" + "(setq gsepvor (get_tile \"sepvor\")) (setq gsepnach (get_tile \"sepnach\")) (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 (if (= gsepvor "1") "1" "2") (if (= gsepnach "1") "1" "2")))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) (princ)) ;; ------------------------------------------------------------ @@ -912,49 +999,450 @@ (set_tile "wert" (rtos vorbelegt 2 1)) (action_tile "accept" "(setq dlg-wert (get_tile \"wert\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") + (action_tile "back" "(done_dialog 2)") (setq ergebnis (start_dialog)) (unload_dialog dat) - (if (and (= ergebnis 1) dlg-wert (> (strlen dlg-wert) 0)) - (vflw-pending-push-all (list (atof dlg-wert)))))) + (cond + ((and (= ergebnis 1) dlg-wert (> (strlen dlg-wert) 0)) + (vflw-pending-push-all (list (atof dlg-wert)))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + ((= ergebnis 0) (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) (princ)) +;; ============================================================ +;; TEIL 0b-4a: WEITERE GRUPPEN-DIALOGE (Modus 1, Radio-Buttons statt Dropdown) +;; ============================================================ + +;; Text in maximal max-zeilen Zeilen von je hoechstens max-len Zeichen +;; umbrechen (an Wortgrenzen; bereits vorhandene "\n" bleiben als Zeilenumbruch +;; erhalten) - fuer DCL-text-Tiles, die selbst NICHT automatisch umbrechen +;; (einzeiliges Tile, laengerer Text wird sonst stillschweigend abgeschnitten - +;; siehe vflw-gruppe-ja-nein-impl). Ueberzaehlige Zeilen werden auf eine "..."- +;; Zeile gekuerzt statt verworfen, damit sichtbar bleibt, dass Text fehlt. +(defun vflw-umbruch-zeilen (text max-len max-zeilen / roh-zeilen zeilen woerter aktuelle i gekuerzt) + (setq roh-zeilen (vfl-kette-split text "\n")) + (setq zeilen '()) + (foreach roh roh-zeilen + (setq woerter (vfl-kette-split roh " ") aktuelle nil) + (foreach wort woerter + (cond + ((= wort "")) + ((null aktuelle) (setq aktuelle wort)) + ((<= (+ (strlen aktuelle) 1 (strlen wort)) max-len) + (setq aktuelle (strcat aktuelle " " wort))) + (t (setq zeilen (append zeilen (list aktuelle))) + (setq aktuelle wort)))) + (setq zeilen (append zeilen (list (if aktuelle aktuelle ""))))) + (if (> (length zeilen) max-zeilen) + (progn + (setq gekuerzt '() i 0) + (repeat (1- max-zeilen) + (setq gekuerzt (append gekuerzt (list (nth i zeilen))) i (1+ i))) + (setq zeilen (append gekuerzt (list "..."))))) + zeilen) + ;; ------------------------------------------------------------ -;; Gruppe "Horizontales Stueck": Separator VOR + Separator NACH + -;; Foerderer-Ende (3 Optionen). Original-Reihenfolge/-Journal (alle in -;; vfl-baue-horizontal-koerper): vfl-in-string (Sep-vor), vfl-in-string -;; (Sep-nach), [nur im Ziel-Modus] vfl-in-string (Ist-Ende). Der Endpunkt -;; wird an der Aufrufstelle bereits separat ueber vfl-neue-linie-messen -;; gemessen - kein Punkt-Button hier (analog Gefaelle-/Ziel-Hoehe-Gruppe). -;; mit-ende: T, wenn (im Ziel-Modus) zusaetzlich die Ist-Ende-Frage -;; mitgestellt werden soll (siehe vfl-baue-horizontal-koerper). -(defun vflw-gruppe-horizontal-impl (mit-ende / dat dcl-pfad ergebnis gsepvor gsepnach gende) +;; Generische Ja/Nein-Rueckfrage (2 Radio-Buttons, dynamischer Kopftext ueber +;; MEHRERE Zeilen - siehe vflw-umbruch-zeilen, ein einzelnes text-Tile schneidet +;; laengere Hinweise sonst ab) - wiederverwendet ueberall dort, wo bisher eine +;; einzelne Ja/Nein-Frage auf den generischen Dropdown (vflw_wahl) +;; zurueckgefallen waere, z.B. "trotzdem mit Mindestlaenge bauen?" +;; (Zu-kurz-Nachfrage in vfl-baue-horizontal-koerper). +(defun vflw-gruppe-ja-nein-impl (kopf-txt / dat ergebnis gwahl zeilen zeile i dlg-name max-zeilen) + ;; Zeilenzahl VOR new_dialog ermitteln - waehlt eine von drei Groessen- + ;; varianten (1/3/6 Kopf-Zeilen), damit kurze Hinweise nicht mit leeren + ;; Zeilen aufgeblaeht werden (siehe Kommentar bei den vflw_ja_nein_*- + ;; Dialogen im DCL). + (setq zeilen (vflw-umbruch-zeilen (vflw-clean kopf-txt) 70 6)) + (cond + ((<= (length zeilen) 1) (setq dlg-name "vflw_ja_nein_1" max-zeilen 1)) + ((<= (length zeilen) 3) (setq dlg-name "vflw_ja_nein_3" max-zeilen 3)) + (t (setq dlg-name "vflw_ja_nein_6" max-zeilen 6))) (setq dat (load_dialog (vflw-dcl-pfad))) - (if (not (new_dialog "vflw_horizontal" dat)) + (if (not (new_dialog dlg-name dat)) (if (and dat (>= dat 0)) (unload_dialog dat)) (progn - (set_tile "kopf" "Horizontales Stueck") - (set_tile "sepvor" "0") - (set_tile "sepnach" "0") - (start_list "istende") - (add_list (vflw-clean (ssg-text "vfl-ja-nur-motorstation"))) - (add_list (vflw-clean (ssg-text "vfl-nein-weiterbauen"))) - (add_list (vflw-clean (ssg-text "vfl-ja-motorstation-kettenende"))) - (end_list) - (set_tile "istende" "1") - (mode_tile "istende" (if mit-ende 0 1)) + (setq i 1) + (foreach zeile zeilen + (set_tile (strcat "kopf" (itoa i)) zeile) + (setq i (1+ i))) + (while (<= i max-zeilen) (set_tile (strcat "kopf" (itoa i)) "") (setq i (1+ i))) + (set_tile "wahl_ja" "1") + (action_tile "accept" "(setq gwahl (get_tile \"wahl_nein\")) (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) + ;; Konsolen-Echo: im Wizard-Modus kommt die Antwort aus dem Dialog, + ;; nicht aus einer getippten Konsolen-Eingabe - ohne dieses Echo + ;; steht im (Debug-)Log/Konsolen-Log nirgends, was hier gewaehlt + ;; wurde. + (princ (ssg-textf "vfl-wizard-antwort-echo" + (list (ssg-text (if (= gwahl "1") "vfl-antwort-nein" "vfl-antwort-ja"))))) + (vflw-pending-push-all (list (if (= gwahl "1") "2" "1")))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; Generische Auf/Ab-Richtungsfrage (2 Radio-Buttons, dynamischer Kopftext) - +;; wiederverwendet fuer die Kletter-Teilstrecke ohne Zielhoehe, sowohl +;; "Naechstes im VF" als auch "Neue Linie: Ab/Auf VF" mit reduziertem +;; Eingang. +(defun vflw-gruppe-richtung-impl (kopf-txt / dat ergebnis grichtung) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_richtung" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean kopf-txt)) + (set_tile "richtung_auf" "1") + (action_tile "accept" "(setq grichtung (get_tile \"richtung_ab\")) (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 (if (= grichtung "1") "2" "1")))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; Startpunkt-Typ (kein eindeutiger GF-/VF-Baustein per KS_AUS-Scan erkannt, +;; siehe vfl-eingang-modus-bestimmen): EINE flache 3-Optionen-Frage (direkt +;; Umlenkstation / GF-Stueck+Umlenkstation / ohne Umlenkstation) statt +;; verschachtelter Zwei-Schritt-Abfrage. +(defun vflw-gruppe-startpunkt-typ-impl ( / dat ergebnis gwahl) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_startpunkt_typ" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-textf "vfl-frage-startpunkt-typ" (list (rtos *vfl-gf-min-laenge* 2 0))))) + (set_tile "eingang_direkt" "1") (action_tile "accept" - "(setq gsepvor (get_tile \"sepvor\")) - (setq gsepnach (get_tile \"sepnach\")) - (setq gende (get_tile \"istende\")) + "(setq gwahl (cond ((= (get_tile \"eingang_stumpf\") \"1\") \"2\") + ((= (get_tile \"eingang_ohne\") \"1\") \"3\") + (t \"1\"))) + (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 gwahl))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; "Ist das Kettenende?" (2-Optionen-Variante: Ja-Separator+ES / Nein- +;; weiterbauen) - vfl-vf-einheit-abschluss. +(defun vflw-gruppe-ist-kettenende-2opt-impl ( / dat ergebnis gwahl) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_ist_kettenende_2opt" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-ist-kettenende-frage"))) + (action_tile "accept" "(setq gwahl (get_tile \"wahl_ja\")) (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 (if (= gwahl "1") "1" "2")))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; --- Modus 2: Lauf-Abschluss (NUR wenn der VF-Lauf das Pfadende ist) --- +;; "1"=ohne Motorstation (offenes Ende) / "2"=Motorstation setzen (kein ES) / +;; "3"=Motorstation + ES-Element (Kettenende). Plain ok_cancel wie alle +;; anderen Modus-2-Segment-Dialoge - kein Zurueck/Abbrechen-Mechanismus. +(defun vflw-m2-lauf-abschluss-impl (kopf-txt / dat ergebnis gwahl) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_m2_lauf_abschluss" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean kopf-txt)) + (set_tile "abschluss_motor" "1") + (action_tile "accept" + "(setq gwahl (cond ((= (get_tile \"abschluss_offen\") \"1\") \"1\") + ((= (get_tile \"abschluss_motor_es\") \"1\") \"3\") + (t \"2\"))) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq ergebnis (start_dialog)) (unload_dialog dat) - (if (= ergebnis 1) - (vflw-pending-push-all - (append - (list (if (= gsepvor "1") "1" "2") (if (= gsepnach "1") "1" "2")) - (if mit-ende (list (itoa (1+ (atoi gende)))) nil)))))) + (if (= ergebnis 1) (vflw-pending-push-all (list gwahl))))) + (princ)) + +;; --- Modus 2: Lauf-Anfang (NUR wenn der VF-Lauf der Pfadanfang ist) --- +;; "1"=ohne Umlenkstation (offener Anfang) / "2"=Umlenkstation direkt (kein +;; GF1/Separator) / "3"=Umlenkstation mit GF1+Separator (heutiges Standard- +;; verhalten). Plain ok_cancel, analog vflw-m2-lauf-abschluss-impl. +(defun vflw-m2-lauf-anfang-impl (kopf-txt / dat ergebnis gwahl) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_m2_lauf_anfang" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean kopf-txt)) + (set_tile "anfang_umlenk_gf1" "1") + (action_tile "accept" + "(setq gwahl (cond ((= (get_tile \"anfang_offen\") \"1\") \"1\") + ((= (get_tile \"anfang_umlenk\") \"1\") \"2\") + (t \"3\"))) + (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (if (= ergebnis 1) (vflw-pending-push-all (list gwahl))))) + (princ)) + +;; GF-Verteilung (Haelfte Einlauf+Ausgang / alles Einlauf) - kopf-txt dynamisch, +;; wiederverwendet fuer Modus 1 (vfl-vf-einheit-abschluss) UND Modus 3 +;; (Segment-Loop br-gf-mode). Die beiden Aufrufer kodieren die Antwort +;; UNTERSCHIEDLICH (Modus 1: "1"=Haelfte/"2"=Einlauf; Modus 3: "2"=Haelfte/ +;; "1"=Einlauf) - haelfte-code/einlauf-code legen das je Aufrufer fest. +(defun vflw-gruppe-gf-verteilung-impl (kopf-txt haelfte-code einlauf-code / dat ergebnis gwahl) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_gf_verteilung" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean kopf-txt)) + (action_tile "accept" "(setq gwahl (get_tile \"wahl_haelfte\")) (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 (if (= gwahl "1") haelfte-code einlauf-code)))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; "Naechstes im VF" (innerhalb einer laufenden VF-Einheit weiterbauen): +;; Horizontaler Foerderer / Vario-Kurve / Auf-Ab-Foerderer. +(defun vflw-gruppe-naechstes-im-vf-impl ( / dat ergebnis gwahl) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_naechstes_im_vf" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-naechstes-element-vf"))) + (action_tile "accept" + "(setq gwahl (cond ((= (get_tile \"wahl_horizontal\") \"1\") \"1\") + ((= (get_tile \"wahl_variokurve\") \"1\") \"2\") + (t \"3\"))) + (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 gwahl))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; Feste Zuordnung Standard-Winkel -> Radio-Tile-Key, gemeinsam genutzt von +;; vflw-gruppe-winkel-hoehen-impl und vflw-gruppe-winkel-wahl-impl (beide +;; Dialoge nutzen dieselben 12 Slots w_3..w_51). +(setq *vflw-winkel-tile-keys* + '((3 . "w_3") (6 . "w_6") (9 . "w_9") (12 . "w_12") (15 . "w_15") (18 . "w_18") + (21 . "w_21") (27 . "w_27") (33 . "w_33") (39 . "w_39") (45 . "w_45") (51 . "w_51"))) + +;; Winkel/Hoehen-Tabelle (vfl-waehle-winkel-hoehen-tabelle): optionen +;; = ALLE konfigurierten Winkel (winkel dH-oder-nil L_VF-oder-nil gueltig), +;; gueltige = die daraus gefilterten baubaren. Fuer JEDEN der 12 Radio-Slots +;; wird das Text-Tile daneben befuellt: baubar -> Endhoehe, nicht baubar -> +;; Grund (wie die Konsolen-Zeile) - und NUR die baubaren werden per mode_tile +;; freigeschaltet. Pusht die POSITION (1-basiert) des gewaehlten Winkels +;; INNERHALB von gueltige, identisch zu dem, was vfl-menu-int an dieser +;; Aufrufstelle sonst liefern wuerde. +(defun vflw-gruppe-winkel-hoehen-impl (optionen gueltige start-z / dat ergebnis e gwinkel + tk htk zeile idx gefunden) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_winkel_hoehen" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-winkel-hoehen-header"))) + (foreach e optionen + (setq tk (cdr (assoc (car e) *vflw-winkel-tile-keys*))) + (if tk + (progn + (setq htk (strcat "h_" (substr tk 3))) + (if (nth 3 e) + (progn + (set_tile htk (ssg-textf "vfl-winkel-hoehen-zeile-tile" (list (rtos (+ start-z (nth 1 e)) 2 0)))) + (mode_tile tk 0) + ) + (progn + (set_tile htk (ssg-text "vfl-winkel-zeile-tile-ungueltig")) + (mode_tile tk 1) + ) + ) + ) + ) + ) + (setq gefunden nil) + (foreach e gueltige + (setq tk (cdr (assoc (car e) *vflw-winkel-tile-keys*))) + (if (and tk (not gefunden)) (progn (set_tile tk "1") (setq gefunden t))) + ) + (action_tile "accept" + "(setq gwinkel (cond + ((= (get_tile \"w_3\") \"1\") 3) ((= (get_tile \"w_6\") \"1\") 6) + ((= (get_tile \"w_9\") \"1\") 9) ((= (get_tile \"w_12\") \"1\") 12) + ((= (get_tile \"w_15\") \"1\") 15) ((= (get_tile \"w_18\") \"1\") 18) + ((= (get_tile \"w_21\") \"1\") 21) ((= (get_tile \"w_27\") \"1\") 27) + ((= (get_tile \"w_33\") \"1\") 33) ((= (get_tile \"w_39\") \"1\") 39) + ((= (get_tile \"w_45\") \"1\") 45) (t 51))) + (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) + (setq idx 1 zeile nil) + (foreach e gueltige + (if (= (car e) gwinkel) (setq zeile idx)) + (setq idx (1+ idx))) + (if zeile (vflw-pending-push-all (list zeile)))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; Winkel-Wahl aus berechne-alle-winkel (Zielhoehe-basierter Solve): +;; ergebnis-liste = ALLE konfigurierten Winkel (winkel L_GF L_VF gueltig), +;; gueltige = die daraus gefilterten baubaren (Filter komplexer als nur der +;; gueltig-Flag - siehe vfl-waehle-winkel: zusaetzlich L_GF/L_VF > 0 - +;; deshalb hier NICHT (nth 3 e) pruefen, sondern per gueltige-winkel-Liste +;; abgleichen). Fuer JEDEN der 12 Radio-Slots wird das Text-Tile daneben +;; befuellt: baubar -> L_GF+L_VF, nicht baubar -> "nicht baubar" - und NUR +;; die baubaren werden per mode_tile freigeschaltet. Pusht die POSITION +;; (1-basiert) des gewaehlten Winkels INNERHALB von gueltige. +(defun vflw-gruppe-winkel-wahl-impl (ergebnis-liste gueltige / dat ergebnis e gwinkel idx + tk htk zeile gefunden gueltige-winkel) + (setq gueltige-winkel (mapcar 'car gueltige)) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_winkel_wahl" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-mehrere-winkel-header"))) + (foreach e ergebnis-liste + (setq tk (cdr (assoc (car e) *vflw-winkel-tile-keys*))) + (if tk + (progn + (setq htk (strcat "h_" (substr tk 3))) + (if (member (car e) gueltige-winkel) + (progn + (set_tile htk (ssg-textf "vfl-winkel-wahl-zeile-tile" (list (rtos (cadr e) 2 1) (rtos (caddr e) 2 1)))) + (mode_tile tk 0) + ) + (progn + (set_tile htk (ssg-text "vfl-winkel-zeile-tile-ungueltig")) + (mode_tile tk 1) + ) + ) + ) + ) + ) + (setq gefunden nil) + (foreach e gueltige + (setq tk (cdr (assoc (car e) *vflw-winkel-tile-keys*))) + (if (and tk (not gefunden)) (progn (set_tile tk "1") (setq gefunden t))) + ) + (action_tile "accept" + "(setq gwinkel (cond + ((= (get_tile \"w_3\") \"1\") 3) ((= (get_tile \"w_6\") \"1\") 6) + ((= (get_tile \"w_9\") \"1\") 9) ((= (get_tile \"w_12\") \"1\") 12) + ((= (get_tile \"w_15\") \"1\") 15) ((= (get_tile \"w_18\") \"1\") 18) + ((= (get_tile \"w_21\") \"1\") 21) ((= (get_tile \"w_27\") \"1\") 27) + ((= (get_tile \"w_33\") \"1\") 33) ((= (get_tile \"w_39\") \"1\") 39) + ((= (get_tile \"w_45\") \"1\") 45) (t 51))) + (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) + (setq idx 1 zeile nil) + (foreach e gueltige + (if (= (car e) gwinkel) (setq zeile idx)) + (setq idx (1+ idx))) + (if zeile (vflw-pending-push-all (list zeile)))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + (princ)) + +;; "Naechstes Element waehlen" - Hauptmenue des Linienzug-Aufbaus (Modus 1). +;; Kettenanfang (frame=nil): alle 6 Optionen waehlbar, Vario-Kurve inklusive +;; (kann nur als allererstes Kettenglied gewaehlt werden - siehe Kommentar an +;; der Aufrufstelle). Sonst (Frame vorhanden): Vario-Kurve per mode_tile +;; deaktiviert, die uebrigen 5 Optionen behalten dieselbe Reihenfolge/ +;; Bedeutung wie im Konsolen-Menue, nur ohne die Luecke. Pusht die +;; POSITIONELLE Antwort ("1".."6" bzw. "1".."5"), identisch zur bisherigen +;; Konsolen-Nummerierung, damit Journal/Replay unveraendert bleiben - die +;; Radio-Buttons selbst tragen daher STABILE, kontextunabhaengige Keys +;; (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) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_naechstes_element" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-naechstes-element-header"))) + (set_tile "wahl_liniegf" "1") + (if (not kettenanfang) (mode_tile "wahl_variokurve" 1)) + (action_tile "accept" + "(setq slot (cond ((= (get_tile \"wahl_gfbogen\") \"1\") 1) + ((= (get_tile \"wahl_variokurve\") \"1\") 2) + ((= (get_tile \"wahl_linievf\") \"1\") 4) + ((= (get_tile \"wahl_horizontalvf\") \"1\") 5) + ((= (get_tile \"wahl_linieende\") \"1\") 6) + (t 3))) + (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) + (setq gwahl (if (or kettenanfang (<= slot 2)) slot (1- slot))) + (vflw-pending-push-all (list (itoa gwahl)))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) (princ)) ;; ============================================================ @@ -988,30 +1476,34 @@ ;; Original-Reihenfolge/-Journal im Loop: vfl-menu (Typ), dann bei GF ;; vfl-in-real (Neigung). Bei VF wird KEIN Neigungswert gefragt -> nur "2" ;; in die Pending-Queue. neigung-default: Vorbelegung Neigungsfeld (Grad). -(defun vflw-seg-linie-m2-impl (kopf-txt neigung-default / dat ergebnis gtyp gwert) +(defun vflw-seg-linie-m2-impl (kopf-txt neigung-default / dat ergebnis gtyp gwert gsepvor gsepnach) (setq dat (load_dialog (vflw-dcl-pfad))) (if (not (new_dialog "vflw_seg_linie_m2" dat)) (if (and dat (>= dat 0)) (unload_dialog dat)) (progn (set_tile "kopf" (vflw-clean kopf-txt)) - (start_list "typ") - (add_list (vflw-clean "GF (Neigungswinkel)")) - (add_list (vflw-clean "VF (Bruecke)")) - (end_list) - (set_tile "typ" "0") + (set_tile "typ_gf" "1") (set_tile "wert" (rtos (float neigung-default) 2 1)) - ;; Neigungsfeld nur bei GF (Index 0) aktiv. - (action_tile "typ" - "(mode_tile \"wert\" (if (= (get_tile \"typ\") \"0\") 0 1))") + ;; Neigungsfeld + Separator-Toggles nur bei GF aktiv. + (action_tile "typ_gf" + "(mode_tile \"wert\" 0) (mode_tile \"sep_vor\" 0) (mode_tile \"sep_nach\" 0)") + (action_tile "typ_vf" + "(mode_tile \"wert\" 1) (mode_tile \"sep_vor\" 1) (mode_tile \"sep_nach\" 1)") (action_tile "accept" - "(setq gtyp (get_tile \"typ\")) (setq gwert (get_tile \"wert\")) (done_dialog 1)") + "(setq gtyp (if (= (get_tile \"typ_gf\") \"1\") \"0\" \"1\")) + (setq gwert (get_tile \"wert\")) + (setq gsepvor (get_tile \"sep_vor\")) + (setq gsepnach (get_tile \"sep_nach\")) + (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq ergebnis (start_dialog)) (unload_dialog dat) (if (= ergebnis 1) (if (= gtyp "0") - (vflw-pending-push-all (list "1" (atof gwert))) ; GF + Neigung - (vflw-pending-push-all (list "2")))))) ; VF (keine Neigung) + ;; GF + Neigung + Separator VOR/NACH (Ja/Nein je "1"/"0") + (vflw-pending-push-all + (list "1" (atof gwert) (if (= gsepvor "1") "1" "2") (if (= gsepnach "1") "1" "2"))) + (vflw-pending-push-all (list "2")))))) ; VF (keine Neigung/Separator) (princ)) ;; --- Modus 3, Segment "Gerade": Typ (GF/VF-Ab/VF-Auf/VF-Hor) + Wert --- @@ -1025,33 +1517,33 @@ (if (and dat (>= dat 0)) (unload_dialog dat)) (progn (set_tile "kopf" (vflw-clean kopf-txt)) - (start_list "typ") - (add_list (vflw-clean "GF (Neigungswinkel)")) - (add_list (vflw-clean "VF-Ab")) - (add_list (vflw-clean "VF-Auf")) - (add_list (vflw-clean "VF-Horizontal")) - (end_list) - (set_tile "typ" "0") + (set_tile "typ_gf" "1") (set_tile "wlabel" "GF-Neigung (Grad):") (set_tile "wert" (rtos (float neigung-default) 2 1)) ;; Feld/Beschriftung schaltet mit dem Typ um: GF->Neigung, VF-Ab/Auf-> ;; Vario-Winkel, VF-Hor->deaktiviert. Werte-Defaults liegen als lokale ;; Variablen vor und werden im Callback (dynamic scope) gelesen. - (action_tile "typ" - "(cond - ((= (get_tile \"typ\") \"0\") - (set_tile \"wlabel\" \"GF-Neigung (Grad):\") - (set_tile \"wert\" (rtos (float neigung-default) 2 1)) - (mode_tile \"wert\" 0)) - ((= (get_tile \"typ\") \"3\") - (set_tile \"wlabel\" \"(kein Wert)\") - (mode_tile \"wert\" 1)) - (t - (set_tile \"wlabel\" \"Vario-Winkel (Grad):\") - (set_tile \"wert\" (rtos (float vario-default) 2 1)) - (mode_tile \"wert\" 0)))") + (action_tile "typ_gf" + "(set_tile \"wlabel\" \"GF-Neigung (Grad):\") + (set_tile \"wert\" (rtos (float neigung-default) 2 1)) + (mode_tile \"wert\" 0)") + (action_tile "typ_vfab" + "(set_tile \"wlabel\" \"Vario-Winkel (Grad):\") + (set_tile \"wert\" (rtos (float vario-default) 2 1)) + (mode_tile \"wert\" 0)") + (action_tile "typ_vfauf" + "(set_tile \"wlabel\" \"Vario-Winkel (Grad):\") + (set_tile \"wert\" (rtos (float vario-default) 2 1)) + (mode_tile \"wert\" 0)") + (action_tile "typ_vfhor" + "(set_tile \"wlabel\" \"(kein Wert)\") + (mode_tile \"wert\" 1)") (action_tile "accept" - "(setq gtyp (get_tile \"typ\")) (setq gwert (get_tile \"wert\")) (done_dialog 1)") + "(setq gtyp (cond ((= (get_tile \"typ_gf\") \"1\") \"0\") + ((= (get_tile \"typ_vfab\") \"1\") \"1\") + ((= (get_tile \"typ_vfauf\") \"1\") \"2\") + (t \"3\"))) + (setq gwert (get_tile \"wert\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq ergebnis (start_dialog)) (unload_dialog dat) @@ -1082,23 +1574,33 @@ (if (and dat (>= dat 0)) (unload_dialog dat)) (progn (set_tile "kopf" (vflw-clean kopf-txt)) - (start_list "typ") - (add_list (vflw-clean "GF-Bogen")) - (add_list (vflw-clean (if vario-erlaubt "Vario-Kurve" "Vario-Kurve (nur im VF-Lauf)"))) - (end_list) - (set_tile "typ" "0") - (start_list "variante") - (add_list (vflw-clean (ssg-text "vfl-variante-aussen"))) - (add_list (vflw-clean (ssg-text "vfl-variante-innen"))) - (end_list) - (set_tile "variante" "0") - (mode_tile "variante" 1) ; Variante erst bei Vario-Kurve aktiv - ;; Variante-Feld nur aktivieren, wenn Vario gewaehlt UND erlaubt. - (if vario-erlaubt - (action_tile "typ" - "(mode_tile \"variante\" (if (= (get_tile \"typ\") \"1\") 0 1))")) + (if (eq vario-erlaubt 'ERZWUNGEN) + (progn + (set_tile "typ_vario" "1") + (mode_tile "typ_gfbogen" 1) ; GF-Bogen gesperrt - Vario ist Pflicht + (mode_tile "variante_aussen" 0) ; Variante sofort aktiv + (mode_tile "variante_innen" 0)) + (progn + (set_tile "typ_gfbogen" "1") + (set_tile "variante_aussen" "1") + (mode_tile "variante_aussen" 1) ; Variante erst bei Vario-Kurve aktiv + (mode_tile "variante_innen" 1) + ;; Vario-Kurve-Option selbst nur anklickbar, wenn erlaubt (Modus 3 + ;; ausserhalb eines offenen VF-Laufs: deaktiviert - ihr Label kann + ;; hier NICHT auf "(nur im VF-Lauf)" umbeschriftet werden, radio_button- + ;; Labels sind fest, siehe DCL-Kommentar). + (if (not vario-erlaubt) (mode_tile "typ_vario" 1)) + ;; Variante-Feld nur aktivieren, wenn Vario gewaehlt UND erlaubt. + (if vario-erlaubt + (progn + (action_tile "typ_gfbogen" + "(mode_tile \"variante_aussen\" 1) (mode_tile \"variante_innen\" 1)") + (action_tile "typ_vario" + "(mode_tile \"variante_aussen\" 0) (mode_tile \"variante_innen\" 0)"))))) (action_tile "accept" - "(setq gtyp (get_tile \"typ\")) (setq gvariante (get_tile \"variante\")) (done_dialog 1)") + "(setq gtyp (if (= (get_tile \"typ_vario\") \"1\") \"1\" \"0\")) + (setq gvariante (if (= (get_tile \"variante_innen\") \"1\") \"1\" \"0\")) + (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq ergebnis (start_dialog)) (unload_dialog dat) @@ -1296,6 +1798,16 @@ ;; Gueltigkeit strenger geprueft werden muss (z.B. vfl-in-string: "" ist ein ;; gueltiger String), siehe vfl-in-value-p. (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/ + ;; -real/-int/vfl-menu/-menu-int komplett ab, statt jede Aufrufstelle im + ;; Bau-Ablauf einzeln pruefen zu muessen. Laeuft AUSSERHALB von vl-catch- + ;; all-apply (das umschliesst nur den vorgelagerten Gruppen-Dialog-Aufruf), + ;; (exit) erreicht also zuverlaessig den scharf geschalteten *error*-Handler. + (if *vfl-wizard-abbruch-grund* + (progn + (dbgmsg (strcat "ABBRUCH-TRIGGER: *vfl-wizard-abbruch-grund*=" *vfl-wizard-abbruch-grund* " -> (exit)")) + (exit))) (setq popped (if *vfl-replay-queue* (vfl-replay-pop) nil)) (if popped (setq v (car popped)) @@ -1311,6 +1823,11 @@ ;; Variante mit explizitem Gueltig-Praedikat (fuer vfl-in-string: "" ist gueltig). (defun vfl-in-value-p (kind gueltig-p livefn / popped v) + ;; Siehe Kommentar in vfl-in-value - derselbe zentrale Abbruch-Trigger. + (if *vfl-wizard-abbruch-grund* + (progn + (dbgmsg (strcat "ABBRUCH-TRIGGER: *vfl-wizard-abbruch-grund*=" *vfl-wizard-abbruch-grund* " -> (exit)")) + (exit))) (setq popped (if *vfl-replay-queue* (vfl-replay-pop) nil)) (if popped (setq v (car popped)) @@ -1804,6 +2321,89 @@ (if (not (boundp '*vfl-winkel-idx-vorgabe*)) (setq *vfl-winkel-idx-vorgabe* nil)) +;; Hilfsfunktionen fuer winkel-werte-Listen, die je nach Aufrufer Zahlen +;; (GF-Bogen) oder Strings (ES) enthalten koennen. +(defun vfl-winkel-als-zahl (w) (if (numberp w) w (atoi w))) +(defun vfl-winkel-in-liste-p (grad liste) + (vl-some (function (lambda (w) (= (vfl-winkel-als-zahl w) grad))) liste)) + +;; Punkt 7: fuer eine VF-Einheit mit reduziertem Eingang (eingang-modus <> +;; nil, siehe vfl-eingang-modus-bestimmen) gibt es KEINE frei waehlbare +;; GF-Laenge mehr, mit der eine beliebige Zielhoehe exakt getroffen werden +;; koennte (L_GF ist dort immer 0.0) - stattdessen wird der Kletter-Winkel +;; aus der Bogen-Bibliothek (*vfk-bogen-winkel* ueber ssg-cfg-or) probiert +;; und die sich daraus ERGEBENDE Endhoehe je Winkel tabellarisch angezeigt. +;; Rueckgabe je Zeile: (winkel dH L_VF gueltig). +(defun vfl-winkel-hoehen-optionen (deltaL richtung / winkel-list rad3 w + mass1 mass2 r2 winkel-eff radEff + bx1 bz1 bx2 bz2 L_VF dH gueltig ergebnisse) + (setq winkel-list (ssg-cfg-or "vario" "bogen_winkel" + '(3 6 9 12 15 18 21 27 33 39 45 51))) + (setq rad3 (* *vfk-gefaelle-winkel* (/ pi 180.0))) + (setq ergebnisse '()) + (foreach w winkel-list + (if (= richtung "Auf") + (setq mass1 (get-bogen-mass bogen-auf w) mass2 (get-bogen-mass bogen-ab w) + r2 (* (float (- *vfk-gefaelle-winkel* w)) (/ pi 180.0)) + winkel-eff (- w *vfk-gefaelle-winkel*)) + (setq mass1 (get-bogen-mass bogen-ab w) mass2 (get-bogen-mass bogen-auf w) + r2 (* (float (+ w *vfk-gefaelle-winkel*)) (/ pi 180.0)) + winkel-eff (+ w *vfk-gefaelle-winkel*))) + (setq dH nil L_VF nil gueltig nil) + (if (and mass1 mass2) + (progn + (setq bx1 (+ (* (car mass1) (cos rad3)) (* (caddr mass1) (sin rad3)))) + (setq bz1 (+ (* (- (car mass1)) (sin rad3)) (* (caddr mass1) (cos rad3)))) + (setq bx2 (+ (* (car mass2) (cos r2)) (* (caddr mass2) (sin r2)))) + (setq bz2 (+ (* (- (car mass2)) (sin r2)) (* (caddr mass2) (cos r2)))) + (setq radEff (* (float winkel-eff) (/ pi 180.0))) + (setq L_VF (/ (- deltaL bx1 bx2) (cos radEff))) + (if (> L_VF *vfk-restlaenge-min-clamp*) + (progn + (setq dH (+ bz1 bz2 (* L_VF (sin radEff)))) + (setq gueltig t) + ) + ) + ) + ) + (setq ergebnisse (append ergebnisse (list (list w dH L_VF gueltig)))) + ) + ergebnisse) + +;; UI zu vfl-winkel-hoehen-optionen: ALLE konfigurierten Winkel als Tabelle +;; zeigen (gueltige mit resultierender Endhoehe, ungueltige mit Hinweis +;; "Bogen passt nicht in die gewaehlte Strecke"), dann aus den GUELTIGEN +;; waehlen lassen. start-z = aktuelle Z-Koordinate (fuer die Anzeige der +;; absoluten Ende-Hoehe). Rueckgabe: (winkel dH L_VF gueltig) oder nil, wenn +;; kein einziger Winkel bei dieser Streckenlaenge baubar ist. +(defun vfl-waehle-winkel-hoehen-tabelle (deltaL richtung start-z / + optionen gueltige idx labels e antwort) + (setq optionen (vfl-winkel-hoehen-optionen deltaL richtung)) + (princ (ssg-text "vfl-winkel-hoehen-header")) + (foreach e optionen + (if (nth 3 e) + (princ (ssg-textf "vfl-winkel-hoehen-zeile" (list (car e) (rtos (+ start-z (nth 1 e)) 2 0)))) + (princ (ssg-textf "vfl-winkel-hoehen-zeile-ungueltig" (list (car e)))) + ) + ) + (setq gueltige (vl-remove-if-not (function (lambda (e) (nth 3 e))) optionen)) + (cond + ((null gueltige) nil) + ((= (length gueltige) 1) (car gueltige)) + (t + (setq idx 1 labels '()) + (foreach e gueltige + (setq labels (append labels + (list (ssg-textf "vfl-winkel-hoehen-option" + (list idx (car e) (rtos (+ start-z (nth 1 e)) 2 0)))))) + (setq idx (1+ idx))) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-winkel-hoehen-impl (list optionen gueltige start-z))) + (setq antwort (vfl-menu-int (ssg-textf "vfl-prompt-wahl-bis-n" (list (length gueltige))) + labels 1 "vfl-winkel-hoehen-header")) + (if (or (null antwort) (< antwort 1) (> antwort (length gueltige))) (setq antwort 1)) + (nth (1- antwort) gueltige)))) + ;; Frage-Schale (Name unveraendert, alle Aufrufstellen bleiben): gueltige ;; Kandidaten bestimmen, bei genau einem ohne Frage nehmen, sonst fragen - ;; bzw. die Vorgabe verwenden. @@ -1853,48 +2453,14 @@ ;; typ="VF": winkel = best-winkel (0 = Horizontale Mitte), L_GF/L_VF wie ;; berechne-alle-winkel bzw. berechne-horizontale-mitte ;; typ=nil : keine VF-Einheit fuer dieses deltaL/deltaH geometrisch moeglich -(defun vfl-vf-entscheidung (deltaL deltaH richtung / - winkel-natuerlich wahl horizontal-info) - (if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek)) - (cond - ;; Zu kurz fuer eine VF-Einheit: Umlenkstation (500 mm) + Motorstation - ;; (500 mm) belegen zusammen 1000 mm deltaL. - ((< deltaL *vfk-vf-mindestlaenge*) (list nil nil nil nil)) - - ;; Segment ohne messbare Hoehenaenderung: kein sinnvolles VF - ((< deltaH 1.0) (list nil nil nil nil)) - - ;; Steigend: bei mehreren gueltigen Winkeln waehlt der Nutzer (vfl-vf-winkel). - ((= richtung "Auf") - (setq wahl (vfl-vf-winkel deltaL deltaH "Auf")) - (if wahl - (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) - (list nil nil nil nil))) - - ;; Fallend: natuerlichen Neigungswinkel bestimmen (atan der Schraege). - ;; steiler als 3 Grad -> absteigender VarioFoerderer (VF-ab) - ;; sonst -> VF (Horizontale Mitte oder diskreter Winkel) - (t - (setq winkel-natuerlich (* (atan (/ deltaH deltaL)) (/ 180.0 pi))) - (if (> winkel-natuerlich *vfk-gefaelle-winkel*) - (progn - (setq wahl (vfl-vf-winkel deltaL deltaH "Ab")) - (if wahl - (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) - (list nil nil nil nil))) - (progn - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) - (if (and horizontal-info (caddr horizontal-info)) - (list "VF" 0 (car horizontal-info) (cadr horizontal-info)) - (progn - (setq wahl (vfl-vf-winkel deltaL deltaH "Ab")) - (if wahl - (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) - (list nil nil nil nil))))) - ) - ) - ) -) +;; Duenner Wrapper: eigene Mindestlaenge (Umlenkstation+Motorstation), sonst +;; delegiert an vfl-winkel-stufe-entscheidung mit dem Eingangs-Budget einer +;; frischen VF-Einheit. schon-flach immer nil - der Frame kommt hier immer +;; frisch von der Umlenkstation bei 3 Grad, nie flach. +(defun vfl-vf-entscheidung (deltaL deltaH richtung) + (if (< deltaL *vfk-vf-mindestlaenge*) + (list nil nil nil nil) + (vfl-winkel-stufe-entscheidung deltaL deltaH richtung nil *vfl-feste-horizontal*))) ;; Stumme Variante von berechne-alle-winkel: NUR die Machbarkeits-Pruefung ;; (mind. ein Winkel mit L_GF>=0 und L_VF>=0), OHNE die Diagnosetabelle auf @@ -1981,7 +2547,7 @@ (setq aus-dx save-ausdx aus-dz save-ausdz) ergebnis) (t - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" nil)) (if (and horizontal-info (caddr horizontal-info)) t (progn @@ -2071,12 +2637,12 @@ (cond ((< deltaL *vfk-kettenende-mindestlaenge*) nil) ((< deltaH 1.0) - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" nil)) (and horizontal-info (caddr horizontal-info) t)) ((= richtung "Auf") (vfl-winkel-machbar-p deltaL deltaH "Auf" *vfk-feste-horizontal-kettenende*)) (t - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" nil)) (if (and horizontal-info (caddr horizontal-info)) t (vfl-winkel-machbar-p deltaL deltaH "Ab" *vfk-feste-horizontal-kettenende*))) @@ -2130,20 +2696,30 @@ (list nil nil nil nil) (list "GF" *vfk-gefaelle-winkel* nil nil))) - ;; Segment ohne messbare Hoehenaenderung: weder Gefaelle noch sinnvolles VF - ((< deltaH 1.0) (list nil nil nil nil)) - - ;; Steigend: Gefaelle kann nicht steigen -> nur VF moeglich. + ;; Steigend: Gefaelle kann nicht steigen -> nur VF moeglich. deltaH<1.0 + ;; (kein messbarer Hoehenunterschied) faellt jetzt NICHT mehr sofort raus - + ;; vfl-vf-entscheidung (ueber vfl-winkel-stufe-entscheidung) behandelt das + ;; selbst als "praktisch flach" (horizontales VF + GF2, Stufe 2). ((= richtung "Auf") (vfl-vf-entscheidung deltaL deltaH richtung)) ;; Fallend: natuerlichen Neigungswinkel bestimmen (atan der Schraege). ;; Eine reine Gefaellestrecke ist nie steiler als 3 Grad, daher: - ;; ~3 Grad (Toleranzband) -> reine GF (fest 3 Grad) + ;; ~3 Grad (Toleranzband) -> reine GF, am NATUERLICHEN Winkel gebaut ;; sonst -> VF (vfl-vf-entscheidung) + ;; WICHTIG: winkel-natuerlich (nicht der feste *vfk-gefaelle-winkel*) wird + ;; zurueckgegeben - vfl-insert-gf-segment (der tatsaechliche Bauaufruf, + ;; siehe Aufrufer) baut GENAU bei diesem Winkel ueber die volle deltaL, + ;; trifft deltaH damit per Definition exakt. Der feste 3-Grad-Wert wuerde + ;; hier - anders als beim Kettenende-Abschluss (vfl-winkel-stufe- + ;; entscheidung/vfl-body-abschluss, wo GF2 ohnehin IMMER fest bei 3 Grad + ;; gebaut wird und ein abweichender Rueckgabewinkel wirkungslos waere) - + ;; einen echten Hoehenfehler erzeugen, sobald der natuerliche Winkel nur + ;; NAHE (Toleranz *vfl-gf-winkel-toleranz*=0.5 Grad), aber nicht EXAKT 3 + ;; Grad ist. (t (setq winkel-natuerlich (* (atan (/ deltaH deltaL)) (/ 180.0 pi))) (if (<= (abs (- winkel-natuerlich *vfk-gefaelle-winkel*)) *vfl-gf-winkel-toleranz*) - (list "GF" *vfk-gefaelle-winkel* nil nil) + (list "GF" winkel-natuerlich nil nil) (vfl-vf-entscheidung deltaL deltaH richtung)) ) ) @@ -2310,6 +2886,16 @@ ;; modus, vfl-in-point auf den allerersten Klick) - er bleibt ein echter ;; absoluter Punkt, weil er den einzigen Anker der ganzen Kette markiert und ;; von keiner Bogen-Aenderung betroffen sein kann. +;; Reine Richtungswahl OHNE Laenge (journalisiert nur REAL, kein DL-Token) - +;; fuer Faelle, in denen am Kettenanfang eine Richtung noetig ist, aber (noch) +;; keine echte Segmentlaenge (z.B. Zielhoehe-zuerst-Zweige "Linie-GF", wo die +;; Laenge erst spaeter aus Hoehe/Winkel berechnet wird). +(defun vfl-in-richtung (p-akt prompt) + (vfl-in-value "REAL" + (function (lambda ( / p2) + (setq p2 (vfl-getpoint p-akt prompt)) + (if p2 (vfl-hz-snappen-absolut (vfl-planar-hz p-akt p2)) nil))))) + (defun vfl-neue-linie-messen (p-akt hz-vorgabe / erg deltaL hz-aktuell ergebnis fertig) (vfl-view-refresh) (setq fertig nil) @@ -2552,6 +3138,90 @@ (make-frame-from-dir pt (hz-winkel->xu hz 0.0)) ) +;; Frage "Ist der Endpunkt der Foerderer?" (Motorstation/weiterbauen/ +;; Motorstation+Kettenende) - eigene Funktion, da an mehreren Stellen genutzt +;; (Ziel-Modus des horizontalen Koerpers UND die Fortsetzungsschleife von +;; vfl-vf-einheit). Zeigt im Wizard-Modus SELBST den Dialog (vflw_horizontal, +;; radio-basiert) und legt die Antwort in die Pending-Queue - der Konsolen- +;; Text bleibt darunter unveraendert stehen (Fallback bei Fehlern/GUI aus). +(defun vfl-frage-ist-endpunkt ( / dat ergebnis gende) + (princ (ssg-text "vfl-ist-endpunkt-frage")) + (princ (ssg-text "vfl-ja-nur-motorstation")) + (princ (ssg-text "vfl-nein-weiterbauen")) + (princ (ssg-text "vfl-ja-motorstation-kettenende")) + (if (vfl-wizard-aktiv) + (progn + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_horizontal" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-ist-endpunkt-frage"))) + (set_tile "istende_1" "1") + (action_tile "accept" + "(setq gende (cond ((= (get_tile \"istende_0\") \"1\") \"0\") + ((= (get_tile \"istende_2\") \"1\") \"2\") + (t \"1\"))) + (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 (itoa (1+ (atoi gende)))))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + ) + ) + (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def2") + (list (ssg-text "vfl-ja-nur-motorstation") + (ssg-text "vfl-nein-weiterbauen") + (ssg-text "vfl-ja-motorstation-kettenende")) 2 + "vfl-ist-endpunkt-frage")) + +;; Frage "Ist das das Kettenende?" (Linie-GF-Segment-Schleife) - eigene +;; Funktion, da an zwei identischen Stellen genutzt (mit/ohne vorherigen +;; 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) + (princ (ssg-text "vfl-ist-kettenende-header")) + (princ (ssg-text "vfl-kettenende-opt-ja-es")) + (princ (ssg-text "vfl-kettenende-opt-ja-ohne-es")) + (princ (ssg-text "vfl-kettenende-opt-nein")) + (if (vfl-wizard-aktiv) + (progn + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_kettenende" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-ist-kettenende-header"))) + (action_tile "accept" + "(setq gwahl (cond ((= (get_tile \"wahl_ja_es\") \"1\") \"1\") + ((= (get_tile \"wahl_ja_ohne_es\") \"1\") \"2\") + (t \"3\"))) + (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 gwahl))) + ((= ergebnis 2) (setq *vfl-wizard-abbruch-grund* "zurueck")) + (t (setq *vfl-wizard-abbruch-grund* "abbrechen")) + ) + ) + ) + ) + ) + (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")) + ;; --- Horizontaler Koerper: Frage-Schale (Name unveraendert) --- ;; Fragt Separator vor/nach und - im Ziel-Modus - "Ist der Endpunkt der ;; Foerderer?", danach baut vfl-hor-koerper-bauen. Keine der drei Fragen @@ -2561,8 +3231,6 @@ ;; damit die Fortsetzungsschleife des Aufrufers sie nicht erneut erfragt. (defun vfl-baue-horizontal-koerper (frame hz dL ziel-modus gf2-laenge / sep-vor sep-nach ist-ende-antwort neu) - (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-horizontal-impl (list ziel-modus))) (princ (ssg-text "vfl-sep-vor-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-nein")) @@ -2576,16 +3244,7 @@ (setq sep-nach (= (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 2 "vfl-sep-nach-frage") "1")) (if ziel-modus - (progn - (princ (ssg-text "vfl-ist-endpunkt-frage")) - (princ (ssg-text "vfl-ja-nur-motorstation")) - (princ (ssg-text "vfl-nein-weiterbauen")) - (princ (ssg-text "vfl-ja-motorstation-kettenende")) - (setq ist-ende-antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def2") - (list (ssg-text "vfl-ja-nur-motorstation") - (ssg-text "vfl-nein-weiterbauen") - (ssg-text "vfl-ja-motorstation-kettenende")) 2 - "vfl-ist-endpunkt-frage")))) + (setq ist-ende-antwort (vfl-frage-ist-endpunkt))) (setq neu (vfl-hor-koerper-bauen frame hz dL ziel-modus ist-ende-antwort sep-vor sep-nach gf2-laenge)) (if ziel-modus (list neu ist-ende-antwort) neu) @@ -2608,50 +3267,206 @@ ;; Laenge aus dem horizontalen VF - genau die zweistufige Logik. ;; Rueckgabe: (typ winkel L_GF2 L_VF) - typ "GF"/"VF"/nil (wie ;; vfl-segment-entscheidung; L_GF2 varriert, Mindestwert siehe vfl-body-abschluss). -(defun vfl-body-zerlegung (deltaL deltaH richtung / - save-ausdx save-ausdz save-feste - winkel-natuerlich wahl horizontal-info res) +;; Sammelt Diagnosetext fuer einen fehlgeschlagenen Stufe-2-Versuch (siehe +;; vfl-stufe2-diagnose) - der Aufrufer (vfl-body-abschluss) haengt/zeigt ihn +;; NACH der endgueltigen FEHLER-Meldung an. Grund: Stufe 2 ist nur ein (evtl. +;; scheiternder) ERSTER Versuch, danach folgt oft noch Stufe 1 (Winkel- +;; Suche) - stuende die Stufe-2-Diagnose weiterhin sofort im Log, wuerde sie +;; sich zwischen ">>> Kettenende-Modus" und die Stufe-1-Winkeltabelle +;; schieben, obwohl sie inhaltlich zur (evtl. erst ganz am Ende sichtbaren) +;; FEHLER-Zeile gehoert. Gelingt Stufe 1 danach doch noch, bleibt der +;; gesammelte Text ungenutzt (kein "typ=nil" in vfl-body-abschluss) - so wird +;; ein erfolgreicher Log nicht mit Details eines verworfenen Zwischenversuchs +;; zugemuellt. +(defun vfl-diag-add (txt) + (setq *vfl-stufe2-diagnose-text* + (strcat (if *vfl-stufe2-diagnose-text* *vfl-stufe2-diagnose-text* "") txt))) + +(defun vfl-stufe2-diagnose (deltaL deltaH horizontal-info schon-flach / + rad3 mass1 mass2 bogen-x1 bogen-z1 bogen-x2 bogen-z2 + gf-total gueltig fixed-x k-term minh minl-mitgf + fest-planar fest-hoehe) + (vfl-diag-add (ssg-textf "vfl-stufe2-diagnose" + (list (rtos deltaL 2 0) (rtos deltaH 2 0) + (if horizontal-info (rtos (car horizontal-info) 2 1) "?") + (if horizontal-info (rtos (cadr horizontal-info) 2 1) "?") + (if (and horizontal-info (caddr horizontal-info)) "GUELTIG" "UNGUELTIG")))) + (setq rad3 (* *vfk-gefaelle-winkel* (/ pi 180.0))) + (setq mass2 (get-bogen-mass bogen-ab (fix *vfk-gefaelle-winkel*))) + (setq bogen-x2 (car mass2) bogen-z2 (caddr mass2)) + (if schon-flach + (setq bogen-x1 0.0 bogen-z1 0.0) + (progn + (setq mass1 (get-bogen-mass bogen-auf (fix *vfk-gefaelle-winkel*))) + (setq bogen-x1 (+ (* (car mass1) (cos rad3)) (* (caddr mass1) (sin rad3)))) + (setq bogen-z1 (+ (* (- (car mass1)) (sin rad3)) (* (caddr mass1) (cos rad3)))) + ) + ) + (vfl-diag-add (ssg-textf "vfl-stufe2-diagnose-details" + (list (if schon-flach "JA" "NEIN") + (rtos aus-dx 2 1) + (rtos ein-dx 2 1) (rtos ein-dz 2 1) + (rtos bogen-x1 2 1) (rtos bogen-z1 2 1) + (rtos bogen-x2 2 1) (rtos bogen-z2 2 1) + (rtos FESTE_HORIZONTAL 2 1)))) + ;; Explizite Anzeige: wieviel Laenge/Hoehe der feste "Schwanz" (Stationen + + ;; Separator + ES, OHNE die optionalen Uebergangsboegen) allein beansprucht - + ;; direkte Antwort auf "was braucht Motorstation+Separator+ES". Das Label + ;; haengt vom Budget-Kontext ab: FESTE_HORIZONTAL=800 (Kettenende, nur + ;; Motor+Separator - der Eingang/Umlenkstation ist zu diesem Zeitpunkt schon + ;; gebaut) vs. 1300 (frischer VF-Einheit-Eingang, zusaetzlich Umlenkstation - + ;; siehe *vfk-feste-horizontal-kettenende*/-linienzug in vf_konstanten.lsp). + (setq fest-planar (+ ein-dx (* FESTE_HORIZONTAL (cos rad3)))) + (setq fest-hoehe (+ ein-dz (- (* FESTE_HORIZONTAL (sin rad3))))) + (vfl-diag-add (ssg-textf + (if (<= (abs (- FESTE_HORIZONTAL *vfk-feste-horizontal-kettenende*)) 0.5) + "vfl-stufe2-fest-kettenende" + "vfl-stufe2-fest-eingang") + (list (rtos fest-planar 2 0) (rtos fest-hoehe 2 0)))) + (setq gueltig (and horizontal-info (caddr horizontal-info))) + ;; *vfl-stufe2-minl-vorschlag*/*vfl-stufe2-minh-vorschlag*: kurze Zahlenwerte + ;; (kein Text) fuer die knappe Alert-Zusammenfassung in vfl-body-abschluss - + ;; minh ist immer definiert (reine Funktion der festen Geometrie), minl nur, + ;; wenn Variante 1 (GF nach Zielhoehe) ueberhaupt eine nicht-negative GF + ;; ergibt - siehe Kommentar oben. + (setq *vfl-stufe2-minl-vorschlag* nil *vfl-stufe2-minh-vorschlag* nil) + (if (not gueltig) + (progn + (setq gf-total (if horizontal-info (car horizontal-info) nil)) + (setq fixed-x (+ aus-dx ein-dx bogen-x1 bogen-x2 (* FESTE_HORIZONTAL (cos rad3)))) + (setq k-term (+ aus-dz ein-dz (- (* FESTE_HORIZONTAL (sin rad3))) bogen-z1 bogen-z2)) + (setq minh (- k-term)) + (setq *vfl-stufe2-minh-vorschlag* minh) + ;; Variante 1: Mindest-Streckenlaenge (L_VF=0, GF nach Zielhoehe) + (if (and gf-total (>= gf-total 0)) + (progn + (setq minl-mitgf (+ fixed-x (* gf-total (cos rad3)))) + (setq *vfl-stufe2-minl-vorschlag* minl-mitgf) + (vfl-diag-add (ssg-textf "vfl-stufe2-minl" (list (rtos minl-mitgf 2 0) (rtos deltaL 2 0))))) + (vfl-diag-add (ssg-textf "vfl-stufe2-minl-unmoeglich" (list (rtos minh 2 0) (rtos deltaH 2 0)))) + ) + ;; Variante 2: Mindest-Hoehenaenderung (GF=0, Rest als gerader VF-Anteil) + (if (>= deltaL fixed-x) + (vfl-diag-add (ssg-textf "vfl-stufe2-minh" (list (rtos minh 2 0) (rtos deltaH 2 0)))) + (vfl-diag-add (ssg-textf "vfl-stufe2-minh-unmoeglich" (list (rtos fixed-x 2 0) (rtos deltaL 2 0)))) + ) + ) + ) + (princ)) + +;; Vereinheitlichte Stufe-1(Winkel-Tabelle)/Stufe-2(horizontal+GF)-Entscheidung. +;; Genutzt von ZWEI Aufrufern mit unterschiedlichem Fest-Budget: +;; - vfl-body-zerlegung (Kettenende innerhalb einer laufenden VF-Einheit): +;; feste-hz=*vfk-feste-horizontal-kettenende* (800, nur Motor+Separator - +;; der Eingang ist zu diesem Zeitpunkt schon gebaut). +;; - vfl-vf-entscheidung ("Neue Linie: Ab/Auf VF"/"BIS Kettenende", Eingang +;; einer FRISCHEN VF-Einheit): feste-hz=*vfl-feste-horizontal* (1300, +;; Umlenkstation+Separator+Motorstation). +;; schon-flach: nur fuer den Kettenende-Fortsetzungsfall relevant (Frame kann +;; dort schon flach sein, siehe vfl-baue-horizontal-koerper) - am Eingang +;; einer frischen VF-Einheit immer nil (Frame kommt frisch von der +;; Umlenkstation bei 3 Grad). +;; Rueckgabe: (typ winkel L_GF L_VF), typ="GF"/"VF"/nil (winkel=0 bei "VF" +;; heisst horizontales Stufe-2-Ergebnis). KEINE eigene Mindestlaengen-Pruefung +;; - die bleibt Sache der Aufrufer (unterschiedliche Schwellwerte: 800/1000). +(defun vfl-winkel-stufe-entscheidung (deltaL deltaH richtung schon-flach feste-hz / + save-ausdx save-ausdz save-feste + winkel-natuerlich wahl horizontal-info res) (if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek)) - ;; Budget-Globals temporaer auf den Mid-Body-Fall umbiegen (mit Restore). + ;; Gesammelten Stufe-2-Diagnosetext + Alert-Vorschlagswerte aus einem evtl. + ;; vorherigen Aufruf verwerfen - der Aufrufer haengt/zeigt sie nur an, wenn + ;; DIESER Aufruf scheitert (typ=nil). + (setq *vfl-stufe2-diagnose-text* nil) + (setq *vfl-stufe2-minl-vorschlag* nil *vfl-stufe2-minh-vorschlag* nil) + ;; Budget-Globals temporaer auf das Aufrufer-Budget umbiegen (mit Restore). (setq save-ausdx aus-dx save-ausdz aus-dz save-feste FESTE_HORIZONTAL) - (setq aus-dx 0.0 aus-dz 0.0 FESTE_HORIZONTAL *vfk-feste-horizontal-kettenende*) + (setq aus-dx 0.0 aus-dz 0.0 FESTE_HORIZONTAL feste-hz) (setq res (cond - ;; kuerzer als Motor(500)+Separator(300): kein Abschluss baubar - ((< deltaL *vfk-kettenende-mindestlaenge*) (list nil nil nil nil)) ;; praktisch flach: horizontales VF + GF2 ((< deltaH 1.0) - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" schon-flach)) + (vfl-stufe2-diagnose deltaL deltaH horizontal-info schon-flach) (if (and horizontal-info (caddr horizontal-info)) (list "VF" 0 (car horizontal-info) (cadr horizontal-info)) (list nil nil nil nil))) - ;; steigend: nur gewinkeltes VF + GF2 moeglich + ;; steigend: Stufe 1 (gewinkeltes VF) zuerst; scheitert das, Stufe 2 + ;; (horizontales VF + GF2) als Fallback. GF2 wird dabei GENAUSO gebaut + ;; wie im "Ab"-Fall (vfs-vf-exit, fest +3 Grad, gleiche Neigung wie + ;; Motorstation/Umlenkstation/Separator) - KEIN Vorzeichenwechsel, keine + ;; Bau-Aenderung noetig. Das Ausgleichsprinzip: Motorstation+GF2 senken + ;; IMMER ab; wird bei knapper Laenge weniger/kein GF2 verbaut (kuerzer + ;; als das volle Laengenbudget), sinkt die Kette insgesamt weniger stark + ;; ab und die dadurch freiwerdende Laenge wird mit einem horizontalen + ;; VF-Stueck (0 Grad, keine weitere Hoehenaenderung) aufgefuellt statt + ;; mit mehr GF2 - der Uebergangsbogen (ab_3, bereits in berechne- + ;; horizontale-mitte eingerechnet) bleibt dabei unveraendert. ((= richtung "Auf") - (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Auf" *vfk-feste-horizontal-kettenende*)))) - (if wahl (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) (list nil nil nil nil))) + (princ (ssg-text "vfl-stufe1-start")) + (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Auf" feste-hz)))) + (if wahl + (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) + (progn + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Auf" schon-flach)) + (vfl-stufe2-diagnose deltaL deltaH horizontal-info schon-flach) + (if (and horizontal-info (caddr horizontal-info)) + (list "VF" 0 (car horizontal-info) (cadr horizontal-info)) + (list nil nil nil nil))))) ;; fallend: natuerlichen Neigungswinkel gegen die 3-Grad-Eigenneigung pruefen (t (setq winkel-natuerlich (* (atan (/ deltaH deltaL)) (/ 180.0 pi))) (cond - ;; ~3 Grad -> reine GF2 (kein Koerper, GF2 traegt Laenge + 3-Grad-Absenkung) - ((<= (abs (- winkel-natuerlich *vfk-gefaelle-winkel*)) *vfl-gf-winkel-toleranz*) - (list "GF" *vfk-gefaelle-winkel* nil nil)) - ;; steiler als 3 Grad -> Stufe 1: gewinkeltes VF + GF2 (GF2 variiert mit Winkel) + ;; KEIN "~3 Grad -> reine GF2 ohne Rechnung"-Kurzschluss mehr - frueher + ;; hier: (list "GF" *vfk-gefaelle-winkel* nil nil) - L_GF/L_VF blieben + ;; nil und vfl-body-abschluss musste GF2 dann selbst aus deltaL ALLEIN + ;; herleiten - deltaH wurde dabei NIE geprueft, der Austrittsbogen + ;; (bogen-x2) NIE abgezogen. Ergebnis: ein REALER Hoehenfehler (in + ;; einem Livetest 2026-09-10 z.B. dZ=-40.5mm), sobald der natuerliche + ;; Winkel nicht EXAKT 3,000 Grad war (nur nahe dran, per Toleranz + ;; *vfl-gf-winkel-toleranz*=0.5 Grad). Stufe 1 (Tabellenwinkel 3 Grad + ;; ist selbst ein Tabelleneintrag) loest deltaL UND deltaH exakt + ;; simultan (vf-winkel-solve) und deckt den ~3-Grad-Fall daher + ;; automatisch und PRAEZISE mit ab - kein separater Zweig noetig. + ;; steiler als 3 Grad -> Stufe 1: gewinkeltes VF + GF2 (GF2 variiert mit + ;; Winkel) zuerst; scheitert das (z.B. bei knapper Streckenlaenge - + ;; "steiler als 3 Grad" heisst nur, dass der NATUERLICHE Winkel ueber + ;; 3 Grad liegt, nicht dass die Tabelle bei JEDEM Winkel passt), Stufe + ;; 2 (horizontales VF + GF2) als Fallback, analog zur "flacher"- + ;; Verzweigung unten und zum "Auf"-Fallback oben. ((> winkel-natuerlich *vfk-gefaelle-winkel*) - (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Ab" *vfk-feste-horizontal-kettenende*)))) - (if wahl (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) (list nil nil nil nil))) + (princ (ssg-text "vfl-stufe1-start")) + (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Ab" feste-hz)))) + (if wahl + (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) + (progn + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" schon-flach)) + (vfl-stufe2-diagnose deltaL deltaH horizontal-info schon-flach) + (if (and horizontal-info (caddr horizontal-info)) + (list "VF" 0 (car horizontal-info) (cadr horizontal-info)) + (list nil nil nil nil))))) ;; flacher als 3 Grad -> Stufe 2: horizontales VF + GF2 (t - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab" schon-flach)) + (vfl-stufe2-diagnose deltaL deltaH horizontal-info schon-flach) (if (and horizontal-info (caddr horizontal-info)) (list "VF" 0 (car horizontal-info) (cadr horizontal-info)) (progn - (setq wahl (vfl-waehle-winkel (nth 3 (berechne-alle-winkel deltaL deltaH "Ab" *vfk-feste-horizontal-kettenende*)))) + (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)))) (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 +;; 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*) + (list nil nil nil nil) + (vfl-winkel-stufe-entscheidung deltaL deltaH richtung schon-flach *vfk-feste-horizontal-kettenende*))) + ;; Fragt Zielpunkt (XY) + Zielhoehe (Z) ab, zerlegt den Rest (vfl-body- ;; zerlegung, Standard-Logik) und baut den Koerper VOR dem Motor: gewinkeltes ;; VF (winkel>0) oder horizontales VF (winkel=0). GF2 (variiert mit dem Winkel, @@ -2672,20 +3487,24 @@ ;; 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 / +(defun vfl-body-abschluss-bauen (frame p-umlenk dL hzn hn schon-flach / dH richtn rad3 dec typ w lgf lvf gf2 cnt - p0 tx ty letzt-hz) + p0 tx ty letzt-hz antwort-gf2) (setq dH (- hn (caddr (car frame)))) (setq richtn (if (>= dH 0.0) "Auf" "Ab")) (setq dH (abs dH)) (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)) + (setq dec (vfl-body-zerlegung dL dH richtn schon-flach)) (setq typ (nth 0 dec) w (nth 1 dec) lgf (nth 2 dec) lvf (nth 3 dec)) (if (null typ) (progn (princ (ssg-text "vfl-fehler-rest-nicht-baubar")) + ;; Gesammelte Stufe-2-Diagnose (siehe vfl-stufe2-diagnose/vfl-diag-add) + ;; erst HIER, NACH der eigentlichen FEHLER-Zeile zeigen - sie gehoert + ;; inhaltlich zur Begruendung, warum nichts gebaut werden konnte. + (if *vfl-stufe2-diagnose-text* (princ *vfl-stufe2-diagnose-text*)) (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Kettenende-Abschluss nicht baubar (dL=" (rtos dL 2 0) " dH=" (rtos dH 2 0) " richtung=" richtn ")")) nil) @@ -2704,11 +3523,31 @@ (setq cnt 0) ;; Koerper VOR dem Motor: winkel 0 = horizontales VF, sonst gewinkeltes VF. ;; typ "GF" -> kein Koerper (Rest laeuft komplett ueber GF2). - (if (and (= typ "VF") lvf (> lvf 1.0)) - (progn - (setq frame (vfl-frame-3grad (vfs-vf-koerper (car frame) richtn w lvf hzn) hzn)) - (vfl-acc-vf-seg richtn w lvf) - (setq cnt (1+ cnt)))) + (cond + ;; Schon flach + horizontales Mittelstueck: OHNE vfs-vf-koerper + ;; (das wuerde unbedingt auf_3+ab_3 einbauen) direkt als reine + ;; Verlaengerung der bereits flachen Zone bauen - kein + ;; ueberfluessiges Bogenpaar. Frame bleibt flach; der spaeter + ;; ohnehin noetige Uebergang auf 3 Grad vor der Motorstation + ;; (Ausgang in vfl-vf-einheit) erledigt den einzigen wirklich + ;; noetigen Bogen. + ((and schon-flach (= typ "VF") (= w 0) lvf (> lvf 1.0)) + (setq frame (make-frame-from-dir + (insert-inclined-scaled-block "Staustrecke_SP_1000_mm" (car frame) lvf 0 hzn) + (hz-winkel->xu hzn 0.0))) + (vfl-acc-vf-seg "horizontal" 0 lvf) + (setq cnt (1+ cnt))) + ;; Normalfall: gewinkelter ODER horizontaler Koerper - vfs-vf-koerper + ;; braucht dafuer zwingend eine 3-Grad-Basis als Eingang. War der + ;; 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. + ((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)) + (vfl-acc-vf-seg richtn w lvf) + (setq cnt (1+ cnt))) + ) ;; ohne Wirkung: letzt-hz ist lokal und wird nicht mehr gelesen - ;; die Fahrtrichtung verlaesst die Funktion ueber die Rueckgabe. ;; Beim Umzug bewusst wortwoertlich uebernommen. @@ -2721,11 +3560,25 @@ ((= typ "GF") (max 0.0 (- (/ (- dL (abs (if ein-dx ein-dx *vfk-as-es-fallback-dx*))) (cos rad3)) *vfk-feste-horizontal-kettenende*))) (t 0.0))) + ;; Nicht mehr stillschweigend auffuellen (fuehrte zu einer teils + ;; grossen Zielpunkt-Abweichung, siehe Ist-Ziel-Report) - stattdessen + ;; fragen: mit dem exakt berechneten (kleineren) Wert bauen (trifft + ;; den Zielpunkt exakt, Default) ODER auf die uebliche Mindestlaenge + ;; auffuellen (Zielpunkt verschiebt sich entsprechend weiter). (if (and (> gf2 0.0) (< gf2 *vfl-gf-min-laenge*)) (progn - (princ (ssg-textf "vfl-hinweis-gf2-minimum" + (princ (ssg-textf "vfl-frage-gf2-minimum" (list (rtos gf2 2 0) (rtos *vfl-gf-min-laenge* 2 0)))) - (setq gf2 *vfl-gf-min-laenge*))) + (princ (ssg-text "vfl-ja")) + (princ (ssg-text "vfl-nein")) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-ja-nein-impl + (list (ssg-textf "vfl-frage-gf2-minimum" + (list (rtos gf2 2 0) (rtos *vfl-gf-min-laenge* 2 0)))))) + (setq antwort-gf2 (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 1 + "vfl-frage-gf2-minimum")) + (if (= antwort-gf2 "2") (setq gf2 *vfl-gf-min-laenge*)))) (dbgmsg (strcat "GEOMETRIE ERFOLG: Kettenende-Abschluss gebaut (cnt=" (itoa cnt) " gf2=" (rtos gf2 2 0) "), neue Position=" (dbg-tostring (car frame)))) (list frame cnt hzn gf2) @@ -2740,11 +3593,15 @@ ;; Reihenfolge: flache Zone abschliessen -> Laenge messen -> Vorschlaege ;; berechnen -> Zielhoehe fragen -> bauen. (defun vfl-body-abschluss (frame letzt-hz p-umlenk / - linie-mess dL hzn hn + linie-mess dL hzn hn schon-flach ergebnis dH richtn hoehe-vorschlaege hoehe-ab hoehe-auf hoehe-fallback) - ;; Der Abschluss-Koerper (vfs-vf-koerper) und der Motor gehen von 3-Grad-Basis - ;; aus - eine gerade laufende flache Zone hier mit ab_3 abschliessen. - (setq frame (vfl-nach-3grad frame)) + ;; Schon-flach VOR jeder Konvertierung feststellen - NICHT mehr blind auf + ;; 3 Grad zwingen, bevor feststeht, ob die Zerlegung ohnehin ein + ;; horizontales Mittelstueck ergibt (dann waere die Konvertierung + der + ;; Wiedereintritt in die flache Zone via vfs-vf-koerper ein ueberfluessiges + ;; auf_3/ab_3-Bogenpaar - siehe Kommentar bei vfl-winkel-stufe-entscheidung). + ;; Die Positions-Messung selbst funktioniert unabhaengig von der Neigung. + (setq schon-flach (vfl-frame-flach-p frame)) (setq linie-mess (vfl-neue-linie-messen (car frame) letzt-hz)) (if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen-kein-ziel")) nil) @@ -2768,7 +3625,49 @@ (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)) - (vfl-body-abschluss-bauen frame p-umlenk dL hzn hn) + (setq ergebnis (vfl-body-abschluss-bauen frame p-umlenk dL hzn hn schon-flach)) + ;; 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 + ;; Hoehe-Abfrage berechneten baubaren Vorschlaege (hoehe-ab/hoehe-auf) + ;; hier NOCHMAL zeigen - der Nutzer sieht sie sonst nur einmal vor der + ;; Eingabe und muss beim Fehler wieder hochscrollen. hoehe-ab/hoehe-auf + ;; sind nur hier (Frage-Schale) bekannt, darum die Zusatzmeldung hier + ;; statt im reinen Bauteil. + (if (null ergebnis) + (progn + (setq dH (- hn (caddr (car frame))) richtn (if (>= dH 0.0) "Auf" "Ab")) + (setq dH (abs dH)) + (if (or hoehe-ab hoehe-auf) + (princ (ssg-textf "vfl-fehler-rest-nicht-baubar-mit-vorschlag" + (list (rtos hn 2 0) (rtos dL 2 0) (rtos dH 2 0) richtn + (cond + ((and hoehe-ab hoehe-auf) + (ssg-textf "vfl-vorschlag-ab-auf" + (list (rtos hoehe-ab 2 0) (rtos hoehe-auf 2 0)))) + (hoehe-ab (ssg-textf "vfl-vorschlag-nur-ab" (list (rtos hoehe-ab 2 0)))) + (t (ssg-textf "vfl-vorschlag-nur-auf" (list (rtos hoehe-auf 2 0)))))))) + (princ (ssg-textf "vfl-fehler-rest-nicht-baubar-ohne-vorschlag" + (list (rtos hn 2 0) (rtos dL 2 0) (rtos dH 2 0) richtn)))) + ;; Kurze 2-Punkte-Zusammenfassung zusaetzlich als Alert-Popup (nicht + ;; nur im Konsolen-Log) - zweiter Punkt nur, wenn Stufe 2 ueberhaupt + ;; versucht wurde (siehe *vfl-stufe2-min*-vorschlag*, von + ;; vfl-stufe2-diagnose gesetzt). + (alert + (strcat + (ssg-textf "vfl-alert-kettenende-p1" (list (rtos dL 2 0) (rtos dH 2 0) richtn)) + (cond + ((and *vfl-stufe2-minl-vorschlag* *vfl-stufe2-minh-vorschlag*) + (ssg-textf "vfl-alert-kettenende-p2-beide" + (list (rtos *vfl-stufe2-minl-vorschlag* 2 0) (rtos *vfl-stufe2-minh-vorschlag* 2 0)))) + (*vfl-stufe2-minh-vorschlag* + (ssg-textf "vfl-alert-kettenende-p2-nur-minh" (list (rtos *vfl-stufe2-minh-vorschlag* 2 0)))) + (*vfl-stufe2-minl-vorschlag* + (ssg-textf "vfl-alert-kettenende-p2-nur-minl" (list (rtos *vfl-stufe2-minl-vorschlag* 2 0)))) + (t "")))) + ) + ) + ergebnis ) ) ) @@ -2780,11 +3679,14 @@ ;; mitbaut - die *vfl-acc-*-Aufrufe muessen an derselben Stelle in derselben ;; Reihenfolge bleiben, sonst vertauschen sich die Komma-Listen L_VF_m/L_GF_m ;; im Sivas-Export (in der Zeichnung unsichtbar). -(defun vfl-vf-eingang-bauen (frame hz1 L_GF1-bau) - (setq frame (vfl-frame-3grad (vfs-vf-entry (car frame) L_GF1-bau hz1) hz1)) +(defun vfl-vf-eingang-bauen (frame hz1 L_GF1-bau eingang-modus) + (setq frame (vfl-frame-3grad + (vfs-vf-entry (car frame) L_GF1-bau hz1 (equal eingang-modus "separator")) + hz1)) (if (> L_GF1-bau 0.1) (vfl-acc-gf-seg L_GF1-bau (ssg-cfg-or "vario" "gefaelle_winkel" 3))) - (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)) ; Einlauf-Separator (in vfs-vf-entry) + (if (not (equal eingang-modus "separator")) + (setq *vfl-acc-separator* (1+ *vfl-acc-separator*))) ; Einlauf-Separator (in vfs-vf-entry) frame) ;; --- VF-Einheit: Ausgang (reiner Bauteil) --- @@ -2805,7 +3707,7 @@ frame) ;; Rueckgabe: (frame anzahl-koerper ziel-ende) -(defun vfl-vf-einheit (frame hz1 richtung1 winkel1 L_GF1 L_VF1 gf-am-ausgang / +(defun vfl-vf-einheit (frame hz1 richtung1 winkel1 L_GF1 L_VF1 gf-am-ausgang eingang-modus / p-umlenk vf-count antwort L_GF-eff L_GF1-bau L_GF2-bau linie-mess dL dH hn hzn richtn ent typ w lgf lvf letzt-hz fertig ziel-ende ziel-gf2 res3 gf2-eff entry-start @@ -2814,18 +3716,31 @@ ;; Vorbelegung: ES gewuenscht (Default) - nur bei "3 - Kettenende definieren" ;; wird explizit gefragt und ggf. auf nil gesetzt (siehe dort). (setq es-gewuenscht t) - ;; Gesamte Staustrecke (mind. *vfl-gf-min-laenge*) auf Einlauf/Ausgang verteilen. - (setq L_GF-eff (max L_GF1 *vfl-gf-min-laenge*)) + ;; Gesamte Staustrecke (mind. *vfl-gf-min-laenge*) auf Einlauf/Ausgang + ;; verteilen - AUSSER eingang-modus "gf"/"separator"/"keine": dort ist kein + ;; GF1-Stumpf noetig (siehe vfl-eingang-modus-bestimmen). + (if (member eingang-modus '("gf" "separator" "keine")) + (setq L_GF-eff 0.0) + (setq L_GF-eff (max L_GF1 *vfl-gf-min-laenge*))) (if gf-am-ausgang (setq L_GF1-bau (/ L_GF-eff 2.0) L_GF2-bau (/ L_GF-eff 2.0)) ; halbe/halbe (setq L_GF1-bau L_GF-eff L_GF2-bau 0.0)) ; alles am Einlauf - ;; --- Eingang: GF1 + Separator + Umlenkstation --- + ;; --- Eingang: [GF1] + [Separator] + Umlenkstation --- ;; entry-start/p-umlenk sind der Stand VOR bzw. NACH dem Eingang - die ;; horizontale Erstkoerper-Rechnung braucht beide (gemessener Fussabdruck). + ;; eingang-modus "keine": Vorgaenger ist bereits Teil einer virtuellen + ;; VF-Kette OHNE eigene Umlenkstation (z.B. Vario-Kurve als erstes + ;; Kettenglied) - eine zweite Umlenkstation waere mechanisch sinnlos, der + ;; Koerper knuepft direkt am uebergebenen frame an. (setq entry-start (car frame)) - (setq frame (vfl-vf-eingang-bauen frame hz1 L_GF1-bau)) - (setq p-umlenk (car frame)) + (if (equal eingang-modus "keine") + (setq p-umlenk (car frame)) + (progn + (setq frame (vfl-vf-eingang-bauen frame hz1 L_GF1-bau eingang-modus)) + (setq p-umlenk (car frame)) + ) + ) ;; --- Erstes Koerper-Sub-Segment --- ;; winkel1=0 => horizontaler Anfang (Option 3): mit Separator-vor/nach-Abfrage. @@ -2852,6 +3767,11 @@ (setq frame (car res-h) vor-antwort (cadr res-h)) ) (progn + ;; vfs-vf-koerper braucht die 3-Grad-Basis als Eintritt - im Normalfall + ;; liefert die Umlenkstation die bereits (vfl-nach-3grad ist dann No-op); + ;; bei eingang-modus "keine" kann frame noch flach sein (z.B. direkt + ;; nach einer Vario-Kurve) und muss hier erst konvertiert werden. + (setq frame (vfl-nach-3grad frame)) (setq frame (vfl-frame-3grad (vfs-vf-koerper (car frame) richtung1 winkel1 L_VF1 hz1) hz1)) (vfl-acc-vf-seg richtung1 winkel1 L_VF1) ) @@ -2867,17 +3787,7 @@ ;; erneut fragen - sonst normal abfragen. (if vor-antwort (setq antwort vor-antwort vor-antwort nil) - (progn - (princ (ssg-text "vfl-ist-endpunkt-frage")) - (princ (ssg-text "vfl-ja-nur-motorstation")) - (princ (ssg-text "vfl-nein-weiterbauen")) - (princ (ssg-text "vfl-ja-motorstation-kettenende")) - (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def2") - (list (ssg-text "vfl-ja-nur-motorstation") - (ssg-text "vfl-nein-weiterbauen") - (ssg-text "vfl-ja-motorstation-kettenende")) 2 - "vfl-ist-endpunkt-frage")) - ) + (setq antwort (vfl-frage-ist-endpunkt)) ) (if (= antwort "1") (setq fertig t) @@ -3216,6 +4126,196 @@ (caddr startpunkt) nil "KS_EIN") ) +;; Kettenanfang-Baustein: falls as-vorhanden, AS-Element einfuegen und die +;; GF/VF-Restlaenge um den tatsaechlichen AS-Fussabdruck kuerzen. Falls NICHT +;; as-vorhanden (Nutzer hat "Kein AS-Element" gewaehlt), beginnt die Kette +;; direkt am Startpunkt - deltaL bleibt die gemessene Rohlaenge (kein +;; Alle seit checkpoint (Ergebnis von (entlast), NIL falls Zeichnung vorher leer +;; war) neu erzeugten Entities wieder loeschen - Gegenteil von +;; vfl-modus-abbruch-sichern (das wickelt statt zu loeschen). Genutzt, wenn ein +;; Baustein (z.B. VF-Einheit-Eingang) sich im Nachhinein als sinnlos erweist +;; (zu kurz, Nutzer verzichtet auf "trotzdem bauen") - erst alle enames +;; sammeln, dann loeschen (entdel veraendert waehrend der Iteration die +;; Datenbank-Reihenfolge, siehe SSG_LIB_Commands.lsp). +(defun vfl-loesche-seit (checkpoint / e liste) + (setq liste '()) + (setq e (if checkpoint (entnext checkpoint) (entnext))) + (while e (setq liste (cons e liste)) (setq e (entnext e))) + (foreach e liste (entdel e)) +) + +;; KS_AUS-Ursprung UND -Richtung (hz-Winkel in Grad) eines platzierten Blocks - +;; Massstab-bereinigte Kopie wie vfl-kette-ks-ursprung (Explode auf einer +;; skalierungsneutralen Kopie, dann geloescht), zusaetzlich mit der KS_AUS- +;; Achsrichtung: die Laengen-Streckung (XScaleFactor) verschiebt nur den +;; KS_AUS-URSPRUNG entlang der Blocklaenge (gegenueber KS_EIN), die +;; Achsrichtung des kleinen KS_AUS-Unterblocks selbst bleibt davon unberuehrt +;; (an der skalierungsneutralen Kopie unverfaelscht messbar). Rueckgabe: +;; (punkt . hz) oder nil (kein KS_AUS gefunden). +(defun vfl-kette-ks-aus-richtung (block-obj / sx copyobj ksdata kez kaz-raw kax-raw kaz hz) + (setq sx (vla-get-XScaleFactor block-obj)) + (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 kez (if (assoc "KS_EIN" ksdata) (car (cadr (assoc "KS_EIN" ksdata))) nil)) + (setq kaz-raw (if (assoc "KS_AUS" ksdata) (car (cadr (assoc "KS_AUS" ksdata))) nil)) + (setq kax-raw (if (assoc "KS_AUS" ksdata) (cadr (cadr (assoc "KS_AUS" ksdata))) nil)) + (if (and kez kaz-raw kax-raw) + (progn + (setq kaz + (if (/= sx 1.0) + (list (+ (car kez) (* sx (- (car kaz-raw) (car kez)))) + (+ (cadr kez) (* sx (- (cadr kaz-raw) (cadr kez)))) + (+ (caddr kez) (* sx (- (caddr kaz-raw) (caddr kez))))) + kaz-raw)) + (setq hz (/ (* (atan (- (cadr kax-raw) (cadr kaz-raw)) (- (car kax-raw) (car kaz-raw))) 180.0) pi)) + (cons kaz hz) + ) + nil + ) +) + +;; Sucht am gegebenen Punkt (Toleranz 1mm) einen KS_AUS eines vorhandenen +;; Vario-Kette-Bausteins der Zeichnung (lose Teile UND VF_n-Wrapper - gleicher +;; Scan wie vfl-kette-sammle-alle/Vario_Kette_Merge) und liefert dessen +;; Richtung (hz in Grad). Genutzt fuer den Kettenanfang bei GF-Bogen/Vario- +;; Kurve OHNE AS-Element: setzt der Nutzer den Startpunkt exakt auf den KS_AUS +;; eines bestehenden Bausteins (z.B. Fortsetzung einer schon gebauten Kette), +;; soll die neue Kurve dessen Richtung uebernehmen statt der Welt-X-Achse. +;; Rueckgabe: (hz . typ) oder nil, wenn kein KS_AUS in Toleranz gefunden +;; wurde. typ ist das vfl-kette-typ-Ergebnis des GEFUNDENEN Bausteins (bei +;; einem Wrapper-Kind dessen EIGENER Blockname, nicht "WRAPPER") - Basis fuer +;; vfl-kette-typ-familie (GF/VF/uneindeutig), genutzt von +;; vfl-keine-umlenkstation-p. +(defun vfl-ks-aus-hz-an-punkt (pt / tol ss i ename bname typ obj kinder kind + erg bester-d d hz-treffer typ-treffer kind-bname kind-typ) + (setq tol 1.0) + (setq bester-d nil hz-treffer nil typ-treffer nil) + (setq ss (ssget "X" '((0 . "INSERT")))) + (if ss + (progn + (setq i 0) + (while (< i (sslength ss)) + (setq ename (ssname ss i)) + (setq bname (cdr (assoc 2 (entget ename)))) + (setq typ (vfl-kette-typ bname)) + (cond + ((= typ "WRAPPER") + (setq obj (vlax-ename->vla-object ename)) + (setq kinder (vlax-invoke obj 'Explode)) + (foreach kind kinder + (if (and (not (vlax-erased-p kind)) + (= (vla-get-ObjectName kind) "AcDbBlockReference")) + (progn + (setq kind-bname (vla-get-Name kind)) + (setq kind-typ (vfl-kette-typ kind-bname)) + (setq erg (vfl-kette-ks-aus-richtung kind)) + (if erg + (progn + (setq d (distance pt (car erg))) + (if (and (< d tol) (or (null bester-d) (< d bester-d))) + (setq bester-d d hz-treffer (cdr erg) typ-treffer kind-typ)) + ) + ) + ) + ) + ) + (foreach kind kinder (if (not (vlax-erased-p kind)) (vla-Delete kind))) + ) + ((/= typ "UNBEKANNT") + (setq obj (vlax-ename->vla-object ename)) + (setq erg (vfl-kette-ks-aus-richtung obj)) + (if erg + (progn + (setq d (distance pt (car erg))) + (if (and (< d tol) (or (null bester-d) (< d bester-d))) + (setq bester-d d hz-treffer (cdr erg) typ-treffer typ)) + ) + ) + ) + ) + (setq i (1+ i)) + ) + ) + ) + (if hz-treffer (cons hz-treffer typ-treffer) nil) +) + +;; Grobe GF-/VF-Familie-Klassifikation eines vfl-kette-typ-Ergebnisses fuer die +;; Umlenkstations-Entscheidung am echten Kettenanfang (siehe +;; vfl-eingang-modus-bestimmen): AS/ES/STRECKE/SEP werden von BEIDEN Familien +;; genutzt (eine GF-Gerade UND das horizontale VF-Mittelstueck sind derselbe +;; Block "Staustrecke_SP_1000_mm") und bleiben daher absichtlich uneindeutig +;; (nil) - der Scan kann ein reines GF-Geraden-Ende grundsaetzlich NICHT vom +;; Ende eines VF-Horizontalstuecks unterscheiden. +(defun vfl-kette-typ-familie (typ) + (cond + ((member typ '("WRAPPER" "KURVE" "UMLENK" "MOTOR" "BOGENAUF" "BOGENAB")) "VF") + ((member typ '("GFBOGEN")) "GF") + (t nil) + ) +) + +;; Eingang-Modus + L_GF-Stumpf fuer eine neue VF-Einheit bestimmen - EINE +;; gemeinsame Entscheidung fuer "Neue VF mit horizontalem Anfang" UND "Neue +;; Linie: Ab/Auf VF" (Punkt 5). Reihenfolge: +;; Fall 1 - letzter-typ="Separator"/"GF" (session-lokal bekannt, reduzierter +;; aber vorhandener Eingang - kein GF1-Stumpf, ggf. kein neuer Separator). +;; Fall 2 - letzter-typ="Vario-Kurve": die hat keine eigene Umlenkstation/ +;; keinen Abschluss - eine zweite waere mechanisch sinnlos -> KEINE +;; Umlenkstation. +;; Fall 3 - echter Kettenanfang OHNE AS-Element (kettenanfang UND NICHT +;; as-vorhanden): am Startpunkt wird per KS_AUS-Scan (vfl-ks-aus-hz-an- +;; punkt) nachgesehen, was dort schon steht: +;; - eindeutig VF-Familie erkannt -> KEINE Umlenkstation. +;; - eindeutig GF-Familie (GF-Bogen) erkannt -> voller Eingang. +;; - NICHTS Eindeutiges (auch bei einer reinen GF-Geraden/VF-Horizontal- +;; stueck, die per Blockname nicht unterscheidbar sind - siehe +;; vfl-kette-typ-familie) -> der automatische Scan kann hier prinzipiell +;; nicht entscheiden, also EINE flache 3-Optionen-Frage an den Nutzer: +;; Option Eins - direkt Umlenkstation (kein GF-Stumpf); Option Zwei - GF- +;; Stumpf+Umlenkstation; Option Drei - ohne Umlenkstation (VF-Fortsetzung). +;; Fall 4 - sonst voller Eingang (GF1+Separator+Umlenkstation). +;; Rueckgabe: (lgf . eingang-modus). +(defun vfl-eingang-modus-bestimmen (letzter-typ kettenanfang as-vorhanden p-aktuell / + erg familie antwort) + (cond + ((equal letzter-typ "Separator") (cons 0.0 "separator")) + ((equal letzter-typ "GF") (cons 0.0 "gf")) + ((equal letzter-typ "Vario-Kurve") (cons 0.0 "keine")) + ((and kettenanfang (not as-vorhanden)) + (setq erg (vfl-ks-aus-hz-an-punkt p-aktuell)) + (setq familie (if erg (vfl-kette-typ-familie (cdr erg)) nil)) + (cond + ((equal familie "VF") (cons 0.0 "keine")) + ((equal familie "GF") (cons *vfl-gf-min-laenge* nil)) + (t + (princ (ssg-textf "vfl-frage-startpunkt-typ" (list (rtos *vfl-gf-min-laenge* 2 0)))) + (princ (ssg-text "vfl-opt-eingang-direkt")) + (princ (ssg-textf "vfl-opt-eingang-mit-stumpf" (list (rtos *vfl-gf-min-laenge* 2 0)))) + (princ (ssg-text "vfl-opt-eingang-ohne-umlenk")) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-startpunkt-typ-impl nil)) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def1") + (list (ssg-text "vfl-opt-eingang-direkt") + (ssg-textf "vfl-opt-eingang-mit-stumpf" (list (rtos *vfl-gf-min-laenge* 2 0))) + (ssg-text "vfl-opt-eingang-ohne-umlenk")) 1 + "vfl-frage-startpunkt-typ")) + (cond + ((= antwort "2") (cons *vfl-gf-min-laenge* nil)) + ((= antwort "3") (cons 0.0 "keine")) + (t (cons 0.0 "gf")) + ) + ) + ) + ) + (t (cons *vfl-gf-min-laenge* nil)) + ) +) + ;; Kettenanfang-Baustein: falls as-vorhanden, AS-Element einfuegen und die ;; GF/VF-Restlaenge um den tatsaechlichen AS-Fussabdruck kuerzen. Falls NICHT ;; as-vorhanden (Nutzer hat "Kein AS-Element" gewaehlt), beginnt die Kette @@ -3276,6 +4376,9 @@ (list "vf-winkel-ein-header" (list (ssg-text "vf-winkel-90") (ssg-text "vf-winkel-30")) (list "90" "30")))) + (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"))))) ; 30/90 vor Seite @@ -3458,17 +4561,24 @@ (setq *vfl-ziel-punkt* nil))) (princ)) -(defun vfl-vf-einheit-abschluss (frame hz richtung winkel L_GF L_VF auto-ende / +(defun vfl-vf-einheit-abschluss (frame hz richtung winkel L_GF L_VF auto-ende gf-verteilung-fest eingang-modus / antwort res es-s ende es-gewuenscht) ;; GF-Verteilung: halbe Staustrecke am Ausgang (GF2) oder alles am Einlauf. - (princ (ssg-text "vfl-gf-verteilung-header")) - (princ (ssg-text "vfl-gf-verteilung-haelfte")) - (princ (ssg-text "vfl-gf-verteilung-ganz-einlauf")) - (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") - (list (ssg-text "vfl-gf-verteilung-haelfte") - (ssg-text "vfl-gf-verteilung-ganz-einlauf")) 2 - "vfl-gf-verteilung-header")) - (setq res (vfl-vf-einheit frame hz richtung winkel L_GF L_VF (= antwort "1"))) + ;; gf-verteilung-fest: Aufrufer erzwingt die Antwort (z.B. "2", wenn L_GF + ;; wegen eingang-modus ohnehin 0.0 ist - die Frage waere dann sinnlos). + (if gf-verteilung-fest + (setq antwort gf-verteilung-fest) + (progn + (princ (ssg-text "vfl-gf-verteilung-header")) + (princ (ssg-text "vfl-gf-verteilung-haelfte")) + (princ (ssg-text "vfl-gf-verteilung-ganz-einlauf")) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-gf-verteilung-impl (list (ssg-text "vfl-gf-verteilung-header") "1" "2"))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") + (list (ssg-text "vfl-gf-verteilung-haelfte") + (ssg-text "vfl-gf-verteilung-ganz-einlauf")) 2 + "vfl-gf-verteilung-header")))) + (setq res (vfl-vf-einheit frame hz richtung winkel L_GF L_VF (= antwort "1") eingang-modus)) (setq frame (nth 0 res) es-gewuenscht (nth 3 res)) ;; Kettenende? Bei auto-ende (Kettenende-Modus) ohne Frage direkt ES setzen. ;; ziel-ende (Option 3 IN der VF-Einheit) OHNE ES-Wunsch (dort abgefragt, @@ -3532,7 +4642,8 @@ as-vorhanden erg old-error vfl-ins dbg-an hoehe-vorschlaege hoehe-ab hoehe-auf hoehe-fallback gf-laenge-modus gf-steigend-modus sep-vor-gf sep-nach-gf - sep-anzahl erg-bogen) + sep-anzahl erg-bogen vf-eingang-lgf vf-eingang-modus + eingang-laenge winkel-hoehen-erg) (princ "\n\n=========================================") (princ (ssg-text "vfl-modus1-header")) (princ "\n=========================================") @@ -3638,6 +4749,9 @@ (setq *vfl-as-winkel* nil *vfl-es-winkel* nil) (if as-vorhanden (progn + (princ (ssg-text "vf-winkel-aus-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) (setq *vfl-as-winkel* (vfl-in-value "STR" (function (lambda () (vf-frage-element-winkel "vf-winkel-aus-header"))))) ; 30/90 vor Seite @@ -3685,6 +4799,8 @@ ;; Ketten eines vorherigen INSERTs konsistent uebersprungen werden. (setq seg-lastEnt (vf-lastent-ohne-attribute)) (vfl-journal-mark "?") + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-naechstes-element-impl (list (null frame)))) (if frame (progn (princ (ssg-text "vfl-menu-gf-bogen-1")) @@ -3706,20 +4822,33 @@ (t "Linie-GF"))) ; "2" oder leer ) (progn - (princ (ssg-text "vfl-menu-linie-gf-1")) - (princ (ssg-text "vfl-menu-linie-vf-2")) - (princ (ssg-text "vfl-menu-horizontal-vf-3")) - (princ (ssg-text "vfl-menu-linie-ende-4")) - (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-4-def1") - (list (ssg-text "vfl-menu-linie-gf-1") - (ssg-text "vfl-menu-linie-vf-2") - (ssg-text "vfl-menu-horizontal-vf-3") - (ssg-text "vfl-menu-linie-ende-4")) 1 + ;; Kettenanfang: 6 Optionen statt 4 - GF-Bogen und Vario-Kurve sind + ;; hier ZUSAETZLICH waehlbar (stueckweiser Aufbau kann auch mit einer + ;; horizontalen Kurve beginnen, z.B. Fortsetzung einer bereits an + ;; anderer Stelle gebauten Teilkette). Beide brauchen dafuer keine + ;; eigene Laengenmessung, nur eine Referenzrichtung - siehe die + ;; KS_AUS-Erkennung (vfl-ks-aus-hz-an-punkt) in den beiden Zweigen + ;; unten. + (princ (ssg-text "vfl-menu-gf-bogen-ka-1")) + (princ (ssg-text "vfl-menu-variokurve-ka-2")) + (princ (ssg-text "vfl-menu-linie-gf-ka-3")) + (princ (ssg-text "vfl-menu-linie-vf-ka-4")) + (princ (ssg-text "vfl-menu-horizontal-vf-ka-5")) + (princ (ssg-text "vfl-menu-linie-ende-ka-6")) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-6-def3") + (list (ssg-text "vfl-menu-gf-bogen-ka-1") + (ssg-text "vfl-menu-variokurve-ka-2") + (ssg-text "vfl-menu-linie-gf-ka-3") + (ssg-text "vfl-menu-linie-vf-ka-4") + (ssg-text "vfl-menu-horizontal-vf-ka-5") + (ssg-text "vfl-menu-linie-ende-ka-6")) 3 "vfl-naechstes-element-header")) - (setq wahl (cond ((= antwort "2") "Linie-VF") - ((= antwort "3") "Horizontal-VF") - ((= antwort "4") (setq linie-ende-modus t) "Linie") - (t "Linie-GF"))) ; "1" oder leer + (setq wahl (cond ((= antwort "1") "GF-Bogen") + ((= antwort "2") "Vario-Kurve") + ((= antwort "4") "Linie-VF") + ((= antwort "5") "Horizontal-VF") + ((= antwort "6") (setq linie-ende-modus t) "Linie") + (t "Linie-GF"))) ; "3" oder leer ) ) ;; Segmenttyp steht fest -> Glied-Label nachtragen (fuer die Edit-Liste). @@ -3728,10 +4857,49 @@ (progn (cond ((= wahl "GF-Bogen") + ;; Als ALLERERSTES Kettenglied (frame=nil) braucht eine Kurve technisch + ;; eine Referenzrichtung, von der aus Winkel+Seite gemessen werden - + ;; eine zusaetzliche Punktwahl nur zur Richtungsbestimmung ist + ;; ueberfluessig (kein eigenes Segment, keine Laenge wird dabei + ;; gemessen). Liegt der gewaehlte Startpunkt exakt auf dem KS_AUS eines + ;; bestehenden Vario-Kette-Bausteins (Fortsetzung einer schon gebauten + ;; Kette), wird dessen Richtung uebernommen; sonst Standard Welt-0 + ;; Grad/+X-Achse. Das AS-Element wird ganz normal ueber + ;; vfl-kettenanfang-baustein eingefuegt (deltaL dabei irrelevant, da + ;; hier kein Segment gebaut wird - Wert wird verworfen). + (if (null frame) + (progn + (setq hz-neu (car (vfl-ks-aus-hz-an-punkt p-aktuell))) + (if (null hz-neu) (setq hz-neu 0.0)) + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu 0.0 as-seite as-vorhanden)) + (setq frame (nth 0 erg)) + ) + ) (setq frame (vfl-insert-gf-bogen frame)) (setq p-aktuell (car frame)) ) + ((= wahl "Vario-Kurve") + ;; Gleiche Kettenanfang-Behandlung wie GF-Bogen oben (KS_AUS- + ;; Richtungsuebernahme bei Fortsetzung, sonst Welt-0 Grad). + (if (null frame) + (progn + (setq hz-neu (car (vfl-ks-aus-hz-an-punkt p-aktuell))) + (if (null hz-neu) (setq hz-neu 0.0)) + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu 0.0 as-seite as-vorhanden)) + (setq frame (nth 0 erg)) + ) + ) + (setq frame (vfl-insert-vario-kurve frame)) + (setq p-aktuell (car frame)) + ;; letzter-typ merken: eine Vario-Kurve hat KEINE eigene Umlenkstation + ;; und ist mechanisch Teil einer VF-Kette - ein direkt folgendes + ;; "Neue Linie: Ab/Auf VF"/"Horizontal-VF" baut daher (via + ;; vfl-eingang-modus-bestimmen, eingang-modus="keine") KEINE zweite + ;; Umlenkstation. + (setq letzter-typ "Vario-Kurve") + ) + ;; --- Neue horizontal VF: VF-Einheit mit horizontalem Anfangs-Koerper --- ((= wahl "Horizontal-VF") (setq linie-mess (vfl-neue-linie-messen p-aktuell @@ -3755,13 +4923,23 @@ (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Horizontal-VF zu kurz (deltaL=" (rtos deltaL 2 0) ")")))) (progn - ;; VF-Einheit mit horizontalem ersten Koerper (winkel=0, L_VF=deltaL, - ;; L_GF = Mindestlaenge fuer den Einlauf-Anschluss). + ;; Eingang haengt vom VORHERIGEN Kettenglied ab (letzter-typ) bzw. + ;; am echten Kettenanfang vom KS_AUS-Scan - siehe + ;; vfl-eingang-modus-bestimmen (gemeinsam mit "Neue Linie: Ab/Auf + ;; VF"). + (setq erg (vfl-eingang-modus-bestimmen letzter-typ kettenanfang as-vorhanden p-aktuell)) + (setq vf-eingang-lgf (car erg) vf-eingang-modus (cdr erg)) + ;; VF-Einheit mit horizontalem ersten Koerper (winkel=0, L_VF=deltaL). (if dbg-an (dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss horizontal (deltaL=" (rtos deltaL 2 0) - " L_GF=" (rtos *vfl-gf-min-laenge* 2 0) " L_VF=" (rtos deltaL 2 0) ")"))) + " L_GF=" (rtos vf-eingang-lgf 2 0) " L_VF=" (rtos deltaL 2 0) + " eingang-modus=" (if vf-eingang-modus vf-eingang-modus "voll") ")"))) + ;; GF-Verteilungsfrage entfaellt hier ("2" = alles am Einlauf, kein + ;; GF2 fest vorgegeben): L_GF ist nur der strukturelle Mindest- + ;; Eingang, das Ausgangs-Ende regelt allein die mit/ohne- + ;; Motorstation-Frage (siehe vfl-baue-horizontal-koerper). (setq vf-einheit-res - (vfl-vf-einheit-abschluss frame hz-neu "Ab" 0 *vfl-gf-min-laenge* deltaL nil)) + (vfl-vf-einheit-abschluss frame hz-neu "Ab" 0 vf-eingang-lgf deltaL nil "2" vf-eingang-modus)) (setq frame (nth 0 vf-einheit-res)) (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) (if (nth 2 vf-einheit-res) (setq fertig t)) @@ -3784,6 +4962,7 @@ ;; gezeigt. gf-laenge-modus="2" => Zielhoehe zuerst (Zweig B), "3" => ;; steigende GF (Sonderfall, Zweig C, KEIN Separator), sonst (Default ;; "1") Endpunkt waehlen (Zweig A, heutiges Verhalten + Separator). + (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")) @@ -3814,9 +4993,8 @@ ;; --- Zweig C2: Zielhoehe zuerst (steigend) --- (if kettenanfang (progn - (setq linie-mess (vfl-neue-linie-messen p-aktuell nil)) - (if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) - (setq hz-neu (cadr linie-mess)) + (setq hz-neu (vfl-in-richtung p-aktuell (ssg-text "vfl-prompt-richtung-waehlen"))) + (if (null hz-neu) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu 1.0e9 as-seite as-vorhanden)) (setq frame (nth 0 erg) p-aktuell (car frame)) ) @@ -3899,15 +5077,15 @@ ;; --- Zweig B: Zielhoehe zuerst festlegen, Laenge wird berechnet --- (if kettenanfang (progn - (setq linie-mess (vfl-neue-linie-messen p-aktuell nil)) - (if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) - (setq hz-neu (cadr linie-mess)) + (setq hz-neu (vfl-in-richtung p-aktuell (ssg-text "vfl-prompt-richtung-waehlen"))) + (if (null hz-neu) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu 1.0e9 as-seite as-vorhanden)) (setq frame (nth 0 erg) p-aktuell (car frame)) ) (setq hz-neu (car (frame->hz-winkel frame))) ) (setq rad3 (* gf-max-winkel (/ pi 180.0))) + (if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-sep-gf-impl nil)) (princ (ssg-text "vfl-sep-vor-gf-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-nein")) @@ -3998,6 +5176,7 @@ ;; gepickten deltaL abgezogen, damit die Kette exakt am ;; gepickten Punkt endet statt danach ueberzustehen. (setq rad3 (* gf-max-winkel (/ pi 180.0))) + (if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-sep-gf-impl nil)) (princ (ssg-text "vfl-sep-vor-gf-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-nein")) @@ -4019,7 +5198,7 @@ (progn (if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-gefaelle-impl - (list (vfl-gf-hoehe-vorschlag (caddr p-aktuell))))) + (list (vfl-gf-hoehe-vorschlag (caddr p-aktuell)) nil))) (princ (ssg-text "vfl-gefaelle-festlegen-header")) (princ (ssg-text "vfl-gefaelle-opt-hoehe")) (princ (ssg-text "vfl-gefaelle-opt-winkel")) @@ -4147,15 +5326,7 @@ (setq p-aktuell (car frame)) ) ) - (princ (ssg-text "vfl-ist-kettenende-header")) - (princ (ssg-text "vfl-kettenende-opt-ja-es")) - (princ (ssg-text "vfl-kettenende-opt-ja-ohne-es")) - (princ (ssg-text "vfl-kettenende-opt-nein")) - (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")) + (setq antwort (vfl-frage-ist-kettenende)) (cond ((= antwort "1") (setq es-seite (vfl-frage-es-seite)) @@ -4189,53 +5360,121 @@ (if (< deltaL *vfk-vf-mindestlaenge*) (princ (ssg-text "vfl-fehler-vf-kurz")) (progn - (setq hoehe-vorschlaege (vfl-vf-hoehe-vorschlaege (caddr p-aktuell) deltaL)) - (setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege)) - (setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr p-aktuell))) - (vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf) - (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl - (list (list hoehe-ab hoehe-auf (caddr p-aktuell))))) - (setq hoehe-neu - (vfl-in-real - (if (and hoehe-ab hoehe-auf) - (ssg-textf "vfl-prompt-hoehe-linienendpunkt-2" - (list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) - (ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos hoehe-fallback 2 1)))))) - (if (null hoehe-neu) (setq hoehe-neu hoehe-fallback)) - (setq deltaH (- hoehe-neu (caddr p-aktuell))) - (setq richtung (if (>= deltaH 0.0) "Auf" "Ab")) - (setq deltaH (abs deltaH)) - (setq entscheidung (vfl-vf-entscheidung deltaL deltaH richtung)) - (setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung) - L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung)) - (if (null typ) - (progn - (vfl-meldung (ssg-textf "vfl-alert-vf-nicht-baubar" - (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung))) - (if dbg-an - (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Linie-VF nicht baubar (deltaL=" - (rtos deltaL 2 0) " deltaH=" (rtos deltaH 2 0) - " richtung=" richtung ")")))) - (progn - (if dbg-an - (dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss (deltaL=" (rtos deltaL 2 0) - " deltaH=" (rtos deltaH 2 0) " richtung=" richtung - " winkel=" (rtos (float winkel) 2 1) - " L_GF=" (rtos L_GF 2 0) " L_VF=" (rtos L_VF 2 0) ")"))) - (setq vf-einheit-res - (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF nil)) - (setq frame (nth 0 vf-einheit-res)) - (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) - (if (nth 2 vf-einheit-res) (setq fertig t)) - (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) - (setq letzter-typ "VF") - (setq p-aktuell (car frame)) - (if dbg-an - (dbgmsg (strcat "GEOMETRIE ERFOLG: VF-Einheit gebaut, neue Position=" - (dbg-tostring p-aktuell)))) + ;; Eingang haengt vom VORHERIGEN Kettenglied ab (letzter-typ) bzw. + ;; am echten Kettenanfang vom KS_AUS-Scan - siehe + ;; vfl-eingang-modus-bestimmen (gemeinsam mit "Neue VF mit + ;; horizontalem Anfang"). + (setq erg (vfl-eingang-modus-bestimmen letzter-typ kettenanfang as-vorhanden p-aktuell)) + (setq L_GF (car erg) vf-eingang-modus (cdr erg)) + (if vf-eingang-modus + ;; Reduzierter Eingang (Separator/GF/keine): L_GF ist danach immer + ;; 0.0 (vfl-vf-einheit zerlegt L_GF-eff sowieso auf 0.0) - keine + ;; frei waehlbare GF-Laenge mehr, mit der ein 2-Unbekannten-Solve + ;; (vfl-vf-entscheidung) eine beliebige Zielhoehe treffen koennte. + ;; Daher direkt Richtung+Winkel/Hoehen-Tabelle statt Zielhoehe- + ;; Abfrage (siehe vfl-eingang-modus-bestimmen). + (progn + (princ (ssg-text "vfl-frage-auf-ab-richtung")) + (princ (ssg-text "vfl-opt-richtung-auf")) + (princ (ssg-text "vfl-opt-richtung-ab")) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-richtung-impl + (list (ssg-text "vfl-frage-auf-ab-richtung")))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-2") + (list (ssg-text "vfl-opt-richtung-auf") + (ssg-text "vfl-opt-richtung-ab")) 1 + "vfl-frage-auf-ab-richtung")) + (setq richtung (if (= antwort "2") "Ab" "Auf")) + ;; Anders als bei "keine" (Vario-Kurve, dort wird NICHTS gebaut) + ;; wird bei "gf"/"separator" tatsaechlich noch Separator+ + ;; Umlenkstation (bzw. nur Umlenkstation) eingefuegt, BEVOR der + ;; Kletter-Koerper beginnt - das verbraucht reale Laenge/Hoehe + ;; (beide auf 3-Grad-Basis), die hier VOR dem Tabellen-Aufruf + ;; abgezogen werden muss, sonst waere die Tabelle zu optimistisch. + (setq eingang-laenge + (cond + ((equal vf-eingang-modus "gf") (+ *vfk-separator-laenge* *vfk-stations-laenge*)) + ((equal vf-eingang-modus "separator") *vfk-stations-laenge*) + (t 0.0))) + (setq winkel-hoehen-erg + (vfl-waehle-winkel-hoehen-tabelle + (- deltaL (* eingang-laenge (cos (* *vfk-gefaelle-winkel* (/ pi 180.0))))) + richtung + (- (caddr p-aktuell) (* eingang-laenge (sin (* *vfk-gefaelle-winkel* (/ pi 180.0))))))) + (if (null winkel-hoehen-erg) + (princ (ssg-text "vfl-linie-zu-kurz-simple")) + (progn + (setq winkel (nth 0 winkel-hoehen-erg) L_VF (nth 2 winkel-hoehen-erg)) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss reduzierter Eingang (deltaL=" + (rtos deltaL 2 0) " richtung=" richtung + " winkel=" (rtos (float winkel) 2 1) + " L_VF=" (rtos L_VF 2 0) + " eingang-modus=" vf-eingang-modus ")"))) + (setq vf-einheit-res + (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF nil "2" vf-eingang-modus)) + (setq frame (nth 0 vf-einheit-res)) + (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) + (if (nth 2 vf-einheit-res) (setq fertig t)) + (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) + (setq letzter-typ "VF") + (setq p-aktuell (car frame)) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE ERFOLG: VF-Einheit reduzierter Eingang gebaut, neue Position=" + (dbg-tostring p-aktuell)))) + ) ) ) + (progn + (setq hoehe-vorschlaege (vfl-vf-hoehe-vorschlaege (caddr p-aktuell) deltaL)) + (setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege)) + (setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr p-aktuell))) + (vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl + (list (list hoehe-ab hoehe-auf (caddr p-aktuell))))) + (setq hoehe-neu + (vfl-in-real + (if (and hoehe-ab hoehe-auf) + (ssg-textf "vfl-prompt-hoehe-linienendpunkt-2" + (list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) + (ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos hoehe-fallback 2 1)))))) + (if (null hoehe-neu) (setq hoehe-neu hoehe-fallback)) + (setq deltaH (- hoehe-neu (caddr p-aktuell))) + (setq richtung (if (>= deltaH 0.0) "Auf" "Ab")) + (setq deltaH (abs deltaH)) + (setq entscheidung (vfl-vf-entscheidung deltaL deltaH richtung)) + (setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung) + L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung)) + (if (null typ) + (progn + (vfl-meldung (ssg-textf "vfl-alert-vf-nicht-baubar" + (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung))) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Linie-VF nicht baubar (deltaL=" + (rtos deltaL 2 0) " deltaH=" (rtos deltaH 2 0) + " richtung=" richtung ")")))) + (progn + (if dbg-an + (dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss (deltaL=" (rtos deltaL 2 0) + " deltaH=" (rtos deltaH 2 0) " richtung=" richtung + " winkel=" (rtos (float winkel) 2 1) + " L_GF=" (rtos L_GF 2 0) " L_VF=" (rtos L_VF 2 0) ")"))) + (setq vf-einheit-res + (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF nil nil nil)) + (setq frame (nth 0 vf-einheit-res)) + (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) + (if (nth 2 vf-einheit-res) (setq fertig t)) + (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) + (setq letzter-typ "VF") + (setq p-aktuell (car frame)) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE ERFOLG: VF-Einheit gebaut, neue Position=" + (dbg-tostring p-aktuell)))) + ) + ) + ) + ) ) ) ) @@ -4359,17 +5598,7 @@ ;; Sonst nachfragen, ob die Kette hier endet. (if linie-ende-modus (setq antwort "1") - (progn - (princ (ssg-text "vfl-ist-kettenende-header")) - (princ (ssg-text "vfl-kettenende-opt-ja-es")) - (princ (ssg-text "vfl-kettenende-opt-ja-ohne-es")) - (princ (ssg-text "vfl-kettenende-opt-nein")) - (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")) - ) + (setq antwort (vfl-frage-ist-kettenende)) ) (cond ((= antwort "1") @@ -4391,7 +5620,7 @@ " linie-ende-modus=" (if linie-ende-modus "T" "nil") ")"))) (setq vf-einheit-res (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF - linie-ende-modus)) + linie-ende-modus nil nil)) (setq frame (nth 0 vf-einheit-res)) (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) (if (nth 2 vf-einheit-res) (setq fertig t)) @@ -4532,27 +5761,19 @@ (alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) nil) (progn (set_tile "kopf" (ssg-text "vfl-gf-bogen-winkel-header")) - (start_list "winkel") - (add_list (ssg-text "vfl-winkel-30")) - (add_list (ssg-text "vfl-winkel-60")) - (add_list (ssg-text "vfl-winkel-90")) - (end_list) - ;; Winkel 30/60/90 -> Listenposition 0/1/2 - (set_tile "winkel" (itoa (- (length *vfk-gf-bogen-winkel*) - (length (member vor-winkel *vfk-gf-bogen-winkel*))))) - (start_list "seite") - (add_list (ssg-text "gf-seite-links")) - (add_list (ssg-text "gf-seite-rechts")) - (end_list) - (set_tile "seite" (if (= vor-seite-code "2") "1" "0")) + (set_tile (strcat "winkel_" (itoa vor-winkel)) "1") + (set_tile (if (= vor-seite-code "2") "seite_rechts" "seite_links") "1") (action_tile "accept" - "(setq gwinkel (get_tile \"winkel\")) (setq gseite (get_tile \"seite\")) (done_dialog 1)") + "(setq gwinkel (cond ((= (get_tile \"winkel_30\") \"1\") 30) + ((= (get_tile \"winkel_60\") \"1\") 60) + (t 90))) + (setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\")) + (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq ergebnis (start_dialog)) (unload_dialog dat) (if (= ergebnis 1) - (list (nth (atoi gwinkel) *vfk-gf-bogen-winkel*) ; Listenposition 0/1/2 -> 30/60/90 - (if (= gseite "1") "2" "1")) ; Liste 0=links/1=rechts -> code "1"/"2" + (list gwinkel gseite) nil)))) ;; Pre-fill-faehiger Winkel+Seite+Variante-Dialog fuer die Vario-Kurve (nutzt @@ -4570,33 +5791,21 @@ (alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) nil) (progn (set_tile "kopf" (ssg-text "vfl-variokurve-winkel-header")) - (start_list "winkel") - (add_list (ssg-text "vfl-opt3-30grad")) - (add_list (ssg-text "vfl-opt2-60grad")) - (add_list (ssg-text "vfl-opt1-90grad")) - (end_list) - ;; Winkel 30/60/90 -> Listenposition 0/1/2 - (set_tile "winkel" (itoa (- (length *vfk-gf-bogen-winkel*) - (length (member vor-winkel *vfk-gf-bogen-winkel*))))) - (start_list "seite") - (add_list (ssg-text "gf-seite-links")) - (add_list (ssg-text "gf-seite-rechts")) - (end_list) - (set_tile "seite" (if (= vor-seite-code "2") "1" "0")) - (start_list "variante") - (add_list (ssg-text "vfl-variante-aussen")) - (add_list (ssg-text "vfl-variante-innen")) - (end_list) - (set_tile "variante" (if (= vor-variante-code "2") "1" "0")) + (set_tile (strcat "winkel_" (itoa vor-winkel)) "1") + (set_tile (if (= vor-seite-code "2") "seite_rechts" "seite_links") "1") + (set_tile (if (= vor-variante-code "2") "variante_innen" "variante_aussen") "1") (action_tile "accept" - "(setq gwinkel (get_tile \"winkel\")) (setq gseite (get_tile \"seite\")) (setq gvariante (get_tile \"variante\")) (done_dialog 1)") + "(setq gwinkel (cond ((= (get_tile \"winkel_30\") \"1\") 30) + ((= (get_tile \"winkel_60\") \"1\") 60) + (t 90))) + (setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\")) + (setq gvariante (if (= (get_tile \"variante_innen\") \"1\") \"2\" \"1\")) + (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq ergebnis (start_dialog)) (unload_dialog dat) (if (= ergebnis 1) - (list (nth (atoi gwinkel) *vfk-gf-bogen-winkel*) ; Listenposition 0/1/2 -> 30/60/90 - (if (= gseite "1") "2" "1") ; Liste 0=links/1=rechts -> "1"/"2" - (if (= gvariante "1") "2" "1")) ; Liste 0=aussen/1=innen -> "1"/"2" + (list gwinkel gseite gvariante) nil)))) ;; Pre-fill-faehiger Winkel+Seite-Dialog fuer AS/ES-Element: nur ZWEI @@ -4613,25 +5822,19 @@ (progn (if (and dat (>= dat 0)) (unload_dialog dat)) (alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) nil) (progn + (mode_tile "winkel_60" 1) (set_tile "kopf" (ssg-text kopf-key)) - (start_list "winkel") - (add_list (ssg-text "vf-winkel-90")) - (add_list (ssg-text "vf-winkel-30")) - (end_list) - (set_tile "winkel" (if (= vor-winkel-str "30") "1" "0")) ; Liste 0=90/1=30 - (start_list "seite") - (add_list (ssg-text "gf-seite-links")) - (add_list (ssg-text "gf-seite-rechts")) - (end_list) - (set_tile "seite" (if (= vor-seite-code "2") "1" "0")) + (set_tile (if (= vor-winkel-str "30") "winkel_30" "winkel_90") "1") + (set_tile (if (= vor-seite-code "2") "seite_rechts" "seite_links") "1") (action_tile "accept" - "(setq gwinkel (get_tile \"winkel\")) (setq gseite (get_tile \"seite\")) (done_dialog 1)") + "(setq gwinkel (if (= (get_tile \"winkel_30\") \"1\") \"30\" \"90\")) + (setq gseite (if (= (get_tile \"seite_rechts\") \"1\") \"2\" \"1\")) + (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq ergebnis (start_dialog)) (unload_dialog dat) (if (= ergebnis 1) - (list (if (= gwinkel "1") "30" "90") ; Liste 0=90/1=30 -> "90"/"30" - (if (= gseite "1") "2" "1")) ; Liste 0=links/1=rechts -> "1"/"2" + (list gwinkel gseite) nil)))) ;; --- AS-/ES-Element (Winkel 30/90 + Seite links/rechts) --- @@ -5023,6 +6226,9 @@ (if (/= as "Nein") (progn ;; gleiche Frage wie im Bau-Ablauf (liefert "30"/"90") + (princ (ssg-text "vf-winkel-aus-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) (setq w (vf-frage-element-winkel "vf-winkel-aus-header")) (initget "Links Rechts") (setq s (getkword (ssg-text "vfl-restore-frage-as-seite"))) @@ -5345,7 +6551,7 @@ ;; VF-Einheit OEFFNEN (Modus 2): GF1 (Basis-Staustrecke) + Separator + ;; Umlenkstation. Rueckgabe: Frame nach der Umlenkstation (Beginn reiner VF). (defun vfl2-vf-open (frame hz / f) - (setq f (vfl-frame-3grad (vfs-vf-entry (car frame) *vfl-gf-min-laenge* hz) hz)) + (setq f (vfl-frame-3grad (vfs-vf-entry (car frame) *vfl-gf-min-laenge* hz nil) hz)) (if (> *vfl-gf-min-laenge* 0.1) (vfl-acc-gf-seg *vfl-gf-min-laenge* (ssg-cfg-or "vario" "gefaelle_winkel" 3))) f) @@ -5439,6 +6645,9 @@ (list "vf-winkel-aus-header" (list (ssg-text "vf-winkel-90") (ssg-text "vf-winkel-30")) (list "90" "30")))) + (princ (ssg-text "vf-winkel-aus-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) (setq *vfl-as-winkel* (vfl-in-value "STR" (function (lambda () (vf-frage-element-winkel "vf-winkel-aus-header"))))) ; 30/90 vor Seite @@ -5853,14 +7062,17 @@ vf-run-member carrier-idx kv-variante seg-hz letzt-koerper-hz vf-first-line vf-last-line climber-span mid-hor z-aftermotor gf2-drop gf2-planar br-lvf this-lvf - nach-kurve n-climb n-hor target-climb winkel-list + nach-kurve nach-vf sep-vor-gf sep-nach-gf + n-climb n-hor target-climb winkel-list fdz fdx wslope lvf planar-len ang-diff best-diff w climb-thresh longest-idx climbers nonclimber-len nonclimber-cnt nkurve kurve-chords run-span - hor-koerper-len hor-pairs flat-p fill-len wahl3 + hor-koerper-len hor-pairs flat-p flat-zone-erste fill-len wahl3 rad3v feste-vf dH-adj dir-x dir-y fill-D end-hz gf-total br-gf-mode br-gf2-exp filler-A-len filler-a-done - as-vorhanden es-vorhanden dbg-an dbg-old-error) + as-vorhanden es-vorhanden dbg-an dbg-old-error + m2-lauf-antwort m2-offenes-ende + m2-front-antwort m2-offener-anfang m2-kein-gf1-vorne entry-fixed) (princ "\n\n=========================================") (princ (ssg-text "vfl-m3-titel")) (princ "\n=========================================") @@ -5922,6 +7134,9 @@ (setq *vfl-as-winkel* nil *vfl-es-winkel* nil) (if as-vorhanden (progn + (princ (ssg-text "vf-winkel-aus-header")) + (princ (ssg-text "vf-winkel-90")) + (princ (ssg-text "vf-winkel-30")) (setq *vfl-as-winkel* (vfl-in-value "STR" (function (lambda () (vf-frage-element-winkel "vf-winkel-aus-header"))))) ; 30/90 vor Seite @@ -5957,6 +7172,9 @@ (setq es-vorhanden (/= antwort "2")) (if es-vorhanden (progn + (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"))))) ; 30/90 vor Seite @@ -5992,8 +7210,12 @@ ;; Wizard: alle Fragen dieses Segments in EINEM Dialog erfassen (die ;; unveraenderten vfl-menu/vfl-in-*-Aufrufe unten konsumieren die Antworten ;; aus *vflw-pending*). Segment vorher in der Zeichnung hervorheben. Der - ;; nach-kurve-Fall stellt keine Frage (auto-VF) -> kein Dialog. - (if (and (vfl-wizard-aktiv) (not (and (= typ "Linie") nach-kurve))) + ;; nach-kurve-Fall stellt keine Frage (auto-VF) -> kein Dialog. Ebenso + ;; nach-vf bei einem Bogen: Vario-Kurve ist dann erzwungen (eine VF- + ;; Einheit kann nicht in einen GF-Bogen auslaufen), auch kein Dialog. + (if (and (vfl-wizard-aktiv) + (not (and (= typ "Linie") nach-kurve)) + (not (and (= typ "Bogen") nach-vf))) (progn (vfl-seg-highlight seg-ent T) (if (= typ "Linie") @@ -6016,28 +7238,47 @@ (nach-kurve (princ (ssg-text "vfl-m3-auto-vf")) (setq plan (cons (list "Linie" hz laenge "VF" nil) plan)) - (setq nach-kurve nil)) + (setq nach-kurve nil nach-vf t)) (t (princ (ssg-text "vfl-m3-typ-gerade")) (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") (list "GF (Neigungswinkel)" "VF (Bruecke)") 1 "vfl-m3-typ-gerade")) (if (= antwort "2") - (setq plan (cons (list "Linie" hz laenge "VF" nil) plan)) + (progn + (setq plan (cons (list "Linie" hz laenge "VF" nil) plan)) + (setq nach-vf t)) (progn (setq winkel (vfl-in-real (ssg-text "vfl-m3-prompt-gf-neigung"))) (if (null winkel) (setq winkel *vfk-gefaelle-winkel*)) (if (> winkel *vfk-gefaelle-winkel*) (progn (princ (ssg-text "vfl-m3-hinweis-gf-max")) (setq winkel *vfk-gefaelle-winkel*))) - (setq plan (cons (list "Linie" hz laenge "GF" winkel) plan))))))) + ;; Separator VOR/NACH diesem GF-Stueck (analog Modus 1) - die + ;; Planlaenge bleibt hier UNVERAENDERT (reale Pfadlaenge, fuer + ;; die Anker-Vorschau noetig); die Trennung in GF-Koerper+ + ;; Separator passiert erst beim Bauen (Phase B). + (princ (ssg-text "vfl-sep-vor-gf-frage")) + (setq sep-vor-gf (= (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 2 + "vfl-sep-vor-gf-frage") "1")) + (princ (ssg-text "vfl-sep-nach-gf-frage")) + (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")) + (setq plan (cons (list "Linie" hz laenge "GF" winkel sep-vor-gf sep-nach-gf) plan)) + (setq nach-vf nil)))))) ((= typ "Bogen") (setq bwinkel (nth 3 seg) bseite (nth 4 seg)) (princ (ssg-textf "vfl-m3-seg-bogen" (list (itoa (1+ i)) (itoa n) (itoa bwinkel) bseite))) - (princ (ssg-text "vfl-m3-typ-bogen")) - (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") - (list "GF-Bogen" "Vario-Kurve") 1 - "vfl-m3-typ-bogen")) + (if nach-vf + (setq antwort "2") ; nach VF-Gerade: Vario-Kurve erzwungen, keine Typ-Frage + (progn + (princ (ssg-text "vfl-m3-typ-bogen")) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list "GF-Bogen" "Vario-Kurve") 1 + "vfl-m3-typ-bogen")))) + (setq nach-vf nil) (if (= antwort "2") (progn (princ (ssg-text "vfl-m3-variante-frage")) @@ -6138,6 +7379,58 @@ (princ (ssg-text "vfl-m3-anker-hinweis")) (princ "\n=========================================") + ;; --- Lauf-Anfang waehlen, NUR wenn der VF-Lauf der Pfadanfang ist (kein + ;; Front-Lauf davor) - sonst bleibt die Steuerung komplett unveraendert (AS- + ;; Element aus der Upfront-Frage, Umlenkstation+GF1+Separator immer gebaut). + ;; Muss VOR der Phase-B2-Fussabdruck-Berechnung (entry-fixed) feststehen. + (setq m2-offener-anfang nil m2-kein-gf1-vorne nil) + (if (= vf-start 0) + (progn + (princ (ssg-text "vfl-m3-lauf-anfang-header")) + (princ (ssg-text "vfl-m3-lauf-anfang-opt-offen")) + (princ (ssg-text "vfl-m3-lauf-anfang-opt-umlenk")) + (princ (ssg-text "vfl-m3-lauf-anfang-opt-umlenk-gf1")) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-m2-lauf-anfang-impl (list "vfl-m3-lauf-anfang-header"))) + (setq m2-front-antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") + (list (ssg-text "vfl-m3-lauf-anfang-opt-offen") + (ssg-text "vfl-m3-lauf-anfang-opt-umlenk") + (ssg-text "vfl-m3-lauf-anfang-opt-umlenk-gf1")) 3 + "vfl-m3-lauf-anfang-header")) + (cond + ((= m2-front-antwort "1") + (setq as-vorhanden nil m2-offener-anfang t) + (princ (ssg-text "vfl-m3-lauf-anfang-offen-hinweis"))) + ((= m2-front-antwort "2") (setq m2-kein-gf1-vorne t))))) + + ;; --- Lauf-Abschluss waehlen, NUR wenn der VF-Lauf das Pfadende ist (kein + ;; Back-Lauf danach) - sonst bleibt die Steuerung komplett unveraendert + ;; (es-vorhanden aus der Upfront-Frage, Motorstation immer gebaut). "Ohne + ;; Motorstation" muss VOR der Phase-B2-Zielhoehen-Berechnung feststehen, + ;; da sie die Separator/ES-Naeherung in vfl3-dback wieder aufhebt. + (setq m2-offenes-ende nil) + (if (= vf-ende (1- n)) + (progn + (princ (ssg-text "vfl-m3-lauf-abschluss-header")) + (princ (ssg-text "vfl-m3-lauf-abschluss-opt-offen")) + (princ (ssg-text "vfl-m3-lauf-abschluss-opt-motor")) + (princ (ssg-text "vfl-m3-lauf-abschluss-opt-motor-es")) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-m2-lauf-abschluss-impl (list "vfl-m3-lauf-abschluss-header"))) + (setq m2-lauf-antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def2") + (list (ssg-text "vfl-m3-lauf-abschluss-opt-offen") + (ssg-text "vfl-m3-lauf-abschluss-opt-motor") + (ssg-text "vfl-m3-lauf-abschluss-opt-motor-es")) 2 + "vfl-m3-lauf-abschluss-header")) + (cond + ((= m2-lauf-antwort "1") + (setq es-vorhanden nil m2-offenes-ende t) + (princ (ssg-text "vfl-m3-lauf-abschluss-offen-hinweis"))) + ((= m2-lauf-antwort "3") + (setq es-vorhanden t) + (if (null es-seite) (setq es-seite (vfl-frage-es-seite)))) + (t (setq es-vorhanden nil))))) + ;; ================= PHASE B: BAUEN (messen statt schaetzen) ================= ;; VF-Lauf darf mehrsegmentig sein (VF-Geraden + Vario-Kurven, EINE VF-Einheit). ;; Nummerierung + Akkumulatoren + AS/ES-Fussabdruecke. Ohne AS-Element (aus- @@ -6188,7 +7481,7 @@ (setq seg (nth i plan) typ (car seg) hz (cadr seg)) (cond ((= typ "Linie") - (setq winkel (nth 4 seg)) + (setq winkel (nth 4 seg) sep-vor-gf (nth 5 seg) sep-nach-gf (nth 6 seg)) ;; AS zuerst platzieren (falls gewuenscht), damit der echte KS_AUS bekannt ;; ist. Ohne AS-Element beginnt die Kette direkt am Startpunkt (flach) - ;; die nachfolgende Fussabdruck-Trimmung wird dann automatisch zu 0, da @@ -6204,10 +7497,30 @@ (setq deltaL (- deltaL (+ (* (- (car (car frame)) (car startpunkt)) (cos (* hz (/ pi 180.0)))) (* (- (cadr (car frame)) (cadr startpunkt)) (sin (* hz (/ pi 180.0)))))))) + ;; Separator(en) VOR/NACH aus der Klassifizierung (Punkt 1): die reale + ;; Planlaenge (deltaL, oben aus dem gemessenen Pfad) bleibt fuer die + ;; Anker-Vorschau unangetastet - erst HIER, beim tatsaechlichen Bauen, + ;; wird der GF-Koerper um die Separator-Laenge(n) verkuerzt. + (if sep-vor-gf (setq deltaL (- deltaL *vfk-separator-laenge*))) + (if sep-nach-gf (setq deltaL (- deltaL *vfk-separator-laenge*))) (setq deltaL (max *vfk-restlaenge-min-clamp* deltaL)) + (if sep-vor-gf + (progn + (setq frame (make-frame-from-dir + (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" + (car frame) hz winkel *vfk-separator-laenge* 0) + (hz-winkel->xu hz winkel))) + (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)))) (setq frame (vfl-insert-gf-segment (car frame) hz deltaL winkel)) (vfl-acc-gf-seg (/ deltaL (cos (* winkel (/ pi 180.0)))) winkel) - (setq anzahl-gf (1+ anzahl-gf) letzt-winkel winkel)) + (setq anzahl-gf (1+ anzahl-gf) letzt-winkel winkel) + (if sep-nach-gf + (progn + (setq frame (make-frame-from-dir + (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" + (car frame) hz winkel *vfk-separator-laenge* 0) + (hz-winkel->xu hz winkel))) + (setq *vfl-acc-separator* (1+ *vfl-acc-separator*))))) ((= typ "Bogen") (setq bwinkel (nth 3 seg) bseite (nth 4 seg) klass (nth 5 seg)) (if (= klass "GF-Bogen") @@ -6230,6 +7543,10 @@ ;; --- B2: Back-Abstieg -> Junction; Kletterer + Horizontal-Mitte bestimmen --- (setq z-junction (+ (float end-hoehe) (vfl3-dback plan (1+ vf-ende) n last-line ein))) + ;; Offenes Ende (kein Motor/Separator/ES danach): vfl3-dback's Tail-Naeherung + ;; (reserviert IMMER einen Separator+ES-Fussabdruck) ist hier falsch - die + ;; Zielhoehe fuer den Loeser ist exakt end-hoehe. + (if m2-offenes-ende (setq z-junction (float end-hoehe))) (setq dH-bruecke (- z-front z-junction)) ;; Modell: EIN Vario mit Horizontal-Mitte. Nur VF-Geraden, die LANG GENUG sind ;; (Vertikalboegen brauchen viel Platz), tragen die Hoehe (Kletterer, gleicher @@ -6260,6 +7577,11 @@ ;; (ein auf_3 rein, ein ab_3 raus), unabhaengig von der Zahl der Fueller/Kurven. (setq hor-pairs (if (or (> nkurve 0) (> nonclimber-cnt 0)) 1 0)) (setq run-span (+ climber-span nonclimber-len kurve-chords)) + ;; Laengen-Obergrenze fuer eine angetriebene VF-Einheit (Konstruktions- + ;; grenze, siehe *vfk-vf-laenge-max*) - nur Hinweis, kein Abbruch. + (if (> run-span *vfk-vf-laenge-max*) + (vfl-meldung (ssg-textf "vfl-m3-alert-vf-zu-lang" + (list (rtos (/ run-span 1000.0) 2 1) (rtos (/ *vfk-vf-laenge-max* 1000.0) 2 1))))) (setq br-gf1 *vfl-gf-min-laenge*) ; feste kleine GF1 (setq br-richtn (if (< dH-bruecke 0) "Auf" "Ab")) (setq target-climb (- z-junction z-front)) ; noetige Netto-Hoehe (Auf>0) @@ -6273,32 +7595,75 @@ (list (rtos target-climb 2 1) (itoa n-climb) (itoa nkurve) (itoa nonclimber-cnt)))) ;; feste-Horizontal + Hoehen-Anpassung fuer den Solver: ;; - Mit flacher Zone: Motor sitzt am Kettenende (nicht im Kletter-Segment) -> - ;; feste = 800 (Umlenk+Sep). berechne rechnet Motor-/Uebergangs-Abstieg NICHT, - ;; daher Kletterhoehe um diese Abstiege anpassen (GF2 bleibt ~0). - ;; - Ohne flache Zone (Einzel-Bruecke): feste = 1300 (inkl. Motor), keine Anpassung. + ;; feste = entry-fixed (Umlenk+Sep, ODER weniger bei Lauf-Anfang-Wahl). + ;; berechne rechnet Motor-/Uebergangs-Abstieg NICHT, daher Kletterhoehe + ;; um diese Abstiege anpassen (GF2 bleibt ~0) - ausser bei offenem Ende. + ;; - Ohne flache Zone (Einzel-Bruecke): feste = entry-fixed + Motor (0 bei + ;; offenem Ende), keine Hoehen-Anpassung. (setq rad3v (* *vfk-gefaelle-winkel* (/ pi 180.0))) + ;; Eingangs-Fussabdruck haengt von der Lauf-Anfang-Wahl ab (siehe oben) - + ;; Default (beide Flags nil) ergibt exakt die bisherigen 800/1300. + (setq entry-fixed + (cond (m2-offener-anfang 0.0) + (m2-kein-gf1-vorne *vfk-stations-laenge*) + (t (+ *vfk-stations-laenge* *vfk-separator-laenge*)))) (if (> hor-pairs 0) - (setq feste-vf *vfk-feste-horizontal-kettenende* + (setq feste-vf entry-fixed dH-adj (- dH-bruecke (+ (* *vfk-stations-laenge* (sin rad3v)) *vfk-bruecke-korrektur*))) ; Motor + auf_3/ab_3 - (setq feste-vf *vfk-feste-horizontal-linienzug* dH-adj dH-bruecke)) + (setq feste-vf (+ entry-fixed (if m2-offenes-ende 0.0 *vfk-stations-laenge*)) dH-adj dH-bruecke)) + ;; Offenes Ende (m2-offenes-ende): kein Motor wird gebaut, die obige + ;; Motor-Abstiegs-Korrektur darf dann NICHT abgezogen werden - der Solver + ;; soll die volle dH-bruecke exakt treffen (Ziel = z-junction = end-hoehe). + (if m2-offenes-ende (setq dH-adj dH-bruecke)) (setq wahl3 (vfl3-waehle-winkel climber-span dH-adj feste-vf)) (if (null wahl3) - (progn (princ (ssg-text "vfl-m3-kein-winkel")) - (princ) (exit))) - (setq br-winkel (car wahl3) gf-total (cadr wahl3) br-lvf (caddr wahl3) br-richtn (cadddr wahl3)) - ;; GF-Verteilung: 1 = alles am Einlauf (GF1); 2 = 1/2 GF1 + 1/2 GF2. Bei 1/2/1/2 - ;; wird der im Kletter-Segment durch das halbe GF1 frei werdende Platz mit einem - ;; horizontalen Fueller-A gefuellt; GF2 (~1/2 L_GF) sitzt hinter dem Motor, der - ;; ES-Laengen-Abschluss zieht seinen Fussabdruck ab (Fueller-B wird kuerzer). + (progn + ;; Stufe 2: KEIN Tabellenwinkel passt (der/die Kletterer sind bei JEDER + ;; Neigung zu kurz fuer Umlenkstation+2 Vertikalboegen) - ganzer Lauf wird + ;; flach gebaut, wie die bereits vorhandenen "kurzen" VF-Geraden. Die + ;; komplette Hoehe wandert in GF1 (reine Kompensation, darf legitim + ;; (nahe) 0 sein). + (princ (ssg-text "vfl-m3-kletter-zu-kurz-flach")) + (setq nonclimber-len (+ nonclimber-len climber-span) + nonclimber-cnt (+ nonclimber-cnt n-climb)) + (setq climbers '() n-climb 0 climber-span 0.0) + ;; hor-pairs war ggf. 0 (reine Einzel-Bruecke ohne Kurve/Fueller) - jetzt + ;; gibt es garantiert mindestens einen Fueller (den ex-Kletterer), also + ;; feste-vf/dH-adj auf die flache-Zone-Variante nachziehen. + (if (<= hor-pairs 0) + (progn + (setq hor-pairs 1) + (setq feste-vf entry-fixed + dH-adj (- dH-bruecke (+ (* *vfk-stations-laenge* (sin rad3v)) *vfk-bruecke-korrektur*))))) + (if m2-offenes-ende (setq dH-adj dH-bruecke)) + (setq br-winkel (fix *vfk-gefaelle-winkel*) br-lvf 0.0 + br-richtn (if (< dH-adj 0) "Auf" "Ab") + gf-total (/ (abs dH-adj) (/ (sin rad3v) (cos rad3v)))) + (princ (ssg-textf "vfl-m3-kletter-flach-gf" (list (rtos gf-total 2 0))))) + (setq br-winkel (car wahl3) gf-total (cadr wahl3) br-lvf (caddr wahl3) br-richtn (cadddr wahl3))) + ;; GF-Verteilung: 1 = alles am Einlauf (GF1); 2 = 1/2 GF1 + 1/2 GF2; 3 = alles + ;; am Auslauf (GF2) - erzwungen (kein GF1-Platz), wenn der Lauf-Anfang ohne + ;; GF1 gewaehlt wurde (offener Anfang ODER Umlenkstation direkt). Bei 1/2/1/2 + ;; wird der im Kletter-Segment durch das halbe GF1 frei werdende Platz mit + ;; einem horizontalen Fueller-A gefuellt; GF2 (~1/2 L_GF) sitzt hinter dem + ;; Motor, der ES-Laengen-Abschluss zieht seinen Fussabdruck ab (Fueller-B + ;; wird kuerzer). (princ (ssg-text "vfl-m3-gf-verteilung")) - (setq br-gf-mode - (if (= (vfl-menu (ssg-text "prompt-wahl-1-2") - (list "Alles am Einlauf (GF1)" "1/2 GF1 + 1/2 GF2") 1 - "vfl-m3-gf-verteilung") "2") 2 1)) - (if (= br-gf-mode 2) - (setq br-gf1 (/ gf-total 2.0) br-gf2-exp (/ gf-total 2.0) - filler-A-len (* (/ gf-total 2.0) (cos rad3v))) - (setq br-gf1 gf-total br-gf2-exp 0.0 filler-A-len 0.0)) + (if (or m2-offener-anfang m2-kein-gf1-vorne) + (progn + (setq br-gf-mode 3 br-gf1 0.0 br-gf2-exp gf-total filler-A-len 0.0) + (princ (ssg-text "vfl-m3-gf-verteilung-alles-auslauf"))) + (progn + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-gf-verteilung-impl (list (ssg-text "vfl-m3-gf-verteilung") "2" "1"))) + (setq br-gf-mode + (if (= (vfl-menu (ssg-text "prompt-wahl-1-2") + (list "Alles am Einlauf (GF1)" "1/2 GF1 + 1/2 GF2") 1 + "vfl-m3-gf-verteilung") "2") 2 1)) + (if (= br-gf-mode 2) + (setq br-gf1 (/ gf-total 2.0) br-gf2-exp (/ gf-total 2.0) + filler-A-len (* (/ gf-total 2.0) (cos rad3v))) + (setq br-gf1 gf-total br-gf2-exp 0.0 filler-A-len 0.0)))) (setq filler-a-done nil) (princ (ssg-textf "vfl-m3-vario-ergebnis" (list (itoa br-winkel) @@ -6306,8 +7671,9 @@ (ssg-text "vfl-m3-richtung-ab-kurz")) (rtos br-lvf 2 0) (rtos gf-total 2 0) - (if (= br-gf-mode 2) (ssg-text "vfl-m3-vert-halb") - (ssg-text "vfl-m3-vert-ganz"))))) + (cond ((= br-gf-mode 2) (ssg-text "vfl-m3-vert-halb")) + ((= br-gf-mode 3) (ssg-text "vfl-m3-vert-auslauf")) + (t (ssg-text "vfl-m3-vert-ganz")))))) ;; --- B3: Standard-Vario (Klettern, 3-Grad-Basis) + flache Zone (0 Grad) --- ;; Die flache Zone (Vario-Kurve + horizontaler Fueller) haengt EINMAL ueber auf_3 @@ -6315,8 +7681,13 @@ ;; verbunden (keine Zwischen-Boegen). Der horizontale Fueller gleicht die ;; Restlaenge aus (letztes Stueck vor dem Motor getrimmt). (setq pt (car frame) letzt-koerper-hz (cadr (nth vf-start plan)) flat-p nil) - (setq pt (vfs-vf-entry pt br-gf1 letzt-koerper-hz)) ; GF1 + Separator + Umlenk (3 Grad) - (vfl-acc-gf-seg br-gf1 3) + ;; Lauf-Anfang: offener Anfang ueberspringt Umlenkstation komplett; sonst + ;; GF1 (0, wenn m2-kein-gf1-vorne oder GF-Verteilung das so ergab) + ggf. + ;; Separator (uebersprungen bei m2-kein-gf1-vorne) + Umlenk (3 Grad). + (if (not m2-offener-anfang) + (progn + (setq pt (vfs-vf-entry pt br-gf1 letzt-koerper-hz m2-kein-gf1-vorne)) + (vfl-acc-gf-seg br-gf1 3))) (setq i vf-start) (while (<= i vf-ende) (setq seg (nth i plan) seg-hz (cadr seg)) @@ -6330,6 +7701,7 @@ (setq anzahl-vf (1+ anzahl-vf) letzt-koerper-hz seg-hz)) ;; --- kurze VF-Gerade -> horizontaler Fueller (0 Grad) --- ((= (car seg) "Linie") + (setq flat-zone-erste (not flat-p)) (if (not flat-p) (progn (setq pt (vfl3-flach-ein pt letzt-koerper-hz)) (setq flat-p t) ;; Fueller-A: der im Kletter-Segment durch 1/2 GF1 frei werdende Platz @@ -6358,6 +7730,15 @@ ) ) (setq fill-len (caddr seg))) + ;; Kritische Fueller-Position (direkt nach Umlenkstation ODER direkt vor + ;; Motorstation) zu kurz fuer den geforderten Wert - statt still zu + ;; klemmen, den Nutzer warnen (Zielhoehe/-position wird dann nicht exakt + ;; erreicht, siehe vfl-m3-warnung-gf2-negativ fuer die Hoehen-Seite). + (if (and (< fill-len *vfk-restlaenge-min-clamp*) (or flat-zone-erste (= i vf-ende))) + (vfl-meldung (ssg-textf + (if flat-zone-erste "vfl-m3-warnung-fueller-eingang-zu-kurz" + "vfl-m3-warnung-fueller-ausgang-zu-kurz") + (list (rtos fill-len 2 0) (rtos *vfk-restlaenge-min-clamp* 2 0))))) (setq fill-len (max *vfk-restlaenge-min-clamp* fill-len)) (setq pt (insert-inclined-scaled-block "Staustrecke_SP_1000_mm" pt fill-len 0 seg-hz)) (vfl-acc-vf-seg "horizontal" 0 fill-len) (setq anzahl-vf (1+ anzahl-vf)) @@ -6379,24 +7760,30 @@ (setq pt (car frame)) (if (< i vf-ende) (setq letzt-koerper-hz (cadr (nth (1+ i) plan)))))) (setq i (1+ i))) - (if flat-p (progn (setq pt (vfl3-flach-aus pt letzt-koerper-hz)) (setq flat-p nil))) ; zurueck 3 Grad - ;; Motorstation (ohne GF2) - (setq pt (vfs-vf-exit pt 0.0 letzt-koerper-hz nil)) - (setq *vfl-acc-motorseite* (append *vfl-acc-motorseite* (list "rechts"))) - ;; GF2 = gemessener exakter Hoehen-Ausgleich (Abstieg bis zur Junction) - (setq z-aftermotor (caddr pt)) - (setq gf2-drop (- z-aftermotor z-junction)) - (if (< gf2-drop 0.0) + (if m2-offenes-ende + ;; Bewusst offenes Ende (kein Motor/Separator/ES) - Lauf bleibt flach + ;; (0 Grad) genau dort stehen, wo die Bau-Schleife endete; KEIN + ;; Rueck-Uebergang auf 3 Grad, KEINE Motorstation/GF2. + (setq frame (make-frame-from-dir pt (hz-winkel->xu letzt-koerper-hz 0.0))) (progn - (princ (ssg-textf "vfl-m3-warnung-gf2-negativ" (list (rtos (- gf2-drop) 2 1)))) - (setq gf2-drop 0.0))) - (setq gf2-planar (/ gf2-drop (/ (sin (* *vfk-gefaelle-winkel* (/ pi 180.0))) (cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))))) - (if (> gf2-planar 0.1) - (progn - (princ (ssg-textf "vfl-m3-gf2-ausgleich" (list (rtos gf2-planar 2 1)))) - (setq frame (vfl-insert-gf-segment pt letzt-koerper-hz gf2-planar (fix *vfk-gefaelle-winkel*))) - (vfl-acc-gf-seg (/ gf2-planar (cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))) (fix *vfk-gefaelle-winkel*))) - (setq frame (vfl-frame-3grad pt letzt-koerper-hz))) + (if flat-p (progn (setq pt (vfl3-flach-aus pt letzt-koerper-hz)) (setq flat-p nil))) ; zurueck 3 Grad + ;; Motorstation (ohne GF2) + (setq pt (vfs-vf-exit pt 0.0 letzt-koerper-hz nil)) + (setq *vfl-acc-motorseite* (append *vfl-acc-motorseite* (list "rechts"))) + ;; GF2 = gemessener exakter Hoehen-Ausgleich (Abstieg bis zur Junction) + (setq z-aftermotor (caddr pt)) + (setq gf2-drop (- z-aftermotor z-junction)) + (if (< gf2-drop 0.0) + (progn + (vfl-meldung (ssg-textf "vfl-m3-warnung-gf2-negativ" (list (rtos (- gf2-drop) 2 1)))) + (setq gf2-drop 0.0))) + (setq gf2-planar (/ gf2-drop (/ (sin (* *vfk-gefaelle-winkel* (/ pi 180.0))) (cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))))) + (if (> gf2-planar 0.1) + (progn + (princ (ssg-textf "vfl-m3-gf2-ausgleich" (list (rtos gf2-planar 2 1)))) + (setq frame (vfl-insert-gf-segment pt letzt-koerper-hz gf2-planar (fix *vfk-gefaelle-winkel*))) + (vfl-acc-gf-seg (/ gf2-planar (cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))) (fix *vfk-gefaelle-winkel*))) + (setq frame (vfl-frame-3grad pt letzt-koerper-hz))))) (setq hz letzt-koerper-hz) ;; --- B4: BACK-Lauf bauen (Segmente vf-ende+1 .. n-1) --- @@ -6405,15 +7792,33 @@ (setq seg (nth i plan) typ (car seg) hz (cadr seg)) (cond ((= typ "Linie") - (setq winkel (nth 4 seg) deltaL (caddr seg)) + (setq winkel (nth 4 seg) deltaL (caddr seg) + sep-vor-gf (nth 5 seg) sep-nach-gf (nth 6 seg)) ;; Footprint fuer Separator(300)+ES nur reservieren, wenn ES-Element ;; gewuenscht ist (ein=0 sonst, siehe oben) - ohne ES entfaellt auch ;; der abschliessende Separator. (if (= i last-line) (setq deltaL (- deltaL (if es-vorhanden *vfk-separator-laenge* 0.0) ein))) + ;; Separator(en) VOR/NACH aus der Klassifizierung (Punkt 1, wie B1). + (if sep-vor-gf (setq deltaL (- deltaL *vfk-separator-laenge*))) + (if sep-nach-gf (setq deltaL (- deltaL *vfk-separator-laenge*))) (setq deltaL (max *vfk-restlaenge-min-clamp* deltaL)) + (if sep-vor-gf + (progn + (setq frame (make-frame-from-dir + (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" + (car frame) hz winkel *vfk-separator-laenge* 0) + (hz-winkel->xu hz winkel))) + (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)))) (setq frame (vfl-insert-gf-segment (car frame) hz deltaL winkel)) (vfl-acc-gf-seg (/ deltaL (cos (* winkel (/ pi 180.0)))) winkel) - (setq anzahl-gf (1+ anzahl-gf) letzt-winkel winkel)) + (setq anzahl-gf (1+ anzahl-gf) letzt-winkel winkel) + (if sep-nach-gf + (progn + (setq frame (make-frame-from-dir + (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" + (car frame) hz winkel *vfk-separator-laenge* 0) + (hz-winkel->xu hz winkel))) + (setq *vfl-acc-separator* (1+ *vfl-acc-separator*))))) ((= typ "Bogen") (setq bwinkel (nth 3 seg) bseite (nth 4 seg) klass (nth 5 seg)) (if (= klass "GF-Bogen") diff --git a/Lisp/vf_spec.lsp b/Lisp/vf_spec.lsp index 6b620c8..437e89a 100644 --- a/Lisp/vf_spec.lsp +++ b/Lisp/vf_spec.lsp @@ -202,6 +202,15 @@ " erlaubt - jedes weitere erbt die Fahrtrichtung" " vom Vorgaenger und hat keinen Journal-Eintrag"))))) +;; Reine Richtungswahl OHNE Laenge (vfl-in-richtung: journalisiert NUR REAL, +;; kein DL-Token) - fuer den Kettenanfang-Fall der Zielhoehe-zuerst-Zweige +;; ("Linie-GF" modus="hoehe"/"steigend"+"hoehe"), wo noch keine Laenge +;; bekannt ist. Nur beim allerersten Segment der Kette relevant (sonst gar +;; kein Aufruf, siehe Aufrufer) - toggelt *vsp-erster-dl* wie vsp-linie. +(defun vsp-richtung (quelle) + (vsp-zahl "REAL" (ssg-val quelle "hz") "hz (Richtungswahl, kein DL noetig)") + (setq *vsp-erster-dl* nil)) + ;; Winkelwahl (vfl-waehle-winkel) steht nur im Journal, wenn mehrere ;; Kandidatenwinkel gueltig waren - das haengt an der real gemessenen ;; Restlaenge und ist vorab nicht immer bekannt. Fehlt das Feld und der Bau @@ -275,12 +284,12 @@ (vsp-code-raus *vsp-tab-gf-laenge-modus* smodus "steigend_modus") (if (= smodus "endpunkt") (vsp-linie sek) - (if erster (vsp-linie sek))) + (if erster (vsp-richtung sek))) (if (= smodus "hoehe") (vsp-zahl "REAL" (ssg-val sek "hoehe") "hoehe")) (vsp-zahl "REAL" (ssg-val sek "winkel") "winkel")) ((= modus "hoehe") - (if erster (vsp-linie sek)) + (if erster (vsp-richtung sek)) (vsp-raus "STR" (vsp-ja-code (ssg-val sek "sep_vor"))) (vsp-raus "STR" (vsp-ja-code (ssg-val sek "sep_nach"))) (vsp-zahl "REAL" (ssg-val sek "hoehe") "hoehe") diff --git a/Lisp/vf_standard.lsp b/Lisp/vf_standard.lsp index d5a8ec5..b903ed0 100644 --- a/Lisp/vf_standard.lsp +++ b/Lisp/vf_standard.lsp @@ -337,20 +337,32 @@ ;; erreichbar (im Rahmen von deltaL), GF1+GF2 werden einfach laenger. ;; - "Auf": wirkt der gewuenschten Steigung entgegen -> nur fuer SEHR ;; KLEINE deltaH ueberhaupt gueltig (wenige cm). +;; schon-flach: T => KEIN Bogen1 (auf_3) am Eintritt - der Aufrufer ist +;; bereits flach (0 Grad) angekommen und wird KEINEN Uebergangsbogen bauen +;; (vermeidet ein ueberfluessiges auf_3/ab_3-Paar, wenn eine bereits flache +;; Kette ohnehin ein horizontales Mittelstueck braucht - siehe +;; vfl-body-abschluss). Default nil (unveraendertes Verhalten fuer alle +;; anderen Aufrufer, die immer von der 3-Grad-Basis starten). ;; Rueckgabe: (GF_total L_VF gueltig) oder nil falls Boegen nicht messbar. -(defun berechne-horizontale-mitte (deltaL deltaH richtung / +(defun berechne-horizontale-mitte (deltaL deltaH richtung schon-flach / mass1 mass2 rad3 bogen-x1 bogen-z1 bogen-x2 bogen-z2 deltaH-signiert A-hz B-hz GF_total L_VF-hz gueltig) - (setq mass1 (get-bogen-mass bogen-auf (fix *vfk-gefaelle-winkel*))) + (setq mass1 (if schon-flach t (get-bogen-mass bogen-auf (fix *vfk-gefaelle-winkel*)))) (setq mass2 (get-bogen-mass bogen-ab (fix *vfk-gefaelle-winkel*))) (if (or (null mass1) (null mass2)) nil (progn (setq rad3 (* *vfk-gefaelle-winkel* (/ pi 180.0))) - ;; Bogen1 (immer auf_3): Eintritt bei 3 Grad (von Umlenkstation), biegt auf 0 Grad - (setq bogen-x1 (+ (* (car mass1) (cos rad3)) (* (caddr mass1) (sin rad3)))) - (setq bogen-z1 (+ (* (- (car mass1)) (sin rad3)) (* (caddr mass1) (cos rad3)))) + ;; Bogen1 (immer auf_3): Eintritt bei 3 Grad (von Umlenkstation), biegt + ;; auf 0 Grad - entfaellt bei schon-flach (kein Eintrittsbogen noetig). + (if schon-flach + (setq bogen-x1 0.0 bogen-z1 0.0) + (progn + (setq bogen-x1 (+ (* (car mass1) (cos rad3)) (* (caddr mass1) (sin rad3)))) + (setq bogen-z1 (+ (* (- (car mass1)) (sin rad3)) (* (caddr mass1) (cos rad3)))) + ) + ) ;; Bogen2 (immer ab_3): Eintritt bei 0 Grad (von der horizontalen Mitte), biegt auf 3 Grad (setq bogen-x2 (car mass2)) (setq bogen-z2 (caddr mass2)) @@ -412,7 +424,11 @@ ;; Beginnt eine reine VF-Einheit: bringt die Kette von der (3-Grad-geneigten) ;; AS-Seite ueber GF1 + Separator bis zur Umlenkstation. Wird pro VF-Einheit ;; GENAU EINMAL aufgerufen (auch wenn danach mehrere Sub-Segmente folgen). -(defun vfs-vf-entry (aktueller-punkt L_GF1 hz) +;; ohne-separator: T => der Separator entfaellt (das vorherige Kettenglied +;; IST bereits ein Separator, siehe letzter-typ in vf-linienzug-modus - eine +;; gueltige Trennstelle braucht nur einen Separator, nicht zwei hintereinander). +;; L_GF1 sollte in diesem Fall vom Aufrufer bereits auf 0 gesetzt sein. +(defun vfs-vf-entry (aktueller-punkt L_GF1 hz ohne-separator) (if (null hz) (setq hz 0.0)) (setq hz (float hz)) ;; 1. Gefaellestrecke GF1 (verbindet AS-Neigung mit Umlenkstation) @@ -425,13 +441,17 @@ ) (princ (ssg-text "vfs-vf-eingang-gf1-skip")) ) - ;; 2. Separator (am GF1-Ende / vor Umlenkstation) - (princ (ssg-text "vfs-vf-eingang-separator")) - (setq aktueller-punkt - (insert-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt - (ssg-cfg-or "vario" "gefaelle_winkel" 3) - (ssg-cfg-or "vario" "separator_block_dx" 300) - (ssg-cfg-or "vario" "separator_block_dz" 0) hz)) + ;; 2. Separator (am GF1-Ende / vor Umlenkstation) - entfaellt bei ohne-separator + (if (not ohne-separator) + (progn + (princ (ssg-text "vfs-vf-eingang-separator")) + (setq aktueller-punkt + (insert-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt + (ssg-cfg-or "vario" "gefaelle_winkel" 3) + (ssg-cfg-or "vario" "separator_block_dx" 300) + (ssg-cfg-or "vario" "separator_block_dz" 0) hz)) + ) + ) ;; 3. Umlenkstation (princ (ssg-text "vfs-vf-eingang-umlenk")) (setq aktueller-punkt @@ -604,7 +624,7 @@ (defun vfs-mitte-teil (aktueller-punkt richtung best-winkel L_GF1 L_GF2 L_VF hz) (if (null hz) (setq hz 0.0)) (setq hz (float hz)) - (setq aktueller-punkt (vfs-vf-entry aktueller-punkt L_GF1 hz)) + (setq aktueller-punkt (vfs-vf-entry aktueller-punkt L_GF1 hz nil)) (setq aktueller-punkt (vfs-vf-koerper aktueller-punkt richtung best-winkel L_VF hz)) (setq aktueller-punkt (vfs-vf-exit aktueller-punkt L_GF2 hz t)) aktueller-punkt diff --git a/dcl/variofoerderer.dcl b/dcl/variofoerderer.dcl index d525479..7b33694 100644 --- a/dcl/variofoerderer.dcl +++ b/dcl/variofoerderer.dcl @@ -1,16 +1,98 @@ // ============================================================ -// variofoerderer.dcl - Standard-VarioFoerderer Parameter-Eingabe -// Zwei Dialoge fuer den Standardfall (anlage-typ "standard") von -// c:VarioFoerderer, ersetzen die interaktive Werteingabe (Modus -// "Werteingabe") aus vf-eingabe-abfragen / vf_core.lsp: -// Dialog 1 (variofoerderer_basis): deltaL, deltaH, Foerderrichtung, -// Einfuegehoehe, Fahrtrichtung, Seite. -// Dialog 2 (variofoerderer_winkel): Winkel (dynamisch berechnete -// gueltige Varianten), Verteilung der Gefaellestrecken vorne/hinten. -// Die 3D-Linie-Eingabe (Modus "3D-Linie") und andere Anlagen-Typen -// (Etage, Linienzug) bleiben interaktiv (Kommandozeile). +// variofoerderer.dcl - VarioFoerderer Parameter-Eingabe +// Dialoge fuer c:VarioFoerderer (vf_core.lsp): +// vfc_typ: Anlagen-Typ waehlen (Standard/Etage/Linienzug) - ersetzt die +// Konsolen-Liste am Befehlsanfang. Radio-Buttons statt Dropdown, daher +// Labels FEST auf Deutsch (siehe Kommentar bei vfc_linienzug_modus). +// vfc_linienzug_modus: NUR bei Typ "Linienzug" - Modus 1/2/3 waehlen. +// variofoerderer_basis/variofoerderer_winkel: Werteingabe fuer den +// Standardfall (anlage-typ "standard"): deltaL, deltaH, Foerderrichtung, +// Einfuegehoehe, Fahrtrichtung, Seite, Winkel, GF-Verteilung. +// Die 3D-Linie-Eingabe (Modus "3D-Linie"), der Etage-Typ und die +// Linienzug-Kette selbst (nach der Modus-Wahl) bleiben interaktiv +// (Kommandozeile bzw. eigener Wizard in vf_linienzug_wizard.dcl). // ============================================================ +// Anlagen-Typ waehlen (Standard/Etage/Linienzug). Radio-Buttons statt +// Dropdown - alle Optionen sofort sichtbar. WICHTIG: Labels sind hier FEST +// einprogrammiert (Deutsch) und NICHT wie bei popup_list zur Laufzeit aus +// ssg-text befuellbar (set_tile kann das Label eines radio_button nicht +// setzen, nur den Zustand - siehe auch dcl/vfl_edit_modus.dcl). Bei +// aktivem Englisch (DXFM_LANG=en_GB) faellt vfc-dialog-typ-waehlen in +// vf_core.lsp automatisch auf die alte, vollstaendig uebersetzte +// Konsolen-Liste zurueck (siehe dortiger Kommentar). +vfc_typ : dialog { + label = "VarioFoerderer - Anlagen-Typ"; + + : boxed_radio_column { + label = "Anlagen-Typ waehlen:"; + key = "typ"; + + : radio_button { + key = "typ_standard"; + label = "Standard VarioFoerderer (AS/ES 90 Grad, horizontal versetzt)"; + value = "1"; + } + : radio_button { + key = "typ_etage"; + label = "Etage VarioFoerderer (AS/ES 30 Grad, direkt uebereinander)"; + } + : radio_button { + key = "typ_linienzug"; + label = "3D-Linienzug (gemischte GF/VF-Kette)"; + } + } + + // 3-Button-Zeile wie im Linienzug-Wizard (dcl/vf_linienzug_wizard.dcl): + // Zurueck(2)/Ok Weiter(1)/Abbrechen(0). "Zurueck" hat hier nichts, wohin es + // zurueckspringen koennte (erste Frage der gesamten Anlage) - vf_core.lsp + // zeigt in diesem Fall einfach denselben Dialog erneut. + : 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; } + } +} + +// Linienzug-Modus waehlen (nur wenn Anlagen-Typ = Linienzug). Radio-Buttons, +// gleicher Deutsch-fest-Grund wie bei vfc_typ oben. +vfc_linienzug_modus : dialog { + label = "VarioFoerderer - Linienzug Modus"; + + : boxed_radio_column { + label = "Linienzug-Modus waehlen:"; + key = "modus"; + + : radio_button { + key = "modus_1"; + label = "Manuelle Eingabe (Punkte klicken)"; + value = "1"; + } + : radio_button { + key = "modus_2"; + label = "3D-Objekte + Ziel-Hoehe (Randwert-Solver, fertig)"; + } + : radio_button { + key = "modus_3"; + label = "3D-Objekte stueckweise (Vorwaerts-Nachbau, in Arbeit)"; + } + } + + // "Zurueck" springt hier sinnvoll zur Anlagen-Typ-Frage zurueck (siehe + // vfc-dialog-linienzug-modus-waehlen/c:VarioFoerderer). + : 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; } + } +} + variofoerderer_basis : dialog { label = "VarioFoerderer (Standard) - Eingabe"; diff --git a/dcl/vf_linienzug_wizard.dcl b/dcl/vf_linienzug_wizard.dcl index 38fe15e..c7bac0b 100644 --- a/dcl/vf_linienzug_wizard.dcl +++ b/dcl/vf_linienzug_wizard.dcl @@ -31,7 +31,14 @@ vflw_zahl : dialog { } } - ok_cancel; + : 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; } + } } // Mehrfachauswahl (ersetzt eine princ-Menue-Liste + getstring/getint). @@ -55,7 +62,14 @@ vflw_wahl : dialog { } } - ok_cancel; + : 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; } + } } // ============================================================ @@ -112,14 +126,24 @@ vflw_punkt_zahl : dialog { } } - ok_cancel; + // "back" nutzt hier done_dialog 3 statt 2 - Code 2 ist bereits durch den + // "Punkt waehlen..."-Button oben belegt (siehe vflw-gruppe-punkt-hoehe-impl). + : 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; } + } } // AS-/ES-Element (Kettenanfang bzw. -ende): Ja/Nein-Toggle + Winkel + Seite // in einem Bildschirm - "kopf" traegt die konkrete Frage (AS oder ES), // "setzen" bleibt bewusst generisch beschriftet, damit derselbe Dialog fuer // beide Faelle passt. Winkel/Seite werden deaktiviert, solange der Toggle -// aus ist. +// aus ist. Radio-Buttons statt Dropdown, Labels daher fest auf Deutsch +// (siehe Kommentar bei vfc_typ in variofoerderer.dcl). vflw_as : dialog { label = "VarioFoerderer Assistent"; @@ -133,24 +157,34 @@ vflw_as : dialog { key = "setzen"; label = "Ja, setzen"; } - : popup_list { - key = "winkel"; + : boxed_radio_column { label = "Winkel:"; - width = 20; + key = "winkel"; + : radio_button { key = "winkel_90"; label = "90 Grad"; value = "1"; } + : radio_button { key = "winkel_30"; label = "30 Grad"; } } - : popup_list { - key = "seite"; + : boxed_radio_column { label = "Seite:"; - width = 20; + key = "seite"; + : radio_button { key = "seite_links"; label = "Links"; value = "1"; } + : radio_button { key = "seite_rechts"; label = "Rechts"; } } } - ok_cancel; + : 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; } + } } -// Winkel + Seite. Wiederverwendet fuer GF-Bogen (3 Winkel-Optionen) UND -// ES-Element am Kettenende (2 Winkel-Optionen) - die Optionsliste wird pro -// Aufruf zur Laufzeit befuellt, die Feld-Anzahl ist in beiden Faellen gleich. +// Winkel + Seite. Wiederverwendet fuer GF-Bogen (3 Winkel-Optionen: 30/60/90) +// UND ES-Element am Kettenende (2 Winkel-Optionen: 90/30 - dort wird +// "winkel_60" per mode_tile deaktiviert, siehe vflw-gruppe-winkel-seite-impl/ +// vfl-glied-as-es-dialog). Radio-Buttons statt Dropdown, Labels fest deutsch. vflw_winkel_seite : dialog { label = "VarioFoerderer Assistent"; @@ -160,22 +194,33 @@ vflw_winkel_seite : dialog { label = ""; width = 60; } - : popup_list { - key = "winkel"; + : boxed_radio_column { label = "Winkel:"; - width = 20; + key = "winkel"; + : radio_button { key = "winkel_30"; label = "30 Grad"; } + : radio_button { key = "winkel_60"; label = "60 Grad"; } + : radio_button { key = "winkel_90"; label = "90 Grad"; value = "1"; } } - : popup_list { - key = "seite"; + : boxed_radio_column { label = "Seite:"; - width = 20; + key = "seite"; + : radio_button { key = "seite_links"; label = "Links"; value = "1"; } + : radio_button { key = "seite_rechts"; label = "Rechts"; } } } - ok_cancel; + : 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 { label = "VarioFoerderer Assistent"; @@ -185,30 +230,41 @@ vflw_variokurve : dialog { label = ""; width = 60; } - : popup_list { - key = "winkel"; + : boxed_radio_column { label = "Winkel:"; - width = 20; + key = "winkel"; + : radio_button { key = "winkel_30"; label = "30 Grad"; } + : radio_button { key = "winkel_60"; label = "60 Grad"; } + : radio_button { key = "winkel_90"; label = "90 Grad"; value = "1"; } } - : popup_list { - key = "seite"; + : boxed_radio_column { label = "Seite:"; - width = 20; + key = "seite"; + : radio_button { key = "seite_links"; label = "Links"; value = "1"; } + : radio_button { key = "seite_rechts"; label = "Rechts"; } } - : popup_list { - key = "variante"; + : boxed_radio_column { label = "Variante:"; - width = 20; + key = "variante"; + : radio_button { key = "variante_aussen"; label = "Aussen"; value = "1"; } + : radio_button { key = "variante_innen"; label = "Innen"; } } } - ok_cancel; + : 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; } + } } // Gefaelle festlegen (Linie GF): Modus (Hoehe/Winkel) + EIN Wertfeld, dessen // Beschriftung sich je nach Modus umschaltet (Action-Tile auf "modus", siehe // vflw-gruppe-gefaelle-impl in vf_linienzug.lsp). Kein Punkt-Feld - siehe -// Kopfkommentar oben. +// Kopfkommentar oben. Radio-Buttons statt Dropdown, Labels fest deutsch. vflw_gefaelle : dialog { label = "VarioFoerderer Assistent"; @@ -218,10 +274,11 @@ vflw_gefaelle : dialog { label = ""; width = 60; } - : popup_list { - key = "modus"; + : boxed_radio_column { label = "Eingabe als:"; - width = 40; + key = "modus"; + : radio_button { key = "modus_winkel"; label = "Neigungswinkel eingeben"; value = "1"; } + : radio_button { key = "modus_hoehe"; label = "Gegebene Hoehe (Zielhoehe)"; } } : text { key = "wlabel"; @@ -232,15 +289,64 @@ vflw_gefaelle : dialog { label = ""; edit_width = 10; } + // Nur befuellt/sichtbar relevant, wenn vflw-gruppe-gefaelle-impl mit + // nur-winkel=T aufgerufen wird (Zweig "Zielhoehe zuerst festlegen" bei + // "Neue Linie: GF") - zeigt dann den Hinweis, dass deltaL daraus + // berechnet wird, statt der sonst hier stehenden Hoehe-Option. + : text { + key = "hinweis"; + label = ""; + } } - ok_cancel; + : 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; } + } } -// Horizontales Stueck: Separator-vor + Separator-nach + "Foerderer-Ende?" -// (3 Optionen) in einem Bildschirm. Kein Punkt-Feld - siehe Kopfkommentar -// oben. -vflw_horizontal : dialog { +// "Wie soll die Laenge dieser Gefaellestrecke bestimmt werden?" (Neue Linie: +// GF) - Endpunkt-Pick (heutiges Verhalten) ODER Zielhoehe zuerst festlegen +// (Laenge wird dann aus Zielhoehe+Winkel berechnet, siehe +// vflw-gruppe-gf-laenge-modus-impl). Nur gezeigt, wenn bereits ein Frame +// existiert (Kettenanfang braucht weiterhin zwingend den Pick fuer die +// Richtung). Radio-Buttons statt Dropdown, Labels fest deutsch. +vflw_gf_laenge_modus : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + key = "modus"; + label = ""; + : 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)"; } + } + } + + : 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; } + } +} + +// Separator VOR/NACH bei "Neue Linie: GF": beide Ja/Nein-Fragen in einem +// Bildschirm (Toggles, da echte Ja/Nein-Fragen - kein Radio-Cluster noetig). +// Siehe vflw-gruppe-sep-gf-impl in vf_linienzug.lsp. +vflw_sep_gf : dialog { label = "VarioFoerderer Assistent"; : column { @@ -251,20 +357,502 @@ vflw_horizontal : dialog { } : toggle { key = "sepvor"; - label = "Separator VOR dem Stueck"; + label = "Separator VOR dieser Gefaellestrecke"; } : toggle { key = "sepnach"; - label = "Separator NACH dem Stueck"; - } - : popup_list { - key = "istende"; - label = "Foerderer-Ende:"; - width = 45; + label = "Separator NACH dieser Gefaellestrecke"; } } - ok_cancel; + : 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; } + } +} + +// Horizontales Stueck: nur noch "Foerderer-Ende?" (3 Optionen) - kein +// Separator mehr (siehe vfl-baue-horizontal-koerper). Kein Punkt-Feld - +// siehe Kopfkommentar oben. Radio-Buttons statt Dropdown, Labels daher fest +// auf Deutsch (siehe Kommentar bei vfc_typ in variofoerderer.dcl). +vflw_horizontal : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + label = "Foerderer-Ende:"; + key = "istende"; + + : radio_button { + key = "istende_0"; + label = "Ja (nur Motorstation setzen)"; + value = "1"; + } + : radio_button { + key = "istende_1"; + label = "Nein (weiterbauen)"; + } + : radio_button { + key = "istende_2"; + label = "Ja (Motorstation setzen, Kettenende definieren)"; + } + } + } + + : 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; } + } +} + +// "Naechstes Element waehlen" - Hauptmenue des Linienzug-Aufbaus (Modus 1). +// IMMER alle 6 Optionen im Dialog vorhanden (stabile Keys) - "Vario-Kurve" +// wird per mode_tile deaktiviert, wenn kein echter Kettenanfang vorliegt +// (siehe vflw-gruppe-naechstes-element-impl, das dort auch die Positions- +// Nummerierung passend umrechnet). Radio-Buttons statt Dropdown, Labels fest +// deutsch, OHNE Nummern-Prefix (anders als die Konsolen-Variante - hier +// braucht es keine Zifferneingabe). +vflw_naechstes_element : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + key = "wahl"; + label = ""; + : radio_button { key = "wahl_gfbogen"; label = "GF-Bogen (horizontale Kurve)"; } + : radio_button { key = "wahl_variokurve"; label = "Vario-Kurve (horizontale Kurve, 30/60/90 Grad)"; } + : radio_button { key = "wahl_liniegf"; label = "Neue Linie: GF (Gefaellestrecke)"; value = "1"; } + : radio_button { key = "wahl_linievf"; label = "Neue Linie: Ab/Auf VF (VarioFoerderer-Einheit)"; } + : radio_button { key = "wahl_horizontalvf"; label = "Neue VF mit horizontalem Anfang (Horizontal-Stueck)"; } + : radio_button { key = "wahl_linieende"; label = "Neue Linie BIS Kettenende (danach Separator + ES-Element)"; } + } + } + + // PROTOTYP "Zurueck"-Button (siehe Plan curious-prancing-parasol.md): ersetzt + // ok_cancel durch eine eigene 3-Button-Zeile. done_dialog-Codes: 0=Abbrechen + // (unveraendert, is_cancel -> ESC/Leertaste wirkt weiterhin), 1=Weiter + // (unveraendert, is_default), NEU 2=Zurueck (verwirft das zuletzt gebaute + // Kettenglied und fragt es neu ab, siehe vflw-gruppe-naechstes-element-impl/ + // vfl-modus-abbruch-sichern). + : 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; } + } +} + +// "Ist das das Kettenende?" (Linie-GF-Segment-Schleife) - 3 feste Optionen. +// Radio-Buttons statt Dropdown, Labels fest deutsch. +vflw_kettenende : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + key = "wahl"; + label = ""; + : radio_button { key = "wahl_ja_es"; label = "Ja (ES-Element setzen)"; } + : radio_button { key = "wahl_ja_ohne_es"; label = "Ja (ohne ES-Element setzen)"; } + : radio_button { key = "wahl_nein"; label = "Nein (weiterbauen)"; 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; } + } +} + +// "Ist das Kettenende?" (2-Optionen-Variante - Ja/Nein statt der 3-Optionen- +// Variante vflw_kettenende oben). Radio-Buttons statt Dropdown, Labels fest +// deutsch. +vflw_ist_kettenende_2opt : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + key = "wahl"; + label = ""; + : radio_button { key = "wahl_ja"; label = "Ja (Separator + ES-Element setzen)"; } + : radio_button { key = "wahl_nein"; label = "Nein (weiterbauen)"; 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; } + } +} + +// GF-Verteilung (halbe Staustrecke am Ausgang GF2 oder alles am Einlauf +// GF1) - wiederverwendet fuer Modus 1 (vfl-vf-einheit-abschluss) UND Modus 3 +// (Segment-Loop, br-gf-mode). Radio-Buttons statt Dropdown, Labels fest +// deutsch. +vflw_gf_verteilung : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + key = "wahl"; + label = ""; + : radio_button { key = "wahl_haelfte"; label = "Haelfte am Einlauf (GF1) + Haelfte am Ausgang (GF2)"; } + : radio_button { key = "wahl_einlauf"; label = "Alles am Einlauf (GF1), kein GF2"; 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; } + } +} + +// "Naechstes im VF" (innerhalb einer laufenden VF-Einheit weiterbauen): +// Horizontaler Foerderer / Vario-Kurve / Auf-Ab-Foerderer. Radio-Buttons +// statt Dropdown, Labels fest deutsch. +vflw_naechstes_im_vf : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + key = "wahl"; + label = ""; + : radio_button { key = "wahl_horizontal"; label = "Horizontaler Foerderer (Linie ohne Hoehendifferenz)"; } + : radio_button { key = "wahl_variokurve"; label = "Vario-Kurve (30/60/90 Grad)"; } + : radio_button { key = "wahl_aufab"; label = "Auf/Ab-Foerderer (Linie mit Hoehendifferenz)"; 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; } + } +} + +// Punkt-7-Winkel/Hoehen-Tabelle (vfl-waehle-winkel-hoehen-tabelle): 12 feste +// Radio-Slots (einer je Standard-Winkel 3-51 Grad), nicht baubare per +// mode_tile deaktiviert. WICHTIG: die radio_button-Tiles muessen DIREKTE +// Kinder eines radio_column/radio_row/boxed_radio_column-Clusters sein - eine +// Verschachtelung ueber : row {} INNERHALB des Clusters (fruehere Version) +// hebt die gegenseitige Ausschliesslichkeit auf (per Test bestaetigt: mehrere +// Radios gleichzeitig waehlbar, keins abwaehlbar)! Die Endhoehe steht daher +// NICHT im selben row-Tile, sondern in einer PARALLELEN Text-Spalte rechts +// daneben (eigene column AUSSERHALB des Radio-Clusters, per aeusserem : row +// nebeneinandergestellt, gleiche Zeilenreihenfolge) - dynamisch befuellt via +// vflw-gruppe-winkel-hoehen-impl (zeigt auch bei nicht baubaren Winkeln den +// Grund, siehe dortige Kommentare). +vflw_winkel_hoehen : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : text { label = "Winkel waehlen:"; } + : row { + : radio_column { + key = "wahl"; + : radio_button { key = "w_3"; label = "3 Grad"; } + : radio_button { key = "w_6"; label = "6 Grad"; } + : radio_button { key = "w_9"; label = "9 Grad"; } + : radio_button { key = "w_12"; label = "12 Grad"; } + : radio_button { key = "w_15"; label = "15 Grad"; } + : radio_button { key = "w_18"; label = "18 Grad"; } + : radio_button { key = "w_21"; label = "21 Grad"; } + : radio_button { key = "w_27"; label = "27 Grad"; } + : radio_button { key = "w_33"; label = "33 Grad"; } + : radio_button { key = "w_39"; label = "39 Grad"; } + : radio_button { key = "w_45"; label = "45 Grad"; } + : radio_button { key = "w_51"; label = "51 Grad"; } + } + : column { + : text { key = "h_3"; label = ""; width = 48; } + : text { key = "h_6"; label = ""; width = 48; } + : text { key = "h_9"; label = ""; width = 48; } + : text { key = "h_12"; label = ""; width = 48; } + : text { key = "h_15"; label = ""; width = 48; } + : text { key = "h_18"; label = ""; width = 48; } + : text { key = "h_21"; label = ""; width = 48; } + : text { key = "h_27"; label = ""; width = 48; } + : text { key = "h_33"; label = ""; width = 48; } + : text { key = "h_39"; label = ""; width = 48; } + : text { key = "h_45"; label = ""; width = 48; } + : text { key = "h_51"; label = ""; width = 48; } + } + } + } + + : 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; } + } +} + +// Winkel-Wahl aus berechne-alle-winkel (Zielhoehe-basierter Solve, mehrere +// gueltige Winkel): wie vflw_winkel_hoehen (radio_column direkt, Text-Spalte +// parallel daneben), aber die Text-Spalte zeigt L_GF+L_VF statt Endhoehe +// (dynamisch befuellt, siehe vflw-gruppe-winkel-wahl-impl). +vflw_winkel_wahl : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : text { label = "Winkel waehlen:"; } + : row { + : radio_column { + key = "wahl"; + : radio_button { key = "w_3"; label = "3 Grad"; } + : radio_button { key = "w_6"; label = "6 Grad"; } + : radio_button { key = "w_9"; label = "9 Grad"; } + : radio_button { key = "w_12"; label = "12 Grad"; } + : radio_button { key = "w_15"; label = "15 Grad"; } + : radio_button { key = "w_18"; label = "18 Grad"; } + : radio_button { key = "w_21"; label = "21 Grad"; } + : radio_button { key = "w_27"; label = "27 Grad"; } + : radio_button { key = "w_33"; label = "33 Grad"; } + : radio_button { key = "w_39"; label = "39 Grad"; } + : radio_button { key = "w_45"; label = "45 Grad"; } + : radio_button { key = "w_51"; label = "51 Grad"; } + } + : column { + : text { key = "h_3"; label = ""; width = 48; } + : text { key = "h_6"; label = ""; width = 48; } + : text { key = "h_9"; label = ""; width = 48; } + : text { key = "h_12"; label = ""; width = 48; } + : text { key = "h_15"; label = ""; width = 48; } + : text { key = "h_18"; label = ""; width = 48; } + : text { key = "h_21"; label = ""; width = 48; } + : text { key = "h_27"; label = ""; width = 48; } + : text { key = "h_33"; label = ""; width = 48; } + : text { key = "h_39"; label = ""; width = 48; } + : text { key = "h_45"; label = ""; width = 48; } + : text { key = "h_51"; label = ""; width = 48; } + } + } + } + + : 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; } + } +} + +// Generische Ja/Nein-Rueckfrage (2 Radio-Buttons, dynamischer Kopftext) - +// wiederverwendet z.B. fuer "trotzdem mit Mindestlaenge bauen?" (Zu-kurz- +// Nachfrage in vfl-baue-horizontal-koerper). Radio-Buttons statt Dropdown, +// Labels fest deutsch (nur "kopf" wird je Aufruf per set_tile befuellt). +// Drei Groessenvarianten (1/3/6 Kopf-Zeilen) statt EINER Variante mit immer 6 +// Zeilen: DCL kann Tiles nicht dynamisch ausblenden/schrumpfen - ein leeres +// text-Tile belegt trotzdem seine volle Zeilenhoehe (grosse Luecke bei kurzen +// Hinweisen wie "Zusaetzlichen Separator einfuegen?"). vflw-gruppe-ja-nein-impl +// waehlt anhand der per vflw-umbruch-zeilen ermittelten Zeilenzahl die +// passende Variante (1/3/6). Alle drei teilen dieselben Tile-Keys "kopf1".."kopfN" +// plus "wahl"/"wahl_ja"/"wahl_nein"/"back"/"accept"/"cancel" - der Aufrufer +// muss dadurch NICHT zwischen ihnen unterscheiden, ausser bei new_dialog/ +// set_tile fuer die (in der kleineren Variante gar nicht vorhandenen) hoeheren +// kopfN-Tiles. +vflw_ja_nein_1 : dialog { + label = "VarioFoerderer Assistent"; + : column { + : text { key = "kopf1"; label = ""; width = 70; } + : boxed_radio_column { + key = "wahl"; + label = ""; + : radio_button { key = "wahl_ja"; label = "Ja"; value = "1"; } + : radio_button { key = "wahl_nein"; label = "Nein"; } + } + } + : 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; } + } +} + +vflw_ja_nein_3 : dialog { + label = "VarioFoerderer Assistent"; + : column { + : text { key = "kopf1"; label = ""; width = 70; } + : text { key = "kopf2"; label = ""; width = 70; } + : text { key = "kopf3"; label = ""; width = 70; } + : boxed_radio_column { + key = "wahl"; + label = ""; + : radio_button { key = "wahl_ja"; label = "Ja"; value = "1"; } + : radio_button { key = "wahl_nein"; label = "Nein"; } + } + } + : 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; } + } +} + +vflw_ja_nein_6 : dialog { + label = "VarioFoerderer Assistent"; + : column { + : text { key = "kopf1"; label = ""; width = 70; } + : text { key = "kopf2"; label = ""; width = 70; } + : text { key = "kopf3"; label = ""; width = 70; } + : text { key = "kopf4"; label = ""; width = 70; } + : text { key = "kopf5"; label = ""; width = 70; } + : text { key = "kopf6"; label = ""; width = 70; } + : boxed_radio_column { + key = "wahl"; + label = ""; + : radio_button { key = "wahl_ja"; label = "Ja"; value = "1"; } + : radio_button { key = "wahl_nein"; label = "Nein"; } + } + } + : 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; } + } +} + +// Generische Auf/Ab-Richtungsfrage (2 Radio-Buttons, dynamischer Kopftext) - +// wiederverwendet fuer Punkt 7 (Kletter-Teilstrecke ohne Zielhoehe, sowohl +// "Naechstes im VF" als auch "Neue Linie: Ab/Auf VF" mit reduziertem +// Eingang). Radio-Buttons statt Dropdown, Labels fest deutsch. +vflw_richtung : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + key = "richtung"; + label = ""; + : radio_button { key = "richtung_auf"; label = "Auf"; value = "1"; } + : radio_button { key = "richtung_ab"; label = "Ab"; } + } + } + + : 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; } + } +} + +// Startpunkt-Typ (kein eindeutiger GF-/VF-Baustein per KS_AUS-Scan erkannt, +// siehe vfl-eingang-modus-bestimmen): EINE flache 3-Optionen-Frage statt +// verschachtelter Zwei-Schritt-Abfrage - ist der Vorgaenger unklar, sind alle +// drei Ergebnisse gleichwertig direkt waehlbar. Radio-Buttons statt Dropdown, +// Labels fest deutsch (GF-Stumpf-Laenge als Default-Wert 400mm statisch im +// Label, siehe *vfl-gf-min-laenge*). +vflw_startpunkt_typ : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + label = "Eingang:"; + key = "eingang"; + : radio_button { key = "eingang_direkt"; label = "Direkt Umlenkstation (kein GF-Stueck)"; value = "1"; } + : radio_button { key = "eingang_stumpf"; label = "GF-Stueck (min. 400mm) + Umlenkstation"; } + : radio_button { key = "eingang_ohne"; label = "Ohne Umlenkstation (VF-Fortsetzung)"; } + } + } + + : 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; } + } } // ============================================================ @@ -278,6 +866,7 @@ vflw_horizontal : dialog { // Modus 2, Segment "Gerade": Typ (GF/VF) + [nur bei GF aktiv] GF-Neigung. // Das Neigungsfeld wird per action_tile auf "typ" aktiviert/deaktiviert. +// Radio-Buttons statt Dropdown, Labels fest deutsch. vflw_seg_linie_m2 : dialog { label = "VarioFoerderer Assistent"; @@ -287,10 +876,11 @@ vflw_seg_linie_m2 : dialog { label = ""; width = 60; } - : popup_list { - key = "typ"; + : boxed_radio_column { label = "Typ:"; - width = 40; + key = "typ"; + : radio_button { key = "typ_gf"; label = "GF (Neigungswinkel)"; value = "1"; } + : radio_button { key = "typ_vf"; label = "VF (Bruecke)"; } } : text { key = "wlabel"; @@ -301,6 +891,11 @@ vflw_seg_linie_m2 : dialog { label = ""; edit_width = 10; } + : boxed_column { + label = "Separator (nur bei GF):"; + : toggle { key = "sep_vor"; label = "Separator VOR diesem GF-Stueck"; } + : toggle { key = "sep_nach"; label = "Separator NACH diesem GF-Stueck"; } + } } ok_cancel; @@ -309,7 +904,8 @@ vflw_seg_linie_m2 : dialog { // Modus 3, Segment "Gerade": Typ (GF / VF-Ab / VF-Auf / VF-Horizontal) + EIN // Wertfeld, dessen Beschriftung mit dem Typ umschaltet (GF -> Neigung, // VF-Ab/Auf -> Vario-Winkel, VF-Horizontal -> Feld deaktiviert). Umschaltung -// per action_tile auf "typ" (siehe vflw-seg-linie-m3-impl). +// per action_tile auf "typ" (siehe vflw-seg-linie-m3-impl). Radio-Buttons +// statt Dropdown, Labels fest deutsch. vflw_seg_linie_m3 : dialog { label = "VarioFoerderer Assistent"; @@ -319,10 +915,13 @@ vflw_seg_linie_m3 : dialog { label = ""; width = 60; } - : popup_list { - key = "typ"; + : boxed_radio_column { label = "Typ:"; - width = 45; + key = "typ"; + : radio_button { key = "typ_gf"; label = "GF (Neigungswinkel)"; value = "1"; } + : radio_button { key = "typ_vfab"; label = "VF-Ab"; } + : radio_button { key = "typ_vfauf"; label = "VF-Auf"; } + : radio_button { key = "typ_vfhor"; label = "VF-Horizontal"; } } : text { key = "wlabel"; @@ -340,7 +939,9 @@ vflw_seg_linie_m3 : dialog { // Segment "Eck/Bogen" (Modus 2 + Modus 3 identisch): Typ (GF-Bogen / // Vario-Kurve) + [nur bei Vario-Kurve aktiv] Variante (aussen/innen). Die -// Variante-Liste wird per action_tile auf "typ" aktiviert/deaktiviert. +// Variante-Gruppe wird per action_tile auf "typ" aktiviert/deaktiviert, die +// Vario-Kurve-Option selbst ggf. ueber "vario-erlaubt" (mode_tile), siehe +// vflw-seg-bogen-impl. Radio-Buttons statt Dropdown, Labels fest deutsch. vflw_seg_bogen : dialog { label = "VarioFoerderer Assistent"; @@ -350,15 +951,65 @@ vflw_seg_bogen : dialog { label = ""; width = 60; } - : popup_list { - key = "typ"; + : boxed_radio_column { label = "Typ:"; - width = 40; + key = "typ"; + : radio_button { key = "typ_gfbogen"; label = "GF-Bogen"; value = "1"; } + : radio_button { key = "typ_vario"; label = "Vario-Kurve"; } } - : popup_list { - key = "variante"; + : boxed_radio_column { label = "Variante:"; - width = 30; + key = "variante"; + : radio_button { key = "variante_aussen"; label = "Aussen"; value = "1"; } + : radio_button { key = "variante_innen"; label = "Innen"; } + } + } + + ok_cancel; +} + +// Modus 2: Lauf-Abschluss, NUR wenn der VF-Lauf das Ende des gewaehlten Pfads +// ist (kein Back-Lauf danach) - siehe vflw-m2-lauf-abschluss-impl. Radio- +// Buttons, Labels fest deutsch. +vflw_m2_lauf_abschluss : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + label = "Lauf beenden mit:"; + key = "abschluss"; + : radio_button { key = "abschluss_offen"; label = "Ohne Motorstation (offenes Ende, spaeter fortsetzen)"; } + : radio_button { key = "abschluss_motor"; label = "Motorstation setzen"; value = "1"; } + : radio_button { key = "abschluss_motor_es"; label = "Motorstation + ES-Element setzen (Kettenende)"; } + } + } + + ok_cancel; +} + +// Modus 2: Lauf-Anfang, NUR wenn der VF-Lauf der Anfang des gewaehlten Pfads +// ist (kein Front-Lauf davor) - siehe vflw-m2-lauf-anfang-impl. Radio-Buttons, +// Labels fest deutsch. +vflw_m2_lauf_anfang : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : boxed_radio_column { + label = "Lauf beginnen mit:"; + key = "anfang"; + : radio_button { key = "anfang_offen"; label = "Ohne Umlenkstation (offener Anfang, spaeter fortsetzen)"; } + : radio_button { key = "anfang_umlenk"; label = "Umlenkstation direkt (kein GF1/Separator)"; } + : radio_button { key = "anfang_umlenk_gf1"; label = "Umlenkstation mit GF1 + Separator"; value = "1"; } } } diff --git a/lang/de_DE.json b/lang/de_DE.json index 8da5ac2..3bffcc2 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -19,12 +19,20 @@ "vfl-menu-horizontal-vf-3": "\n 3 - Neue VF mit horizontalem Anfang (Horizontal-Stueck)", "vfl-menu-linie-ende-4": "\n 4 - Neue Linie BIS Kettenende (danach Separator + ES-Element)", "vfl-prompt-wahl-1-4-def1": "\nIhre Wahl (1-4) [1]: ", + "vfl-menu-gf-bogen-ka-1": "\n 1 - GF-Bogen (horizontale Kurve)", + "vfl-menu-variokurve-ka-2": "\n 2 - Vario-Kurve (horizontale Kurve, 30/60/90 Grad)", + "vfl-menu-linie-gf-ka-3": "\n 3 - Neue Linie: GF (Gefaellestrecke)", + "vfl-menu-linie-vf-ka-4": "\n 4 - Neue Linie: Ab/Auf VF (VarioFoerderer-Einheit)", + "vfl-menu-horizontal-vf-ka-5": "\n 5 - Neue VF mit horizontalem Anfang (Horizontal-Stueck)", + "vfl-menu-linie-ende-ka-6": "\n 6 - Neue Linie BIS Kettenende (danach Separator + ES-Element)", + "vfl-prompt-wahl-1-6-def3": "\nIhre Wahl (1-6) [3]: ", "vfl-fehler-horizontal-vf-kurz": "\nFEHLER: Horizontaler VF braucht >= 1000 mm (Umlenk + Motor) - laenger zeichnen.", "vfl-fehler-linie-zu-kurz": "\nFEHLER: Linie zu kurz (oder entgegen der Fahrtrichtung) - bitte erneut waehlen.", "vfl-fehler-vf-kurz": "\nFEHLER: VarioFoerderer braucht >= 1000 mm (Umlenk + Motor) - laenger zeichnen oder \"GF\" waehlen.", "vfl-gefaelle-festlegen-header": "\nGefaelle festlegen:", "vfl-gefaelle-opt-hoehe": "\n 1 - Gegebene Hoehe (Zielhoehe)", "vfl-gefaelle-opt-winkel": "\n 2 - Neigungswinkel eingeben", + "vfl-gf-hinweis-laenge-berechnet": "(deltaL wird berechnet und eingefuegt)", "vfl-prompt-neigungswinkel": "\nNeigungswinkel (Grad, 0 < Winkel <= %1) [%1]: ", "vfl-alert-winkel-ungueltig": "Neigungswinkel ungueltig: %1 Grad. Erlaubt: 0 < Winkel <= %2 Grad.", "vfl-prompt-hoehe-linienendpunkt": "\nHoehe (Z) des Linienendpunkts [%1]: ", @@ -42,6 +50,7 @@ "vfl-alert-gf-steigend-falsche-richtung": "Steigende Gefaellestrecke: die gewaehlte Zielhoehe liegt unter der aktuellen Hoehe - bitte hoehere Zielhoehe waehlen oder den normalen (fallenden) Modus benutzen.", "vfl-sep-vor-gf-frage": "\n\nSeparator VOR dieser Gefaellestrecke einfuegen?", "vfl-sep-nach-gf-frage": "\n\nSeparator NACH dieser Gefaellestrecke einfuegen?", + "vfl-sep-gf-header": "Separator an dieser Gefaellestrecke", "vfl-ist-kettenende-header": "\nIst das das Kettenende?", "vfl-kettenende-opt-ja-es": "\n 1 - Ja (ES-Element setzen)", "vfl-kettenende-opt-ja-ohne-es": "\n 2 - Ja (ohne ES-Element setzen)", @@ -106,6 +115,10 @@ "vfl-opt2-60grad": "\n 60 Grad", "vfl-opt3-30grad": "\n 30 Grad", "vfl-prompt-wahl-1-3-def1": "\nIhre Wahl (1/2/3) [1]: ", + "vfl-frage-startpunkt-typ": "\n\nAm Startpunkt konnte kein eindeutiger GF-/VF-Baustein erkannt werden (GF-Stueck und VF-Horizontalstueck sehen baulich identisch aus). Wie soll der Eingang gebaut werden?", + "vfl-opt-eingang-direkt": "\n 1 - Direkt Umlenkstation bauen (kein GF-Stueck)", + "vfl-opt-eingang-mit-stumpf": "\n 2 - GF (%1 mm) + Umlenkstation", + "vfl-opt-eingang-ohne-umlenk": "\n 3 - Ohne Umlenkstation (VF-Fortsetzung)", "vfl-variokurve-seite-header": "\nVario-Kurve - Seite waehlen:", "vfl-variokurve-variante-header": "\nVario-Kurve - Variante waehlen:", "vfl-variante-aussen": "\n 1 - Aussen", @@ -164,9 +177,26 @@ "vfl-m3-junction-exakt": "\n Junction (exakt): %1 mm", "vfl-m3-kletter-info": "\n Kletterhoehe %1 mm | Kletterer %2 | Kurven %3 | kurze VF %4", "vfl-m3-kein-winkel": "\n KEIN passender Vario-Winkel -> infeasibel (Front bereits gebaut).", + "vfl-m3-kletter-zu-kurz-flach": "\n Kein Kletter-Winkel passt (Segment zu kurz) -> Lauf wird komplett flach gebaut, Hoehe wandert in GF1.", + "vfl-m3-kletter-flach-gf": "\n Flache Zone: GF-Kompensation (GF1) = %1 mm", + "vfl-m3-alert-vf-zu-lang": "VF-Lauf ist %1 m lang (Grenze %2 m) - bitte neu planen (z.B. Zwischen-Motorstation einfuegen).", + "vfl-m3-warnung-fueller-eingang-zu-kurz": "\n WARNUNG: Fueller direkt nach der Umlenkstation zu kurz (%1 mm < Minimum %2 mm) - nur Minimalabstand gebaut, Zielposition nicht exakt erreicht.", + "vfl-m3-warnung-fueller-ausgang-zu-kurz": "\n WARNUNG: Fueller direkt vor der Motorstation zu kurz (%1 mm < Minimum %2 mm) - nur Minimalabstand gebaut, Zielposition nicht exakt erreicht.", + "vfl-m3-lauf-anfang-header": "\n\nDer VF-Lauf ist der Anfang des gewaehlten Pfads. Lauf beginnen mit:", + "vfl-m3-lauf-anfang-opt-offen": "\n 1 - Ohne Umlenkstation (offener Anfang, spaeter fortsetzen/verschmelzen)", + "vfl-m3-lauf-anfang-opt-umlenk": "\n 2 - Umlenkstation direkt (kein GF1/Separator)", + "vfl-m3-lauf-anfang-opt-umlenk-gf1": "\n 3 - Umlenkstation mit GF1 + Separator", + "vfl-m3-lauf-anfang-offen-hinweis": "\n Anfang bleibt bewusst offen - keine Umlenkstation/GF1/Separator gebaut, spaeter fortsetzen oder per Vario_Kette_Merge verbinden.", + "vfl-m3-lauf-abschluss-header": "\n\nDer VF-Lauf ist das Ende des gewaehlten Pfads. Lauf beenden mit:", + "vfl-m3-lauf-abschluss-opt-offen": "\n 1 - Ohne Motorstation (offenes Ende, spaeter fortsetzen/verschmelzen)", + "vfl-m3-lauf-abschluss-opt-motor": "\n 2 - Motorstation setzen (kein ES-Element)", + "vfl-m3-lauf-abschluss-opt-motor-es": "\n 3 - Motorstation + ES-Element setzen (Kettenende)", + "vfl-m3-lauf-abschluss-offen-hinweis": "\n Lauf bleibt bewusst offen - keine Motorstation/Separator/ES gebaut, spaeter fortsetzen oder per Vario_Kette_Merge verbinden.", "vfl-m3-gf-verteilung": "\n\n GF-Verteilung: 1 - alles am Einlauf (GF1) 2 - 1/2 GF1 + 1/2 GF2", + "vfl-m3-gf-verteilung-alles-auslauf": "\n Kein GF1-Platz am Einlauf gewaehlt - komplette Kompensation wandert nach GF2 (Auslauf).", "vfl-m3-vert-halb": "1/2 GF1 + 1/2 GF2", "vfl-m3-vert-ganz": "alles GF1", + "vfl-m3-vert-auslauf": "alles GF2 (Auslauf)", "vfl-m3-vario-ergebnis": "\n -> Vario %1 (%2), L_VF %3 mm, GF gesamt %4 mm, Verteilung %5 (GF2-Rest = Mess-Feinkorrektur)", "vfl-m3-warnung-gf2-negativ": "\n WARNUNG: Koerper klettert zu wenig - GF2<0 (fehlen %1 mm). Winkel zu flach; dZ nicht exakt.", "vfl-m3-gf2-ausgleich": "\n GF2 (gemessener Ausgleich): L=%1 mm", @@ -303,6 +333,26 @@ "vfe-tabelle-zeile-fehler": "\n %1 --- --- FEHLER", "vfl-20m-hinweis": "\n >>> HINWEIS: Foerderer laenger als 20 m (%1 m) - Motorstation empfohlen!", "vfl-block-erstellt": "\n>>> Block '%1' (%2) erstellt und eingefuegt.", + "vfl-fehler-rest-nicht-baubar-mit-vorschlag": "\n FEHLER: Bei Zielhoehe %1 mm (Strecke dL=%2 mm, Hoehendifferenz dH=%3 mm, %4) nicht baubar (zu steil/zu kurz fuer Schwanz Motor+GF2+Separator+ES). Baubare Zielhoehe waere ungefaehr:%5", + "vfl-fehler-rest-nicht-baubar-ohne-vorschlag": "\n FEHLER: Bei Zielhoehe %1 mm (Strecke dL=%2 mm, Hoehendifferenz dH=%3 mm, %4) nicht baubar - bei dieser Streckenlaenge wurde auch keine alternative Zielhoehe gefunden. Bitte laenger zeichnen oder flacher planen.", + "vfl-vorschlag-ab-auf": " Ab %1 mm oder Auf %2 mm", + "vfl-vorschlag-nur-ab": " Ab %1 mm (Auf ist bei dieser Streckenlaenge nicht baubar)", + "vfl-vorschlag-nur-auf": " Auf %1 mm (Ab ist bei dieser Streckenlaenge nicht baubar)", + "vfl-alert-kettenende-p1": "1. Ziel △L=%1 mm, △H=%2 mm (%3): Auf/Ab-Foerderer (Winkel-Tabelle) nicht baubar.", + "vfl-alert-kettenende-p2-beide": "\n\n2. Horizontal+GF nicht baubar - noetig waeren mindestens △L=%1 mm ODER mindestens △H=%2 mm.", + "vfl-alert-kettenende-p2-nur-minh": "\n\n2. Horizontal+GF nicht baubar - noetig waere mindestens △H=%1 mm Hoehenaenderung.", + "vfl-alert-kettenende-p2-nur-minl": "\n\n2. Horizontal+GF nicht baubar - noetig waere mindestens △L=%1 mm Streckenlaenge.", + "vfl-stufe1-start": "\n\n[Diagnose Stufe 1 - VF-Winkel-Suche]", + "vfl-stufe2-diagnose": "\n\n[Diagnose Stufe 2 - horizontal+GF] deltaL=%1 mm deltaH=%2 mm -> GF_total=%3 mm L_VF=%4 mm (%5)", + "vfl-stufe2-diagnose-details": "\n [Details] schon-flach=%1 | aus-dx=%2 mm (Einlauf, sollte 0 sein) | ein-dx=%3 mm ein-dz=%4 mm (ES-Element) | bogen-x1=%5 mm bogen-z1=%6 mm (Eintrittsbogen 3->0 Grad, nur falls nicht schon-flach) | bogen-x2=%7 mm bogen-z2=%8 mm (Austrittsbogen 0->3 Grad, immer) | FESTE_HORIZONTAL=%9 mm (Separator+Motorstation)", + "vfl-stufe2-fest-kettenende": "\n Motorstation+Separator+ES benoetigen: Laenge=%1 mm, Hoehenabsenkung=%2 mm (fest, unabhaengig vom Winkel)", + "vfl-stufe2-fest-eingang": "\n Umlenkstation+Separator+Motorstation+ES benoetigen: Laenge=%1 mm, Hoehenabsenkung=%2 mm (fest, unabhaengig vom Winkel)", + "vfl-stufe2-minl": "\n [Mindestwert 1] Ohne geraden VF-Anteil (GF nach Zielhoehe dimensioniert): mindestens %1 mm Streckenlaenge noetig (vorhanden: %2 mm)", + "vfl-stufe2-minl-unmoeglich": "\n [Mindestwert 1] Nicht per Streckenlaenge loesbar: schon ohne GF-Bogen aendert sich die Hoehe um %1 mm - die Zielhoehe verlangt aber nur %2 mm (zu wenig Hoehenunterschied fuer die feste Neigung)", + "vfl-stufe2-minh": "\n [Mindestwert 2] Ohne GF-Bogen (Rest als gerader VF-Anteil, der die Hoehe nicht aendert): mindestens %1 mm Hoehenaenderung noetig (vorhanden: %2 mm)", + "vfl-stufe2-minh-unmoeglich": "\n [Mindestwert 2] Nicht per Zielhoehe loesbar: schon ohne geraden VF-Anteil und ohne GF-Bogen betraegt der feste Fussabdruck %1 mm - die Strecke bietet aber nur %2 mm", + "vfl-stufe2-ungueltig": "\n Stufe 2 (horizontal+GF) war ungueltig - es wurde stattdessen Stufe 1 (VF-Winkel-Suche) versucht (siehe Tabelle oben).", + "vfl-frage-gf2-minimum": "\n Berechnetes GF2=%1 mm liegt unter der ueblichen Mindestlaenge (%2 mm).\n Ja = mit den exakt berechneten %1 mm bauen (Zielpunkt wird exakt getroffen).\n Nein = auf %2 mm auffuellen (Zielpunkt verschiebt sich entsprechend weiter).", "vfl-fehler-rest-nicht-baubar": "\n FEHLER: Rest nicht baubar (zu steil/zu kurz fuer Schwanz Motor+GF2+Separator+ES). Bitte weiter zeichnen oder flacher planen.", "vfl-fuege-block-ein": "\n Fuege %1 ein ...", "vfl-hinweis-gf2-minimum": "\n HINWEIS: berechnetes GF2=%1 mm < Minimum %2 mm -> auf Minimum angehoben (ES endet dadurch etwas weiter; siehe Ist-Ziel-Report).", @@ -313,6 +363,13 @@ "vfl-prompt-hoehe-kettenende": "\nHoehe (Z) des Kettenendes (ES-Element) [%1]: ", "vfl-prompt-hoehe-kettenende-2": "\nHoehe (Z) des Kettenendes (ES-Element) (Ab: %1 | Auf: %2) [%1]: ", "vfl-prompt-wahl-bis-n": "\nIhre Wahl (1-%1) [1]: ", + "vfl-frage-auf-ab-richtung": "\n\nKette kommt flach an - keine Zielhoehe verfuegbar. Richtung waehlen:", + "vfl-opt-richtung-auf": "\n 1 - Auf", + "vfl-opt-richtung-ab": "\n 2 - Ab", + "vfl-winkel-hoehen-header": "\n\nVerfuegbare Winkel und die damit erreichte Endhoehe - bitte waehlen:", + "vfl-winkel-hoehen-option": "\n %1 - %2 Grad (Endhoehe: %3 mm)", + "vfl-winkel-hoehen-zeile": "\n %1 Grad - Endhoehe: %2 mm", + "vfl-winkel-hoehen-zeile-ungueltig": "\n %1 Grad - nicht baubar (Bogen passt nicht in die gewaehlte Strecke)", "vfl-segment-gf-nicht-erlaubt": "\n Segment waere GF (zu steil) oder nicht baubar - innerhalb einer VF-Einheit nicht erlaubt.\n Bitte flacher/steigend zeichnen oder Foerderer beenden.", "vfl-winkel-option": "\n %1 - %2 Grad (L_GF=%3 mm L_VF=%4 mm)", "vfs-as90-mass": "\n AS_90: dx=%1 dz=%2", diff --git a/lang/en_GB.json b/lang/en_GB.json index 53314f5..125c002 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -19,12 +19,20 @@ "vfl-menu-horizontal-vf-3": "\n 3 - New VF with horizontal start (horizontal piece)", "vfl-menu-linie-ende-4": "\n 4 - New line TO chain end (then separator + ES element)", "vfl-prompt-wahl-1-4-def1": "\nYour choice (1-4) [1]: ", + "vfl-menu-gf-bogen-ka-1": "\n 1 - GF arc (horizontal curve)", + "vfl-menu-variokurve-ka-2": "\n 2 - Vario curve (horizontal curve, 30/60/90 degrees)", + "vfl-menu-linie-gf-ka-3": "\n 3 - New line: GF (gravity section)", + "vfl-menu-linie-vf-ka-4": "\n 4 - New line: down/up VF (VarioFoerderer unit)", + "vfl-menu-horizontal-vf-ka-5": "\n 5 - New VF with horizontal start (horizontal piece)", + "vfl-menu-linie-ende-ka-6": "\n 6 - New line TO chain end (then separator + ES element)", + "vfl-prompt-wahl-1-6-def3": "\nYour choice (1-6) [3]: ", "vfl-fehler-horizontal-vf-kurz": "\nERROR: Horizontal VF needs >= 1000 mm (deflection + motor) - draw it longer.", "vfl-fehler-linie-zu-kurz": "\nERROR: Line too short (or against travel direction) - please pick again.", "vfl-fehler-vf-kurz": "\nERROR: VarioFoerderer needs >= 1000 mm (deflection + motor) - draw it longer or choose \"GF\".", "vfl-gefaelle-festlegen-header": "\nDefine slope:", "vfl-gefaelle-opt-hoehe": "\n 1 - Given height (target height)", "vfl-gefaelle-opt-winkel": "\n 2 - Enter incline angle", + "vfl-gf-hinweis-laenge-berechnet": "(deltaL will be calculated and inserted)", "vfl-prompt-neigungswinkel": "\nIncline angle (degrees, 0 < angle <= %1) [%1]: ", "vfl-alert-winkel-ungueltig": "Incline angle invalid: %1 degrees. Allowed: 0 < angle <= %2 degrees.", "vfl-prompt-hoehe-linienendpunkt": "\nHeight (Z) of the line end point [%1]: ", @@ -42,6 +50,7 @@ "vfl-alert-gf-steigend-falsche-richtung": "Rising gravity conveyor: the chosen target height is below the current height - please choose a higher target height or use the normal (falling) mode.", "vfl-sep-vor-gf-frage": "\n\nInsert separator BEFORE this gravity section?", "vfl-sep-nach-gf-frage": "\n\nInsert separator AFTER this gravity section?", + "vfl-sep-gf-header": "Separator at this gravity section", "vfl-ist-kettenende-header": "\nIs this the chain end?", "vfl-kettenende-opt-ja-es": "\n 1 - Yes (place ES element)", "vfl-kettenende-opt-ja-ohne-es": "\n 2 - Yes (without placing ES element)", @@ -106,6 +115,10 @@ "vfl-opt2-60grad": "\n 60 deg", "vfl-opt3-30grad": "\n 30 deg", "vfl-prompt-wahl-1-3-def1": "\nYour choice (1/2/3) [1]: ", + "vfl-frage-startpunkt-typ": "\n\nNo clear GF/VF component was recognized at the starting point (a GF stretch and a VF horizontal stretch look structurally identical). How should the entry be built?", + "vfl-opt-eingang-direkt": "\n 1 - Build idler station directly (no GF stretch)", + "vfl-opt-eingang-mit-stumpf": "\n 2 - GF (%1 mm) + idler station", + "vfl-opt-eingang-ohne-umlenk": "\n 3 - No idler station (VF continuation)", "vfl-variokurve-seite-header": "\nVario curve - choose side:", "vfl-variokurve-variante-header": "\nVario curve - choose variant:", "vfl-variante-aussen": "\n 1 - Outer", @@ -164,9 +177,26 @@ "vfl-m3-junction-exakt": "\n Junction (exact): %1 mm", "vfl-m3-kletter-info": "\n Climb height %1 mm | climbers %2 | curves %3 | short VF %4", "vfl-m3-kein-winkel": "\n NO matching Vario angle -> infeasible (front already built).", + "vfl-m3-kletter-zu-kurz-flach": "\n No climb angle fits (segment too short) -> run is built entirely flat, height is absorbed by GF1.", + "vfl-m3-kletter-flach-gf": "\n Flat zone: GF compensation (GF1) = %1 mm", + "vfl-m3-alert-vf-zu-lang": "VF run is %1 m long (limit %2 m) - please re-plan (e.g. insert an intermediate motor station).", + "vfl-m3-warnung-fueller-eingang-zu-kurz": "\n WARNING: filler right after the reversing station is too short (%1 mm < minimum %2 mm) - only the minimum clearance was built, target position not reached exactly.", + "vfl-m3-warnung-fueller-ausgang-zu-kurz": "\n WARNING: filler right before the motor station is too short (%1 mm < minimum %2 mm) - only the minimum clearance was built, target position not reached exactly.", + "vfl-m3-lauf-anfang-header": "\n\nThe VF run is the start of the selected path. Start the run with:", + "vfl-m3-lauf-anfang-opt-offen": "\n 1 - No reversing station (open start, continue/merge later)", + "vfl-m3-lauf-anfang-opt-umlenk": "\n 2 - Reversing station directly (no GF1/separator)", + "vfl-m3-lauf-anfang-opt-umlenk-gf1": "\n 3 - Reversing station with GF1 + separator", + "vfl-m3-lauf-anfang-offen-hinweis": "\n Start deliberately left open - no reversing station/GF1/separator built; continue later or join with Vario_Kette_Merge.", + "vfl-m3-lauf-abschluss-header": "\n\nThe VF run is the end of the selected path. End the run with:", + "vfl-m3-lauf-abschluss-opt-offen": "\n 1 - No motor station (open end, continue/merge later)", + "vfl-m3-lauf-abschluss-opt-motor": "\n 2 - Set motor station (no ES element)", + "vfl-m3-lauf-abschluss-opt-motor-es": "\n 3 - Motor station + ES element (chain end)", + "vfl-m3-lauf-abschluss-offen-hinweis": "\n Run deliberately left open - no motor station/separator/ES built; continue later or join with Vario_Kette_Merge.", "vfl-m3-gf-verteilung": "\n\n GF distribution: 1 - all at inlet (GF1) 2 - 1/2 GF1 + 1/2 GF2", + "vfl-m3-gf-verteilung-alles-auslauf": "\n No GF1 room at the inlet chosen - full compensation moves to GF2 (outlet).", "vfl-m3-vert-halb": "1/2 GF1 + 1/2 GF2", "vfl-m3-vert-ganz": "all GF1", + "vfl-m3-vert-auslauf": "all GF2 (outlet)", "vfl-m3-vario-ergebnis": "\n -> Vario %1 (%2), L_VF %3 mm, GF total %4 mm, distribution %5 (GF2 remainder = measured fine correction)", "vfl-m3-warnung-gf2-negativ": "\n WARNING: body climbs too little - GF2<0 (missing %1 mm). Angle too shallow; dZ not exact.", "vfl-m3-gf2-ausgleich": "\n GF2 (measured compensation): L=%1 mm", @@ -304,6 +334,26 @@ "vfl-20m-hinweis": "\n >>> NOTE: conveyor longer than 20 m (%1 m) - motor station recommended!", "vfl-block-erstellt": "\n>>> Block '%1' (%2) created and inserted.", "vfl-fehler-rest-nicht-baubar": "\n ERROR: remainder cannot be built (too steep/too short for tail motor+GF2+separator+ES). Please continue drawing or plan flatter.", + "vfl-fehler-rest-nicht-baubar-mit-vorschlag": "\n ERROR: not buildable at target height %1 mm (distance dL=%2 mm, height difference dH=%3 mm, %4) - too steep/too short for tail motor+GF2+separator+ES. An approximately buildable target height would be:%5", + "vfl-fehler-rest-nicht-baubar-ohne-vorschlag": "\n ERROR: not buildable at target height %1 mm (distance dL=%2 mm, height difference dH=%3 mm, %4) - no alternative target height was found for this distance either. Please draw a longer distance or plan flatter.", + "vfl-vorschlag-ab-auf": " down to %1 mm or up to %2 mm", + "vfl-vorschlag-nur-ab": " down to %1 mm (up is not buildable at this distance)", + "vfl-vorschlag-nur-auf": " up to %1 mm (down is not buildable at this distance)", + "vfl-alert-kettenende-p1": "1. Target ΔL=%1 mm, ΔH=%2 mm (%3): angled Vario (angle table) not buildable.", + "vfl-alert-kettenende-p2-beide": "\n\n2. Horizontal+GF not buildable - would need at least ΔL=%1 mm OR at least ΔH=%2 mm.", + "vfl-alert-kettenende-p2-nur-minh": "\n\n2. Horizontal+GF not buildable - would need at least ΔH=%1 mm of height change.", + "vfl-alert-kettenende-p2-nur-minl": "\n\n2. Horizontal+GF not buildable - would need at least ΔL=%1 mm of distance.", + "vfl-stufe1-start": "\n\n[Diagnosis stage 1 - VF angle search]", + "vfl-stufe2-diagnose": "\n\n[Diagnosis stage 2 - horizontal+GF] deltaL=%1 mm deltaH=%2 mm -> GF_total=%3 mm L_VF=%4 mm (%5)", + "vfl-stufe2-diagnose-details": "\n [Details] already-flat=%1 | aus-dx=%2 mm (entry, should be 0) | ein-dx=%3 mm ein-dz=%4 mm (ES element) | bogen-x1=%5 mm bogen-z1=%6 mm (entry bend 3->0 deg, only if not already-flat) | bogen-x2=%7 mm bogen-z2=%8 mm (exit bend 0->3 deg, always) | FESTE_HORIZONTAL=%9 mm (separator+motor station)", + "vfl-stufe2-fest-kettenende": "\n Motor station+separator+ES require: length=%1 mm, height drop=%2 mm (fixed, independent of angle)", + "vfl-stufe2-fest-eingang": "\n Reversing station+separator+motor station+ES require: length=%1 mm, height drop=%2 mm (fixed, independent of angle)", + "vfl-stufe2-minl": "\n [Minimum 1] Without a straight VF section (GF sized to the target height): at least %1 mm of distance needed (available: %2 mm)", + "vfl-stufe2-minl-unmoeglich": "\n [Minimum 1] Not solvable via distance: even without a GF bend the height already changes by %1 mm - the target only calls for %2 mm (not enough height difference for the fixed incline)", + "vfl-stufe2-minh": "\n [Minimum 2] Without a GF bend (remainder as a straight VF section, which does not change height): at least %1 mm of height change needed (available: %2 mm)", + "vfl-stufe2-minh-unmoeglich": "\n [Minimum 2] Not solvable via target height: even without a straight VF section and without a GF bend, the fixed footprint is already %1 mm - the distance only offers %2 mm", + "vfl-stufe2-ungueltig": "\n Stage 2 (horizontal+GF) was invalid - stage 1 (VF angle search) was tried instead (see table above).", + "vfl-frage-gf2-minimum": "\n Calculated GF2=%1 mm is below the usual minimum length (%2 mm).\n Yes = build with the exact calculated %1 mm (hits the target point exactly).\n No = pad up to %2 mm (target point shifts further accordingly).", "vfl-fuege-block-ein": "\n Inserting %1 ...", "vfl-hinweis-gf2-minimum": "\n NOTE: calculated GF2=%1 mm < minimum %2 mm -> raised to minimum (ES therefore ends a bit further on; see actual-vs-target report).", "vfl-horizontale-zwischenstrecke": "\n\nHorizontal intermediate section (0 deg, L=%1 mm)", @@ -313,6 +363,13 @@ "vfl-prompt-hoehe-kettenende": "\nHeight (Z) of the chain end (ES element) [%1]: ", "vfl-prompt-hoehe-kettenende-2": "\nHeight (Z) of the chain end (ES element) (down: %1 | up: %2) [%1]: ", "vfl-prompt-wahl-bis-n": "\nYour choice (1-%1) [1]: ", + "vfl-frage-auf-ab-richtung": "\n\nChain arrives flat - no target height available. Choose direction:", + "vfl-opt-richtung-auf": "\n 1 - Up", + "vfl-opt-richtung-ab": "\n 2 - Down", + "vfl-winkel-hoehen-header": "\n\nAvailable angles and the resulting end height - please choose:", + "vfl-winkel-hoehen-option": "\n %1 - %2 deg (end height: %3 mm)", + "vfl-winkel-hoehen-zeile": "\n %1 deg - end height: %2 mm", + "vfl-winkel-hoehen-zeile-ungueltig": "\n %1 deg - not buildable (bend does not fit into the chosen distance)", "vfl-segment-gf-nicht-erlaubt": "\n Segment would be GF (too steep) or not buildable - not allowed within a VF unit.\n Please draw flatter/rising or end the conveyor.", "vfl-winkel-option": "\n %1 - %2 deg (L_GF=%3 mm L_VF=%4 mm)", "vfs-as90-mass": "\n AS_90: dx=%1 dz=%2", diff --git a/lib/vf_spec_export.py b/lib/vf_spec_export.py index 8698684..8a7d4ad 100644 --- a/lib/vf_spec_export.py +++ b/lib/vf_spec_export.py @@ -430,6 +430,14 @@ class SpecSchreiber(object): raise ValueError("%s: Feld %r fehlt" % (self.wo, name)) return None + def richtung(self, quelle): + # Reine Richtungswahl OHNE Laenge (vfl-in-richtung: nur REAL, kein + # DL-Token) - fuer den Kettenanfang-Fall von Linie-GF modus="hoehe"/ + # "steigend"+"hoehe", wo die Laenge erst aus Hoehe/Winkel berechnet + # wird. Nur relevant, wenn dies das erste Segment der Kette ist. + self.zahl("REAL", self.feld(quelle, "hz")) + self.erster_dl = False + def linie(self, quelle): self.zahl("DL", self.feld(quelle, "dl")) if self.erster_dl: @@ -516,14 +524,16 @@ class SpecSchreiber(object): or "endpunkt") self.raus("STR", _code(GF_LAENGE_MODUS, smodus, "steigend_modus")) - if smodus == "endpunkt" or self.erster_dl: + if smodus == "endpunkt": self.linie(sek) + elif self.erster_dl: + self.richtung(sek) if smodus == "hoehe": self.zahl("REAL", self.feld(sek, "hoehe")) self.zahl("REAL", self.feld(sek, "winkel")) elif modus == "hoehe": if self.erster_dl: - self.linie(sek) + self.richtung(sek) self.raus("STR", _ja_code(self.feld(sek, "sep_vor", pflicht=False))) self.raus("STR", _ja_code(self.feld(sek, "sep_nach", diff --git a/tests/test_vf_spec.lsp b/tests/test_vf_spec.lsp index 071b63a..1cd33ed 100644 --- a/tests/test_vf_spec.lsp +++ b/tests/test_vf_spec.lsp @@ -146,12 +146,14 @@ (vsp-journal spec)) ;; --- Linie-GF, Zielhoehe zuerst (laenge_modus "hoehe") --- - ;; Kein Separator-Paar VOR der Hoehen-/Winkel-Eingabe wie im Endpunkt-Zweig - ;; - hier stehen sie NACH DL(+hz), aber vor Hoehe/Winkel (siehe - ;; vf-linienzug-modus, Zweig B). + ;; Kettenanfang braucht nur eine REINE Richtungswahl (vfl-in-richtung: nur + ;; REAL, KEIN DL-Token - die Laenge ist hier ja noch unbekannt, sie ergibt + ;; sich erst aus Hoehe/Winkel). Kein Separator-Paar VOR der Hoehen-/Winkel- + ;; Eingabe wie im Endpunkt-Zweig - hier stehen sie NACH der Richtung, aber + ;; vor Hoehe/Winkel (siehe vf-linienzug-modus, Zweig B). (setq spec (tsp-spec T (list (tsp-sek (list (cons "glied" "Linie-GF") (cons "laenge_modus" "hoehe") - (cons "dl" 100.0) (cons "hz" 0.0) + (cons "hz" 0.0) (cons "sep_vor" 1) (cons "sep_nach" 0) (cons "hoehe" 1800.0) (cons "winkel" 3.0) (cons "ende" "nein")) nil)))) @@ -159,7 +161,7 @@ (append (tsp-pre-mit-as) (list (cons "STEP" "Linie-GF") (cons "STR" "1") (cons "STR" "2") ; laenge_modus: hoehe - (cons "DL" 100.0) (cons "REAL" 0.0) + (cons "REAL" 0.0) ; reine Richtungswahl, kein DL (cons "STR" "1") (cons "STR" "2") ; Separator vor(ja)/nach(nein) (cons "REAL" 1800.0) (cons "REAL" 3.0) (cons "STR" "3"))) @@ -182,6 +184,25 @@ (cons "STR" "3"))) (vsp-journal spec)) + ;; --- Linie-GF, Sonderfall Steigend, Zielhoehe-Unterwahl --- + ;; Wie "hoehe" oben: nur reine Richtungswahl (REAL, kein DL) am + ;; Kettenanfang - KEIN Separator-Feld. + (setq spec (tsp-spec T (list + (tsp-sek (list (cons "glied" "Linie-GF") (cons "laenge_modus" "steigend") + (cons "steigend_modus" "hoehe") + (cons "hz" 0.0) + (cons "hoehe" 1810.0) (cons "winkel" 1.5) + (cons "ende" "nein")) nil)))) + (tsp-journal-eq "Linie-GF, Steigend + Zielhoehe" + (append (tsp-pre-mit-as) + (list (cons "STEP" "Linie-GF") (cons "STR" "1") + (cons "STR" "3") ; laenge_modus: steigend + (cons "STR" "2") ; steigend_modus: hoehe + (cons "REAL" 0.0) ; reine Richtungswahl, kein DL + (cons "REAL" 1810.0) (cons "REAL" 1.5) + (cons "STR" "3"))) + (vsp-journal spec)) + ;; --- Horizontal-VF: horizontaler Erstkoerper --- ;; Nur hier stehen Separator vor/nach VOR der Endpunkt-Antwort ;; (vfl-baue-horizontal-koerper im Ziel-Modus). diff --git a/tests/test_vf_spec.py b/tests/test_vf_spec.py index 4e71fc3..20e7101 100644 --- a/tests/test_vf_spec.py +++ b/tests/test_vf_spec.py @@ -342,7 +342,7 @@ LISP_FAELLE = { "start": _start(), "sektionen": [ {"glied": "Linie-GF", "laenge_modus": "hoehe", - "dl": 100.0, "hz": 0.0, "sep_vor": True, "sep_nach": False, + "hz": 0.0, "sep_vor": True, "sep_nach": False, "hoehe": 1800.0, "winkel": 3.0, "ende": "nein"}]}, "Linie-GF, Steigend + Endpunkt": { "start": _start(), @@ -350,6 +350,12 @@ LISP_FAELLE = { {"glied": "Linie-GF", "laenge_modus": "steigend", "steigend_modus": "endpunkt", "dl": 800.0, "hz": 0.0, "winkel": 2.0, "ende": "nein"}]}, + "Linie-GF, Steigend + Zielhoehe": { + "start": _start(), + "sektionen": [ + {"glied": "Linie-GF", "laenge_modus": "steigend", + "steigend_modus": "hoehe", + "hz": 0.0, "hoehe": 1810.0, "winkel": 1.5, "ende": "nein"}]}, "Horizontal-VF + Motorstation + ES": { "start": _start(), "sektionen": [ @@ -453,8 +459,8 @@ class TestLispErwartungen: def test_alle_faelle_gefunden(self): erwartungen = _lisp_erwartungen() - assert len(erwartungen) == 9, \ - f"9 tsp-journal-eq-Faelle erwartet, {len(erwartungen)} gefunden: " \ + assert len(erwartungen) == 10, \ + f"10 tsp-journal-eq-Faelle erwartet, {len(erwartungen)} gefunden: " \ f"{sorted(erwartungen)}" @pytest.mark.parametrize("praefix", sorted(LISP_FAELLE))