fix: VF-Familie bei "Neue Linie BIS Kettenende" nutzt vfl-body-abschluss

Ersetzt den direkten vfl-vf-entscheidung-Aufruf (1300mm Budget, setzt
immer eine frische Umlenkstation voraus) durch Wiederverwendung von
vfl-body-abschluss + vfl-vf-ausgang-bauen - denselben Bausteinen, die
bereits "Option 3: Kettenende exakt am Zielpunkt" innerhalb einer
laufenden VF-Einheit nutzt (800mm Budget, keine Umlenkstation, volle
Stufe-1/2-Diagnose inkl. exakter Zielhoehe bleibt erhalten, da kein
GF1-Stumpf noetig ist).

Zusaetzlich: vfl-letzter-typ-familie korrigiert - letzter-typ="VF"
(gerade fertig gebaute VF-Einheit) zaehlt NICHT zur "VF"-Familie fuer
diesen Zweck, nur "Vario-Kurve" hat keine eigene Umlenkstation. Eine
neue VF-Einheit nach einer bereits fertigen braucht weiterhin eine
frische Umlenkstation (faellt jetzt korrekt auf die bisherige
Automatik zurueck).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Yuelin Wang
2026-09-12 01:33:01 +02:00
co-authored by Claude Sonnet 5
parent 38ee74ed3e
commit 0d9ec93623
+311 -256
View File
@@ -3486,12 +3486,16 @@
;; Vereinheitlichte Stufe-1(Winkel-Tabelle)/Stufe-2(horizontal+GF)-Entscheidung. ;; Vereinheitlichte Stufe-1(Winkel-Tabelle)/Stufe-2(horizontal+GF)-Entscheidung.
;; Genutzt von ZWEI Aufrufern mit unterschiedlichem Fest-Budget: ;; Genutzt von ZWEI Aufrufern mit unterschiedlichem Fest-Budget:
;; - vfl-body-zerlegung (Kettenende innerhalb einer laufenden VF-Einheit): ;; - vfl-body-zerlegung (Kettenende innerhalb einer laufenden VF-Einheit
;; ODER "Neue Linie BIS Kettenende" mit als VF-Familie erkanntem
;; Startpunkt, siehe linie-ende-familie/vfl-body-abschluss - beide Faelle
;; brauchen KEINE eigene Umlenkstation):
;; feste-hz=*vfk-feste-horizontal-kettenende* (800, nur Motor+Separator - ;; feste-hz=*vfk-feste-horizontal-kettenende* (800, nur Motor+Separator -
;; der Eingang ist zu diesem Zeitpunkt schon gebaut). ;; der Eingang ist zu diesem Zeitpunkt schon gebaut bzw. entfaellt).
;; - vfl-vf-entscheidung ("Neue Linie: Ab/Auf VF"/"BIS Kettenende", Eingang ;; - vfl-vf-entscheidung ("Neue Linie: Ab/Auf VF" bzw. "BIS Kettenende" mit
;; einer FRISCHEN VF-Einheit): feste-hz=*vfl-feste-horizontal* (1300, ;; NICHT eindeutig zuordenbarem Startpunkt, Eingang einer FRISCHEN
;; Umlenkstation+Separator+Motorstation). ;; VF-Einheit): feste-hz=*vfl-feste-horizontal* (1300, Umlenkstation+
;; Separator+Motorstation).
;; schon-flach: nur fuer den Kettenende-Fortsetzungsfall relevant (Frame kann ;; schon-flach: nur fuer den Kettenende-Fortsetzungsfall relevant (Frame kann
;; dort schon flach sein, siehe vfl-baue-horizontal-koerper) - am Eingang ;; dort schon flach sein, siehe vfl-baue-horizontal-koerper) - am Eingang
;; einer frischen VF-Einheit immer nil (Frame kommt frisch von der ;; einer frischen VF-Einheit immer nil (Frame kommt frisch von der
@@ -4452,9 +4456,16 @@
;; laufende Fortsetzung (kettenanfang=nil) ist der Vorgaengertyp bereits ;; laufende Fortsetzung (kettenanfang=nil) ist der Vorgaengertyp bereits
;; ohne KS_AUS-Scan bekannt. "Separator" zaehlt als GF-Familie (er folgt in ;; ohne KS_AUS-Scan bekannt. "Separator" zaehlt als GF-Familie (er folgt in
;; diesem Ablauf immer auf ein GF-Segment, siehe "Linie-GF"-Zweig). ;; diesem Ablauf immer auf ein GF-Segment, siehe "Linie-GF"-Zweig).
;; WICHTIG: "VF" (eine gerade FERTIG gebaute VF-Einheit, Motorstation schon
;; eingefuegt) zaehlt hier BEWUSST NICHT zur "VF"-Familie - eine neue
;; VF-Einheit direkt danach braucht sehr wohl eine frische Umlenkstation
;; (siehe vfl-eingang-modus-bestimmen: nur "Vario-Kurve" mappt dort auf
;; eingang-modus="keine", "VF" fehlt dort bewusst und faellt auf den
;; Default/volle-Eingang-Fall zurueck). Nur "Vario-Kurve" hat keine eigene
;; Umlenkstation/keinen Abschluss - eine zweite waere mechanisch sinnlos.
(defun vfl-letzter-typ-familie (letzter-typ) (defun vfl-letzter-typ-familie (letzter-typ)
(cond (cond
((member letzter-typ '("VF" "Vario-Kurve")) "VF") ((equal letzter-typ "Vario-Kurve") "VF")
((member letzter-typ '("GF" "Separator")) "GF") ((member letzter-typ '("GF" "Separator")) "GF")
(t nil) (t nil)
) )
@@ -4860,7 +4871,8 @@
sep-anzahl erg-bogen vf-eingang-lgf vf-eingang-modus sep-anzahl erg-bogen vf-eingang-lgf vf-eingang-modus
eingang-laenge winkel-hoehen-erg eingang-laenge winkel-hoehen-erg
bogen-mass fest-drop fest-laenge eingang-fertig bogen-mass fest-drop fest-laenge eingang-fertig
linie-ende-familie linie-ende-untermodus) linie-ende-familie linie-ende-untermodus
res3 save-eindx save-eindz es-gewuenscht)
;; "Zurueck"/"Abbrechen"-Flag ganz am Anfang zuruecksetzen (auch schon vor ;; "Zurueck"/"Abbrechen"-Flag ganz am Anfang zuruecksetzen (auch schon vor
;; der ersten Praeambel-Frage) - sonst wuerde ein von einem VORHERIGEN Lauf ;; der ersten Praeambel-Frage) - sonst wuerde ein von einem VORHERIGEN Lauf
;; noch gesetztes Flag (z.B. nach "Abbrechen") den allerersten vfl-in-*- ;; noch gesetztes Flag (z.B. nach "Abbrechen") den allerersten vfl-in-*-
@@ -5808,263 +5820,306 @@
((= wahl "Linie") ;; --- Neue Linie BIS Kettenende --- ((= wahl "Linie") ;; --- Neue Linie BIS Kettenende ---
;; GF/VF-Entscheidung: wird der Startpunkt eindeutig einer bestehenden ;; GF/VF-Entscheidung: wird der Startpunkt eindeutig einer bestehenden
;; VF- oder GF-Kette zugeordnet (linie-ende-familie, siehe unten), ;; VF- oder GF-Kette zugeordnet (linie-ende-familie), entscheidet DAS
;; entscheidet DAS die Bau-Logik (Stufe-1/2-Diagnose bzw. Endpunkt/ ;; die Bau-Logik - nur wenn nicht eindeutig, greift die automatische
;; Zielhoehe-Wahl) - nur wenn nicht eindeutig, greift weiterhin die ;; Machbarkeits-Entscheidung (vfl-segment-entscheidung).
;; automatische Machbarkeits-Entscheidung (vfl-segment-entscheidung).
;; Fahrtrichtung folgt dem vorherigen Element (Frame); nur das erste
;; Segment (frame=nil) definiert die Richtung frei.
(setq linie-mess (vfl-neue-linie-messen p-aktuell
(if frame (car (frame->hz-winkel frame)) nil)))
(if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen")) (exit)))
(setq deltaL (car linie-mess) hz-neu (cadr linie-mess))
(setq kettenanfang (null frame)) (setq kettenanfang (null frame))
;; Startpunkt-Typ erkennen (VF/GF/nicht eindeutig): bei einer ;; Startpunkt-Typ erkennen: bei einer laufenden Fortsetzung ist der
;; laufenden Fortsetzung ist der Vorgaengertyp schon bekannt ;; Vorgaengertyp schon bekannt (letzter-typ); am echten Kettenanfang
;; (letzter-typ); am echten Kettenanfang OHNE AS-Element wird wie bei ;; OHNE AS-Element wird wie bei vfl-eingang-modus-bestimmen per
;; vfl-eingang-modus-bestimmen per KS_AUS-Scan erkannt, ob der ;; KS_AUS-Scan erkannt (Rueckgabe (hz . typ) - typ wird bei VF-Familie
;; gepickte Startpunkt auf einer bestehenden VF- oder GF-Kette liegt. ;; unten fuer die Flach/3-Grad-Unterscheidung gebraucht). Steht schon
;; Steht schon ein AS-Element (as-vorhanden), ist der Anfang per ;; ein AS-Element (as-vorhanden), ist der Anfang per Definition
;; Definition neutral/nicht zuordenbar - dann bleibt die generische ;; neutral/nicht zuordenbar.
;; Automatik (vfl-segment-entscheidung) unten aktiv. Genutzt weiter (setq erg (if (and kettenanfang (not as-vorhanden))
;; unten, um bei erkannter Familie NICHT die generische Automatik zu (vfl-ks-aus-hz-an-punkt p-aktuell)
;; fragen, sondern direkt die passende (VF: Stufe-1/2-Diagnose; GF: nil))
;; Endpunkt/Zielhoehe-Wahl wie "Neue Linie: GF") Logik zu verwenden.
(setq linie-ende-familie (setq linie-ende-familie
(if kettenanfang (if kettenanfang
(if (not as-vorhanden) (if erg (vfl-kette-typ-familie (cdr erg)) nil)
(progn
(setq erg (vfl-ks-aus-hz-an-punkt p-aktuell))
(if erg (vfl-kette-typ-familie (cdr erg)) nil))
nil)
(vfl-letzter-typ-familie letzter-typ))) (vfl-letzter-typ-familie letzter-typ)))
(if (< deltaL 1.0) (cond
(princ (ssg-text "vfl-fehler-linie-zu-kurz")) ;; --- Startpunkt als VF-Familie erkannt: KEINE eigene Umlenkstation
(progn ;; noetig (Vorgaenger Vario-Kurve/Umlenk/Motor/Bogen bzw. laufende
;; Kettenanfang: AS-Element (falls gewuenscht) SOFORT einfuegen ;; VF-Fortsetzung). Strukturell IDENTISCH zu "Option 3: Kettenende
;; (immer flach, typ-unabhaengig - siehe vfl-insert-as-element; ;; exakt am Zielpunkt" INNERHALB einer laufenden VF-Einheit
;; welcher Segmenttyp folgt, steht hier noch nicht fest), reale ;; (vfl-vf-einheit): derselbe Stufe-1/Stufe-2-Diagnose-Baustein
;; Restlaenge aus dem tatsaechlichen KS_AUS nachrechnen (siehe ;; (vfl-body-abschluss, Budget OHNE Umlenkstation -
;; vfl-kettenanfang-baustein). ;; *vfk-feste-horizontal-kettenende*) + Motorstation/GF2
(if kettenanfang ;; (vfl-vf-ausgang-bauen) + ES-Element - KEIN Rueckfall auf eine
(progn ;; reine Winkeltabelle noetig (anders als bei "Neue Linie: Ab/Auf
(setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu deltaL as-seite as-vorhanden)) ;; VF" mit reduziertem Eingang): hier gibt es keinen GF1-Stumpf,
(setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) ;; dessen Wegfall die 2-Unbekannten-Loesung stoeren wuerde - die
) ;; volle Freiheit (Winkel + GF2) bleibt erhalten, exakte Zielhoehe
) ;; ist also weiterhin moeglich.
;; Nach dem AS-Einfuegen kann die reale Restlaenge (aus dem ((equal linie-ende-familie "VF")
;; tatsaechlichen KS_AUS neu gemessen) kleiner als der urspruenglich (if kettenanfang
;; gepickte Rohwert sein - bei einem knapp gepickten Punkt sogar ;; Kettenanfang auf einer bestehenden VF-Kette: Frame
;; NEGATIV. Ohne diese zweite Pruefung wuerde die Kurzsegment- ;; konstruieren (Vario-Kurve endet flach, alle anderen VF-Typen
;; Automatik unten (< 1000mm) mit negativem deltaL trotzdem ein ;; auf der 3-Grad-Basis) - der eigentliche Endpunkt-Pick erfolgt
;; "erfolgreiches" GF-Segment bauen (entartete/unsichtbare Strecke, ;; gleich INNERHALB von vfl-body-abschluss.
;; das naechste Element - z.B. ein GF-Bogen - erscheint dann direkt (setq frame (make-frame-from-dir p-aktuell
;; am AS-Element, obwohl der Nutzer davor noch eine Linie wollte). (hz-winkel->xu (car erg)
(if (< deltaL 1.0) (if (equal (cdr erg) "KURVE") 0.0 *vfk-gefaelle-winkel*)))))
(princ (ssg-text "vfl-fehler-linie-zu-kurz")) ;; ES-Element hier gewuenscht (+ falls ja: Winkel/Seite) - wie bei
(progn ;; "Option 3" (vfl-vf-einheit) VOR vfl-body-abschluss erfragt, weil
;; Segment-Typ bestimmen. Kurzsegment (deltaL < 1000 mm): KEINE ;; der tatsaechliche ES-Fussabdruck (ein-dx/ein-dz) die
;; Hoehenabfrage - automatisch 3-Grad-Gefaellestrecke. Grund: ein VF ;; Streckenzerlegung beeinflusst.
;; braucht >= 1000 mm deltaL (Umlenk- + Motorstation = 500+500 mm), (princ (ssg-text "vfl-es-setzen-frage"))
;; und eine GF ist mindestens 3 Grad geneigt. Die Endhoehe ergibt (princ (ssg-text "vfl-ja"))
;; sich damit fest aus deltaH = deltaL*tan(3 Grad). (princ (ssg-text "vfl-es-nein-zielpunkt"))
;; Im Kettenende-Modus (Option 4) wird IMMER nach der Zielhoehe (if (vfl-wizard-aktiv)
;; gefragt (Kurzsegment-Automatik hier ueberspringen). (vl-catch-all-apply 'vflw-gruppe-as-impl (list "vfl-es-setzen-frage")))
(if (and (< deltaL *vfk-vf-mindestlaenge*) (not linie-ende-modus)) (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2")
(progn (list (ssg-text "vfl-ja") (ssg-text "vfl-es-nein-zielpunkt")) 1
(setq typ "GF" winkel *vfk-gefaelle-winkel* richtung "Ab" L_GF nil L_VF nil) "vfl-es-setzen-frage"))
(setq deltaH (* deltaL (/ (sin (* *vfk-gefaelle-winkel* (/ pi 180.0))) (setq es-gewuenscht (/= antwort "2"))
(cos (* *vfk-gefaelle-winkel* (/ pi 180.0)))))) (if es-gewuenscht
(setq hoehe-neu (- (caddr p-aktuell) deltaH)) (setq es-seite (vfl-frage-es-seite t))
(princ (ssg-textf "vfl-info-kurzes-segment" (progn (setq save-eindx ein-dx save-eindz ein-dz) (setq ein-dx 0.0 ein-dz 0.0)))
(list (rtos deltaL 2 0) (rtos deltaH 2 1)))) (setq res3 (vfl-body-abschluss frame (car (frame->hz-winkel frame)) (car frame)))
) (if (not es-gewuenscht) (setq ein-dx save-eindx ein-dz save-eindz))
(progn (if (null res3)
(setq hoehe-vorschlaege (vfl-segment-hoehe-vorschlaege (caddr p-aktuell) deltaL)) (if dbg-an
(setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege)) (dbgmsg "GEOMETRIE FEHLGESCHLAGEN: Linie (VF-Familie, Kettenende) nicht baubar"))
(setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr p-aktuell))) (progn
(vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf) (setq anzahl-vf (+ anzahl-vf (nth 1 res3)))
(if (vfl-wizard-aktiv) (setq frame (vfl-vf-ausgang-bauen (nth 0 res3) (nth 2 res3) (nth 3 res3)))
(vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (if es-gewuenscht
(list (list hoehe-ab hoehe-auf (caddr p-aktuell))))) (setq frame (vfl-insert-es-element "VF" frame (car (frame->hz-winkel frame)) 0.0
(setq hoehe-neu (caddr (car frame)) es-seite)))
(vfl-in-real (vfl-ziel-report frame)
(if (and hoehe-ab hoehe-auf) (setq letzter-typ "VF" p-aktuell (car frame) fertig t)
(ssg-textf "vfl-prompt-hoehe-linienendpunkt-2" (if dbg-an
(list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) (dbgmsg (strcat "GEOMETRIE ERFOLG: Linie (VF-Familie, Kettenende) gebaut, neue Position="
(ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos hoehe-fallback 2 1)))))) (dbg-tostring p-aktuell))))
(if (null hoehe-neu) (setq hoehe-neu hoehe-fallback)) )
(setq deltaH (- hoehe-neu (caddr p-aktuell))) )
(setq richtung (if (>= deltaH 0.0) "Auf" "Ab")) )
(setq deltaH (abs deltaH)) ;; --- Startpunkt als GF-Familie erkannt ODER nicht eindeutig ---
(vfl-echo-endpunkt-hoehe p-aktuell deltaL hz-neu hoehe-neu deltaH richtung) (t
;; Kettenende-Modus (Option 4): Der abgefragte Endpunkt (XY+Z) ;; Fahrtrichtung folgt dem vorherigen Element (Frame); nur das
;; ist das exakte Ende der Kette NACH Separator + ES-Element. ;; erste Segment (frame=nil) definiert die Richtung frei.
;; Deren Footprint (Separator 300 mm bei ~3 Grad + ES-Element (setq linie-mess (vfl-neue-linie-messen p-aktuell
;; ein-dx/ein-dz) muss vom baubaren GF/VF-Segment reserviert (if frame (car (frame->hz-winkel frame)) nil)))
;; (abgezogen) werden, damit das ES-Element genau am Zielpunkt (if (null linie-mess) (progn (princ (ssg-text "vfl-abgebrochen")) (exit)))
;; endet. Naeherung: Separator-Neigung = 3 Grad (Auslauf). (setq deltaL (car linie-mess) hz-neu (cadr linie-mess))
(if linie-ende-modus (if (< deltaL 1.0)
(progn (princ (ssg-text "vfl-fehler-linie-zu-kurz"))
(setq rad3 (* (float (ssg-cfg-or "vario" "gefaelle_winkel" 3)) (progn
(/ pi 180.0))) ;; Kettenanfang: AS-Element (falls gewuenscht) SOFORT einfuegen
(setq deltaL (max 1.0 (- deltaL (* *vfk-separator-laenge* (cos rad3)) ;; (immer flach, typ-unabhaengig - siehe vfl-insert-as-element;
(abs (if ein-dx ein-dx 0.0))))) ;; welcher Segmenttyp folgt, steht hier noch nicht fest), reale
(setq deltaH (max 0.0 (- deltaH (* *vfk-separator-laenge* (sin rad3)) ;; Restlaenge aus dem tatsaechlichen KS_AUS nachrechnen (siehe
(abs (if ein-dz ein-dz 0.0))))) ;; vfl-kettenanfang-baustein).
(princ (ssg-textf "vfl-info-kettenende-footprint" (if kettenanfang
(list (rtos deltaL 2 0) (rtos deltaH 2 0)))) (progn
) (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu deltaL as-seite as-vorhanden))
) (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame))
(cond )
;; --- Startpunkt als VF-Familie erkannt --- )
;; IMMER ueber die Stufe-1/Stufe-2-Diagnose bauen (auch ;; Nach dem AS-Einfuegen kann die reale Restlaenge (aus dem
;; wenn der natuerliche Winkel zufaellig nahe 3 Grad ;; tatsaechlichen KS_AUS neu gemessen) kleiner als der urspruenglich
;; liegt) - vfl-segment-entscheidung wuerde in dem Fall ;; gepickte Rohwert sein - bei einem knapp gepickten Punkt sogar
;; faelschlich eine reine GF waehlen, obwohl der ;; NEGATIV. Ohne diese zweite Pruefung wuerde die Kurzsegment-
;; Vorgaenger eindeutig eine VF-Kette ist. ;; Automatik unten (< 1000mm) mit negativem deltaL trotzdem ein
((equal linie-ende-familie "VF") ;; "erfolgreiches" GF-Segment bauen (entartete/unsichtbare Strecke,
(setq entscheidung (vfl-vf-entscheidung deltaL deltaH richtung)) ;; das naechste Element - z.B. ein GF-Bogen - erscheint dann direkt
(setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung) ;; am AS-Element, obwohl der Nutzer davor noch eine Linie wollte).
L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung))) (if (< deltaL 1.0)
;; --- Startpunkt als GF-Familie erkannt --- (princ (ssg-text "vfl-fehler-linie-zu-kurz"))
;; Dieselbe Endpunkt-/Zielhoehe-Wahl wie "Neue Linie: GF" (progn
;; (Zweig A/B) statt der generischen Automatik - eine ;; Segment-Typ bestimmen. Kurzsegment (deltaL < 1000 mm): KEINE
;; reine Gefaellestrecke kann nicht steigen. ;; Hoehenabfrage - automatisch 3-Grad-Gefaellestrecke. Grund: ein VF
((equal linie-ende-familie "GF") ;; braucht >= 1000 mm deltaL (Umlenk- + Motorstation = 500+500 mm),
;; Stufe-2-Diagnosevariablen zuruecksetzen: dieser Zweig ;; und eine GF ist mindestens 3 Grad geneigt. Die Endhoehe ergibt
;; ruft vfl-vf-entscheidung NICHT auf, ein evtl. noch ;; sich damit fest aus deltaH = deltaL*tan(3 Grad).
;; von einem frueheren Versuch gesetzter Text/Vorschlag ;; Im Kettenende-Modus (Option 4) wird IMMER nach der Zielhoehe
;; darf bei einem hier fehlschlagenden GF-Segment nicht ;; gefragt (Kurzsegment-Automatik hier ueberspringen).
;; faelschlich mit angezeigt werden (siehe gemeinsamer (if (and (< deltaL *vfk-vf-mindestlaenge*) (not linie-ende-modus))
;; "typ=nil"-Meldungsblock unten). (progn
(setq *vfl-stufe2-diagnose-text* nil) (setq typ "GF" winkel *vfk-gefaelle-winkel* richtung "Ab" L_GF nil L_VF nil)
(setq *vfl-stufe2-minl-vorschlag* nil *vfl-stufe2-minh-vorschlag* nil) (setq deltaH (* deltaL (/ (sin (* *vfk-gefaelle-winkel* (/ pi 180.0)))
(if (= richtung "Auf") (cos (* *vfk-gefaelle-winkel* (/ pi 180.0))))))
(setq typ nil) (setq hoehe-neu (- (caddr p-aktuell) deltaH))
(princ (ssg-textf "vfl-info-kurzes-segment"
(list (rtos deltaL 2 0) (rtos deltaH 2 1))))
)
(progn
(setq hoehe-vorschlaege (vfl-segment-hoehe-vorschlaege (caddr p-aktuell) deltaL))
(setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege))
(setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr p-aktuell)))
(vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf)
(if (vfl-wizard-aktiv)
(vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl
(list (list hoehe-ab hoehe-auf (caddr p-aktuell)))))
(setq hoehe-neu
(vfl-in-real
(if (and hoehe-ab hoehe-auf)
(ssg-textf "vfl-prompt-hoehe-linienendpunkt-2"
(list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1)))
(ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos hoehe-fallback 2 1))))))
(if (null hoehe-neu) (setq hoehe-neu hoehe-fallback))
(setq deltaH (- hoehe-neu (caddr p-aktuell)))
(setq richtung (if (>= deltaH 0.0) "Auf" "Ab"))
(setq deltaH (abs deltaH))
(vfl-echo-endpunkt-hoehe p-aktuell deltaL hz-neu hoehe-neu deltaH richtung)
;; Kettenende-Modus (Option 4): Der abgefragte Endpunkt (XY+Z)
;; ist das exakte Ende der Kette NACH Separator + ES-Element.
;; Deren Footprint (Separator 300 mm bei ~3 Grad + ES-Element
;; ein-dx/ein-dz) muss vom baubaren GF/VF-Segment reserviert
;; (abgezogen) werden, damit das ES-Element genau am Zielpunkt
;; endet. Naeherung: Separator-Neigung = 3 Grad (Auslauf).
(if linie-ende-modus
(progn (progn
(princ (ssg-text "vfl-gf-laenge-modus-header")) (setq rad3 (* (float (ssg-cfg-or "vario" "gefaelle_winkel" 3))
(princ (ssg-text "vfl-gf-laenge-modus-opt-endpunkt")) (/ pi 180.0)))
(princ (ssg-text "vfl-gf-laenge-modus-opt-hoehe")) (setq deltaL (max 1.0 (- deltaL (* *vfk-separator-laenge* (cos rad3))
(if (vfl-wizard-aktiv) (abs (if ein-dx ein-dx 0.0)))))
(vl-catch-all-apply 'vflw-gruppe-gf-steigend-untermodus-impl nil)) (setq deltaH (max 0.0 (- deltaH (* *vfk-separator-laenge* (sin rad3))
(setq linie-ende-untermodus (abs (if ein-dz ein-dz 0.0)))))
(vfl-menu (ssg-text "prompt-wahl-1-2") (princ (ssg-textf "vfl-info-kettenende-footprint"
(list (ssg-text "vfl-gf-laenge-modus-opt-endpunkt") (list (rtos deltaL 2 0) (rtos deltaH 2 0))))
(ssg-text "vfl-gf-laenge-modus-opt-hoehe")) 1
"vfl-gf-laenge-modus-header"))
(if (= linie-ende-untermodus "2")
;; Zielhoehe fest, Winkel fix *vfk-gefaelle-winkel*
;; -> Laenge wird daraus berechnet (ersetzt die
;; oben gemessene/reservierte deltaL).
(progn
(setq winkel *vfk-gefaelle-winkel*)
(setq deltaL
(/ deltaH (/ (sin (* winkel (/ pi 180.0))) (cos (* winkel (/ pi 180.0))))))
(if (< deltaL 1.0)
(setq typ nil)
(setq typ "GF" L_GF nil L_VF nil)))
;; Endpunkt (deltaL) fest, Winkel aus deltaL +
;; Zielhoehe berechnen.
(progn
(setq winkel (* (atan (/ deltaH deltaL)) (/ 180.0 pi)))
(if (> winkel *vfk-gefaelle-winkel*)
(setq typ nil)
(setq typ "GF" L_GF nil L_VF nil)))
)
) )
) )
) (if (equal linie-ende-familie "GF")
;; --- Nicht eindeutig zuordenbar: bisherige Automatik --- (progn
(t ;; --- Startpunkt als GF-Familie erkannt ---
(setq entscheidung (vfl-segment-entscheidung deltaL deltaH richtung)) ;; Dieselbe Endpunkt-/Zielhoehe-Wahl wie "Neue
(setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung) ;; Linie: GF" (Zweig A/B) statt der generischen
L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung))) ;; Automatik - eine reine Gefaellestrecke kann
) ;; nicht steigen. Stufe-2-Diagnosevariablen
) ;; zuruecksetzen: dieser Zweig ruft
) ;; vfl-vf-entscheidung NICHT auf, ein evtl. noch
;; von einem frueheren Versuch gesetzter Text/
;; Vorschlag darf bei einem hier fehlschlagenden
;; GF-Segment nicht faelschlich mit angezeigt
;; werden (siehe gemeinsamer "typ=nil"-
;; Meldungsblock unten).
(setq *vfl-stufe2-diagnose-text* nil)
(setq *vfl-stufe2-minl-vorschlag* nil *vfl-stufe2-minh-vorschlag* nil)
(if (= richtung "Auf")
(setq typ nil)
(progn
(princ (ssg-text "vfl-gf-laenge-modus-header"))
(princ (ssg-text "vfl-gf-laenge-modus-opt-endpunkt"))
(princ (ssg-text "vfl-gf-laenge-modus-opt-hoehe"))
(if (vfl-wizard-aktiv)
(vl-catch-all-apply 'vflw-gruppe-gf-steigend-untermodus-impl nil))
(setq linie-ende-untermodus
(vfl-menu (ssg-text "prompt-wahl-1-2")
(list (ssg-text "vfl-gf-laenge-modus-opt-endpunkt")
(ssg-text "vfl-gf-laenge-modus-opt-hoehe")) 1
"vfl-gf-laenge-modus-header"))
(if (= linie-ende-untermodus "2")
(progn
(setq winkel *vfk-gefaelle-winkel*)
(setq deltaL
(/ deltaH (/ (sin (* winkel (/ pi 180.0))) (cos (* winkel (/ pi 180.0))))))
(if (< deltaL 1.0)
(setq typ nil)
(setq typ "GF" L_GF nil L_VF nil)))
(progn
(setq winkel (* (atan (/ deltaH deltaL)) (/ 180.0 pi)))
(if (> winkel *vfk-gefaelle-winkel*)
(setq typ nil)
(setq typ "GF" L_GF nil L_VF nil)))
)
)
)
)
;; --- Nicht eindeutig zuordenbar: bisherige Automatik ---
(progn
(setq entscheidung (vfl-segment-entscheidung deltaL deltaH richtung))
(setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung)
L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung)))
)
)
)
(if (null typ) (if (null typ)
(progn (progn
(vfl-meldung (ssg-textf "vfl-alert-segment-nicht-baubar" (vfl-meldung (ssg-textf "vfl-alert-segment-nicht-baubar"
(list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung))) (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung)))
;; Gesammelte Stufe-2-Diagnose (falls versucht) + kompaktes ;; Gesammelte Stufe-2-Diagnose (falls versucht) + kompaktes
;; 2-Punkte-Alert mit Mindestwerten - analog vfl-body-abschluss. ;; 2-Punkte-Alert mit Mindestwerten - analog vfl-body-abschluss.
(if *vfl-stufe2-diagnose-text* (princ *vfl-stufe2-diagnose-text*)) (if *vfl-stufe2-diagnose-text* (princ *vfl-stufe2-diagnose-text*))
(vfl-meldung (vfl-meldung
(strcat (strcat
(ssg-textf "vfl-alert-vf-entscheidung-p1" (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung)) (ssg-textf "vfl-alert-vf-entscheidung-p1" (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung))
(cond (cond
((and *vfl-stufe2-minl-vorschlag* *vfl-stufe2-minh-vorschlag*) ((and *vfl-stufe2-minl-vorschlag* *vfl-stufe2-minh-vorschlag*)
(ssg-textf "vfl-alert-vf-entscheidung-p2-beide" (ssg-textf "vfl-alert-vf-entscheidung-p2-beide"
(list (rtos *vfl-stufe2-minl-vorschlag* 2 0) (rtos *vfl-stufe2-minh-vorschlag* 2 0)))) (list (rtos *vfl-stufe2-minl-vorschlag* 2 0) (rtos *vfl-stufe2-minh-vorschlag* 2 0))))
(*vfl-stufe2-minh-vorschlag* (*vfl-stufe2-minh-vorschlag*
(ssg-textf "vfl-alert-vf-entscheidung-p2-nur-minh" (list (rtos *vfl-stufe2-minh-vorschlag* 2 0)))) (ssg-textf "vfl-alert-vf-entscheidung-p2-nur-minh" (list (rtos *vfl-stufe2-minh-vorschlag* 2 0))))
(*vfl-stufe2-minl-vorschlag* (*vfl-stufe2-minl-vorschlag*
(ssg-textf "vfl-alert-vf-entscheidung-p2-nur-minl" (list (rtos *vfl-stufe2-minl-vorschlag* 2 0)))) (ssg-textf "vfl-alert-vf-entscheidung-p2-nur-minl" (list (rtos *vfl-stufe2-minl-vorschlag* 2 0))))
(t "")))) (t ""))))
(if dbg-an (if dbg-an
(dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Linie (automatisch) nicht baubar" (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Linie (automatisch) nicht baubar"
" (deltaL=" (rtos deltaL 2 0) " deltaH=" (rtos deltaH 2 0) " (deltaL=" (rtos deltaL 2 0) " deltaH=" (rtos deltaH 2 0)
" richtung=" richtung ")")))) " richtung=" richtung ")"))))
(progn (progn
(if (= typ "GF") (if (= typ "GF")
(progn (progn
;; --- reine Gefaellestrecke --- ;; --- reine Gefaellestrecke ---
(if dbg-an (if dbg-an
(dbgmsg (strcat "GEOMETRIE: vfl-insert-gf-segment (deltaL=" (rtos deltaL 2 0) (dbgmsg (strcat "GEOMETRIE: vfl-insert-gf-segment (deltaL=" (rtos deltaL 2 0)
" hz=" (rtos hz-neu 2 1) " winkel=" (rtos (float winkel) 2 1) ")"))) " hz=" (rtos hz-neu 2 1) " winkel=" (rtos (float winkel) 2 1) ")")))
(setq frame (vfl-insert-gf-segment (car frame) hz-neu deltaL winkel)) (setq frame (vfl-insert-gf-segment (car frame) hz-neu deltaL winkel))
(setq anzahl-gf (1+ anzahl-gf)) (setq anzahl-gf (1+ anzahl-gf))
;; GF-Segment erfassen (Schraeglaenge = deltaL/cos(winkel)) ;; GF-Segment erfassen (Schraeglaenge = deltaL/cos(winkel))
(vfl-acc-gf-seg (/ deltaL (cos (* (float winkel) (/ pi 180.0)))) winkel) (vfl-acc-gf-seg (/ deltaL (cos (* (float winkel) (/ pi 180.0)))) winkel)
(setq letzter-typ "GF") (setq letzter-typ "GF")
(setq p-aktuell (car frame)) (setq p-aktuell (car frame))
(if dbg-an (if dbg-an
(dbgmsg (strcat "GEOMETRIE ERFOLG: GF-Segment gebaut, neue Position=" (dbgmsg (strcat "GEOMETRIE ERFOLG: GF-Segment gebaut, neue Position="
(dbg-tostring p-aktuell)))) (dbg-tostring p-aktuell))))
;; Kettenende-Modus (Option 4): ohne Frage direkt ES setzen. ;; Kettenende-Modus (Option 4): ohne Frage direkt ES setzen.
;; Sonst nachfragen, ob die Kette hier endet. ;; Sonst nachfragen, ob die Kette hier endet.
(if linie-ende-modus (if linie-ende-modus
(setq antwort "1") (setq antwort "1")
(setq antwort (vfl-frage-ist-kettenende)) (setq antwort (vfl-frage-ist-kettenende))
) )
(cond (cond
((= antwort "1") ((= antwort "1")
(setq es-seite (vfl-frage-es-seite nil)) (setq es-seite (vfl-frage-es-seite nil))
(setq frame (vfl-insert-es-element "GF" frame hz-neu winkel (setq frame (vfl-insert-es-element "GF" frame hz-neu winkel
(caddr (car frame)) es-seite)) (caddr (car frame)) es-seite))
(setq fertig t)) (setq fertig t))
((= antwort "2") (setq fertig t)) ((= antwort "2") (setq fertig t))
) )
) )
(progn (progn
;; --- VarioFoerderer-Einheit (Umlenk..Motor, mehrsegmentig) --- ;; --- VarioFoerderer-Einheit (Umlenk..Motor, mehrsegmentig) ---
;; linie-ende-modus=T -> direkt Kettenende (Separator + ES). ;; linie-ende-modus=T -> direkt Kettenende (Separator + ES).
(if dbg-an (if dbg-an
(dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss (deltaL=" (rtos deltaL 2 0) (dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss (deltaL=" (rtos deltaL 2 0)
" deltaH=" (rtos deltaH 2 0) " richtung=" richtung " deltaH=" (rtos deltaH 2 0) " richtung=" richtung
" winkel=" (rtos (float winkel) 2 1) " winkel=" (rtos (float winkel) 2 1)
" L_GF=" (rtos L_GF 2 0) " L_VF=" (rtos L_VF 2 0) " L_GF=" (rtos L_GF 2 0) " L_VF=" (rtos L_VF 2 0)
" linie-ende-modus=" (if linie-ende-modus "T" "nil") ")"))) " linie-ende-modus=" (if linie-ende-modus "T" "nil") ")")))
(setq vf-einheit-res (setq vf-einheit-res
(vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF
linie-ende-modus nil nil)) linie-ende-modus nil nil))
(setq frame (nth 0 vf-einheit-res)) (setq frame (nth 0 vf-einheit-res))
(setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res)))
(if (nth 2 vf-einheit-res) (setq fertig t)) (if (nth 2 vf-einheit-res) (setq fertig t))
(if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res)))
(setq letzter-typ "VF") (setq letzter-typ "VF")
(setq p-aktuell (car frame)) (setq p-aktuell (car frame))
(if dbg-an (if dbg-an
(dbgmsg (strcat "GEOMETRIE ERFOLG: VF-Einheit gebaut, neue Position=" (dbgmsg (strcat "GEOMETRIE ERFOLG: VF-Einheit gebaut, neue Position="
(dbg-tostring p-aktuell)))) (dbg-tostring p-aktuell))))
) )
) )
) )
) )
) )
) )
)
)
) )
) )
) )