diff --git a/CLAUDE.md b/CLAUDE.md index 546df9e..7ad4ed3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,7 +67,7 @@ Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD. |---|---|---| | Kreisel-Module | `KreiselInsert` | KreiselInsert, KreiselConnect, KreiselEdit, ILS_Eckrad | | Zusatzmodul/Foerderer/Kurven | `SSG_LIB_Commands` | ILS_BTMT_*, ILS_ETF_*, ILS_K*_*, ILS_GK*_* | -| VarioFoerderer | `VarioFoerderer` | FOERDERANLAGE, VARIOFOERDERER_EDIT | +| VarioFoerderer | `VarioFoerderer` | FOERDERANLAGE, VARIOFOERDERER_EDIT, Vario_Kette_Merge | | Gefaellestrecke | `Gefaellestrecke` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT | | Omniflo (komplett) | `OmniModulInsert` | OMNI_APB_*, OMNI_W*_*, OMNI_AP*, OMNI_TEF_*, OMNI_TV_*, OMNI_EDIT | | Export | `export` | EXPORTSIVAS, EXPORTCSV, CALLPYTHON | @@ -92,7 +92,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 | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standardfall + Werteingabe per DCL-Dialog (`vfs-standard-dialog-ablauf` in vf_standard.lsp); Doppelklick auf VF_n-Block ruft VARIOFOERDERER_EDIT (nur fuer per Dialog erstellte Standard-Bloecke, erkannt an XDATA) | +| `VarioFoerderer.lsp` (Wrapper fuer `vf_core.lsp`/`vf_standard.lsp`/`vf_etage.lsp`/`vf_linienzug.lsp`) | FOERDERANLAGE, VARIOFOERDERER_EDIT, Vario_Kette_Merge | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standardfall + Werteingabe per DCL-Dialog (`vfs-standard-dialog-ablauf` in vf_standard.lsp); Doppelklick auf VF_n-Block ruft VARIOFOERDERER_EDIT (nur fuer per Dialog erstellte Standard-Bloecke, erkannt an XDATA); `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) | | `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 | diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index d1f7633..5d893a2 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -32,10 +32,10 @@ ;; automatisch als VF eingestuft wird) kann ein sichtbarer Knick entstehen: ;; vfs-mitte-teil beginnt sein erstes Element (GF1) immer fest bei 3 Grad, ;; unabhaengig vom Neigungswinkel des vorangehenden GF-Segments. -;; - Die Fusspunkte von AS-/ES-Element (aus-dx/ein-dx) werden NICHT von der -;; angegebenen Segmentlaenge abgezogen (anders als in gf-linienzug-modus). -;; Das erste bzw. letzte Segment kann dadurch um bis zu aus-dx/ein-dx mm -;; (typischerweise wenige hundert mm) laenger werden als eingegeben. +;; - Die Fusspunkte von AS-/ES-Element (aus-dx/dz bzw. ein-dx/dz) werden vom +;; Erst- bzw. Letzt-Segment abgezogen (vfl-as-deltaL/H-korrigiert bzw. die +;; Separator+ES-Reservierung im Kettenende-Modus), damit der gepickte +;; Endpunkt vom gebauten GF/VF-Koerper exakt getroffen wird. ;; ============================================================ ;; Attribut-Definitionen fuer den Linienzug-Block kommen aus dem gemeinsamen @@ -142,17 +142,79 @@ ;; berechne-alle-winkel ausfuehren (mit Linienzug-FESTE_HORIZONTAL = 1300) und ;; den Winkel waehlen lassen. Rueckgabe: (winkel L_GF L_VF) oder nil. -(defun vfl-vf-winkel (deltaL deltaH richtung) - (vfl-waehle-winkel - (nth 3 (berechne-alle-winkel deltaL deltaH richtung *vfl-feste-horizontal*)))) +;; aus-dx/aus-dz temporaer nullen: an jeder Aufrufstelle (ueber vfl-vf- +;; entscheidung) ist ein evtl. vorhandenes AS-Element bereits real eingefuegt +;; und deltaL bereits aus dessen echtem KS_AUS neu berechnet (vfl-projiziere- +;; distanz) - der Platzbedarf ist also schon "verbraucht" und darf nicht +;; nochmal in berechne-alle-winkel abgezogen werden (sonst fehlt am Ende +;; systematisch genau dieser Betrag, aus-dx typischerweise mehrere hundert mm). +;; ein-dx/ein-dz bleiben unangetastet: das ES-Element ist an dieser Stelle noch +;; nicht gebaut (folgt erst nach der "Kettenende?"-Frage) - konsistent mit +;; vfl-body-zerlegung, die ebenfalls nur aus-dx/aus-dz nullt. +(defun vfl-vf-winkel (deltaL deltaH richtung / save-ausdx save-ausdz res) + (setq save-ausdx aus-dx save-ausdz aus-dz) + (setq aus-dx 0.0 aus-dz 0.0) + (setq res + (vfl-waehle-winkel + (nth 3 (berechne-alle-winkel deltaL deltaH richtung *vfl-feste-horizontal*)))) + (setq aus-dx save-ausdx aus-dz save-ausdz) + res) + +;; Rueckgabe: (typ winkel L_GF L_VF) - erzwingt IMMER eine VF-Einheit (nie GF), +;; genutzt sowohl von vfl-segment-entscheidung (automatische Zweig-Auswahl) als +;; auch direkt vom expliziten "Ab/Auf VF"-Menuepunkt in Modus 1 (vf-linienzug-modus). +;; typ="VF": winkel = best-winkel (0 = Horizontale Mitte), L_GF/L_VF wie +;; berechne-alle-winkel bzw. berechne-horizontale-mitte +;; typ=nil : keine VF-Einheit fuer dieses deltaL/deltaH geometrisch moeglich +(defun vfl-vf-entscheidung (deltaL deltaH richtung / + winkel-natuerlich wahl horizontal-info) + (if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek)) + (cond + ;; Zu kurz fuer eine VF-Einheit: Umlenkstation (500 mm) + Motorstation + ;; (500 mm) belegen zusammen 1000 mm deltaL. + ((< deltaL 1000.0) (list nil nil nil nil)) + + ;; Segment ohne messbare Hoehenaenderung: kein sinnvolles VF + ((< deltaH 1.0) (list nil nil nil nil)) + + ;; Steigend: bei mehreren gueltigen Winkeln waehlt der Nutzer (vfl-vf-winkel). + ((= richtung "Auf") + (setq wahl (vfl-vf-winkel deltaL deltaH "Auf")) + (if wahl + (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) + (list nil nil nil nil))) + + ;; Fallend: natuerlichen Neigungswinkel bestimmen (atan der Schraege). + ;; steiler als 3 Grad -> absteigender VarioFoerderer (VF-ab) + ;; sonst -> VF (Horizontale Mitte oder diskreter Winkel) + (t + (setq winkel-natuerlich (* (atan (/ deltaH deltaL)) (/ 180.0 pi))) + (if (> winkel-natuerlich 3.0) + (progn + (setq wahl (vfl-vf-winkel deltaL deltaH "Ab")) + (if wahl + (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) + (list nil nil nil nil))) + (progn + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (if (and horizontal-info (caddr horizontal-info)) + (list "VF" 0 (car horizontal-info) (cadr horizontal-info)) + (progn + (setq wahl (vfl-vf-winkel deltaL deltaH "Ab")) + (if wahl + (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) + (list nil nil nil nil))))) + ) + ) + ) +) ;; Rueckgabe: (typ winkel L_GF L_VF) ;; typ="GF": winkel = kontinuierlicher Neigungswinkel, L_GF/L_VF ungenutzt (nil) ;; typ="VF": winkel = best-winkel (0 = Horizontale Mitte), L_GF/L_VF wie ;; berechne-alle-winkel bzw. berechne-horizontale-mitte ;; typ=nil : weder GF noch VF fuer dieses deltaL/deltaH geometrisch moeglich -(defun vfl-segment-entscheidung (deltaL deltaH richtung / - winkel-natuerlich wahl horizontal-info) +(defun vfl-segment-entscheidung (deltaL deltaH richtung / winkel-natuerlich) (if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek)) (cond ;; Zu kurz fuer eine VF-Einheit: Umlenkstation (500 mm) + Motorstation @@ -168,43 +230,17 @@ ((< deltaH 1.0) (list nil nil nil nil)) ;; Steigend: Gefaelle kann nicht steigen -> nur VF moeglich. - ;; Bei mehreren gueltigen Winkeln waehlt der Nutzer (vfl-vf-winkel). - ((= richtung "Auf") - (setq wahl (vfl-vf-winkel deltaL deltaH "Auf")) - (if wahl - (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) - (list nil nil nil nil))) + ((= richtung "Auf") (vfl-vf-entscheidung deltaL deltaH richtung)) ;; Fallend: natuerlichen Neigungswinkel bestimmen (atan der Schraege). ;; Eine reine Gefaellestrecke ist nie steiler als 3 Grad, daher: ;; ~3 Grad (Toleranzband) -> reine GF (fest 3 Grad) - ;; steiler als 3 Grad -> absteigender VarioFoerderer (VF-ab) - ;; flacher als 3 Grad -> VF (Horizontale Mitte oder diskreter Winkel) + ;; sonst -> VF (vfl-vf-entscheidung) (t (setq winkel-natuerlich (* (atan (/ deltaH deltaL)) (/ 180.0 pi))) - (cond - ;; ~3 Grad -> reine 3-Grad-Gefaellestrecke - ((<= (abs (- winkel-natuerlich 3.0)) *vfl-gf-winkel-toleranz*) - (list "GF" 3.0 nil nil)) - - ;; steiler als 3 Grad -> VF-ab (Nutzer waehlt aus gueltigen Winkeln) - ((> winkel-natuerlich 3.0) - (setq wahl (vfl-vf-winkel deltaL deltaH "Ab")) - (if wahl - (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) - (list nil nil nil nil))) - - ;; flacher als 3 Grad -> VF: erst Horizontale Mitte, dann diskreter Winkel - (t - (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) - (if (and horizontal-info (caddr horizontal-info)) - (list "VF" 0 (car horizontal-info) (cadr horizontal-info)) - (progn - (setq wahl (vfl-vf-winkel deltaL deltaH "Ab")) - (if wahl - (list "VF" (nth 0 wahl) (nth 1 wahl) (nth 2 wahl)) - (list nil nil nil nil))))) - ) + (if (<= (abs (- winkel-natuerlich 3.0)) *vfl-gf-winkel-toleranz*) + (list "GF" 3.0 nil nil) + (vfl-vf-entscheidung deltaL deltaH richtung)) ) ) ) @@ -246,29 +282,71 @@ ;; 2-Argument-Form genutzt (Gummiband), ohne (base=nil) die reine Prompt-Form. ;; Zweck: ein Testmock kann diese feste Signatur ersetzen (getpoint selbst kann ;; als defun nicht 1- UND 2-argumentig gemockt werden). -(defun vfl-getpoint (base prompt) - (if base (getpoint base prompt) (getpoint prompt))) +;; DYNMODE waehrend des Picks auf 3 (Pointer- + Dimensions-Input) setzen, damit +;; BricsCAD Distanz/Winkel dynamisch am Cursor anzeigt (Laengen-Feedback beim +;; Picken) - danach den Nutzer-Wert wiederherstellen. +(defun vfl-getpoint (base prompt / old-dynmode pt) + (setq old-dynmode (vl-catch-all-apply 'getvar (list "DYNMODE"))) + (if (vl-catch-all-error-p old-dynmode) (setq old-dynmode nil)) + (if old-dynmode (vl-catch-all-apply 'setvar (list "DYNMODE" 3))) + (setq pt (if base (getpoint base prompt) (getpoint prompt))) + (if old-dynmode (vl-catch-all-apply 'setvar (list "DYNMODE" old-dynmode))) + pt +) -;; Rueckgabe: (deltaL hz) oder nil bei Abbruch. -(defun vfl-neue-linie-messen (p-akt hz-vorgabe / p2 rad ux uy) - (setq p2 (vfl-getpoint p-akt - (if hz-vorgabe - "\n\nEndpunkt entlang Fahrtrichtung waehlen (bestimmt die Laenge): " - "\n\nEndpunkt der Linie (XY, beliebige Richtung): "))) - (if (null p2) - nil - (if hz-vorgabe +;; Rueckgabe: (deltaL hz p2) oder nil bei Abbruch. p2 = der rohe gepickte +;; Punkt (fuer Diagnose/Nachrechnung nach dem AS-Element-Insert, siehe +;; 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) + (setq fertig nil) + (while (not fertig) + (setq p2 (vfl-getpoint p-akt + (if hz-vorgabe + "\n\nEndpunkt entlang Fahrtrichtung waehlen (bestimmt die Laenge): " + "\n\nEndpunkt der Linie (XY, beliebige Richtung): "))) + (if (null p2) + (setq ergebnis nil fertig t) (progn - (setq rad (* (float hz-vorgabe) (/ pi 180.0)) ux (cos rad) uy (sin rad)) - ;; Skalarprojektion des gewaehlten Vektors auf die Fahrtrichtung - (list (+ (* (- (car p2) (car p-akt)) ux) (* (- (cadr p2) (cadr p-akt)) uy)) - hz-vorgabe) + ;; Freie Richtung (nur beim allerersten Segment der Kette, hz-vorgabe + ;; noch nil): auf das feste 30-Grad-Raster des Weltkoordinatensystems + ;; snappen - im System sind Fahrtrichtungen immer 30/60/90-Grad- + ;; Vielfache relativ zur Zeichnung, nie ein freier Zwischenwert. Bei + ;; einem Retry (zu lang) bleibt hz-vorgabe bewusst nil, damit die + ;; Richtung erneut frei gewaehlt werden kann. + (setq hz-aktuell (if hz-vorgabe hz-vorgabe (vfl-hz-snappen-absolut (vfl-planar-hz p-akt p2)))) + (setq rad (* (float hz-aktuell) (/ pi 180.0)) ux (cos rad) uy (sin rad)) + ;; Skalarprojektion des gewaehlten Vektors auf die (ggf. gesnappte) + ;; Fahrtrichtung + (setq deltaL (+ (* (- (car p2) (car p-akt)) ux) (* (- (cadr p2) (cadr p-akt)) uy))) + (if (> deltaL 25000.0) + (princ (strcat "\n>>> FEHLER: Laenge " (rtos (/ deltaL 1000.0) 2 2) + " m ueberschreitet die Foerderer-Maximallaenge von 25 m" + " - bitte anderen Endpunkt waehlen.")) + (progn + (setq ergebnis (list deltaL hz-aktuell p2)) + (setq fertig t) + ) + ) ) - (list (vfl-planar-dist p-akt p2) (vfl-planar-hz p-akt p2)) ) ) + ergebnis ) +;; Planare Projektionsdistanz von neu-basis zu ziel-punkt entlang der +;; Fahrtrichtung hz (Grad) - wird genutzt, um nach dem AS-Element-Insert die +;; tatsaechlich noetige Restlaenge (vom echten KS_AUS zum urspruenglich +;; gepickten Punkt) direkt zu berechnen. Bewusst KEINE Fussabdruck-Schaetzung +;; (weder aus KS_EIN->KS_AUS noch aus Block-Ursprung->KS_AUS): beide ignorieren +;; die Dreh­teller-Rotation, die insert-block-mixed-to-ks beim echten Einfuegen +;; anwendet, und liefern empirisch bestaetigt einen falschen Wert (~210mm +;; Schaetzung vs. ~420mm tatsaechlich noetiger Versatz bei AS_Element_30). +(defun vfl-projiziere-distanz (neu-basis ziel-punkt hz / rad) + (setq rad (* (float hz) (/ pi 180.0))) + (+ (* (- (car ziel-punkt) (car neu-basis)) (cos rad)) + (* (- (cadr ziel-punkt) (cadr neu-basis)) (sin rad)))) + ;; Rahmen am Ende eines vfs-*-Bausteins: die Bausteine (Entry/Koerper/Exit) ;; enden IMMER auf der 3-Grad-Basisneigung (siehe Prinzipien-Dok Abschnitt 6). (defun vfl-frame-3grad (punkt hz) @@ -330,32 +408,84 @@ ;; (vfl-nach-3grad). Der auf_3-Eintritt wird nur gesetzt, wenn der Frame noch ;; NICHT flach ist (sonst bleibt die laufende flache Zone erhalten). Separatoren ;; VOR/NACH liegen in der 0-Grad-Ebene. Rueckgabe: neuer Frame (flach, 0 Grad). -(defun vfl-baue-horizontal-koerper (frame hz dL / pt m1 sep-vor) +;; ziel-modus=T: dL ist die GESAMT-Zielstrecke ab pt (der Nutzer hat einen +;; Endpunkt gepickt, den die Kette exakt treffen soll). In diesem Fall werden +;; ALLE Fragen, die die spaeter tatsaechlich gebaute Laenge beeinflussen +;; (Separator VOR/NACH, UND "Ist der Endpunkt der Foerderer?"), VOR der +;; Laengenberechnung gestellt - erst wenn wirklich alle Informationen da sind, +;; wird dL final berechnet und die horizontale Strecke gebaut. Das verhindert, +;; dass die Kette am Ende ueber den gepickten Punkt hinausragt, nur weil +;; nachtraeglich noch ein Separator oder eine Motorstation dazukommt. +;; gf2-laenge: die (schon feststehende) GF2-Laenge aus der GF-Verteilungs- +;; Frage (L_GF2-bau in vfl-vf-einheit) - wird bei Antwort "1" (nur Motor- +;; station) MIT reserviert, da vfs-vf-exit sie direkt danach anbaut. Bei +;; Antwort "3" (Kettenende definieren) NICHT reservieren: dort berechnet +;; vfl-body-abschluss ein eigenes, unabhaengiges ziel-gf2 (siehe dort) - hier +;; unbekannt und irrelevant. +;; Rueckgabe bei ziel-modus=T: (frame ist-endpunkt-antwort) - der Aufrufer +;; (vfl-vf-einheit) muss die Frage dann NICHT erneut stellen. Bei ziel-modus= +;; nil (Default/mid-chain-Fortsetzung): unveraendertes Verhalten, Rueckgabe +;; nur frame. +(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)) (princ (ssg-text "vfl-sep-vor-frage")) (princ (ssg-text "vfl-ja")) (princ (ssg-text "vfl-nein")) (setq sep-vor (= (getstring (ssg-text "vfl-prompt-wahl-1-2-def2")) "1")) - ;; auf_3-Eintritt nur, wenn noch NICHT flach (sonst flache Zone fortsetzen) + (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- + ;; Fussabdruck (gemessen, nicht aus der Tabellen-Masse geschaetzt - die + ;; stimmt nach der Rotation nicht mehr exakt) wird von dL abgezogen, damit + ;; das horizontale Stueck am gewuenschten Zielpunkt endet. (if (not (vfl-frame-flach-p frame)) (progn + (setq pt-vor-bogen pt) (setq m1 (get-bogen-mass bogen-auf 3)) (princ (ssg-text "vfl-bogen-auf3-uebergang")) (setq pt (insert-rotated-block-with-ks "Vario_Bogen_auf_3_TEF_rechts" pt - (ssg-cfg-or "vario" "gefaelle_winkel" 3) (car m1) (caddr m1) hz)))) + (ssg-cfg-or "vario" "gefaelle_winkel" 3) (car m1) (caddr m1) hz)) + (setq dL (max 100.0 (- dL (vfl-projiziere-distanz pt-vor-bogen pt hz)))))) + ;; Separator NACH abfragen (noch nicht bauen) - im Ziel-Modus VOR der + ;; Laengenberechnung, damit der Fussabdruck feststeht. + (princ (ssg-text "vfl-sep-nach-frage")) + (princ (ssg-text "vfl-ja")) + (princ (ssg-text "vfl-nein")) + (setq sep-nach (= (getstring (ssg-text "vfl-prompt-wahl-1-2-def2")) "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 + ;; (Vario_Bogen_ab_3 + Motorstation) wird nur reserviert, wenn tatsaechlich + ;; sofort geschlossen wird (Antwort 1 oder 3). + (if ziel-modus + (progn + (princ (ssg-text "vfl-ist-endpunkt-frage")) + (princ (ssg-text "vfl-ja-nur-motorstation")) + (princ (ssg-text "vfl-nein-weiterbauen")) + (princ (ssg-text "vfl-ja-motorstation-kettenende")) + (setq ist-ende-antwort (getstring (ssg-text "vfl-prompt-wahl-1-3-def2"))) + (cond + ((= ist-ende-antwort "1") + (setq dL (max 100.0 (- dL (car (get-bogen-mass bogen-ab 3)) 500.0 + (* (if gf2-laenge gf2-laenge 0.0) + (cos (* 3.0 (/ pi 180.0)))))))) + ((= ist-ende-antwort "3") + (setq dL (max 100.0 (- dL (car (get-bogen-mass bogen-ab 3)) 500.0)))) + ) + ) + ) ;; optionaler Separator VOR - in der horizontalen Ebene (0 Grad) (if sep-vor (setq pt (vfl-sep-hz pt hz))) ;; horizontale Zwischenstrecke (0 Grad) (princ (ssg-textf "vfl-horizontale-zwischenstrecke" (list (rtos dL 2 2)))) (setq pt (insert-inclined-scaled-block "Staustrecke_SP_1000_mm" pt dL 0 hz)) (vfl-acc-vf-seg "horizontal" 0 dL) - ;; optionaler Separator NACH - ebenfalls horizontal (0 Grad) - (princ (ssg-text "vfl-sep-nach-frage")) - (princ (ssg-text "vfl-ja")) - (princ (ssg-text "vfl-nein")) - (if (= (getstring (ssg-text "vfl-prompt-wahl-1-2-def2")) "1") (setq pt (vfl-sep-hz pt hz))) + ;; optionaler Separator NACH (jetzt tatsaechlich bauen) + (if sep-nach (setq pt (vfl-sep-hz pt hz))) ;; KEIN ab_3 mehr -> das Stueck ENDET FLACH (0 Grad) - (make-frame-from-dir pt (hz-winkel->xu hz 0.0)) + (setq frame (make-frame-from-dir pt (hz-winkel->xu hz 0.0))) + (if ziel-modus (list frame ist-ende-antwort) frame) ) ;; ============================================================ @@ -493,7 +623,11 @@ (defun vfl-vf-einheit (frame hz1 richtung1 winkel1 L_GF1 L_VF1 gf-am-ausgang / p-umlenk vf-count antwort L_GF-eff L_GF1-bau L_GF2-bau linie-mess dL dH hn hzn richtn ent typ w lgf lvf - letzt-hz fertig ziel-ende ziel-gf2 res3 gf2-eff) + letzt-hz fertig ziel-ende ziel-gf2 res3 gf2-eff entry-start + res-h vor-antwort es-gewuenscht es-antwort save-eindx save-eindz) + ;; Vorbelegung: ES gewuenscht (Default) - nur bei "3 - Kettenende definieren" + ;; wird explizit gefragt und ggf. auf nil gesetzt (siehe dort). + (setq es-gewuenscht t) ;; Gesamte Staustrecke (mind. *vfl-gf-min-laenge*) auf Einlauf/Ausgang verteilen. (setq L_GF-eff (max L_GF1 *vfl-gf-min-laenge*)) (if gf-am-ausgang @@ -501,6 +635,7 @@ (setq L_GF1-bau L_GF-eff L_GF2-bau 0.0)) ; alles am Einlauf ;; --- Eingang: GF1 + Separator + Umlenkstation --- + (setq entry-start (car frame)) (setq frame (vfl-frame-3grad (vfs-vf-entry (car frame) L_GF1-bau hz1) hz1)) (if (> L_GF1-bau 0.1) (vfl-acc-gf-seg L_GF1-bau (ssg-cfg-or "vario" "gefaelle_winkel" 3))) @@ -509,8 +644,28 @@ ;; --- Erstes Koerper-Sub-Segment --- ;; winkel1=0 => horizontaler Anfang (Option 3): mit Separator-vor/nach-Abfrage. + ;; L_VF1 wird bei winkel1=0 vom Aufrufer (Modus 1, Option 3) als GESAMT- + ;; Zielstrecke ab entry-start (dem gepickten Endpunkt) verstanden - abgezogen + ;; werden daher: + ;; 1) der reale Eingang-Fussabdruck (GF1+Separator+Umlenkstation, GEMESSEN + ;; statt geschaetzt, ueber entry-start/p-umlenk) + ;; 2) der Fussabdruck fuer einen MOEGLICHEN sofortigen Abschluss direkt + ;; nach diesem Stueck: Vario_Bogen_ab_3 (Ausgangs-Uebergang zurueck auf + ;; 3 Grad, Tabellen-Mass wie in vfl-nach-3grad) + Motorstation (500mm). + ;; Falls die Kette hier NICHT sofort endet, wird dieser Fussabdruck + ;; trotzdem reserviert - konsistent mit dem "Kettenende"-Verhalten an + ;; anderer Stelle (lieber vorsichtig reservieren als ueberschiessen). (if (= (fix winkel1) 0) - (setq frame (vfl-baue-horizontal-koerper frame hz1 L_VF1)) + (progn + ;; ziel-modus=T: Separator VOR/NACH + "Ist der Endpunkt der Foerderer?" + ;; werden INNERHALB von vfl-baue-horizontal-koerper VOR der Laengen- + ;; berechnung gestellt (siehe dortiger Kommentar) - die Antwort kommt + ;; hier zurueck, damit die Schleife unten sie nicht nochmal erfragt. + (setq res-h (vfl-baue-horizontal-koerper frame hz1 + (max 100.0 (- L_VF1 (vfl-projiziere-distanz entry-start p-umlenk hz1))) + t L_GF2-bau)) + (setq frame (car res-h) vor-antwort (cadr res-h)) + ) (progn (setq frame (vfl-frame-3grad (vfs-vf-koerper (car frame) richtung1 winkel1 L_VF1 hz1) hz1)) (vfl-acc-vf-seg richtung1 winkel1 L_VF1) @@ -522,17 +677,39 @@ ;; --- Fortsetzungs-Schleife bis Foerderer-Ende --- (setq fertig nil) (while (not fertig) - (princ (ssg-text "vfl-ist-endpunkt-frage")) - (princ (ssg-text "vfl-ja-nur-motorstation")) - (princ (ssg-text "vfl-nein-weiterbauen")) - (princ (ssg-text "vfl-ja-motorstation-kettenende")) - (setq antwort (getstring (ssg-text "vfl-prompt-wahl-1-3-def2"))) + ;; War die Frage schon in vfl-baue-horizontal-koerper (ziel-modus) oder + ;; bei der letzten Runde "Horizontaler Foerderer" beantwortet, hier NICHT + ;; erneut fragen - sonst normal abfragen. + (if vor-antwort + (setq antwort vor-antwort vor-antwort nil) + (progn + (princ (ssg-text "vfl-ist-endpunkt-frage")) + (princ (ssg-text "vfl-ja-nur-motorstation")) + (princ (ssg-text "vfl-nein-weiterbauen")) + (princ (ssg-text "vfl-ja-motorstation-kettenende")) + (setq antwort (getstring (ssg-text "vfl-prompt-wahl-1-3-def2"))) + ) + ) (if (= antwort "1") (setq fertig t) (if (= antwort "3") ;; --- Option 3: Kettenende exakt am Zielpunkt (nur EIN Motor) --- (progn + ;; ES-Element hier gewuenscht? Falls nein, ein-dx/ein-dz waehrend der + ;; Zerlegung (vfl-body-abschluss -> vfl-body-zerlegung -> berechne- + ;; alle-winkel) temporaer nullen, damit KEIN ES-Fussabdruck reserviert + ;; wird - die Kette endet dann direkt am Zielpunkt ohne Separator+ES. + (princ "\n\nES-Element setzen?") + (princ "\n 1 - Ja") + (princ "\n 2 - Nein (Kette endet direkt am Zielpunkt)") + (setq es-antwort (getstring "\nIhre Wahl (1/2) [1]: ")) + (setq es-gewuenscht (/= es-antwort "2")) + (if (not es-gewuenscht) + (progn (setq save-eindx ein-dx save-eindz ein-dz) + (setq ein-dx 0.0 ein-dz 0.0))) (setq res3 (vfl-body-abschluss frame letzt-hz p-umlenk)) + (if (not es-gewuenscht) + (setq ein-dx save-eindx ein-dz save-eindz)) (if res3 (setq frame (nth 0 res3) vf-count (+ vf-count (nth 1 res3)) @@ -560,8 +737,13 @@ (setq dL (car linie-mess) hzn (cadr linie-mess)) (if (> dL 1.0) (progn - ;; inkl. Separator-vor/nach-Abfrage - (setq frame (vfl-baue-horizontal-koerper frame hzn dL)) + ;; ziel-modus=T: Separator VOR/NACH + "Ist der Endpunkt der + ;; Foerderer?" werden VOR der Laengenberechnung gestellt + ;; (siehe vfl-baue-horizontal-koerper) - Antwort kommt hier + ;; zurueck und wird in der naechsten Schleifen-Runde + ;; verwendet, statt erneut zu fragen. + (setq res-h (vfl-baue-horizontal-koerper frame hzn dL t L_GF2-bau)) + (setq frame (car res-h) vor-antwort (cadr res-h)) (setq vf-count (1+ vf-count) letzt-hz hzn) (vfl-20m-check p-umlenk (car frame)) ) @@ -625,7 +807,43 @@ (vfs-vf-exit (car frame) gf2-eff letzt-hz nil) letzt-hz)) (if (> gf2-eff 0.1) (vfl-acc-gf-seg gf2-eff (ssg-cfg-or "vario" "gefaelle_winkel" 3))) - (list frame vf-count ziel-ende) + (list frame vf-count ziel-ende es-gewuenscht) +) + +;; Rundet einen Winkel (Grad) auf das naechste 30-Grad-Vielfache DES WELT- +;; KOORDINATENSYSTEMS (absolut, nicht relativ zu einer Vorgaenger-Richtung). +;; Im System sind Fahrtrichtungen immer 30/60/90-Grad-Vielfache relativ zur +;; Zeichnung selbst - jede Abweichung (freier erster Klick, Bogen-Block- +;; Zeichnungsungenauigkeit) wird damit auf den naechsten gueltigen absoluten +;; Wert korrigiert, statt sich ueber die Kette aufzusummieren. +(defun vfl-hz-snappen-absolut (hz / n) + (setq n (/ hz 30.0)) + (setq n (if (>= n 0.0) (fix (+ n 0.5)) (fix (- n 0.5)))) + (* n 30.0) +) + +;; Rotiert einen kompletten Frame (P xu yu zu) um die WELT-Z-Achse um delta +;; Grad - im Gegensatz zu (make-frame-from-dir P neue-xu) bleibt dabei die +;; urspruengliche Rollung (yu/zu, aus der echten Blockgeometrie gemessen) +;; erhalten. WICHTIG: make-frame-from-dir erzeugt yu/zu nach einer generischen +;; Konvention, die bei Bloecken mit eigener, nicht-generischer Ausrichtung +;; (z.B. Vario-Kurve) NICHT zur tatsaechlichen Verkettung passt - das fuehrte +;; empirisch zu einer um 90 Grad verdrehten Motorstation nach einem gesnappten +;; horizontalen Bogen. Eine reine Z-Drehung (nur X/Y von xu/yu/zu betroffen, +;; Z-Komponente unveraendert) behebt die winzige Snapping-Abweichung, ohne die +;; Rollung anzutasten. +(defun vfl-vec-um-z-drehen (v c s) + (list (- (* (car v) c) (* (cadr v) s)) + (+ (* (car v) s) (* (cadr v) c)) + (caddr v)) +) +(defun vfl-frame-um-z-drehen (frame delta / rad c s) + (setq rad (* (float delta) (/ pi 180.0))) + (setq c (cos rad) s (sin rad)) + (list (car frame) + (vfl-vec-um-z-drehen (cadr frame) c s) + (vfl-vec-um-z-drehen (caddr frame) c s) + (vfl-vec-um-z-drehen (cadddr frame) c s)) ) ;; GF-Bogen (horizontale Kurve, Neigung bleibt wie im aktuellen Frame). @@ -633,14 +851,21 @@ ;; Nicht-interaktiver Kern: GF-Bogen mit gegebenem Winkel/Seite einfuegen. ;; Genutzt von der interaktiven Abfrage UND von den Pfad-Modi (Winkel/Seite ;; aus der Geometrie). Rueckgabe: neuer Frame. -(defun vfl-insert-gf-bogen-block (frame bwinkel bseite / blockname) +(defun vfl-insert-gf-bogen-block (frame bwinkel bseite / blockname neuer-frame hz-gemessen hz-gesnappt) (setq blockname (gf-bogen-blockname bwinkel bseite)) (princ (ssg-textf "vfl-fuege-block-ein" (list blockname))) ;; GF-Bogen zaehlen (Seite L/R + Winkel) -> Attribut GF_Bogen_L/R_xx (setq *vfl-acc-gfbogen* (vfl-inc-count *vfl-acc-gfbogen* (strcat (if (= bseite "rechts") "R" "L") "_" (itoa bwinkel)))) - (insert-block-ks-to-ks blockname frame) + (setq neuer-frame (insert-block-ks-to-ks blockname frame)) + (setq hz-gemessen (car (frame->hz-winkel neuer-frame))) + (setq hz-gesnappt (vfl-hz-snappen-absolut hz-gemessen)) + ;; Reine Z-Drehung statt make-frame-from-dir-Neuaufbau: erhaelt die aus dem + ;; Block gemessene Rollung (yu/zu) - siehe Kommentar bei vfl-frame-um-z-drehen. + (if (> (abs (- hz-gemessen hz-gesnappt)) 0.0001) + (setq neuer-frame (vfl-frame-um-z-drehen neuer-frame (- hz-gesnappt hz-gemessen)))) + neuer-frame ) ;; Interaktiv (i18n): GF-Bogen-Winkel + Seite abfragen, dann Kern aufrufen. @@ -670,7 +895,9 @@ ;; (Winkel/Seite aus der Geometrie, Variante abgefragt). Rueckgabe: neuer Frame. ;; Die Vario_Kurve-Bloecke fuehren KS_EIN/KS_AUS als KSYS_EIN/KSYS_AUS - ;; extract-ks-from-block-raw normalisiert das (siehe ks-normalize-name). -(defun vfl-insert-vario-kurve-block (frame kwinkel kseite kvariante / blockname hz flach-frame) +(defun vfl-insert-vario-kurve-block (frame kwinkel kseite kvariante / + blockname hz flach-frame neuer-frame + hz-gemessen hz-gesnappt) (setq blockname (vfl-kurve-blockname kwinkel kseite kvariante)) (princ (ssg-textf "vfl-fuege-block-ein" (list blockname))) ;; Vario-Kurve zaehlen (Variante A=aussen/I=innen + Winkel) -> VF_Bogen_A/I_xx @@ -682,7 +909,18 @@ ;; daher auf 0 Grad abgeflacht (Position + Fahrtrichtung bleiben erhalten). (setq hz (car (frame->hz-winkel frame))) (setq flach-frame (make-frame-from-dir (car frame) (hz-winkel->xu hz 0.0))) - (insert-block-ks-to-ks blockname flach-frame) + (setq neuer-frame (insert-block-ks-to-ks blockname flach-frame)) + ;; Auf den absoluten 30-Grad-Raster snappen (siehe vfl-hz-snappen-absolut) - + ;; gleiche Zeichnungsungenauigkeit wie bei GF-Bogen moeglich. Reine Z-Drehung + ;; statt make-frame-from-dir-Neuaufbau: erhaelt die aus dem Block gemessene + ;; Rollung (yu/zu) - siehe Kommentar bei vfl-frame-um-z-drehen. Ein Neuaufbau + ;; ueber make-frame-from-dir fuehrte hier empirisch zu einer um 90 Grad + ;; verdrehten Motorstation NACH der Vario-Kurve. + (setq hz-gemessen (car (frame->hz-winkel neuer-frame))) + (setq hz-gesnappt (vfl-hz-snappen-absolut hz-gemessen)) + (if (> (abs (- hz-gemessen hz-gesnappt)) 0.0001) + (setq neuer-frame (vfl-frame-um-z-drehen neuer-frame (- hz-gesnappt hz-gemessen)))) + neuer-frame ) ;; Vario-Kurve (horizontale Kurve, Neigung bleibt wie im aktuellen Frame). @@ -714,30 +952,48 @@ ;; TEIL 3: KETTENANFANG (AS) / KETTENENDE (ES) ;; ============================================================ -;; AS-Element am Kettenanfang. typ="GF": AS wird gekippt eingefuegt (KS_EIN -;; auf den Neigungswinkel des ersten Segments ausgerichtet), wie in -;; Gefaellestrecke. typ="VF": AS wird flach eingefuegt (nur hz, keine -;; Neigung), wie im Standard-VarioFoerderer (vfs-as-teil). +;; AS-Element am Kettenanfang. Wird IMMER FLACH eingefuegt (KS_EIN ohne +;; Neigung) - per Einzel-Insert-Test in BricsCAD bestaetigt (2026-07-24): +;; das AS-Element selbst hat keine Neigung, die Neigung beginnt erst im +;; nachfolgenden GF-Koerper (vfl-insert-gf-segment). typ/winkel sind aus +;; Call-Kompatibilitaet weiterhin Parameter, werden aber fuer die AS-eigene +;; Ausrichtung nicht mehr verwendet (KEIN vertikaler Tilt mehr, unabhaengig +;; vom folgenden Segmenttyp). ;; Rueckgabe: Frame am AS-Ausgang (KS_AUS). (defun vfl-insert-as-element (typ startpunkt hz winkel as-seite / - ein-hz-as rad-h rad-v xu-ein as-turn) - (if (= typ "GF") + ein-hz-as rad-h xu-ein as-turn) + ;; Schwenk aus dem Block messen -> KS_EIN so drehen, dass KS_AUS entlang hz + ;; zeigt (Grundriss-Versatz des 30-Grad-Elements bleibt beruecksichtigt). + (setq as-turn (vf-element-plan-turn (strcat "AS_Element_" (vfl-as-winkel) "_" as-seite))) + (setq ein-hz-as (- hz as-turn)) + (setq rad-h (* (float ein-hz-as) (/ pi 180.0))) + (setq xu-ein (list (cos rad-h) (sin rad-h) 0.0)) + (insert-block-mixed-to-ks + (strcat "AS_Element_" (vfl-as-winkel) "_" as-seite) + (make-frame-from-dir startpunkt xu-ein) + (caddr startpunkt) nil "KS_EIN") +) + +;; Kettenanfang-Baustein: falls as-vorhanden, AS-Element einfuegen und die +;; GF/VF-Restlaenge aus dem tatsaechlichen KS_AUS neu berechnen (siehe +;; vfl-projiziere-distanz). Falls NICHT as-vorhanden (Nutzer hat "Kein AS- +;; Element" gewaehlt), beginnt die Kette direkt am Startpunkt - deltaL bleibt +;; die gemessene Rohlaenge (kein Fussabdruck abzuziehen). Rueckgabe: (frame +;; deltaL). +(defun vfl-kettenanfang-baustein (p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden / frame) + (if as-vorhanden (progn - ;; Schwenk aus dem Block messen -> KS_EIN so drehen, dass KS_AUS entlang hz - (setq as-turn (vf-element-plan-turn (strcat "AS_Element_" (vfl-as-winkel) "_" as-seite))) - (setq ein-hz-as (- hz as-turn)) - (setq rad-h (* (float ein-hz-as) (/ pi 180.0))) - (setq rad-v (* (float winkel) (/ pi 180.0))) - (setq xu-ein (list (* (cos rad-h)(cos rad-v)) - (* (sin rad-h)(cos rad-v)) - (- (sin rad-v)))) - (insert-block-mixed-to-ks - (strcat "AS_Element_" (vfl-as-winkel) "_" as-seite) - (make-frame-from-dir startpunkt xu-ein) - (caddr startpunkt) nil "KS_EIN") + (setq frame (vfl-insert-as-element "GF" p-aktuell hz-neu 0.0 as-seite)) + (setq deltaL (vfl-projiziere-distanz (car frame) pick-punkt hz-neu)) + (princ (strcat "\n>>> AS-Element eingefuegt - reale Restlaenge: deltaL=" + (rtos deltaL 2 1) " mm.")) + ) + (progn + (setq frame (make-frame-from-dir p-aktuell (hz-winkel->xu hz-neu 0.0))) + (princ "\n>>> Kein AS-Element - Kette beginnt direkt am Startpunkt.") ) - (make-frame-from-dir (vfs-as-teil startpunkt as-seite hz) (hz-winkel->xu hz 0.0)) ) + (list frame deltaL) ) ;; ES-Winkel (30/90) + Seite erst am Kettenende abfragen. Setzt *vfl-es-winkel* @@ -880,60 +1136,88 @@ ;; gesetzt (Option "Neue Linie BIS Kettenende"). ;; Rueckgabe: (frame anzahl-koerper ende-flag es-seite-oder-nil). (defun vfl-vf-einheit-abschluss (frame hz richtung winkel L_GF L_VF auto-ende / - antwort res es-s ende) + antwort res es-s ende es-gewuenscht) ;; GF-Verteilung: halbe Staustrecke am Ausgang (GF2) oder alles am Einlauf. (princ (ssg-text "vfl-gf-verteilung-header")) (princ (ssg-text "vfl-gf-verteilung-haelfte")) (princ (ssg-text "vfl-gf-verteilung-ganz-einlauf")) (setq antwort (getstring (ssg-text "vfl-prompt-wahl-1-2-def2"))) (setq res (vfl-vf-einheit frame hz richtung winkel L_GF L_VF (= antwort "1"))) - (setq frame (nth 0 res)) + (setq frame (nth 0 res) es-gewuenscht (nth 3 res)) ;; Kettenende? Bei auto-ende (Kettenende-Modus) ohne Frage direkt ES setzen. - ;; Sonst fragen - zwischen einem AS und ES koennen mehrere Foerderer liegen. - ;; auto-ende (Option 4) ODER ziel-ende aus der laufenden Einheit (Option 3): - ;; ohne Frage direkt Separator + ES setzen. - (if (or auto-ende (nth 2 res)) - (setq antwort "1") - (progn - (princ (ssg-text "vfl-ist-kettenende-frage")) - (princ (ssg-text "vfl-ja-separator-es")) - (princ (ssg-text "vfl-nein-weiterbauen")) - (setq antwort (getstring (ssg-text "vfl-prompt-wahl-1-2-def2"))) - ) - ) - (if (= antwort "1") - (progn - (setq es-s (vfl-frage-es-seite)) - (setq frame (vfl-insert-es-element "VF" frame - (car (frame->hz-winkel frame)) 0.0 - (caddr (car frame)) es-s)) - (setq ende t) - ;; Ist-Ziel-Report (Option 3): Soll-ES (aus vfl-body-abschluss) vs. Ist-ES. - (if *vfl-ziel-punkt* - (progn - (princ (ssg-text "vfl-ist-ziel-vergleich-header")) - (princ (ssg-textf "vfl-soll-xyz" - (list (rtos (car *vfl-ziel-punkt*) 2 1) - (rtos (cadr *vfl-ziel-punkt*) 2 1) - (rtos (caddr *vfl-ziel-punkt*) 2 1)))) - (princ (ssg-textf "vfl-ist-xyz" - (list (rtos (car (car frame)) 2 1) - (rtos (cadr (car frame)) 2 1) - (rtos (caddr (car frame)) 2 1)))) - (princ (ssg-textf "vfl-abweichung-xyz" - (list (rtos (- (car (car frame)) (car *vfl-ziel-punkt*)) 2 1) - (rtos (- (cadr (car frame)) (cadr *vfl-ziel-punkt*)) 2 1) - (rtos (- (caddr (car frame)) (caddr *vfl-ziel-punkt*)) 2 1)))) - (setq *vfl-ziel-punkt* nil) - ) + ;; ziel-ende (Option 3 IN der VF-Einheit) OHNE ES-Wunsch (dort abgefragt, + ;; siehe vfl-vf-einheit): Kette endet direkt hier, kein Separator+ES, keine + ;; weitere Frage. ziel-ende MIT ES-Wunsch ODER auto-ende (Option 4): ohne + ;; Frage direkt Separator + ES. Sonst normal fragen - zwischen einem AS und + ;; ES koennen mehrere Foerderer liegen. + (if (and (nth 2 res) (not es-gewuenscht)) + (setq antwort "kein-es") + (if (or auto-ende (nth 2 res)) + (setq antwort "1") + (progn + (princ (ssg-text "vfl-ist-kettenende-frage")) + (princ (ssg-text "vfl-ja-separator-es")) + (princ (ssg-text "vfl-nein-weiterbauen")) + (setq antwort (getstring (ssg-text "vfl-prompt-wahl-1-2-def2"))) ) ) - (progn - (princ (ssg-text "vfl-sep-an-stelle-frage")) - (princ (ssg-text "vfl-ja")) - (princ (ssg-text "vfl-nein")) - (setq antwort (getstring (ssg-text "vfl-prompt-wahl-1-2-def2"))) - (if (= antwort "1") (setq frame (vfl-insert-separator frame))) + ) + (cond + ((= antwort "kein-es") + (setq ende t) + ;; Ist-Ziel-Report auch ohne ES (Vergleich Soll-Zielpunkt vs. tatsaechliches + ;; Kettenende nach GF2/Motor). + (if *vfl-ziel-punkt* + (progn + (princ (ssg-text "vfl-ist-ziel-vergleich-header")) + (princ (ssg-textf "vfl-soll-xyz" + (list (rtos (car *vfl-ziel-punkt*) 2 1) + (rtos (cadr *vfl-ziel-punkt*) 2 1) + (rtos (caddr *vfl-ziel-punkt*) 2 1)))) + (princ (ssg-textf "vfl-ist-xyz" + (list (rtos (car (car frame)) 2 1) + (rtos (cadr (car frame)) 2 1) + (rtos (caddr (car frame)) 2 1)))) + (princ (ssg-textf "vfl-abweichung-xyz" + (list (rtos (- (car (car frame)) (car *vfl-ziel-punkt*)) 2 1) + (rtos (- (cadr (car frame)) (cadr *vfl-ziel-punkt*)) 2 1) + (rtos (- (caddr (car frame)) (caddr *vfl-ziel-punkt*)) 2 1)))) + (setq *vfl-ziel-punkt* nil) + ) + ) + ) + ((= antwort "1") + (setq es-s (vfl-frage-es-seite)) + (setq frame (vfl-insert-es-element "VF" frame + (car (frame->hz-winkel frame)) 0.0 + (caddr (car frame)) es-s)) + (setq ende t) + ;; Ist-Ziel-Report (Option 3): Soll-ES (aus vfl-body-abschluss) vs. Ist-ES. + (if *vfl-ziel-punkt* + (progn + (princ (ssg-text "vfl-ist-ziel-vergleich-header")) + (princ (ssg-textf "vfl-soll-xyz" + (list (rtos (car *vfl-ziel-punkt*) 2 1) + (rtos (cadr *vfl-ziel-punkt*) 2 1) + (rtos (caddr *vfl-ziel-punkt*) 2 1)))) + (princ (ssg-textf "vfl-ist-xyz" + (list (rtos (car (car frame)) 2 1) + (rtos (cadr (car frame)) 2 1) + (rtos (caddr (car frame)) 2 1)))) + (princ (ssg-textf "vfl-abweichung-xyz" + (list (rtos (- (car (car frame)) (car *vfl-ziel-punkt*)) 2 1) + (rtos (- (cadr (car frame)) (cadr *vfl-ziel-punkt*)) 2 1) + (rtos (- (caddr (car frame)) (caddr *vfl-ziel-punkt*)) 2 1)))) + (setq *vfl-ziel-punkt* nil) + ) + ) + ) + (t + (princ (ssg-text "vfl-sep-an-stelle-frage")) + (princ (ssg-text "vfl-ja")) + (princ (ssg-text "vfl-nein")) + (setq antwort (getstring (ssg-text "vfl-prompt-wahl-1-2-def2"))) + (if (= antwort "1") (setq frame (vfl-insert-separator frame))) ) ) (list frame (nth 1 res) ende es-s) @@ -946,7 +1230,9 @@ p-aktuell linie-mess hoehe-neu hoehe-bis deltaL deltaH richtung hz-neu entscheidung typ winkel L_GF L_VF vf-einheit-res frame letzter-typ fertig linie-ende-modus rad3 - anzahl-gf anzahl-vf vfl-nummer lastEnt) + anzahl-gf anzahl-vf vfl-nummer lastEnt + gf-max-winkel gf-ok kettenanfang pick-punkt + as-vorhanden erg) (princ "\n\n=========================================") (princ (ssg-text "vfl-modus1-header")) (princ "\n=========================================") @@ -975,12 +1261,21 @@ (if (null start-hoehe) (setq start-hoehe (caddr startpunkt))) (setq startpunkt (list (car startpunkt) (cadr startpunkt) start-hoehe)) - (setq *vfl-as-winkel* (vf-frage-element-winkel "vf-winkel-aus-header")) ; 30/90 vor Seite - (princ "\n\nAUS-Element (AS_Element_*) - Seite waehlen:") - (princ "\n 1 - Links\n 2 - Rechts") + (princ "\n\nAS-Element setzen?") + (princ "\n 1 - Ja") + (princ "\n 2 - Nein (Kette beginnt direkt mit GF/VF am Startpunkt)") (setq antwort (getstring "\nIhre Wahl (1/2) [1]: ")) - (setq as-seite (if (= antwort "2") "rechts" "links")) - (vf-set-as-masse *vfl-as-winkel* as-seite) ; Masse fuer Variante + (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 + (princ "\n\nAUS-Element (AS_Element_*) - Seite waehlen:") + (princ "\n 1 - Links\n 2 - Rechts") + (setq antwort (getstring "\nIhre Wahl (1/2) [1]: ")) + (setq as-seite (if (= antwort "2") "rechts" "links")) + (vf-set-as-masse *vfl-as-winkel* as-seite) ; Masse fuer Variante + ) + ) ;; ES-Seite wird erst am Kettenende abgefragt (siehe vfl-frage-es-seite), ;; da das ES-Element erst dort eingefuegt wird. @@ -1000,29 +1295,37 @@ ;; Menue immer anzeigen; GF-Bogen nur, wenn bereits ein Frame existiert ;; (am Kettenanfang gibt es keinen Vorgaenger-Rahmen fuer einen Bogen). ;; Lueckenlose Nummerierung: GF-Bogen (nur mit Frame) ist immer Option 1; - ;; ohne Frame ruecken die uebrigen Optionen auf 1..3 auf. + ;; ohne Frame ruecken die uebrigen Optionen auf 1..4 auf. + ;; "Neue Linie" ist in zwei explizite Zweige aufgeteilt (GF / Ab-Auf-VF) - + ;; der Nutzer legt den Segmenttyp direkt fest, keine Geometrie-Automatik + ;; mehr wie bei "Neue Linie BIS Kettenende" (die bleibt unveraendert und + ;; nutzt weiterhin vfl-segment-entscheidung). (princ "\n\nNaechstes Element waehlen:") (setq linie-ende-modus nil) (if frame (progn (princ "\n 1 - GF-Bogen (horizontale Kurve)") - (princ "\n 2 - Neue Linie (GF, Ab/Auf VF)") - (princ "\n 3 - Neue VF mit horizontalem Anfang (Horizontal-Stueck)") - (princ "\n 4 - Neue Linie BIS Kettenende (danach Separator + ES-Element)") - (setq antwort (getstring "\nIhre Wahl (1-4) [2]: ")) + (princ "\n 2 - Neue Linie: GF (Gefaellestrecke)") + (princ "\n 3 - Neue Linie: Ab/Auf VF (VarioFoerderer-Einheit)") + (princ "\n 4 - Neue VF mit horizontalem Anfang (Horizontal-Stueck)") + (princ "\n 5 - Neue Linie BIS Kettenende (danach Separator + ES-Element)") + (setq antwort (getstring "\nIhre Wahl (1-5) [2]: ")) (setq wahl (cond ((= antwort "1") "GF-Bogen") - ((= antwort "3") "Horizontal-VF") - ((= antwort "4") (setq linie-ende-modus t) "Linie") - (t "Linie"))) ; "2" oder leer + ((= antwort "3") "Linie-VF") + ((= antwort "4") "Horizontal-VF") + ((= antwort "5") (setq linie-ende-modus t) "Linie") + (t "Linie-GF"))) ; "2" oder leer ) (progn - (princ "\n 1 - Neue Linie (GF, Ab/Auf VF)") - (princ "\n 2 - Neue VF mit horizontalem Anfang (Horizontal-Stueck)") - (princ "\n 3 - Neue Linie BIS Kettenende (danach Separator + ES-Element)") - (setq antwort (getstring "\nIhre Wahl (1-3) [1]: ")) - (setq wahl (cond ((= antwort "2") "Horizontal-VF") - ((= antwort "3") (setq linie-ende-modus t) "Linie") - (t "Linie"))) ; "1" oder leer + (princ "\n 1 - Neue Linie: GF (Gefaellestrecke)") + (princ "\n 2 - Neue Linie: Ab/Auf VF (VarioFoerderer-Einheit)") + (princ "\n 3 - Neue VF mit horizontalem Anfang (Horizontal-Stueck)") + (princ "\n 4 - Neue Linie BIS Kettenende (danach Separator + ES-Element)") + (setq antwort (getstring "\nIhre Wahl (1-4) [1]: ")) + (setq wahl (cond ((= antwort "2") "Linie-VF") + ((= antwort "3") "Horizontal-VF") + ((= antwort "4") (setq linie-ende-modus t) "Linie") + (t "Linie-GF"))) ; "1" oder leer ) ) @@ -1037,13 +1340,20 @@ (setq linie-mess (vfl-neue-linie-messen p-aktuell (if frame (car (frame->hz-winkel frame)) nil))) (if (null linie-mess) (progn (princ "\nAbgebrochen.") (exit))) - (setq deltaL (car linie-mess) hz-neu (cadr linie-mess)) + (setq deltaL (car linie-mess) hz-neu (cadr linie-mess) pick-punkt (caddr linie-mess)) + (setq kettenanfang (null frame)) + ;; Kettenanfang: AS-Element (falls gewuenscht) SOFORT einfuegen, reale + ;; Restlaenge aus dem tatsaechlichen KS_AUS nachrechnen (siehe + ;; vfl-kettenanfang-baustein). + (if kettenanfang + (progn + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden)) + (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) + ) + ) (if (< deltaL 1000.0) (princ "\nFEHLER: Horizontaler VF braucht >= 1000 mm (Umlenk + Motor) - laenger zeichnen.") (progn - ;; Kettenanfang: AS-Element (flach, wie beim VF) einfuegen - (if (null frame) - (setq frame (vfl-insert-as-element "VF" p-aktuell hz-neu 0.0 as-seite))) ;; VF-Einheit mit horizontalem ersten Koerper (winkel=0, L_VF=deltaL, ;; L_GF = Mindestlaenge fuer den Einlauf-Anschluss). (setq vf-einheit-res @@ -1058,16 +1368,182 @@ ) ) - (t ;; --- Neue Linie --- + ;; --- Neue Linie: GF (Nutzer legt den Typ explizit fest) --- + ((= wahl "Linie-GF") ;; 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 "\nAbgebrochen.") (exit))) - (setq deltaL (car linie-mess) hz-neu (cadr linie-mess)) + (setq deltaL (car linie-mess) hz-neu (cadr linie-mess) pick-punkt (caddr linie-mess)) + (setq kettenanfang (null frame)) + (setq gf-max-winkel (float (ssg-cfg-or "vario" "gefaelle_winkel" 3))) (if (< deltaL 1.0) (princ "\nFEHLER: Linie zu kurz (oder entgegen der Fahrtrichtung) - bitte erneut waehlen.") (progn + ;; Kettenanfang: AS-Element (falls gewuenscht) SOFORT einfuegen + ;; (Richtung hz-neu jetzt bekannt) und die GF-Restlaenge aus dem + ;; TATSAECHLICHEN KS_AUS nachrechnen (siehe vfl-kettenanfang- + ;; baustein). Keine Fussabdruck-Schaetzung mehr: sowohl KS_EIN- als + ;; auch Ursprung-basierte Vorab-Messung ignorieren die Dreh­teller- + ;; Rotation, die insert-block-mixed-to-ks beim echten Einfuegen + ;; anwendet, und liefern daher einen falschen Wert (empirisch + ;; bestaetigt: ~210mm Schaetzung vs. tatsaechlich ~420mm noetiger + ;; Versatz). + (if kettenanfang + (progn + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden)) + (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) + ) + ) + (setq gf-ok t) + (princ "\nGefaelle festlegen:") + (princ "\n 1 - Gegebene Hoehe (Zielhoehe)") + (princ "\n 2 - Neigungswinkel eingeben") + (setq antwort (getstring "\nIhre Wahl (1/2) [1]: ")) + (if (= antwort "2") + (progn + ;; Winkel direkt vorgeben - deltaH ergibt sich aus deltaL*tan(winkel). + (setq winkel + (getreal (strcat "\nNeigungswinkel (Grad, 0 < Winkel <= " + (rtos gf-max-winkel 2 1) ") [" (rtos gf-max-winkel 2 1) "]: "))) + (if (null winkel) (setq winkel gf-max-winkel)) + (if (or (<= winkel 0.0) (> winkel gf-max-winkel)) + (progn + (alert (strcat "Neigungswinkel ungueltig: " (rtos winkel 2 1) + " Grad. Erlaubt: 0 < Winkel <= " (rtos gf-max-winkel 2 1) " Grad.")) + (setq gf-ok nil)) + (progn + (setq richtung "Ab") + (setq deltaH (* deltaL (/ (sin (* winkel (/ pi 180.0))) + (cos (* winkel (/ pi 180.0)))))) + ) + ) + ) + (progn + ;; Gegebene Hoehe - wie bisher, aber Winkel wird daraus abgeleitet + ;; und gegen den GF-Maximalwinkel geprueft (GF kann nicht steigen). + ;; p-aktuell ist ab hier immer der reale Referenzpunkt (bei + ;; Kettenanfang das echte KS_AUS des AS-Elements). + (setq hoehe-neu + (getreal (strcat "\nHoehe (Z) des Linienendpunkts [" (rtos (caddr p-aktuell) 2 1) "]: "))) + (if (null hoehe-neu) (setq hoehe-neu (caddr p-aktuell))) + (setq deltaH (- hoehe-neu (caddr p-aktuell))) + (setq richtung (if (>= deltaH 0.0) "Auf" "Ab")) + (setq deltaH (abs deltaH)) + (cond + ((= richtung "Auf") + (alert "Gefaellestrecke (GF) kann nicht steigen - bitte tiefere Zielhoehe waehlen oder \"Ab/Auf VF\" benutzen.") + (setq gf-ok nil)) + (t + (setq winkel (* (atan (/ deltaH deltaL)) (/ 180.0 pi))) + (if (> winkel gf-max-winkel) + (progn + (alert (strcat "Gefaelle zu steil fuer GF: " (rtos winkel 2 1) + " Grad (erlaubt max " (rtos gf-max-winkel 2 1) + " Grad).\nBitte kleinere Hoehendifferenz waehlen oder \"Ab/Auf VF\" benutzen.")) + (setq gf-ok nil)) + ) + ) + ) + ) + ) + (if gf-ok + (progn + (setq frame (vfl-insert-gf-segment (car frame) hz-neu deltaL winkel)) + (setq anzahl-gf (1+ anzahl-gf)) + (vfl-acc-gf-seg (/ deltaL (cos (* (float winkel) (/ pi 180.0)))) winkel) + (setq letzter-typ "GF") + (setq p-aktuell (car frame)) + (princ "\nIst das das Kettenende?") + (princ "\n 1 - Ja (ES-Element setzen)") + (princ "\n 2 - Ja (ohne ES-Element setzen)") + (princ "\n 3 - Nein (weiterbauen)") + (setq antwort (getstring "\nIhre Wahl (1-3) [3]: ")) + (cond + ((= antwort "1") + (setq es-seite (vfl-frage-es-seite)) + (setq frame (vfl-insert-es-element "GF" frame hz-neu winkel + (caddr (car frame)) es-seite)) + (setq fertig t)) + ((= antwort "2") (setq fertig t)) + ) + ) + ) + ) + ) + ) + + ;; --- Neue Linie: Ab/Auf VF (Nutzer legt den Typ explizit fest) --- + ((= wahl "Linie-VF") + (setq linie-mess (vfl-neue-linie-messen p-aktuell + (if frame (car (frame->hz-winkel frame)) nil))) + (if (null linie-mess) (progn (princ "\nAbgebrochen.") (exit))) + (setq deltaL (car linie-mess) hz-neu (cadr linie-mess) pick-punkt (caddr linie-mess)) + (setq kettenanfang (null frame)) + ;; Kettenanfang: AS-Element (falls gewuenscht) SOFORT einfuegen, reale + ;; Restlaenge aus dem tatsaechlichen KS_AUS nachrechnen (siehe + ;; vfl-kettenanfang-baustein). + (if kettenanfang + (progn + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden)) + (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) + ) + ) + (if (< deltaL 1000.0) + (princ "\nFEHLER: VarioFoerderer braucht >= 1000 mm (Umlenk + Motor) - laenger zeichnen oder \"GF\" waehlen.") + (progn + (setq hoehe-neu + (getreal (strcat "\nHoehe (Z) des Linienendpunkts [" (rtos (caddr p-aktuell) 2 1) "]: "))) + (if (null hoehe-neu) (setq hoehe-neu (caddr p-aktuell))) + (setq deltaH (- hoehe-neu (caddr p-aktuell))) + (setq richtung (if (>= deltaH 0.0) "Auf" "Ab")) + (setq deltaH (abs deltaH)) + (setq entscheidung (vfl-vf-entscheidung deltaL deltaH richtung)) + (setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung) + L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung)) + (if (null typ) + (alert (strcat "VF-Einheit geometrisch nicht baubar!\n" + "deltaL=" (rtos deltaL 2 0) " mm, deltaH=" (rtos deltaH 2 0) + " mm, Richtung=" richtung + "\nBitte anderen Endpunkt/Hoehe waehlen.")) + (progn + (setq vf-einheit-res + (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF nil)) + (setq frame (nth 0 vf-einheit-res)) + (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) + (if (nth 2 vf-einheit-res) (setq fertig t)) + (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) + (setq letzter-typ "VF") + (setq p-aktuell (car frame)) + ) + ) + ) + ) + ) + + ((= wahl "Linie") ;; --- Neue Linie BIS Kettenende (automatische GF/VF-Entscheidung, unveraendert) --- + ;; 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 "\nAbgebrochen.") (exit))) + (setq deltaL (car linie-mess) hz-neu (cadr linie-mess) pick-punkt (caddr linie-mess)) + (setq kettenanfang (null frame)) + (if (< deltaL 1.0) + (princ "\nFEHLER: Linie zu kurz (oder entgegen der Fahrtrichtung) - bitte erneut waehlen.") + (progn + ;; Kettenanfang: AS-Element (falls gewuenscht) SOFORT einfuegen + ;; (immer flach, typ-unabhaengig - siehe vfl-insert-as-element; + ;; welcher Segmenttyp folgt, steht hier noch nicht fest), reale + ;; Restlaenge aus dem tatsaechlichen KS_AUS nachrechnen (siehe + ;; vfl-kettenanfang-baustein). + (if kettenanfang + (progn + (setq erg (vfl-kettenanfang-baustein p-aktuell hz-neu pick-punkt deltaL as-seite as-vorhanden)) + (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) + ) + ) ;; Segment-Typ bestimmen. Kurzsegment (deltaL < 1000 mm): KEINE ;; Hoehenabfrage - automatisch 3-Grad-Gefaellestrecke. Grund: ein VF ;; braucht >= 1000 mm deltaL (Umlenk- + Motorstation = 500+500 mm), @@ -1123,13 +1599,6 @@ " mm, Richtung=" richtung "\nBitte anderen Endpunkt/Hoehe waehlen.")) (progn - ;; Kettenanfang: AS-Element passend zum ersten Segment-Typ einfuegen - (if (null frame) - (setq frame - (vfl-insert-as-element typ p-aktuell hz-neu - (if (= typ "GF") winkel 0.0) as-seite)) - ) - (if (= typ "GF") (progn ;; --- reine Gefaellestrecke --- @@ -1146,17 +1615,18 @@ (progn (princ "\nIst das das Kettenende?") (princ "\n 1 - Ja (ES-Element setzen)") - (princ "\n 2 - Nein (weiterbauen)") - (setq antwort (getstring "\nIhre Wahl (1/2) [2]: ")) + (princ "\n 2 - Ja (ohne ES-Element setzen)") + (princ "\n 3 - Nein (weiterbauen)") + (setq antwort (getstring "\nIhre Wahl (1-3) [3]: ")) ) ) - (if (= antwort "1") - (progn - (setq es-seite (vfl-frage-es-seite)) - (setq frame (vfl-insert-es-element "GF" frame hz-neu winkel - (caddr (car frame)) es-seite)) - (setq fertig t) - ) + (cond + ((= antwort "1") + (setq es-seite (vfl-frage-es-seite)) + (setq frame (vfl-insert-es-element "GF" frame hz-neu winkel + (caddr (car frame)) es-seite)) + (setq fertig t)) + ((= antwort "2") (setq fertig t)) ) ) (progn @@ -1311,8 +1781,13 @@ ;; Ergebnis: KS_EIN.X = Startpunkt.X, KS_EIN quer um das AS-Y-Mass versetzt, ;; KS_AUS liegt exakt auf dem Pfad -> die ganze Kette folgt der Mittellinie. ;; Rueckgabe: (korrigierter) Frame am KS_AUS. +;; winkel-Parameter bleibt aus Call-Kompatibilitaet bestehen (vfl2-insert-as-vf +;; ruft mit 0.0), wird aber NICHT mehr fuer eine Kippung verwendet: das AS- +;; Element hat keine eigene Neigung (per Einzel-Insert-Test in BricsCAD +;; bestaetigt, siehe vfl-insert-as-element in Modus 1) - unabhaengig vom +;; folgenden Segmenttyp (GF/VF) wird es IMMER flach eingefuegt. (defun vfl2-insert-as-gf (startpunkt hz winkel as-seite / - ein-hz-as rad-h rad-v xu-ein frame blk ks-aus + ein-hz-as rad-h xu-ein frame blk ks-aus rad-hz perp-x perp-y d-perp sx sy as-turn rad-ein de-x de-y de-dot-np t-shift) ;; Schwenk aus dem AS-Block MESSEN (30/90/gerade), KS_EIN so drehen, dass @@ -1320,10 +1795,7 @@ (setq as-turn (vf-element-plan-turn (strcat "AS_Element_" (vfl-as-winkel) "_" as-seite))) (setq ein-hz-as (- hz as-turn)) (setq rad-h (* (float ein-hz-as) (/ pi 180.0))) - (setq rad-v (* (float winkel) (/ pi 180.0))) - (setq xu-ein (list (* (cos rad-h)(cos rad-v)) - (* (sin rad-h)(cos rad-v)) - (- (sin rad-v)))) + (setq xu-ein (list (cos rad-h) (sin rad-h) 0.0)) ;; (1) KS_EIN auf den Startpunkt (Laengsposition korrekt) (setq frame (insert-block-mixed-to-ks (strcat "AS_Element_" (vfl-as-winkel) "_" as-seite) @@ -1788,7 +2260,8 @@ nonclimber-cnt nkurve kurve-chords run-span hor-koerper-len hor-pairs flat-p fill-len wahl3 rad3v feste-vf dH-adj dir-x dir-y fill-D end-hz - gf-total br-gf-mode br-gf2-exp filler-A-len filler-a-done) + gf-total br-gf-mode br-gf2-exp filler-A-len filler-a-done + as-vorhanden es-vorhanden) (princ "\n\n=========================================") (princ (ssg-text "vfl-m3-titel")) (princ "\n=========================================") @@ -1814,12 +2287,21 @@ (list (rtos (caddr startpunkt) 2 1))))) (if (null start-hoehe) (setq start-hoehe (caddr startpunkt))) (setq startpunkt (list (car startpunkt) (cadr startpunkt) start-hoehe)) - (setq *vfl-as-winkel* (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")) - (vf-set-as-masse *vfl-as-winkel* as-seite) ; Masse fuer Variante + (princ "\n\nAS-Element setzen?") + (princ "\n 1 - Ja") + (princ "\n 2 - Nein (Kette beginnt direkt am Startpunkt)") + (setq antwort (getstring "\nIhre Wahl (1/2) [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 + (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")) + (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"))) @@ -1828,12 +2310,21 @@ (list (rtos (caddr endpunkt) 2 1))))) (if (null end-hoehe) (setq end-hoehe (caddr endpunkt))) (setq endpunkt (list (car endpunkt) (cadr endpunkt) end-hoehe)) - (setq *vfl-es-winkel* (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")) - (vf-set-es-masse *vfl-es-winkel* es-seite) ; Masse fuer Variante + (princ "\n\nES-Element setzen?") + (princ "\n 1 - Ja") + (princ "\n 2 - Nein (Kette endet direkt am Zielpunkt)") + (setq antwort (getstring "\nIhre Wahl (1/2) [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 + (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")) + (vf-set-es-masse *vfl-es-winkel* es-seite) ; Masse fuer Variante + ) + ) ;; --- 4. Sortieren + Analysieren + Eck-Vorpruefung --- (setq kette (gf-sortiere-objekte obj-liste startpunkt)) @@ -1977,8 +2468,11 @@ ;; ================= PHASE B: BAUEN (messen statt schaetzen) ================= ;; VF-Lauf darf mehrsegmentig sein (VF-Geraden + Vario-Kurven, EINE VF-Einheit). - ;; Nummerierung + Akkumulatoren + AS/ES-Fussabdruecke - (setq aus (if aus-dx aus-dx 576.0) ein (if ein-dx ein-dx 576.0)) + ;; Nummerierung + Akkumulatoren + AS/ES-Fussabdruecke. Ohne AS-Element (aus- + ;; vorhanden=nil) faellt der Fussabdruck weg - die Kette beginnt direkt am + ;; Startpunkt, also 0 statt Block-/Fallback-Mass. + (setq aus (if as-vorhanden (if aus-dx aus-dx 576.0) 0.0) + ein (if es-vorhanden (if ein-dx ein-dx 576.0) 0.0)) (setq vfl-nummer (vf-next-number)) (setq lastEnt (vf-lastent-ohne-attribute)) (vfl-acc-reset) @@ -1998,9 +2492,14 @@ (cond ((= typ "Linie") (setq winkel (nth 4 seg)) - ;; AS zuerst platzieren, damit der echte KS_AUS bekannt ist + ;; AS zuerst platzieren (falls gewuenscht), damit der echte KS_AUS bekannt + ;; ist. Ohne AS-Element beginnt die Kette direkt am Startpunkt (flach) - + ;; die nachfolgende Fussabdruck-Trimmung wird dann automatisch zu 0, da + ;; (car frame) bereits gleich startpunkt ist. (if (null frame) - (setq frame (vfl2-insert-as-gf startpunkt hz winkel as-seite))) + (setq frame (if as-vorhanden + (vfl2-insert-as-gf startpunkt hz winkel as-seite) + (make-frame-from-dir startpunkt (hz-winkel->xu hz 0.0))))) (setq deltaL (caddr seg)) ;; erste Gerade: AS-Fussabdruck ENTLANG des Pfads exakt aus KS_AUS abziehen ;; (das Block-Maß aus-dx stimmt nach dem Achs-Versatz nicht mehr). @@ -2022,10 +2521,13 @@ (princ (ssg-text "vfl-m3-kurve-front-uebersprungen"))))) (setq i (1+ i))) - ;; Front-Anker (gemessen). Falls die VF-Bruecke ganz vorne liegt: AS jetzt setzen. + ;; Front-Anker (gemessen). Falls die VF-Bruecke ganz vorne liegt: AS (falls + ;; gewuenscht) jetzt setzen. (setq hz (cadr (nth vf-start plan))) (if (null frame) - (setq frame (vfl2-insert-as-vf startpunkt hz as-seite))) + (setq frame (if as-vorhanden + (vfl2-insert-as-vf startpunkt hz as-seite) + (make-frame-from-dir startpunkt (hz-winkel->xu hz 0.0))))) (setq z-front (caddr (car frame))) ;; --- B2: Back-Abstieg -> Junction; Kletterer + Horizontal-Mitte bestimmen --- @@ -2137,14 +2639,24 @@ (vfl-acc-vf-seg "horizontal" 0 filler-A-len) (setq anzahl-vf (1+ anzahl-vf) filler-a-done t))))) (if (= i vf-ende) - ;; letzter Fueller: Laenge so, dass der ENDPUNKT auf der ES-KS_AUS-ACHSE - ;; liegt (Spiegel der AS-Regel). Der Schwanz (Fueller + ab_3 + Motor + GF2 - ;; + Separator + ES) verschiebt sich starr entlang seg-hz mit dem Fueller; - ;; KS_AUS = pt + (fill + C)*dp + perp-es*np, Achse u_a = seg-hz + ES-Turn. - ;; Aus (Endpunkt - KS_AUS)*n_a = 0 folgt fill (n_a senkrecht zu u_a). - (setq fill-len (vfl3-es-fueller pt endpunkt seg-hz - (strcat "ES_Element_" (vfl-es-winkel) "_" es-seite) - br-gf2-exp rad3v)) + ;; letzter Fueller, MIT ES-Element (unveraendert): Laenge so, dass der + ;; ENDPUNKT auf der ES-KS_AUS-ACHSE liegt (Spiegel der AS-Regel). Der + ;; Schwanz (Fueller + ab_3 + Motor + GF2 + Separator + ES) verschiebt + ;; sich starr entlang seg-hz mit dem Fueller; KS_AUS = pt + (fill + C)* + ;; dp + perp-es*np, Achse u_a = seg-hz + ES-Turn. Aus (Endpunkt - + ;; KS_AUS)*n_a = 0 folgt fill (n_a senkrecht zu u_a). OHNE ES-Element + ;; (Nutzerwunsch): keine Achsen-Korrektur noetig, da nach Motor+GF2 + ;; nichts mehr gebaut wird - Fueller zielt direkt auf den Endpunkt. + (setq fill-len + (if es-vorhanden + (vfl3-es-fueller pt endpunkt seg-hz + (strcat "ES_Element_" (vfl-es-winkel) "_" es-seite) + br-gf2-exp rad3v) + (- (+ (* (- (car endpunkt) (car pt)) (cos (* seg-hz (/ pi 180.0)))) + (* (- (cadr endpunkt) (cadr pt)) (sin (* seg-hz (/ pi 180.0))))) + (* (+ 500.0 br-gf2-exp) (cos rad3v))) + ) + ) (setq fill-len (caddr seg))) (setq fill-len (max 100.0 fill-len)) (setq pt (insert-inclined-scaled-block "Staustrecke_SP_1000_mm" pt fill-len 0 seg-hz)) @@ -2194,7 +2706,10 @@ (cond ((= typ "Linie") (setq winkel (nth 4 seg) deltaL (caddr seg)) - (if (= i last-line) (setq deltaL (- deltaL 300.0 ein))) + ;; Footprint fuer Separator(300)+ES nur reservieren, wenn ES-Element + ;; gewuenscht ist (ein=0 sonst, siehe oben) - ohne ES entfaellt auch + ;; der abschliessende Separator. + (if (= i last-line) (setq deltaL (- deltaL (if es-vorhanden 300.0 0.0) ein))) (setq deltaL (max 100.0 deltaL)) (setq frame (vfl-insert-gf-segment (car frame) hz deltaL winkel)) (vfl-acc-gf-seg (/ deltaL (cos (* winkel (/ pi 180.0)))) winkel) @@ -2206,10 +2721,11 @@ (princ (ssg-text "vfl-m3-kurve-back-uebersprungen"))))) (setq i (1+ i))) - ;; --- B5: Kettenende Separator + ES --- + ;; --- B5: Kettenende Separator + ES (nur falls gewuenscht) --- (if (null frame) (progn (princ (ssg-text "vfl-m3-nichts-gebaut")) (exit))) - (setq frame (vfl-insert-es-element "GF" frame (car (frame->hz-winkel frame)) - (if letzt-winkel letzt-winkel 3.0) (caddr (car frame)) es-seite)) + (if es-vorhanden + (setq frame (vfl-insert-es-element "GF" frame (car (frame->hz-winkel frame)) + (if letzt-winkel letzt-winkel 3.0) (caddr (car frame)) es-seite))) ;; ---------- Block + Ist-Ziel-Report ---------- (setq hoehe-bis (caddr (car frame))) @@ -2240,6 +2756,622 @@ (princ) ) +;; ============================================================ +;; TEIL 5: KETTE ZUSAMMENFUEHREN +;; ============================================================ +;; Vario_Kette_Merge: eine Kette aus bereits in der Zeichnung liegenden +;; Vario-Foerderer-Bausteinen (lose Einzelteile WIE AUCH bereits fertig +;; gewickelte VF_n-Bloecke, in beliebiger Mischung) wird ab einem gewaehlten +;; Start-Baustein ueber die reale KS_AUS->KS_EIN-Nachbarschaft verfolgt und zu +;; EINEM neuen Gesamt-VF_n-Block verschmolzen. Die Attribute werden dabei aus +;; der gefundenen Bausteinfolge NEU hergeleitet (dieselben Akkumulatoren/ +;; Formeln wie beim interaktiven Bau in Modus 1/2 - vfl-acc-*, +;; ssg-strecke-attrib-defs -, nur rueckwirkend nach dem Auffinden statt +;; waehrend des Bauens gefuellt). Nur VORWAERTS ab dem gewaehlten +;; Start-Baustein (keine Rueckwaerts-Suche). +;; +;; Alle beteiligten Bausteintypen tragen laut Nutzerbestaetigung ein eigenes +;; KS_EIN/KS_AUS (auch Umlenk-/Motorstation, Vertikalboegen, das gestreckte +;; Zwischenstueck und der Separator) - die Verkettung laeuft daher komplett +;; ueber KS-Nachbarschaft, keine Bounding-Box-Geometrie noetig. + +;; Toleranzen (mm) fuer die Nachbarschaftspruefung zwischen zwei Bausteinen: +;; <= tol-eng -> gilt als sauber verbunden, Kette geht weiter +;; <= tol-weit -> sieht verbunden aus, ist es aber nicht -> Warnung, Kettenende +;; > tol-weit -> kein Zusammenhang, normales (stilles) Kettenende +(if (null *vfl-kette-tol-eng*) (setq *vfl-kette-tol-eng* 2.0)) +(if (null *vfl-kette-tol-weit*) (setq *vfl-kette-tol-weit* 100.0)) + +;; Kleine Feld-Zugriffe auf einen Ketten-Datensatz +;; (ename bname ks-ein-punkt ks-aus-punkt attribute-alist ist-wrapper) +(defun vfl-kette-rec-ename (rec) (nth 0 rec)) +(defun vfl-kette-rec-bname (rec) (nth 1 rec)) +(defun vfl-kette-rec-ein (rec) (nth 2 rec)) +(defun vfl-kette-rec-aus (rec) (nth 3 rec)) +(defun vfl-kette-rec-attribs (rec) (nth 4 rec)) +(defun vfl-kette-rec-wrapper (rec) (nth 5 rec)) + +;; String an einem Trennzeichen aufteilen (reine Teilstring-Suche, keine +;; Wildcards). Bei "_"-Trennung eines Bausteinnamens liefert das die +;; Namensteile unabhaengig vom Dimensions-Suffix (_2D/_3D) - der steht immer +;; am Ende und wird von den (nur von vorne indizierenden) Zugriffen unten +;; ignoriert. +(defun vfl-kette-split (str delim / pos ergebnis rest) + (setq ergebnis '() rest str) + (while (setq pos (vl-string-search delim rest)) + (setq ergebnis (append ergebnis (list (substr rest 1 pos)))) + (setq rest (substr rest (+ pos 1 (strlen delim)))) + ) + (append ergebnis (list rest)) +) +(defun vfl-kette-teil (bname idx) (nth idx (vfl-kette-split bname "_"))) +(defun vfl-kette-split-komma (str) + (if (and str (> (strlen str) 0)) (vfl-kette-split str ",") '())) + +;; Bausteintyp aus dem Blocknamen ableiten. Scanner/Separator_SP (manuelle +;; Sensor-Bloecke, siehe count_sep_scan.lsp) gehoeren NICHT zur Kette selbst +;; und tauchen hier bewusst nicht auf. +(defun vfl-kette-typ (bname) + (cond + ((wcmatch bname "VF_*") "WRAPPER") + ((wcmatch bname "AS_Element_*") "AS") + ((wcmatch bname "ES_Element_*") "ES") + ((wcmatch bname "Gefaellebogen_*") "GFBOGEN") + ((wcmatch bname "Vario_Kurve_*") "KURVE") + ((wcmatch bname "Vario_Umlenkstation_*") "UMLENK") + ((wcmatch bname "Vario_Motorstation_*") "MOTOR") + ((wcmatch bname "Vario_Bogen_auf_*") "BOGENAUF") + ((wcmatch bname "Vario_Bogen_ab_*") "BOGENAB") + ((wcmatch bname "Staustrecke_SP_1000_mm*") "STRECKE") + ((wcmatch bname "Staustrecke_Separator_SP_300_mm*") "SEP") + (t "UNBEKANNT") + ) +) + +;; Gemessene Neigung (Grad, positiv=abwaerts wie frame->hz-winkel) zwischen +;; zwei Welt-Punkten. +(defun vfl-kette-neigung (ein aus / dx dy dz horiz) + (setq dx (- (car aus) (car ein)) dy (- (cadr aus) (cadr ein)) dz (- (caddr aus) (caddr ein))) + (setq horiz (sqrt (+ (* dx dx) (* dy dy)))) + (if (> horiz 1e-6) (* (atan (- dz) horiz) (/ 180.0 pi)) 0.0) +) +(defun vfl-kette-round (x) (atoi (rtos x 2 0))) + +;; Attribut-Wert als Zahl/Text lesen (Default falls Tag fehlt/leer). +(defun vfl-kette-attrib-zahl (attribs tag / w) + (setq w (cdr (assoc tag attribs))) + (if w (atoi w) 0)) +(defun vfl-kette-attrib-text (attribs tag default / w) + (setq w (cdr (assoc tag attribs))) + (if (and w (> (strlen w) 0)) w default)) + +;; Attribut-Wert auf "" erzwingen. ssg-attrib-set-on ueberspringt leere Werte +;; bewusst als "keine Ueberschreibung" (ATTDEF-Default bleibt stehen) - hier +;; soll das Feld aber ABSICHTLICH geleert werden (z.B. SEITE_AS/SEITE_ES, +;; wenn die Kette kein AS-/ES-Element hat und der ATTDEF-Default "rechts" +;; sonst faelschlich stehen bliebe). +(defun vfl-kette-attrib-leeren (ent tag / obj ed typ etag) + (setq obj (entnext ent)) + (while obj + (setq ed (entget obj)) + (setq typ (cdr (assoc 0 ed))) + (if (equal typ "SEQEND") + (setq obj nil) + (progn + (if (and (equal typ "ATTRIB") (equal (cdr (assoc 2 ed)) tag)) + (progn (entmod (subst (cons 1 "") (assoc 1 ed) ed)) (entupd obj))) + (setq obj (entnext obj)) + ) + ) + ) +) + +;; KS_EIN/KS_AUS-URSPRUNGSPUNKTE (Welt-Koordinaten, keine Richtung) eines +;; Bausteins ermitteln - robust gegen NICHT-UNIFORME Skalierung (z.B. +;; Staustrecke_SP_1000_mm, das per insert-inclined-scaled-block auf die +;; reale Segmentlaenge gestreckt wird). extract-ks-from-block-raw +;; (vf_core.lsp) klassifiziert die 3 Achslinien im KS-Sub-Block ueber ihre +;; ABSOLUTE LAENGE (ks-line-axis, feste Baender ~1/~100 Einheiten) - wird die +;; Fahrtrichtungs-Achslinie mitgestreckt, faellt sie aus diesem Raster und +;; die Extraktion schlaegt still fehl (empirisch bestaetigt: bei den meisten +;; Staustrecke-Instanzen "KS_EIN/KS_AUS FEHLT"). Uebernimmt daher die in +;; ks_segmente.lsp (kseg-collect-lose) bereits bewaehrte Methode: an einer +;; KOPIE die Skalierung auf 1:1:1 zuruecksetzen (Marker wieder nominal lang, +;; Extraktion funktioniert normal), KS_EIN/KS_AUS dort lesen, danach den +;; KS_AUS-Versatz mit dem echten XScaleFactor zurueckrechnen (die Streckung +;; wirkt lokal rein auf der Block-X-Achse/Docking-Richtung; nach Rotation ins +;; Weltsystem hat der Versatzvektor i.A. X-/Y-/Z-Anteile, die Streckung wirkt +;; aber auf alle drei mit demselben Faktor sx - Y/Z-Skalierung bleibt bei +;; dieser Teilefamilie immer 1.0). Kopie wird sofort wieder geloescht - +;; block-obj selbst bleibt unveraendert. +;; Rueckgabe: (("KS_EIN" . punkt) ("KS_AUS" . punkt)) - je nur wenn gefunden. +(defun vfl-kette-ks-ursprung (block-obj / sx copyobj ksdata kez kaz ergebnis) + (setq sx (vla-get-XScaleFactor block-obj)) + (setq copyobj (vla-Copy block-obj)) + (vla-put-XScaleFactor copyobj 1.0) + (vla-put-YScaleFactor copyobj 1.0) + (vla-put-ZScaleFactor copyobj 1.0) + (setq ksdata (extract-ks-from-block-raw copyobj)) + (if (not (vlax-erased-p copyobj)) (vl-catch-all-apply 'vla-Delete (list copyobj))) + (setq kez (if (assoc "KS_EIN" ksdata) (car (cadr (assoc "KS_EIN" ksdata))) nil)) + (setq kaz (if (assoc "KS_AUS" ksdata) (car (cadr (assoc "KS_AUS" ksdata))) nil)) + (if (and kez kaz (/= sx 1.0)) + (setq kaz (list + (+ (car kez) (* sx (- (car kaz) (car kez)))) + (+ (cadr kez) (* sx (- (cadr kaz) (cadr kez)))) + (+ (caddr kez) (* sx (- (caddr kaz) (caddr kez)))) + )) + ) + (setq ergebnis '()) + (if kez (setq ergebnis (cons (cons "KS_EIN" kez) ergebnis))) + (if kaz (setq ergebnis (cons (cons "KS_AUS" kaz) ergebnis))) + ergebnis +) + +;; Gesamt-KS_EIN (erster Baustein) und Gesamt-KS_AUS (letzter Baustein) EINES +;; Bausteins ermitteln + Kennzeichen ob es sich um einen Wrapper handelt. +;; Zuerst DIREKT versucht (Leaf-Element - traegt selbst KS_EIN/KS_AUS als +;; Sub-Block, siehe vfl-kette-ks-ursprung). Liefert die direkte Suche NICHTS +;; (leer), wird block-obj als Wrapper (bereits gemergter VF_n) behandelt: +;; eine Ebene tiefer je Sub-Element gesucht, intern zusammenhaengende Punkte +;; herausgefiltert. +;; Rueckgabe: (list ks-ein ks-aus ist-wrapper). +(defun vfl-kette-block-ks-punkte (block-obj / direkt kinder kind sub-ks + ein-liste aus-liste ergebnis-ein ergebnis-aus p q match) + (setq direkt (vfl-kette-ks-ursprung block-obj)) + (if direkt + (list + (cdr (assoc "KS_EIN" direkt)) + (cdr (assoc "KS_AUS" direkt)) + nil + ) + (progn + (setq kinder (vlax-invoke block-obj 'Explode)) + (setq ein-liste '() aus-liste '()) + (foreach kind kinder + (if (and (not (vlax-erased-p kind)) + (= (vla-get-ObjectName kind) "AcDbBlockReference")) + (progn + (setq sub-ks (vfl-kette-ks-ursprung kind)) + (if (assoc "KS_EIN" sub-ks) (setq ein-liste (cons (cdr (assoc "KS_EIN" sub-ks)) ein-liste))) + (if (assoc "KS_AUS" sub-ks) (setq aus-liste (cons (cdr (assoc "KS_AUS" sub-ks)) aus-liste))) + ) + ) + ) + (foreach kind kinder (if (not (vlax-erased-p kind)) (vla-Delete kind))) + (setq ergebnis-ein nil) + (foreach p ein-liste + (setq match nil) + (foreach q aus-liste (if (< (distance p q) *vfl-kette-tol-eng*) (setq match T))) + (if (not match) (setq ergebnis-ein p)) + ) + (setq ergebnis-aus nil) + (foreach p aus-liste + (setq match nil) + (foreach q ein-liste (if (< (distance p q) *vfl-kette-tol-eng*) (setq match T))) + (if (not match) (setq ergebnis-aus p)) + ) + (list ergebnis-ein ergebnis-aus T) + ) + ) +) + +;; Alle Vario-Kette-Bausteine der Zeichnung einsammeln (lose Einzelteile UND +;; bereits gewickelte VF_n - siehe vfl-kette-typ): Attribute (nur bei +;; Wrappern vorhanden, VOR jeder Veraenderung gelesen), Gesamt-KS_EIN/KS_AUS +;; und Wrapper-Kennzeichen je Baustein. +(defun vfl-kette-sammle-alle ( / ss i ename bname attribs obj ks-info records) + (setq records '()) + (setq ss (ssget "X" '((0 . "INSERT")))) + (if ss + (progn + (setq i 0) + (while (< i (sslength ss)) + (setq ename (ssname ss i)) + (setq bname (cdr (assoc 2 (entget ename)))) + (if (/= (vfl-kette-typ bname) "UNBEKANNT") + (progn + (setq attribs (ssg-attrib-read ename)) + (setq obj (vlax-ename->vla-object ename)) + (setq ks-info (vfl-kette-block-ks-punkte obj)) + (setq records (cons (list ename bname (car ks-info) (cadr ks-info) attribs (caddr ks-info)) records)) + ) + ) + (setq i (1+ i)) + ) + ) + ) + records +) + +;; Naechsten Datensatz in rest-liste suchen, dessen KS_EIN am naechsten am +;; gegebenen KS_AUS-Punkt liegt. Rueckgabe: (rec . abstand) oder nil. +(defun vfl-kette-naechster (aus-punkt rest-liste / rec bester bester-d d) + (setq bester nil bester-d nil) + (foreach rec rest-liste + (if (vfl-kette-rec-ein rec) + (progn + (setq d (distance aus-punkt (vfl-kette-rec-ein rec))) + (if (or (null bester-d) (< d bester-d)) + (progn (setq bester rec) (setq bester-d d))) + ) + ) + ) + (if bester (cons bester bester-d) nil) +) + +;; Kette ab start-rec NUR VORWAERTS verfolgen. Rueckgabe: (list kette warnung) +;; kette = Liste der Datensaetze in Ketten-Reihenfolge (mind. start-rec) +;; warnung = (letzter-bname kandidat-bname abstand) wenn eine Luecke im +;; tol-weit-Band gefunden wurde, sonst nil. +;; letzter-fund = (rec . abstand) des zuletzt geprueften (aber verworfenen) +;; Kandidaten - Diagnose-Hilfe, wenn die Kette bei Laenge 1 +;; endet (dann kein warnung, aber evtl. trotzdem ein Fund +;; ausserhalb von tol-weit). +(defun vfl-kette-verfolgen (start-rec alle-records / rest kette aktuell fund fertig warnung letzter-fund) + (setq rest (vl-remove start-rec alle-records)) + (setq kette (list start-rec)) + (setq aktuell start-rec) + (setq warnung nil) + (setq letzter-fund nil) + (setq fertig nil) + (while (not fertig) + (setq fund (vfl-kette-naechster (vfl-kette-rec-aus aktuell) rest)) + (setq letzter-fund fund) + (cond + ((null fund) (setq fertig T)) + ((<= (cdr fund) *vfl-kette-tol-eng*) + (setq aktuell (car fund)) + (setq kette (append kette (list aktuell))) + (setq rest (vl-remove aktuell rest)) + (setq letzter-fund nil) + ) + ((<= (cdr fund) *vfl-kette-tol-weit*) + (setq warnung (list (vfl-kette-rec-bname aktuell) (vfl-kette-rec-bname (car fund)) (cdr fund))) + (setq fertig T) + ) + (t (setq fertig T)) + ) + ) + (list kette warnung letzter-fund) +) + +;; Attribute des neuen Gesamt-Blocks aus der gefundenen Bausteinfolge +;; herleiten: dieselben Akkumulatoren (vfl-acc-*) wie beim interaktiven Bau, +;; hier rueckwirkend anhand der Bausteinfolge gefuellt statt waehrend des +;; Bauens. Bereits gewickelte VF_n-Bausteine werden mit ihren VORHANDENEN +;; Attributen eingespeist (Komma-Listen aufgeteilt/angehaengt, Zaehler +;; addiert) - so lassen sich lose Einzelteile und fertige VF_n beliebig +;; mischen. chain-start/chain-end = Gesamt-KS_EIN/KS_AUS der ganzen Kette +;; (Welt-Z liefert Hoehe-von/-bis direkt, kein erneutes Auslesen noetig). +;; Rueckgabe: (list attribut-alist typ-str). +(defun vfl-kette-baue-attribute (kette neuer-bname chain-start chain-end / + rec typ bname anzahl-vf phase entry-info gemessen betrag richtung + as-seite es-seite w-attribs tag n delta-l erster letzter ergebnis typ-str) + (vfl-acc-reset) + (setq anzahl-vf 0) + (setq phase "gf") + (setq entry-info nil) + (setq delta-l 0.0) + ;; Leer (nicht "rechts") als Default: falls die Kette (Ausnahmefall) ohne + ;; eigenes AS-/ES-Element beginnt/endet, soll das im Attribut auch als + ;; "keins vorhanden" erkennbar bleiben statt eine falsche Seite vorzutaeuschen. + (setq as-seite "" es-seite "") + (setq erster (car kette)) + (setq letzter (car (reverse kette))) + + (foreach rec kette + (setq bname (vfl-kette-rec-bname rec)) + (setq typ (vfl-kette-typ bname)) + (if (and (vfl-kette-rec-ein rec) (vfl-kette-rec-aus rec)) + (setq delta-l (+ delta-l (distance (vfl-kette-rec-ein rec) (vfl-kette-rec-aus rec))))) + + (cond + ;; --- Bereits gewickelter VF_n: fertige Attribute direkt einspeisen --- + ((vfl-kette-rec-wrapper rec) + (setq w-attribs (vfl-kette-rec-attribs rec)) + (setq *vfl-acc-lgf* (append *vfl-acc-lgf* (vfl-kette-split-komma (vfl-kette-attrib-text w-attribs "L_GF_m" "")))) + (setq *vfl-acc-gfwinkel* (append *vfl-acc-gfwinkel* (vfl-kette-split-komma (vfl-kette-attrib-text w-attribs "GF_WINKEL" "")))) + (setq *vfl-acc-lvf* (append *vfl-acc-lvf* (vfl-kette-split-komma (vfl-kette-attrib-text w-attribs "L_VF_m" "")))) + (setq *vfl-acc-winkel* (append *vfl-acc-winkel* (vfl-kette-split-komma (vfl-kette-attrib-text w-attribs "VF_WINKEL" "")))) + (setq *vfl-acc-richtung* (append *vfl-acc-richtung* (vfl-kette-split-komma (vfl-kette-attrib-text w-attribs "ANTRIEBFAHRTRICHTUNG" "")))) + (setq *vfl-acc-motorseite* (append *vfl-acc-motorseite* (vfl-kette-split-komma (vfl-kette-attrib-text w-attribs "MOTORSEITE" "")))) + (foreach tag '("L_90" "L_60" "L_30" "R_90" "R_60" "R_30") + (setq n (vfl-kette-attrib-zahl w-attribs (strcat "GF_Bogen_" tag))) + (repeat n (setq *vfl-acc-gfbogen* (vfl-inc-count *vfl-acc-gfbogen* tag)))) + (foreach tag '("A_90" "A_60" "A_30" "I_90" "I_60" "I_30") + (setq n (vfl-kette-attrib-zahl w-attribs (strcat "VF_Bogen_" tag))) + (repeat n (setq *vfl-acc-variokurve* (vfl-inc-count *vfl-acc-variokurve* tag)))) + (setq *vfl-acc-separator* (+ *vfl-acc-separator* (vfl-kette-attrib-zahl w-attribs "ANZAHL_SEPARATOR"))) + (setq anzahl-vf (+ anzahl-vf (vfl-kette-attrib-zahl w-attribs "ANZAHL_VF"))) + (if (equal rec erster) (setq as-seite (vfl-kette-attrib-text w-attribs "SEITE_AS" ""))) + (if (equal rec letzter) (setq es-seite (vfl-kette-attrib-text w-attribs "SEITE_ES" ""))) + ) + + ((= typ "AS") + (if (equal rec erster) (setq as-seite (vfl-kette-teil bname 3)))) + + ((= typ "ES") + (if (equal rec letzter) (setq es-seite (vfl-kette-teil bname 3)))) + + ((= typ "GFBOGEN") + ;; Gefaellebogen___R500 + (setq *vfl-acc-gfbogen* + (vfl-inc-count *vfl-acc-gfbogen* + (strcat (if (= (vfl-kette-teil bname 1) "rechts") "R" "L") "_" (vfl-kette-teil bname 2))))) + + ((= typ "KURVE") + ;; Vario_Kurve___TEF_ + (setq *vfl-acc-variokurve* + (vfl-inc-count *vfl-acc-variokurve* + (strcat (if (= (vfl-kette-teil bname 5) "aussen") "A" "I") "_" (vfl-kette-teil bname 3))))) + + ((= typ "UMLENK") + (setq phase "vf") + (setq anzahl-vf (1+ anzahl-vf)) + (setq entry-info nil)) + + ((= typ "MOTOR") + ;; Vario_Motorstation_500mm_ + (setq *vfl-acc-motorseite* (append *vfl-acc-motorseite* (list (vfl-kette-teil bname 3)))) + (setq phase "gf") + (setq entry-info nil)) + + ((or (= typ "BOGENAUF") (= typ "BOGENAB")) + (if (null entry-info) + (setq entry-info rec) ; erster Bogen des Koerper-Tripels + (progn + ;; Zweiter Bogen schliesst das Tripel. Neigung/Richtung ueber die + ;; ECHTE Geometrie messen (Anfang des ersten bis Ende des zweiten + ;; Bogens) - die Blocknamen allein sind fuer den 3-Grad/horizontal- + ;; Fall mehrdeutig (beide nutzen "auf_3"/"ab_3", vfs-vf-koerper). + (setq gemessen (vfl-kette-neigung (vfl-kette-rec-ein entry-info) (vfl-kette-rec-aus rec))) + (setq betrag (vfl-kette-round (abs gemessen))) + (setq richtung (if (< gemessen 0.0) "Auf" "Ab")) + (vfl-acc-vf-seg richtung betrag + (distance (vfl-kette-rec-aus entry-info) (vfl-kette-rec-ein rec))) + (setq entry-info nil) + ) + ) + ) + + ((= typ "STRECKE") + (if (= phase "gf") + (vfl-acc-gf-seg + (distance (vfl-kette-rec-ein rec) (vfl-kette-rec-aus rec)) + (abs (vfl-kette-neigung (vfl-kette-rec-ein rec) (vfl-kette-rec-aus rec)))) + ;; Innerhalb eines Koerper-Tripels traegt das Zwischenstueck selbst + ;; nichts direkt bei - Laenge/Neigung werden beim schliessenden + ;; Bogen (s.o.) aus der Gesamtspanne des Tripels gemessen. + ) + ) + + ((= typ "SEP") + (setq *vfl-acc-separator* (1+ *vfl-acc-separator*))) + ) + ) + + (setq typ-str + (if (or (> anzahl-vf 0) (> (length *vfl-acc-lgf*) 1) + (> (length *vfl-acc-gfbogen*) 0) (> (length *vfl-acc-variokurve*) 0)) + "Streckengruppe" "Gefaellestrecke")) + + (setq ergebnis + (list + (cons "Bezeichnung" neuer-bname) + (cons "ARTINR" "6220") + (cons "MONTAGEHOEHE_m" (rtos (/ (+ (caddr chain-start) (caddr chain-end)) 2000.0) 2 3)) + (cons "HOEHE_VON_mm" (itoa (fix (caddr chain-start)))) + (cons "HOEHE_BIS_mm" (itoa (fix (caddr chain-end)))) + (cons "DELTA_H_mm" (itoa (fix (abs (- (caddr chain-end) (caddr chain-start)))))) + (cons "DELTA_L_mm" (itoa (fix delta-l))) + (cons "TYP" typ-str) + (cons "SEITE_AS" as-seite) + (cons "SEITE_ES" es-seite) + (cons "ANZAHL_GF" (itoa (length *vfl-acc-lgf*))) + (cons "L_GF_m" (vfl-join-komma *vfl-acc-lgf*)) + (cons "GF_WINKEL" (vfl-join-komma *vfl-acc-gfwinkel*)) + (cons "GF_Bogen_L_90" (itoa (vfl-get-count *vfl-acc-gfbogen* "L_90"))) + (cons "GF_Bogen_L_60" (itoa (vfl-get-count *vfl-acc-gfbogen* "L_60"))) + (cons "GF_Bogen_L_30" (itoa (vfl-get-count *vfl-acc-gfbogen* "L_30"))) + (cons "GF_Bogen_R_90" (itoa (vfl-get-count *vfl-acc-gfbogen* "R_90"))) + (cons "GF_Bogen_R_60" (itoa (vfl-get-count *vfl-acc-gfbogen* "R_60"))) + (cons "GF_Bogen_R_30" (itoa (vfl-get-count *vfl-acc-gfbogen* "R_30"))) + (cons "ANZAHL_VF" (itoa anzahl-vf)) + (cons "MOTORSEITE" (vfl-join-komma *vfl-acc-motorseite*)) + (cons "L_VF_m" (vfl-join-komma *vfl-acc-lvf*)) + (cons "ANTRIEBFAHRTRICHTUNG" (vfl-join-komma *vfl-acc-richtung*)) + (cons "VF_WINKEL" (vfl-join-komma *vfl-acc-winkel*)) + (cons "VF_Bogen_A_90" (itoa (vfl-get-count *vfl-acc-variokurve* "A_90"))) + (cons "VF_Bogen_A_60" (itoa (vfl-get-count *vfl-acc-variokurve* "A_60"))) + (cons "VF_Bogen_A_30" (itoa (vfl-get-count *vfl-acc-variokurve* "A_30"))) + (cons "VF_Bogen_I_90" (itoa (vfl-get-count *vfl-acc-variokurve* "I_90"))) + (cons "VF_Bogen_I_60" (itoa (vfl-get-count *vfl-acc-variokurve* "I_60"))) + (cons "VF_Bogen_I_30" (itoa (vfl-get-count *vfl-acc-variokurve* "I_30"))) + (cons "ANZAHL_SEPARATOR" (itoa *vfl-acc-separator*)) + ) + ) + (list ergebnis typ-str) +) + +(defun c:Vario_Kette_Merge ( / sel start-ename start-bname alle-records start-rec + lauf kette warnung naechster-fund merge-ss leaf-enames chain-start chain-end neuer-bname + rec kinder kind diag-obj diag-kinder erg aggregiert typ-str neuer-insert def + leaf-ename leaf-obj leaf-noch-da) + (ssg-start "Vario_Kette_Merge" nil) + (princ (ssg-text "vfl-kette-titel")) + (setq sel (entsel (ssg-text "vfl-kette-start-waehlen"))) + (if (null sel) + (progn (princ (ssg-text "vfl-kette-kein-objekt")) (ssg-end) (exit))) + (setq start-ename (car sel)) + (setq start-bname (cdr (assoc 2 (entget start-ename)))) + (if (= (vfl-kette-typ (if start-bname start-bname "")) "UNBEKANNT") + (progn + (princ (ssg-textf "vfl-kette-kein-vf-block" (list (if start-bname start-bname "?")))) + (ssg-end) (exit))) + + (setq alle-records (vfl-kette-sammle-alle)) + + ;; DIAGNOSE: fuer jede erfasste Staustrecke_SP_1000_mm* zeigen, ob KS_EIN/ + ;; KS_AUS gefunden wurden (Verdachtsfall aus vorherigen Tests). + (foreach rec alle-records + (if (= (vfl-kette-typ (vfl-kette-rec-bname rec)) "STRECKE") + (princ (strcat "\n [Diagnose] " (vfl-kette-rec-bname rec) + " KS_EIN=" (if (vfl-kette-rec-ein rec) "gefunden" "FEHLT") + " KS_AUS=" (if (vfl-kette-rec-aus rec) "gefunden" "FEHLT") + " wrapper=" (if (vfl-kette-rec-wrapper rec) "ja" "nein"))) + ) + ) + + (setq start-rec nil) + (foreach rec alle-records (if (equal (vfl-kette-rec-ename rec) start-ename) (setq start-rec rec))) + (if (null start-rec) + (progn + (princ (ssg-textf "vfl-kette-start-nicht-gefunden-diag" + (list (itoa (length alle-records)) (if start-bname start-bname "?") + (itoa (length (vl-remove-if-not + (function (lambda (r) (equal (vfl-kette-rec-bname r) start-bname))) + alle-records)))))) + (ssg-end) (exit))) + (if (null (vfl-kette-rec-ein start-rec)) + (progn (princ (ssg-text "vfl-kette-start-ohne-ks-ein")) (ssg-end) (exit))) + + (setq lauf (vfl-kette-verfolgen start-rec alle-records)) + (setq kette (car lauf)) + (setq warnung (cadr lauf)) + (setq naechster-fund (caddr lauf)) + + (if (< (length kette) 2) + (progn + (princ (strcat "\n [Diagnose] KS_AUS Startbaustein (" (vfl-kette-rec-bname start-rec) "): X=" + (rtos (car (vfl-kette-rec-aus start-rec)) 2 1) " Y=" + (rtos (cadr (vfl-kette-rec-aus start-rec)) 2 1) " Z=" + (rtos (caddr (vfl-kette-rec-aus start-rec)) 2 1))) + (if naechster-fund + (princ (strcat "\n [Diagnose] Naechster Kandidat: " (vfl-kette-rec-bname (car naechster-fund)) + " Abstand=" (rtos (cdr naechster-fund) 2 1) + " mm (Toleranz eng=" (rtos *vfl-kette-tol-eng* 2 1) + " mm, weit=" (rtos *vfl-kette-tol-weit* 2 1) " mm)")) + (princ (strcat "\n [Diagnose] Kein anderer Baustein mit KS_EIN gefunden (insgesamt " + (itoa (length alle-records)) " Bausteine erfasst)."))) + (princ (ssg-text "vfl-kette-nur-ein-baustein")) (ssg-end) (exit))) + + (princ (ssg-textf "vfl-kette-gefunden" (list (itoa (length kette))))) + (foreach rec kette (princ (strcat "\n " (vfl-kette-rec-bname rec)))) + (if warnung + (princ (ssg-textf "vfl-kette-luecke-warnung" + (list (car warnung) (cadr warnung) (rtos (caddr warnung) 2 1))))) + + ;; Attribute + Kettenanfang/-ende VOR dem Explodieren sichern (Attribute + ;; eines Wrappers gehen beim Explodieren verloren - werden zu wertlosem Text). + (setq neuer-bname (strcat "VF_" (itoa (vf-next-number)))) + (setq chain-start (vfl-kette-rec-ein (car kette))) + (setq chain-end (vfl-kette-rec-aus (car (reverse kette)))) + (setq erg (vfl-kette-baue-attribute kette neuer-bname chain-start chain-end)) + (setq aggregiert (car erg)) + (setq typ-str (cadr erg)) + + ;; Wrapper (bereits gemergte VF_n) explodieren (Sub-Elemente bleiben als + ;; Bloecke erhalten, ATTRIB-Textreste werden verworfen), Original loeschen. + ;; Lose Einzel-Bausteine werden unveraendert direkt uebernommen (_.-BLOCK + ;; unten SOLLTE sie beim Wickeln konsumieren, wie bei frisch gebauter + ;; Geometrie - leaf-enames wird trotzdem mitgefuehrt, um sie nach dem + ;; Wickeln sicherheitshalber explizit zu entfernen, falls _.-BLOCK sie aus + ;; irgendeinem Grund NICHT aus dem Modellraum nimmt (doppelte/ueberlappende + ;; Geometrie waere sonst die Folge). + (setq merge-ss (ssadd)) + (setq leaf-enames '()) + (foreach rec kette + (if (vfl-kette-rec-wrapper rec) + (progn + (setq kinder (vlax-invoke (vlax-ename->vla-object (vfl-kette-rec-ename rec)) 'Explode)) + (foreach kind kinder + (if (not (vlax-erased-p kind)) + (if (= (vla-get-ObjectName kind) "AcDbBlockReference") + (ssadd (vlax-vla-object->ename kind) merge-ss) + (vla-Delete kind) + ) + ) + ) + (vla-Delete (vlax-ename->vla-object (vfl-kette-rec-ename rec))) + ) + (progn + ;; DIAGNOSE: Skalierung unmittelbar VOR dem Einwickeln pruefen (grenzt + ;; ein, ob eine evtl. Verzerrung schon vor _.-BLOCK/_.INSERT entsteht). + (setq diag-obj (vlax-ename->vla-object (vfl-kette-rec-ename rec))) + (princ (strcat "\n [Diagnose] " (vfl-kette-rec-bname rec) + " vor dem Wickeln: XScale=" + (rtos (vla-get-XScaleFactor diag-obj) 2 4) + " YScale=" (rtos (vla-get-YScaleFactor diag-obj) 2 4) + " ZScale=" (rtos (vla-get-ZScaleFactor diag-obj) 2 4))) + (setq leaf-enames (cons (vfl-kette-rec-ename rec) leaf-enames)) + (ssadd (vfl-kette-rec-ename rec) merge-ss) + ) + ) + ) + + ;; Frische ATTDEFs am Kettenanfang (wie vfl-block-erstellen), neu wickeln. + (foreach def (ssg-strecke-attrib-defs typ-str) + (entmake + (list '(0 . "ATTDEF") + (cons 10 chain-start) + (cons 11 chain-start) + '(40 . 50.0) + (cons 1 (cadr def)) + (cons 2 (car def)) + (cons 3 (car def)) + '(70 . 1) + '(72 . 0) + '(74 . 0))) + (ssadd (entlast) merge-ss) + ) + (setq neuer-insert (ssg-block-wrap-welt neuer-bname chain-start merge-ss)) + (ssg-attrib-set-on neuer-insert aggregiert) + ;; SEITE_AS/SEITE_ES explizit leeren, wenn die Kette (Ausnahmefall) ohne + ;; eigenes AS-/ES-Element beginnt/endet - ssg-attrib-set-on wuerde einen + ;; leeren Wert sonst als "keine Ueberschreibung" behandeln und den + ;; ATTDEF-Default "rechts" faelschlich stehen lassen. + (if (= (cdr (assoc "SEITE_AS" aggregiert)) "") (vfl-kette-attrib-leeren neuer-insert "SEITE_AS")) + (if (= (cdr (assoc "SEITE_ES" aggregiert)) "") (vfl-kette-attrib-leeren neuer-insert "SEITE_ES")) + (if (car (atoms-family 1 '("SSG-ID-GENERATE"))) (ssg-id-generate neuer-insert)) + + ;; DIAGNOSE: Skalierung der verschachtelten Bausteine NACH dem Wickeln + ;; pruefen (temporaerer Explode einer Kopie, sofort wieder geloescht - + ;; neuer-insert selbst bleibt unveraendert). Grenzt ein, ob eine + ;; Verzerrung erst durch _.-BLOCK/_.INSERT entsteht. + (setq diag-kinder (vlax-invoke (vlax-ename->vla-object neuer-insert) 'Explode)) + (foreach diag-obj diag-kinder + (if (and (not (vlax-erased-p diag-obj)) (= (vla-get-ObjectName diag-obj) "AcDbBlockReference")) + (princ (strcat "\n [Diagnose] " (vla-get-Name diag-obj) + " nach dem Wickeln: XScale=" (rtos (vla-get-XScaleFactor diag-obj) 2 4) + " YScale=" (rtos (vla-get-YScaleFactor diag-obj) 2 4) + " ZScale=" (rtos (vla-get-ZScaleFactor diag-obj) 2 4))) + ) + ) + (foreach diag-obj diag-kinder (if (not (vlax-erased-p diag-obj)) (vla-Delete diag-obj))) + + ;; Sicherheitsnetz: lose Einzelteile, die _.-BLOCK aus irgendeinem Grund NICHT + ;; aus dem Modellraum entfernt hat, jetzt explizit loeschen - verhindert + ;; doppelte/ueberlappende Geometrie (altes Original + neuer Gesamt-Block). + (setq leaf-noch-da 0) + (foreach leaf-ename leaf-enames + (setq leaf-obj (vl-catch-all-apply 'vlax-ename->vla-object (list leaf-ename))) + (if (and (not (vl-catch-all-error-p leaf-obj)) leaf-obj (not (vlax-erased-p leaf-obj))) + (progn + (setq leaf-noch-da (1+ leaf-noch-da)) + (vla-Delete leaf-obj) + ) + ) + ) + (if (> leaf-noch-da 0) + (princ (strcat "\n [Diagnose] " (itoa leaf-noch-da) + " lose Einzelteil(e) waren nach _.-BLOCK noch im Modellraum vorhanden - jetzt nachtraeglich entfernt."))) + + (princ (ssg-textf "vfl-kette-fertig" (list neuer-bname (itoa (length kette))))) + (ssg-end) + (princ) +) + (vf-typ-registrieren "linienzug" 'vfl-berechne-platzhalter diff --git a/lang/de_DE.json b/lang/de_DE.json index 91c8f1b..51967d6 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -630,6 +630,17 @@ "tefl-prompt-endpunkt": "\nEndpunkt der Foerderstrecke waehlen: ", "tefl-abgebrochen": "\n[TEF] Abgebrochen.", "tefl-fehler-laenge-null": "\n[TEF] FEHLER: Start- und Endpunkt liegen zu nah beieinander.", - "tefl-fertig": "\n[TEF] %1 Element(e) eingefuegt, Streckenlaenge=%2 mm." + "tefl-fertig": "\n[TEF] %1 Element(e) eingefuegt, Streckenlaenge=%2 mm.", + "vfl-kette-titel": "\n Vario_Kette_Merge - mehrere Vario-Foerderer-Bausteine (einzeln oder bereits gewickelt) zu einem Gesamt-Block verschmelzen", + "vfl-kette-start-waehlen": "\n\nStart-Baustein der Kette waehlen (erstes Element - AS-Element oder VF_n): ", + "vfl-kette-kein-objekt": "\nKein Objekt gewaehlt - Abbruch.", + "vfl-kette-kein-vf-block": "\nGewaehltes Objekt ('%1') ist kein bekannter Vario-Kette-Baustein (AS-/ES-Element, GF-Bogen, Vario-Kurve, Umlenk-/Motorstation, Vertikalbogen, Staustrecke/Separator oder VF_n).", + "vfl-kette-start-nicht-gefunden": "\nFEHLER: Start-Baustein nicht in der Ketten-Erfassung gefunden (interner Fehler).", + "vfl-kette-start-nicht-gefunden-diag": "\nFEHLER: Start-Baustein nicht in der Ketten-Erfassung gefunden (interner Fehler).\n Diagnose: %1 Bausteine insgesamt erfasst, gewaehlter Blockname='%2', davon %3 mit gleichem Blocknamen erfasst.", + "vfl-kette-start-ohne-ks-ein": "\nFEHLER: Am gewaehlten Baustein konnte kein KS_EIN gefunden werden - Kette kann nicht verfolgt werden.", + "vfl-kette-nur-ein-baustein": "\nAb dem gewaehlten Baustein wurde kein weiterer angeschlossener VF_n-Baustein gefunden - nichts zum Zusammenfuehren.", + "vfl-kette-gefunden": "\n\nKette erkannt: %1 Baustein(e) werden zusammengefuehrt:", + "vfl-kette-luecke-warnung": "\n\n WARNUNG: Nach '%1' wurde ein visuell nahes, aber nicht sauber verbundenes VF_n ('%2') gefunden (KS-Abstand %3 mm) - Kette wurde dort beendet, dieser und alle weiteren Bausteine bleiben unangetastet.", + "vfl-kette-fertig": "\n\n>>> Fertig: neuer Gesamt-Block '%1' aus %2 Baustein(en) erstellt." } } diff --git a/lang/en_GB.json b/lang/en_GB.json index 0f94dba..e0306d8 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -630,6 +630,17 @@ "tefl-prompt-endpunkt": "\nSelect end point of the conveyor path: ", "tefl-abgebrochen": "\n[TEF] Cancelled.", "tefl-fehler-laenge-null": "\n[TEF] ERROR: Start and end point are too close together.", - "tefl-fertig": "\n[TEF] %1 element(s) inserted, path length=%2 mm." + "tefl-fertig": "\n[TEF] %1 element(s) inserted, path length=%2 mm.", + "vfl-kette-titel": "\n Vario_Kette_Merge - merge several Vario conveyor blocks (loose or already wrapped) into one combined block", + "vfl-kette-start-waehlen": "\n\nSelect the starting block of the chain (first element - AS element or VF_n): ", + "vfl-kette-kein-objekt": "\nNo object selected - cancelled.", + "vfl-kette-kein-vf-block": "\nSelected object ('%1') is not a known Vario chain block (AS/ES element, GF bend, Vario curve, deflection/motor station, vertical bend, buffer/separator or VF_n).", + "vfl-kette-start-nicht-gefunden": "\nERROR: Starting block not found in the chain collection (internal error).", + "vfl-kette-start-nicht-gefunden-diag": "\nERROR: Starting block not found in the chain collection (internal error).\n Diagnostic: %1 blocks collected in total, selected block name='%2', %3 of those with the same block name.", + "vfl-kette-start-ohne-ks-ein": "\nERROR: No KS_EIN found on the selected block - chain cannot be followed.", + "vfl-kette-nur-ein-baustein": "\nNo further connected VF_n block was found from the selected block onward - nothing to merge.", + "vfl-kette-gefunden": "\n\nChain detected: %1 block(s) will be merged:", + "vfl-kette-luecke-warnung": "\n\n WARNING: after '%1' a visually close but not properly connected VF_n ('%2') was found (KS distance %3 mm) - the chain was ended there; this and all further blocks are left untouched.", + "vfl-kette-fertig": "\n\n>>> Done: new combined block '%1' created from %2 block(s)." } } diff --git a/menu/SSG_LIB.cui b/menu/SSG_LIB.cui index 1c89c3c..6b1d71d 100644 --- a/menu/SSG_LIB.cui +++ b/menu/SSG_LIB.cui @@ -86,631 +86,643 @@ ^C^CETAGEVARIOFOERDERER - + + + Vario_Kette_Merge + ^C^C(ssg-ensure "VarioFoerderer") Vario_Kette_Merge + + + 90 Kurve links angetrieben Aussen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90LA - + 90 Kurve rechts angetrieben Aussen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90RA - + 60 Kurve links angetrieben Aussen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60LA - + 60 Kurve rechts angetrieben Aussen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60RA - + 30 Kurve links angetrieben Aussen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30LA - + 30 Kurve rechts angetrieben Aussen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30RA - + 90 Kurve links angetrieben Innen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90LI - + 90 Kurve rechts angetrieben Innen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90RI - + 60 Kurve links angetrieben Innen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60LI - + 60 Kurve rechts angetrieben Innen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60RI - + 30 Kurve links angetrieben Innen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30LI - + 30 Kurve rechts angetrieben Innen ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30RI - + Gefaellestrecke ^C^C(ssg-ensure "Gefaellestrecke") GEFAELLESTRECKE - + 90 Kurve links Gefaellestrecke ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK90L - + 90 Kurve rechts Gefaellestrecke ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK90R - + 60 Kurve links Gefaellestrecke ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK60L - + 60 Kurve rechts Gefaellestrecke ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK60R - + 30 Kurve links Gefaellestrecke ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK30L - + 30 Kurve rechts Gefaellestrecke ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK30R - + ILS Schliessen ^C^C - + 90 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APB_630_90 - + 67.5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APB_550_675 - + 45 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APB_630_45 - + 22.5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APB_550_225 - + 180 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APB_650_180 - + 90 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APB60_90 - + AP 60 ^C^C(ssg-ensure "OmniModulInsert") OMNI_AP60 - + AP 110 ^C^C(ssg-ensure "OmniModulInsert") OMNI_AP110 - + APG 110 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APG110 - + Einfach 90 700/700 links M ^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Einfach - + Doppel 90 700/700 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Doppel - + Dreiwege 90 700/700 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Dreiwege - + Einfach 45 350/700 links M ^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Einfach - + Doppel 45 350/700 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Doppel - + Dreiwege 45 350/700 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Dreiwege - + Einfach Parallel 200/750 links M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Einfach - + Doppel Parallel 200/750 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Doppel - + Dreiwege Parallel 200/750 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Dreiwege - + Einfach 22.5 links M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Einfach - + Doppel 22.5 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Doppel - + Dreiwege 22.5 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Dreiwege - + Delta 1400/700 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Delta_1400 - + Delta 1600/800 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Delta_1600 - + Star 1400/1400 M ^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Star - + TEF Antriebst. rechts ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebR - + TEF Umlenkspannst. rechts ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkR - + TEF Antriebst. links ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebL - + TEF Umlenkspannst. links ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkL - + TEF Gerade auf Linie ^C^C(ssg-ensure "TEFInsert") TEF_FOERDERER_LINIE - + TEF Gerade ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_Gerade - + Stopper AP ^C^C(ssg-ensure "OmniModulInsert") OMNI_STOPPER - + Scanner ^C^C(ssg-ensure "OmniModulInsert") OMNI_SCANNER - + Bürstenbremse ^C^C(ssg-ensure "OmniModulInsert") OMNI_BUERSTENBREMSE - + KettenFoerderer ^C^C(ssg-ensure "OmniModulInsert") OMNI_KettenFoerderer - + TV W-W kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_W - + TV W-AP110 kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110 - + TV W-AP60 oben kpl. ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP60 - + TV W-AP110-W kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110_W - + TV W-AP oben kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP - + TV 80 ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_80 - + TV 50 ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_50 - + Endplatte Al-Profil AP schraubbar ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_ENDPLATTE - + Anschlag AP-Ende fuer Spulenzug ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_ANSCHLAG - + TV-A fuer AP110/AP60 kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP110_AP60 - + TV-A fuer AP60/ST ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP60_ST - + TV-A fuer AP110/ST kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP110_ST - + TV-SW II fuer SW-SW ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_II_SW_SW - + TV-SW III fuer SW-AP110-SW ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_III_AP110_SW - + TV-SW III fuer SW-AP110 ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_III_AP110 - + TV-SW IV fuer Anschluss SW-AP60 ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_IV_AP60 - + TV-SW IV fuer SW-ST ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_IV_ST - + Muffe ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_MUFFE - + APB 110 R400/45 140 nur fuer Delta ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R400_45_140 - + APB 110 R550/45 194 nur fuer Delta ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_45_194 - + APBW 110 R550/22,5 360x248,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_360 - + APBW 110 R550/22,5 410x298,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410A - + APBW 110 R550/22,5 410x78,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410B - + APBW 110 R550/22,5 410x98,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410C - + APBW 110 R550/67,5 360x598,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_360 - + APBW 110 R400/67,5 260x398,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R400_675_260 - + APBW 110 R550/45 77x160 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_45_77 - + APBW 110 R550/67,5 125x83,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_125 - + APBW 110 R750/90 200x290 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R750_90_200 - + APBW 110 R650/90 300x190 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R650_90_300 - + 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 - + Export Sivas ^C^C(ssg-ensure "count_sep_scan") ZAEHLE_SEP_SCAN (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 - + Gefaellestrecke ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_gefaellestrecke.lsp")) TEST_GEFAELLESTRECKE - + + + 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 - + SSG Bearbeiten (Auto) (ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT @@ -726,21 +738,21 @@ POP1 SSG_LIB - - - - + + + + ILS - + ILS Schliessen - + @@ -819,708 +831,720 @@ + + Vario_Kette_Merge + + + + ~90 Kurve links angetrieben Aussen - - - - - - ~90 Kurve rechts angetrieben Aussen - ~60 Kurve links angetrieben Aussen + ~90 Kurve rechts angetrieben Aussen - ~60 Kurve rechts angetrieben Aussen + ~60 Kurve links angetrieben Aussen - ~30 Kurve links angetrieben Aussen + ~60 Kurve rechts angetrieben Aussen - ~30 Kurve rechts angetrieben Aussen + ~30 Kurve links angetrieben Aussen + + ~30 Kurve rechts angetrieben Aussen + + + + ~90 Kurve links angetrieben Innen - + ~90 Kurve rechts angetrieben Innen - + ~60 Kurve links angetrieben Innen - + ~60 Kurve rechts angetrieben Innen - + ~30 Kurve links angetrieben Innen - + ~30 Kurve rechts angetrieben Innen - + - + Gefaellestrecke Gefaellestrecke - + ~90 Kurve links Gefaellestrecke - + ~90 Kurve rechts Gefaellestrecke - + ~60 Kurve links Gefaellestrecke - + ~60 Kurve rechts Gefaellestrecke - + ~30 Kurve links Gefaellestrecke - + ~30 Kurve rechts Gefaellestrecke - - - - - - Omniflo - - - - - - - - - - - - ~KettenFoerderer - - - - - - - - Element bearbeiten - - + + Omniflo + + + + + + + + + + + + ~KettenFoerderer + + + + + + + + Element bearbeiten + + + + + + Boegen APB110 90 - - - - - - 67.5 - 45 + 67.5 - 22.5 + 45 - 180 + 22.5 + + 180 + + + + - + Boegen APB60 90 - + - + Aluprofil Gerade AP 60 - - - - - - AP 110 - APG 110 + AP 110 + + APG 110 + + + + - + Weiche 90 Grad Einfach 90 700/700 links M - - - - - - Doppel 90 700/700 M - Dreiwege 90 700/700 M + Doppel 90 700/700 M + + Dreiwege 90 700/700 M + + + + - + Weiche 45 Grad Einfach 45 350/700 links M - - - - - - Doppel 45 350/700 M - Dreiwege 45 350/700 M + Doppel 45 350/700 M + + Dreiwege 45 350/700 M + + + + - + Weichen Parallel Einfach Parallel 200/750 links M - - - - - - Doppel Parallel 200/750 M - Dreiwege Parallel 200/750 M + Doppel Parallel 200/750 M + + Dreiwege Parallel 200/750 M + + + + - + Weichenkoerper Einfach 22.5 links M - - - - - - Doppel 22.5 M - Dreiwege 22.5 M + Doppel 22.5 M + + Dreiwege 22.5 M + + + + - + Weichenkombinationen Delta 1400/700 M - - - - - - Delta 1600/800 M - Star 1400/1400 M + Delta 1600/800 M + + Star 1400/1400 M + + + + - + TEF Elemente TEF Antriebst. rechts - + TEF Umlenkspannst. rechts - + TEF Antriebst. links - + TEF Umlenkspannst. links - + TEF Gerade auf Linie - + TEF Gerade - + - + Anbaugruppen Stopper AP - - - - - - Scanner - Bürstenbremse + Scanner + + Bürstenbremse + + + + - + Verbinder ~TV W-W kpl - - - - - - ~TV W-AP110 kpl - ~TV W-AP60 oben kpl. + ~TV W-AP110 kpl - ~TV W-AP110-W kpl + ~TV W-AP60 oben kpl. - ~TV W-AP oben kpl + ~TV W-AP110-W kpl - ~TV 80 + ~TV W-AP oben kpl - ~TV 50 + ~TV 80 - ~Endplatte Al-Profil AP schraubbar + ~TV 50 - ~Anschlag AP-Ende fuer Spulenzug + ~Endplatte Al-Profil AP schraubbar - ~TV-A fuer AP110/AP60 kpl + ~Anschlag AP-Ende fuer Spulenzug - ~TV-A fuer AP60/ST + ~TV-A fuer AP110/AP60 kpl - ~TV-A fuer AP110/ST kpl + ~TV-A fuer AP60/ST - ~TV-SW II fuer SW-SW + ~TV-A fuer AP110/ST kpl - ~TV-SW III fuer SW-AP110-SW + ~TV-SW II fuer SW-SW - ~TV-SW III fuer SW-AP110 + ~TV-SW III fuer SW-AP110-SW - ~TV-SW IV fuer Anschluss SW-AP60 + ~TV-SW III fuer SW-AP110 - ~TV-SW IV fuer SW-ST + ~TV-SW IV fuer Anschluss SW-AP60 - ~Muffe + ~TV-SW IV fuer SW-ST + + ~Muffe + + + + - + Boegen fuer Weichen ~APB 110 R400/45 140 nur fuer Delta - - - - - - ~APB 110 R550/45 194 nur fuer Delta - ~APBW 110 R550/22,5 360x248,5 + ~APB 110 R550/45 194 nur fuer Delta - ~APBW 110 R550/22,5 410x298,5 + ~APBW 110 R550/22,5 360x248,5 - ~APBW 110 R550/22,5 410x78,5 + ~APBW 110 R550/22,5 410x298,5 - ~APBW 110 R550/22,5 410x98,5 + ~APBW 110 R550/22,5 410x78,5 - ~APBW 110 R550/67,5 360x598,5 + ~APBW 110 R550/22,5 410x98,5 - ~APBW 110 R400/67,5 260x398,5 + ~APBW 110 R550/67,5 360x598,5 - ~APBW 110 R550/45 77x160 + ~APBW 110 R400/67,5 260x398,5 - ~APBW 110 R550/67,5 125x83,5 + ~APBW 110 R550/45 77x160 - ~APBW 110 R750/90 200x290 + ~APBW 110 R550/67,5 125x83,5 - ~APBW 110 R650/90 300x190 + ~APBW 110 R750/90 200x290 - ~APBW 110 R550/67,5 208x347 + ~APBW 110 R650/90 300x190 - ~APBW 110 R550/67,5 58x497 + ~APBW 110 R550/67,5 208x347 + + ~APBW 110 R550/67,5 58x497 + + + + - + Export Export Sivas - + Export CSV - + - + Konfiguration Umschalten 2D und 3D - - - - - - Alle Bloecke auf 2D - Alle Bloecke auf 3D + Alle Bloecke auf 2D - Sprache + Alle Bloecke auf 3D + + Sprache + + + + Konfiguration Schliessen - + - + Tests Alle Tests ausfuehren - + Kreisel - + Foerderer - + Foerderer-Linienzug - + Omniflo - + Gefaellestrecke - + + + + + KS 2D/3D pruefen (CSV) + + Export CSV/Sivas ALL - + - + POP501 SSG_LIB Edit Context Kreisel bearbeiten - + Omniflo Element bearbeiten - + Gefaellestrecke bearbeiten - + VarioFoerderer bearbeiten - + SSG Bearbeiten (Auto) - + diff --git a/menu/SSG_LIB.mnu b/menu/SSG_LIB.mnu index c5977b8..0948989 100644 --- a/menu/SSG_LIB.mnu +++ b/menu/SSG_LIB.mnu @@ -18,6 +18,7 @@ [~Durch TEF angetriebene Strecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_TEF_Strecke [VarioFoerderer]^C^CVarioFoerderer [EtageVarioFoerderer]^C^CETAGEVARIOFOERDERER +[Vario_Kette_Merge]^C^C(ssg-ensure "VarioFoerderer") Vario_Kette_Merge [--] [~90 Kurve links angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90LA [~90 Kurve rechts angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90RA diff --git a/tests/testdata/linienzug_tests.json b/tests/testdata/linienzug_tests.json index 229b743..00b16fd 100644 --- a/tests/testdata/linienzug_tests.json +++ b/tests/testdata/linienzug_tests.json @@ -28,8 +28,8 @@ }, { "typ": "string", - "wert": "1", - "kommentar": "getstring Naechstes Element (Neue Linie)" + "wert": "2", + "kommentar": "getstring Naechstes Element (2 = Neue Linie: Ab/Auf VF - Gefaelle hier 26 Grad > GF-Maximalwinkel, daher NICHT Option 1/GF)" }, { "typ": "point_rel",