diff --git a/CLAUDE.md b/CLAUDE.md index 89e149e..476bee6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -93,7 +93,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `ssg_dialog.lsp` | - | DCL-Dialog-Vorlagen und Hilfsfunktionen | | `ssg_layer.lsp` | - | Layer-Verwaltung | | `KreiselInsert.lsp` | KreiselInsert, KreiselConnect, KreiselRedraw, KreiselQuick, KreiselEdit, KreiselParams, KreiselLabelSetup, KreiselLabelPos, KreiselLabelHoehe, ILS_Eckrad | ILS Kreisel und Eckrad komplett in AutoLISP | -| `VarioFoerderer.lsp` (Wrapper fuer `vf_core.lsp`/`vf_standard.lsp`/`vf_etage.lsp`/`vf_linienzug.lsp`) | FOERDERANLAGE, VARIOFOERDERER_EDIT, VARIOFOERDERER_NACHRUESTEN, Vario_Kette_Merge, VF_WIZARD_AN, VF_WIZARD_AUS | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standard- UND Etage-Typ: Werteingabe per DCL-Dialog (`vfs-standard-dialog-ablauf` in vf_standard.lsp bzw. `vfe-etage-dialog-ablauf` in vf_etage.lsp, beide nutzen dieselben Dialoge `vfs-dialog-eingabe-basis`/`vfs-dialog-winkel-verteilung`); Doppelklick auf VF_n-Block ruft VARIOFOERDERER_EDIT, das per SSG_VF_EDIT-XDATA-Marker ("standard"/"etage"/"linienzug") in den passenden Neuaufbau-Zweig dispatcht (`vfe-edit-ent` fuer Etage, `vfl-edit-ent` fuer Linienzug); Altbestand-Bloecke ohne Marker werden abgewiesen. Linienzug (Modus 1, `vf-linienzug-modus`) zeichnet jede interaktive Eingabe in einem Journal auf (`vfl-in-point`/`-string`/`-real`/`-int`) und schreibt es als XDATA auf den fertigen `VF_n`-Block; ein Abbruch (ESC) loescht dadurch nichts mehr, sondern wickelt die bis dahin gebaute Teil-Geometrie ebenso zu einem Block (`vfl-modus-abbruch-sichern`) - sie bleibt stehen und ist sofort per Doppelklick weiter editierbar/fortsetzbar. Der komplette Linienzug-Hauptstrang (Menue-Fragen von AS-Element bis Kettenende, inkl. GF-Bogen/Vario-Kurve/VF-Einheit-Fortsetzung) laeuft per Default ueber DCL-Dialoge statt Konsole (`*vfl-wizard-mode*`, Befehle VF_WIZARD_AN/VF_WIZARD_AUS): `vfl-in-string`/`-int`/`-real` zeigen bei aktivem Wizard-Modus generische Dialoge aus `dcl/vf_linienzug_wizard.dcl` (Zahl-Eingabe bzw. Mehrfachauswahl aus `vfl-menu`/`vfl-menu-int`) statt `getstring`/`getint`/`getreal` aufzurufen; die ORIGINALEN Konsolen-Fragen (princ + get*, de/en ueber ssg-text) bleiben unveraendert im Code (Fallback bei Fehlern via `vl-catch-all-apply`, siehe `doc/variofoerderer.md`). `vfl-edit-ent` liest das Journal, zeigt die Sektionen ueber einen DCL-Dialog (`vfl-dlg-position`, `dcl/vfl_edit.dcl`) an, kuerzt bei Bedarf auf eine gewaehlte Sektion (stummer Replay der behaltenen Eingaben, umgeht den Wizard-Zweig komplett) und baut danach interaktiv weiter. Linienzug Modus 2 (Pfad+Zielhoehe-Solver, `vf-linienzug-modus2`) nutzt dieselben Wrapper PLUS die neue Objektauswahl-Wrapper-Funktion `vfl-in-selection` (Pfad-Objekte als stabile Entity-Handles journalisiert, neue Journal-Art `"OBJS"`) und schreibt sein Journal unter dem eigenen XDATA-Marker `"linienzug2"`; Doppelklick baut hier NICHT abschnittsweise, sondern per vollem Reset 1:1 aus dem Journal neu auf (`vfl-edit-ent2`, dispatcht aus `vfl-edit-ent` per Marker) - Modus 3 (Vorwaerts-Nachbau) bleibt bewusst reine Konsole (im Code selbst als Legacy/"wird umgebaut" markiert). `Vario_Kette_Merge` (in vf_linienzug.lsp) fuehrt mehrere einzeln gebaute VF_n-Bloecke ab einem gewaehlten Start-Baustein ueber die reale KS_AUS->KS_EIN-Nachbarschaft zu einem Gesamt-Block zusammen (aggregierte Attribute, Luecken-Erkennung). Details/Entscheidungsbaum: `doc/variofoerderer.md` | +| `VarioFoerderer.lsp` (Wrapper fuer `vf_core.lsp`/`vf_standard.lsp`/`vf_etage.lsp`/`vf_linienzug.lsp`) | FOERDERANLAGE, VARIOFOERDERER_EDIT, VARIOFOERDERER_NACHRUESTEN, Vario_Kette_Merge, VF_WIZARD_AN, VF_WIZARD_AUS | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standard- UND Etage-Typ: Werteingabe per DCL-Dialog (`vfs-standard-dialog-ablauf` in vf_standard.lsp bzw. `vfe-etage-dialog-ablauf` in vf_etage.lsp, beide nutzen dieselben Dialoge `vfs-dialog-eingabe-basis`/`vfs-dialog-winkel-verteilung`); Doppelklick auf VF_n-Block ruft VARIOFOERDERER_EDIT, das per SSG_VF_EDIT-XDATA-Marker ("standard"/"etage"/"linienzug") in den passenden Neuaufbau-Zweig dispatcht (`vfe-edit-ent` fuer Etage, `vfl-edit-ent` fuer Linienzug); Altbestand-Bloecke ohne Marker werden abgewiesen. Linienzug (Modus 1, `vf-linienzug-modus`) zeichnet jede interaktive Eingabe in einem Journal auf (`vfl-in-point`/`-string`/`-real`/`-int`) und schreibt es als XDATA auf den fertigen `VF_n`-Block; ein Abbruch (ESC) loescht dadurch nichts mehr, sondern wickelt die bis dahin gebaute Teil-Geometrie ebenso zu einem Block (`vfl-modus-abbruch-sichern`) - sie bleibt stehen und ist sofort per Doppelklick weiter editierbar/fortsetzbar. Der komplette Linienzug-Hauptstrang (Menue-Fragen von AS-Element bis Kettenende, inkl. GF-Bogen/Vario-Kurve/VF-Einheit-Fortsetzung) laeuft per Default ueber DCL-Dialoge statt Konsole (`*vfl-wizard-mode*`, Befehle VF_WIZARD_AN/VF_WIZARD_AUS): `vfl-in-string`/`-int`/`-real` zeigen bei aktivem Wizard-Modus generische Dialoge aus `dcl/vf_linienzug_wizard.dcl` (Zahl-Eingabe bzw. Mehrfachauswahl aus `vfl-menu`/`vfl-menu-int`) statt `getstring`/`getint`/`getreal` aufzurufen; die ORIGINALEN Konsolen-Fragen (princ + get*, de/en ueber ssg-text) bleiben unveraendert im Code (Fallback bei Fehlern via `vl-catch-all-apply`, siehe `doc/variofoerderer.md`). `vfl-edit-ent` liest das Journal, zeigt die Sektionen ueber einen DCL-Dialog (`vfl-dlg-position`, `dcl/vfl_edit.dcl`) an, kuerzt bei Bedarf auf eine gewaehlte Sektion (stummer Replay der behaltenen Eingaben, umgeht den Wizard-Zweig komplett) und baut danach interaktiv weiter. Linienzug Modus 2 (Pfad+Zielhoehe-Solver, `vf-linienzug-modus2`) nutzt dieselben Wrapper PLUS die neue Objektauswahl-Wrapper-Funktion `vfl-in-selection` (Pfad-Objekte als stabile Entity-Handles journalisiert, neue Journal-Art `"OBJS"`) und schreibt sein Journal unter dem eigenen XDATA-Marker `"linienzug2"`; Doppelklick baut hier NICHT abschnittsweise, sondern per vollem Reset 1:1 aus dem Journal neu auf (`vfl-edit-ent2`, dispatcht aus `vfl-edit-ent` per Marker) - Modus 3 (Vorwaerts-Nachbau) bleibt bewusst reine Konsole (im Code selbst als Legacy/"wird umgebaut" markiert). `Vario_Kette_Merge` (in vf_linienzug.lsp) fuehrt mehrere einzeln gebaute VF_n-Bloecke ab einem gewaehlten Start-Baustein ueber die reale KS_AUS->KS_EIN-Nachbarschaft zu einem Gesamt-Block zusammen (aggregierte Attribute, Luecken-Erkennung). `vf_konstanten.lsp` (von vf_core.lsp vor den drei Submodulen geladen) sammelt alle Laengen-/Winkel-/Toleranz-Magic-Numbers aus dem VarioFoerderer-Cluster als dokumentierte `*vfk-*`-Konstanten - aktuell reines Nachschlagewerk, die Module selbst nutzen weiterhin ihre eigenen Werte (Migration steht noch aus). Details/Entscheidungsbaum: `doc/variofoerderer.md` | | `Gefaellestrecke.lsp` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT | Gefaelle-Foerderanlage (AUS -> Staustrecke skaliert -> Separator -> EIN); Modus 1 per DCL-Dialog (Einfuegehoehe, Element-Winkel 30/90); Doppelklick auf GF_n-Block ruft GEFAELLESTRECKE_EDIT (Dialog vorbelegt, Neuaufbau) | | `export.lsp` | EXPORTSIVAS, EXPORTCSV, OMNI_UPDATE_ATTRIBS | JSON-Sammlung und Python-Export (Omniflo-Merkmale/Sum-Zeile via lib/export_csv.py) | | `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W*_*, OMNI_AP60/AP110, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen, Edit-Dialog | diff --git a/Lisp/vf_core.lsp b/Lisp/vf_core.lsp index 44f1d8c..626a4fd 100644 --- a/Lisp/vf_core.lsp +++ b/Lisp/vf_core.lsp @@ -1222,6 +1222,7 @@ ) (if *vf-lisp-pfad* (progn + (load (strcat *vf-lisp-pfad* "/vf_konstanten.lsp")) (load (strcat *vf-lisp-pfad* "/vf_standard.lsp")) (load (strcat *vf-lisp-pfad* "/vf_etage.lsp")) (load (strcat *vf-lisp-pfad* "/vf_linienzug.lsp")) diff --git a/Lisp/vf_konstanten.lsp b/Lisp/vf_konstanten.lsp new file mode 100644 index 0000000..3714155 --- /dev/null +++ b/Lisp/vf_konstanten.lsp @@ -0,0 +1,259 @@ +;; ============================================================ +;; VF_KONSTANTEN - Zentrale Sammlung aller Laengen-/Winkel-/Toleranz- +;; Magic-Numbers aus vf_core.lsp, vf_standard.lsp, vf_etage.lsp, +;; vf_linienzug.lsp +;; ============================================================ +;; ZWECK dieser Datei: Nachschlagewerk + Grundlage fuer eine schrittweise +;; Migration - NICHT (noch) die aktive Quelle der Werte. Die vier vf_*.lsp- +;; Module verwenden ihre Werte weiterhin direkt (eigene *vfl-*/*vfs-*/ +;; FESTE_*-Variablen bzw. rohe Literale, teils ueber ssg-cfg-or). Aendert +;; sich ein Wert hier, hat das AKTUELL KEINE Wirkung auf den Bauablauf - +;; die entsprechende Stelle im jeweiligen Modul muss weiterhin dort separat +;; angepasst werden. Diese Datei macht nur sichtbar, WELCHE Werte es gibt, +;; wo sie herkommen und wo sie (noch) dupliziert sind. +;; +;; Migrationsidee (spaeter, schrittweise, EIN Modul nach dem anderen): +;; einzelne Aufrufstellen von rohem Literal auf *vfk-*-Konstante umstellen, +;; mit Test in BricsCAD nach jedem Modul. Bei den bereits ueber ssg-cfg-or +;; konfigurierbaren Werten (gefaelle_winkel, bogen_winkel, feste_horizontal, +;; staustrecke_basis, separator_block_dx/dz, station_block_dx/dz, +;; skalierung_basis) bleibt die Config-Anbindung die fuehrende Quelle - +;; *vfk-*-Konstanten hier sind dafuer nur Fallback/Dokumentation, siehe +;; jeweiliger Kommentar. +;; +;; Geladen von vf_core.lsp VOR vf_standard/vf_etage/vf_linienzug (siehe +;; dortige Ladereihenfolge, dieselbe Guard-Systematik wie in den anderen +;; vf_*.lsp-Dateien: atoms-family-Check verhindert Doppel-Laden). +;; ============================================================ + +(if (not (car (atoms-family 1 '("VF-TYP-REGISTRIEREN")))) + (progn + (setq *vf-konst-core-pfad* + (cond + ((getenv "DXFM_LISP") + (vl-string-translate "\\" "/" (getenv "DXFM_LISP"))) + ((and (boundp '*ssg-lisp-pfad*) *ssg-lisp-pfad*) + *ssg-lisp-pfad*) + (t nil) + ) + ) + (if *vf-konst-core-pfad* + (load (strcat *vf-konst-core-pfad* "/vf_core.lsp")) + (princ "\n[WARNUNG] vf_konstanten.lsp: DXFM_LISP/ssg-lisp-pfad nicht gesetzt.") + ) + ) +) + +;; ============================================================ +;; TEIL 1: WINKEL (Grad) +;; ============================================================ + +;; Basis-Neigungswinkel jeder Gefaellestrecke (GF) - AKTIVE Quelle bleibt +;; (ssg-cfg-or "vario" "gefaelle_winkel" 3), an >15 Stellen korrekt darueber +;; bezogen. ABER an mindestens 12 weiteren Stellen als rohes 3.0/3-Literal +;; dupliziert, OHNE Bezug zur Config (vf_standard.lsp Z.309/412; +;; vf_etage.lsp Z.449-450/479/654ff/793; vf_linienzug.lsp Z.1071/1554/2873/ +;; 3394/4159/4273/4278) - eine Aenderung des Winkels ueber Config wuerde +;; diese Stellen NICHT mitziehen. +(if (null *vfk-gefaelle-winkel*) (setq *vfk-gefaelle-winkel* 3.0)) + +;; Toleranzband (Grad) um *vfk-gefaelle-winkel*: liegt der natuerliche +;; Neigungswinkel eines fallenden Segments innerhalb Toleranz, gilt es als +;; reine Gefaellestrecke statt VF. Bereits als *vfl-gf-winkel-toleranz* in +;; vf_linienzug.lsp benannt (Wert 0.5) - hier nur gespiegelt/dokumentiert. +(if (null *vfk-gf-winkel-toleranz*) (setq *vfk-gf-winkel-toleranz* 0.5)) + +;; Diskrete Bogenwinkel-Tabelle fuer VF-Boegen (auf/ab). AKTIVE Quelle in +;; vf_standard.lsp/vf_linienzug.lsp: (ssg-cfg-or "vario" "bogen_winkel" ...) +;; mit demselben Fallback. INKONSISTENZ: in vf_etage.lsp (Zeile ~447) fest +;; verdrahtet OHNE Config-Anbindung - eine Config-Aenderung wuerde dort +;; nicht greifen. +(if (null *vfk-bogen-winkel*) (setq *vfk-bogen-winkel* '(3 6 9 12 15 18 21 27 33 39 45 51))) + +;; GF-Bogen-Winkel (horizontale Kurve): 30/60/90 Grad, ueberall als +;; Menue-Auswahl hartcodiert (KEIN Config-Bezug, auch nicht ueber +;; ssg-cfg-or) - Blocknamen "Gefaellebogen___R500" leiten +;; sich direkt aus diesen drei Werten ab. +(if (null *vfk-gf-bogen-winkel*) (setq *vfk-gf-bogen-winkel* '(30 60 90))) + +;; Etage-Typ: Schwenkwinkel der Ein-/Auslauf-Schraegsektion. Bereits als +;; ETAGE_HZ_WINKEL in vf_etage.lsp benannt (Wert 30, Kommentar "war frueher +;; 60") - hier nur gespiegelt. +(if (null *vfk-etage-hz-winkel*) (setq *vfk-etage-hz-winkel* 30.0)) + +;; Eckwinkel-Toleranz bei der automatischen Pfad-Klassifizierung (Modus 3, +;; vf-linienzug-modus3 -> vfl2-pruefe-eckwinkel). Rohes Literal in +;; vf_linienzug.lsp Zeile ~3386, keine Konstante bisher. +(if (null *vfk-eckwinkel-toleranz*) (setq *vfk-eckwinkel-toleranz* 5.0)) + +;; Schwellwert (Grad), ab dem ein Frame noch als "flach" (~0 Grad) gilt. +;; Rohes Literal in vfl-frame-flach-p (vf_linienzug.lsp), keine Konstante. +(if (null *vfk-frame-flach-toleranz*) (setq *vfk-frame-flach-toleranz* 1.5)) + +;; ============================================================ +;; TEIL 2: HORIZONTALE BUDGETS (mm) - Umlenk-/Motorstation + Separatoren +;; ============================================================ +;; ACHTUNG: vier verschiedene, NICHT austauschbare Werte fuer "horizontales +;; Budget der festen Elemente einer VF-Einheit", je nach Kontext - das ist +;; die verwirrendste Stelle im ganzen Modul-Satz: +;; - Standard-VF (2 Separatoren, Ein+Aus): FESTE_HORIZONTAL = 1600 +;; (vf_standard.lsp Z.38, ssg-cfg-or "vario" "feste_horizontal" 1600) +;; - Linienzug-VF (1 Separator, nur Einlauf): *vfl-feste-horizontal* = 1300 +;; (vf_linienzug.lsp Z.63) +;; - Etage-VF (mittlere Sektion): FESTE_ETAGE_MITTE = 1000 +;; (vf_etage.lsp Z.41) +;; - Linienzug-Kettenende/Body-Abschluss (nur Motor+1 Separator, KEIN +;; Umlenk-Anteil): 800 als rohes Literal an >10 Stellen in +;; vf_linienzug.lsp (vfl-body-zerlegung, vfl3-waehle-winkel, ...) +;; Diese vier NICHT vereinheitlichen ohne sorgfaeltige Pruefung - sie +;; entstehen aus unterschiedlicher Bauteil-Zusammensetzung (siehe jeweiliger +;; Kommentar im Modul), keine Kopiergleichheit. +(if (null *vfk-feste-horizontal-standard*) (setq *vfk-feste-horizontal-standard* 1600.0)) +(if (null *vfk-feste-horizontal-linienzug*) (setq *vfk-feste-horizontal-linienzug* 1300.0)) +(if (null *vfk-feste-horizontal-etage*) (setq *vfk-feste-horizontal-etage* 1000.0)) +(if (null *vfk-feste-horizontal-kettenende*) (setq *vfk-feste-horizontal-kettenende* 800.0)) + +;; Umlenk-/Motorstation-Fussabdruck (mm), je EINE Station. AKTIVE Quelle in +;; vf_standard.lsp: (ssg-cfg-or "vario" "station_block_dx" 500). In +;; vf_etage.lsp/vf_linienzug.lsp ueberwiegend als rohes 500/500.0-Literal +;; direkt in Formeln/Blockaufrufen dupliziert (>10 Fundstellen), OHNE +;; Config-Bezug. +(if (null *vfk-stations-laenge*) (setq *vfk-stations-laenge* 500.0)) + +;; Separator-Laenge (mm). AKTIVE Quelle in vf_standard.lsp: (ssg-cfg-or +;; "vario" "separator_block_dx" 300). In vf_etage.lsp/vf_linienzug.lsp +;; ueberwiegend als rohes 300/300.0-Literal dupliziert (Blockname +;; "Staustrecke_Separator_SP_300_mm" traegt den Wert zusaetzlich im String). +(if (null *vfk-separator-laenge*) (setq *vfk-separator-laenge* 300.0)) + +;; Mindestlaenge (mm) fuer eine VF-Einheit (Umlenk+Motor = 2x +;; *vfk-stations-laenge*). Rohes 1000.0-Literal an 7 Stellen in +;; vf_linienzug.lsp dupliziert (vfl-vf-entscheidung, vfl-vf-machbar-p, +;; vfl-segment-entscheidung, vf-linienzug-modus mehrfach). +(if (null *vfk-vf-mindestlaenge*) (setq *vfk-vf-mindestlaenge* 1000.0)) + +;; Mindestlaenge (mm) am Linienzug-Kettenende-Abschluss (nur Motor+ +;; Separator, kein Umlenk-Anteil - siehe *vfk-feste-horizontal-kettenende*). +;; Rohes 800.0-Literal, identisch zum Budget-Wert selbst. +(if (null *vfk-kettenende-mindestlaenge*) (setq *vfk-kettenende-mindestlaenge* 800.0)) + +;; Mindestlaenge (mm) fuer die 3-Grad-GF-Anschlussstrecke (GF1 am Einlauf +;; einer VF-Einheit). Bereits als *vfl-gf-min-laenge* in vf_linienzug.lsp +;; benannt (Wert 400.0) - hier nur gespiegelt. In vf_linienzug.lsp Zeile +;; ~4143 zusaetzlich als rohes 400.0-Literal dupliziert (br-gf1), ohne +;; Bezug auf *vfl-gf-min-laenge*. +(if (null *vfk-gf-anschluss-mindestlaenge*) (setq *vfk-gf-anschluss-mindestlaenge* 400.0)) + +;; ============================================================ +;; TEIL 3: STRECKENLAENGEN-GRENZWERTE (mm) +;; ============================================================ + +;; Foerderer-Maximallaenge (Linienzug-Einzelsegment beim Picken). Rohes +;; 25000.0-Literal in vfl-neue-linie-messen (vf_linienzug.lsp), keine +;; Konstante bisher. +(if (null *vfk-segment-maximallaenge*) (setq *vfk-segment-maximallaenge* 25000.0)) + +;; 20-Meter-Regel (Warnschwelle Gesamtlaenge seit letzter Umlenkstation, +;; siehe Prinzipien-Dok Abschnitt 7). Rohes 20000.0-Literal in +;; vfl-20m-check (vf_linienzug.lsp), keine Konstante bisher. +(if (null *vfk-motorabstand-warnung*) (setq *vfk-motorabstand-warnung* 20000.0)) + +;; Unterer Clamp-Wert (mm) fuer diverse Restlaengen-Berechnungen +;; ("max 100.0 ..."), verhindert negative/entartete Kurzstrecken. Rohes +;; 100.0-Literal an >10 Stellen in vf_linienzug.lsp dupliziert +;; (vfl-baue-horizontal-koerper, vf-linienzug-modus3-Umfeld, ...). +(if (null *vfk-restlaenge-min-clamp*) (setq *vfk-restlaenge-min-clamp* 100.0)) + +;; Unterer Clamp-Wert (mm) fuer die variable Auslauf-Staustrecke im +;; Etage-Typ ("Schutz gegen negative/zu kurze GF"). Rohes 50.0-Literal in +;; etage-foerderanlage-einfuegen (vf_etage.lsp Zeile ~800). +(if (null *vfk-etage-auslauf-min-clamp*) (setq *vfk-etage-auslauf-min-clamp* 50.0)) + +;; ============================================================ +;; TEIL 4: FALLBACK-VERSATZWERTE (mm) - AS-/ES-/Gefaellebogen-Masse, falls +;; die Blockdefinition/das Koordinatensystem nicht extrahierbar ist +;; ============================================================ +;; Diese Werte sind EMPIRISCH aus den realen Blockmassen abgeleitet und +;; sollten bei einer Aenderung der zugrundeliegenden DWG-Bloecke ebenfalls +;; neu vermessen werden - keine "sauberen" Rundwerte. + +;; AS-/ES-Element-Fallback-Versatz (dx, mm), Standard-Typ (90 Grad) und +;; Linienzug. Rohes 576.0-Literal an mehreren Stellen in vf_linienzug.lsp +;; dupliziert (Zeile ~3393/4030/4031: "(if aus-dx aus-dx 576.0)" bzw. +;; ein-dx-Aequivalent). +(if (null *vfk-as-es-fallback-dx*) (setq *vfk-as-es-fallback-dx* 576.0)) + +;; Etage-Typ (30 Grad): eigene Fallback-Masse fuer AS_Element_30 (dx/dz, +;; vf_etage.lsp Zeile ~90/96) und ES_Element_30 (Zeile ~124/130) - NICHT +;; identisch zu *vfk-as-es-fallback-dx* (anderer Blocktyp/Winkel). +(if (null *vfk-etage-as-fallback-dx*) (setq *vfk-etage-as-fallback-dx* 525.8)) +(if (null *vfk-etage-as-fallback-dz*) (setq *vfk-etage-as-fallback-dz* -72.9)) +(if (null *vfk-etage-es-fallback-dx*) (setq *vfk-etage-es-fallback-dx* 576.2)) +(if (null *vfk-etage-es-fallback-dz*) (setq *vfk-etage-es-fallback-dz* -54.6)) + +;; Etage-Typ: Fallback-Versatz (dz, mm) fuer Gefaellebogen links/rechts, +;; falls Block/KS nicht extrahierbar (vf_etage.lsp Zeile ~156-195). +(if (null *vfk-etage-gefaellebogen-fallback-dz*) (setq *vfk-etage-gefaellebogen-fallback-dz* -10.0)) + +;; ============================================================ +;; TEIL 5: BESCHRIFTUNG / TEXT (mm) +;; ============================================================ + +;; Texthoehe (mm) des sichtbaren ATTDEF/TEXT-Labels (vf-make-label, +;; vf_core.lsp Zeile ~1073). Rohes Literal, keine Konstante bisher. +(if (null *vfk-label-texthoehe*) (setq *vfk-label-texthoehe* 100.0)) + +;; Texthoehe (mm) der unsichtbaren ATTDEFs (vf-block-erstellen, +;; vf_core.lsp Zeile ~1125). Rohes Literal, keine Konstante bisher. +(if (null *vfk-attdef-texthoehe*) (setq *vfk-attdef-texthoehe* 50.0)) + +;; Y-Versatz (mm) zwischen aufeinanderfolgenden ATTDEF-Zeilen +;; (vf_core.lsp Zeile ~1131). Rohes Literal, keine Konstante bisher. +(if (null *vfk-attdef-zeilenabstand*) (setq *vfk-attdef-zeilenabstand* 100.0)) + +;; Beschriftungsversatz (mm) senkrecht zur Fahrtrichtung (vf-make-label, +;; vf_core.lsp Zeile ~1059-1060). Rohes 200.0-Literal. +(if (null *vfk-label-versatz*) (setq *vfk-label-versatz* 200.0)) + +;; ============================================================ +;; TEIL 6: SONSTIGE +;; ============================================================ + +;; mm -> m Umrechnungsfaktor fuer die Montagehoehe-Mittelwertbildung +;; ("(/ (+ hoehe-von hoehe-bis) 2000.0)" = Mittelwert zweier mm-Werte, +;; direkt in m). Kommt identisch in vf_core.lsp Zeile ~1154 UND +;; vf_linienzug.lsp Zeile ~2258/4742 vor - inhaltlich einfach 1000.0*2, +;; aber nirgends so ausgedrueckt. +(if (null *vfk-mm-je-m*) (setq *vfk-mm-je-m* 1000.0)) + +;; Skalierungsbasis (mm) fuer insert-inclined-scaled-block. AKTIVE Quelle: +;; (ssg-cfg-or "vario" "skalierung_basis" 1000.0), vf_core.lsp Zeile ~821. +;; Hier nur gespiegelt/dokumentiert. +(if (null *vfk-skalierungsbasis*) (setq *vfk-skalierungsbasis* 1000.0)) + +;; Toleranzband (mm) der automatischen Ketten-Nachbarschaftserkennung +;; (Vario_Kette_Merge). Bereits als *vfl-kette-tol-eng*/*vfl-kette-tol-weit* +;; in vf_linienzug.lsp benannt (Werte 2.0/100.0) - hier nur gespiegelt. +(if (null *vfk-kette-tol-eng*) (setq *vfk-kette-tol-eng* 2.0)) +(if (null *vfk-kette-tol-weit*) (setq *vfk-kette-tol-weit* 100.0)) + +;; Diagnose-Schwellwert (mm): ab wann ein Anschlussabstand beim +;; Ketten-Verfolgen als "spuerbar, aber noch sauber" gilt (vfl-kette- +;; verfolgen, vf_linienzug.lsp Zeile ~4617). Rohes 0.5-Literal. +(if (null *vfk-kette-anschluss-warnung*) (setq *vfk-kette-anschluss-warnung* 0.5)) + +;; Warnschwelle (Grad): Vario-Winkel oberhalb des Maximums der +;; Bogenwinkel-Tabelle (Modus 3, vf-linienzug-modus3 Zeile ~4018). Rohes +;; 51.0-Literal, dupliziert das Maximum von *vfk-bogen-winkel*. +(if (null *vfk-vario-winkel-max*) (setq *vfk-vario-winkel-max* 51.0)) + +;; Empirischer Korrekturfaktor (mm) fuer die Bruecken-Hoehenberechnung in +;; Modus 3 (vf-linienzug-modus3, "dH-adj", vf_linienzug.lsp Zeile ~4162). +;; UNKOMMENTIERTE Herleitung im Original - nur "Motor + auf_3/ab_3"-Notiz. +;; Bei Gelegenheit pruefen/nachvollziehen, ob sich der Wert geometrisch +;; herleiten laesst statt empirisch fixiert zu bleiben. +(if (null *vfk-bruecke-korrektur*) (setq *vfk-bruecke-korrektur* 10.48)) + +(setq *vfk-konstanten-geladen* t) +(princ "\nvf_konstanten geladen.") +(princ) diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index 227b76e..2454cff 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -536,15 +536,34 @@ ;; Zahl (Default = aktuelle Kettenhoehe, wie im Original-Prompt). Nutzt ;; bewusst den generischen Einzel-Dialog vflw_zahl (kein Punkt-Button, der ;; faelschlich eine hier moegliche Punktwahl suggerieren wuerde). -;; hoehe-default: aktuelle Kettenhoehe (Vorbelegung, wie im Original-Prompt). -(defun vflw-gruppe-ziel-hoehe-impl (hoehe-default / dat dcl-pfad ergebnis dlg-wert) +;; hoehe-default: entweder eine Zahl (aktuelle Kettenhoehe, alte Vorbelegung - +;; die bei direkter Uebernahme immer als deltaH=0 abgelehnt wird), ODER eine +;; Liste (hoehe-ab hoehe-auf) mit zwei baubaren Vorschlaegen (siehe +;; vfl-vf-hoehe-vorschlaege/vfl-segment-hoehe-vorschlaege) - dann zeigt der +;; Kopftext beide Richtungen, vorbelegt wird die Ab-Variante (haeufigerer +;; Fall, siehe vfl-segment-entscheidung). Ist hoehe-ab nil (kein baubarer +;; Wert in der sondierten Zone gefunden), faellt die Vorbelegung auf die +;; unveraenderte Kettenhoehe zurueck (altes Verhalten) plus Warnhinweis. +(defun vflw-gruppe-ziel-hoehe-impl (hoehe-default / dat dcl-pfad ergebnis dlg-wert + zwei-werte hoehe-ab hoehe-auf hoehe-kette vorbelegt) + (setq zwei-werte (listp hoehe-default)) + (if zwei-werte + (progn + (setq hoehe-ab (nth 0 hoehe-default) hoehe-auf (nth 1 hoehe-default)) + (setq hoehe-kette (nth 2 hoehe-default)) + (setq vorbelegt (if hoehe-ab hoehe-ab hoehe-kette))) + (setq vorbelegt hoehe-default)) (setq dat (load_dialog (vflw-dcl-pfad))) (if (not (new_dialog "vflw_zahl" dat)) (if (and dat (>= dat 0)) (unload_dialog dat)) (progn - (set_tile "kopf" (vflw-clean (ssg-textf "vfl-prompt-hoehe-endpunkt" - (list (rtos hoehe-default 2 1))))) - (set_tile "wert" (rtos hoehe-default 2 1)) + (set_tile "kopf" + (vflw-clean + (if (and zwei-werte hoehe-ab hoehe-auf) + (ssg-textf "vfl-prompt-hoehe-endpunkt-2" + (list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) + (ssg-textf "vfl-prompt-hoehe-endpunkt" (list (rtos vorbelegt 2 1)))))) + (set_tile "wert" (rtos vorbelegt 2 1)) (action_tile "accept" "(setq dlg-wert (get_tile \"wert\")) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq ergebnis (start_dialog)) @@ -1020,6 +1039,223 @@ ) ) +;; Stumme Variante von berechne-alle-winkel: NUR die Machbarkeits-Pruefung +;; (mind. ein Winkel mit L_GF>=0 und L_VF>=0), OHNE die Diagnosetabelle auf +;; die Kommandozeile zu schreiben. Rechenweg 1:1 aus berechne-alle-winkel +;; (vf_standard.lsp) uebernommen - bei Aenderungen dort auch hier nachziehen. +;; Gebraucht von vfl-vf-machbar-p fuer die Sondierung in vfl-vf-min-deltah, +;; die viele Testwerte durchprobiert (dort wuerde die Tabellenausgabe von +;; berechne-alle-winkel die Konsole zuspammen). +(defun vfl-winkel-machbar-p (deltaL deltaH richtung feste-hz / + winkel-list cos3 sin3 mass1 mass2 rad5 rad7 + bogen-x1 bogen-z1 bogen-x2 bogen-z2 cosa sina + A B winkel-eff cosEff sinEff L_GF L_VF + abs-dz-AUS abs-dz-EIN gefunden) + (if (null feste-hz) (setq feste-hz FESTE_HORIZONTAL)) + (setq abs-dz-AUS (abs aus-dz) abs-dz-EIN (abs ein-dz)) + (setq winkel-list (ssg-cfg-or "vario" "bogen_winkel" + '(3 6 9 12 15 18 21 27 33 39 45 51))) + (setq cos3 (cos (* (ssg-cfg-or "vario" "gefaelle_winkel" 3) (/ pi 180.0))) + sin3 (sin (* (ssg-cfg-or "vario" "gefaelle_winkel" 3) (/ pi 180.0)))) + (setq gefunden nil) + (foreach winkel winkel-list + (if (not gefunden) + (progn + (if (= richtung "Auf") + (setq mass1 (get-bogen-mass bogen-auf winkel) + mass2 (get-bogen-mass bogen-ab winkel)) + (setq mass1 (get-bogen-mass bogen-ab winkel) + mass2 (get-bogen-mass bogen-auf winkel))) + (if (and mass1 mass2) + (progn + (setq rad5 (* 3.0 (/ pi 180.0))) + (setq rad7 (* (float (if (= richtung "Auf") (- 3 winkel) (+ winkel 3))) + (/ pi 180.0))) + (setq bogen-x1 (+ (* (car mass1) (cos rad5)) (* (caddr mass1) (sin rad5)))) + (setq bogen-z1 (+ (* (- (car mass1)) (sin rad5)) (* (caddr mass1) (cos rad5)))) + (setq bogen-x2 (+ (* (car mass2) (cos rad7)) (* (caddr mass2) (sin rad7)))) + (setq bogen-z2 (+ (* (- (car mass2)) (sin rad7)) (* (caddr mass2) (cos rad7)))) + (setq cosa (cos (* winkel (/ pi 180.0))) + sina (sin (* winkel (/ pi 180.0)))) + (setq A (- deltaL aus-dx ein-dx bogen-x1 bogen-x2 (* feste-hz cos3))) + (setq winkel-eff (if (= richtung "Auf") (- winkel 3) (+ winkel 3))) + (setq cosEff (cos (* winkel-eff (/ pi 180.0))) + sinEff (sin (* winkel-eff (/ pi 180.0)))) + (if (= richtung "Auf") + (setq B (+ deltaH abs-dz-AUS abs-dz-EIN (- bogen-z1) (- bogen-z2) + (* feste-hz sin3))) + (setq B (+ (- deltaH abs-dz-AUS abs-dz-EIN (* feste-hz sin3)) + bogen-z1 bogen-z2))) + (if (> (abs sina) 0.0001) + (progn + (setq L_GF (/ (- (* A sinEff) (* B cosEff)) sina)) + (if (= richtung "Auf") + (setq L_VF (/ (+ (* A sin3) (* B cos3)) sina)) + (setq L_VF (/ (- (* B cos3) (* A sin3)) sina))) + (if (and (numberp L_GF) (numberp L_VF) (>= L_GF 0) (>= L_VF 0)) + (setq gefunden t)) + ) + ) + ) + ) + ) + ) + ) + gefunden +) + +;; Nur-Machbarkeits-Check (kein interaktives Waehlen wie vfl-waehle-winkel): +;; T, wenn fuer deltaL/deltaH/richtung MINDESTENS ein gueltiger Winkel bzw. +;; die horizontale Mitte existiert - sonst nil. Nutzt dieselbe Fallunter- +;; scheidung wie vfl-vf-entscheidung, aber ohne Nutzer-Interaktion (fuer die +;; Sondierung in vfl-vf-min-deltah). aus-dx/aus-dz werden wie in vfl-vf-winkel +;; temporaer genullt (AS-Footprint an dieser Stelle bereits verbraucht) - +;; sonst wuerde die Sondierung ein zu kleines Budget sehen und einen +;; eigentlich baubaren Wert faelschlich als "nicht baubar" verwerfen. +(defun vfl-vf-machbar-p (deltaL deltaH richtung / horizontal-info save-ausdx save-ausdz ergebnis) + (if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek)) + (cond + ((< deltaL 1000.0) nil) + ((< deltaH 1.0) nil) + ((= richtung "Auf") + (setq save-ausdx aus-dx save-ausdz aus-dz) + (setq aus-dx 0.0 aus-dz 0.0) + (setq ergebnis (vfl-winkel-machbar-p deltaL deltaH "Auf" *vfl-feste-horizontal*)) + (setq aus-dx save-ausdx aus-dz save-ausdz) + ergebnis) + (t + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (if (and horizontal-info (caddr horizontal-info)) + t + (progn + (setq save-ausdx aus-dx save-ausdz aus-dz) + (setq aus-dx 0.0 aus-dz 0.0) + (setq ergebnis (vfl-winkel-machbar-p deltaL deltaH "Ab" *vfl-feste-horizontal*)) + (setq aus-dx save-ausdx aus-dz save-ausdz) + ergebnis))) + ) +) + +;; Kleinste baubare Hoehendifferenz (mm, > 0) fuer deltaL/richtung sondieren - +;; linearer Anstieg in 10-mm-Schritten (grob genug fuer einen Vorschlagswert, +;; fein genug um keine schmale gueltige Zone zu ueberspringen) bis 1/3 von +;; deltaL (grosszuegige Obergrenze; steilere Faelle braucht kein Vorschlag). +;; Rueckgabe: deltaH (mm) oder nil, wenn in diesem Bereich nichts baubar ist. +(defun vfl-vf-min-deltah (deltaL richtung / schritt grenze h gefunden) + (setq schritt 10.0) + (setq grenze (/ deltaL 3.0)) + (setq h schritt gefunden nil) + (while (and (not gefunden) (<= h grenze)) + (if (vfl-vf-machbar-p deltaL h richtung) + (setq gefunden h) + (setq h (+ h schritt))) + ) + gefunden +) + +;; Liefert zwei baubare Ziel-Hoehen-Vorschlaege (Ab zuerst, Auf danach) fuer +;; die aktuelle Kettenhoehe p-aktuell-z bei gegebenem deltaL - Ersatz fuer den +;; blossen "unveraenderte Ist-Hoehe"-Default, der bei direkter Uebernahme +;; immer als deltaH=0 ("kein sinnvolles VF") abgelehnt wird (siehe +;; vfl-vf-entscheidung). NUR-VF-Variante: fuer den expliziten "Linie-VF"- +;; Menuepunkt, wo GF keine Option ist (der Nutzer hat VF bereits gewaehlt). +;; Rueckgabe: (hoehe-ab hoehe-auf) - je nil, wenn in der sondierten Zone kein +;; baubarer Wert existiert. +(defun vfl-vf-hoehe-vorschlaege (p-aktuell-z deltaL / min-ab min-auf) + (setq min-ab (vfl-vf-min-deltah deltaL "Ab")) + (setq min-auf (vfl-vf-min-deltah deltaL "Auf")) + (list + (if min-ab (- p-aktuell-z min-ab) nil) + (if min-auf (+ p-aktuell-z min-auf) nil)) +) + +;; Wie vfl-vf-hoehe-vorschlaege, aber fuer den automatischen "Linie"-Menue- +;; punkt (vfl-segment-entscheidung: GF ODER VF). Der Ab-Vorschlag nutzt dort +;; NICHT die VF-Sondierung, sondern direkt die feste 3-Grad-GF-Neigung +;; (deltaH = deltaL*tan(3 Grad), wie im bestehenden Kurzsegment-Zweig, +;; vfl-baue-mehrsegment-linie oben) - bei exakt 3 Grad natuerlichem Winkel +;; greift IMMER der GF-Zweig von vfl-segment-entscheidung (Toleranzband um +;; 3 Grad), eine reine Gefaellestrecke hat keine deltaL-Mindestlaenge und ist +;; damit garantiert baubar, ohne die (teurere) VF-Sondierung zu brauchen. Der +;; Auf-Vorschlag bleibt VF-only (GF kann nicht steigen). +(defun vfl-segment-hoehe-vorschlaege (p-aktuell-z deltaL / min-ab min-auf rad3) + (setq rad3 (* (float (ssg-cfg-or "vario" "gefaelle_winkel" 3)) (/ pi 180.0))) + (setq min-ab (* deltaL (/ (sin rad3) (cos rad3)))) + (setq min-auf (vfl-vf-min-deltah deltaL "Auf")) + (list + (- p-aktuell-z min-ab) + (if min-auf (+ p-aktuell-z min-auf) nil)) +) + +;; Hinweis auf die Konsole, wenn NUR EINE der beiden Richtungen einen +;; baubaren Vorschlag hat (die andere Richtung ist bei dieser Segmentlaenge +;; also aussichtslos) - macht sichtbar, warum der Dialog/Prompt dann nur +;; einen Wert zeigt, statt es wie einen Fehler wirken zu lassen. +(defun vfl-hoehe-hinweis-falls-noetig (hoehe-ab hoehe-auf) + (if (or (and hoehe-ab (not hoehe-auf)) (and hoehe-auf (not hoehe-ab))) + (princ (ssg-text "vfl-hinweis-hoehe-vorschlag-fehlt"))) + (princ) +) + +;; Wie vfl-vf-machbar-p, aber fuer das Budget von vfl-body-zerlegung +;; (Kettenende-Modus, "Ja - Motorstation setzen, Kettenende festlegen"): +;; feste-hz=800 (nur Motor+Separator, KEIN Umlenk-/AS-Anteil) statt +;; *vfl-feste-horizontal*, Mindestlaenge 800mm statt 1000mm, und bei +;; praktisch flachem Rest (deltaH<1) NUR die horizontale Mitte (kein +;; direkter GF-Fallback wie bei vfl-vf-machbar-p - vfl-body-zerlegung prueft +;; GF nur beim natuerlichen ~3-Grad-Fall weiter unten). aus-dx/aus-dz werden +;; wie im Original immer genullt (nicht nur bedingt wie bei vfl-vf-machbar-p), +;; da der Abschluss-Koerper nie einen AS-Fussabdruck traegt. +(defun vfl-body-machbar-p (deltaL deltaH richtung / horizontal-info save-ausdx save-ausdz ergebnis) + (if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek)) + (setq save-ausdx aus-dx save-ausdz aus-dz) + (setq aus-dx 0.0 aus-dz 0.0) + (setq ergebnis + (cond + ((< deltaL 800.0) nil) + ((< deltaH 1.0) + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (and horizontal-info (caddr horizontal-info) t)) + ((= richtung "Auf") + (vfl-winkel-machbar-p deltaL deltaH "Auf" 800.0)) + (t + (setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab")) + (if (and horizontal-info (caddr horizontal-info)) + t + (vfl-winkel-machbar-p deltaL deltaH "Ab" 800.0))) + ) + ) + (setq aus-dx save-ausdx aus-dz save-ausdz) + ergebnis +) + +;; Wie vfl-vf-min-deltah, aber mit vfl-body-machbar-p (Budget von +;; vfl-body-zerlegung statt vfl-vf-entscheidung). +(defun vfl-body-min-deltah (deltaL richtung / schritt grenze h gefunden) + (setq schritt 10.0) + (setq grenze (/ deltaL 3.0)) + (setq h schritt gefunden nil) + (while (and (not gefunden) (<= h grenze)) + (if (vfl-body-machbar-p deltaL h richtung) + (setq gefunden h) + (setq h (+ h schritt))) + ) + gefunden +) + +;; Wie vfl-vf-hoehe-vorschlaege, aber fuer vfl-body-abschluss (Kettenende- +;; Modus): nutzt vfl-body-min-deltah (800mm-Budget) statt vfl-vf-min-deltah +;; (1300mm-Budget) - sonst wuerde ein Vorschlag als baubar erscheinen, der es +;; am Kettenende (kleineres Budget: nur Motor+Separator, kein Umlenk-Anteil) +;; tatsaechlich nicht ist. +(defun vfl-body-hoehe-vorschlaege (p-aktuell-z deltaL / min-ab min-auf) + (setq min-ab (vfl-body-min-deltah deltaL "Ab")) + (setq min-auf (vfl-body-min-deltah deltaL "Auf")) + (list + (if min-ab (- p-aktuell-z min-ab) nil) + (if min-auf (+ p-aktuell-z min-auf) 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 @@ -1405,7 +1641,8 @@ ;; Rueckgabe: (frame anzahl-koerper letzt-hz gf2-laenge) oder nil. (defun vfl-body-abschluss (frame letzt-hz p-umlenk / linie-mess dL hzn hn dH richtn rad3 dec typ w lgf lvf - gf2 cnt p0 tx ty) + gf2 cnt p0 tx ty + hoehe-vorschlaege hoehe-ab hoehe-auf hoehe-fallback) ;; Der Abschluss-Koerper (vfs-vf-koerper) und der Motor gehen von 3-Grad-Basis ;; aus - eine gerade laufende flache Zone hier mit ab_3 abschliessen. (setq frame (vfl-nach-3grad frame)) @@ -1414,11 +1651,24 @@ (progn (princ (ssg-text "vfl-abgebrochen-kein-ziel")) nil) (progn (setq dL (car linie-mess) hzn (cadr linie-mess)) + ;; Baubare Vorschlaege (Ab/Auf) statt der unveraenderten Kettenhoehe als + ;; Default - sonst waere dH=0 ("Auf", da (>= 0.0 0.0)) und der Rest wird + ;; von vfl-body-zerlegung sofort als "nicht baubar" abgelehnt (kleineres + ;; Budget als vfl-vf-entscheidung: nur Motor+Separator, 800mm statt + ;; 1300mm) - siehe vfl-body-hoehe-vorschlaege/vfl-body-machbar-p. + (setq hoehe-vorschlaege (vfl-body-hoehe-vorschlaege (caddr (car frame)) dL)) + (setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege)) + (setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr (car frame)))) + (vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf) (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (list (caddr (car frame))))) - (setq hn (vfl-in-real (ssg-textf "vfl-prompt-hoehe-kettenende" - (list (rtos (caddr (car frame)) 2 1))))) - (if (null hn) (setq hn (caddr (car frame)))) + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl + (list (list hoehe-ab hoehe-auf (caddr (car frame)))))) + (setq hn (vfl-in-real + (if (and hoehe-ab hoehe-auf) + (ssg-textf "vfl-prompt-hoehe-kettenende-2" + (list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) + (ssg-textf "vfl-prompt-hoehe-kettenende" (list (rtos hoehe-fallback 2 1)))))) + (if (null hn) (setq hn hoehe-fallback)) (setq dH (- hn (caddr (car frame)))) (setq richtn (if (>= dH 0.0) "Auf" "Ab")) (setq dH (abs dH)) @@ -1430,8 +1680,15 @@ (if (null typ) (progn (princ (ssg-text "vfl-fehler-rest-nicht-baubar")) + (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Kettenende-Abschluss nicht baubar (dL=" + (rtos dL 2 0) " dH=" (rtos dH 2 0) " richtung=" richtn ")")) nil) (progn + (dbgmsg (strcat "GEOMETRIE: vfl-body-zerlegung ERFOLG (dL=" (rtos dL 2 0) + " dH=" (rtos dH 2 0) " richtung=" richtn + " typ=" typ " winkel=" (rtos (float w) 2 1) + " L_GF=" (if lgf (rtos lgf 2 0) "nil") + " L_VF=" (if lvf (rtos lvf 2 0) "nil") ")")) ;; Soll-ES-Punkt fuer den Ist-Ziel-Report merken (Startpunkt + ;; projizierter Laenge entlang der Fahrtrichtung). (setq p0 (car frame)) @@ -1460,6 +1717,8 @@ (princ (ssg-textf "vfl-hinweis-gf2-minimum" (list (rtos gf2 2 0) (rtos *vfl-gf-min-laenge* 2 0)))) (setq gf2 *vfl-gf-min-laenge*))) + (dbgmsg (strcat "GEOMETRIE ERFOLG: Kettenende-Abschluss gebaut (cnt=" (itoa cnt) + " gf2=" (rtos gf2 2 0) "), neue Position=" (dbg-tostring (car frame)))) (list frame cnt hzn gf2) ) ) @@ -1472,7 +1731,8 @@ p-umlenk vf-count antwort L_GF-eff L_GF1-bau L_GF2-bau linie-mess dL dH hn hzn richtn ent typ w lgf lvf letzt-hz fertig ziel-ende ziel-gf2 res3 gf2-eff entry-start - res-h vor-antwort es-gewuenscht es-antwort save-eindx save-eindz) + res-h vor-antwort es-gewuenscht es-antwort save-eindx save-eindz + hoehe-vorschlaege hoehe-ab hoehe-auf hoehe-fallback) ;; Vorbelegung: ES gewuenscht (Default) - nur bei "3 - Kettenende definieren" ;; wird explizit gefragt und ggf. auf nil gesetzt (siehe dort). (setq es-gewuenscht t) @@ -1620,11 +1880,25 @@ (setq dL (car linie-mess) hzn (cadr linie-mess)) (if (> dL 1.0) (progn + ;; NUR-VF-Vorschlaege (nicht vfl-segment-hoehe-vorschlaege): + ;; dieser Zweig setzt eine bestehende VF-Kette fort und lehnt + ;; ein hier zurueckkommendes typ="GF" explizit ab (siehe + ;; "vfl-segment-gf-nicht-erlaubt" unten) - der GF-Vorschlag + ;; (3-Grad-Formel) waere hier also gerade NICHT baubar. + (setq hoehe-vorschlaege (vfl-vf-hoehe-vorschlaege (caddr (car frame)) dL)) + (setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege)) + (setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr (car frame)))) + (vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf) (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (list (caddr (car frame))))) - (setq hn (vfl-in-real (ssg-textf "vfl-prompt-hoehe-endpunkt" - (list (rtos (caddr (car frame)) 2 1))))) - (if (null hn) (setq hn (caddr (car frame)))) + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl + (list (list hoehe-ab hoehe-auf (caddr (car frame)))))) + (setq hn (vfl-in-real + (if (and hoehe-ab hoehe-auf) + (ssg-textf "vfl-prompt-hoehe-endpunkt-2" + (list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) + (ssg-textf "vfl-prompt-hoehe-endpunkt" + (list (rtos hoehe-fallback 2 1)))))) + (if (null hn) (setq hn hoehe-fallback)) (setq dH (- hn (caddr (car frame)))) (setq richtn (if (>= dH 0.0) "Auf" "Ab")) (setq dH (abs dH)) @@ -1714,17 +1988,26 @@ (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))) + (dbgmsg (strcat "GEOMETRIE: vfl-insert-gf-bogen-block (block=" blockname + " bwinkel=" (itoa bwinkel) " bseite=" bseite ")")) ;; 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)))) (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)))) + (if (null neuer-frame) + (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Block " blockname " nicht eingefuegt")) + (progn + (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)))) + (dbgmsg (strcat "GEOMETRIE ERFOLG: GF-Bogen gebaut, neue Position=" + (dbg-tostring (car neuer-frame)))) + ) + ) neuer-frame ) @@ -2126,7 +2409,8 @@ frame letzter-typ fertig linie-ende-modus rad3 anzahl-gf anzahl-vf vfl-nummer lastEnt gf-max-winkel gf-ok kettenanfang pick-punkt - as-vorhanden erg old-error vfl-ins dbg-an) + as-vorhanden erg old-error vfl-ins dbg-an + hoehe-vorschlaege hoehe-ab hoehe-auf hoehe-fallback) (princ "\n\n=========================================") (princ (ssg-text "vfl-modus1-header")) (princ "\n=========================================") @@ -2327,10 +2611,17 @@ ) ) (if (< deltaL 1000.0) - (princ (ssg-text "vfl-fehler-horizontal-vf-kurz")) + (progn + (princ (ssg-text "vfl-fehler-horizontal-vf-kurz")) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Horizontal-VF zu kurz (deltaL=" + (rtos deltaL 2 0) ")")))) (progn ;; VF-Einheit mit horizontalem ersten Koerper (winkel=0, L_VF=deltaL, ;; L_GF = Mindestlaenge fuer den Einlauf-Anschluss). + (if dbg-an + (dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss horizontal (deltaL=" (rtos deltaL 2 0) + " L_GF=" (rtos *vfl-gf-min-laenge* 2 0) " L_VF=" (rtos deltaL 2 0) ")"))) (setq vf-einheit-res (vfl-vf-einheit-abschluss frame hz-neu "Ab" 0 *vfl-gf-min-laenge* deltaL nil)) (setq frame (nth 0 vf-einheit-res)) @@ -2339,6 +2630,9 @@ (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) (setq letzter-typ "VF") (setq p-aktuell (car frame)) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE ERFOLG: Horizontal-VF-Einheit gebaut, neue Position=" + (dbg-tostring p-aktuell)))) ) ) ) @@ -2371,89 +2665,119 @@ (setq frame (nth 0 erg) deltaL (nth 1 erg) p-aktuell (car frame)) ) ) - (setq gf-ok t) - (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-gefaelle-impl - (list (vfl-gf-hoehe-vorschlag (caddr p-aktuell))))) - (princ (ssg-text "vfl-gefaelle-festlegen-header")) - (princ (ssg-text "vfl-gefaelle-opt-hoehe")) - (princ (ssg-text "vfl-gefaelle-opt-winkel")) - (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") - (list (ssg-text "vfl-gefaelle-opt-hoehe") - (ssg-text "vfl-gefaelle-opt-winkel")) 1 - "vfl-gefaelle-festlegen-header")) - (if (= antwort "2") + ;; Nach dem AS-Einfuegen kann die reale Restlaenge (aus dem + ;; tatsaechlichen KS_AUS neu gemessen) kleiner als der urspruenglich + ;; gepickte Rohwert sein - bei einem knapp gepickten Punkt sogar + ;; NEGATIV (das AS-Element allein braucht bereits mehr Platz als bis + ;; zum Klickpunkt vorhanden war). Ohne diese zweite Pruefung wuerde + ;; vfl-insert-gf-segment mit negativem deltaL "erfolgreich" eine + ;; entartete/unsichtbare GF-Strecke bauen (leerer Sprung zwischen AS + ;; und dem naechsten Element) statt den Nutzer erneut picken zu + ;; lassen - siehe vfl-fehler-linie-zu-kurz oben (dieselbe Meldung). + ;; Sofortiger Abbruch DIESES Zweigs (kein Weiterfragen nach Winkel/ + ;; Hoehe fuer ein Segment, das ohnehin nicht gebaut werden kann) - + ;; gf-ok wird unten sonst mehrfach ueberschrieben. + (if (< deltaL 1.0) + (princ (ssg-text "vfl-fehler-linie-zu-kurz")) (progn - ;; Winkel direkt vorgeben - deltaH ergibt sich aus deltaL*tan(winkel). - (setq winkel - (vfl-in-real (ssg-textf "vfl-prompt-neigungswinkel" (list (rtos gf-max-winkel 2 1))))) - (if (null winkel) (setq winkel gf-max-winkel)) - (if (or (<= winkel 0.0) (> winkel gf-max-winkel)) + (setq gf-ok t) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-gefaelle-impl + (list (vfl-gf-hoehe-vorschlag (caddr p-aktuell))))) + (princ (ssg-text "vfl-gefaelle-festlegen-header")) + (princ (ssg-text "vfl-gefaelle-opt-hoehe")) + (princ (ssg-text "vfl-gefaelle-opt-winkel")) + (setq antwort (vfl-menu (ssg-text "prompt-wahl-1-2") + (list (ssg-text "vfl-gefaelle-opt-hoehe") + (ssg-text "vfl-gefaelle-opt-winkel")) 1 + "vfl-gefaelle-festlegen-header")) + (if (= antwort "2") (progn - (alert (ssg-textf "vfl-alert-winkel-ungueltig" - (list (rtos winkel 2 1) (rtos gf-max-winkel 2 1)))) - (setq gf-ok nil)) - (progn - (setq richtung "Ab") - (setq deltaH (* deltaL (/ (sin (* winkel (/ pi 180.0))) - (cos (* winkel (/ pi 180.0)))))) + ;; Winkel direkt vorgeben - deltaH ergibt sich aus deltaL*tan(winkel). + (setq winkel + (vfl-in-real (ssg-textf "vfl-prompt-neigungswinkel" (list (rtos gf-max-winkel 2 1))))) + (if (null winkel) (setq winkel gf-max-winkel)) + (if (or (<= winkel 0.0) (> winkel gf-max-winkel)) + (progn + (alert (ssg-textf "vfl-alert-winkel-ungueltig" + (list (rtos winkel 2 1) (rtos gf-max-winkel 2 1)))) + (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). Vorschlag/ - ;; Enter-Default = vfl-gf-hoehe-vorschlag (siehe dort), NICHT - ;; die unveraenderte Ist-Hoehe - sonst waere deltaH=0 und die - ;; GF-Pruefung wiese den Wert als "kann nicht steigen" ab. - (setq hoehe-neu - (vfl-in-real (ssg-textf "vfl-prompt-hoehe-linienendpunkt" - (list (rtos (vfl-gf-hoehe-vorschlag (caddr p-aktuell)) 2 1))))) - (if (null hoehe-neu) (setq hoehe-neu (vfl-gf-hoehe-vorschlag (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 (ssg-text "vfl-alert-gf-kann-nicht-steigen")) - (setq gf-ok nil)) - (t - (setq winkel (* (atan (/ deltaH deltaL)) (/ 180.0 pi))) - (if (> winkel gf-max-winkel) - (progn - (alert (ssg-textf "vfl-alert-gefaelle-zu-steil" - (list (rtos winkel 2 1) (rtos gf-max-winkel 2 1)))) + (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). Vorschlag/ + ;; Enter-Default = vfl-gf-hoehe-vorschlag (siehe dort), NICHT + ;; die unveraenderte Ist-Hoehe - sonst waere deltaH=0 und die + ;; GF-Pruefung wiese den Wert als "kann nicht steigen" ab. + (setq hoehe-neu + (vfl-in-real (ssg-textf "vfl-prompt-hoehe-linienendpunkt" + (list (rtos (vfl-gf-hoehe-vorschlag (caddr p-aktuell)) 2 1))))) + (if (null hoehe-neu) (setq hoehe-neu (vfl-gf-hoehe-vorschlag (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 (ssg-text "vfl-alert-gf-kann-nicht-steigen")) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Linie-GF kann nicht steigen" + " (deltaL=" (rtos deltaL 2 0) " deltaH=" (rtos deltaH 2 0) ")"))) (setq gf-ok nil)) - ) + (t + (setq winkel (* (atan (/ deltaH deltaL)) (/ 180.0 pi))) + (if (> winkel gf-max-winkel) + (progn + (alert (ssg-textf "vfl-alert-gefaelle-zu-steil" + (list (rtos winkel 2 1) (rtos gf-max-winkel 2 1)))) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Linie-GF zu steil (deltaL=" + (rtos deltaL 2 0) " deltaH=" (rtos deltaH 2 0) + " winkel=" (rtos winkel 2 1) " max=" (rtos gf-max-winkel 2 1) ")"))) + (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 (ssg-text "vfl-ist-kettenende-header")) - (princ (ssg-text "vfl-kettenende-opt-ja-es")) - (princ (ssg-text "vfl-kettenende-opt-ja-ohne-es")) - (princ (ssg-text "vfl-kettenende-opt-nein")) - (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") - (list (ssg-text "vfl-kettenende-opt-ja-es") - (ssg-text "vfl-kettenende-opt-ja-ohne-es") - (ssg-text "vfl-kettenende-opt-nein")) 3 - "vfl-ist-kettenende-header")) - (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)) + (if gf-ok + (progn + (if dbg-an + (dbgmsg (strcat "GEOMETRIE: vfl-insert-gf-segment (deltaL=" (rtos deltaL 2 0) + " hz=" (rtos hz-neu 2 1) " winkel=" (rtos winkel 2 1) ")"))) + (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)) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE ERFOLG: GF-Segment gebaut, neue Position=" + (dbg-tostring p-aktuell)))) + (princ (ssg-text "vfl-ist-kettenende-header")) + (princ (ssg-text "vfl-kettenende-opt-ja-es")) + (princ (ssg-text "vfl-kettenende-opt-ja-ohne-es")) + (princ (ssg-text "vfl-kettenende-opt-nein")) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") + (list (ssg-text "vfl-kettenende-opt-ja-es") + (ssg-text "vfl-kettenende-opt-ja-ohne-es") + (ssg-text "vfl-kettenende-opt-nein")) 3 + "vfl-ist-kettenende-header")) + (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)) + ) + ) ) ) ) @@ -2480,11 +2804,20 @@ (if (< deltaL 1000.0) (princ (ssg-text "vfl-fehler-vf-kurz")) (progn + (setq hoehe-vorschlaege (vfl-vf-hoehe-vorschlaege (caddr p-aktuell) deltaL)) + (setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege)) + (setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr p-aktuell))) + (vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf) (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (list (caddr p-aktuell)))) + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl + (list (list hoehe-ab hoehe-auf (caddr p-aktuell))))) (setq hoehe-neu - (vfl-in-real (ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos (caddr p-aktuell) 2 1))))) - (if (null hoehe-neu) (setq hoehe-neu (caddr p-aktuell))) + (vfl-in-real + (if (and hoehe-ab hoehe-auf) + (ssg-textf "vfl-prompt-hoehe-linienendpunkt-2" + (list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) + (ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos hoehe-fallback 2 1)))))) + (if (null hoehe-neu) (setq hoehe-neu hoehe-fallback)) (setq deltaH (- hoehe-neu (caddr p-aktuell))) (setq richtung (if (>= deltaH 0.0) "Auf" "Ab")) (setq deltaH (abs deltaH)) @@ -2492,9 +2825,19 @@ (setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung) L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung)) (if (null typ) - (alert (ssg-textf "vfl-alert-vf-nicht-baubar" - (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung))) (progn + (alert (ssg-textf "vfl-alert-vf-nicht-baubar" + (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung))) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Linie-VF nicht baubar (deltaL=" + (rtos deltaL 2 0) " deltaH=" (rtos deltaH 2 0) + " richtung=" richtung ")")))) + (progn + (if dbg-an + (dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss (deltaL=" (rtos deltaL 2 0) + " deltaH=" (rtos deltaH 2 0) " richtung=" richtung + " winkel=" (rtos (float winkel) 2 1) + " L_GF=" (rtos L_GF 2 0) " L_VF=" (rtos L_VF 2 0) ")"))) (setq vf-einheit-res (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF nil)) (setq frame (nth 0 vf-einheit-res)) @@ -2503,6 +2846,9 @@ (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) (setq letzter-typ "VF") (setq p-aktuell (car frame)) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE ERFOLG: VF-Einheit gebaut, neue Position=" + (dbg-tostring p-aktuell)))) ) ) ) @@ -2531,105 +2877,147 @@ (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), - ;; und eine GF ist mindestens 3 Grad geneigt. Die Endhoehe ergibt - ;; sich damit fest aus deltaH = deltaL*tan(3 Grad). - ;; Im Kettenende-Modus (Option 4) wird IMMER nach der Zielhoehe - ;; gefragt (Kurzsegment-Automatik hier ueberspringen). - (if (and (< deltaL 1000.0) (not linie-ende-modus)) + ;; Nach dem AS-Einfuegen kann die reale Restlaenge (aus dem + ;; tatsaechlichen KS_AUS neu gemessen) kleiner als der urspruenglich + ;; gepickte Rohwert sein - bei einem knapp gepickten Punkt sogar + ;; NEGATIV. Ohne diese zweite Pruefung wuerde die Kurzsegment- + ;; Automatik unten (< 1000mm) mit negativem deltaL trotzdem ein + ;; "erfolgreiches" GF-Segment bauen (entartete/unsichtbare Strecke, + ;; das naechste Element - z.B. ein GF-Bogen - erscheint dann direkt + ;; am AS-Element, obwohl der Nutzer davor noch eine Linie wollte). + (if (< deltaL 1.0) + (princ (ssg-text "vfl-fehler-linie-zu-kurz")) (progn - (setq typ "GF" winkel 3.0 richtung "Ab" L_GF nil L_VF nil) - (setq deltaH (* deltaL (/ (sin (* 3.0 (/ pi 180.0))) - (cos (* 3.0 (/ pi 180.0)))))) - (setq hoehe-neu (- (caddr p-aktuell) deltaH)) - (princ (ssg-textf "vfl-info-kurzes-segment" - (list (rtos deltaL 2 0) (rtos deltaH 2 1)))) - ) - (progn - (if (vfl-wizard-aktiv) - (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl (list (caddr p-aktuell)))) - (setq hoehe-neu - (vfl-in-real (ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos (caddr p-aktuell) 2 1))))) - (if (null hoehe-neu) (setq hoehe-neu (caddr p-aktuell))) - (setq deltaH (- hoehe-neu (caddr p-aktuell))) - (setq richtung (if (>= deltaH 0.0) "Auf" "Ab")) - (setq deltaH (abs deltaH)) - ;; Kettenende-Modus (Option 4): Der abgefragte Endpunkt (XY+Z) - ;; ist das exakte Ende der Kette NACH Separator + ES-Element. - ;; Deren Footprint (Separator 300 mm bei ~3 Grad + ES-Element - ;; ein-dx/ein-dz) muss vom baubaren GF/VF-Segment reserviert - ;; (abgezogen) werden, damit das ES-Element genau am Zielpunkt - ;; endet. Naeherung: Separator-Neigung = 3 Grad (Auslauf). - (if linie-ende-modus + ;; 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), + ;; und eine GF ist mindestens 3 Grad geneigt. Die Endhoehe ergibt + ;; sich damit fest aus deltaH = deltaL*tan(3 Grad). + ;; Im Kettenende-Modus (Option 4) wird IMMER nach der Zielhoehe + ;; gefragt (Kurzsegment-Automatik hier ueberspringen). + (if (and (< deltaL 1000.0) (not linie-ende-modus)) (progn - (setq rad3 (* (float (ssg-cfg-or "vario" "gefaelle_winkel" 3)) - (/ pi 180.0))) - (setq deltaL (max 1.0 (- deltaL (* 300.0 (cos rad3)) - (abs (if ein-dx ein-dx 0.0))))) - (setq deltaH (max 0.0 (- deltaH (* 300.0 (sin rad3)) - (abs (if ein-dz ein-dz 0.0))))) - (princ (ssg-textf "vfl-info-kettenende-footprint" - (list (rtos deltaL 2 0) (rtos deltaH 2 0)))) + (setq typ "GF" winkel 3.0 richtung "Ab" L_GF nil L_VF nil) + (setq deltaH (* deltaL (/ (sin (* 3.0 (/ pi 180.0))) + (cos (* 3.0 (/ pi 180.0)))))) + (setq hoehe-neu (- (caddr p-aktuell) deltaH)) + (princ (ssg-textf "vfl-info-kurzes-segment" + (list (rtos deltaL 2 0) (rtos deltaH 2 1)))) ) - ) - (setq entscheidung (vfl-segment-entscheidung deltaL deltaH richtung)) - (setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung) - L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung)) - ) - ) - - (if (null typ) - (alert (ssg-textf "vfl-alert-segment-nicht-baubar" - (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung))) - (progn - (if (= typ "GF") (progn - ;; --- reine Gefaellestrecke --- - (setq frame (vfl-insert-gf-segment (car frame) hz-neu deltaL winkel)) - (setq anzahl-gf (1+ anzahl-gf)) - ;; GF-Segment erfassen (Schraeglaenge = deltaL/cos(winkel)) - (vfl-acc-gf-seg (/ deltaL (cos (* (float winkel) (/ pi 180.0)))) winkel) - (setq letzter-typ "GF") - (setq p-aktuell (car frame)) - ;; Kettenende-Modus (Option 4): ohne Frage direkt ES setzen. - ;; Sonst nachfragen, ob die Kette hier endet. + (setq hoehe-vorschlaege (vfl-segment-hoehe-vorschlaege (caddr p-aktuell) deltaL)) + (setq hoehe-ab (nth 0 hoehe-vorschlaege) hoehe-auf (nth 1 hoehe-vorschlaege)) + (setq hoehe-fallback (if hoehe-ab hoehe-ab (caddr p-aktuell))) + (vfl-hoehe-hinweis-falls-noetig hoehe-ab hoehe-auf) + (if (vfl-wizard-aktiv) + (vl-catch-all-apply 'vflw-gruppe-ziel-hoehe-impl + (list (list hoehe-ab hoehe-auf (caddr p-aktuell))))) + (setq hoehe-neu + (vfl-in-real + (if (and hoehe-ab hoehe-auf) + (ssg-textf "vfl-prompt-hoehe-linienendpunkt-2" + (list (rtos hoehe-ab 2 1) (rtos hoehe-auf 2 1))) + (ssg-textf "vfl-prompt-hoehe-linienendpunkt" (list (rtos hoehe-fallback 2 1)))))) + (if (null hoehe-neu) (setq hoehe-neu hoehe-fallback)) + (setq deltaH (- hoehe-neu (caddr p-aktuell))) + (setq richtung (if (>= deltaH 0.0) "Auf" "Ab")) + (setq deltaH (abs deltaH)) + ;; Kettenende-Modus (Option 4): Der abgefragte Endpunkt (XY+Z) + ;; ist das exakte Ende der Kette NACH Separator + ES-Element. + ;; Deren Footprint (Separator 300 mm bei ~3 Grad + ES-Element + ;; ein-dx/ein-dz) muss vom baubaren GF/VF-Segment reserviert + ;; (abgezogen) werden, damit das ES-Element genau am Zielpunkt + ;; endet. Naeherung: Separator-Neigung = 3 Grad (Auslauf). (if linie-ende-modus - (setq antwort "1") (progn - (princ (ssg-text "vfl-ist-kettenende-header")) - (princ (ssg-text "vfl-kettenende-opt-ja-es")) - (princ (ssg-text "vfl-kettenende-opt-ja-ohne-es")) - (princ (ssg-text "vfl-kettenende-opt-nein")) - (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") - (list (ssg-text "vfl-kettenende-opt-ja-es") - (ssg-text "vfl-kettenende-opt-ja-ohne-es") - (ssg-text "vfl-kettenende-opt-nein")) 3 - "vfl-ist-kettenende-header")) + (setq rad3 (* (float (ssg-cfg-or "vario" "gefaelle_winkel" 3)) + (/ pi 180.0))) + (setq deltaL (max 1.0 (- deltaL (* 300.0 (cos rad3)) + (abs (if ein-dx ein-dx 0.0))))) + (setq deltaH (max 0.0 (- deltaH (* 300.0 (sin rad3)) + (abs (if ein-dz ein-dz 0.0))))) + (princ (ssg-textf "vfl-info-kettenende-footprint" + (list (rtos deltaL 2 0) (rtos deltaH 2 0)))) ) ) - (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)) - ) + (setq entscheidung (vfl-segment-entscheidung deltaL deltaH richtung)) + (setq typ (nth 0 entscheidung) winkel (nth 1 entscheidung) + L_GF (nth 2 entscheidung) L_VF (nth 3 entscheidung)) ) + ) + + (if (null typ) (progn - ;; --- VarioFoerderer-Einheit (Umlenk..Motor, mehrsegmentig) --- - ;; linie-ende-modus=T -> direkt Kettenende (Separator + ES). - (setq vf-einheit-res - (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF - linie-ende-modus)) - (setq frame (nth 0 vf-einheit-res)) - (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) - (if (nth 2 vf-einheit-res) (setq fertig t)) - (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) - (setq letzter-typ "VF") - (setq p-aktuell (car frame)) + (alert (ssg-textf "vfl-alert-segment-nicht-baubar" + (list (rtos deltaL 2 0) (rtos deltaH 2 0) richtung))) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE FEHLGESCHLAGEN: Linie (automatisch) nicht baubar" + " (deltaL=" (rtos deltaL 2 0) " deltaH=" (rtos deltaH 2 0) + " richtung=" richtung ")")))) + (progn + (if (= typ "GF") + (progn + ;; --- reine Gefaellestrecke --- + (if dbg-an + (dbgmsg (strcat "GEOMETRIE: vfl-insert-gf-segment (deltaL=" (rtos deltaL 2 0) + " hz=" (rtos hz-neu 2 1) " winkel=" (rtos (float winkel) 2 1) ")"))) + (setq frame (vfl-insert-gf-segment (car frame) hz-neu deltaL winkel)) + (setq anzahl-gf (1+ anzahl-gf)) + ;; GF-Segment erfassen (Schraeglaenge = deltaL/cos(winkel)) + (vfl-acc-gf-seg (/ deltaL (cos (* (float winkel) (/ pi 180.0)))) winkel) + (setq letzter-typ "GF") + (setq p-aktuell (car frame)) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE ERFOLG: GF-Segment gebaut, neue Position=" + (dbg-tostring p-aktuell)))) + ;; Kettenende-Modus (Option 4): ohne Frage direkt ES setzen. + ;; Sonst nachfragen, ob die Kette hier endet. + (if linie-ende-modus + (setq antwort "1") + (progn + (princ (ssg-text "vfl-ist-kettenende-header")) + (princ (ssg-text "vfl-kettenende-opt-ja-es")) + (princ (ssg-text "vfl-kettenende-opt-ja-ohne-es")) + (princ (ssg-text "vfl-kettenende-opt-nein")) + (setq antwort (vfl-menu (ssg-text "vfl-prompt-wahl-1-3-def3") + (list (ssg-text "vfl-kettenende-opt-ja-es") + (ssg-text "vfl-kettenende-opt-ja-ohne-es") + (ssg-text "vfl-kettenende-opt-nein")) 3 + "vfl-ist-kettenende-header")) + ) + ) + (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 + ;; --- VarioFoerderer-Einheit (Umlenk..Motor, mehrsegmentig) --- + ;; linie-ende-modus=T -> direkt Kettenende (Separator + ES). + (if dbg-an + (dbgmsg (strcat "GEOMETRIE: vfl-vf-einheit-abschluss (deltaL=" (rtos deltaL 2 0) + " deltaH=" (rtos deltaH 2 0) " richtung=" richtung + " winkel=" (rtos (float winkel) 2 1) + " L_GF=" (rtos L_GF 2 0) " L_VF=" (rtos L_VF 2 0) + " linie-ende-modus=" (if linie-ende-modus "T" "nil") ")"))) + (setq vf-einheit-res + (vfl-vf-einheit-abschluss frame hz-neu richtung winkel L_GF L_VF + linie-ende-modus)) + (setq frame (nth 0 vf-einheit-res)) + (setq anzahl-vf (+ anzahl-vf (nth 1 vf-einheit-res))) + (if (nth 2 vf-einheit-res) (setq fertig t)) + (if (nth 3 vf-einheit-res) (setq es-seite (nth 3 vf-einheit-res))) + (setq letzter-typ "VF") + (setq p-aktuell (car frame)) + (if dbg-an + (dbgmsg (strcat "GEOMETRIE ERFOLG: VF-Einheit gebaut, neue Position=" + (dbg-tostring p-aktuell)))) + ) + ) ) ) ) diff --git a/lang/de_DE.json b/lang/de_DE.json index 3a2d5ec..d78eb66 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -28,6 +28,8 @@ "vfl-prompt-neigungswinkel": "\nNeigungswinkel (Grad, 0 < Winkel <= %1) [%1]: ", "vfl-alert-winkel-ungueltig": "Neigungswinkel ungueltig: %1 Grad. Erlaubt: 0 < Winkel <= %2 Grad.", "vfl-prompt-hoehe-linienendpunkt": "\nHoehe (Z) des Linienendpunkts [%1]: ", + "vfl-prompt-hoehe-linienendpunkt-2": "\nHoehe (Z) des Linienendpunkts (Ab: %1 | Auf: %2) [%1]: ", + "vfl-hinweis-hoehe-vorschlag-fehlt": "\n(Hinweis: In diese Richtung ist bei dieser Segmentlaenge kein baubarer Vorschlag gefunden - bitte Wert manuell pruefen.)", "vfl-alert-gf-kann-nicht-steigen": "Gefaellestrecke (GF) kann nicht steigen - bitte tiefere Zielhoehe waehlen oder Ab/Auf VF benutzen.", "vfl-alert-gefaelle-zu-steil": "Gefaelle zu steil fuer GF: %1 Grad (erlaubt max %2 Grad).\nBitte kleinere Hoehendifferenz waehlen oder Ab/Auf VF benutzen.", "vfl-ist-kettenende-header": "\nIst das das Kettenende?", @@ -284,7 +286,9 @@ "vfl-horizontale-zwischenstrecke": "\n\nHorizontale Zwischenstrecke (0 Grad, L=%1 mm)", "vfl-kettenende-modus-ziel": "\n>>> Kettenende-Modus: Ziel dL=%1 mm, dH=%2 mm (%3). GF2 variiert mit dem Winkel.", "vfl-prompt-hoehe-endpunkt": "\nHoehe (Z) des Endpunkts [%1]: ", + "vfl-prompt-hoehe-endpunkt-2": "\nHoehe (Z) des Endpunkts (Ab: %1 | Auf: %2) [%1]: ", "vfl-prompt-hoehe-kettenende": "\nHoehe (Z) des Kettenendes (ES-Element) [%1]: ", + "vfl-prompt-hoehe-kettenende-2": "\nHoehe (Z) des Kettenendes (ES-Element) (Ab: %1 | Auf: %2) [%1]: ", "vfl-prompt-wahl-bis-n": "\nIhre Wahl (1-%1) [1]: ", "vfl-segment-gf-nicht-erlaubt": "\n Segment waere GF (zu steil) oder nicht baubar - innerhalb einer VF-Einheit nicht erlaubt.\n Bitte flacher/steigend zeichnen oder Foerderer beenden.", "vfl-winkel-option": "\n %1 - %2 Grad (L_GF=%3 mm L_VF=%4 mm)", diff --git a/lang/en_GB.json b/lang/en_GB.json index f9dd505..261b96f 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -28,6 +28,8 @@ "vfl-prompt-neigungswinkel": "\nIncline angle (degrees, 0 < angle <= %1) [%1]: ", "vfl-alert-winkel-ungueltig": "Incline angle invalid: %1 degrees. Allowed: 0 < angle <= %2 degrees.", "vfl-prompt-hoehe-linienendpunkt": "\nHeight (Z) of the line end point [%1]: ", + "vfl-prompt-hoehe-linienendpunkt-2": "\nHeight (Z) of the line end point (down: %1 | up: %2) [%1]: ", + "vfl-hinweis-hoehe-vorschlag-fehlt": "\n(Note: no buildable suggestion found for that direction at this segment length - please check the value manually.)", "vfl-alert-gf-kann-nicht-steigen": "Gravity section (GF) cannot rise - please pick a lower target height or use down/up VF.", "vfl-alert-gefaelle-zu-steil": "Slope too steep for GF: %1 degrees (max allowed %2 degrees).\nPlease pick a smaller height difference or use down/up VF.", "vfl-ist-kettenende-header": "\nIs this the chain end?", @@ -284,7 +286,9 @@ "vfl-horizontale-zwischenstrecke": "\n\nHorizontal intermediate section (0 deg, L=%1 mm)", "vfl-kettenende-modus-ziel": "\n>>> Chain-end mode: target dL=%1 mm, dH=%2 mm (%3). GF2 varies with the angle.", "vfl-prompt-hoehe-endpunkt": "\nHeight (Z) of the end point [%1]: ", + "vfl-prompt-hoehe-endpunkt-2": "\nHeight (Z) of the end point (down: %1 | up: %2) [%1]: ", "vfl-prompt-hoehe-kettenende": "\nHeight (Z) of the chain end (ES element) [%1]: ", + "vfl-prompt-hoehe-kettenende-2": "\nHeight (Z) of the chain end (ES element) (down: %1 | up: %2) [%1]: ", "vfl-prompt-wahl-bis-n": "\nYour choice (1-%1) [1]: ", "vfl-segment-gf-nicht-erlaubt": "\n Segment would be GF (too steep) or not buildable - not allowed within a VF unit.\n Please draw flatter/rising or end the conveyor.", "vfl-winkel-option": "\n %1 - %2 deg (L_GF=%3 mm L_VF=%4 mm)",