From e3dbaceb24c9f3f3713465d90a84146f1a2d258f Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Wed, 26 Aug 2026 11:33:19 +0200 Subject: [PATCH] =?UTF-8?q?Wizard=20mit=20Oberfl=C3=A4chenst=C3=BCckwerk?= =?UTF-8?q?=20f=C3=BCr=20den=20Mode=203=20f=C3=BCr=20den=20VF=20gebaut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 5 +- Lisp/vf_core.lsp | 29 +- Lisp/vf_linienzug.lsp | 831 ++++++++++++++++++++++++++++++++---- Lisp/vf_standard.lsp | 9 +- dcl/vf_linienzug_wizard.dcl | 268 ++++++++++++ doc/variofoerderer.md | 500 ++++++++++++++++++++++ lang/de_DE.json | 2 + lang/en_GB.json | 2 + menu/SSG_LIB.cui | 186 ++++---- menu/SSG_LIB.mnu | 2 + 10 files changed, 1651 insertions(+), 183 deletions(-) create mode 100644 dcl/vf_linienzug_wizard.dcl create mode 100644 doc/variofoerderer.md diff --git a/CLAUDE.md b/CLAUDE.md index e47713e..89e149e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -93,7 +93,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `ssg_dialog.lsp` | - | DCL-Dialog-Vorlagen und Hilfsfunktionen | | `ssg_layer.lsp` | - | Layer-Verwaltung | | `KreiselInsert.lsp` | KreiselInsert, KreiselConnect, KreiselRedraw, KreiselQuick, KreiselEdit, KreiselParams, KreiselLabelSetup, KreiselLabelPos, KreiselLabelHoehe, ILS_Eckrad | ILS Kreisel und Eckrad komplett in AutoLISP | -| `VarioFoerderer.lsp` (Wrapper fuer `vf_core.lsp`/`vf_standard.lsp`/`vf_etage.lsp`/`vf_linienzug.lsp`) | FOERDERANLAGE, VARIOFOERDERER_EDIT, VARIOFOERDERER_NACHRUESTEN, Vario_Kette_Merge | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standard- UND Etage-Typ: Werteingabe per DCL-Dialog (`vfs-standard-dialog-ablauf` in vf_standard.lsp bzw. `vfe-etage-dialog-ablauf` in vf_etage.lsp, beide nutzen dieselben Dialoge `vfs-dialog-eingabe-basis`/`vfs-dialog-winkel-verteilung`); Doppelklick auf VF_n-Block ruft VARIOFOERDERER_EDIT, das per SSG_VF_EDIT-XDATA-Marker ("standard"/"etage"/"linienzug") in den passenden Neuaufbau-Zweig dispatcht (`vfe-edit-ent` fuer Etage, `vfl-edit-ent` fuer Linienzug); Altbestand-Bloecke ohne Marker werden abgewiesen. Linienzug (Modus 1, `vf-linienzug-modus`) zeichnet jede interaktive Eingabe in einem Journal auf (`vfl-in-point`/`-string`/`-real`/`-int`) und schreibt es als XDATA auf den fertigen `VF_n`-Block; ein Abbruch (ESC) loescht dadurch nichts mehr, sondern wickelt die bis dahin gebaute Teil-Geometrie ebenso zu einem Block (`vfl-modus-abbruch-sichern`) - sie bleibt stehen und ist sofort per Doppelklick weiter editierbar/fortsetzbar. `vfl-edit-ent` liest das Journal, zeigt die Sektionen ueber einen DCL-Dialog (`vfl-dlg-position`, `dcl/vfl_edit.dcl`) an, kuerzt bei Bedarf auf eine gewaehlte Sektion (stummer Replay der behaltenen Eingaben) und baut danach interaktiv weiter; `Vario_Kette_Merge` (in vf_linienzug.lsp) fuehrt mehrere einzeln gebaute VF_n-Bloecke ab einem gewaehlten Start-Baustein ueber die reale KS_AUS->KS_EIN-Nachbarschaft zu einem Gesamt-Block zusammen (aggregierte Attribute, Luecken-Erkennung) | +| `VarioFoerderer.lsp` (Wrapper fuer `vf_core.lsp`/`vf_standard.lsp`/`vf_etage.lsp`/`vf_linienzug.lsp`) | FOERDERANLAGE, VARIOFOERDERER_EDIT, VARIOFOERDERER_NACHRUESTEN, Vario_Kette_Merge, VF_WIZARD_AN, VF_WIZARD_AUS | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standard- UND Etage-Typ: Werteingabe per DCL-Dialog (`vfs-standard-dialog-ablauf` in vf_standard.lsp bzw. `vfe-etage-dialog-ablauf` in vf_etage.lsp, beide nutzen dieselben Dialoge `vfs-dialog-eingabe-basis`/`vfs-dialog-winkel-verteilung`); Doppelklick auf VF_n-Block ruft VARIOFOERDERER_EDIT, das per SSG_VF_EDIT-XDATA-Marker ("standard"/"etage"/"linienzug") in den passenden Neuaufbau-Zweig dispatcht (`vfe-edit-ent` fuer Etage, `vfl-edit-ent` fuer Linienzug); Altbestand-Bloecke ohne Marker werden abgewiesen. Linienzug (Modus 1, `vf-linienzug-modus`) zeichnet jede interaktive Eingabe in einem Journal auf (`vfl-in-point`/`-string`/`-real`/`-int`) und schreibt es als XDATA auf den fertigen `VF_n`-Block; ein Abbruch (ESC) loescht dadurch nichts mehr, sondern wickelt die bis dahin gebaute Teil-Geometrie ebenso zu einem Block (`vfl-modus-abbruch-sichern`) - sie bleibt stehen und ist sofort per Doppelklick weiter editierbar/fortsetzbar. Der komplette Linienzug-Hauptstrang (Menue-Fragen von AS-Element bis Kettenende, inkl. GF-Bogen/Vario-Kurve/VF-Einheit-Fortsetzung) laeuft per Default ueber DCL-Dialoge statt Konsole (`*vfl-wizard-mode*`, Befehle VF_WIZARD_AN/VF_WIZARD_AUS): `vfl-in-string`/`-int`/`-real` zeigen bei aktivem Wizard-Modus generische Dialoge aus `dcl/vf_linienzug_wizard.dcl` (Zahl-Eingabe bzw. Mehrfachauswahl aus `vfl-menu`/`vfl-menu-int`) statt `getstring`/`getint`/`getreal` aufzurufen; die ORIGINALEN Konsolen-Fragen (princ + get*, de/en ueber ssg-text) bleiben unveraendert im Code (Fallback bei Fehlern via `vl-catch-all-apply`, siehe `doc/variofoerderer.md`). `vfl-edit-ent` liest das Journal, zeigt die Sektionen ueber einen DCL-Dialog (`vfl-dlg-position`, `dcl/vfl_edit.dcl`) an, kuerzt bei Bedarf auf eine gewaehlte Sektion (stummer Replay der behaltenen Eingaben, umgeht den Wizard-Zweig komplett) und baut danach interaktiv weiter. Linienzug Modus 2 (Pfad+Zielhoehe-Solver, `vf-linienzug-modus2`) nutzt dieselben Wrapper PLUS die neue Objektauswahl-Wrapper-Funktion `vfl-in-selection` (Pfad-Objekte als stabile Entity-Handles journalisiert, neue Journal-Art `"OBJS"`) und schreibt sein Journal unter dem eigenen XDATA-Marker `"linienzug2"`; Doppelklick baut hier NICHT abschnittsweise, sondern per vollem Reset 1:1 aus dem Journal neu auf (`vfl-edit-ent2`, dispatcht aus `vfl-edit-ent` per Marker) - Modus 3 (Vorwaerts-Nachbau) bleibt bewusst reine Konsole (im Code selbst als Legacy/"wird umgebaut" markiert). `Vario_Kette_Merge` (in vf_linienzug.lsp) fuehrt mehrere einzeln gebaute VF_n-Bloecke ab einem gewaehlten Start-Baustein ueber die reale KS_AUS->KS_EIN-Nachbarschaft zu einem Gesamt-Block zusammen (aggregierte Attribute, Luecken-Erkennung). Details/Entscheidungsbaum: `doc/variofoerderer.md` | | `Gefaellestrecke.lsp` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT | Gefaelle-Foerderanlage (AUS -> Staustrecke skaliert -> Separator -> EIN); Modus 1 per DCL-Dialog (Einfuegehoehe, Element-Winkel 30/90); Doppelklick auf GF_n-Block ruft GEFAELLESTRECKE_EDIT (Dialog vorbelegt, Neuaufbau) | | `export.lsp` | EXPORTSIVAS, EXPORTCSV, OMNI_UPDATE_ATTRIBS | JSON-Sammlung und Python-Export (Omniflo-Merkmale/Sum-Zeile via lib/export_csv.py) | | `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W*_*, OMNI_AP60/AP110, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen, Edit-Dialog | @@ -114,13 +114,14 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `tro_insert.dcl` | TRO_INSERT (Tro_Edit.lsp) | | `tro_edit.dcl` | TRO_EDIT (Tro_Edit.lsp) | | `vfl_edit.dcl` | Linienzug-Editieren/Fortsetzen (vf_linienzug.lsp, `vfl-dlg-position`, aufgerufen aus `vfl-edit-ent`) | +| `vf_linienzug_wizard.dcl` | Linienzug Modus 1 Assistent: zwei generische Einzel-Dialoge (Zahl-Eingabe, Mehrfachauswahl; `vflw-zahl`/`vflw-wahl`, aufgerufen aus `vfl-in-real`/`vfl-in-string`/`vfl-in-int` bei aktivem `*vfl-wizard-mode*`) PLUS sieben Gruppen-Dialoge, die mehrere immer unmittelbar aufeinanderfolgende Fragen in einem Bildschirm zusammenfassen (Kettenstart, AS-Element, GF-Bogen, ES-Element, Vario-Kurve, Gefaelle festlegen, Ziel-Hoehe, Horizontales Stueck - inkl. Punktwahl-Button mit X/Y/Z-Anzeige; `vflw-gruppe-*-impl` in vf_linienzug.lsp fuellen dafuer vorab eine kleine Pending-Queue `*vflw-pending*`, die einzelnen `vfl-in-*`-Aufrufe bleiben dabei unveraendert). Details: `doc/variofoerderer.md` | ## Menue (SSG_LIB.mnu + SSG_LIB.mnl) - `SSG_LIB.mnu` - Menuedefinition mit Lazy-Loading (`(ssg-ensure "Modul") Befehl`) - `SSG_LIB.mnl` - Automatisch geladen mit dem Menue, definiert `ssg-ensure` Loader - `***MENUGROUP=SSG_LIB` - Menuegruppenname -- `***POP1` - Hauptmenue (ILS, Omniflo, Export, Konfiguration) +- `***POP1` - Hauptmenue (ILS, Omniflo, SPS [TRO, Connections], Export, Konfiguration) - `***DOUBLECLICK` - Doppelklick auf INSERT-Bloecke ruft SSG_BLOCKEDIT auf - `***POP501` - Rechtsklick-Kontextmenue (KreiselEdit, OMNI_EDIT, SSG_BLOCKEDIT) diff --git a/Lisp/vf_core.lsp b/Lisp/vf_core.lsp index 9ec78fd..44f1d8c 100644 --- a/Lisp/vf_core.lsp +++ b/Lisp/vf_core.lsp @@ -764,11 +764,30 @@ ;; 30/90-Wahl fuer ein AS/ES-Element. Rueckgabe: "30" oder "90" (Vorgabe 90). ;; headerkey: i18n-Key fuer die Kopfzeile ("vf-winkel-aus-header" oder ;; "vf-winkel-ein-header"). Rueckgabe: "30" oder "90" (Default 90). -(defun vf-frage-element-winkel (headerkey) - (princ (ssg-text headerkey)) - (princ (ssg-text "vf-winkel-90")) - (princ (ssg-text "vf-winkel-30")) - (if (= (getstring (ssg-text "prompt-wahl-1-2")) "2") "30" "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. +(defun vf-frage-element-winkel (headerkey / antwort) + (if (and (boundp '*vfl-wizard-mode*) *vfl-wizard-mode* + (car (atoms-family 1 '("VFLW-WAHL")))) + (progn + (setq antwort + (vl-catch-all-apply 'vflw-wahl + (list (ssg-text headerkey) + (list (ssg-text "vf-winkel-90") (ssg-text "vf-winkel-30")) 1))) + (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"))) + ) + ) + (if (= antwort "2") "30" "90")) ;; AS-/ES-Masse-Globals (aus-dx/dy/dz bzw. ein-dx/dy/dz) fuer die gewaehlte ;; Winkel-/Seiten-Variante neu setzen (fuer berechne-alle-winkel, GF-Winkel, diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index f0f812a..1f151bc 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -170,34 +170,526 @@ (list (cdr e))) nil)) +;; ============================================================ +;; TEIL 0b-2: WIZARD-EINGABE (DCL statt Konsole) +;; ============================================================ +;; Ersetzt NUR die LIVE-Eingabe (frischer Bau) durch DCL-Dialoge +;; (dcl/vf_linienzug_wizard.dcl). Journal-Replay (Editieren bestehender +;; Ketten, vfl-edit-ent) ist UNVERAENDERT: er liefert seinen Wert ueber +;; "popped" und erreicht den Wizard-Zweig unten gar nicht erst. +;; Die ORIGINALEN Konsolen-Fragen (princ + getstring/getreal/getint an jeder +;; Aufrufstelle) bleiben vollstaendig im Code stehen (weiterhin de/en ueber +;; ssg-text/lang/*.json) - sie laufen bei *vfl-wizard-mode* = nil unveraendert +;; wie bisher. Schnell zurueckschalten: Befehl VF_WIZARD_AUS bzw. +;; (setq *vfl-wizard-mode* nil). +;; Sicherheitsnetz: jeder Wizard-Aufruf ist per vl-catch-all-apply +;; abgesichert - jeder Fehler (fehlendes DCL, kaputtes Tile etc.) faellt +;; automatisch und lautlos auf die alte Konsolen-Eingabe zurueck, es gibt +;; also keinen Abbruch-Pfad, der NUR durch den Wizard entsteht. +(if (not (boundp '*vfl-wizard-mode*)) (setq *vfl-wizard-mode* T)) +(if (not (boundp '*vflw-menu-optionen*)) (setq *vflw-menu-optionen* nil)) +(if (not (boundp '*vflw-menu-default*)) (setq *vflw-menu-default* 1)) + +(defun c:VF_WIZARD_AN () + (setq *vfl-wizard-mode* T) + (princ "\nVF-Linienzug-Assistent: EIN (DCL-Dialoge)") + (princ)) +(defun c:VF_WIZARD_AUS () + (setq *vfl-wizard-mode* nil) + (princ "\nVF-Linienzug-Assistent: AUS (Konsolen-Fragen)") + (princ)) + +(defun vflw-dcl-pfad () + (strcat (vl-string-translate "\\" "/" (getenv "DXFM_DCL")) "/vf_linienzug_wizard.dcl")) + +;; Text fuer Dialog-Anzeige (Kopfzeile ODER Popup-Listen-Option) saeubern: +;; fuehrende Newlines/Leerzeichen entfernen, DANACH ein fuehrendes +;; Konsolen-Ziffernpraefix wie "1 - " (aus "1 - 90 Grad", "2 - Links" usw.) +;; abschneiden - im Dialog klickt der Nutzer die Option, die Ziffer braucht +;; er nur an der Kommandozeile. Die Ziffer/der Index selbst wird davon nicht +;; beruehrt: Popup-Auswahl und Pending-Queue arbeiten weiterhin ueber die +;; Listenposition (get_tile "..." liefert einen 0-basierten Index), nicht +;; ueber diesen Anzeigetext. Kopfzeilen-Texte beginnen nie mit einer Ziffer +;; und sind von diesem zweiten Schritt daher unberuehrt. +(defun vflw-clean (s / i n) + (while (and (> (strlen s) 0) (member (substr s 1 1) (list "\n" " "))) + (setq s (substr s 2))) + (setq n (strlen s) i 1) + (while (and (<= i n) (wcmatch (substr s i 1) "#")) (setq i (1+ i))) + (if (> i 1) + (progn + (while (and (<= i n) (= (substr s i 1) " ")) (setq i (1+ i))) + (if (and (<= i n) (= (substr s i 1) "-")) + (progn + (setq i (1+ i)) + (while (and (<= i n) (= (substr s i 1) " ")) (setq i (1+ i))) + (setq s (substr s i)))))) + s) + +;; Generischer Zahlen-Dialog (ersetzt getreal). Rueckgabe: reale Zahl oder +;; nil (Abbruch/leer - wie getreal bei blossem Enter, von den Aufrufern +;; bereits ueberall mit einem Default abgefangen). +(defun vflw-zahl-impl (prompt / dat dcl-pfad dlg-wert ergebnis) + (setq dcl-pfad (vflw-dcl-pfad)) + (setq dat (load_dialog dcl-pfad)) + (if (not (new_dialog "vflw_zahl" dat)) + (progn (if (and dat (>= dat 0)) (unload_dialog dat)) nil) + (progn + (set_tile "kopf" (vflw-clean prompt)) + (action_tile "accept" "(setq dlg-wert (get_tile \"wert\")) (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (if (and (= ergebnis 1) dlg-wert (> (strlen dlg-wert) 0)) + (atof dlg-wert) + 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)) + +;; Generischer Auswahl-Dialog (ersetzt eine princ-Menue-Liste + getstring/ +;; getint). optionen = Liste bereits lokalisierter Options-Texte, +;; default-idx = 1-basiert vorselektiert. Rueckgabe: "1".."N" (String, wie +;; getstring) oder "" (Abbruch/leer - faellt bei den Aufrufern ueberall auf +;; den bestehenden Default-Zweig zurueck, genau wie ein leeres Enter heute). +(defun vflw-wahl-impl (prompt optionen default-idx / dat dcl-pfad dlg-opt ergebnis opt) + (setq dcl-pfad (vflw-dcl-pfad)) + (setq dat (load_dialog dcl-pfad)) + (if (not (new_dialog "vflw_wahl" dat)) + (progn (if (and dat (>= dat 0)) (unload_dialog dat)) "") + (progn + (set_tile "kopf" (vflw-clean prompt)) + (start_list "opts") + (foreach opt optionen (add_list (vflw-clean opt))) + (end_list) + (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)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (if (= ergebnis 1) (itoa (1+ (atoi dlg-opt))) "")))) +(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)) + +;; ============================================================ +;; TEIL 0b-4: GRUPPEN-DIALOGE - GEMEINSAME PUNKTWAHL-BAUSTEINE +;; ============================================================ +;; Punktwahl aus einem offenen Dialog heraus: (getpoint) direkt aus einem +;; action_tile-Callback funktioniert in BricsCAD NICHT zuverlaessig (der +;; Dialog behaelt den Fokus, die Zeichnung reagiert nicht auf Klicks - per +;; Test bestaetigt). Stattdessen das robuste "Schliessen-Picken-Neu-Zeigen"- +;; Muster: der Pick-Button beendet den Dialog ueber einen eigenen +;; done_dialog-Code (2), NACH dem unload_dialog laeuft (getpoint) ganz +;; normal auf der Kommandozeile, danach wird der Dialog mit dem Ergebnis neu +;; aufgebaut (new_dialog erneut) - eine (while ...)-Schleife um new_dialog/ +;; start_dialog statt eines einmaligen Aufrufs. +(defun vflw-g-punkt-str (pt) + (strcat "X=" (rtos (car pt) 2 1) " Y=" (rtos (cadr pt) 2 1) " Z=" (rtos (caddr pt) 2 1))) + +;; ------------------------------------------------------------ +;; Gruppe "Punkt+Hoehe": ein Punkt gefolgt von einer davon abhaengigen +;; Hoehen-Zahl (Default = Z des gepickten Punkts, wie im Original-Prompt). +;; Wiederverwendet fuer Modus 1 "Kettenstart" (Startpunkt+Starthoehe) UND +;; Modus 2 "Startpunkt/Endpunkt" (jeweils +Hoehe) - kopf-key/wlabel-text pro +;; Aufruf. Original-Reihenfolge/-Journal an jeder Aufrufstelle: vfl-in-point, +;; dann vfl-in-real - bleibt unveraendert, nur die Werte kommen aus der +;; Pending-Queue. +(defun vflw-gruppe-punkt-hoehe-impl (kopf-key wlabel-text / + dat dcl-pfad ergebnis gpunkt gwert wert-akt fertig) + (setq wert-akt "0" fertig nil) + (while (not fertig) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_punkt_zahl" dat)) + (progn (if (and dat (>= dat 0)) (unload_dialog dat)) (setq fertig t)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text kopf-key))) + (set_tile "wlabel" wlabel-text) + (set_tile "wert" wert-akt) + (if gpunkt (set_tile "pt_anzeige" (vflw-g-punkt-str gpunkt))) + (action_tile "pick" "(done_dialog 2)") + (action_tile "accept" "(setq gwert (get_tile \"wert\")) (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (cond + ((= ergebnis 2) + ;; Dialog ist jetzt zu - Zeichnung hat den Fokus, getpoint geht normal. + (setq gpunkt (vfl-getpoint nil "\nPunkt waehlen: ")) + (if gpunkt (setq wert-akt (rtos (caddr gpunkt) 2 1))) + ;; fertig bleibt nil -> Schleife zeigt den Dialog mit dem Ergebnis erneut. + ) + ((= ergebnis 1) + (setq fertig t) + (if (and gpunkt gwert (> (strlen gwert) 0)) + (vflw-pending-push-all (list gpunkt (atof gwert))))) + (t (setq fertig t))) + ) + ) + ) + (princ)) + +;; ------------------------------------------------------------ +;; Gruppe "AS-/ES-Element": Ja/Nein + [wenn Ja] Winkel(30/90) + Seite. +;; Wiederverwendet fuer Modus 1 UND Modus 2, jeweils fuer AS (Kettenanfang) +;; UND ES (Kettenende) - kopf-key pro Aufruf traegt die konkrete Frage; die +;; Winkel/Seite-Optionen sind in allen vier Faellen identisch (90/30 bzw. +;; links/rechts), "Nein" ist journalseitig immer "2" (identischer Vergleich +;; im Aufrufer-Code) - beides braucht daher keinen eigenen Parameter. +;; Original-Reihenfolge/-Journal: vfl-in-string (Ja/Nein), dann bei Ja +;; vfl-in-value (Winkel) + vfl-in-string (Seite) - bleibt unveraendert. +(defun vflw-gruppe-as-impl (kopf-key / dat dcl-pfad ergebnis gsetzen gwinkel gseite) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_as" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (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") + (action_tile "setzen" + "(mode_tile \"winkel\" (if (= (get_tile \"setzen\") \"1\") 0 1)) + (mode_tile \"seite\" (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\")) + (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (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")))))) + (princ)) + +;; ------------------------------------------------------------ +;; Gruppe "Winkel+Seite": GF-Bogen (3 Winkel-Optionen) ODER ES-Element am +;; Kettenende (2 Winkel-Optionen). Original-Reihenfolge/-Journal: +;; vfl-in-int/vfl-in-value (Winkel), dann vfl-in-string (Seite). +;; winkel-kind: "INT" (GF-Bogen, vfl-in-int liefert Zahl) oder "STR" +;; (ES-Element, vfl-in-value liefert "30"/"90" als String). +(defun vflw-gruppe-winkel-seite-impl (kopf-key winkel-optionen winkel-kind / dat dcl-pfad ergebnis gwinkel 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") + (action_tile "accept" + "(setq gwinkel (get_tile \"winkel\")) (setq gseite (get_tile \"seite\")) (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (if (= ergebnis 1) + (vflw-pending-push-all + (list + (if (= winkel-kind "INT") (1+ (atoi gwinkel)) (nth (atoi gwinkel) '("90" "30"))) + (if (= gseite "1") "2" "1")))))) + (princ)) + +;; ------------------------------------------------------------ +;; Gruppe "Vario-Kurve": Winkel(90/60/30) + Seite + Variante(aussen/innen). +;; Original-Reihenfolge/-Journal: vfl-in-int (Winkel), vfl-in-string +;; (Seite), vfl-in-string (Variante). +(defun vflw-gruppe-variokurve-impl ( / dat dcl-pfad ergebnis gwinkel gseite gvariante) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_variokurve" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-variokurve-winkel-header"))) + (start_list "winkel") + (add_list (vflw-clean (ssg-text "vfl-opt1-90grad"))) + (add_list (vflw-clean (ssg-text "vfl-opt2-60grad"))) + (add_list (vflw-clean (ssg-text "vfl-opt3-30grad"))) + (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") + (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") + (action_tile "accept" + "(setq gwinkel (get_tile \"winkel\")) + (setq gseite (get_tile \"seite\")) + (setq gvariante (get_tile \"variante\")) + (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (if (= ergebnis 1) + (vflw-pending-push-all + (list (1+ (atoi gwinkel)) + (if (= gseite "1") "2" "1") + (if (= gvariante "1") "2" "1")))))) + (princ)) + +;; ------------------------------------------------------------ +;; Gruppe "Gefaelle festlegen" (Linie GF): Modus(Hoehe/Winkel) + EIN +;; Wertfeld (Beschriftung wechselt mit dem Modus). KEIN Punkt-Feld: der +;; Endpunkt (X/Y, fuer die Fahrtrichtung/Laengenberechnung) ist an der +;; Aufrufstelle bereits VOR dieser Gruppe ueber vfl-neue-linie-messen/ +;; vfl-in-point gepickt - dessen Z wird nie gelesen, "Hoehe" hier ist ein +;; davon unabhaengiger Zahlenwert (siehe Kommentar bei +;; vfl-neue-linie-messen). 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) + (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)) + ;; 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 "accept" + "(setq gmodus (get_tile \"modus\")) (setq gwert (get_tile \"wert\")) (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + (if (= ergebnis 1) + (vflw-pending-push-all + (list (if (= gmodus "1") "2" "1") (atof gwert)))))) + (princ)) + +;; ------------------------------------------------------------ +;; Gruppe "Ziel-Hoehe": NUR die Hoehen-Zahl (kein Punkt-Feld). Wiederverwendet +;; an mehreren Stellen (Linie-VF, VF-Einheit-Fortsetzung "Auf/Ab", +;; vfl-body-abschluss). Der Endpunkt (X/Y, fuer die Segmentlaenge) ist an der +;; Aufrufstelle bereits separat ueber vfl-neue-linie-messen gepickt - dessen +;; Z wird nirgends verwendet, die Hoehe hier ist eine davon unabhaengige +;; Zahl (Default = aktuelle Kettenhoehe, wie im Original-Prompt). Nutzt +;; bewusst den generischen Einzel-Dialog vflw_zahl (kein Punkt-Button, der +;; faelschlich eine hier moegliche Punktwahl suggerieren wuerde). +;; hoehe-default: aktuelle Kettenhoehe (Vorbelegung, wie im Original-Prompt). +(defun vflw-gruppe-ziel-hoehe-impl (hoehe-default / dat dcl-pfad ergebnis dlg-wert) + (setq dat (load_dialog (vflw-dcl-pfad))) + (if (not (new_dialog "vflw_zahl" dat)) + (if (and dat (>= dat 0)) (unload_dialog dat)) + (progn + (set_tile "kopf" (vflw-clean (ssg-text "vfl-prompt-hoehe-endpunkt"))) + (set_tile "wert" (rtos hoehe-default 2 1)) + (action_tile "accept" "(setq dlg-wert (get_tile \"wert\")) (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (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)))))) + (princ)) + +;; ------------------------------------------------------------ +;; 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) + (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" "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)) + (action_tile "accept" + "(setq gsepvor (get_tile \"sepvor\")) + (setq gsepnach (get_tile \"sepnach\")) + (setq gende (get_tile \"istende\")) + (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)))))) + (princ)) + +;; ============================================================ +;; TEIL 0b-3: GRUPPEN-DIALOGE (PENDING-QUEUE) +;; ============================================================ +;; Mehrere Fragen, die im Ablauf IMMER unmittelbar hintereinander kommen +;; (kein Zwischenschritt, keine Verzweigung dazwischen), werden im Wizard in +;; EINEM Dialog gemeinsam erfasst (siehe vflw-gruppe-* unten). Die +;; darunterliegende Aufruf-Reihenfolge in vf-linienzug-modus/vfl-* bleibt +;; dabei WOERTLICH UNVERAENDERT (weiterhin ein vfl-in-point/-string/-real/ +;; -int/-value-Aufruf pro Wert, in derselben Reihenfolge) - nur die HERKUNFT +;; des Werts aendert sich: statt live zu fragen (oder einen Einzel-Dialog zu +;; zeigen) wird der naechste Wert aus *vflw-pending* entnommen, den der +;; Gruppen-Dialog vorher dort abgelegt hat. Journal-Aufzeichnung passiert +;; weiterhin in JEDEM einzelnen vfl-in-*-Aufruf selbst - Editieren/Replay +;; bestehender Ketten ist dadurch unveraendert (siehe TEIL 0b-2). +;; Bricht der Nutzer den Gruppen-Dialog ab, bleibt *vflw-pending* leer - +;; die nachfolgenden vfl-in-*-Aufrufe fallen dann automatisch auf ihre +;; EINZEL-Dialoge zurueck (kein Sonderfall noetig). +(if (not (boundp '*vflw-pending*)) (setq *vflw-pending* nil)) +(defun vflw-pending-pop ( / v) + (if *vflw-pending* + (progn (setq v (car *vflw-pending*)) (setq *vflw-pending* (cdr *vflw-pending*)) (list v)) + nil)) +(defun vflw-pending-push-all (vals) (setq *vflw-pending* (append *vflw-pending* vals)) nil) + ;; --- Eingabe-Wrapper --- ;; kind steuert nur, wie ein FRISCH live erfasster Wert typisiert wird; beim ;; Replay wird der gespeicherte Wert unveraendert durchgereicht. (defun vfl-in-point (base prompt / popped v) (setq popped (if *vfl-replay-queue* (vfl-replay-pop) nil)) - (if popped (setq v (car popped)) (setq v (vfl-getpoint base prompt))) + (if popped + (setq v (car popped)) + (progn + (setq popped (vflw-pending-pop)) + (if popped (setq v (car popped)) (setq v (vfl-getpoint base prompt))))) (vfl-journal-record (if v "PT" "NIL") v) v) +;; Objektauswahl (Modus 2: Pfad-Objekte). Wie die anderen Wrapper repliziert +;; bzw. journalisiert - aber KEIN Wizard-Dialog (Objektwahl braucht wie +;; Punktwahl die Zeichnung, kein DCL-Fenster wuerde hier helfen). Beim Replay +;; werden die gespeicherten Handles zurueck in Enames aufgeloest; Handles +;; sind - anders als Enames - ueber Sitzungen hinweg stabil und damit fuer +;; die XDATA-Persistenz geeignet. Loest sich ein Handle nicht mehr auf (z.B. +;; weil der Nutzer die urspruengliche Pfad-Geometrie zwischenzeitlich +;; geloescht hat), wird das klar gemeldet statt eine unvollstaendige Auswahl +;; stillschweigend weiterzureichen. +(defun vfl-in-selection (filter / popped v handles h en k ss fehlt) + (setq popped (if *vfl-replay-queue* (vfl-replay-pop) nil)) + (if popped + (progn + (setq handles (car popped) v nil fehlt 0) + (foreach h handles + (setq en (vl-catch-all-apply 'handent (list h))) + (if (or (vl-catch-all-error-p en) (null en)) + (setq fehlt (1+ fehlt)) + (setq v (cons en v)))) + (setq v (reverse v)) + (if (> fehlt 0) + (alert (ssg-textf "vfl-m3-alert-objekte-fehlen" (list (itoa fehlt)))))) + (progn + (setq ss (ssget filter)) + (setq v nil) + (if ss + (progn + (setq k 0) + (while (< k (sslength ss)) + (setq v (cons (ssname ss k) v)) + (setq k (1+ k))) + (setq v (reverse v)))))) + (setq handles (mapcar (function (lambda (e) (cdr (assoc 5 (entget e))))) v)) + (vfl-journal-record (if v "OBJS" "NIL") handles) + v) + (defun vfl-in-string (prompt / popped v) (setq popped (if *vfl-replay-queue* (vfl-replay-pop) nil)) - (if popped (setq v (car popped)) (setq v (getstring prompt))) - ;; "" (Enter) ist ein gueltiger String, kein Abbruch -> "STR". + (if popped + (setq v (car popped)) + (progn + (setq popped (vflw-pending-pop)) + (if popped + (setq v (car popped)) + (setq v + (if (and *vfl-wizard-mode* *vflw-menu-optionen*) + (vflw-wahl prompt *vflw-menu-optionen* *vflw-menu-default*) + (getstring prompt)))))) + ;; "" (Enter/Abbruch) ist ein gueltiger String, kein Abbruch -> "STR". (vfl-journal-record (if (eq (type v) 'STR) "STR" "NIL") v) v) (defun vfl-in-real (prompt / popped v) (setq popped (if *vfl-replay-queue* (vfl-replay-pop) nil)) - (if popped (setq v (car popped)) (setq v (getreal prompt))) + (if popped + (setq v (car popped)) + (progn + (setq popped (vflw-pending-pop)) + (if popped + (setq v (car popped)) + (setq v (if *vfl-wizard-mode* (vflw-zahl prompt) (getreal prompt)))))) (vfl-journal-record (if v "REAL" "NIL") v) v) -(defun vfl-in-int (prompt / popped v) +(defun vfl-in-int (prompt / popped v vs) (setq popped (if *vfl-replay-queue* (vfl-replay-pop) nil)) - (if popped (setq v (car popped)) (setq v (getint prompt))) + (if popped + (setq v (car popped)) + (progn + (setq popped (vflw-pending-pop)) + (if popped + (setq v (car popped)) + (setq v + (if (and *vfl-wizard-mode* *vflw-menu-optionen*) + (progn + (setq vs (vflw-wahl prompt *vflw-menu-optionen* *vflw-menu-default*)) + (if (and vs (> (strlen vs) 0)) (atoi vs) nil)) + (getint prompt)))))) (vfl-journal-record (if v "INT" "NIL") v) v) +;; Menue-Wrapper: princ-Ausgabe der Optionen bleibt beim Aufrufer unveraendert +;; stehen (Konsolen-Fallback, de/en via ssg-text) - hier wird nur die +;; ABSCHLIESSENDE Eingabe-Zeile ersetzt. *vflw-menu-optionen*/-default sind +;; ueber die '/'-Lokalvariablen dynamisch nur waehrend dieses Aufrufs sichtbar +;; (AutoLISP dynamic scoping) und wirken daher ausschliesslich auf den EINEN +;; vfl-in-string/-int-Aufruf im Rumpf. +(defun vfl-menu (prompt option-labels default-idx / *vflw-menu-optionen* *vflw-menu-default*) + (setq *vflw-menu-optionen* option-labels) + (setq *vflw-menu-default* default-idx) + (vfl-in-string prompt)) +(defun vfl-menu-int (prompt option-labels default-idx / *vflw-menu-optionen* *vflw-menu-default*) + (setq *vflw-menu-optionen* option-labels) + (setq *vflw-menu-default* default-idx) + (vfl-in-int prompt)) + ;; Generischer Wrapper fuer eine Eingabe, die nicht direkt ein getXXX ist, ;; sondern das Ergebnis einer fragenden Hilfsfunktion (z.B. die gemeinsame ;; vf-frage-element-winkel). livefn ist ein aufrufbares Objekt ohne Argumente; @@ -205,7 +697,11 @@ ;; Replay aus der Queue geliefert (livefn wird dann NICHT aufgerufen). (defun vfl-in-value (kind livefn / popped v) (setq popped (if *vfl-replay-queue* (vfl-replay-pop) nil)) - (if popped (setq v (car popped)) (setq v (apply livefn nil))) + (if popped + (setq v (car popped)) + (progn + (setq popped (vflw-pending-pop)) + (if popped (setq v (car popped)) (setq v (apply livefn nil))))) (vfl-journal-record (if v kind "NIL") v) v) @@ -225,6 +721,10 @@ ;; --- Serialisierung (tagged, selbstbeschreibend) --- ;; Zeilenformat "kind:payload", Eintraege per "\n" verkettet. getstring/getreal ;; liefern nie ein Newline, daher ist "\n" ein sicherer Record-Trenner. +;; "OBJS" (Objektauswahl, Modus 2): Payload = kommagetrennte Liste von +;; Entity-Handles (Hex-Strings, kollidieren nie mit dem Komma-Trenner). +;; Handles bleiben - anders als Enames - ueber Sitzungen/Undo hinweg stabil +;; und sind damit die richtige Persistenzform fuer ssget-Ergebnisse. (defun vfl-entry->string (e / k v) (setq k (car e) v (cdr e)) (cond @@ -234,6 +734,7 @@ ((= k "INT") (strcat "INT:" (itoa v))) ((= k "STR") (strcat "STR:" v)) ((= k "STEP") (strcat "STEP:" v)) + ((= k "OBJS") (strcat "OBJS:" (vfl-strjoin v ","))) (t "NIL:"))) (defun vfl-string->entry (ln / p kind pay c) (setq p (vl-string-search ":" ln)) @@ -249,6 +750,7 @@ ((= kind "INT") (cons "INT" (atoi pay))) ((= kind "STR") (cons "STR" pay)) ((= kind "STEP") (cons "STEP" pay)) + ((= kind "OBJS") (cons "OBJS" (if (> (strlen pay) 0) (vfl-strsplit pay ",") nil))) (t (cons "NIL" nil)))))) (defun vfl-journal->string () (vfl-strjoin (mapcar 'vfl-entry->string (reverse *vfl-journal*)) "\n")) @@ -269,20 +771,26 @@ (setq s (substr s (1+ n)))) (if (> (strlen s) 0) (setq out (cons s out))) (reverse out)) -(defun vfl-journal-xdata-schreiben (ent / chunks appentry) +;; marker: "linienzug" (Modus 1, Sektions-Editieren via vfl-edit-ent) oder +;; "linienzug2" (Modus 2, vfl-edit-ent2 - voller Reset ohne Sektionswahl, +;; siehe dortiger Kommentar). Der Marker steht in der ersten 1000-Gruppe und +;; entscheidet beim Lesen (vfl-journal-xdata-lesen), welcher Editier-Pfad +;; greift. +(defun vfl-journal-xdata-schreiben (ent marker / chunks appentry) (if (null *vf-xdata-app*) (setq *vf-xdata-app* "SSG_VF_EDIT")) (regapp *vf-xdata-app*) (setq chunks (vfl-chunk-string (vfl-journal->string) 250)) (setq appentry (cons *vf-xdata-app* - (cons (cons 1000 "linienzug") + (cons (cons 1000 marker) (mapcar (function (lambda (c) (cons 1000 c))) chunks)))) (entmod (append (entget ent) (list (list -3 appentry)))) ent) +;; Rueckgabe: (marker . journal) oder nil (kein/unbekanntes Journal). (defun vfl-journal-xdata-lesen (ent / xd) (setq xd (vfs-xdata-lesen ent)) - (if (and xd (= (car xd) "linienzug")) - (vfl-string->journal (apply 'strcat (cdr xd))) + (if (and xd (member (car xd) '("linienzug" "linienzug2"))) + (cons (car xd) (vfl-string->journal (apply 'strcat (cdr xd)))) nil)) ;; --- Abbruch-Sicherung --- @@ -296,7 +804,7 @@ ;; Sonderfall mehr noetig). Aufgerufen aus dem *error*-Handler von ;; vf-linienzug-modus. (defun vfl-modus-abbruch-sichern (lastEnt vfl-nummer anzahl-gf anzahl-vf - startpunkt frame as-seite es-seite / + startpunkt frame as-seite es-seite marker / e cnt vfl-ins wickel-erg) (setq cnt 0 e (if lastEnt (entnext lastEnt) (entnext))) (while e (setq cnt (1+ cnt)) (setq e (entnext e))) @@ -315,7 +823,7 @@ (caddr startpunkt) (caddr (car frame)) (vfl-planar-dist startpunkt (car frame)) as-seite es-seite startpunkt lastEnt)) - (if vfl-ins (vfl-journal-xdata-schreiben vfl-ins)))) + (if vfl-ins (vfl-journal-xdata-schreiben vfl-ins marker)))) nil)) (if (vl-catch-all-error-p wickel-erg) (princ (ssg-textf "vfl-abbruch-wickeln-fehler" @@ -372,7 +880,7 @@ ;; Aus der Ergebnisliste von berechne-alle-winkel die GUELTIGEN Winkel filtern ;; und - bei mehreren - den Nutzer waehlen lassen. Rueckgabe: (winkel L_GF L_VF) ;; oder nil, wenn kein gueltiger Winkel existiert. -(defun vfl-waehle-winkel (ergebnis-liste / gueltige idx antwort e) +(defun vfl-waehle-winkel (ergebnis-liste / gueltige idx antwort e labels) (setq gueltige '()) (foreach e ergebnis-liste (if (and (cadddr e) (numberp (cadr e)) (numberp (caddr e)) @@ -384,12 +892,15 @@ (setq e (car gueltige)) (list (nth 0 e) (nth 1 e) (nth 2 e))) (t (princ (ssg-text "vfl-mehrere-winkel-header")) - (setq idx 1) + (setq idx 1 labels '()) (foreach e gueltige (princ (ssg-textf "vfl-winkel-option" (list idx (car e) (rtos (cadr e) 2 1) (rtos (caddr e) 2 1)))) + (setq labels (append labels + (list (ssg-textf "vfl-winkel-option" (list idx (car e) (rtos (cadr e) 2 1) (rtos (caddr e) 2 1)))))) (setq idx (1+ idx))) - (setq antwort (vfl-in-int (ssg-textf "vfl-prompt-wahl-bis-n" (list (length gueltige))))) + (setq antwort (vfl-menu-int (ssg-textf "vfl-prompt-wahl-bis-n" (list (length gueltige))) + labels 1)) (if (or (null antwort) (< antwort 1) (> antwort (length gueltige))) (setq antwort 1)) (setq e (nth (1- antwort) gueltige)) (list (nth 0 e) (nth 1 e) (nth 2 e))))) @@ -516,6 +1027,22 @@ (make-frame-from-dir endpunkt (hz-winkel->xu hz winkel)) ) +;; Ansicht auf Grundriss (Draufsicht, Welt-UCS) zoomen: nach jedem +;; Kettenglied mit Geometrieerzeugung wird die neu entstandene Strecke sonst +;; leicht aus dem sichtbaren Bereich oder in eine schraege 3D-Ansicht +;; hinauslaufen - der naechste Punkt (vfl-neue-linie-messen, siehe unten) +;; waere dann schwer/ungenau anzuwaehlen. _PLAN "_World" aendert nur die +;; ANSICHT, nicht das aktuell aktive BKS. Rein kosmetisch (per +;; vl-catch-all-apply abgesichert) - ein Fehler hier darf den eigentlichen +;; Kettenbau nie unterbrechen. +(defun vfl-view-refresh ( / ) + (vl-catch-all-apply + (function (lambda () + (command "_.PLAN" "_World") + (command "_.ZOOM" "_Extents"))) + nil) + (princ)) + ;; --- Hilfsfunktionen fuer die VF-Einheit --- ;; Planare (XY-)Distanz und Richtung zwischen zwei Punkten. @@ -553,6 +1080,7 @@ ;; vfl-projiziere-distanz). Foerderer-Maximallaenge 25 m: bei Ueberschreitung ;; wird die Eingabe abgelehnt und der Endpunkt erneut abgefragt. (defun vfl-neue-linie-messen (p-akt hz-vorgabe / p2 rad ux uy deltaL hz-aktuell ergebnis fertig) + (vfl-view-refresh) (setq fertig nil) (while (not fertig) (setq p2 (vfl-in-point p-akt @@ -681,10 +1209,13 @@ (defun vfl-baue-horizontal-koerper (frame hz dL ziel-modus gf2-laenge / pt m1 sep-vor pt-vor-bogen sep-nach ist-ende-antwort) (setq pt (car frame)) + (if *vfl-wizard-mode* + (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")) - (setq sep-vor (= (vfl-in-string (ssg-text "vfl-prompt-wahl-1-2-def2")) "1")) + (setq sep-vor (= (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 2) "1")) (if (and ziel-modus sep-vor) (setq dL (max 100.0 (- dL 300.0)))) ;; auf_3-Eintritt nur, wenn noch NICHT flach (sonst flache Zone fortsetzen). ;; dL ist die gewuenschte Reststrecke AB HIER (pt) - der reale Bogen- @@ -704,7 +1235,8 @@ (princ (ssg-text "vfl-sep-nach-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-nein")) - (setq sep-nach (= (vfl-in-string (ssg-text "vfl-prompt-wahl-1-2-def2")) "1")) + (setq sep-nach (= (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 2) "1")) (if (and ziel-modus sep-nach) (setq dL (max 100.0 (- dL 300.0)))) ;; Im Ziel-Modus: "Ist der Endpunkt der Foerderer?" JETZT abfragen (statt ;; erst danach in der Aufruferschleife) - der Ausgangs-Fussabdruck @@ -716,7 +1248,10 @@ (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-in-string (ssg-text "vfl-prompt-wahl-1-3-def2"))) + (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)) (cond ((= ist-ende-antwort "1") (setq dL (max 100.0 (- dL (car (get-bogen-mass bogen-ab 3)) 500.0 @@ -820,6 +1355,8 @@ (progn (princ (ssg-text "vfl-abgebrochen-kein-ziel")) nil) (progn (setq dL (car linie-mess) hzn (cadr linie-mess)) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (list (caddr (car frame))))) (setq hn (vfl-in-real (ssg-textf "vfl-prompt-hoehe-kettenende" (list (rtos (caddr (car frame)) 2 1))))) (if (null hn) (setq hn (caddr (car frame)))) @@ -939,7 +1476,10 @@ (princ (ssg-text "vfl-ja-nur-motorstation")) (princ (ssg-text "vfl-nein-weiterbauen")) (princ (ssg-text "vfl-ja-motorstation-kettenende")) - (setq antwort (vfl-in-string (ssg-text "vfl-prompt-wahl-1-3-def2"))) + (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)) ) ) (if (= antwort "1") @@ -954,7 +1494,8 @@ (princ (ssg-text "vfl-es-setzen-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-es-nein-zielpunkt")) - (setq es-antwort (vfl-in-string (ssg-text "prompt-wahl-1-2"))) + (setq es-antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-es-nein-zielpunkt")) 1)) (setq es-gewuenscht (/= es-antwort "2")) (if (not es-gewuenscht) (progn (setq save-eindx ein-dx save-eindz ein-dz) @@ -974,7 +1515,10 @@ (princ (ssg-text "vfl-opt-horizontaler-foerderer")) (princ (ssg-text "vfl-opt-vario-kurve")) (princ (ssg-text "vfl-opt-auf-ab-foerderer")) - (setq antwort (vfl-in-string (ssg-text "vfl-prompt-wahl-1-3-def3"))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") + (list (ssg-text "vfl-opt-horizontaler-foerderer") + (ssg-text "vfl-opt-vario-kurve") + (ssg-text "vfl-opt-auf-ab-foerderer")) 3)) (cond ;; --- Vario-Kurve (aendert hz) --- ((= antwort "2") @@ -1014,6 +1558,8 @@ (setq dL (car linie-mess) hzn (cadr linie-mess)) (if (> dL 1.0) (progn + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (list (caddr (car frame))))) (setq hn (vfl-in-real (ssg-textf "vfl-prompt-hoehe-endpunkt" (list (rtos (caddr (car frame)) 2 1))))) (if (null hn) (setq hn (caddr (car frame)))) @@ -1122,17 +1668,25 @@ ;; Interaktiv (i18n): GF-Bogen-Winkel + Seite abfragen, dann Kern aufrufen. (defun vfl-insert-gf-bogen (frame / bwinkel bseite antwort) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-winkel-seite-impl + (list "vfl-gf-bogen-winkel-header" + (list (ssg-text "vfl-winkel-30") (ssg-text "vfl-winkel-60") (ssg-text "vfl-winkel-90")) + "INT"))) (princ (ssg-text "vfl-gf-bogen-winkel-header")) (princ (ssg-text "vfl-winkel-30")) (princ (ssg-text "vfl-winkel-60")) (princ (ssg-text "vfl-winkel-90")) - (setq antwort (vfl-in-int (ssg-text "vfl-prompt-wahl-1-3-def3"))) + (setq antwort (vfl-menu-int (ssg-text "vfl-prompt-wahl-1-3-def3") + (list (ssg-text "vfl-winkel-30") (ssg-text "vfl-winkel-60") + (ssg-text "vfl-winkel-90")) 3)) (if (null antwort) (setq antwort 3)) (setq bwinkel (cond ((= antwort 1) 30) ((= antwort 2) 60) (t 90))) (princ (ssg-text "vfl-gf-bogen-seite-header")) (princ (ssg-text "gf-seite-links")) (princ (ssg-text "gf-seite-rechts")) - (setq antwort (vfl-in-string (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1)) (setq bseite (if (= antwort "2") "rechts" "links")) (vfl-insert-gf-bogen-block frame bwinkel bseite) ) @@ -1182,22 +1736,27 @@ ;; (siehe ks-normalize-name). ;; Interaktiv (i18n): Vario-Kurve-Winkel + Seite + Variante abfragen, dann Kern. (defun vfl-insert-vario-kurve (frame / kwinkel kseite kvariante antwort) + (if *vfl-wizard-mode* (vl-catch-all-apply 'vflw-gruppe-variokurve-impl nil)) (princ (ssg-text "vfl-variokurve-winkel-header")) (princ (ssg-text "vfl-opt1-90grad")) (princ (ssg-text "vfl-opt2-60grad")) (princ (ssg-text "vfl-opt3-30grad")) - (setq antwort (vfl-in-int (ssg-text "vfl-prompt-wahl-1-3-def1"))) + (setq antwort (vfl-menu-int (ssg-text "vfl-prompt-wahl-1-3-def1") + (list (ssg-text "vfl-opt1-90grad") (ssg-text "vfl-opt2-60grad") + (ssg-text "vfl-opt3-30grad")) 1)) (if (null antwort) (setq antwort 1)) (setq kwinkel (cond ((= antwort 1) 90) ((= antwort 2) 60) (t 30))) (princ (ssg-text "vfl-variokurve-seite-header")) (princ (ssg-text "gf-seite-links")) (princ (ssg-text "gf-seite-rechts")) - (setq antwort (vfl-in-string (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1)) (setq kseite (if (= antwort "2") "rechts" "links")) (princ (ssg-text "vfl-variokurve-variante-header")) (princ (ssg-text "vfl-variante-aussen")) (princ (ssg-text "vfl-variante-innen")) - (setq antwort (vfl-in-string (ssg-text "vfl-prompt-wahl-1-2-def2"))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") + (list (ssg-text "vfl-variante-aussen") (ssg-text "vfl-variante-innen")) 2)) (setq kvariante (if (= antwort "1") "aussen" "innen")) (vfl-insert-vario-kurve-block frame kwinkel kseite kvariante) ) @@ -1252,13 +1811,19 @@ ;; ES-Winkel (30/90) + Seite erst am Kettenende abfragen. Setzt *vfl-es-winkel* ;; und die ES-Masse (ein-dx/dz) fuer die Variante. Rueckgabe: Seite (links/rechts). (defun vfl-frage-es-seite ( / antwort es-seite) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-winkel-seite-impl + (list "vf-winkel-ein-header" + (list (ssg-text "vf-winkel-90") (ssg-text "vf-winkel-30")) + "STR"))) (setq *vfl-es-winkel* (vfl-in-value "STR" (function (lambda () (vf-frage-element-winkel "vf-winkel-ein-header"))))) ; 30/90 vor Seite (princ (ssg-text "gf-seite-ein-header")) (princ (ssg-text "gf-seite-links")) (princ (ssg-text "gf-seite-rechts")) - (setq antwort (vfl-in-string (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1)) (setq es-seite (if (= antwort "2") "rechts" "links")) (vf-set-es-masse *vfl-es-winkel* es-seite) es-seite @@ -1396,7 +1961,9 @@ (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-in-string (ssg-text "vfl-prompt-wahl-1-2-def2"))) + (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)) (setq res (vfl-vf-einheit frame hz richtung winkel L_GF L_VF (= antwort "1"))) (setq frame (nth 0 res) es-gewuenscht (nth 3 res)) ;; Kettenende? Bei auto-ende (Kettenende-Modus) ohne Frage direkt ES setzen. @@ -1413,7 +1980,9 @@ (princ (ssg-text "vfl-ist-kettenende-frage")) (princ (ssg-text "vfl-ja-separator-es")) (princ (ssg-text "vfl-nein-weiterbauen")) - (setq antwort (vfl-in-string (ssg-text "vfl-prompt-wahl-1-2-def2"))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") + (list (ssg-text "vfl-ja-separator-es") + (ssg-text "vfl-nein-weiterbauen")) 2)) ) ) ) @@ -1471,7 +2040,8 @@ (princ (ssg-text "vfl-sep-an-stelle-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-nein")) - (setq antwort (vfl-in-string (ssg-text "vfl-prompt-wahl-1-2-def2"))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 2)) (if (= antwort "1") (setq frame (vfl-insert-separator frame))) ) ) @@ -1539,10 +2109,13 @@ (function (lambda (msg) (setq *error* old-error) (vfl-modus-abbruch-sichern lastEnt vfl-nummer anzahl-gf anzahl-vf - startpunkt frame as-seite es-seite) + startpunkt frame as-seite es-seite "linienzug") (if (and (boundp '*ssg-start-stack*) *ssg-start-stack*) (ssg-end)) (princ)))) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-punkt-hoehe-impl + (list "vfl-prompt-startpunkt-kette" "Starthoehe (Z, mm):"))) (setq startpunkt (vfl-in-point nil (ssg-text "vfl-prompt-startpunkt-kette"))) (if (null startpunkt) (progn (princ (ssg-text "vfl-abgebrochen")) (exit))) ;; Hoehe (Z) des Startpunkts abfragen und in die Z-Koordinate uebernehmen. @@ -1551,10 +2124,13 @@ (if (null start-hoehe) (setq start-hoehe (caddr startpunkt))) (setq startpunkt (list (car startpunkt) (cadr startpunkt) start-hoehe)) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-as-impl (list "vfl-as-setzen-frage"))) (princ (ssg-text "vfl-as-setzen-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-as-nein")) - (setq antwort (vfl-in-string (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-as-nein")) 1)) (setq as-vorhanden (/= antwort "2")) (if as-vorhanden (progn @@ -1564,7 +2140,8 @@ (princ (ssg-text "vfl-aus-seite-header")) (princ (ssg-text "gf-seite-links")) (princ (ssg-text "gf-seite-rechts")) - (setq antwort (vfl-in-string (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1)) (setq as-seite (if (= antwort "2") "rechts" "links")) (vf-set-as-masse *vfl-as-winkel* as-seite) ; Masse fuer Variante ) @@ -1605,7 +2182,12 @@ (princ (ssg-text "vfl-menu-linie-vf-3")) (princ (ssg-text "vfl-menu-horizontal-vf-4")) (princ (ssg-text "vfl-menu-linie-ende-5")) - (setq antwort (vfl-in-string (ssg-text "vfl-prompt-wahl-1-5-def2"))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-5-def2") + (list (ssg-text "vfl-menu-gf-bogen-1") + (ssg-text "vfl-menu-linie-gf-2") + (ssg-text "vfl-menu-linie-vf-3") + (ssg-text "vfl-menu-horizontal-vf-4") + (ssg-text "vfl-menu-linie-ende-5")) 2)) (setq wahl (cond ((= antwort "1") "GF-Bogen") ((= antwort "3") "Linie-VF") ((= antwort "4") "Horizontal-VF") @@ -1617,7 +2199,11 @@ (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-in-string (ssg-text "vfl-prompt-wahl-1-4-def1"))) + (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)) (setq wahl (cond ((= antwort "2") "Linie-VF") ((= antwort "3") "Horizontal-VF") ((= antwort "4") (setq linie-ende-modus t) "Linie") @@ -1695,10 +2281,14 @@ ) ) (setq gf-ok t) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-gefaelle-impl (list (caddr p-aktuell)))) (princ (ssg-text "vfl-gefaelle-festlegen-header")) (princ (ssg-text "vfl-gefaelle-opt-hoehe")) (princ (ssg-text "vfl-gefaelle-opt-winkel")) - (setq antwort (vfl-in-string (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-gefaelle-opt-hoehe") + (ssg-text "vfl-gefaelle-opt-winkel")) 1)) (if (= antwort "2") (progn ;; Winkel direkt vorgeben - deltaH ergibt sich aus deltaL*tan(winkel). @@ -1755,7 +2345,10 @@ (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-in-string (ssg-text "vfl-prompt-wahl-1-3-def3"))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") + (list (ssg-text "vfl-kettenende-opt-ja-es") + (ssg-text "vfl-kettenende-opt-ja-ohne-es") + (ssg-text "vfl-kettenende-opt-nein")) 3)) (cond ((= antwort "1") (setq es-seite (vfl-frage-es-seite)) @@ -1789,6 +2382,8 @@ (if (< deltaL 1000.0) (princ (ssg-text "vfl-fehler-vf-kurz")) (progn + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (list (caddr p-aktuell)))) (setq hoehe-neu (vfl-in-real (ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos (caddr p-aktuell) 2 1))))) (if (null hoehe-neu) (setq hoehe-neu (caddr p-aktuell))) @@ -1855,6 +2450,8 @@ (list (rtos deltaL 2 0) (rtos deltaH 2 1)))) ) (progn + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (list (caddr p-aktuell)))) (setq hoehe-neu (vfl-in-real (ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos (caddr p-aktuell) 2 1))))) (if (null hoehe-neu) (setq hoehe-neu (caddr p-aktuell))) @@ -1907,7 +2504,10 @@ (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-in-string (ssg-text "vfl-prompt-wahl-1-3-def3"))) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") + (list (ssg-text "vfl-kettenende-opt-ja-es") + (ssg-text "vfl-kettenende-opt-ja-ohne-es") + (ssg-text "vfl-kettenende-opt-nein")) 3)) ) ) (cond @@ -1949,7 +2549,7 @@ startpunkt lastEnt)) ;; Eingabe-Journal am fertigen Block persistieren (Marker "linienzug" + ;; Chunks) -> spaeter per Doppelklick editierbar (vfl-edit-ent). - (if vfl-ins (vfl-journal-xdata-schreiben vfl-ins)) + (if vfl-ins (vfl-journal-xdata-schreiben vfl-ins "linienzug")) ;; Erfolgreicher Abschluss: *error* zuruecksetzen. (setq *error* old-error) @@ -1970,29 +2570,50 @@ ;; Glieder werden stumm abgespielt, danach laeuft die Eingabe interaktiv fuer ;; die geaenderten/neuen Glieder weiter. Vorbelegung im Dialog = voller Stand ;; -> Doppelklick + sofort OK setzt einen abgebrochenen Bau nahtlos fort. -(defun vfl-edit-ent (ent / journal glieder n i pos trunc) - (setq journal (vfl-journal-xdata-lesen ent)) - (if (null journal) +;; Marker-Dispatch: "linienzug" (Modus 1) -> abschnittsweises Zuruecksetzen +;; wie bisher; "linienzug2" (Modus 2) -> voller Reset ohne Sektionswahl +;; (vfl-edit-ent2) - Modus 2s Klassifizierungs-Schleife traegt keine +;; Glied-Marker, ein Sektions-Dialog wie bei Modus 1 ist dafuer (noch) nicht +;; vorgesehen. +(defun vfl-edit-ent (ent / xd marker journal glieder n i pos trunc) + (setq xd (vfl-journal-xdata-lesen ent)) + (if (null xd) (progn (alert (ssg-text "vfl-edit-kein-journal")) (exit))) - (setq glieder (vfl-journal-glieder journal)) - (setq n (length glieder)) - (princ (ssg-textf "vfl-edit-kette-header" (list (itoa n)))) - (setq i 1) - (foreach g glieder - (princ (strcat "\n " (itoa i) ") " (vfl-glied-label-text g))) - (setq i (1+ i))) - (setq pos (vfl-dlg-position glieder)) - (if (null pos) - (progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit))) - (setq trunc (vfl-journal-truncate journal pos)) - ;; Alten Block entfernen (wie Standard/Etage: entdel + kompletter Neuaufbau). - ;; Bricht der Neuaufbau selbst ab, wickelt vfl-modus-abbruch-sichern den - ;; Zwischenstand automatisch zu einem neuen Block - kein Sonderfall noetig. + (setq marker (car xd) journal (cdr xd)) + (if (= marker "linienzug2") + (vfl-edit-ent2 ent journal) + (progn + (setq glieder (vfl-journal-glieder journal)) + (setq n (length glieder)) + (princ (ssg-textf "vfl-edit-kette-header" (list (itoa n)))) + (setq i 1) + (foreach g glieder + (princ (strcat "\n " (itoa i) ") " (vfl-glied-label-text g))) + (setq i (1+ i))) + (setq pos (vfl-dlg-position glieder)) + (if (null pos) + (progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit))) + (setq trunc (vfl-journal-truncate journal pos)) + ;; Alten Block entfernen (wie Standard/Etage: entdel + kompletter Neuaufbau). + ;; Bricht der Neuaufbau selbst ab, wickelt vfl-modus-abbruch-sichern den + ;; Zwischenstand automatisch zu einem neuen Block - kein Sonderfall noetig. + (entdel ent) + (princ (ssg-textf "vfl-edit-abgespielt" (list (itoa pos) (itoa (- n pos))))) + ;; Behaltene Glieder abspielen, dann live weiterbauen. + (vfl-journal-replay-start trunc) + (vf-linienzug-modus))) + (princ)) + +;; Modus-2-Block per Doppelklick zuruecksetzen: voller Reset - die komplette +;; gespeicherte Eingabe (inkl. der gewaehlten Pfad-Objekte, siehe +;; vfl-in-selection) wird 1:1 stumm abgespielt, identischer Neuaufbau. Kein +;; Sektions-Dialog; der Nutzer kann den neu entstandenen Block danach ganz +;; normal weiterbearbeiten oder loeschen. +(defun vfl-edit-ent2 (ent journal) (entdel ent) - (princ (ssg-textf "vfl-edit-abgespielt" (list (itoa pos) (itoa (- n pos))))) - ;; Behaltene Glieder abspielen, dann live weiterbauen. - (vfl-journal-replay-start trunc) - (vf-linienzug-modus) + (princ (ssg-text "vfl-edit2-reset-info")) + (vfl-journal-replay-start journal) + (vf-linienzug-modus2) (princ)) ;; DCL-Dialog: Sektion waehlen, auf die die Kette zurueckgesetzt wird. @@ -2610,7 +3231,7 @@ aus ein first-line last-line frame deltaL br-winkel br-gf1 br-gf2 br-lvf br-richtn pt letzt-winkel vfl-nummer lastEnt anzahl-gf anzahl-vf - hoehe-bis soll-ende ist-ende + hoehe-bis soll-ende ist-ende old-error vfl-ins 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 @@ -2633,55 +3254,72 @@ ;; --- 1. Pfad-Objekte waehlen --- (princ (ssg-text "vfl-m3-pfad-waehlen")) - (setq ss (ssget '((0 . "LINE,ARC")))) + (setq ss (vfl-in-selection '((0 . "LINE,ARC")))) (if (null ss) (progn (princ (ssg-text "vfl-m3-keine-objekte")) (exit))) - (setq obj-liste '() k 0) - (repeat (sslength ss) - (setq obj-liste (cons (vlax-ename->vla-object (ssname ss k)) obj-liste)) - (setq k (1+ k))) + (setq obj-liste (mapcar 'vlax-ename->vla-object ss)) ;; --- 2. Startpunkt + Z + AS-Seite --- - (setq startpunkt (vfl-getpoint nil (ssg-text "vfl-m3-prompt-startpunkt"))) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-punkt-hoehe-impl + (list "vfl-m3-prompt-startpunkt" "Starthoehe (Z, mm):"))) + (setq startpunkt (vfl-in-point nil (ssg-text "vfl-m3-prompt-startpunkt"))) (if (null startpunkt) (progn (princ (ssg-text "gf-status-abgebrochen")) (exit))) - (setq start-hoehe (getreal (ssg-textf "vfl-prompt-hoehe-startpunkt" + (setq start-hoehe (vfl-in-real (ssg-textf "vfl-prompt-hoehe-startpunkt" (list (rtos (caddr startpunkt) 2 1))))) (if (null start-hoehe) (setq start-hoehe (caddr startpunkt))) (setq startpunkt (list (car startpunkt) (cadr startpunkt) start-hoehe)) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-as-impl (list "vfl-as-setzen-frage"))) (princ (ssg-text "vfl-as-setzen-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-m3-as-nein")) - (setq antwort (getstring (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-m3-as-nein")) 1)) (setq as-vorhanden (/= antwort "2")) (if as-vorhanden (progn - (setq *vfl-as-winkel* (vf-frage-element-winkel "vf-winkel-aus-header")) ; 30/90 vor Seite + (setq *vfl-as-winkel* + (vfl-in-value "STR" + (function (lambda () (vf-frage-element-winkel "vf-winkel-aus-header"))))) ; 30/90 vor Seite (princ (ssg-text "gf-seite-aus-header")) (princ (ssg-text "gf-seite-links")) (princ (ssg-text "gf-seite-rechts")) - (setq as-seite (if (= (getstring (ssg-text "prompt-wahl-1-2")) "2") "rechts" "links")) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1)) + (setq as-seite (if (= antwort "2") "rechts" "links")) (vf-set-as-masse *vfl-as-winkel* as-seite) ; Masse fuer Variante ) ) ;; --- 3. Endpunkt + Z + ES-Seite (NEU in Modus 3) --- - (setq endpunkt (vfl-getpoint nil (ssg-text "vfl-m3-prompt-endpunkt"))) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-punkt-hoehe-impl + (list "vfl-m3-prompt-endpunkt" "Zielhoehe (Z, mm):"))) + (setq endpunkt (vfl-in-point nil (ssg-text "vfl-m3-prompt-endpunkt"))) (if (null endpunkt) (progn (princ (ssg-text "gf-status-abgebrochen")) (exit))) - (setq end-hoehe (getreal (ssg-textf "vfl-m3-prompt-zielhoehe" + (setq end-hoehe (vfl-in-real (ssg-textf "vfl-m3-prompt-zielhoehe" (list (rtos (caddr endpunkt) 2 1))))) (if (null end-hoehe) (setq end-hoehe (caddr endpunkt))) (setq endpunkt (list (car endpunkt) (cadr endpunkt) end-hoehe)) + (if *vfl-wizard-mode* + (vl-catch-all-apply 'vflw-gruppe-as-impl (list "vfl-es-setzen-frage"))) (princ (ssg-text "vfl-es-setzen-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-es-nein-zielpunkt")) - (setq antwort (getstring (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-ja") (ssg-text "vfl-es-nein-zielpunkt")) 1)) (setq es-vorhanden (/= antwort "2")) (if es-vorhanden (progn - (setq *vfl-es-winkel* (vf-frage-element-winkel "vf-winkel-ein-header")) ; 30/90 vor Seite + (setq *vfl-es-winkel* + (vfl-in-value "STR" + (function (lambda () (vf-frage-element-winkel "vf-winkel-ein-header"))))) ; 30/90 vor Seite (princ (ssg-text "gf-seite-ein-header")) (princ (ssg-text "gf-seite-links")) (princ (ssg-text "gf-seite-rechts")) - (setq es-seite (if (= (getstring (ssg-text "prompt-wahl-1-2")) "2") "rechts" "links")) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1)) + (setq es-seite (if (= antwort "2") "rechts" "links")) (vf-set-es-masse *vfl-es-winkel* es-seite) ; Masse fuer Variante ) ) @@ -2716,11 +3354,12 @@ (setq nach-kurve nil)) (t (princ (ssg-text "vfl-m3-typ-gerade")) - (setq antwort (getstring (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list "GF (Neigungswinkel)" "VF (Bruecke)") 1)) (if (= antwort "2") (setq plan (cons (list "Linie" hz laenge "VF" nil) plan)) (progn - (setq winkel (getreal (ssg-text "vfl-m3-prompt-gf-neigung"))) + (setq winkel (vfl-in-real (ssg-text "vfl-m3-prompt-gf-neigung"))) (if (null winkel) (setq winkel 3.0)) (if (> winkel 3.0) (progn (princ (ssg-text "vfl-m3-hinweis-gf-max")) (setq winkel 3.0))) @@ -2730,11 +3369,14 @@ (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 (getstring (ssg-text "prompt-wahl-1-2"))) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list "GF-Bogen" "Vario-Kurve") 1)) (if (= antwort "2") (progn (princ (ssg-text "vfl-m3-variante-frage")) - (setq kv-variante (if (= (getstring (ssg-text "vfl-prompt-wahl-1-2-def2")) "1") "aussen" "innen")) + (setq kv-variante (if (= (vfl-menu (ssg-text "vfl-prompt-wahl-1-2-def2") + (list (ssg-text "vfl-variante-aussen") (ssg-text "vfl-variante-innen")) 2) + "1") "aussen" "innen")) (setq plan (cons (list "Bogen" hz laenge bwinkel bseite "Vario-Kurve" kv-variante) plan)) (setq nach-kurve t)) ; naechste Gerade automatisch VF (progn @@ -2837,6 +3479,18 @@ (setq lastEnt (vf-lastent-ohne-attribute)) (vfl-acc-reset) (setq anzahl-gf 0 anzahl-vf 0 frame nil) + ;; --- Abbruch-Sicherung ab hier scharf (analog Modus 1, siehe dortiger + ;; Kommentar) - Phase A (oben) baut noch keine Geometrie, ein Abbruch + ;; waehrend der Klassifizierungsfragen haette also ohnehin nichts zu + ;; wickeln. Ab Phase B kann jederzeit Geometrie entstehen. + (setq old-error *error*) + (setq *error* + (function (lambda (msg) + (setq *error* old-error) + (vfl-modus-abbruch-sichern lastEnt vfl-nummer anzahl-gf anzahl-vf + startpunkt frame as-seite es-seite "linienzug2") + (if (and (boundp '*ssg-start-stack*) *ssg-start-stack*) (ssg-end)) + (princ)))) ;; erste/letzte Gerade fuer AS/ES-Trimmung bestimmen (setq first-line -1 last-line -1 i 0) (while (< i n) @@ -2954,7 +3608,9 @@ ;; 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 (= (getstring (ssg-text "prompt-wahl-1-2")) "2") 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) "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))) @@ -3089,8 +3745,15 @@ ;; ---------- Block + Ist-Ziel-Report ---------- (setq hoehe-bis (caddr (car frame))) - (vfl-block-erstellen vfl-nummer anzahl-gf anzahl-vf (caddr startpunkt) hoehe-bis - (vfl-planar-dist startpunkt (car frame)) as-seite es-seite startpunkt lastEnt) + (setq vfl-ins + (vfl-block-erstellen vfl-nummer anzahl-gf anzahl-vf (caddr startpunkt) hoehe-bis + (vfl-planar-dist startpunkt (car frame)) as-seite es-seite startpunkt lastEnt)) + ;; Eingabe-Journal am fertigen Block persistieren (Marker "linienzug2") -> + ;; spaeter per Doppelklick editierbar (vfl-edit-ent2: voller Reset, kein + ;; Sektions-Dialog wie bei Modus 1 - siehe dortiger Kommentar). + (if vfl-ins (vfl-journal-xdata-schreiben vfl-ins "linienzug2")) + ;; Erfolgreicher Abschluss: *error* zuruecksetzen. + (setq *error* old-error) (setq soll-ende endpunkt ist-ende (car frame)) (princ "\n\n=========================================") (princ (ssg-text "vfl-m3-fertig-header")) diff --git a/Lisp/vf_standard.lsp b/Lisp/vf_standard.lsp index 237df93..1f781a4 100644 --- a/Lisp/vf_standard.lsp +++ b/Lisp/vf_standard.lsp @@ -1197,10 +1197,11 @@ ;; Marker (Linienzug/Altbestand) werden abgewiesen. (if (= (car xd) "etage") (progn (vfe-edit-ent ent) (ssg-end) (exit))) - ;; Linienzug-Bloecke tragen als Marker "linienzug" + serialisiertes Eingabe- - ;; Journal (vf_linienzug.lsp). Der Edit-Zweig laesst Glieder zuruecknehmen und - ;; baut die Kette per Replay neu auf. - (if (= (car xd) "linienzug") + ;; Linienzug-Bloecke tragen als Marker "linienzug" (Modus 1) oder + ;; "linienzug2" (Modus 2) + serialisiertes Eingabe-Journal (vf_linienzug.lsp). + ;; vfl-edit-ent liest den Marker selbst erneut und dispatcht intern weiter + ;; (Modus 1: Glieder zuruecknehmen + Replay; Modus 2: voller Reset). + (if (member (car xd) '("linienzug" "linienzug2")) (progn (vfl-edit-ent ent) (ssg-end) (exit))) (if (/= (car xd) "standard") (progn (alert (ssg-textf "vfs-edit-keine-xdata" (list bname))) (ssg-end) (exit))) diff --git a/dcl/vf_linienzug_wizard.dcl b/dcl/vf_linienzug_wizard.dcl new file mode 100644 index 0000000..caa3516 --- /dev/null +++ b/dcl/vf_linienzug_wizard.dcl @@ -0,0 +1,268 @@ +// ============================================================ +// vf_linienzug_wizard.dcl - VF Linienzug Assistent (Modus 1) +// Zwei GENERISCHE Einzel-Dialoge (vflw_zahl/vflw_wahl) fuer alle Fragen, die +// im Ablauf isoliert stehen, PLUS mehrere GRUPPEN-Dialoge weiter unten, die +// Fragen zusammenfassen, die immer unmittelbar hintereinander kommen (z.B. +// Startpunkt+Starthoehe, AS-Element Ja/Nein+Winkel+Seite). Kopfzeilen/ +// Optionslisten werden zur Laufzeit befuellt, siehe vf_linienzug.lsp, +// Abschnitte "WIZARD-EINGABE" und "GRUPPEN-DIALOGE". +// Die ORIGINALEN Konsolen-Fragen (princ + getstring/getreal/getint) bleiben +// im Code stehen (de/en ueber ssg-text/lang/*.json) - Umschalten zurueck auf +// reine Konsole: (setq *vfl-wizard-mode* nil) bzw. Befehl VF_WIZARD_AUS. +// Bricht der Nutzer einen Gruppen-Dialog ab, fallen die betroffenen Fragen +// automatisch auf die Einzel-Dialoge (vflw_zahl/vflw_wahl) zurueck. +// ============================================================ + +// Zahlen-Eingabe (ersetzt getreal/getint). "kopf" zeigt den kompletten +// Original-Prompt-Text (inkl. Default in eckigen Klammern) als Label. +vflw_zahl : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : edit_box { + key = "wert"; + label = ""; + edit_width = 16; + } + } + + ok_cancel; +} + +// Mehrfachauswahl (ersetzt eine princ-Menue-Liste + getstring/getint). +// "opts" wird zur Laufzeit per start_list/add_list mit den (bereits +// lokalisierten) Optionstexten befuellt - ein einziger Dialog fuer jede +// Options-Anzahl (2-5), analog zum bestehenden Muster in +// dcl/variofoerderer.dcl und dcl/vfl_edit.dcl. +vflw_wahl : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : popup_list { + key = "opts"; + label = ""; + width = 50; + } + } + + ok_cancel; +} + +// ============================================================ +// GRUPPEN-DIALOGE - fassen mehrere Fragen, die im Ablauf IMMER +// unmittelbar hintereinander kommen, in EINEM Bildschirm zusammen (statt je +// einem vflw_zahl/vflw_wahl-Dialog pro Frage). Aufgerufen aus den +// vflw-gruppe-*-Funktionen in vf_linienzug.lsp (Abschnitt "GRUPPEN-DIALOGE"). +// Punktwahl-Zeile (Button + Anzeige) NUR in vflw_punkt_zahl, wo tatsaechlich +// live gepickt wird: der Button schliesst den Dialog (done_dialog 2), DANACH +// laeuft (getpoint) auf der Kommandozeile - (getpoint) direkt aus einem +// action_tile-Callback heraus (Dialog bleibt offen) funktioniert in BricsCAD +// NICHT (kein Fokuswechsel zur Zeichnung, per Test bestaetigt). Die uebrigen +// Gruppen-Dialoge (Gefaelle, Ziel-Hoehe, Horizontal-Stueck) picken KEINEN +// Punkt - der Endpunkt ist an ihrer Aufrufstelle bereits ueber +// vfl-neue-linie-messen gemessen (nur X/Y, fuer die Segmentlaenge; die Hoehe +// dort ist ein unabhaengiger Zahlenwert) - sie zeigen deshalb bewusst KEINE +// Punkt-Zeile, die faelschlich eine hier moegliche Punktwahl suggerieren +// wuerde. +// ============================================================ + +// Punkt + EIN Zahlenfeld, mit Punktwahl-Button (siehe oben). Nur fuer +// "Kettenstart" (Startpunkt + Starthoehe, Modus 1) und Modus 2s +// Start-/Endpunkt - "kopf"/"wlabel" werden je Aufruf per set_tile passend +// beschriftet. +vflw_punkt_zahl : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : row { + : button { + key = "pick"; + label = "Punkt waehlen..."; + fixed_width = true; + width = 18; + } + : text { + key = "pt_anzeige"; + label = "(kein Punkt gewaehlt)"; + } + } + : text { + key = "wlabel"; + label = ""; + } + : edit_box { + key = "wert"; + label = ""; + edit_width = 10; + } + } + + ok_cancel; +} + +// 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. +vflw_as : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : toggle { + key = "setzen"; + label = "Ja, setzen"; + } + : popup_list { + key = "winkel"; + label = "Winkel:"; + width = 20; + } + : popup_list { + key = "seite"; + label = "Seite:"; + width = 20; + } + } + + ok_cancel; +} + +// 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. +vflw_winkel_seite : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : popup_list { + key = "winkel"; + label = "Winkel:"; + width = 20; + } + : popup_list { + key = "seite"; + label = "Seite:"; + width = 20; + } + } + + ok_cancel; +} + +// Vario-Kurve: Winkel + Seite + Variante (aussen/innen) in einem Bildschirm. +vflw_variokurve : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : popup_list { + key = "winkel"; + label = "Winkel:"; + width = 20; + } + : popup_list { + key = "seite"; + label = "Seite:"; + width = 20; + } + : popup_list { + key = "variante"; + label = "Variante:"; + width = 20; + } + } + + ok_cancel; +} + +// 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. +vflw_gefaelle : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : popup_list { + key = "modus"; + label = "Eingabe als:"; + width = 40; + } + : text { + key = "wlabel"; + label = ""; + } + : edit_box { + key = "wert"; + label = ""; + edit_width = 10; + } + } + + ok_cancel; +} + +// Horizontales Stueck: Separator-vor + Separator-nach + "Foerderer-Ende?" +// (3 Optionen) in einem Bildschirm. Kein Punkt-Feld - siehe Kopfkommentar +// oben. +vflw_horizontal : dialog { + label = "VarioFoerderer Assistent"; + + : column { + : text { + key = "kopf"; + label = ""; + width = 60; + } + : toggle { + key = "sepvor"; + label = "Separator VOR dem Stueck"; + } + : toggle { + key = "sepnach"; + label = "Separator NACH dem Stueck"; + } + : popup_list { + key = "istende"; + label = "Foerderer-Ende:"; + width = 45; + } + } + + ok_cancel; +} diff --git a/doc/variofoerderer.md b/doc/variofoerderer.md new file mode 100644 index 0000000..11b3111 --- /dev/null +++ b/doc/variofoerderer.md @@ -0,0 +1,500 @@ +# VarioFoerderer / Gefaellestrecke — Eingabe-Inventar und Ablauf + +Bestandsaufnahme aller Eingabemoeglichkeiten der Befehle `FOERDERANLAGE` +(`c:VarioFoerderer`, Typen Standard/Etage/Linienzug) und `GEFAELLESTRECKE` +(`c:GEFAELLESTRECKE`) — als Grundlage fuer eine GUI-Neugestaltung je Gruppe. +Stand: Code in `Lisp/vf_core.lsp`, `vf_standard.lsp`, `vf_etage.lsp`, +`vf_linienzug.lsp`, `Gefaellestrecke.lsp` und die zugehoerigen DCL-Dialoge +(`dcl/variofoerderer.dcl`, `dcl/gefaellestrecke.dcl`, `dcl/vfl_edit.dcl`, +`dcl/vf_linienzug_wizard.dcl`). + +## Wizard-Status (Umsetzung des Entscheidungsbaums, Abschnitt 10) + +Standard und Etage waren bereits DCL-Dialoge (Abschnitte 2-3). Der komplette +Linienzug-Hauptstrang (Blocke 31-46 in Abschnitt 10) laeuft jetzt ebenfalls +ueber DCL-Dialoge statt Konsole: +`dcl/vf_linienzug_wizard.dcl` stellt zwei generische Dialoge (Zahl-Eingabe, +Mehrfachauswahl) bereit, die von JEDER Konsolen-Frage in `vf_linienzug.lsp` +wiederverwendet werden (siehe dortiger Abschnitt "WIZARD-EINGABE"). Die +Original-Konsolen-Fragen (princ + getstring/getreal/getint, de/en ueber +`ssg-text`) bleiben unveraendert im Code stehen und sind die Grundlage der +Dialoge (Prompt-Text = Dialog-Kopfzeile, Menue-Optionen = Popup-Liste) - bei +Bedarf per Befehl `VF_WIZARD_AUS` (zurueck: `VF_WIZARD_AN`) sofort wieder +reine Konsole, ohne Codeaenderung. Journal-Replay (Editieren bestehender +Ketten ueber Doppelklick, `vfl-edit-ent`) ist davon unberuehrt: es liefert +seine Werte aus dem gespeicherten Journal, bevor der Wizard-Zweig ueberhaupt +erreicht wird. Jeder Wizard-Dialogaufruf ist zusaetzlich per +`vl-catch-all-apply` abgesichert und faellt bei jedem Fehler (fehlendes DCL, +falscher `DXFM_DCL`-Pfad etc.) automatisch auf die Konsolen-Frage zurueck. + +Linienzug Modus 2 (Pfad+Zielhoehe-Solver, Blocke 50-57) laeuft seit Kurzem +ebenfalls ueber `vfl-in-point`/`-real`/`-string`/`-value` UND eine neue +Objektauswahl-Wrapper-Funktion `vfl-in-selection` (fuer die Pfad-Objekte, +Block 50) - dadurch schreibt auch Modus 2 jetzt ein Eingabe-Journal als XDATA +(Marker `"linienzug2"`) und reagiert auf Doppelklick. Anders als Modus 1 +NICHT abschnittsweise editierbar (keine Glied-Marker in der Klassifizierungs- +Schleife) - Doppelklick baut die Kette stattdessen 1:1 aus dem gespeicherten +Journal neu auf ("voller Reset", `vfl-edit-ent2`), danach normal weiter +bearbeitbar/loeschbar. Die Pfad-Objektauswahl wird dabei als Liste stabiler +Entity-Handles gespeichert (neue Journal-Art `"OBJS"`) und beim Reset wieder +aufgeloest; wurden die urspruenglichen Linien/Boegen zwischenzeitlich +geloescht, meldet das der Reset klar statt eine unvollstaendige Kette zu +bauen. `vfl-in-selection` zeigt bewusst KEINEN Wizard-Dialog (Objektauswahl +braucht wie Punktwahl die Zeichnung). + +**Ansicht-Refresh vor jedem Folge-Punkt** (Modus 1): `vfl-neue-linie-messen` - +die einzige Stelle, ueber die JEDE Endpunkt-Abfrage fuer ein neues Glied +laeuft (Haupt-Menue UND VF-Einheit-Fortsetzung) - schaltet vor dem Pick per +`vfl-view-refresh` auf Grundriss-Ansicht (`_PLAN` `_World`) und zoomt auf +alles Sichtbare (`_ZOOM` `_Extents`), damit das zuletzt gebaute Stueck immer +sichtbar und der naechste Punkt treffsicher anwaehlbar ist. Aendert nur die +Ansicht, nicht das aktive BKS; rein kosmetisch und per `vl-catch-all-apply` +abgesichert. + +Nicht umgestellt (bleiben bewusst reine Konsole, siehe Abschnitt 6): Modus 3 +(Vorwaerts-Nachbau, Legacy - im Code selbst als "wird umgebaut" markiert, +Aufwand fuer bald ersetzten Code waere nicht sinnvoll) sowie die +Gefaellestrecke-Konsolenmodi 2/3. Punktwahl (`getpoint`) bleibt ausserhalb +von Gruppen-Dialogen unveraendert Konsole/Zeichnung - eine Maus-Punktauswahl +braucht keinen eigenen Dialog, das BricsCAD-Prompt an der Eingabezeile +leistet bereits die vom Nutzer gewuenschte "Punkt waehlen"-Statusmeldung. + +### Gruppen-Dialoge (mehrere Fragen in einem Bildschirm) + +Fragen, die im Ablauf IMMER unmittelbar hintereinander kommen (kein +Zwischenschritt, keine Verzweigung dazwischen), werden nicht mehr einzeln +nacheinander abgefragt, sondern in EINEM Dialog gemeinsam erfasst. Sechs +Gruppen-Dialoge PLUS die beiden generischen Einzel-Dialoge (siehe +`dcl/vf_linienzug_wizard.dcl`, Abschnitte "GRUPPEN-DIALOGE"/oben): + +| Gruppe | Felder in einem Bildschirm | Ersetzt (Einzel-Screens) | +|---|---|---| +| Kettenstart | Punkt (Button) + Starthoehe | Block 31 | +| AS-Element | Ja/Nein-Toggle + Winkel + Seite (Winkel/Seite deaktiviert, solange Toggle aus) | Block 32 (+33 bei Ja) | +| GF-Bogen | Winkel(30/60/90) + Seite | Block 35 | +| ES-Element (Kettenende) | Winkel(30/90) + Seite | Block 45 | +| Vario-Kurve | Winkel(90/60/30) + Seite + Variante(aussen/innen) | Teil von Block 46 | +| Gefaelle festlegen | Modus(Hoehe/Winkel) + EIN Wertfeld (Beschriftung wechselt mit dem Modus) | Teil von Block 36 | +| Ziel-Hoehe | Zielhoehe (generischer `vflw_zahl`-Dialog, an 4 Aufrufstellen wiederverwendet: Block 36 GF-Wechsel, 37, 41/vfl-body-abschluss, 42) | Je 1 Screen | +| Horizontales Stueck | Separator VOR + Separator NACH + Foerderer-Ende (3 Optionen) | Teil von Block 38 | + +**Punktwahl-Button nur bei "Kettenstart"** (bzw. bei Modus 2s Start-/ +Endpunkt): `(getpoint)` direkt aus einem offenen `action_tile`-Callback +heraus funktioniert in BricsCAD NICHT (kein Fokuswechsel zur Zeichnung, per +Test bestaetigt) - stattdessen schliesst der Button den Dialog +(`done_dialog 2`), `getpoint` laeuft danach ganz normal auf der +Kommandozeile, der Dialog wird mit dem Ergebnis neu geoeffnet +(`vflw-gruppe-punkt-hoehe-impl`, `(while (not fertig) ...)`-Schleife um +`new_dialog`/`start_dialog`). Die uebrigen Gruppen-Dialoge (Gefaelle, +Ziel-Hoehe, Horizontal-Stueck) zeigen bewusst KEINEN Punkt-Button: ihr +Endpunkt (nur X/Y, fuer die Segmentlaenge) ist an der jeweiligen +Aufrufstelle bereits VOR der Gruppe ueber `vfl-neue-linie-messen` gepickt - +dessen Z wird nirgends verwendet, die dort abgefragte Hoehe ist ein davon +unabhaengiger Zahlenwert (siehe Kommentar bei `vfl-neue-linie-messen`). + +Technisch: die zugrunde liegende Aufruf-Reihenfolge in `vf-linienzug-modus`/ +`vfl-*` bleibt woertlich unveraendert (weiterhin ein `vfl-in-point`/`-string`/ +`-real`/`-int`/`-value`-Aufruf pro Wert, Journal-Aufzeichnung inklusive) - ein +Gruppen-Dialog fuellt vor dieser Sequenz nur eine kleine Pending-Queue +(`*vflw-pending*`), aus der jeder einzelne Aufruf transparent seinen Wert +zieht, statt live zu fragen. Bricht der Nutzer einen Gruppen-Dialog ab, +bleibt die Queue leer - die betroffenen Fragen fallen dann automatisch auf +die bestehenden Einzel-Dialoge (`vflw_zahl`/`vflw_wahl`) zurueck, kein +Sonderfall noetig. + +Steuerelement-Kuerzel in den Tabellen: + +| Kuerzel | Bedeutung | +|---|---| +| Dropdown | Combobox/Popup-Liste mit fester Werteliste | +| Zahl | Zahlenfeld (mm oder Grad) | +| Text | Freitextfeld | +| Toggle | Checkbox/Toggle | +| Punktwahl | Mausklick in der Zeichnung (`getpoint`/`entsel`) — laesst sich nicht durch ein reines Formularfeld ersetzen | +| Button | Aktions-Button innerhalb eines Dialogs | +| Legacy | Nur noch ueber die Kommandozeile erreichbar, kein DCL-Dialog | + +--- + +## 1. Anlagen-Typ-Wahl (`FOERDERANLAGE`) + +`c:VarioFoerderer` fragt zuerst den Typ ab, sofern keine Vorauswahl +(`*vf-vorauswahl-typ*`) gesetzt ist. + +| Feld | Steuerelement | Werte | Default | +|---|---|---|---| +| Typ | Dropdown | Standard / Etage / Linienzug | Standard | + +--- + +## 2. VF Standard (`dcl/variofoerderer.dcl`) + +Zwei Dialoge nacheinander: erst Geometrie/Ausrichtung/Geruest (Dialog 1), danach +Winkel und Staustrecken-Verteilung (Dialog 2) — Dialog 2 wird erst nach der +Winkelberechnung befuellt, da seine Optionsliste von Dialog 1 abhaengt. + +### Dialog 1 — Basis (`variofoerderer_basis`) + +| Feld | Tile-Key | Steuerelement | Werte | Default | +|---|---|---|---|---| +| Horiz. Distanz DeltaL | `deltal` | Zahl (mm) | frei | 15000 | +| Hoehenunterschied DeltaH | `deltah` | Zahl (mm) | frei | 3000 | +| Foerderrichtung | `richtung` | Dropdown | Auf / Ab | Auf | +| Einfuegehoehe | `einfuegehoehe` | Zahl (mm) | frei | 0 | +| Fahrtrichtung | `fahrtrichtung` | Dropdown | 0 Grad (X+, Ost) / 90 Grad (Y+, Nord) / 180 Grad (X-, West) / 270 Grad (Y-, Sued) | 0 Grad | +| Seite | `seite` | Dropdown | Rechts / Links | Rechts | +| Motorseite | `motorseite` | Dropdown | Rechts / Links | Rechts | +| Darstellung | `dimension` | Dropdown | 3D / 2D | aktueller Modus | +| Geruest Einzelmodul | `geruest_einzelmodul` | Toggle | an / aus | an | +| Geruestoption | `geruest_typ` | Dropdown | siehe [Geruestoptionen](#9-wiederverwendete-bausteine) (4 Werte) | Schoenenberger Geruest | + +### Dialog 2 — Winkel/Verteilung (`variofoerderer_winkel`) + +| Feld | Tile-Key | Steuerelement | Werte | Default | +|---|---|---|---|---| +| Winkel | `winkel` | Dropdown | dynamisch berechnete, geometrisch gueltige Varianten (z.B. 3/6/.../horizontal), je mit L_GF/L_VF-Vorschau | kleinster gueltiger Winkel | +| Verteilung Staustrecken | `verteilung` | Dropdown | Gleichmaessig (L_GF1=L_GF2) / Vorne Minimum, hinten Rest / Hinten Minimum, vorne Rest / Eigene Werte | Gleichmaessig | +| L_GF1 vorne (manuell) | `lgf1_manuell` | Zahl (mm) | nur aktiv bei Verteilung "Eigene Werte" | L_GF / 2 | + +Vorgelagert (Konsole, vor Dialog 1): Eingabemodus-Frage "3D-Linie" vs. "Werte +manuell" — nur bei Wahl "2" oeffnen sich obige Dialoge, sonst laeuft der +komplette [Legacy-Konsolen-Pfad](#8-legacy-konsolen-pfad). Direkt vor Dialog 1 +wird zusaetzlich der Startpunkt (X/Y) per Punktwahl gewaehlt +(`vfs-standard-dialog-ablauf`, `Lisp/vf_standard.lsp:1069`); die Z-Hoehe kommt +aus dem Feld "Einfuegehoehe". + +--- + +## 3. VF Etage + +Nutzt exakt dieselben Dialoge wie VF Standard (`variofoerderer_basis` und +`variofoerderer_winkel`, siehe Abschnitt 2) — nur die interne +Geometrieberechnung unterscheidet sich (Etagen-Boegen statt gerader AS/ES- +Elemente). Vorgelagert: + +| Feld | Steuerelement | Werte | Default | +|---|---|---|---| +| Startpunkt (X/Y) | Punktwahl | Klick in der Zeichnung | 0,0,0 | + +Die Hoehe (Z) des Startpunkts kommt wie bei Standard aus dem Feld +"Einfuegehoehe" von Dialog 1 (`vfe-etage-dialog-ablauf`, +`Lisp/vf_etage.lsp:894`). + +--- + +## 4. Gefaellestrecke (GF) (`dcl/gefaellestrecke.dcl`) + +Ein Dialog fuer den manuellen Modus 1 (analog Kreisel-Dialog). + +### Dialog — Gefaellestrecke (`gefaellestrecke`) + +| Feld | Tile-Key | Steuerelement | Werte | Default | +|---|---|---|---|---| +| Abstand DeltaL | `deltal` | Zahl (mm) | frei | - | +| Einfuegehoehe | `einfuegehoehe` | Zahl (mm) | frei | - | +| Gefaellewinkel | `winkel` | Zahl (Grad) | 0 < Winkel <= 3 Grad | - | +| Fahrtrichtung | `fahrtrichtung` | Dropdown | 0 / 90 / 180 / 270 Grad | 0 Grad | +| Darstellung | `dimension` | Dropdown | 3D / 2D | aktueller Modus | +| AUS-Element — Winkel | `aus_winkel` | Dropdown | 90 Grad / 30 Grad | 90 Grad | +| AUS-Element — Seite | `aus_seite` | Dropdown | Links / Rechts | Links | +| EIN-Element — Winkel | `ein_winkel` | Dropdown | 90 Grad / 30 Grad | 90 Grad | +| EIN-Element — Seite | `ein_seite` | Dropdown | Links / Rechts | Links | +| Geruest Einzelmodul | `geruest_einzelmodul` | Toggle | an / aus | an | +| Geruestoption | `geruest_typ` | Dropdown | 4 Werte, siehe [unten](#9-wiederverwendete-bausteine) | Schoenenberger Geruest | +| VarioFoerderer daneben bauen | `build_vf` | Button | baut parallel 2000 mm VF, gegenlaeufig, steigend — keine Zusatzwerte | - | + +Das Winkel/Seite-Paar (`aus_winkel`/`aus_seite`, `ein_winkel`/`ein_seite`) +taucht identisch auch im Linienzug als AS-/ES-Element-Baustein auf (siehe +Abschnitt 5.2). + +Zusaetzlich als Legacy-Konsole vorhanden (kein Dialog): + +- **Modus 2** — Startpunkt/Endpunkt waehlen: 2x Punktwahl + Gefaellewinkel + (Zahl, aus DeltaH automatisch vorgeschlagen). +- **Modus 3** — Bestehenden Linienzug (Linien/Boegen) auswaehlen: Objektauswahl, + Winkel wird aus der Geometrie vorgeschlagen und kann per j/n bestaetigt oder + ueberschrieben werden. + +--- + +## 5. VF Linienzug — Kette (Modus 1, frei zeichnend) + +Kein Formular, sondern eine Serie von Konsolen-Abfragen, verzahnt mit +Punktwahl in der Zeichnung — der Nutzer baut die Kette Segment fuer Segment. +Enthaelt die Option "VF mit horizontalem Anfang". Fuer eine GUI heisst das: ein +Assistent/Wizard mit Zeichnungs-Interaktion, kein einmaliges Werteformular. + +### 5.1 Ablauf + +1. **Start**: Startpunkt der Kette (Punktwahl), Starthoehe (Zahl, Default = Z + des Punkts). +2. **AS-Element setzen?** Ja/Nein — bei Ja: Winkel (30/90 Grad) + Seite + (links/rechts), siehe Baustein 5.2. +3. **Naechstes Element waehlen** (wiederholt sich pro Segment), Menue mit bis + zu 5 Optionen: + - GF-Bogen (horizontale Kurve) -> Winkel 30/60/90 Grad + Seite links/rechts + - Neue Linie: GF (Gefaellestrecke) -> Endpunkt (Punktwahl), dann Zielhoehe + *oder* Neigungswinkel (siehe Baustein 5.2) + - Neue Linie: Ab/Auf VF (VarioFoerderer-Einheit) -> Endpunkt (Punktwahl) + + Zielhoehe (Zahl) + - Neue VF mit horizontalem Anfang (Horizontal-Stueck) -> Endpunkt + (Punktwahl) entlang der aktuellen Fahrtrichtung, danach Separator-vor/ + -nach-Fragen + - Neue Linie BIS Kettenende (danach automatisch Separator + ES-Element) +4. **Innerhalb einer VF-Einheit** (nach dem ersten Koerper) wird pro + weiterem Teilstueck erneut gefragt: *Ist der Endpunkt der Foerderer?* + - Ja, nur Motorstation + - Nein, weiterbauen -> als naechstes: horizontaler Foerderer / Vario-Kurve + (30/60/90 Grad + Seite + aussen/innen) / Auf-Ab-Foerderer + - Ja, Motorstation + Kettenende -> ES-Element setzen? Ja/Nein +5. **Separator-Fragen** (bei horizontalem Stueck): zusaetzlichen Separator + VOR? Ja/Nein · NACH? Ja/Nein. +6. **Ist das Kettenende?** nach jedem GF-Segment: Ja (ES-Element) / Ja (ohne + ES) / Nein, weiterbauen. +7. **Kettenende**: ES-Element setzen? Bei Ja: Winkel 30/90 Grad + Seite + links/rechts (gleicher Baustein wie AS-Element). + +Groessenlimits, die als Validierung statt als Eingabe wirken: VF-Einheit +< 1000 mm wird abgelehnt ("Umlenk + Motor"), Gesamtlaenge > 25 m wird +abgelehnt, GF-Neigung > 3 Grad wird abgelehnt bzw. auf 3 Grad begrenzt. + +### 5.2 Wiederkehrende Bausteine + +Diese vier Eingabegruppen tauchen mehrfach in der Kette auf (und teils auch in +GF/Standard) — lohnt sich als eigene GUI-Komponente. + +**AS-/ES-Element** + +| Feld | Steuerelement | Werte | +|---|---|---| +| Winkel | Dropdown | 90 Grad / 30 Grad | +| Seite | Dropdown | links / rechts | + +**GF-Bogen** + +| Feld | Steuerelement | Werte | +|---|---|---| +| Winkel | Dropdown | 30 / 60 / 90 Grad | +| Seite | Dropdown | links / rechts | + +**Vario-Kurve** + +| Feld | Steuerelement | Werte | +|---|---|---| +| Winkel | Dropdown | 90 / 60 / 30 Grad | +| Seite | Dropdown | links / rechts | +| Variante | Dropdown | Aussen / Innen | + +**Gefaelle festlegen (Linie "GF")** + +| Feld | Steuerelement | Werte | +|---|---|---| +| Endpunkt | Punktwahl | entlang Fahrtrichtung | +| Modus | Dropdown | Gegebene Zielhoehe / Neigungswinkel eingeben | +| -> Zielhoehe | Zahl (mm) | bei Modus "Zielhoehe" | +| -> Neigungswinkel | Zahl (Grad) | 0 < Winkel <= 3 Grad, bei Modus "Winkel" | + +--- + +## 6. VF Linienzug — Modus 2 und 3 (fortgeschritten / Legacy) + +Zwei alternative Einstiege in `c:VarioFoerderer` -> Typ "Linienzug". Beide +arbeiten auf bereits in der Zeichnung vorhandener Geometrie statt auf freier +Klick-Eingabe — fuer eine GUI eher Import/Solver-Werkzeuge als klassische +Formulare. + +### Modus 2 — Pfad + Zielhoehe (Solver) + +| Feld | Steuerelement | Werte | +|---|---|---| +| Pfad-Objekte | Objektauswahl | Linien + Boegen der geplanten Trasse | +| Startpunkt + Hoehe | Punktwahl + Zahl | hoehere Seite der Kette | +| Endpunkt + Zielhoehe | Punktwahl + Zahl | Ziel der Kette | +| Je gerades Segment: Typ | Dropdown | GF (Eingabe-Winkel) / VF (Bruecke) | +| -> GF-Neigung | Zahl (Grad) | Default 3 Grad, Maximum 3 Grad | +| Je Bogen-Segment: Typ | Dropdown | GF-Bogen / Vario-Kurve | +| -> Vario-Kurve-Variante | Dropdown | Aussen / Innen | +| GF-Verteilung | Dropdown | alles am Einlauf (GF1) / 1/2 GF1 + 1/2 GF2 | + +### Modus 3 — Vorwaerts-Nachbau (Legacy, wird umgebaut) + +| Feld | Steuerelement | Werte | +|---|---|---| +| Startpunkt (3D) | Punktwahl | KS_EIN AUS-Element / Kettenanfang | +| Gefaellewinkel | Zahl (Grad) | wird auch aus 2 gewaehlten 3D-Punkten vorgeschlagen | +| AUS-Element Seite | Dropdown | links / rechts | +| Separator vor EIN? | Dropdown | Ja/Nein | +| Einfuegen bestaetigen | Dropdown | Ja/Nein | + +--- + +## 7. Editieren / Fortsetzen / Zusammenfuegen + +**Linienzug editieren** (`dcl/vfl_edit.dcl`) + +| Feld | Steuerelement | Werte | +|---|---|---| +| Zuruecksetzen zu Sektion | Dropdown | jedes Journal-Glied der Kette (GF-Bogen, GF, VF, horizontal-VF, Linie bis Ende, offen) | + +Kuerzt die Kette stumm auf die gewaehlte Sektion, danach laeuft der normale +interaktive Linienzug-Ablauf weiter (Abschnitt 5). + +**Vario_Kette_Merge** + +| Feld | Steuerelement | Werte | +|---|---|---| +| Start-Block der Kette | Objektauswahl | ein VF_n/GF_n-Block, ab dem ueber KS_AUS->KS_EIN-Nachbarschaft zusammengefuehrt wird | + +Einzige Eingabe — Rest laeuft automatisch (Attribute aggregiert, Luecken +werden gemeldet). + +--- + +## 8. Legacy-Konsolen-Pfad + +Wird bei Standard/Etage durchlaufen, wenn auf die Eingabemodus-Frage *nicht* +"2" getippt wird (Enter/leer faellt ebenfalls hierher zurueck) — also aktuell +noch der Vorgabe-Pfad. Zwei Untermodi: + +**3D-Linie auswaehlen** + +| Feld | Steuerelement | Werte | +|---|---|---| +| Linie/Polylinie | Objektauswahl | liefert DeltaL, DeltaH, Fahrtrichtung automatisch aus der Geometrie | + +**Werte manuell eingeben** + +| Feld | Steuerelement | Werte | +|---|---|---| +| DeltaL / DeltaH | Zahl (mm) | Defaults 15000 / 3000 | +| Foerderrichtung | Dropdown | Auf/Ab | +| Startpunkt | Punktwahl | - | +| Fahrtrichtung | Dropdown | 0 / 90 / 180 / 270 Grad | + +Danach identisch fuer beide Untermodi: Seite (rechts/links) -> Winkelwahl, +falls mehrere gueltig sind (nummerierte Liste) -> Staustrecken-Verteilung (4 +Optionen, bei "Eigene Werte" zusaetzlich L_GF1 als Zahl) -> Bestaetigung +"Einfuegen? Ja/Nein". + +--- + +## 9. Wiederverwendete Bausteine + +**Geruestoptionen** (`*ssg-geruest-optionen*` in `ssg_core.lsp`, auch bei +Kreisel/Eckrad verwendet) + +| Feld | Steuerelement | Werte | Default | +|---|---|---|---| +| Geruest fuer Einzelmodul | Toggle | an / aus | an | +| Geruestoption | Dropdown | IPE-Geruest abgestuft / Obergeruest oben / Schoenenberger Geruest / nur Doppelrohrtraeger | Schoenenberger Geruest | + +--- + +## 10. Entscheidungsbaum + +Jeder Block ist ein moeglicher Wizard-Screen. "Weiter mit" listet die +Blocknummer(n), zu denen von hier aus verzweigt werden kann. Rueckverweise auf +eine bereits genannte, kleinere Nummer (z.B. 34 -> 35 -> 34) sind Schleifen +(iteratives Weiterbauen), keine Fehler in der Nummerierung. + +### Baum A — Befehl `FOERDERANLAGE` + +| Nr | Block | Eingaben | Weiter mit | +|---|---|---|---| +| 1 | Befehl waehlen | FOERDERANLAGE / GEFAELLESTRECKE | 2, 40 | +| 2 | Anlagen-Typ | Standard / Etage / Linienzug | 3, 3, 30 | +| 3 | Eingabemodus (nur Standard/Etage) | Konsole / Dialog | 4, 10 | +| 4 | Startpunkt waehlen | Punktwahl | 5 | +| 5 | Dialog "Basis" | DeltaL, DeltaH, Auf/Ab, Einfuegehoehe, Fahrtrichtung, Seite, Motorseite, 2D/3D, Geruest | 6 | +| 6 | Winkelberechnung (automatisch) | - | 7 | +| 7 | Dialog "Winkel/Verteilung" | Winkel, Verteilung, ggf. L_GF1 | 8 | +| 8 | Bau (automatisch) | - | ENDE | +| 10 | Eingabemodus Konsole | 3D-Linie / Werte | 11, 12 | +| 11 | 3D-Linie waehlen | Objektwahl -> DeltaL/DeltaH/Fahrtrichtung automatisch | 13 | +| 12 | Werte eingeben | DeltaL, DeltaH, Auf/Ab, Startpunkt, Fahrtrichtung | 13 | +| 13 | Seite waehlen | rechts/links | 14 | +| 14 | Winkel waehlen | automatisch bei 1 Treffer, sonst Liste | 16 | +| 16 | Staustrecken-Verteilung | 4 Optionen, ggf. L_GF1 manuell | 17 | +| 17 | Bestaetigung "Einfuegen?" | Ja/Nein | 8 | +| 30 | Linienzug-Modus | Manuell / Pfad+Zielhoehe / Vorwaerts-Nachbau | 31, 50, 55 | +| 31 | Startpunkt + Starthoehe | Punktwahl + Zahl | 32 | +| 32 | AS-Element setzen? | Ja/Nein | 33, 34 | +| 33 | AS-Element | Winkel 30/90, Seite | 34 | +| 34 | Naechstes Element waehlen | 5 Optionen | 35, 36, 37, 38, 39 | +| 35 | GF-Bogen | Winkel 30/60/90, Seite | 34 (Schleife) | +| 36 | GF | Endpunkt, Zielhoehe/Neigungswinkel | 41 | +| 37 | Auf/Ab-VF starten | Endpunkt, Zielhoehe | 42 | +| 38 | Horizontal-VF starten | Endpunkt (+ Separator vor/nach inline) | 42 | +| 39 | Bis Kettenende | Endpunkt | 45 | +| 41 | Kettenende-Frage (nach GF) | Ja+ES / Ja ohne ES / Nein | 45, ENDE, 34 (Schleife) | +| 42 | Ist Endpunkt der Foerderer? | nur Motor / weiterbauen / +Kettenende | 34, 46, 45 | +| 45 | ES-Element setzen | Winkel 30/90, Seite | ENDE | +| 46 | Sub-Element in VF-Einheit | horizontal / Vario-Kurve / Auf-Ab | 42 (Schleife) | +| 50 | Pfad-Objekte waehlen | Linien + Boegen | 51 | +| 51 | Startpunkt + Starthoehe | Punktwahl + Zahl | 52 | +| 52 | Endpunkt + Zielhoehe | Punktwahl + Zahl | 53 | +| 53 | je gerades Segment: Typ | GF/VF (+GF-Neigung) | 54 | +| 54 | je Bogen-Segment: Typ | GF-Bogen/Vario-Kurve (+aussen/innen) | 56 | +| 56 | GF-Verteilung | 2 Optionen | 57 | +| 57 | Bau (automatisch) | - | ENDE | +| 55 | Startpunkt | Punktwahl | 58 | +| 58 | Gefaellewinkel | Zahl, Vorschlag aus 2 Punkten | 59 | +| 59 | AUS-Element Seite | links/rechts | 60 | +| 60 | Separator vor EIN? | Ja/Nein | 61 | +| 61 | Bestaetigung "Einfuegen?" | Ja/Nein | ENDE | + +### Baum B — Befehl `GEFAELLESTRECKE` + +| Nr | Block | Eingaben | Weiter mit | +|---|---|---|---| +| 40 | GF-Modus | Dialog / Start+Endpunkt / Bestehenden Linienzug | 70, 75, 80 | +| 70 | Dialog "Gefaellestrecke" | DeltaL, Hoehe, Winkel, AUS/EIN Winkel+Seite, Geruest, Button "VF daneben bauen" | 71 | +| 71 | Bau (automatisch) | - | ENDE | +| 75 | Startpunkt | Punktwahl | 76 | +| 76 | Endpunkt | Punktwahl | 77 | +| 77 | AUS-Element | Winkel/Seite | 78 | +| 78 | EIN-Element | Winkel/Seite | 79 | +| 79 | Bestaetigung "Einfuegen?" | Ja/Nein | ENDE | +| 80 | Pfad-Objekte waehlen | Objektauswahl | 81 | +| 81 | Berechneten Winkel uebernehmen? | j/n (n -> Winkel-Zahl) | 82 | +| 82 | AUS-Element | Winkel/Seite | 83 | +| 83 | EIN-Element | Winkel/Seite | 84 | +| 84 | Bestaetigung "Einfuegen?" | Ja/Nein | ENDE | + +### Beispiel-Abfolgen + +- Standard, Dialog-Pfad: `1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8` +- Standard, Legacy-Konsole mit 3D-Linie: `1 -> 2 -> 3 -> 10 -> 11 -> 13 -> 14 -> 16 -> 17 -> 8` +- Etage, Dialog-Pfad: `1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8` +- Linienzug — AS-Element, GF, Auf/Ab-VF mit Zwischenkurve, Kettenende: + `1 -> 2 -> 30 -> 31 -> 32 -> 33 -> 34 -> 36 -> 41 -> 34 -> 37 -> 42 -> 46 -> 42 -> 45` +- Linienzug — horizontaler Anfang direkt bis Kettenende: + `1 -> 2 -> 30 -> 31 -> 32 -> 34 -> 38 -> 42 -> 45` +- Gefaellestrecke per Dialog: `1 -> 40 -> 70 -> 71` +- Gefaellestrecke ueber Start-/Endpunkt: `1 -> 40 -> 75 -> 76 -> 77 -> 78 -> 79` + +--- + +## 11. GUI-Konzept-Empfehlung (Assistent + Punktwahl) + +- Ein einziger schrittweiser Assistent ist sinnvoll — die Blocknummern in + Abschnitt 10 sind bereits fast 1:1 die Wizard-Screens. Verzweigungen/ + Schleifen (z.B. Linienzug 34<->35, 42<->46) werden zu bedingten Spruengen + zum passenden Screen statt einer starren linearen Abfolge. **Umgesetzt** + fuer den Linienzug-Hauptstrang (Blocke 31-46) — siehe "Wizard-Status" oben + und `dcl/vf_linienzug_wizard.dcl`. +- **Punktwahl-Integration**: ein Button pro Punkt-Feld, der im Ruhezustand + leer ist und nach Auswahl X/Y/Z daneben anzeigt. Klick aktiviert einen + "Punktwahl-Modus" mit Statuszeile/Hinweis am unteren Rand ("Punkt + waehlen..."), bis der Benutzer in die Zeichnung klickt — danach zurueck ins + Formular. Dieses Muster deckt alle "Punktwahl"-Felder im Entscheidungsbaum + ab. **Umsetzung:** bewusst NICHT als eigener DCL-Dialog gebaut — BricsCAD + zeigt den `getpoint`-Prompt bereits direkt am Fadenkreuz/an der + Befehlszeile, was exakt die gewuenschte "Punkt waehlen"-Statusmeldung ist; + ein zusaetzlicher Dialog wuerde hier nur im Weg stehen (siehe naechster + Punkt). +- **Einschraenkung**: Solange BricsCAD synchron auf `getpoint`/`entsel` + wartet, kann die Formular-Oberflaeche waehrend der Punktwahl nicht + gleichzeitig bedienbar sein — die Statuszeile ersetzt den heutigen + Konsolen-Prompt, das Formular selbst bleibt aber bis zur Auswahl gesperrt + (modal), genau wie heute die Kommandozeile blockiert. diff --git a/lang/de_DE.json b/lang/de_DE.json index 48eccdd..d0afd2a 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -55,6 +55,7 @@ "vfl-edit-kein-journal": "Dieser Linienzug-Block traegt kein Eingabe-Journal (Altbestand) und kann nicht schrittweise editiert werden.", "vfl-edit-kette-header": "\n\nLinienzug mit %1 Glied(ern):", "vfl-edit-abgespielt": "\n>>> %1 Glied(er) werden abgespielt, %2 zurueckgenommen - danach interaktiv weiter.", + "vfl-edit2-reset-info": "\n>>> Linienzug (Modus 2) wird mit den gespeicherten Angaben identisch neu aufgebaut...", "omni-alle-winkel": "alle Winkel", "omni-grad": " Grad", "omni-bogen-keine-gefunden": "Keine Boegen fuer %1%2 gefunden.", @@ -98,6 +99,7 @@ "vfl-m3-prompt-zielhoehe": "\nZiel-Hoehe (Z) des Endpunkts [%1]: ", "vfl-m3-fehler-nicht-sortierbar": "\nFEHLER: Pfad nicht sortierbar (haengt er lueckenlos zusammen?).", "vfl-m3-alert-eckwinkel": "Kein passender Bogen: Eck-Winkel %1 Grad ist nicht ~30/60/90.\nBitte die Winkel anpassen.", + "vfl-m3-alert-objekte-fehlen": "%1 der urspruenglich gewaehlten Pfad-Objekte wurden in der Zeichnung nicht mehr gefunden (vermutlich geloescht). Die Kette kann so nicht korrekt neu aufgebaut werden.", "vfl-m3-seg-gerade": "\n\nSegment %1/%2: Gerade L=%3 mm hz=%4", "vfl-m3-auto-vf": "\n (automatisch VF - Segment folgt direkt auf eine Vario-Kurve)", "vfl-m3-typ-gerade": "\n Typ? 1 = GF (Eingabe-Winkel) 2 = VF (Bruecke)", diff --git a/lang/en_GB.json b/lang/en_GB.json index 4bf1615..db57811 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -55,6 +55,7 @@ "vfl-edit-kein-journal": "This chain block carries no input journal (legacy) and cannot be edited step by step.", "vfl-edit-kette-header": "\n\nChain with %1 segment(s):", "vfl-edit-abgespielt": "\n>>> %1 segment(s) replayed, %2 undone - then continue interactively.", + "vfl-edit2-reset-info": "\n>>> Rebuilding this Modus-2 chain identically from the saved inputs...", "omni-alle-winkel": "all angles", "omni-grad": " deg", "omni-bogen-keine-gefunden": "No arcs found for %1%2.", @@ -98,6 +99,7 @@ "vfl-m3-prompt-zielhoehe": "\nTarget height (Z) of the end point [%1]: ", "vfl-m3-fehler-nicht-sortierbar": "\nERROR: path cannot be sorted (is it connected without gaps?).", "vfl-m3-alert-eckwinkel": "No matching arc: corner angle %1 deg is not ~30/60/90.\nPlease adjust the angles.", + "vfl-m3-alert-objekte-fehlen": "%1 of the originally selected path objects could no longer be found in the drawing (likely deleted). The chain cannot be rebuilt correctly like this.", "vfl-m3-seg-gerade": "\n\nSegment %1/%2: straight L=%3 mm hz=%4", "vfl-m3-auto-vf": "\n (automatic VF - segment follows directly after a Vario curve)", "vfl-m3-typ-gerade": "\n Type? 1 = GF (input angle) 2 = VF (bridge)", diff --git a/menu/SSG_LIB.cui b/menu/SSG_LIB.cui index 66e4675..3fa97d1 100644 --- a/menu/SSG_LIB.cui +++ b/menu/SSG_LIB.cui @@ -620,175 +620,175 @@ ^C^C(ssg-ensure "OmniModulInsert") OMNI_EDIT - + Marker einfuegen ^C^C(ssg-ensure "Tro_Edit") TRO_INSERT - + Marker bearbeiten ^C^C(ssg-ensure "Tro_Edit") TRO_EDIT - + Bearbeiten (Auto) ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT - + Verbindung einfuegen ^C^C(ssg-ensure "Connection_Edit") CONNECTION_INSERT - + Verbindung bearbeiten ^C^C(ssg-ensure "Connection_Edit") CONNECTION_EDIT - + Export Sivas - ^C^C(ssg-ensure "count_sep_scan") ZAEHLE_SEP_SCAN (ssg-ensure "export") EXPORTSIVAS + ^C^C(ssg-ensure "export") EXPORTSIVAS - + Export CSV ^C^C(ssg-ensure "export") EXPORTCSV - + Umschalten 2D und 3D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_SWITCH - + Alle Bloecke auf 2D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_ALL_2D - + Alle Bloecke auf 3D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_ALL_3D - + Sprache ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_SPRACHE - + Alle Tests ausfuehren ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) SSG_RUN_ALL_TESTS - + Kreisel ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_kreisel.lsp")) TEST_KREISEL - + Foerderer ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_foerderer.lsp")) TEST_FOERDERER - + Foerderer-Linienzug ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_linienzug.lsp")) TEST_LINIENZUG - + Omniflo ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo.lsp")) TEST_OMNIFLO - + Omniflo Strecke ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo_strecke.lsp")) TEST_OMNIFLO_STRECKE - + Gefaellestrecke ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_gefaellestrecke.lsp")) TEST_GEFAELLESTRECKE - + Mubea Gesamtmodell ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_mubea.lsp")) TEST_MUBEA - + HundM05 Kreisel-Abschnitt ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_hundm05.lsp")) TEST_HUNDM05 - + KS 2D/3D pruefen (CSV) ^C^C(load (strcat (getenv "DXFMAKRO") "/Lisp/ks_pruefung.lsp")) KS_PRUEFEN - + Export CSV/Sivas ALL ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_export_all.lsp")) TEST_EXPORT_ALL - + Kreisel bearbeiten (ssg-ensure "KreiselInsert") KreiselEdit - + Omniflo Element bearbeiten (ssg-ensure "OmniModulInsert") OMNI_EDIT - + Gefaellestrecke bearbeiten (ssg-ensure "Gefaellestrecke") GEFAELLESTRECKE_EDIT - + VarioFoerderer bearbeiten (ssg-ensure "VarioFoerderer") VARIOFOERDERER_EDIT - + TRO-Marker bearbeiten (ssg-ensure "Tro_Edit") TRO_EDIT - + Verbindung bearbeiten (ssg-ensure "Connection_Edit") CONNECTION_EDIT - + SSG Bearbeiten (Auto) (ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT @@ -806,10 +806,9 @@ - - - - + + + ILS @@ -1488,88 +1487,99 @@ + SPS + + + + SPS Schliessen + + + + + + TRO Marker einfuegen - - - - - - Marker bearbeiten - Bearbeiten (Auto) + Marker bearbeiten + + Bearbeiten (Auto) + + + + - + Connections Verbindung einfuegen - - - - - - Verbindung bearbeiten + + Verbindung bearbeiten + + + + Bearbeiten (Auto) - + - + Export Export Sivas - + Export CSV - - - - - - - Konfiguration - - Umschalten 2D und 3D + + + Konfiguration - Alle Bloecke auf 2D - - - - - - Alle Bloecke auf 3D + Umschalten 2D und 3D - Sprache + Alle Bloecke auf 2D + + Alle Bloecke auf 3D + + + + + + Sprache + + + + Konfiguration Schliessen @@ -1577,120 +1587,120 @@ - + Tests Alle Tests ausfuehren - + Kreisel - + Foerderer - + Foerderer-Linienzug - + Omniflo - + Omniflo Strecke - + Gefaellestrecke - + Mubea Gesamtmodell - + HundM05 Kreisel-Abschnitt - + KS 2D/3D pruefen (CSV) - + Export CSV/Sivas ALL - + - + POP501 SSG_LIB Edit Context Kreisel bearbeiten - + Omniflo Element bearbeiten - + Gefaellestrecke bearbeiten - + VarioFoerderer bearbeiten - + TRO-Marker bearbeiten - + Verbindung bearbeiten - + SSG Bearbeiten (Auto) - + diff --git a/menu/SSG_LIB.mnu b/menu/SSG_LIB.mnu index f5acc9f..1ea191e 100644 --- a/menu/SSG_LIB.mnu +++ b/menu/SSG_LIB.mnu @@ -126,6 +126,7 @@ [~APBW 110 R550/67,5 208x347]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_208 [<-~APBW 110 R550/67,5 58x497]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_58 [<-Element bearbeiten]^C^C(ssg-ensure "OmniModulInsert") OMNI_EDIT +[->SPS] [->TRO] [Marker einfuegen]^C^C(ssg-ensure "Tro_Edit") TRO_INSERT [Marker bearbeiten]^C^C(ssg-ensure "Tro_Edit") TRO_EDIT @@ -134,6 +135,7 @@ [Verbindung einfuegen]^C^C(ssg-ensure "Connection_Edit") CONNECTION_INSERT [Verbindung bearbeiten]^C^C(ssg-ensure "Connection_Edit") CONNECTION_EDIT [<-Bearbeiten (Auto)]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT +[<-SPS Schliessen]^C^C [->Export] [Export Sivas]^C^C(ssg-ensure "export") EXPORTSIVAS [<-Export CSV]^C^C(ssg-ensure "export") EXPORTCSV