diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp
index 26e9766..81368eb 100644
--- a/Lisp/vf_linienzug.lsp
+++ b/Lisp/vf_linienzug.lsp
@@ -683,13 +683,47 @@
;; 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)
+;; Vorgabewert aus einem Prompt ziehen, damit der Zahlen-Dialog sein Eingabe-
+;; feld damit vorbelegen kann. Die Konsolen-Prompts tragen ihn seit jeher in
+;; Klammern ("[3]", "<2154.0>"); im Dialog blieb das Feld trotzdem leer und
+;; der Wert war nur in der Kopfzeile ablesbar (Nutzer-Wunsch 2026-10-22:
+;; gleich eintragen). Bewusst GENERISCH statt an einer Aufrufstelle: dieselbe
+;; Luecke hatten alle Zahlen-Dialoge des Assistenten.
+;;
+;; Gesucht wird die LETZTE Klammergruppe, deren Inhalt eine Zahl ist - damit
+;; stoeren Klammern im uebrigen Text nicht. Beispiel:
+;; "Neigungswinkel (Grad, 0 < Winkel <= 3) [3]: " -> "3"
+;; Das "<" in "0 < Winkel" hat kein schliessendes ">" und faellt weg, "(Grad,
+;; ...)" ist keine Zahl. Rueckgabe: Zahl als String oder nil.
+(defun vflw-vorgabe-aus-prompt (prompt / i n c zu inhalt ergebnis)
+ (setq n (strlen prompt) i 1 ergebnis nil)
+ (while (<= i n)
+ (setq c (substr prompt i 1))
+ (if (or (= c "[") (= c "<"))
+ (progn
+ ;; vl-string-search zaehlt 0-basiert, substr 1-basiert: die 1-basierte
+ ;; Position i der oeffnenden Klammer ist als 0-basierter Startwert
+ ;; genau die Stelle DAHINTER.
+ (setq zu (vl-string-search (if (= c "[") "]" ">") prompt i))
+ (if zu
+ (progn
+ (setq inhalt (substr prompt (1+ i) (- zu i)))
+ (if (distof inhalt 2) (setq ergebnis inhalt))))))
+ (setq i (1+ i)))
+ ergebnis)
+
+(defun vflw-zahl-impl (prompt / dat dcl-pfad dlg-wert ergebnis vorgabe)
(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))
+ ;; Vorgabe ins Feld schreiben - "Ok Weiter" ohne Aenderung liefert damit
+ ;; denselben Wert wie frueher das leere Feld (dort griff der Default
+ ;; beim Aufrufer).
+ (setq vorgabe (vflw-vorgabe-aus-prompt prompt))
+ (if vorgabe (set_tile "wert" vorgabe))
(action_tile "accept" "(setq dlg-wert (get_tile \"wert\")) (done_dialog 1)")
(action_tile "cancel" "(done_dialog 0)")
(action_tile "back" "(done_dialog 2)")
@@ -914,8 +948,11 @@
;; meldet dann vfl-frage-as-winkel-seite-oder-achse auf der Konsole.
(if mit-achse
(progn
+ ;; Beim AS ist der Punkt der Kettenanfang, beim ES (Rueckwaerts-
+ ;; Bau) das Kettenende - die Beschriftung folgt der Kopfzeile.
(set_tile "start_anzeige"
- (strcat "Startpunkt: " (vflw-g-punkt-str achse-basis)))
+ (strcat (if (= kopf-key "vfl-es-setzen-frage") "Endpunkt: " "Startpunkt: ")
+ (vflw-g-punkt-str achse-basis)))
(if gpunkt
(set_tile "pt_anzeige"
(strcat (vflw-g-punkt-str gpunkt)
@@ -2032,6 +2069,16 @@
(defun vfl-in-point (base prompt)
(vfl-in-value "PT" (function (lambda () (vfl-getpoint base prompt)))))
+;; Wie vfl-in-point, aber der Cursor haengt auf einer ACHSE (SNAPANG+ORTHO,
+;; siehe vfl-getpoint-achse) statt frei in der Ebene. Fuer Punkte, deren
+;; Richtung bereits feststeht und bei denen der Klick nur noch die LAENGE
+;; beisteuert - dort fuehrt ein frei schwenkendes Gummiband sonst in die Irre
+;; (Nutzer-Befund 2026-10-22 beim Rueckwaerts-Bau: der Kettenanfang kann nur
+;; auf der Achse des Separator-KS_EIN liegen, die Gummiband-Linie zeigte aber
+;; schraeg daneben). Journal-Format unveraendert: ein "PT"-Eintrag.
+(defun vfl-in-point-achse (base prompt hz)
+ (vfl-in-value "PT" (function (lambda () (vfl-getpoint-achse base prompt hz)))))
+
;; 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
@@ -2147,6 +2194,33 @@
(setq *vflw-menu-radio* T)
(vfl-in-string prompt))
+;; Wie vfl-menu-radio, journalisiert aber den WERT der Auswahl statt des
+;; Auswahl-Index ("vor"/"rueck" statt "1"/"2"). Gebraucht, wo eine NEUE Frage
+;; VOR eine bestehende gesetzt wird: mit einem Index waere beim Replay nicht
+;; mehr unterscheidbar, ob der naechste Eintrag zur neuen oder zur alten Frage
+;; gehoert - die Folgefrage benutzt ja dieselben "1"/"2". Mit einem eigenen
+;; Wertevorrat sind die Mengen disjunkt und ein Blick per
+;; vfl-replay-peek-wert genuegt. Entspricht der Konvention "Werte
+;; selbstbeschreibend fuehren, nicht als positionsabhaengige Indizes"
+;; (CLAUDE.md) - dieselbe Begruendung wie bei vfl-menu-winkel.
+;; werte: Rueckgabewerte in der Reihenfolge der Labels.
+(defun vfl-menu-strwert (prompt option-labels werte default-idx frage-key /
+ *vflw-menu-optionen* *vflw-menu-default* *vflw-menu-frage*
+ *vflw-menu-radio*)
+ (setq *vflw-menu-optionen* option-labels)
+ (setq *vflw-menu-default* default-idx)
+ (setq *vflw-menu-frage* frage-key)
+ (setq *vflw-menu-radio* T)
+ (vfl-in-value "STR"
+ (function (lambda ( / i k)
+ (setq i (if (and (vfl-wizard-mode-p) *vflw-menu-optionen*)
+ (vflw-radio-wahl (ssg-text frage-key) *vflw-menu-optionen* *vflw-menu-default*)
+ (getstring prompt)))
+ (setq k (if (and i (/= i "")) (atoi i) *vflw-menu-default*))
+ (if (and (>= k 1) (<= k (length werte)))
+ (nth (1- k) werte)
+ (nth (1- *vflw-menu-default*) werte))))))
+
(defun vfl-menu-int (prompt option-labels default-idx frage-key /
*vflw-menu-optionen* *vflw-menu-default* *vflw-menu-frage*)
(setq *vflw-menu-optionen* option-labels)
@@ -5032,6 +5106,350 @@
)
)
+;; ==================================================================
+;; RUECKWAERTS BAUEN (Modus 1, Nutzer-Vorgabe 2026-10-22)
+;; ==================================================================
+;; Normalfall ist "vorwaerts": der geklickte Punkt ist der KettenANFANG, dort
+;; sitzt das AS-Element, und die Kette waechst von da weg - die Endhoehe ist
+;; das Ergebnis. Manchmal steht aber das ANDERE Ende fest (typisch: der
+;; Anschluss an einen Kreisel). Dann ist der geklickte Punkt das KS_AUS des
+;; ES-Elements, und gebaut wird von dort nach hinten.
+;;
+;; ANKER-ENTSCHEIDUNG (Nutzer, 2026-10-22): das ES wird ZUERST mit seinem
+;; KS_AUS exakt auf den geklickten Punkt gesetzt; alles Weitere wird daraus
+;; rueckwaerts bestimmt. Eine Rest-Ungenauigkeit landet damit am
+;; Kettenanfang, wo sie nicht stoert - genau spiegelbildlich zum
+;; Vorwaerts-Fall, wo das AS-KS_EIN der exakte Anker ist.
+;;
+;; Umfang zunaechst bewusst klein (Nutzer-Vorgabe): ES + EIN GF-Stueck
+;; (+ bei "Parallel zum Kreisel" ein Bogen davor), danach ist die Kette
+;; fertig. Die Spiegel-Frage "Ist das der Kettenanfang?" (mit optionalem
+;; AS-Element und Weiterbauen) ist bewusst NICHT eingebaut.
+;;
+;; Alle Bausteine sind GERADE bzw. haben einen messbaren Fussabdruck, darum
+;; wird nirgends "rueckwaerts eingefuegt": es wird der jeweilige
+;; START-Punkt ausgerechnet und dann ganz normal vorwaerts platziert. Das
+;; Ergebnis ist identisch, nutzt aber die erprobten Einfuege-Primitiven.
+
+;; ES-Winkel + Seite + Abfuehrungsachse (2. Punkt) - Spiegelbild von
+;; vfl-frage-as-winkel-seite-oder-achse. Die Achse ist hier NICHT optional:
+;; ohne Richtung laesst sich das ES gar nicht platzieren (vorwaerts kommt die
+;; Richtung aus dem ersten Streckenklick, den es hier nicht gibt).
+;; Setzt *vfl-es-winkel*, die ES-Masse (vf-set-es-masse) und
+;; *vfl-es-basis-hz*. Rueckgabe: Seite ("links"/"rechts") oder nil, wenn
+;; keine brauchbare Achse gewaehlt wurde.
+;; Fahrtrichtung ueber einen zweiten Punkt. Rueckgabe: hz in Grad oder nil.
+;; Eigene kleine Schale, weil sie an ZWEI Stellen gebraucht wird: mit
+;; ES-Element (dort bestimmt sie zugleich dessen Lage) und ohne ES-Element
+;; (dann endet die Kette direkt am geklickten Punkt, die Richtung muss aber
+;; trotzdem bekannt sein - vorwaerts kaeme sie aus dem ersten Streckenklick,
+;; den es rueckwaerts nicht gibt).
+(defun vfl-frage-fahrtrichtung-p2 (basis / p2)
+ (setq p2 (vfl-in-point basis (ssg-text "vfl-prompt-es-achse-p2")))
+ (if (and p2
+ (or (> (abs (- (car p2) (car basis))) 1e-9)
+ (> (abs (- (cadr p2) (cadr basis))) 1e-9)))
+ (progn
+ (setq *vfl-es-basis-hz* (vfl-planar-hz basis p2))
+ (princ (ssg-textf "vfl-es-basislinie-info" (list (rtos *vfl-es-basis-hz* 2 1))))
+ *vfl-es-basis-hz*)
+ (progn (princ (ssg-text "vfl-basislinie-punkte-gleich")) nil)))
+
+(defun vfl-frage-es-winkel-seite-achse (startpunkt / antwort es-seite)
+ (setq *vfl-es-basis-hz* nil)
+ (princ (ssg-text "vf-winkel-ein-header"))
+ (princ (ssg-text "vf-winkel-90"))
+ (princ (ssg-text "vf-winkel-30"))
+ (setq *vfl-es-winkel*
+ (vfl-in-value "STR"
+ (function (lambda () (vf-frage-element-winkel "vf-winkel-ein-header")))))
+ (princ (ssg-text "gf-seite-ein-header"))
+ (princ (ssg-text "gf-seite-links"))
+ (princ (ssg-text "gf-seite-rechts"))
+ (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2")
+ (list (ssg-text "gf-seite-links") (ssg-text "gf-seite-rechts")) 1
+ "gf-seite-ein-header"))
+ (setq es-seite (if (= antwort "2") "rechts" "links"))
+ (vf-set-es-masse *vfl-es-winkel* es-seite)
+ (if (vfl-frage-fahrtrichtung-p2 startpunkt) es-seite nil))
+
+;; Punkt um eine Strecke ENTGEGEN der Fahrtrichtung zurueckversetzen.
+;; laenge-planar = horizontale (Grundriss-)Laenge, winkel = Gefaelle in Grad
+;; (positiv = fallend). Vorwaerts gilt
+;; P_next = P + (L*cos(hz), L*sin(hz), -L*tan(winkel))
+;; - rueckwaerts also mit umgekehrtem Vorzeichen. Damit liegt der Startpunkt
+;; eines Bausteins fest, der an einem BEKANNTEN Endpunkt ankommen soll.
+(defun vfl-rueck-punkt (p hz laenge-planar winkel / rad radw)
+ (setq rad (* (float hz) (/ pi 180.0)))
+ (setq radw (* (float winkel) (/ pi 180.0)))
+ (list (- (car p) (* laenge-planar (cos rad)))
+ (- (cadr p) (* laenge-planar (sin rad)))
+ (+ (caddr p) (* laenge-planar (/ (sin radw) (cos radw))))))
+
+;; ES-Element so platzieren, dass sein KS_AUS EXAKT auf p-ende liegt und von
+;; dort in Richtung hz-achse weiterzeigt; davor den Separator, den das
+;; ES-Element im Vorwaerts-Bau immer mitbringt (vfl-insert-es-element).
+;;
+;; insert-block-mixed-to-ks dreht den Block IMMER so, dass sein KS_EIN auf den
+;; uebergebenen Rahmen passt - xy-ref/z-ref steuern nur die Verschiebung.
+;; Fuer "KS_AUS zeigt entlang hz-achse" muss der Rahmen also um den
+;; Grundriss-Schwenk des ES zurueckgedreht werden: hz-ein = hz-achse - es-turn
+;; (dieselbe Rechnung wie in vfl-insert-as-element, nur andersherum gebraucht).
+;; Rueckgabe: (frame-vor-dem-Separator hz-ein) - der Punkt, an dem das
+;; GF-Stueck ankommen muss.
+(defun vfl-rueck-es-setzen (es-w es-s p-ende hz-achse /
+ es-turn hz-ein w rad-w frame-ziel p-ein p-sep)
+ (setq es-turn (vf-element-plan-turn (strcat "ES_Element_" es-w "_" es-s)))
+ (setq hz-ein (- hz-achse es-turn))
+ (setq w (fix *vfk-gefaelle-winkel*))
+ ;; Zielrahmen traegt die Standard-Fallneigung: so kommt die Kette am ES an
+ ;; (vgl. vfl-insert-es-element, das den ES ebenfalls auf den geneigten
+ ;; Rahmen setzt).
+ (setq frame-ziel (make-frame-from-dir p-ende (hz-winkel->xu hz-ein w)))
+ (insert-block-mixed-to-ks (strcat "ES_Element_" es-w "_" es-s)
+ frame-ziel (caddr p-ende) "KS_AUS" "KS_AUS")
+ ;; KS_EIN des GERADE gesetzten ES messen - der Versatz KS_EIN->KS_AUS ist
+ ;; beim ES seitlich und laesst sich nicht aus dem Klickpunkt ableiten.
+ (setq p-ein (vfl-block-ks-punkt (vlax-ename->vla-object (entlast)) "KS_EIN"))
+ (if (null p-ein) (setq p-ein p-ende))
+ ;; Separator rueckwaerts davor: sein KS_AUS trifft das ES-KS_EIN.
+ (setq p-sep (vfl-rueck-punkt p-ein hz-ein
+ (* *vfk-separator-laenge* (cos (* (float w) (/ pi 180.0)))) w))
+ (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" p-sep hz-ein w
+ *vfk-separator-laenge* 0)
+ (if (boundp '*vfl-acc-separator*)
+ (setq *vfl-acc-separator* (1+ *vfl-acc-separator*)))
+ (list p-sep hz-ein))
+
+;; GF-Gerade rueckwaerts: sie soll an p-ziel ANKOMMEN, Grundrisslaenge
+;; laenge-planar, Neigung winkel. Rueckgabe: ihr Startpunkt (= neues
+;; Kettenende nach hinten).
+(defun vfl-rueck-gf (p-ziel hz laenge-planar winkel / p-start)
+ (setq p-start (vfl-rueck-punkt p-ziel hz laenge-planar winkel))
+ (vfl-insert-gf-segment p-start hz laenge-planar winkel)
+ (vfl-acc-gf-seg (/ laenge-planar (cos (* (float winkel) (/ pi 180.0)))) winkel)
+ p-start)
+
+;; ------------------------------------------------------------------
+;; Rueckwaerts-Ablauf (Treiber). Nutzt - wie die uebrigen Bau-Zweige - die
+;; dynamisch sichtbaren Lokalvariablen des Aufrufers vf-linienzug-modus
+;; (startpunkt = geklicktes KETTENENDE, frame, p-aktuell, anzahl-gf,
+;; es-seite, fertig, letzter-typ).
+(defun vfl-rueckwaerts-bauen ( / es-w es-s es-vorhanden hz-achse erg p-ziel hz-ein
+ modus gf-max-winkel winkel laenge deltaH
+ p-pick p-start h-start rad
+ bogen-seite bogen-winkel bogen-turn hz-bogen
+ kandidaten tol w
+ abstand perp-ziel perp-bogen nx ny rad-a bw
+ acc-gfbogen-save acc-sep-save probe-checkpoint
+ probe-frame basis-frame dxp dyp dzp p-bogen-start)
+ ;; --- ES-Element: "setzen?" + Winkel + Seite + Fahrtrichtung ---
+ ;; WICHTIG: vflw-gruppe-as-impl legt VIER Werte in die Pending-Queue
+ ;; (ja/nein, Winkel, Seite, Punkt). Die Ja/Nein-Antwort MUSS hier zuerst
+ ;; konsumiert werden - fehlt dieser Schritt, rutscht alles um eine Position
+ ;; und der Winkel bekommt die "1" der Ja/Nein-Frage (realer Fehler
+ ;; 2026-10-22: Blockname "ES_Element_1_links").
+ (if (vfl-wizard-aktiv)
+ (vl-catch-all-apply 'vflw-gruppe-as-impl (list "vfl-es-setzen-frage" startpunkt)))
+ (princ (ssg-text "vfl-es-setzen-frage"))
+ (princ (ssg-text "vfl-ja"))
+ (princ (ssg-text "vfl-nein"))
+ (setq es-vorhanden
+ (/= "2" (vfl-menu-radio (ssg-text "prompt-wahl-1-2")
+ (list (ssg-text "vfl-ja") (ssg-text "vfl-nein")) 1
+ "vfl-es-setzen-frage")))
+ (setq w (fix *vfk-gefaelle-winkel*))
+ (if es-vorhanden
+ (progn
+ (setq es-s (vfl-frage-es-winkel-seite-achse startpunkt))
+ (if (null es-s) (progn (princ (ssg-text "vfl-abgebrochen")) (exit)))
+ (setq es-seite es-s)
+ (setq es-w (vfl-es-winkel))
+ (setq hz-achse *vfl-es-basis-hz*)
+ ;; ES + Separator setzen - Anker: KS_AUS exakt auf dem geklickten Punkt.
+ (setq erg (vfl-rueck-es-setzen es-w es-s startpunkt hz-achse))
+ (setq p-ziel (nth 0 erg) hz-ein (nth 1 erg)))
+ (progn
+ ;; Ohne ES endet die Kette direkt am geklickten Punkt; die Richtung
+ ;; muss trotzdem bekannt sein.
+ (setq hz-achse (vfl-frage-fahrtrichtung-p2 startpunkt))
+ (if (null hz-achse) (progn (princ (ssg-text "vfl-abgebrochen")) (exit)))
+ (setq p-ziel startpunkt hz-ein hz-achse)))
+ (setq gf-max-winkel (float (ssg-cfg-or "vario" "gefaelle_winkel" 3)))
+ ;; --- Nur EINE Element-Option (Nutzer-Vorgabe): Neue Linie GF ---
+ ;; vfl-menu-radio statt vfl-menu: Radio-Buttons statt Auswahlliste, wie bei
+ ;; den uebrigen kurzen Entscheidungen im Assistenten (Nutzer-Wunsch
+ ;; 2026-10-22). Journal-Semantik ist identisch - derselbe STR-Eintrag.
+ (princ (ssg-text "vfl-naechstes-element-header"))
+ (princ (ssg-text "vfl-rueck-menu-linie-gf"))
+ (vfl-menu-radio (ssg-text "prompt-wahl-1-2")
+ (list (ssg-text "vfl-rueck-menu-linie-gf")) 1 "vfl-naechstes-element-header")
+ ;; --- Laengen-Frage: drei Optionen (Nutzer-Vorgabe) ---
+ ;; "Parallel zum Kreisel" braucht das ES als Bezug (sein Grundriss-Schwenk
+ ;; bestimmt den Bogen) - ohne ES-Element entfaellt die Option.
+ (princ (ssg-text "vfl-gf-laenge-modus-header"))
+ (princ (ssg-text "vfl-rueck-laenge-opt-anfangspunkt"))
+ (princ (ssg-text "vfl-rueck-laenge-opt-anfangshoehe"))
+ (if es-vorhanden (princ (ssg-text "vfl-gf-laenge-modus-opt-parallel")))
+ (setq modus (vfl-menu-radio (ssg-text "prompt-wahl-1-2")
+ (if es-vorhanden
+ (list (ssg-text "vfl-rueck-laenge-opt-anfangspunkt")
+ (ssg-text "vfl-rueck-laenge-opt-anfangshoehe")
+ (ssg-text "vfl-gf-laenge-modus-opt-parallel"))
+ (list (ssg-text "vfl-rueck-laenge-opt-anfangspunkt")
+ (ssg-text "vfl-rueck-laenge-opt-anfangshoehe"))) 1
+ "vfl-gf-laenge-modus-header"))
+ (cond
+ ;; --- Option 3: Parallel zum Kreisel (Spiegelbild von
+ ;; vfl-gf-parallel-kreisel) ---
+ ((= modus "3")
+ ;; Bogen zur GEGENSEITE der ES-Seite, Winkel so, dass er den
+ ;; Grundriss-Schwenk des ES aufhebt - identische Regel wie vorwaerts,
+ ;; nur mit es-turn statt as-turn. Ergibt mit den vorhandenen Bausteinen
+ ;; die Nutzer-Tabelle: ES 30 links -> 30-Grad-Bogen rechts usw.
+ (setq bogen-seite (if (= es-s "rechts") "links" "rechts"))
+ (setq kandidaten '())
+ (foreach bw *vfk-gf-bogen-winkel*
+ (setq kandidaten
+ (cons (cons bw (vf-element-plan-turn (gf-bogen-blockname bw bogen-seite)))
+ kandidaten)))
+ (setq tol 2.0) ; wie in vfl-qc-linie-mit-gf
+ (setq bogen-winkel
+ (vfl-par-bogen-waehlen
+ (vf-element-plan-turn (strcat "ES_Element_" es-w "_" es-s))
+ (reverse kandidaten) tol))
+ (if (null bogen-winkel)
+ (vfl-meldung (ssg-textf "vfl-par-kein-bogen"
+ (list (rtos (vf-element-plan-turn
+ (strcat "ES_Element_" es-w "_" es-s)) 2 1)
+ bogen-seite)))
+ (progn
+ (setq abstand (vfl-in-real (ssg-text "vfl-par-prompt-abstand")))
+ (if (or (null abstand) (<= (abs abstand) 0.0))
+ (princ (ssg-text "vfl-abgebrochen"))
+ (progn
+ ;; Normale zur Abfuehrungsachse; alle Querversatz-Werte beziehen
+ ;; sich auf den geklickten Punkt (= ES-KS_AUS, perp = 0).
+ (setq rad-a (* (float hz-achse) (/ pi 180.0)))
+ (setq nx (- (sin rad-a)) ny (cos rad-a))
+ (setq perp-ziel (+ (* (- (car p-ziel) (car startpunkt)) nx)
+ (* (- (cadr p-ziel) (cadr startpunkt)) ny)))
+ ;; Bogen-Querversatz messen - Probe auf GENAU dem Rahmen, auf dem
+ ;; der echte Bogen spaeter sitzt (idealisierter Gefaelle-Rahmen,
+ ;; siehe gleichlautende Begruendung in vfl-gf-parallel-kreisel).
+ ;;
+ ;; RUECKWAERTS-BESONDERHEIT: der Bogen sitzt VOR dem GF-Stueck,
+ ;; sein AUSGANG muss also auf der GF-Richtung hz-ein liegen.
+ ;; insert-block-ks-to-ks richtet aber immer den EINGANG am
+ ;; uebergebenen Rahmen aus - der Eingang muss daher um den
+ ;; Bogenschwenk vorgedreht werden: hz-bogen = hz-ein - bogen-turn.
+ ;; Ohne diese Drehung zeigt der Bogen-Ausgang um genau den
+ ;; Bogenwinkel neben der GF-Achse und die KS treffen sich nicht
+ ;; (realer Fehler 2026-10-22). Vorwaerts (vfl-gf-parallel-kreisel)
+ ;; tritt das nicht auf: dort folgt der Bogen dem GF-Stueck, sein
+ ;; Eingang liegt also ohnehin schon auf der GF-Richtung.
+ (setq bogen-turn (cdr (assoc bogen-winkel kandidaten)))
+ (setq hz-bogen (- hz-ein bogen-turn))
+ (setq acc-gfbogen-save *vfl-acc-gfbogen* acc-sep-save *vfl-acc-separator*)
+ (setq probe-checkpoint (ssg-lastent-ohne-attribute))
+ (setq basis-frame (make-frame-from-dir p-ziel (hz-winkel->xu hz-bogen w)))
+ (setq probe-frame (vfl-insert-gf-bogen-block basis-frame bogen-winkel bogen-seite))
+ (setq dxp (- (car (car probe-frame)) (car (car basis-frame))))
+ (setq dyp (- (cadr (car probe-frame)) (cadr (car basis-frame))))
+ (setq dzp (- (caddr (car probe-frame)) (caddr (car basis-frame))))
+ (vfl-loesche-seit probe-checkpoint)
+ (setq *vfl-acc-gfbogen* acc-gfbogen-save *vfl-acc-separator* acc-sep-save)
+ (setq perp-bogen (+ (* dxp nx) (* dyp ny)))
+ ;; Querversatz des GF-Stuecks je Laengeneinheit: es laeuft auf
+ ;; hz-ein, die Achse auf hz-achse - die Differenz ist genau der
+ ;; ES-Schwenk. Rueckwaerts gezaehlt kehrt sich das Vorzeichen um.
+ (setq laenge (vfl-par-gf-laenge abstand perp-ziel (- perp-bogen)
+ (sin (* (- hz-achse hz-ein) (/ pi 180.0)))))
+ (cond
+ ((null laenge) (vfl-meldung (ssg-text "vfl-par-kein-versatz")))
+ ((< laenge 1.0)
+ (vfl-meldung (ssg-textf "vfl-par-zu-klein"
+ (list (rtos (abs abstand) 2 1)
+ (rtos (abs (- perp-ziel perp-bogen)) 2 1)))))
+ (t
+ (setq p-start (vfl-rueck-gf p-ziel hz-ein laenge w))
+ (setq anzahl-gf (1+ anzahl-gf))
+ ;; Bogen rueckwaerts: sein KS_AUS muss den GF-Start treffen -
+ ;; also um den GEMESSENEN Versatz (inkl. Hoehe) zurueckgesetzt.
+ (setq p-bogen-start (list (- (car p-start) dxp)
+ (- (cadr p-start) dyp)
+ (- (caddr p-start) dzp)))
+ ;; Gleiche Eingangsdrehung wie bei der Probe (s.o.) - nur so
+ ;; passt der gemessene Versatz und der Ausgang landet auf der
+ ;; GF-Achse.
+ (setq basis-frame (make-frame-from-dir p-bogen-start (hz-winkel->xu hz-bogen w)))
+ (setq frame (vfl-insert-gf-bogen-block basis-frame bogen-winkel bogen-seite))
+ (setq p-aktuell p-bogen-start)
+ (princ (ssg-textf "vfl-rueck-erfolg-parallel"
+ (list (rtos laenge 2 1) (itoa bogen-winkel) bogen-seite)))
+ (setq fertig t))))))))
+ ;; --- Option 2: Anfangshoehe vorgeben, Laenge ergibt sich ---
+ ((= modus "2")
+ (setq h-start (vfl-in-real (ssg-textf "vfl-rueck-prompt-anfangshoehe"
+ (list (rtos (caddr p-ziel) 2 1)))))
+ (if (null h-start) (setq h-start (caddr p-ziel)))
+ (setq deltaH (- h-start (caddr p-ziel)))
+ (setq winkel (vfl-in-real (ssg-textf "vfl-prompt-neigungswinkel-laenge-berechnet"
+ (list (rtos gf-max-winkel 2 1)))))
+ (if (null winkel) (setq winkel gf-max-winkel))
+ (cond
+ ((<= deltaH 0.0) (vfl-meldung (ssg-text "vfl-rueck-alert-hoehe-zu-klein")))
+ ((or (<= winkel 0.0) (> winkel gf-max-winkel))
+ (vfl-meldung (ssg-textf "vfl-alert-winkel-ungueltig"
+ (list (rtos winkel 2 1) (rtos gf-max-winkel 2 1)))))
+ (t
+ (setq laenge (/ deltaH (/ (sin (* winkel (/ pi 180.0)))
+ (cos (* winkel (/ pi 180.0))))))
+ (if (< laenge 1.0)
+ (princ (ssg-text "vfl-fehler-linie-zu-kurz"))
+ (progn
+ (setq p-start (vfl-rueck-gf p-ziel hz-ein laenge winkel))
+ (setq anzahl-gf (1+ anzahl-gf))
+ (setq frame (make-frame-from-dir p-start (hz-winkel->xu hz-ein winkel)))
+ (setq p-aktuell p-start)
+ (princ (ssg-textf "vfl-rueck-erfolg-hoehe"
+ (list (rtos laenge 2 1) (rtos (caddr p-start) 2 1))))
+ (setq fertig t))))))
+ ;; --- Option 1: Kettenanfang klicken, Anfangshoehe ergibt sich ---
+ (t
+ ;; Cursor auf die Kettenachse zwingen: ab hier kann nur noch ENTLANG
+ ;; hz-ein gebaut werden (der Separator gibt die Richtung vor), ein frei
+ ;; schwenkendes Gummiband wuerde eine Freiheit vorgaukeln, die es nicht
+ ;; gibt. ORTHO laesst beide Richtungen der Achse zu - gemessen wird
+ ;; ohnehin die Projektion.
+ (setq p-pick (vfl-in-point-achse p-ziel (ssg-text "vfl-rueck-prompt-anfangspunkt") hz-ein))
+ (if (null p-pick)
+ (progn (princ (ssg-text "vfl-abgebrochen")) (exit)))
+ ;; Der Klick gibt nur die LAENGE her - die Richtung steht ueber die
+ ;; Abfuehrungsachse schon fest. Darum auf hz-ein zurueckprojizieren
+ ;; (entgegen der Fahrtrichtung gemessen).
+ (setq rad (* (float hz-ein) (/ pi 180.0)))
+ (setq laenge (+ (* (- (car p-ziel) (car p-pick)) (cos rad))
+ (* (- (cadr p-ziel) (cadr p-pick)) (sin rad))))
+ (setq winkel (vfl-in-real (ssg-textf "vfl-prompt-neigungswinkel"
+ (list (rtos gf-max-winkel 2 1)))))
+ (if (null winkel) (setq winkel gf-max-winkel))
+ (cond
+ ((< laenge 1.0) (princ (ssg-text "vfl-fehler-linie-zu-kurz")))
+ ((or (<= winkel 0.0) (> winkel gf-max-winkel))
+ (vfl-meldung (ssg-textf "vfl-alert-winkel-ungueltig"
+ (list (rtos winkel 2 1) (rtos gf-max-winkel 2 1)))))
+ (t
+ (setq p-start (vfl-rueck-gf p-ziel hz-ein laenge winkel))
+ (setq anzahl-gf (1+ anzahl-gf))
+ (setq frame (make-frame-from-dir p-start (hz-winkel->xu hz-ein winkel)))
+ (setq p-aktuell p-start)
+ (princ (ssg-textf "vfl-rueck-erfolg-punkt"
+ (list (rtos laenge 2 1) (rtos (caddr p-start) 2 1))))
+ (setq fertig t)))))
+ (setq letzter-typ "GF")
+ (princ))
+
;; ------------------------------------------------------------------
;; "QC Linie mit GF und U-Form" (Option 5 der gf-laenge-modus-Frage,
;; Nutzer-Vorgabe 2026-09-13, nach mehreren Praezisierungsrunden - inkl. echter
@@ -7397,7 +7815,8 @@
startpunkt-familie gf-kettenende-antwort
vorab-antwort vorab-es-gewuenscht vorab-es-seite
save-eindx-vorab save-eindz-vorab erg-es vorab-ziel-punkt
- rad3-sep sep-eindx-add sep-eindz-add gf-parallel-moeglich)
+ rad3-sep sep-eindx-add sep-eindz-add gf-parallel-moeglich
+ bau-richtung)
;; "Zurueck"/"Abbrechen"-Flag ganz am Anfang zuruecksetzen (auch schon vor
;; der ersten Praeambel-Frage) - sonst wuerde ein von einem VORHERIGEN Lauf
;; noch gesetztes Flag (z.B. nach "Abbrechen") den allerersten vfl-in-*-
@@ -7489,6 +7908,30 @@
;; faellt dann auf einen neutralen Text zurueck (kein falsches "GF"/"VF").
;; Nur wenn GAR KEIN KS_AUS in Toleranz gefunden wurde, wird wie bisher
;; gefragt.
+ ;; --- Bau-Richtung (Nutzer-Vorgabe 2026-10-22) ---
+ ;; "vor" = der geklickte Punkt ist der KettenANFANG (alles wie bisher).
+ ;; "rueck"= er ist das KettenENDE, genauer das KS_AUS des ES-Elements;
+ ;; gebaut wird von dort nach hinten (vfl-rueckwaerts-bauen).
+ ;; Journalisiert wird der WERT, nicht der Auswahl-Index (vfl-menu-strwert):
+ ;; die Frage steht VOR der AS-Ja/Nein-Frage, die ebenfalls "1"/"2" schreibt -
+ ;; mit einem Index waere ein Alt-Journal (ohne diese Frage) beim Replay nicht
+ ;; mehr davon zu unterscheiden. So genuegt ein Blick auf den Wert.
+ (setq bau-richtung
+ (if (and *vfl-replay-queue*
+ (not (member (vfl-replay-peek-wert) '("vor" "rueck"))))
+ "vor" ; Altbestand ohne diese Frage
+ (progn
+ (princ (ssg-text "vfl-richtung-header"))
+ (princ (ssg-text "vfl-richtung-opt-vor"))
+ (princ (ssg-text "vfl-richtung-opt-rueck"))
+ (vfl-menu-strwert (ssg-text "prompt-wahl-1-2")
+ (list (ssg-text "vfl-richtung-opt-vor") (ssg-text "vfl-richtung-opt-rueck"))
+ (list "vor" "rueck") 1 "vfl-richtung-header"))))
+ ;; Startpunkt-Erkennung und AS-Praeambel gelten NUR vorwaerts - rueckwaerts
+ ;; gibt es kein AS-Element am geklickten Punkt, sondern ein ES.
+ (if (= bau-richtung "rueck")
+ (setq as-vorhanden nil startpunkt-familie nil)
+ (progn
(setq erg (vfl-ks-aus-hz-an-punkt startpunkt))
(setq startpunkt-familie (if erg (vfl-kette-typ-familie (cdr erg)) nil))
(if erg
@@ -7524,11 +7967,16 @@
(setq as-seite (vfl-frage-as-winkel-seite-oder-achse "vfl-aus-seite-header" startpunkt)))
;; ES-Seite wird erst am Kettenende abgefragt (siehe vfl-frage-es-seite),
;; da das ES-Element erst dort eingefuegt wird.
+ ))
(setq p-aktuell startpunkt)
(setq letzter-typ nil fertig nil frame nil)
(setq anzahl-gf 0 anzahl-vf 0)
(vfl-acc-reset)
+ ;; Rueckwaerts: ES + GF (+ Bogen) komplett hier bauen und fertig=t setzen -
+ ;; die Hauptschleife unten laeuft dann gar nicht erst an, der gemeinsame
+ ;; Abschluss (Block, Attribute, Journal-XDATA) danach aber ganz normal.
+ (if (= bau-richtung "rueck") (vfl-rueckwaerts-bauen))
;; *vfl-journal*-Reset steht jetzt GANZ AM ANFANG der Funktion (vor der
;; Startpunkt/Hoehe/AS-Praeambel) - siehe Kommentar dort. Hier NICHT mehr
;; noetig (und schaedlich: wuerde die bereits aufgezeichnete Praeambel
diff --git a/dcl/vf_linienzug_wizard.dcl b/dcl/vf_linienzug_wizard.dcl
index 52fea60..9dfdd20 100644
--- a/dcl/vf_linienzug_wizard.dcl
+++ b/dcl/vf_linienzug_wizard.dcl
@@ -213,14 +213,18 @@ vflw_as_achse : dialog {
: radio_button { key = "winkel_90"; label = "90 Grad"; value = "1"; }
: radio_button { key = "winkel_30"; label = "30 Grad"; }
}
+ // Beschriftungen bewusst NEUTRAL: derselbe Dialog dient dem AS-Element
+ // am Kettenanfang (vorwaerts) UND dem ES-Element am Kettenende
+ // (rueckwaerts bauen, 2026-10-22). Welches Element gemeint ist, sagt die
+ // Kopfzeile ("kopf").
: boxed_radio_column {
- label = "Seite (AS schleust nach):";
+ label = "Seite (Element schleust nach):";
key = "seite";
: radio_button { key = "seite_links"; label = "Links"; value = "1"; }
: radio_button { key = "seite_rechts"; label = "Rechts"; }
}
: boxed_column {
- label = "Zufuehrungsachse (Fahrtrichtung):";
+ label = "Fahrtrichtung (2. Punkt):";
// Startpunkt der Kette - er ist der Sitz des AS-Elements UND der
// Ausgangspunkt der Achse; waehrend der Punktwahl haengt das
// Gummiband an ihm (vfl-getpoint mit Basispunkt).
diff --git a/lang/de_DE.json b/lang/de_DE.json
index dc861fd..2cdeedd 100644
--- a/lang/de_DE.json
+++ b/lang/de_DE.json
@@ -56,6 +56,20 @@
"vfl-gf-laenge-modus-opt-steigend": "\n 3 - Steigende GF (Sonderfall, bis 3 Grad)",
"vfl-gf-laenge-modus-opt-qc": "\n 4 - QC Linie mit GF (automatische Auf-Ab-Berechnung)",
"vfl-gf-laenge-modus-opt-parallel": "\n 5 - Parallel zum Kreisel weiterbauen (nur Abstand eingeben)",
+ "vfl-richtung-header": "\n\nIn welche Richtung soll gebaut werden?",
+ "vfl-richtung-opt-vor": "\n 1 - Vorwaerts bauen (der gewaehlte Punkt ist der Kettenanfang)",
+ "vfl-richtung-opt-rueck": "\n 2 - Rueckwaerts bauen (der gewaehlte Punkt ist das Kettenende, ES-Austritt)",
+ "vfl-prompt-es-achse-p2": "\n\nFahrtrichtung - 2. Punkt (gibt nur die Richtung, der Endpunkt bleibt): ",
+ "vfl-es-basislinie-info": "\n Abfuehrungsachse (Fahrtrichtung): %1 Grad.",
+ "vfl-rueck-menu-linie-gf": "\n 1 - Neue Linie: GF (Gefaellestrecke)",
+ "vfl-rueck-laenge-opt-anfangspunkt": "\n 1 - Kettenanfang waehlen (Laenge ergibt sich, Anfangshoehe wird gerechnet)",
+ "vfl-rueck-laenge-opt-anfangshoehe": "\n 2 - Anfangshoehe festlegen (Laenge wird berechnet)",
+ "vfl-rueck-prompt-anfangspunkt": "\n\nKettenanfang waehlen (Richtung steht ueber die Abfuehrungsachse fest): ",
+ "vfl-rueck-prompt-anfangshoehe": "\nGewuenschte Hoehe am Kettenanfang (mm) <%1>: ",
+ "vfl-rueck-alert-hoehe-zu-klein": "Der Kettenanfang muss HOEHER liegen als das Kettenende - eine Gefaellestrecke faellt in Fahrtrichtung.",
+ "vfl-rueck-erfolg-punkt": "\n>>> Rueckwaerts gebaut: GF-Stueck %1 mm (horizontal), Anfangshoehe %2 mm.",
+ "vfl-rueck-erfolg-hoehe": "\n>>> Rueckwaerts gebaut: GF-Stueck %1 mm (horizontal), Anfangshoehe %2 mm.",
+ "vfl-rueck-erfolg-parallel": "\n>>> Rueckwaerts, parallel zum Kreisel: GF-Stueck %1 mm (horizontal), Bogen %2 Grad %3.",
"vfl-par-prompt-abstand": "\n\nAbstand zum Kreisel (mm, senkrecht zur Zufuehrungsachse, von AS-KS_EIN bis Bogen-KS_AUS): ",
"vfl-par-nur-kettenanfang": "'Parallel zum Kreisel' geht nur am Kettenanfang mit AS-Element UND festgelegter Zufuehrungsachse (2. Punkt im AS-Dialog).",
"vfl-par-kein-bogen": "Kein GF-Bogen hebt den AS-Schwenk von %1 Grad auf (Seite %2) - parallel zum Kreisel nicht schliessbar.",
diff --git a/lang/en_GB.json b/lang/en_GB.json
index 543e8b6..7a115c0 100644
--- a/lang/en_GB.json
+++ b/lang/en_GB.json
@@ -56,6 +56,20 @@
"vfl-gf-laenge-modus-opt-steigend": "\n 3 - Rising GF (special case, up to 3 degrees)",
"vfl-gf-laenge-modus-opt-qc": "\n 4 - QC line with GF (automatic up/down calculation)",
"vfl-gf-laenge-modus-opt-parallel": "\n 5 - Continue parallel to the carousel (distance only)",
+ "vfl-richtung-header": "\n\nIn which direction should the chain be built?",
+ "vfl-richtung-opt-vor": "\n 1 - Build forwards (the picked point is the start of the chain)",
+ "vfl-richtung-opt-rueck": "\n 2 - Build backwards (the picked point is the end of the chain, ES outlet)",
+ "vfl-prompt-es-achse-p2": "\n\nTravel direction - 2nd point (defines the direction only, the end point stays): ",
+ "vfl-es-basislinie-info": "\n Outfeed axis (travel direction): %1 degrees.",
+ "vfl-rueck-menu-linie-gf": "\n 1 - New line: GF (gravity section)",
+ "vfl-rueck-laenge-opt-anfangspunkt": "\n 1 - Pick start of chain (length results, start height is calculated)",
+ "vfl-rueck-laenge-opt-anfangshoehe": "\n 2 - Set start height (length will be calculated)",
+ "vfl-rueck-prompt-anfangspunkt": "\n\nPick the start of the chain (direction is fixed by the outfeed axis): ",
+ "vfl-rueck-prompt-anfangshoehe": "\nDesired height at the start of the chain (mm) <%1>: ",
+ "vfl-rueck-alert-hoehe-zu-klein": "The start of the chain must be HIGHER than its end - a gravity section falls in the travel direction.",
+ "vfl-rueck-erfolg-punkt": "\n>>> Built backwards: GF section %1 mm (horizontal), start height %2 mm.",
+ "vfl-rueck-erfolg-hoehe": "\n>>> Built backwards: GF section %1 mm (horizontal), start height %2 mm.",
+ "vfl-rueck-erfolg-parallel": "\n>>> Backwards, parallel to the carousel: GF section %1 mm (horizontal), bend %2 degrees %3.",
"vfl-par-prompt-abstand": "\n\nDistance to the carousel (mm, perpendicular to the feed axis, from AS KS_EIN to bend KS_AUS): ",
"vfl-par-nur-kettenanfang": "'Parallel to the carousel' only works at the start of a chain with an AS element AND a defined feed axis (2nd point in the AS dialog).",
"vfl-par-kein-bogen": "No GF bend cancels the AS plan turn of %1 degrees (side %2) - cannot close parallel to the carousel.",
diff --git a/menu/SSG_LIB.cui b/menu/SSG_LIB.cui
index 85b684e..e104881 100644
--- a/menu/SSG_LIB.cui
+++ b/menu/SSG_LIB.cui
@@ -118,7 +118,7 @@
- 3D Objekte stueckweise (in Arbeit)
+ aus 3D Linie ohne Zielhoehe
^C^C(ssg-ensure "VarioFoerderer") LinienzugVarioFoerdererStueckweise
@@ -1088,7 +1088,7 @@
- 3D Objekte stueckweise (in Arbeit)
+ aus 3D Linie ohne Zielhoehe
diff --git a/tests/test_unit.lsp b/tests/test_unit.lsp
index b9f18a7..2fd0e54 100644
--- a/tests/test_unit.lsp
+++ b/tests/test_unit.lsp
@@ -449,6 +449,47 @@
(< (vfl-par-gf-laenge 100.0 200.0 300.0 1.0) 0.0))
;; AS schwenkt gar nicht aus der Achse -> keine Loesung
(tu-nil "vfl-par-laenge/kein-versatz" (vfl-par-gf-laenge 2000.0 0.0 0.0 0.0))
+
+ ;; --- Vorgabewert aus einem Prompt ziehen (Dialog-Feld vorbelegen) ---
+ ;; Die Konsolen-Prompts tragen ihre Vorgabe in Klammern; der Zahlen-Dialog
+ ;; liest sie daraus. Gesucht ist die LETZTE Klammergruppe MIT Zahl - die
+ ;; echten Texte enthalten davor "<" ohne Partner ("0 < Winkel <= 3") und
+ ;; runde Klammern mit Fliesstext, beides darf nicht stoeren.
+ (tu-eq "vflw-vorgabe/neigungswinkel" "3"
+ (vflw-vorgabe-aus-prompt "\nNeigungswinkel (Grad, 0 < Winkel <= 3) [3]: "))
+ (tu-eq "vflw-vorgabe/neigungswinkel-berechnet" "3"
+ (vflw-vorgabe-aus-prompt
+ "\nNeigungswinkel (Grad, 0 < Winkel <= 3) [3] (deltaL wird berechnet und eingefuegt): "))
+ (tu-eq "vflw-vorgabe/spitze-klammer" "2154.0"
+ (vflw-vorgabe-aus-prompt "\nGewuenschte Hoehe am Kettenanfang (mm) <2154.0>: "))
+ (tu-eq "vflw-vorgabe/negativ" "-12.5"
+ (vflw-vorgabe-aus-prompt "Hoehendifferenz <-12.5>: "))
+ ;; Ohne Klammergruppe bleibt das Feld leer (nil), nicht geraten.
+ (tu-nil "vflw-vorgabe/ohne-vorgabe"
+ (vflw-vorgabe-aus-prompt "\nAbstand zum Kreisel (mm, senkrecht zur Achse): "))
+ (tu-nil "vflw-vorgabe/keine-zahl"
+ (vflw-vorgabe-aus-prompt "Bitte Namen eingeben [frei]: "))
+
+ ;; --- Rueckwaerts bauen: Punkt entgegen der Fahrtrichtung zuruecksetzen ---
+ ;; vfl-rueck-punkt ist der Rechenkern des Rueckwaerts-Baus: zu einem
+ ;; BEKANNTEN Endpunkt den Startpunkt eines Bausteins finden. Vorwaerts gilt
+ ;; P_next = P + (L*cos hz, L*sin hz, -L*tan w) - hier also mit umgekehrtem
+ ;; Vorzeichen. Die Hoehe muss STEIGEN (der Vorgaenger liegt hoeher).
+ (tu-eqf "vfl-rueck-punkt/ost-flach"
+ (list 0.0 0.0 0.0) (vfl-rueck-punkt '(1000.0 0.0 0.0) 0.0 1000.0 0.0))
+ (tu-eqf "vfl-rueck-punkt/nord-flach"
+ (list 0.0 0.0 0.0) (vfl-rueck-punkt '(0.0 1000.0 0.0) 90.0 1000.0 0.0))
+ ;; 45 Grad Gefaelle: 1000 mm horizontal zurueck = 1000 mm hoeher
+ (tu-eqf "vfl-rueck-punkt/45-grad"
+ (list 0.0 0.0 1000.0) (vfl-rueck-punkt '(1000.0 0.0 0.0) 0.0 1000.0 45.0))
+ ;; Rundlauf: vorwaerts wieder auf den Ausgangspunkt (3 Grad, schraeg)
+ (setq _l (vfl-rueck-punkt '(5000.0 3000.0 1800.0) 30.0 2000.0 3.0))
+ (tu-eqf "vfl-rueck-punkt/rundlauf-x" 5000.0
+ (+ (car _l) (* 2000.0 (cos (/ (* 30.0 pi) 180.0)))))
+ (tu-eqf "vfl-rueck-punkt/rundlauf-y" 3000.0
+ (+ (cadr _l) (* 2000.0 (sin (/ (* 30.0 pi) 180.0)))))
+ (tu-eqf "vfl-rueck-punkt/rundlauf-z" 1800.0
+ (- (caddr _l) (* 2000.0 (/ (sin (/ (* 3.0 pi) 180.0)) (cos (/ (* 3.0 pi) 180.0))))))
)