[MERGE] Lager branch in main
This commit is contained in:
commit
5821619e12
96 files changed
+9707
-727
No files matched your search
@@ -73,9 +73,11 @@ Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD.
|
||||
|---|---|---|
|
||||
| Kreisel-Module | `KreiselInsert` | KreiselInsert, KreiselConnect, KreiselEdit, ILS_Eckrad, EckradEdit, KREISEL_WEICHEN |
|
||||
| TRO | `Tro_Edit` | TRO_INSERT, TRO_EDIT |
|
||||
| Zusatzmodul/Foerderer/Kurven | `SSG_LIB_Commands` | ILS_BTMT_*, ILS_ETF_*, ILS_GK*_* |
|
||||
| Zusatzmodul | `SSG_LIB_Commands` | ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_SCANNER_INSERT, ILS_SEPARATOR_INSERT (die frueheren Dummy-Befehle ILS_ETF_*/ILS-Kurven sind entfernt) |
|
||||
| SPS: Staubereiche | `Jam_Edit` | JAM_EDIT (nur per Doppelklick auf `JAM_AREA` bzw. Kommandozeile, kein Menueeintrag) |
|
||||
| VarioFoerderer | `VarioFoerderer` | FOERDERANLAGE, VARIOFOERDERER_EDIT, Vario_Kette_Merge |
|
||||
| Gefaellestrecke | `Gefaellestrecke` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT |
|
||||
| Kettenfoerderer | `KettenFoerderer` | KETTENFOERDERER (Menue: Omniflo -> KettenFoerderer), KF_EDIT (Doppelklick auf KF_n). KF_KS_PRUEFEN ist ein reiner Diagnosebefehl und bewusst NICHT im Menue |
|
||||
| Omniflo (komplett) | `OmniModulInsert` + `GeruestInsert` | OMNI_APB_*, OMNI_W*_*, OMNI_AP*, OMNI_TEF_*, OMNI_TV_*, OMNI_LADESCHLEIFE_*, OMNI_EDIT; OMNI_FAHRSTRECKE / OMNI_FAHRSTRECKE_BESCHRIFTEN (GeruestInsert, Linien-Logik wie GERUEST_TRAEGER) |
|
||||
| Geruest | `GeruestInsert` | GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG (je eigener Dialog aus der Vorlage geruest.dcl, keine Umschaltung), GERUEST_TRAEGER (eigener Dialog), GERUEST_TRAEGER_BESCHRIFTEN (Untermenue Geruest -> Funktionen -> Traeger beschriften; alle Traeger der Zeichnung neu beschriften); Gattertraeger noch Platzhalter auf GERUEST (zeigt nur einen Hinweis) |
|
||||
| Connections | `Connection_Edit` + `SSG_LIB_Commands` | CONNECTION_INSERT, CONNECTION_EDIT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT |
|
||||
@@ -83,7 +85,7 @@ Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD.
|
||||
| Export | `export` | EXPORTSIVAS, EXPORTCSV, CALLPYTHON |
|
||||
| Werkzeuge | `ssg_blocktools`, `ssg_texttools`, `ssg_stueckliste`, `DinFormate` | SSG_BLOCK_COUNT, SSG_BLOCK_DELETE, SSG_ATTR_ERSETZEN, SSG_TEXT_ERSETZEN, SSG_TEXT_PARALLEL, SSG_TEXT_HOEHE, SSG_TEXT_STIL, SSG_FAEHNCHEN_STUECKLISTE, DIN_FORMATE |
|
||||
| Konfiguration | `SSG_LIB_Commands` + `DrawPlanquadrate` | SSG_DIM_SWITCH, SSG_SPRACHE, PLANQUADRATE_TOGGLE (DRAW_PLANQUADRATE/DELETE_PLANQUADRATE) |
|
||||
| Doppelklick/Kontextmenue | `SSG_LIB_Commands` | SSG_BLOCKEDIT (dispatcht Kreisel->KreiselEdit, Eckrad->EckradEdit, Omniflo->OMNI_EDIT, GF_*->GEFAELLESTRECKE_EDIT, VF_*->VARIOFOERDERER_EDIT, LG_*->lg-edit-ent) |
|
||||
| Doppelklick/Kontextmenue | `SSG_LIB_Commands` | SSG_BLOCKEDIT (dispatcht Kreisel->KreiselEdit, Eckrad->EckradEdit, Omniflo->OMNI_EDIT, GF_*->GEFAELLESTRECKE_EDIT, VF_*->VARIOFOERDERER_EDIT, KF_*->KF_EDIT, CONNECTION_*->CONNECTION_EDIT, JAM_*->JAM_EDIT, TRO_*->TRO_EDIT, GR_*->EATTEDIT, LG_*->lg-edit-ent) |
|
||||
|
||||
### Entfernte Legacy-Dateien
|
||||
|
||||
@@ -98,7 +100,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
|
||||
| Datei | Befehle | Beschreibung |
|
||||
|---|---|---|
|
||||
| `ssg_core.lsp` | - | Kernel: ssg-start/ssg-end, ssg-cfg-or, ssg-attrib-read/write, Layer/Block-Ops. Zentrale Helfer: `ssg-lisp-verzeichnis`/`ssg-lisp-datei-pfad` (Lisp-Pfad-Ermittlung), `ssg-rot-matrix-zy` (4x4 Rz(hz)*Ry(vert)-Rotationsmatrix, clusteruebergreifend), GUI-Aus-Schalter `*ssg-gui-aus*` + `ssg-gui-aus`/`ssg-gui-an`/`ssg-gui-p` (fuer automatische Tests: schaltet DCL-/Wizard-Dialoge ab, Module fallen auf Konsolen-/getXXX-Pfad zurueck; der Linienzug hat zusaetzlich `*vfl-headless*`, das die Konsolen-Rueckfrage selbst verbietet - siehe VarioFoerderer-Zeile). **Layer-Zuordnung**: `ssg-layer-cfg-load`/`-reset` (liest `cfg/layer.cfg` lazy), `ssg-layer-cfg-eintrag` (reine Aufloesung "Layername, Farbe" -> `(layer . farbe)`, in `tests/test_unit.lsp` getestet), `ssg-layer-eintrag` (Suchreihenfolge `[ils_<dim>]` -> `[allgemein]`), `ssg-layer-anlegen` (Layer mit cfg-Farbe anlegen, optional aktivieren) und `ssg-layer-setzen` (Blockreferenz auf den Baugruppen-Layer legen) - fuer ZUSAMMENGEBAUTE Baugruppen; `ssg-block-layer-vorgabe` (LAYER-Attribut -> `ssg-ils-block-ebene`) fuer nur EINGEFUEGTE Bloecke. Alle liefern nil, wenn nichts konfiguriert ist, und lassen den Layer dann unangetastet. **JSON**: drei Parser nebeneinander, bewusst nicht zusammengelegt - `ssg-load-json`/`ssg-parse-json-array` (flaches Array von Objekten) und `ssg-cfg-parse-nested` (genau 1 Ebene) sind ZEILENbasiert und koennen weder echte Verschachtelung noch mehrzeilige Arrays, maskierte Anfuehrungszeichen (`\"`) oder Kommas in Strings lesen; ihre Konsumenten (Konfiguration, Sprache, VF-Spec) sind auf dieses Verhalten eingestellt und bleiben unangetastet. Fuer alles andere `ssg-json-laden`/`ssg-json-parse`/`ssg-json-get` (rekursiver Descent-Parser ueber einen Positionszeiger): Objekt -> Alist, Array -> Liste, true -> T, false/null -> nil (beide nil, "Feld fehlt" ist also nicht von "Feld ist false" unterscheidbar), `\uXXXX` nur fuer ASCII. In `tests/test_unit.lsp` (`tu-tests-json`) gegen die echte Geruest-Datendatei getestet. Dazu `ssg-join` (Liste + Trennzeichen -> String). **Polygon-Helfer** (2D, rein, `tu-tests-poly`): `ssg-poly-flaeche`/`-umfang`/`-kanten`/`-bbox`/`-drehen`, `ssg-punkt-in-poly-p`, `ssg-punkt-drehen`, `ssg-poly-schnitt-y` (innere Abschnitte einer Waagrechten, halboffene Kantenregel), `ssg-poly-flaeche-signiert` (Umlaufsinn), `ssg-poly-clip-y`/`ssg-poly-band-x` (x-Ausdehnung im Band, Kantenberuehrung zaehlt nicht), `ssg-intervalle-schnitt`/`-minus`; dazu `ssg-lwpoly-punkte` (WCS, Erhebung) und `ssg-lwpoly-boegen-p`. **DCL-Vorlagen**: `ssg-dcl-vorlage-fuellen` (Vorlage lesen, Markerzeilen `//@NAME@` durch erzeugte Zeilen ersetzen - reiner Kern `ssg-dcl-zeilen-ersetzen`, getestet - und per `ssg-dcl-temp-schreiben` als Temp-Datei schreiben) fuer Dialoge mit fester Grundstruktur und einzelnen datenabhaengigen Bloecken. `ssg-lastent-ohne-attribute`: Startmarke fuer "alles Neue seit Marke per entnext einsammeln" - statt nacktem `(entlast)` verwenden, sonst laeuft `entnext` in die ATTRIBs/SEQEND eines vorherigen Attribut-Blocks und `_.-BLOCK` entfernt sie dort (realer Bug: per Strg+C/V kopierter GR_-Block verlor beim naechsten GERUEST seine Attribute; Test `tests/test_lastent.lsp`) |
|
||||
| `ssg_ks_insert.lsp` | - | Gemeinsame KS-Extraktion + Block-Einfuegeprimitiven (von VarioFoerderer UND Gefaellestrecke genutzt, frueher in beiden dupliziert): `vec-length`, `ks-line-axis`, `ks-normalize-name`, `ks-relativize`/`-absolutize`, `ensure-block-loaded`, `extract-ks-from-block[-raw]` (Cache `*ks-cache*`), `insert-block-by-ks` (nur Rz), `insert-inclined-scaled-block`/`insert-rotated-block-with-ks` (Rz*Ry). MNL laedt es als Core-Modul VOR Gefaellestrecke/VarioFoerderer; vf_core/Gefaellestrecke haben einen guarded Nachlade-Load fuers isolierte Test-Laden |
|
||||
| `ssg_ks_insert.lsp` | - | Gemeinsame KS-Extraktion + Block-Einfuegeprimitiven (von VarioFoerderer UND Gefaellestrecke genutzt, frueher in beiden dupliziert): `vec-length`, `ks-line-axis`, `ks-normalize-name`, `ks-relativize`/`-absolutize`, `ensure-block-loaded`, `extract-ks-from-block[-raw]` (Cache `*ks-cache*`), `insert-block-by-ks` (nur Rz), `insert-inclined-scaled-block`/`insert-rotated-block-with-ks` (Rz*Ry). MNL laedt es als Core-Modul VOR Gefaellestrecke/VarioFoerderer; vf_core/Gefaellestrecke haben einen guarded Nachlade-Load fuers isolierte Test-Laden Fuer aufgerichtete/frei gedrehte Baugruppen: `ks-xy-winkel` (Richtung eines KS), `ks-block-messen`/`ks-versatz`, `insert-block-ks-skaliert` (Rz + X-Skalierung), `insert-block-ks-matrix` (freie 3x3-Rotationsmatrix, `ks-rot-x/-y/-z`). `ensure-block-loaded` nimmt einen Block OHNE Dimensionssuffix unveraendert, wenn nur der Rohname in der Zeichnung steht (Omniflo-Bloecke aus data/omniflo/<Dim>/). |
|
||||
| `ssg_lang.lsp` | - | Sprachumschaltung Deutsch/Englisch (ssg-text, ssg-textf, *ssg-lang*) |
|
||||
| `ssg_dbg.lsp` | - | Debug-Logging (dbgopen, dbgmsg, dbgflush, dbgclose) |
|
||||
| `ssg_dialog.lsp` | - | DCL-Dialog-Vorlagen und Hilfsfunktionen |
|
||||
@@ -108,14 +110,18 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
|
||||
| `ssg_texttools.lsp` | SSG_TEXT_ERSETZEN, SSG_TEXT_PARALLEL, SSG_TEXT_HOEHE, SSG_TEXT_STIL | Text-Werkzeuge (Ursprung ACADSST `CHGTEXT`/`PARTEXT`/`ALTHOEHE`/`ALTSTIL`): Suchen/Ersetzen in TEXT, MTEXT und Block-Attributen (nutzt `ssg-bt-*`, daher NACH `ssg_blocktools` laden), Text parallel zu Linie/Polylinie/Bogen (lesbar ausgerichtet, Abstand), Hoehe/Stil aendern. Arbeitet in der XY-Ebene des Welt-KS. Reine Kerne `ssg-tt-lesbarer-winkel`, `ssg-tt-versetzt` getestet |
|
||||
| `ssg_stueckliste.lsp` | SSG_FAEHNCHEN_STUECKLISTE | Positions-Faehnchen + Stuecklistentabelle, komplett AUS DER ZEICHNUNG - es wird keine Datei eingelesen. Der Benutzer waehlt die Elemente aus (`ssg-sl-erkannte-elemente`: `ssget`-Auswahl, Enter ohne Auswahl = alle erkannten im aktuellen Layout; der reine Filter `ssg-sl-elemente-aus-ss` laesst nicht erkannte Objekte still wegfallen, man darf also grosszuegig ein Fenster aufziehen). `ssg-sl-klasse` klassifiziert Blocknamen (`KREISEL_*`/`ECKRAD_*` -> "ILS Kreisel/Eckrad", `VF_*`/`GF_*` -> "ILS Streckengruppe", `GR_*` -> "Rohrgeruest", `AP60*`/`AP110*`/`AP_110*`/`APG110*` -> je eigene Omniflo-Geraden-Gruppe; wirksamer Blockname ueber `ssg-bt-effname`, also auch dynamische Bloecke). Jedes einzelne Element bekommt ein Faehnchen (`ssg-sl-faehnchen`, Rechteck/Kreis/Automation-Rahmen + Text) an der unteren linken Ecke seiner Bounding-Box (aus `csv:get-bbox` - liefert Zentrum+Abmessungen, NICHT Eckpunkte, die Ecke wird im Code daraus berechnet); die Tabelle (`ssg-sl-tabelle-zeichnen`) gruppiert GROB je Elementklasse (keine Sivas-Artikelaufloesung wie `export_sivas.py`) zu einer Zeile mit Anzahl + Laengensumme aus dem `LAENGE`-Attribut (`ssg-sl-gruppieren`/reiner Kern `ssg-sl-gruppieren-werte`), mehrere gleichartige Elemente tragen daher dieselbe Positionsnummer. **Bewusst KEIN Datei-Import wie bei Walz/Bihler**: dort vergab ein externes System die Positionsnummern und lieferte sie als Datei zurueck, die das CAD nur abzeichnete - bei Walz (`MENU/POSITION.LSP`) eine `.pos`/`.zei` aus einem Clipper-Warenwirtschaftssystem mit Koordinaten-Zuordnung, bei Bihler ITB (`Walz_und_Bihler/SBCADBib/ITB-Module_ori.lsp`, `c:bea_pos`) eine `.pos` mit Zuordnung ueber den Entity-Handle. Diese Umwege sind hier nicht nachgebaut (Entscheidung 2026-10): Nummern und Mengen entstehen in dieser Funktion, die Stuecklisten-AUSGABE liefern EXPORTSIVAS/EXPORTCSV aus denselben Block-Attributen. Der alte `c:stueckl` (Laengen-Summierung ueber hartcodierte Walz-Profillayer wie `L-2`=ST, `A-7`=AP110) hat ebenfalls kein Aequivalent im dxfmakros-Datenmodell (Block-Attribute statt Linien-Layer). Braucht `csv:get-bbox`/`csv:get-attrib` aus `export.lsp` und `ssg-bt-effname` aus `ssg_blocktools.lsp` - muss daher NACH beiden geladen werden (siehe `ssg-ensure`-Reihenfolge in `SSG_LIB.mnl`/`ssg_load.lsp`). Reine Kerne `ssg-sl-klasse`, `ssg-sl-gruppieren-werte` in `tests/test_unit.lsp` getestet |
|
||||
| `KreiselInsert.lsp` | KreiselInsert, KreiselConnect, KreiselRedraw, KreiselQuick, KreiselEdit, KreiselParams, KreiselLabelSetup, KreiselLabelPos, KreiselLabelHoehe, ILS_Eckrad, EckradEdit, KREISEL_WEICHEN | ILS Kreisel und Eckrad komplett in AutoLISP. **Drehrichtungspfeil**: `draw-module` fuegt `data/ils/Drehrichtungspfeil.dwg` auf AN8-Mitte (Block-KS 90 Grad, da die DWG fuer Kreisel Nord->Sued gezeichnet ist; cfg `kreisel.pfeil_winkel`) und SP8-Mitte (+180) mit in den KREISEL_n-Block ein, GUZ = X-Skalierung -1 (reiner Kern `kreisel-pfeil-params`, getestet); Eckrad: ein Pfeil auf der Radmitte mit dem AN8-Winkel (`eckrad-pfeil-params`); bei wiederverwendeter Blockdefinition (KREISEL_n bzw. ECKRAD_n) zieht `kreisel-pfeil-aktualisieren` die Spiegelung per `entmod` nach. **Beruehrpunkte/Weichen** (`kreisel-bp-*`, Befehl KREISEL_WEICHEN, Menue Kreisel-Module -> Weichenpunkte ermitteln): ermittelt aus den Blockparametern (Einfuegepunkt, Drehung, ABSTAND - nicht aus der Geometrie, Modell wie `draw-module`) die Beruehrpunkte aller `KREISEL_*`/`ECKRAD_*` GLEICHER Hoehe (`toleranz_hoehe`): Rad/Rad (`Kreis/Kreis`) und Rad/Laufprofil (`Kreis/Tangente`), nur auf der freien Radseite (aeusserer Halbkreis inkl. Flanken; Eckrad ganz frei), Toleranz `toleranz_beruehrung` (component_defaults.json, Sektion kreisel). Kapsel-Mindestabstand < 2r - tol = KOLLISION (Ueberschneidung), Kreisel Seite an Seite (Beruehrung nur an Flanke/Profil) = KOLLISION `Tangente/Tangente` - beide werden gemeldet, aber nie zur Weiche. Ausgabe: Konsolenliste + Kreis-Marker (Layer `kreisel_weiche`/`kreisel_kollision` aus layer.cfg, XDATA `SSG_KR_WEICHE`, jeder Lauf ersetzt die alten). Der Export schreibt dieselben Punkte als `kreisel_weichen.json` neben `export_raw.json` (`csv:kreisel-weichen-schreiben`, export.lsp); `export_csv.py` uebernimmt sie (`export_neighbors.load_lisp_kreisel_weichen`/`lisp_touch_switches`, Rueckfall auf `compute_kreisel_touch_switches` nur ohne Datei), `export_sivas.py` setzt daraus Merkmal 4403 "Anzahl Weichen ILS". Reine Kerne `kreisel-bp-element`/`-paar`/`-berechnen` in `tests/test_unit.lsp` (`tu-tests-kreisel-bp`, u.a. mit den 11 Einfuegungen aus `tests/testdata/schnittspunkte_kreisel.dxf` -> 10 Beruehrungen) getestet. Eckrad: eigener Dialog `eckrad_edit.dcl` (`eckrad-dialog`, reiner Kern `eckrad-dialog-werte` getestet) beim Einfuegen (ILS_Eckrad, ohne GUI Konsolen-Rueckfall) und per Doppelklick (EckradEdit); kein Abstand/Typ, Drehung als freier Winkel statt fester Kreisel-Ausrichtung. `ils-eckrad-insert` behaelt eine vorhandene NUMMER (Edit -> gleicher Blockname `ECKRAD_n`). Kreiselname: `draw-module` setzt `Bezeichnung` nur noch bei leerem Wert auf die Vorgabe `KreiselN` (eigener Name aus KreiselEdit bleibt erhalten); Beschriftung `kreisel-label-text` = `KREISEL n: <Name> <TYP>_<ABSTAND>` (ohne Namen bzw. bei Vorgabename wie bisher `KREISEL n: <TYP>_<ABSTAND>`); da die Beschriftung als TEXT in der wiederverwendeten Blockdefinition `KREISEL_n_TYP_ABSTAND` steckt, setzt `kreisel-label-aktualisieren` sie dort per `entmod` neu (wirkt auf alle Referenzen der Definition) |
|
||||
| `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_SEKTION_RESTORE, VF_WIZARD_AN, VF_WIZARD_AUS | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standard- UND Etage-Typ: Werteingabe per DCL-Dialog, inkl. der vorgelagerten Eingabemodus-Wahl 3D-Linie/Werte manuell (`vfc_eingabemodus`, `vfc-dialog-eingabemodus-waehlen`) - beide Modi laufen seitdem in denselben Basis-/Winkel-Dialog, der Konsolen-Pfad ist nur noch Rueckfall bei abgeschalteter GUI/anderer Sprache. Der Dialog-Ablauf ist zentral in vf_core (`vf-dialog-ablauf`/`vf-dialog-berechnen-einfuegen`, parametrisiert ueber Typ-Registry `*vf-typ-registry*` + Flag `horizontal-p`); `vfs-standard-dialog-ablauf`/`vfe-etage-dialog-ablauf` sind nur noch duenne Wrapper darauf. Beide nutzen dieselben Dialoge `vfs-dialog-eingabe-basis`/`vfs-dialog-winkel-verteilung` und den gemeinsamen L_GF/L_VF-Solve `vf-winkel-solve` (vf_core; berechne-alle-winkel/berechne-winkel-etage teilen ihn); 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). Die interaktiven Editier-Pfade (`vfl-edit-ent` Sektions-Zweig, `vfl-edit-ent2`) rufen den Neuaufbau BEWUSST direkt auf, NICHT ueber `vl-catch-all-apply`: der alte Block ist beim Neuaufbau schon per `entdel` weg, und ein Catch faengt den Abbruch VOR `*error*` ab - der Abbruch-Wickler `vfl-modus-abbruch-sichern` kaeme nie zum Zug und die ganze Kette bliebe als lose Einzelteile ohne Block liegen (Fehlerbild "VF-Block aufgebrochen"). Nur der nicht-interaktive Batch-Konverter `vfl-konvertiere-ent` behaelt den Catch (die Batch-Schleife muss weiterlaufen) und meldet den betroffenen Block. Die Abbruch-Handler setzen zusaetzlich `*ssg-ils-dim*` zurueck, weil der Aufrufer, der das sonst tut, nach einem Abbruch nicht mehr erreicht wird. Recovery-Pfad fuer bereits aufgebrochene Ketten: `VF_SEKTION_RESTORE` (vf_linienzug.lsp) setzt das Ketten-Journal aus der XDATA der losen Objekte zusammen - `SSG_VF_EDIT_SEG` traegt pro Entity den Journal-Abschnitt DER ITERATION, in der es entstand (indiziert mit dem ersten Glied-Index darin; eine VF-Einheit mit eingebetteten Vario-Kurven erzeugt mehrere Glieder in einer Iteration), `SSG_VF_EDIT_PRE` auf den Entities des ersten Gliedes die Praeambel (Startpunkt/Starthoehe/AS). Die `.dbg`-Dateien sind reine AUSGABE und werden von keinem Befehl gelesen (dbgopen legt sie bei jedem Lauf neu an) - Wiederherstellungs-Daten gehoeren in die XDATA. `vf_konstanten.lsp` (von vf_core.lsp vor den drei Submodulen geladen) sLine truncated
|
||||
| `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_SEKTION_RESTORE, VF_WIZARD_AN, VF_WIZARD_AUS | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standard- UND Etage-Typ: Werteingabe per DCL-Dialog, inkl. der vorgelagerten Eingabemodus-Wahl 3D-Linie/Werte manuell (`vfc_eingabemodus`, `vfc-dialog-eingabemodus-waehlen`) - beide Modi laufen seitdem in denselben Basis-/Winkel-Dialog, der Konsolen-Pfad ist nur noch Rueckfall bei abgeschalteter GUI/anderer Sprache. Der Dialog-Ablauf ist zentral in vf_core (`vf-dialog-ablauf`/`vf-dialog-berechnen-einfuegen`, parametrisiert ueber Typ-Registry `*vf-typ-registry*` + Flag `horizontal-p`); `vfs-standard-dialog-ablauf`/`vfe-etage-dialog-ablauf` sind nur noch duenne Wrapper darauf. Beide nutzen dieselben Dialoge `vfs-dialog-eingabe-basis`/`vfs-dialog-winkel-verteilung` und den gemeinsamen L_GF/L_VF-Solve `vf-winkel-solve` (vf_core; berechne-alle-winkel/berechne-winkel-etage teilen ihn); 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) baut dieselbe Pfad-Geometrie VORWAERTS mit vorgegebenen Winkeln durch: die Endhoehe ist dort ein Ergebnis, kein Ziel (Anfangs- statt Randwertproblem) - genau das ist sein eigener Anwendungsfall, und er schreibt ein eigenes Journal (Marker `"linienzug3"`), ist also ebenso per Doppelklick editierbar. Seit 2026-10-22 fragt er wie Modus 2 "AS bauen?"/"ES bauen?" (je mit Winkel+Seite in EINEM Dialog, `vflw-gruppe-as-impl`), und die **ES-Frage steht VOR dem Bau** - erst damit traegt die Trimmung der letzten Geraden (`- Separator - ein-dx`) den echten ES-Fussabdruck statt eines Schaetzwerts bzw. des Werts der vorherigen Kette. Aeltere `"linienzug3"`-Journale erkennt `alt-journal` am WERT des ersten Antwort-Eintrags (`"30"`/`"90"` = alt vs. `"1"`/`"2"` = neu, disjunkte Mengen; Helfer `vfl-replay-peek-wert`) und spielt sie in der alten Reihenfolge ab. **Helfer-Namensschema**: die Rechenkerne heissen nach ihrer ROLLE, nicht nach der Modus-Nummer - `vfl-zsolve-*` (Hoehen-Solve, nur Modus 2) und `vfl-pfad-*` (Arbeit am gezeichneten Pfad, von Modus 2 UND 3 genutzt). Die frueheren Praefixe `vfl3-`/`vfl2-` stammten aus einer Planungsphase vor der endgueltigen Menue-Zuordnung und waren dazu vertauscht (umbenannt 2026-10-22). `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). Die interaktiven Editier-Pfade (`vfl-edit-ent` Sektions-Zweig, `vfl-edit-ent2`) rufen den Neuaufbau BEWUSST direkt auf, NICHT ueber `vl-catch-all-apply`: der alte Block ist beim Neuaufbau schon per `entdel` weg, und ein Catch faengt den Abbruch VOR `*error*` ab - der Abbruch-Wickler `vfl-modus-abbruch-sicherLine truncated
|
||||
| `vf_spec.lsp` (von vf_core.lsp NACH vf_linienzug.lsp geladen) | VF_SPEC_BAU | Linienzug-Ketten aus **Eingabedaten** bauen, ohne Dialog und ohne Konsolenfrage (Stufe 1 aus `doc/todo/plan-vf-interactive.md`). Eine **Spec** beschreibt eine Kette in Domaenenwerten (`"links"`, `"winkel"`, `"aussen"`, ja/nein) statt in Menue-Codes; `vsp-journal` uebersetzt sie in ein Eingabe-Journal, `vsp-bau-aus-spec` spielt es per `vfl-journal-replay-start` durch den UNVERAENDERTEN `vf-linienzug-modus` (Replay-Kern `vsp-bau-journal` - nimmt auch ein unveraendert uebernommenes, aufgezeichnetes Journal, z.B. aus `dxf_anlage_export.py`). Damit traegt der fertige Block dasselbe `SSG_VF_EDIT`-Journal wie eine handgebaute Kette und bleibt per Doppelklick editier- und 2D/3D-konvertierbar - kein Journal-Konsument muss etwas von Specs wissen. Wichtige Regeln, die der Uebersetzer kennt: der Menue-Code haengt am Frame (erste Sektion 4 Optionen ohne GF-Bogen, danach 5), `hz` steht nur beim ERSTEN Segment im Journal, und `erst-hor` unterscheidet den horizontalen Erstkoerper einer VF-Einheit (Separator-/Endpunktfragen vorab) vom gewinkelten (keine Frage). Fehlerverhalten: fail fast - `vsp-pruefen` sammelt ALLE Spec-Fehler, gebaut wird dann nichts (nichts wird geraten). Ergebnis-Record je Kette mit `status` (`executed`/`warnung`/`desync`/`abbruch`/`spec-fehler`), Block/Handle/Einfuegepunkt/Attributen, `prompts` (muss 0 sein), `glieder_soll` vs. `glieder_ist` (Desync-Detektor, der auch bei aufgehender Queue greift) und den gesammelten `meldungen`. Headless-Rahmen `vsp-headless-an`/`-aus` (Save/Restore von `*vfl-headless*`, `*vfl-wizard-mode*`, `*ssg-gui-aus*` + zaehlende Eingabe-Stubs). Spec-Datei flach als JSON (`ssg-load-json` liest zeilenweise), erzeugt von `lib/vf_spec_export.py`. Gegenstueck/Referenz in Python: derselbe Emitter, gegen die 5 echten HundM-Ketten rundlaufgeprueft |
|
||||
| `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; die Einfuegehoehe kommt aus der aktuellen Z des Einfuegepunkts statt aus XDATA/HOEHE_VON_mm, damit ein in Z verschobener Block per OK direkt auf der neuen Hoehe neu entsteht - gleiches gilt fuer die 2D/3D-Umschaltung `gf-konvertiere-ent`; der GF-Linienzug-Rebuild nutzt weiter die absoluten Segmentpunkte aus XDATA) |
|
||||
| `export.lsp` | EXPORTSIVAS, EXPORTCSV, OMNI_UPDATE_ATTRIBS, CSV_EXPORT_KONFIG | JSON-Sammlung und Python-Export (Omniflo-Merkmale/Sum-Zeile via lib/export_csv.py). **Gefrorene Layer**: `csv:collect-export-blocks` laesst Bloecke auf gefrorenen Layern aus (ausgeschaltete Layer zaehlen NICHT), Schalter `*csv-gefrorene-ausschliessen*` (Standard an, Toggle im Dialog CSV_EXPORT_KONFIG). Die Hilfsobjekte eines gefrorenen VF_n/GF_n (Separator-/Element-Kopien, Einheiten-/AS-ES-Marker) liegen auf eigenen Layern und werden darum ueber `*csv-ausschluss-enames*` mit ausgelassen (gesetzt in `csv:export-vorbereiten` per `csv:hilfskopien-ausschluss`); erzeugt und nummeriert werden sie trotzdem, damit IDs stabil bleiben. DrawPlanquadrate nutzt dieselbe Sammlung und folgt dem Filter. **Hoehen-Neuberechnung**: erster Schritt von `csv:export-vorbereiten` ist `csv:hoehen-aktualisieren` - in Z verschobene `KREISEL_*`/`ECKRAD_*`/`VF_*`/`GF_*` bekommen ihre Hoehen-Attribute aus der Einfuege-Z neu (reiner Kern `csv:hoehen-werte`, getestet; Formeln/Rundung wie beim Bau: Kreisel HOEHE + MONTAGEHOEHE_m=z/1000, Eckrad HOEHE, GF/VF HOEHE_VON_mm=(fix z), MONTAGEHOEHE_m GF=z/1000 bzw. VF=(VON+BIS)/2000). HOEHE_BIS_mm = VON - (VON_alt - BIS_alt), bewusst NICHT z - DELTA_H_mm (ohne Vorzeichen -> steigende VF falsch, separat abgeschnitten -> 1 mm Abweichung); DELTA_H_mm nur Rueckfall. Nicht verschobene Bloecke (Attribut passt zu z) bleiben unangetastet, damit Bau-Werte und Hand-Korrekturen (z.B. Buehnen-Abzug aus HOEHEN_CHECK) bit-genau erhalten bleiben |
|
||||
| `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W*_*, OMNI_AP60/AP110, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_LADESCHLEIFE_AP110, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder (`OMNI_TV_*`: DWGs dimensionsunabhaengig in `data/omniflo/Verbinder`, `omni:insert-verbinder` -> gemeinsamer Einfuegekern `omni:insert-datei`, den auch `omni:insert-dxf` nutzt; im Export ueber `pattern_verbinder` = `VB_*, TV_*` gesammelt (`csv:collect-export-blocks`, `ssg-id-collect-blocks`), Sivas-Zeilen ueber TEILEART/ARTINR wie alle Omniflo-Teile), Transferwagen, Ladeschleifen (`data/json/omniflo_ladeschleifen.json`, per `ssg-json-laden`, da die Beschreibungen Kommas enthalten; Blockdatei darf `.dwg` statt `.dxf` sein), Edit-Dialog |
|
||||
| `SSG_LIB_Commands.lsp` | ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_SCANNER_INSERT, ILS_SEPARATOR_INSERT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT, ILS_ETF_*, ILS_GK*_*, SSG_BLOCKEDIT, SSG_DIM_SWITCH, SSG_SPRACHE | BTMT Be-/Entladung (`ils-insert-station`: wiederholtes Einfuegen von `BTMT-Beladung` bzw. `SC_Entladung`, Drehung interaktiv, Layer aus `LAYER`-Attribut, Dimension via `ssg-ils-block-laden`) + Sensoren (`ils-insert-sensor`) + Eingang-/Ausgang-Symbol (frei platzierbar wie BTMT Be-/Entladung, ueber `ils-insert-station` mit den Rohnamen `Eingang`/`Ausgang`, Bloecke `Eingang_<DIM>.dwg`/`Ausgang_<DIM>.dwg` in data/ils) + Dummy-Befehle fuer Menue + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) |
|
||||
| `SSG_LIB_Commands.lsp` | ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_SCANNER_INSERT, ILS_SEPARATOR_INSERT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT, SSG_BLOCKEDIT, SSG_DIM_SWITCH, SSG_SPRACHE | BTMT Be-/Entladung (`ils-insert-station`: wiederholtes Einfuegen von `BTMT-Beladung` bzw. `SC_Entladung`, Drehung interaktiv, Layer aus `LAYER`-Attribut, Dimension via `ssg-ils-block-laden`) + Sensoren (`ils-insert-sensor`) + Eingang-/Ausgang-Symbol (frei platzierbar wie BTMT Be-/Entladung, ueber `ils-insert-station` mit den Rohnamen `Eingang`/`Ausgang`, Bloecke `Eingang_<DIM>.dwg`/`Ausgang_<DIM>.dwg` in data/ils) + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) |
|
||||
| `Tro_Edit.lsp` | TRO_INSERT, TRO_EDIT | TRO-Marker (Block `TRO_SYM_<Typ>`) fuer sps_skel (lib/tro_annotate.py): TRO_INSERT fuegt eine bestehende Blockdefinition an einem gewaehlten Punkt ein und setzt ID/TYPE (bricht ab, wenn der Typ noch keine Blockdefinition in der Zeichnung hat - die entsteht nur ueber tro_annotate.py); TRO_EDIT aendert ID/TYPE eines bestehenden Markers per Dialog. Typliste aus `tro_types.lsp` (von `tro_annotate.py --emit-lisp` nach DXFM_LISP geschrieben). Der Dispatcher SSG_BLOCKEDIT leitet Blocknamen `TRO_*` zu TRO_EDIT. |
|
||||
| `GeruestInsert.lsp` | GERUEST, GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG, GERUEST_TRAEGER, GERUEST_TRAEGER_BESCHRIFTEN, OMNI_FAHRSTRECKE, OMNI_FAHRSTRECKE_BESCHRIFTEN | Geruest-Baugruppen aus `data/json/geruest.json` konfigurieren und einfuegen. **Ein Dialog je Bereich**: Rohrabhaenger / Saeulen / Wandbefestigung oeffnen NUR ueber ihren eigenen Menuebefehl (`geruest-starten id`, Dialogtitel aus dem ASCII-Feld `titel`); eine Umschaltung im Dialog gibt es nicht (DCL hat kein Reiter-Tile), `GERUEST` ohne Bereich zeigt nur einen Hinweis. Der Dialogstand beginnt je Aufruf frisch. 1"- und 2"-Saeulen liegen in EINER Baugruppe `Saeulen` mit gemeinsamer Anbauteil-Liste; **`teileart` und `dummy` duerfen je Geometrie-Variante ueberschrieben werden** (`geruest-variante-wert`, Variante gewinnt vor Baugruppe; fuer `dummy` ueber `geruest-dummy-wahl`: fehlt die DWG der Variante, Meldung + Rueckfall auf den Baugruppen-Dummy; ist der Dummy zugleich eine Teile-DWG, wird er per `geruest-ohne-pfad` nicht doppelt eingefuegt) - so liefert `R 1"` weiterhin TEILEART `Geruest Saeule 1 Zoll` und die `R 2"`-Varianten `Geruest Saeule 2 Zoll`, die Groessen bleiben im Export also unterscheidbar. **Das Layout steht als Vorlage in `dcl/geruest.dcl`** (bzw. `dcl/geruest_traeger.dcl`); nur die datenabhaengigen Bloecke - ein `radio_button` je Variante (Key `v<i>`, `geruest-radio-key`/`-index`), Mengenfeld + Ankreuzfeld je Anbauteil - werden zur Laufzeit an Markerzeilen `//@NAME@` eingesetzt (`geruest-dcl-ersetzungen` -> `ssg-dcl-vorlage-fuellen` in ssg_core, Temp-Datei, nach `unload_dialog` geloescht). Grund: DCL kann Tiles weder zur Laufzeit erzeugen noch ausblenden, Radiobutton-Labels lassen sich per `set_tile` nicht aendern, und eine `list_box` kann keine Eingabefelder enthalten. Varianten bewusst als Radiobuttons statt `list_box`: BricsCAD zeichnet die Listenspalte nur halb so breit, und ein `tabs`-Wert passt nur schrift-/skalierungsabhaengig. Inhalt: Basis-Variante aus `geometrie_varianten` (`list_box` mit Einfachauswahl, Hoehe nach Variantenzahl, `geruest-dcl-listenhoehe`), **Winkel Platte** (0/90 Grad, `*geruest-winkel-werte*`): Ausrichtung der Anbauteile zur Basis - die Teile-DWGs aus oben/unten/sonstiges werden um diesen Winkel um Z gedreht in den Block eingefuegt, Basis und Dummy bleiben ungedreht (`geruest-teile-dwgs-rot`; in Konfigurationen als echter Wert `winkel_platte`, kein Block-Attribut), Laenge (gegen `attribute.Laenge` min/max geprueft, Retry-Schleife), Farbe (`attribute.Teilefarbe`, Freitext bei `frei_option`) und **eine Befestigungsspalte** "Befestigung oben und unten" mit allen `anbaugruppen.befestigung` - die Anzahl ist die GESAMTanzahl je Teil (oben und unten zusammen; Tile-Keys `b<i>`/`bm<i>`, Zustand `*geruest-dlg-bef*`). Unter jedem Teil (auch in Sonstiges) zeigt eine Textzeile "Art.-Nr. ..." die Artikelnummer(n) (`geruest-artnr-anzeige`: Einzelteil -> `sivas_id`, Gruppe -> eindeutige Nummern der Teile; DCL kennt keine Schriftgroesse, darum normale Groesse in eigener Zeile). `anbaugruppen` ist ein Objekt mit zwei Listen: `befestigung` (Befestigungsspalte) und `sonstiges` (Teile, die weder oben noch unten sitzen, z.B. die Saeulen-Haltearme) - letztere bekommen eine eigene Zeile darunter (nur wenn nicht leer), in ARTINR/BEZEICHNUNG nach "unten" als "sonstiges" (`geruest-anbau-liste`; ein altes flaches Array gilt als `befestigung`). **Zwei Mengenfelder im JSON, bewusst verschieden benannt**: `stueckzahl` = wie oft ein Teil TATSAECHLICH geschrieben wird (je Variante bzw. je Satz/Anbauteil, fehlt = 1), `anzahl_vorgabe` = NUR die Vorbelegung des Anzahl-Feldes im Dialog (Anbaugruppen, fehlt = 1); ein Anbauteil wird Anzahl x `stueckzahl` mal geschrieben, bei einer Gruppe (`teile`) zaehlt die Anzahl die Saetze (`geruest-stueckzahl`/`geruest-anzahl-vorgabe`). In Konfigurationen (`befestigung`/`sonstiges`, dazu `winkel_platte`) heisst der gespeicherte Dialogwert `anzahl`. Aeltere Konfigurationen mit getrennten `oben`/`unten`-Listen laden weiter: deren Mengen werden zur Gesamtanzahl addiert (`geruest-konfig-befestigung`), Sonstiges-Teile darin still in die Sonstiges-Zeile umgehaengt (`geruest-konfig-sonstiges`); beim naechsten Speichern steht alles im neuen Format. Baugruppen ohne `attribute`-Block (Wandbefestigung) bekommen Laenge/Farbe gesperrt, Baugruppen ohne Anbauteile bekommen gar keine Spalten (ein leerer DCL-Cluster ist unzulaessig). Im generierten Label wird `"` zu `''` ersetzt (`geruest-dcl-label`) - fuenf Artikelnamen enthalten ein Anfuehrungszeichen, das das DCL-Label sonst vorzeitig beendet und die Datei zerstoert. **Konfigurationen**: gepflegte Bibliothek je Baugruppe unter `konfigurationen` in `geruest.json` (schreibgeschuetzt) plus eigene in `cfg/geruest_user.json` (gitignored, `geruest-user-schreiben`; getrennte Datei, damit Benutzerdaten und versionierte Bibliothek nicht kollidieren). Eigene Eintraege sind in der Liste mit `*` markiert und nur diese loeschbar. **Geaenderte KonfiguratiLine truncated
|
||||
| `Connection_Edit.lsp` | CONNECTION_INSERT, CONNECTION_EDIT | Verbindung zwischen zwei TRO-Markern als Block `CONNECTION_ARROW` (Pfeilmitte); Beziehung ueber die INTERNEN IDs der TROs (`FROM_ID`/`TO_ID`, sichtbar `FROM_TRO`/`TO_TRO`, `KIND` flow/colocated), damit Umbenennen/Verschieben die Zuordnung nicht bricht. Dialog `connection_edit.dcl`; SSG_BLOCKEDIT leitet `CONNECTION_*` hierher (vor dem TRO-Zweig) |
|
||||
| `Jam_Edit.lsp` | JAM_EDIT | Staubereich `JAM_AREA` aus sps_skel (`tro_annotate.py --anlage`, Name `Jam<NNNN>_<k>`) bearbeiten: Foerderer und laufende Nummer per Dialog `jam_edit.dcl`, Knopf zurueck auf den abgeleiteten Wert (`AUTO`), Warnung bei doppeltem Namen. `TRO`/`ENTRY` sind stabiler Schluessel und werden nicht geaendert. SSG_BLOCKEDIT leitet `JAM_*` hierher; in die SCL kommt die Aenderung ueber `tro_annotate --read-jams` |
|
||||
| `TEFInsert.lsp` | TEF_FOERDERER_LINIE | Linie zwischen zwei Punkten zeichnen und mit 1000-mm-TEF-Geraden (`0_B10030`) belegen; Rest ueber ein zurueckversetztes Element, damit der Foerderer exakt am Linienende endet; geneigte Linien per Rz*Ry wie `ssg_ks_insert.lsp` |
|
||||
| `GeruestInsert.lsp` | GERUEST, GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG, GERUEST_TRAEGER, GERUEST_TRAEGER_BESCHRIFTEN, OMNI_FAHRSTRECKE, OMNI_FAHRSTRECKE_BESCHRIFTEN | Geruest-Baugruppen aus `data/json/geruest.json` konfigurieren und einfuegen. **Ein Dialog je Bereich**: Rohrabhaenger / Saeulen / Wandbefestigung oeffnen NUR ueber ihren eigenen Menuebefehl (`geruest-starten id`, Dialogtitel aus dem ASCII-Feld `titel`); eine Umschaltung im Dialog gibt es nicht (DCL hat kein Reiter-Tile), `GERUEST` ohne Bereich zeigt nur einen Hinweis. Der Dialogstand beginnt je Aufruf frisch. 1"- und 2"-Saeulen liegen in EINER Baugruppe `Saeulen` mit gemeinsamer Anbauteil-Liste; **`teileart` und `dummy` duerfen je Geometrie-Variante ueberschrieben werden** (`geruest-variante-wert`, Variante gewinnt vor Baugruppe; fuer `dummy` ueber `geruest-dummy-wahl`: fehlt die DWG der Variante, Meldung + Rueckfall auf den Baugruppen-Dummy; ist der Dummy zugleich eine Teile-DWG, wird er per `geruest-ohne-pfad` nicht doppelt eingefuegt) - so liefert `R 1"` weiterhin TEILEART `Geruest Saeule 1 Zoll` und die `R 2"`-Varianten `Geruest Saeule 2 Zoll`, die Groessen bleiben im Export also unterscheidbar. **Das Layout steht als Vorlage in `dcl/geruest.dcl`** (bzw. `dcl/geruest_traeger.dcl`); nur die datenabhaengigen Bloecke - ein `radio_button` je Variante (Key `v<i>`, `geruest-radio-key`/`-index`), Mengenfeld + Ankreuzfeld je Anbauteil - werden zur Laufzeit an Markerzeilen `//@NAME@` eingesetzt (`geruest-dcl-ersetzungen` -> `ssg-dcl-vorlage-fuellen` in ssg_core, Temp-Datei, nach `unload_dialog` geloescht). Grund: DCL kann Tiles weder zur Laufzeit erzeugen noch ausblenden, Radiobutton-Labels lassen sich per `set_tile` nicht aendern, und eine `list_box` kann keine Eingabefelder enthalten. Varianten bewusst als Radiobuttons statt `list_box`: BricsCAD zeichnet die Listenspalte nur halb so breit, und ein `tabs`-Wert passt nur schrift-/skalierungsabhaengig. Inhalt: Basis-Variante aus `geometrie_varianten` (Radiobuttons, siehe oben), **Winkel Platte** (0/90 Grad, `*geruest-winkel-werte*`): Ausrichtung der Anbauteile zur Basis - die Teile-DWGs aus oben/unten/sonstiges werden um diesen Winkel um Z gedreht in den Block eingefuegt, Basis und Dummy bleiben ungedreht (`geruest-teile-dwgs-rot`; in Konfigurationen als echter Wert `winkel_platte`, kein Block-Attribut), Laenge (gegen `attribute.Laenge` min/max geprueft, Retry-Schleife), Farbe (`attribute.Teilefarbe`, Freitext bei `frei_option`) und **eine Befestigungsspalte** "Befestigung oben und unten" mit allen `anbaugruppen.befestigung` - die Anzahl ist die GESAMTanzahl je Teil (oben und unten zusammen; Tile-Keys `b<i>`/`bm<i>`, Zustand `*geruest-dlg-bef*`). Unter jedem Teil (auch in Sonstiges) zeigt eine Textzeile "Art.-Nr. ..." die Artikelnummer(n) (`geruest-artnr-anzeige`: Einzelteil -> `sivas_id`, Gruppe -> eindeutige Nummern der Teile; DCL kennt keine Schriftgroesse, darum normale Groesse in eigener Zeile). `anbaugruppen` ist ein Objekt mit zwei Listen: `befestigung` (Befestigungsspalte) und `sonstiges` (Teile, die weder oben noch unten sitzen, z.B. die Saeulen-Haltearme) - letztere bekommen eine eigene Zeile darunter (nur wenn nicht leer), in ARTINR/BEZEICHNUNG nach "unten" als "sonstiges" (`geruest-anbau-liste`; ein altes flaches Array gilt als `befestigung`). **Zwei Mengenfelder im JSON, bewusst verschieden benannt**: `stueckzahl` = wie oft ein Teil TATSAECHLICH geschrieben wird (je Variante bzw. je Satz/Anbauteil, fehlt = 1), `anzahl_vorgabe` = NUR die Vorbelegung des Anzahl-Feldes im Dialog (Anbaugruppen, fehlt = 1); ein Anbauteil wird Anzahl x `stueckzahl` mal geschrieben, bei einer Gruppe (`teile`) zaehlt die Anzahl die Saetze (`geruest-stueckzahl`/`geruest-anzahl-vorgabe`). In Konfigurationen (`befestigung`/`sonstiges`, dazu `winkel_platte`) heisst der gespeicherte Dialogwert `anzahl`. Aeltere Konfigurationen mit getrennten `oben`/`unten`-Listen laden weiter: deren Mengen werden zur Gesamtanzahl addiert (`geruest-konfig-befestigung`), Sonstiges-Teile darin still in die Sonstiges-Zeile umgehaengt (`geruest-konfig-sonstiges`); beim naechsten Speichern steht alles im neuen Format. Baugruppen ohne `attribute`-Block (Wandbefestigung) bekommen Laenge/Farbe gesperrt, Baugruppen ohne Anbauteile bekommen gar keine Spalten (ein leerer DCL-Cluster ist unzulaessig). Im generierten Label wird `"` zu `''` ersetzt (`geruest-dcl-label`) - fuenf Artikelnamen enthalten ein Anfuehrungszeichen, das das DCL-Label sonst vorzeitig beendet und die Datei zerstoert. **Konfigurationen**: gepflegte Bibliothek je Baugruppe unter `konfigurationen` in `geruest.json` (schreibgeschuetzt) plus eigene in `cfg/geruest_user.json` (gitignored, `geruest-user-schreiben`; getrennte Datei, damit Benutzerdaten und versionierte Bibliothek nicht kollidieren). Eigene Eintraege sind in der Liste mit `*` markiert und nur diese loeschbar. **Geaenderte Konfiguration**: beim Anwenden wird der Dialogstand als VergleichsbasLine truncated
|
||||
| `KettenFoerderer.lsp` | KETTENFOERDERER, KF_EDIT, KF_KS_PRUEFEN | Kettenfoerderer/Schraegfoerderer Stahl: baut aus `KF_UM_<winkel>` -> `KF_LAENGE` -> `KF_AN_<winkel>` (je KS_AUS auf KS_EIN) plus der Draufsicht `KF_2D` EINEN Block `KF_<n>`. Daten `data/json/kettenfoerderer.json`, Dialog `dcl/kettenfoerderer.dcl`. **Geometrie**: die Bausteine sind in der XY-Ebene gezeichnet (Hoehe = Y), werden aber AUFGERICHTET eingebaut `Rz(basis)*Rx(90)*Rz(eigen)` (`kf-matrix-aufrecht`) - die Hoehe laeuft in **Z**; dafuer `insert-block-ks-matrix` (freie 3x3-Rotation) in ssg_ks_insert.lsp. Die Neigung (26/30 Grad) ist KEIN Rechenparameter: sie steckt in den Varianten-Bloecken, der Einbauwinkel jedes Folgebausteins wird zur Laufzeit aus der RICHTUNG des KS_AUS seines Vorgaengers gemessen (`ks-xy-winkel`/`kf-hz-folge`) - keine gepflegte Winkeltabelle. `KF_LAENGE` wird in X skaliert, die Einbauhoehe H bestimmt seine Laenge ueber die Hoehenbilanz (`kf-laenge-berechnen`). `KF_2D` liegt DECKUNGSGLEICH mit der Kette (KS_EIN/KS_AUS auf denen von Umlenkung/Antrieb), ist flach gezeichnet, nur um die Steigung geneigt und auf die Schraeglaenge skaliert. **Attribut-Schema** `*kf-attrib-defs-liste*` ist EIGENSTAENDIG und bewusst NICHT von `ssg-strecke-attrib-defs` abgeleitet (sonst ~24 geerbte VF-Tags am Block); die Reihenfolge folgt dem Sivas-Merkmalstamm. FOERDERERTYP = Bauart im Klartext, WINKEL = nackte Zahl 26/30 (der Klartext mit Gradzeichen entsteht erst ueber `[kf_typ_anzeige]` in cfg/sivas.cfg, damit Attributwerte ASCII bleiben); kein TEILEART (Festwert `KF_TEILEART` im Export). Alle Auswahllisten stehen mit ihren Sivas-Optionstexten in der JSON. **Das `KF_`-Praefix ist wie `GR_` nicht kosmetisch**: `SSG_BLOCKEDIT` haelt JEDEN Block mit TEILEART-Attribut fuer ein Omniflo-Element, darum steht ein `KF_*`-Zweig VOR dem Omniflo-Zweig (Doppelklick -> KF_EDIT). **Sivas-Export** (`[kettenfoerderer]` in cfg/sivas.cfg, `build_kettenfoerderer_details` in export_sivas.py): baugleiche Foerderer werden zu EINER Zeile zusammengefasst (`kettenfoerderer_signature`), die Gruppengroesse traegt Merkmal 353 (entsteht erst aus der Gruppierung, daher Code); Farbe (354) und Antriebsmotor (355) sind ZWEI Merkmale, und jedes merkmalbildende Attribut steht auch in der Signatur, sonst verschmelzen unterschiedlich ausgefuehrte Foerderer. Reine Kerne in `tests/test_unit.lsp` (`tu-tests-kf`); das Modul wird in der MNL vorgeladen, Laufzeit-Messung ueber den dbg-Schalter `kf-zeit` |
|
||||
| `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) |
|
||||
| `LagerInsert.lsp` | LG_GESCHOSS, LG_GESCHOSS_AKTIV, LG_GESCHOSS_KOPIEREN, LG_BEREICH, LG_REIHE, LG_GANG, LG_EDIT, LG_REGALE, LAGER_EXPORT, LAGER_HAND_YAML | Lagerplanung GOH-Buehnenlager -> RFQ-YAML (Phase 0+1: Mengen, 2D; Konzept/Schema/YAML-Zuordnung in `doc/plan/lager_rfq.md`). Bloecke `LG_GESCHOSS` (Kopfsymbol, XDATA `SSG_LG` `kontur` -> Belagskontur), `LG_BEREICH` (Kontur + Parameter, fuellt sich selbst), `LG_REIHE_<L>_<T>`/`LG_GANG_<L>_<B>_<BELAG>` (Definition je Geometrie wiederverwendet, Werte in den Attributen der Referenz; Kinder tragen XDATA `bereich`; der Belag steht im Gang-Blocknamen, weil die Definition seine Schraffur enthaelt - Muster aus `lager.json belag_schraffur`, per `vla-AddHatch` auf Layer 0/VONBLOCK, `hallenboden` ohne; BricsCAD-`iso.pat` kennt kein `NET`, Gitterrost = `GRID`). Alle tragen `ID`, `GESCHOSS`, `LAYER`. Blockdefinitionen per `entmake` (BLOCK...ENDBLK), Einfuegen per `vla-InsertBlock` in WCS - kein `_.-BLOCK`/`_.INSERT`. **Attribut-Tags haben gemischte Schreibweise** (`HOEHE_BELAG_mm`) - beim Setzen ueber `vla-get-TagString` daher case-insensitiv zuordnen (`lg-wert-fuer-tag`), sonst bleiben diese Attribute still leer (realer Fehler beim Bau). Layer je Geschoss = Basis aus `cfg/layer.cfg [lager]` + `_G<nr>`; `LG_GESCHOSS_AKTIV` friert die uebrigen (2D-Grundrisse liegen uebereinander), aktives Geschoss als `vlax-ldata` (Dictionary `SSG_LAGER`). Geschosszuordnung `lg-geschoss-fuer-punkt-kern`: eine Kontur -> eindeutig, mehrere nur ueber Z unterscheidbar, wenn die Konturen auf verschiedenen Hoehen liegen (3D), sonst nil. Jede Kontur gehoert genau einem Block (vergebene Kontur wird kopiert). Auto-Fuellung `lg-fuellung-berechnen` (reiner Kern, Muster Reihe|Gang|Reihe Ruecken an Ruecken bzw. Reihe|Gang, nur volle Module, Streifen an Unter-/Mittel-/Oberkante gegen die Kontur geschnitten, Quergaenge ausgerichtet und nicht am Reihenende); Bereichs-Edit = Neuaufbau aller Kinder. **Randgaenge** `RANDGANG_N/O/S/W_mm` (Nord = +Y Welt) laufen entlang der echten Konturkanten (`lg-randgang-streifen`, Himmelsrichtung der Aussennormale ueber `lg-kompass`, auch L-Form; Ecken: N/S besitzen sie - konvex O/W kuerzen, einspringend N/S verlaengern) und werden wie manuelle Gaenge (`LG_GANG`, `QUELLE=manuell`, Kern `lg-gang-einfuegen`; per Linie oder Option `Rechteck` = Flaeche mit dem echten BricsCAD-Befehl RECHTECK gezeichnet, inkl. aller seiner Optionen (`lg-rechteck-zeichnen`: `_.RECTANG` + `(command pause)`-Schleife bei CMDECHO 1, Polylinie danach ueber `lg-rechteck-ecken-aus-poly` gelesen und geloescht; nur 4 Ecken ohne Boegen, sonst Meldung), Breite/Lage aus dem Rechteck ueber `lg-gang-aus-ecken`, Schleife `lg-linien-schleife` mit `rechteck-fn`) als **Sperrflaechen** aus Reihen/Haupt-/Quergaengen ausgeschnitten (`ssg-poly-band-x`). **Von Hand Gesetztes loest KEINE Neuberechnung aus**: `LG_REIHE`/`LG_GANG` (`lg-manuell-einfuegen`) und das Bearbeiten einer Reihe/eines Gangs (`lg-linie-neu-aufbauen-sperre`) schneiden nur die eigene Flaeche aus den rangniedrigeren Objekten heraus (`lg-sperre-anwenden`, reiner Kern `lg-linie-zuschnitt`; Rang `lg-quelle-rang`: auto < auto_geaendert < manuell) - frueher fuellte ein manueller Gang den ganzen Bereich neu, dabei kamen geloeschte Objekte zurueck und geaenderte wurden ersetzt. Die ausdrueckliche Neuberechnung (`lg-bereich-fuellen`, Bereich bearbeiten) entfernt nur `QUELLE=auto`; `manuell`/`auto_geaendert`-Kinder und unverknuepfte manuelle Objekte in der Kontur (`lg-manuelle-in-kontur`) bleiben und sperren ihre Flaeche. `lg-blockdef` ergaenzt bei Altbestand fehlende ATTDEFs (Neudefinition + `_.ATTSYNC`). `LAGER_EXPORT` schreibt `<dwg>_lager_raw.json` (eigener JSON-Schreiber `lg-json-*`), zaehlt `goh_rack` ueber die eigene Erkennung `lg-racks-sammeln`/`lg-racks-finden` mit (parametrischer BricsCAD-Block: Name ueber `getpropertyvalue "EffectiveName"`, Parameter `Laenge`/`Ebenen` als MCAD-Eigenschaft `<Name>~MCAD` vor dynamischer Eigenschaft vor Attribut vor ATTDEF-Vorgabe, Einheit -> mm per `lg-zahl-einheit`; auch in assoziativen Arrays, MINSERT-Rastern und verschachtelten Bloecken, Transformationen `lg-insert-tf`/`lg-tf-verketten`; Ergebnis je Rack `(name laenge ebenen mitte top-ent)`, Zugriff `lg-rk-*`; Befehl `LG_REGALE` (Menue Lager -> Regale zaehlen) zeigt Anzahl, Laenge und Laenge x Ebenen je Geschoss in der Befehlszeile, reiner Kern `lg-racks-auswerten`) und ruft `lib/lager_yaml_export.py` ueber `export:run-python`. Vorgaben aus `data/json/lager.json`. Dialoge `dcl/lager.dcl` ueber den generischen Treiber `lg-dialog` (Feldlisten `*lg-felder-*`, Konsolen-Rueckfall `lg-konsole`, ohne GUI Vorgaben). **Geschoss kopieren** (`LG_GESCHOSS_KOPIEREN`, Dialog `lg_geschoss_kopie`, Kern `lg-geschosse-kopieren`): Quelle (Vorgabe oberstes Geschoss, Erweitern G3 -> G4), Anzahl, Geschosshoehe je Kopie, Belag, Versatz X/Y je Kopie (0 = deckungsgleich; 3D-Zeichnung zusaetzlich +Z). Kein BricsCAD-KOPIEREN (XDATA-Verweise zeigten aufs Original): jedes Objekt entsteLine truncated
|
||||
| `LagerPruefung.lsp` | LG_REGELN | Regelprofile der Lagerplanung: `cfg/regelwerk/<LAND>.json` laden, `erbt_von` aufloesen (`lg-profil-mischen`), je Regel den STRENGSTEN Wert aller zutreffenden Quellen (`lg-regel-aufloesen`: `art` min/max/wert, `bedingung` gegen einen Kontext - fehlt der Schluessel, konservativ einbezogen -, `tabelle` + `tabellen_schluessel`) mit Protokoll. Jede Pruefregel der Lagerplanung wird genau hier implementiert (Python rendert nur). Alle Startwerte `verifiziert: false` |
|
||||
@@ -136,13 +142,18 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
|
||||
| `sprache.dcl` | SSG_SPRACHE (SSG_LIB_Commands.lsp) |
|
||||
| `tro_insert.dcl` | TRO_INSERT (Tro_Edit.lsp) |
|
||||
| `tro_edit.dcl` | TRO_EDIT (Tro_Edit.lsp) |
|
||||
| `connection_edit.dcl` | CONNECTION_INSERT/CONNECTION_EDIT (Connection_Edit.lsp) |
|
||||
| `jam_edit.dcl` | JAM_EDIT (Jam_Edit.lsp) |
|
||||
| `csv_export_konfig.dcl` | CSV_EXPORT_KONFIG (export.lsp) |
|
||||
| `geruest.dcl` | VORLAGE fuer GERUEST_SAEULEN/_ROHRABHAENGER/_WANDBEFESTIGUNG (GeruestInsert.lsp, `geruest-dialog`); Platzhalter `//@TITEL@`/`//@VARIANTEN@`/`//@BEFESTIGUNG@`/`//@SONSTIGES@` werden per `ssg-dcl-vorlage-fuellen` gefuellt, nicht direkt ladbar |
|
||||
| `geruest_traeger.dcl` | VORLAGE fuer GERUEST_TRAEGER (GeruestInsert.lsp, `geruest-traeger-dialog`), Platzhalter `//@VARIANTEN@` |
|
||||
| `fahrstrecke.dcl` | VORLAGE fuer OMNI_FAHRSTRECKE (GeruestInsert.lsp, `geruest-traeger-dialog`), gleiche Tile-Keys wie `geruest_traeger.dcl`, Platzhalter `//@VARIANTEN@` |
|
||||
| `kettenfoerderer.dcl` | KETTENFOERDERER/KF_EDIT (KettenFoerderer.lsp, `kf-dialog`); VORLAGE mit Markerzeile `//@VARIANTEN@` (Typ als Radiobuttons, gefuellt per `ssg-dcl-vorlage-fuellen`), die uebrigen Auswahllisten sind `popup_list`-Tiles, die per `start_list`/`add_list` aus `data/json/kettenfoerderer.json` gefuellt werden. Der Knopf `hoehe_messen` schliesst den Dialog per `done_dialog 2` (Hoehe aus 2 Punkten messen, danach erneut zeigen) |
|
||||
| `dinformate.dcl` | DIN_FORMATE (DinFormate.lsp) |
|
||||
| `lager.dcl` | LG_GESCHOSS/LG_GESCHOSS_KOPIEREN/LG_BEREICH/LG_REIHE/LG_GANG + Edit (LagerInsert.lsp, generischer Treiber `lg-dialog`); Dialoge `lg_geschoss`, `lg_geschoss_kopie`, `lg_bereich` (inkl. Randgaenge N/O/S/W), `lg_reihe`, `lg_gang`, Tile-Keys = Feldlisten `*lg-felder-*` |
|
||||
| `vfl_edit.dcl` | Linienzug-Editieren/Fortsetzen (vf_linienzug.lsp, `vfl-dlg-position`, aufgerufen aus `vfl-edit-ent`) |
|
||||
| `vf_linienzug_wizard.dcl` | Linienzug-Assistent (Modus 1, 2 UND 3): zwei generische Einzel-Dialoge (Zahl-Eingabe, Mehrfachauswahl; `vflw-zahl`/`vflw-wahl`, aufgerufen aus `vfl-in-real`/`vfl-in-string`/`vfl-in-int` bei aktivem `*vfl-wizard-mode*`) PLUS sieben Gruppen-Dialoge, die mehrere immer unmittelbar aufeinanderfolgende Fragen in einem Bildschirm zusammenfassen (Kettenstart, AS-Element, GF-Bogen, ES-Element, Vario-Kurve, Gefaelle festlegen, Ziel-Hoehe, Horizontales Stueck - inkl. Punktwahl-Button mit X/Y/Z-Anzeige; `vflw-gruppe-*-impl` in vf_linienzug.lsp fuellen dafuer vorab eine kleine Pending-Queue `*vflw-pending*`, die einzelnen `vfl-in-*`-Aufrufe bleiben dabei unveraendert) PLUS drei Segment-Gruppen-Dialoge fuer die segmentweise Klassifizierung in Modus 2/3 (`vflw_seg_linie_m2` = Typ+GF-Neigung, `vflw_seg_linie_m3` = 4-fach-Typ+kontextabh. Wertfeld, `vflw_seg_bogen` = Typ+Variante; `vflw-seg-*-impl`). Beide Modi heben vor der Frage das aktuelle Pfad-Segment (LINE/ARC) per `vfl-seg-highlight` (`redraw`) in der Zeichnung hervor und zeigen "Segment i/n ..." im Dialogkopf. Details: `doc/variofoerderer.md` |
|
||||
| `vfl_edit_modus.dcl` | Linienzug-Edit: Auswahl des Edit-Modus (vf_linienzug.lsp) |
|
||||
| `vf_linienzug_wizard.dcl` | Linienzug-Assistent (Modus 1, 2 UND 3): zwei generische Einzel-Dialoge (Zahl-Eingabe, Mehrfachauswahl; `vflw-zahl`/`vflw-wahl`, aufgerufen aus `vfl-in-real`/`vfl-in-string`/`vfl-in-int` bei aktivem `*vfl-wizard-mode*`) PLUS sieben Gruppen-Dialoge, die mehrere immer unmittelbar aufeinanderfolgende Fragen in einem Bildschirm zusammenfassen (Kettenstart, AS-Element, GF-Bogen, ES-Element, Vario-Kurve, Gefaelle festlegen, Ziel-Hoehe, Horizontales Stueck - inkl. Punktwahl-Button mit X/Y/Z-Anzeige; `vflw-gruppe-*-impl` in vf_linienzug.lsp fuellen dafuer vorab eine kleine Pending-Queue `*vflw-pending*`, die einzelnen `vfl-in-*`-Aufrufe bleiben dabei unveraendert). Das AS-Element am Kettenanfang von Modus 1 nutzt die Variante `vflw_as_achse` (Parameter `mit-achse` von `vflw-gruppe-as-impl`): zusaetzlich zu Ja/Nein, Winkel und Seite liegt dort die **Zufuehrungsachse** (2. Punkt, Punktwahl-Button) im selben Fenster, und die Seite ist auch beim 30-Grad-Element waehlbar. Der ES-Fall und die Modi 2/3 bleiben beim unveraenderten `vflw_as` PLUS drei Segment-Gruppen-Dialoge fuer die segmentweise Klassifizierung in Modus 2/3 (`vflw_seg_linie_m2` = Typ+GF-Neigung, `vflw_seg_linie_m3` = 4-fach-Typ+kontextabh. Wertfeld, `vflw_seg_bogen` = Typ+Variante; `vflw-seg-*-impl`). Beide Modi heben vor der Frage das aktuelle Pfad-Segment (LINE/ARC) per `vfl-seg-highlight` (`redraw`) in der Zeichnung hervor und zeigen "Segment i/n ..." im Dialogkopf. Details: `doc/variofoerderer.md` |
|
||||
|
||||
## Menue (SSG_LIB.mnu + SSG_LIB.mnl)
|
||||
|
||||
@@ -174,6 +185,7 @@ Werden via `bin/setenv.bat` gesetzt. Wichtigste:
|
||||
- **Wiederverwendung vor Neuschaffung bei LISP-Routinen**: Neue Funktionen moeglichst als Erweiterung/Ergaenzung bestehender Funktionen anlegen. Bevor eine NEUE Bibliothek (`.lsp`-Datei) geschaffen wird, immer zuerst pruefen, ob es bereits thematisch passende Routinen gibt, in die die Funktionalitaet gehoert (z.B. Einfuege-Primitiven in `ssg_ks_insert.lsp`, Kern-Helfer in `ssg_core.lsp`, Konstanten in `vf_konstanten.lsp`). Erst wenn nichts passt, ein neues Modul.
|
||||
- **Neue LISP-Routinen nach Moeglichkeit in die LISP-Testsuite aufnehmen**: Jede neue LISP-Routine soll moeglichst einen Test bekommen. **Vorrang haben Routinen, die OHNE Zeichnung/Dateien testbar sind** (reine Berechnung, Parser, String-/Listen-Helfer, cfg-/JSON-Aufloesung) - die gehoeren als `tu-*`-Testblock in `tests/test_unit.lsp` (Befehl `TEST_UNIT`), der komplett file- und zeichnungsfrei laeuft. Zeichnungs-/geometrieabhaengige Routinen ueber ein Szenario-Modul (`tests/test_<name>.lsp` + Eintrag in `tests/alltests.json`, ausgefuehrt von `SSG_RUN_ALL_TESTS`) abdecken. Die reinen Berechnungspfade einer solchen Routine trotzdem, wo moeglich, zusaetzlich als file-freien Unit-Test herausziehen.
|
||||
- **Headless-Testlauf**: Die Unit-Tests laufen ohne GUI ueber `bin/run_tests.bat --lisp` - das startet BricsCAD im Batch-Modus (`/nologo /b`) mit `tests/test_unit.scr` und fuehrt `TEST_UNIT` aus. **BricsCAD steht dafuer ueber die Umgebungsvariable `BRICSCAD` zur Verfuegung** (in `bin/setenv.bat` gesetzt, auf die installierte `bricscad.exe` zeigend); `run_tests.bat` bricht mit Hinweis ab, wenn sie fehlt. Ein neuer file-freier Unit-Test ist damit auch ohne interaktive BricsCAD-Sitzung fahrbar. (Python-seitige Tests siehe `.venv` + `pytest tests/`.)
|
||||
- **Woechentliche Doku- und TODO-Pruefung (freitags)**: Einmal pro Woche, am besten freitags in einer Sitzung mit dem Benutzer, werden `README.md`, `CLAUDE.md`, `Lisp/README.md`, `tests/README.md` und alle `doc/*.md` (inkl. `doc/plan/`, `doc/todo/`) auf Aktualitaet geprueft: stimmen Befehle, Dateien, Funktionen und Menuestruktur noch mit dem Code (`menu/SSG_LIB.mnu`, `defun c:`-Liste) ueberein? Dabei die zentrale TODO-Liste `doc/todo.md` durchgehen - Erledigtes entfernen, neu Hinzugekommenes eintragen, Fahrplaene in `doc/todo/*.md` nur loeschen, wenn sie vollstaendig erledigt sind. Ergebnis kurz mit dem Benutzer abstimmen, dann committen.
|
||||
- **Regelmaessiges Tote-Code-Review**: Wiederkehrend auf tote/nicht mehr verwendete LISP-Routinen pruefen und aufraeumen - vorzugsweise zu Wochenbeginn, wenn in der betreffenden Woche ohnehin an den LISP-Routinen gearbeitet wird.
|
||||
- **Wiederherstellungs-/Editierdaten gehoeren in XDATA/Journal, nicht in `.dbg`**: Alles, was zum Neuaufbau/Editieren eines Blocks noetig ist (z.B. das VF-Linienzug-Eingabe-Journal `SSG_VF_EDIT`), wird als XDATA am Block gefuehrt. Die `.dbg`-Dateien (`ssg_dbg.lsp`) sind reine AUSGABE, werden von keinem Befehl gelesen und bei jedem Lauf neu angelegt - nie als Datenquelle nutzen.
|
||||
- **Editierbarkeit: festes Schema vs. Sektions-Ruecksprung**: Konstrukte mit FESTER Feldstruktur (feste Anzahl/Typen von Werten, z.B. AS/ES/GF-Bogen/Vario-Kurve im VF-Linienzug) ueber ein deklaratives Schema als einzeln editierbare Records fuehren (Einzel-Glied-Edit per Feld-Splice). Konstrukte mit VARIABLEM Dialog-Fluss (datenabhaengige Feldzahl, z.B. Horizontal-Koerper/Auf-Ab-Foerderer) NICHT per fragilem "n Felder abschneiden"-Splice editieren, sondern per Sektions-Ruecksprung: ab dem gewaehlten Glied zuruecksetzen und live neu aufbauen. Ein fester Splice ueber eine datenabhaengige Feldgrenze ist genau das Muster des Winkel-Index-Bugs.
|
||||
@@ -201,14 +213,14 @@ Abhaengigkeiten: `ezdxf`, Standard-Library. Benoetigen Umgebungsvariablen (`DXFM
|
||||
| `set_einfuegepkt.py` | Setzt `$INSBASE` (Einfuegepunkt) in Omniflo-DXF-Dateien. Schalter je Typ: `--boegen`, `--weichen45`, `--weichen90`, `--weichenkoerper`, `--weichen-parallel`, `--delta`, `--dreifachweiche`, `--sternweiche`, `--show-omniflo` |
|
||||
| `set_koords.py` | Setzt Koordinatensystem-Bloecke (K1-K4) in Omniflo-DXF-Dateien. Schalter: `--k1set` bis `--k4set`, `--set-all`, `--force`, `--show-omniflo`, `--test`, `--number` |
|
||||
| `export_sivas.py` | Erzeugt Sivas-Export-CSV mit Summierungszeilen (ILS Automation, Omniflo Sum). Omniflo-Elemente werden ueber das TEILEART-Attribut (`Omniflo *`) erkannt, ihre Sivas-Nummern kommen - wie beim Geruest - NUR aus dem kommagetrennten `ARTINR`-Attribut (eine Zeile je Nummer, TEF-Teile `0_B*` als `Omniflo TEF`); KEIN Katalog-Lookup mehr (den nutzt nur noch `export_csv.py` fuer die Merkmale). Schreibt zusaetzlich immer `<output>_zusammengefasst.csv`: Zeilen, die sich nur in Nr/Anzahl/IDs unterscheiden (v.a. Geruest, je Block eine Zeile), zu einer Zeile zusammengefasst (`items_zusammenfassen`, Anzahl addiert, IDs vereinigt); die Hauptdatei bleibt unveraendert. **ILS 2.0 Weiche (6216)**: eine Summenzeile (Anzahl 1), sobald `kreisel_weichen.json` (LISP-Export, siehe KreiselInsert.lsp) Beruehrpunkte enthaelt - je Beruehrpunkt eine Weichenkombination aus 1x aktiv (3371) + 1x passiv (3372), Zuordnung in `cfg/sivas.cfg` `[weichen]` ueber das synthetische Attribut `ANZAHL_WEICHEN`; dieselbe Zahl geht in Merkmal 4403 der Automation-Zeile. Aufruf: `python export_sivas.py <export_raw.json> <data_dir> <output.csv>` |
|
||||
| `export_csv.py` | Erzeugt einfache Item-Liste als CSV (ohne Summierung). Aufruf: `python export_csv.py <export_raw.json> <data_dir> <output.csv>` |
|
||||
| `export_csv.py` | Erzeugt einfache Item-Liste als CSV (ohne Summierung). Spalten `Nachbarn`/`TrackIds` einer VF_n/GF_n kommen aus deren `sepliste` (Bauprotokoll, nur beim Bau per `entnext` gesammelt). **Freie Separatoren** (eigenstaendige `Separator_SP`-Bloecke, deren Zuordnung die Strecke nennt, die aber nicht beim Bau entstanden - realer Fall Mubea VF_3: 0037/0038) nimmt `einsortieren_freie_separatoren` (export_neighbors.py) vor `compute_sep_kette` nach Lage in die Kette auf: nur wenn Mittelpunkt in der Strecken-BBox UND laengs des Linienzugs der Kettenglieder zwischen AS und ES (reiner Kern `sepliste_einsortier_positionen`); der Separator bekommt das Merkmal `"Einsortiert in": <Strecke>` (sps_skel zieht ihn darueber von der sepliste-Gegenprobe ab) und einen Hinweis in `Warnungen`. **Bewusst nur im Speicher des Exportlaufs, NICHT in die sepliste-XDATA zurueckgeschrieben**: Lisp paart die sepliste-Eintraege ueber die Anzahl je Typ mit den eingebauten Bausteinen (`csv:sepliste-kette-paare`) und fuehrt reservierte AS/ES-IDs unter der `lfdnr` (`csv:asmark-res-key`) - ein fremder Eintrag verschoebe beides; ausserdem schreibt jeder Neuaufbau/Edit der Strecke die XDATA neu. Test `tests/test_export_freie_separatoren.py`. Aufruf: `python export_csv.py <export_raw.json> <data_dir> <output.csv>` |
|
||||
| `split_block_library.py` | Teilt `ils_library.dxf` in einzelne DXF-Dateien pro Block auf (mit Abhaengigkeiten). Export-Prefixe: Vario_, Staustrecke_, _3D_AS_, _3D_ES_ |
|
||||
| `vf_journal_export.py` | Liest die Eingabe-Journale der `VF_n`-Bloecke (XDATA-App `SSG_VF_EDIT`, Marker `"linienzug"`) aus einer Zeichnung und schreibt sie als Frage-Antwort-Protokoll im Schema von `tests/testdata/linienzug_tests.json` (Gegenstueck zu `vfl-entry->string`; kein ezdxf, reine Gruppencode-Lesung). Optional `--csv <sivas_export.csv>` fuer Strecken-ID und Erwartungswerte je Kette. Aufruf: `python vf_journal_export.py <dxf> <output.json> [--csv ...] [--kein-startpunkt-fix]` — erzeugt `tests/testdata/hm_recformat.json` aus `data/polylines.dxf` (die Aufzeichnung, aus der `tests/testdata/hundm05.json` als Spec abgeleitet wird) |
|
||||
| `dxf_vf_abbild.py` | Abbild der `VF_`/`GF_`-Wrapperbloecke einer Testzeichnung: Attribute UND Bausteinzusammensetzung je Kette, Ketten ueber den Einfuegepunkt der Spec zugeordnet (der Blockname taugt nicht - die VF-Nummer beginnt in jeder Zeichnung neu bei 1). Regressionsnetz fuer Umbauten am Bau-Ablauf: `--referenz` vergleicht gegen `tests/reference/hundm05_attribute.json` (Exit 1 bei Abweichung), `--schreibe-referenz` frischt sie nach einem GEPRUEFTEN Lauf auf. Faengt genau das, was der Ergebnis-Record nicht sieht - eine vertauschte `vfl-acc-*`-Reihenfolge (Komma-Listen `L_VF_m`/`L_GF_m`/`GF_WINKEL`, in der Zeichnung unsichtbar, im Sivas-Export falsch) und eine falsche Blockvariante. Liest ASCII-DXF streamend; binaere DXF kann `dxf_scan_components.py`. Genutzt von `tests/test_vf_geometrie.py` |
|
||||
| `vf_spec_export.py` | Uebersetzt ein Eingabe-Journal in eine **Spec** und zurueck (`spec_aus_journal` / `journal_aus_spec`) - Gegenstueck zu `vsp-journal` in `Lisp/vf_spec.lsp`, beide muessen dieselbe Tokenfolge liefern. Der Rundlauf `journal_aus_spec(spec_aus_journal(tok)) == tok` laeuft in `tests/test_vf_spec.py` gegen die 5 echten HundM-Ketten und beweist, dass die Spec das Journal verlustfrei abbildet. Schreibt das flache Spec-JSON (vom LISP-Parser lesbar). Objekte der Ziel-Datei, die keine Kette beschreiben (von Hand ergaenzte Anlagenteile mit `function`, z.B. Kreisel), werden beim Neuschreiben unveraendert ans Dateiende uebernommen - sonst waeren sie beim naechsten Lauf weg. Aufruf: `python vf_spec_export.py <protokoll.json> <spec.json>` — erzeugt `tests/testdata/hundm05.json` (Spec, Eingabe fuer `TEST_HUNDM05`/`VF_SPEC_BAU`) aus `tests/testdata/hm_recformat.json` (Aufzeichnung) |
|
||||
| `dxf_anlage_export.py` | Gegenstueck zum Scanner: liest eine mit unseren Makros GEBAUTE (und von Hand nachbearbeitete) Anlage aus der Zeichnung zurueck in Nachbau-Testdaten - je Wrapper genau die Parameter, die auch dessen Edit-Befehl liest (KREISEL_n: Einfuegepunkt, `abstand` exakt aus der Blockdefinition, `drehrichtung` aus DREHRICHTUNG; GF_n: SSG_GF_EDIT + SEITE_AS/ES, endet die GF auf einer Kreisel-Kette, wird dessen Hoehe `hoehe_ende_mm`; VF_n `standard`/`etage`: mubea-Schema wie `vfs-edit-basis-lesen`; VF_n `linienzug`: Journal UNVERAENDERT als `"typ": "linienzug_journal"` - bewusst keine Spec, weil der Bau-Dialog neuer ist als die Spec-Grammatik; uebrige Bloecke als Einzel-Insert ohne `_2D`/`_3D`-Suffix). Reihenfolge Kreisel, VF, GF, Einzelbloecke (VF vor GF wie mubea). Aufruf: `python dxf_anlage_export.py <dxf> <output.json> [--projekt NAME]` — erzeugt `tests/testdata/dematic_arvato.json` aus `Dematic_TST.dxf`. Test `tests/test_dxf_anlage_export.py` |
|
||||
| `lager_yaml_export.py` | Lagerplanung: `<dwg>_lager_raw.json` (LAGER_EXPORT) -> `<dwg>_drawing.yaml` (Overlay im Schema der RFQ-Hand-YAML, nur Zeichnungsfelder, plus `_provenance`/`_conflicts`/`_warnings`) und optional `--nachweis` HTML. `--hand <yaml>` gleicht ab (Hand gewinnt; Konflikte bei > 1 % bzw. 0,005). Aggregiert nur, Regeln leben in LISP. Braucht `pyyaml`. Test `tests/test_lager_yaml.py`. Aufruf: `python lager_yaml_export.py <raw.json> <out.yaml> [--hand ...] [--nachweis ...]` |
|
||||
| `dxf_scan_components.py` | Erkennt ILS-/Omniflo-Komponenten in einer **fremden** Projektzeichnung (ohne unsere Wrapper-Bloecke) und schreibt sie im JSON-Schema aus `tests/testdata/object_data.md` — Grundlage fuer Nachbau-Testfaelle wie `tests/testdata/mubea.json`. Liest binaere DXF im GB-Bereich streamend per mmap (ezdxf-DOM waere zu gross), loest INSERTs inkl. OCS/Extrusionsrichtung rekursiv in Weltkoordinaten auf, paart AN8/SP8 zu Kreiseln und Antrieb/Umlenkung zu Foerderern. Gefaellestrecken, die als 3D-LINE auf einem Staustrecken-Layer gezeichnet sind (`GF_LINIE_LAYER`, z.B. `6-SP`), werden in einem zweiten Lesedurchgang zu Modus-1-Eintraegen: Start/Ende werden auf die Ketten der anschliessenden Kreisel verlaengert (gezeichnet ist nur die Staustrecke; `deltaL` reicht von AS- bis ES-Ursprung), AS-Seite aus dem Ausschleuselement am oberen Ende; dieses und Separatoren auf der Achse entfallen als Einzel-Insert (die GF baut beide selbst). Sitzt der AS am UNTEREN Ende, ist es ein Steigfoerderer und wird nur gemeldet (`gf_eintraege_aus_linien`, Test `tests/test_dxf_scan_gf.py`). `--ohne-hoehen` setzt alle Z auf 0, `--kreisel-hoehe X Y Z` gibt einem Kreisel seine Hoehe - die daran haengenden GF bekommen daraus `start_mm.z`/`hoehe_ende_mm`, den Winkel rechnet der Treiber (`dematic_arvato:gf-geometrie`: atan ueber die HORIZONTALE Laenge, ES-Laenge UND -Abfall bei der Einlaufneigung gemessen und iteriert, Staustrecke daraus - die flache ES-Laenge liess steile GF ~144 mm vor der Kette enden - NICHT `gf-winkel-berechnen`, dessen asin bei steilen GF wie im Showroom ~50 statt ~37 Grad liefert; `dematic_arvato:gf-endhoehe-pruefen` meldet `warnung` bei > 5 mm Abweichung von HOEHE_BIS). Flache 2D-Plaene: `--flach` (waagrechte Staustrecke mit AS an genau einem Ende = GF, zerstueckelte Linien werden vereint, ES am unteren Ende wird verbraucht, AS/ES-Seite ohne Namensangabe aus der Lage zur Fahrtrichtung), `--kreisel-achse X1 Y1 X2 Y2` (Kreisel ohne AN8/SP8), Einzelteile auf einer Kreisel-Kette erben dessen Anwender-Hoehe (`sensor_hoehen_von_kreiseln`). Kreisel-Paarung mit Tausch-Nachbesserung auf minimale Abstandssumme (zwei Kreisel auf einer Achse). Genutzt fuer `tests/testdata/showroom_ils.json` (`TEST_SHOWROOM_ILS`). Aufruf: `python dxf_scan_components.py <dxf> <data_dir> <output.json> [--fenster X0 Y0 X1 Y1]` — ohne `--fenster` liefert eine Anlagenzeichnung leicht ueber 1300 Eintraege, zuviel fuer einen Testlauf |
|
||||
| `dxf_scan_components.py` | Erkennt ILS-/Omniflo-Komponenten in einer **fremden** Projektzeichnung (ohne unsere Wrapper-Bloecke) und schreibt sie im JSON-Schema aus `doc/json-input-lisp.md` (Nachfolger des geloeschten `tests/testdata/object_data.md`) — Grundlage fuer Nachbau-Testfaelle wie `tests/testdata/mubea.json`. Liest binaere DXF im GB-Bereich streamend per mmap (ezdxf-DOM waere zu gross), loest INSERTs inkl. OCS/Extrusionsrichtung rekursiv in Weltkoordinaten auf, paart AN8/SP8 zu Kreiseln und Antrieb/Umlenkung zu Foerderern. Gefaellestrecken, die als 3D-LINE auf einem Staustrecken-Layer gezeichnet sind (`GF_LINIE_LAYER`, z.B. `6-SP`), werden in einem zweiten Lesedurchgang zu Modus-1-Eintraegen: Start/Ende werden auf die Ketten der anschliessenden Kreisel verlaengert (gezeichnet ist nur die Staustrecke; `deltaL` reicht von AS- bis ES-Ursprung), AS-Seite aus dem Ausschleuselement am oberen Ende; dieses und Separatoren auf der Achse entfallen als Einzel-Insert (die GF baut beide selbst). Sitzt der AS am UNTEREN Ende, ist es ein Steigfoerderer und wird nur gemeldet (`gf_eintraege_aus_linien`, Test `tests/test_dxf_scan_gf.py`). `--ohne-hoehen` setzt alle Z auf 0, `--kreisel-hoehe X Y Z` gibt einem Kreisel seine Hoehe - die daran haengenden GF bekommen daraus `start_mm.z`/`hoehe_ende_mm`, den Winkel rechnet der Treiber (`dematic_arvato:gf-geometrie`: atan ueber die HORIZONTALE Laenge, ES-Laenge UND -Abfall bei der Einlaufneigung gemessen und iteriert, Staustrecke daraus - die flache ES-Laenge liess steile GF ~144 mm vor der Kette enden - NICHT `gf-winkel-berechnen`, dessen asin bei steilen GF wie im Showroom ~50 statt ~37 Grad liefert; `dematic_arvato:gf-endhoehe-pruefen` meldet `warnung` bei > 5 mm Abweichung von HOEHE_BIS). Flache 2D-Plaene: `--flach` (waagrechte Staustrecke mit AS an genau einem Ende = GF, zerstueckelte Linien werden vereint, ES am unteren Ende wird verbraucht, AS/ES-Seite ohne Namensangabe aus der Lage zur Fahrtrichtung), `--kreisel-achse X1 Y1 X2 Y2` (Kreisel ohne AN8/SP8), Einzelteile auf einer Kreisel-Kette erben dessen Anwender-Hoehe (`sensor_hoehen_von_kreiseln`). Kreisel-Paarung mit Tausch-Nachbesserung auf minimale Abstandssumme (zwei Kreisel auf einer Achse). Genutzt fuer `tests/testdata/showroom_ils.json` (`TEST_SHOWROOM_ILS`). Aufruf: `python dxf_scan_components.py <dxf> <data_dir> <output.json> [--fenster X0 Y0 X1 Y1]` — ohne `--fenster` liefert eine Anlagenzeichnung leicht ueber 1300 Eintraege, zuviel fuer einen Testlauf |
|
||||
|
||||
### Entwickler-Tools (`lib/`) - kein ezdxf, reine Text-/AutoLISP-Verarbeitung
|
||||
|
||||
@@ -225,7 +237,7 @@ Abhaengigkeiten: `ezdxf`, Standard-Library. Benoetigen Umgebungsvariablen (`DXFM
|
||||
## Entwicklungsstand
|
||||
|
||||
Siehe `doc/plan/Entwicklungsplan.md` fuer Meilensteinplanung und Aufwandsschaetzung.
|
||||
Fertig (DONE): ILS Kreisel, ILS Eckrad, ILS Variofoerderer, ILS BTMT Be-/Entladung (Einfuegen), Omniflo Boegen, Omniflo Weichen.
|
||||
Fertig (DONE, Stand 2026-10-26): ILS Kreisel, ILS Eckrad, ILS Variofoerderer (Standard/Etage/Linienzug), ILS Gefaellestrecke, ILS BTMT Be-/Entladung, Geruest (Rohrabhaenger, Saeulen, Wandbefestigung, Traeger), Omniflo Boegen, Weichen, Verbinder, Fahrstrecke, Ladeschleifen, Kettenfoerderer, CSV-/Sivas-Export. Offen u.a.: Gattertraeger, Omniflo-Boegen fuer Weichen (`OMNI_APBW_*`, Dummy), eigenstaendige ILS-Weichen-/Kurvengeometrie. Alle offenen Punkte: `doc/todo.md` (Detail-Fahrplaene in `doc/todo/`).
|
||||
|
||||
## Debug
|
||||
Wenn Werte für das Debug in der Bricscad Konsole ausgegeben werden z.B. mit princ, soll der Benutzer dazu ermuntert werden, statt dessen die Lisp dbg Routinen zu verwenden, welche dann eine .dbg file im log folder erzeugen. Diese können ja über eine zentrale globale Sammlung von Schalter an und abgeschaltet werden, so dass die Files per default auch nicht geschrieben werden, nur wenn der passende Schalter auf 1 gesetzt wird. Damit können debug aufrufe auch im Code verbleiben.
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
;; ============================================================
|
||||
;; JAM_EDIT.LSP - Staubereich (JAM_AREA) bearbeiten
|
||||
;;
|
||||
;; Die Staubereiche zeichnet sps_skel (lib/tro_annotate.py --anlage) als
|
||||
;; Block JAM_AREA: ein Rechteck, darin der Name Jam<NNNN>_<k>. Attribute
|
||||
;; NAME sichtbar - Jam0054_3
|
||||
;; CONVEYOR, NUMBER unsichtbar - Foerderer NNNN und laufende Nummer k
|
||||
;; TRO, ENTRY unsichtbar - TRO und Eingang, in den er fuehrt
|
||||
;; (stabiler Schluessel, nicht aendern)
|
||||
;; AREA unsichtbar - Kennung der TRO-JSON (J0039)
|
||||
;; AUTO unsichtbar - von sps_skel abgeleitete Nummer NNNN_k
|
||||
;;
|
||||
;; Aufruf JAM_EDIT:
|
||||
;; - Doppelklick auf den Staubereich -> ***DOUBLECLICK [INSERT] -> SSG_BLOCKEDIT
|
||||
;; - EATTEDIT -> c:EATTEDIT -> SSG_BLOCKEDIT
|
||||
;; - direkt: JAM_EDIT
|
||||
;; Der Dispatcher SSG_BLOCKEDIT (SSG_LIB_Commands.lsp) leitet Blocknamen
|
||||
;; "JAM_*" hierher.
|
||||
;;
|
||||
;; Der Dialog aendert nur die Zeichnung. In die SCL kommt die Aenderung mit
|
||||
;; tro_annotate.bat --file <csv> --read-jams (-> cfg/<csv>_jam_names.ini)
|
||||
;; scl_skeleton.bat --json <csv>_anlage.json --templates
|
||||
;;
|
||||
;; Setzt ssg_core.lsp (ssg-start/ssg-end, ssg-attrib-*) und ssg_lang.lsp voraus.
|
||||
;; ============================================================
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; Nur Ziffern, nicht leer
|
||||
;; ------------------------------------------------------------
|
||||
(defun jam-ziffern-p (s)
|
||||
(and s (/= s "") (not (wcmatch s "*[~0-9]*")))
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; Name aus Foerderer und Nummer: "0054" "3" -> "Jam0054_3"
|
||||
;; ------------------------------------------------------------
|
||||
(defun jam-name (foerderer nummer)
|
||||
(strcat "Jam" foerderer "_" nummer)
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; Gibt es den Namen schon an einem anderen Staubereich?
|
||||
;; Liefert die Kennung (AREA) des anderen Blocks oder nil.
|
||||
;; ------------------------------------------------------------
|
||||
(defun jam-name-belegt (name eigener / ss i ent attribs treffer)
|
||||
(setq treffer nil)
|
||||
(if (setq ss (ssget "_X" (list '(0 . "INSERT") '(2 . "JAM_*"))))
|
||||
(progn
|
||||
(setq i 0)
|
||||
(while (and (null treffer) (setq ent (ssname ss i)))
|
||||
(if (not (eq ent eigener))
|
||||
(progn
|
||||
(setq attribs (ssg-attrib-read ent))
|
||||
(if (= (strcase (cond ((cdr (assoc "NAME" attribs))) (""))) (strcase name))
|
||||
(setq treffer (cond ((cdr (assoc "AREA" attribs))) ("?")))
|
||||
)
|
||||
)
|
||||
)
|
||||
(setq i (1+ i))
|
||||
)
|
||||
)
|
||||
)
|
||||
treffer
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; C:JAM_EDIT - Dialog fuer einen Staubereich
|
||||
;; ------------------------------------------------------------
|
||||
(defun c:JAM_EDIT ( / ss ent ed bname attribs
|
||||
alt-conv alt-nr auto tro entry area
|
||||
neu-conv neu-nr auto-conv auto-nr pos
|
||||
dcl-pfad dat ergebnis name andere)
|
||||
|
||||
;; Implied Selection VOR ssg-start pruefen (ssg-start hebt Selektion auf)
|
||||
(setq ss (ssget "I"))
|
||||
(if (and ss (= (sslength ss) 1)
|
||||
(= (cdr (assoc 0 (entget (ssname ss 0)))) "INSERT"))
|
||||
(setq ent (ssname ss 0))
|
||||
)
|
||||
|
||||
(ssg-start "JAM_EDIT" nil)
|
||||
|
||||
(if (null ent)
|
||||
(progn
|
||||
(princ (ssg-text "cmd-block-auswaehlen"))
|
||||
(setq ss (ssget ":S" '((0 . "INSERT"))))
|
||||
(if ss (setq ent (ssname ss 0)))
|
||||
)
|
||||
)
|
||||
(if (null ent)
|
||||
(progn (princ (ssg-text "cmd-kein-block-ausgewaehlt")) (ssg-end) (exit))
|
||||
)
|
||||
|
||||
(setq ed (entget ent)
|
||||
bname (cdr (assoc 2 ed)))
|
||||
(if (not (wcmatch bname "JAM_*"))
|
||||
(progn
|
||||
(alert (ssg-textf "jam-edit-kein-jam" (list bname)))
|
||||
(ssg-end)
|
||||
(exit)
|
||||
)
|
||||
)
|
||||
|
||||
;; --- aktuelle Attribute lesen ----------------------------------------
|
||||
(setq attribs (ssg-attrib-read ent)
|
||||
alt-conv (cond ((cdr (assoc "CONVEYOR" attribs))) (""))
|
||||
alt-nr (cond ((cdr (assoc "NUMBER" attribs))) (""))
|
||||
auto (cond ((cdr (assoc "AUTO" attribs))) (""))
|
||||
tro (cond ((cdr (assoc "TRO" attribs))) ("?"))
|
||||
entry (cond ((cdr (assoc "ENTRY" attribs))) ("?"))
|
||||
area (cond ((cdr (assoc "AREA" attribs))) ("?")))
|
||||
|
||||
;; AUTO "0054_3" -> Foerderer "0054", Nummer "3"
|
||||
(setq auto-conv "" auto-nr "")
|
||||
(if (setq pos (vl-string-search "_" auto))
|
||||
(setq auto-conv (substr auto 1 pos)
|
||||
auto-nr (substr auto (+ pos 2)))
|
||||
)
|
||||
|
||||
;; --- Dialog -----------------------------------------------------------
|
||||
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/jam_edit.dcl"))
|
||||
(setq dat (load_dialog dcl-pfad))
|
||||
(if (not (new_dialog "jam_edit" dat))
|
||||
(progn
|
||||
(alert (ssg-textf "jam-edit-dialog-fehlt" (list dcl-pfad)))
|
||||
(ssg-end)
|
||||
(exit)
|
||||
)
|
||||
)
|
||||
|
||||
(set_tile "bereich" (ssg-textf "jam-edit-bereich" (list area tro entry)))
|
||||
(set_tile "auto" (ssg-textf "jam-edit-auto"
|
||||
(list (if (= auto "") "-" (jam-name auto-conv auto-nr)))))
|
||||
(set_tile "hinweis" (ssg-text "jam-edit-hinweis"))
|
||||
(set_tile "conveyor" alt-conv)
|
||||
(set_tile "number" alt-nr)
|
||||
(if (= auto "") (mode_tile "reset" 1))
|
||||
|
||||
(setq neu-conv alt-conv neu-nr alt-nr)
|
||||
(action_tile "reset"
|
||||
"(set_tile \"conveyor\" auto-conv) (set_tile \"number\" auto-nr)")
|
||||
(action_tile "accept"
|
||||
(strcat "(setq neu-conv (vl-string-trim \" \" (get_tile \"conveyor\"))"
|
||||
" neu-nr (vl-string-trim \" \" (get_tile \"number\")))"
|
||||
"(done_dialog 1)"))
|
||||
(action_tile "cancel" "(done_dialog 0)")
|
||||
|
||||
(setq ergebnis (start_dialog))
|
||||
(unload_dialog dat)
|
||||
|
||||
;; --- pruefen und zurueckschreiben -------------------------------------
|
||||
(if (= ergebnis 1)
|
||||
(cond
|
||||
((not (and (jam-ziffern-p neu-conv) (= (strlen neu-conv) 4)))
|
||||
(alert (ssg-text "jam-edit-foerderer-ungueltig")))
|
||||
((not (and (jam-ziffern-p neu-nr) (> (atoi neu-nr) 0)))
|
||||
(alert (ssg-text "jam-edit-nummer-ungueltig")))
|
||||
(t
|
||||
(setq neu-nr (itoa (atoi neu-nr))
|
||||
name (jam-name neu-conv neu-nr))
|
||||
(ssg-attrib-set-on ent (list (cons "CONVEYOR" neu-conv)
|
||||
(cons "NUMBER" neu-nr)
|
||||
(cons "NAME" name)))
|
||||
(entupd ent)
|
||||
(princ (ssg-textf "jam-edit-gespeichert" (list name area)))
|
||||
(if (setq andere (jam-name-belegt name ent))
|
||||
(princ (ssg-textf "jam-edit-doppelt" (list name andere)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(ssg-end)
|
||||
(princ)
|
||||
)
|
||||
|
||||
|
||||
(prompt "\nJam_Edit.lsp geladen - Befehl: JAM_EDIT")
|
||||
(princ)
|
||||
File diff suppressed because it is too large.
Load diff
+143
-91
@@ -420,6 +420,18 @@
|
||||
att-entity att-data att-tag new-value
|
||||
beforeAtt)
|
||||
|
||||
;; Mindestabstand: unterhalb des Durchmessers wuerden sich die Endkreise
|
||||
;; (AN8/SP8) beruehren bzw. ueberschneiden - harte Sperre fuer alle Aufrufer
|
||||
;; (Insert/Connect/Redraw/Edit/Script), da draw-module der einzige
|
||||
;; gemeinsame Zeichenpfad ist.
|
||||
(if (< abstand *kreisel-durchmesser*)
|
||||
(progn
|
||||
(ssg-emsg (ssg-textf "kreisel-emsg-abstand-zu-klein"
|
||||
(list (rtos abstand 2 0) (rtos *kreisel-durchmesser* 2 0))))
|
||||
(exit)
|
||||
)
|
||||
)
|
||||
|
||||
;; Attribute vorbereiten
|
||||
(setq attribs (ssg-attrib-merge attribs *kreisel-attrib-defs*))
|
||||
(setq attribs (subst (cons "ABSTAND" (rtos abstand 2 0))
|
||||
@@ -695,11 +707,23 @@
|
||||
)
|
||||
|
||||
;; 2. Abstand (Tangentenlaenge) - Linie gibt auch den Winkel vor
|
||||
(setq p2 (getpoint pt (ssg-textf "kreisel-prompt-abstand"
|
||||
(list (rtos *kreisel-default-laenge* 2 0)))))
|
||||
(setq erg (kreisel-insert-richtung pt p2 *kreisel-default-laenge*)
|
||||
abstand (car erg)
|
||||
rotation (cadr erg))
|
||||
;; Mindestabstand = Kreisel-Durchmesser (sonst beruehren/ueberschneiden
|
||||
;; sich die Endkreise) - bei Unterschreitung erneut abfragen.
|
||||
(setq abstand nil)
|
||||
(while (null abstand)
|
||||
(setq p2 (getpoint pt (ssg-textf "kreisel-prompt-abstand"
|
||||
(list (rtos *kreisel-default-laenge* 2 0)))))
|
||||
(setq erg (kreisel-insert-richtung pt p2 *kreisel-default-laenge*)
|
||||
abstand (car erg)
|
||||
rotation (cadr erg))
|
||||
(if (< abstand *kreisel-durchmesser*)
|
||||
(progn
|
||||
(ssg-emsg (ssg-textf "kreisel-emsg-abstand-zu-klein"
|
||||
(list (rtos abstand 2 0) (rtos *kreisel-durchmesser* 2 0))))
|
||||
(setq abstand nil)
|
||||
)
|
||||
)
|
||||
)
|
||||
(princ (ssg-textf "kreisel-abstand-ausgabe" (list (rtos abstand 2 0))))
|
||||
|
||||
;; 3. Hoehe (Z-Koordinate)
|
||||
@@ -747,24 +771,29 @@
|
||||
(progn (ssg-end) (princ (ssg-text "kreisel-abgebrochen")) (princ) (exit))
|
||||
)
|
||||
|
||||
;; 2. Endpunkt (aeusserster Punkt SP-Seite) mit Gummiband
|
||||
(setq ptEnd (getpoint ptStart (ssg-text "kreisel-prompt-endpunkt")))
|
||||
(if (null ptEnd)
|
||||
(progn (ssg-end) (princ (ssg-text "kreisel-abgebrochen")) (princ) (exit))
|
||||
)
|
||||
;; 2. Endpunkt (aeusserster Punkt SP-Seite) mit Gummiband - der Abstand
|
||||
;; (Kreismitten-Tangentenlaenge = dist - Durchmesser) muss mindestens dem
|
||||
;; Durchmesser entsprechen, sonst beruehren/ueberschneiden sich die
|
||||
;; Endkreise; bei Unterschreitung erneut abfragen statt abzubrechen.
|
||||
(setq abstand nil)
|
||||
(while (null abstand)
|
||||
(setq ptEnd (getpoint ptStart (ssg-text "kreisel-prompt-endpunkt")))
|
||||
(if (null ptEnd)
|
||||
(progn (ssg-end) (princ (ssg-text "kreisel-abgebrochen")) (princ) (exit))
|
||||
)
|
||||
|
||||
;; 3. Geometrie berechnen
|
||||
(setq dx (- (car ptEnd) (car ptStart))
|
||||
dy (- (cadr ptEnd) (cadr ptStart)))
|
||||
(setq dist (sqrt (+ (* dx dx) (* dy dy))))
|
||||
(setq abstand (- dist *kreisel-durchmesser*))
|
||||
;; 3. Geometrie berechnen
|
||||
(setq dx (- (car ptEnd) (car ptStart))
|
||||
dy (- (cadr ptEnd) (cadr ptStart)))
|
||||
(setq dist (sqrt (+ (* dx dx) (* dy dy))))
|
||||
(setq abstand (- dist *kreisel-durchmesser*))
|
||||
|
||||
(if (<= abstand 0.0)
|
||||
(progn
|
||||
(ssg-emsg (ssg-textf "kreisel-emsg-distanz-klein"
|
||||
(list (rtos dist 2 0) (rtos *kreisel-durchmesser* 2 0))))
|
||||
(ssg-end)
|
||||
(exit)
|
||||
(if (< abstand *kreisel-durchmesser*)
|
||||
(progn
|
||||
(ssg-emsg (ssg-textf "kreisel-emsg-distanz-klein"
|
||||
(list (rtos dist 2 0) (rtos (* 2.0 *kreisel-durchmesser*) 2 0))))
|
||||
(setq abstand nil)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -883,7 +912,7 @@
|
||||
;; geaendertem) Abstand neu. Alle Attribute bleiben
|
||||
;; erhalten.
|
||||
;; -----------------------------------------------
|
||||
(defun c:KreiselRedraw ( / sel ent ed attribs basePoint rotation newAbstand)
|
||||
(defun c:KreiselRedraw ( / sel ent ed attribs basePoint rotation newAbstand gueltig)
|
||||
|
||||
(ssg-start (ssg-text "kreisel-start-redraw") '(("CECOLOR")))
|
||||
|
||||
@@ -910,11 +939,20 @@
|
||||
(cdr (assoc "HOEHE" attribs))
|
||||
(cdr (assoc "KREISELART" attribs)))))
|
||||
|
||||
;; 3. Neuen Abstand abfragen (Enter = beibehalten)
|
||||
(initget 6)
|
||||
(setq newAbstand (getdist (ssg-textf "kreisel-prompt-neuer-abstand" (list (cdr (assoc "ABSTAND" attribs))))))
|
||||
(if (null newAbstand)
|
||||
(setq newAbstand (atof (cdr (assoc "ABSTAND" attribs))))
|
||||
;; 3. Neuen Abstand abfragen (Enter = beibehalten); Mindestabstand =
|
||||
;; Kreisel-Durchmesser, sonst beruehren/ueberschneiden sich die Endkreise.
|
||||
(setq newAbstand nil gueltig nil)
|
||||
(while (not gueltig)
|
||||
(initget 6)
|
||||
(setq newAbstand (getdist (ssg-textf "kreisel-prompt-neuer-abstand" (list (cdr (assoc "ABSTAND" attribs))))))
|
||||
(if (null newAbstand)
|
||||
(setq newAbstand (atof (cdr (assoc "ABSTAND" attribs))))
|
||||
)
|
||||
(if (< newAbstand *kreisel-durchmesser*)
|
||||
(ssg-emsg (ssg-textf "kreisel-emsg-abstand-zu-klein"
|
||||
(list (rtos newAbstand 2 0) (rtos *kreisel-durchmesser* 2 0))))
|
||||
(setq gueltig T)
|
||||
)
|
||||
)
|
||||
;; NEU - Neue Höhe abfragen:
|
||||
(setq newHoehe (getreal (ssg-textf "kreisel-prompt-neue-hoehe" (list (cdr (assoc "HOEHE" attribs))))))
|
||||
@@ -991,7 +1029,7 @@
|
||||
;; 3. Bei OK: Block loeschen und mit neuen Werten neu zeichnen
|
||||
;; -----------------------------------------------
|
||||
(defun c:KreiselEdit ( / sel ss ent ed attribs basePoint rotation
|
||||
dcl-pfad dat ergebnis
|
||||
dcl-pfad dat ergebnis fertig
|
||||
dlg-name dlg-abstand dlg-hoehe dlg-ausrichtung
|
||||
dlg-drehrichtung dlg-kreiselart dlg-geruest-einzelmodul
|
||||
dlg-geruest-typ
|
||||
@@ -1049,73 +1087,87 @@
|
||||
(princ (ssg-textf "kreisel-edit-bestehend"
|
||||
(list (cdr (assoc "ABSTAND" attribs)) (rtos rotation 2 1) (cdr (assoc "KREISELART" attribs)))))
|
||||
|
||||
;; 3. DCL-Dialog laden
|
||||
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/kreisel_edit.dcl"))
|
||||
(setq dat (load_dialog dcl-pfad))
|
||||
(if (not (new_dialog "kreisel_edit" dat))
|
||||
(progn (alert (ssg-textf "kreisel-edit-dialog-fehlt" (list dcl-pfad))) (ssg-end) (exit))
|
||||
)
|
||||
;; 3. DCL-Dialog laden; bei zu kleinem Abstand (< Kreisel-Durchmesser,
|
||||
;; sonst beruehren/ueberschneiden sich die Endkreise) erneut anzeigen,
|
||||
;; statt den fehlerhaften Wert zu uebernehmen (Projektmuster wie GERUEST).
|
||||
(setq dlg-abstand (cdr (assoc "ABSTAND" attribs)))
|
||||
(setq fertig nil)
|
||||
(while (not fertig)
|
||||
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/kreisel_edit.dcl"))
|
||||
(setq dat (load_dialog dcl-pfad))
|
||||
(if (not (new_dialog "kreisel_edit" dat))
|
||||
(progn (alert (ssg-textf "kreisel-edit-dialog-fehlt" (list dcl-pfad))) (ssg-end) (exit))
|
||||
)
|
||||
|
||||
;; Ausrichtungs-Labels fuer popup_list aufbauen
|
||||
(setq ausrichtLabels "")
|
||||
(foreach entry *kreisel-ausrichtungen*
|
||||
(if (= ausrichtLabels "")
|
||||
(setq ausrichtLabels (car entry))
|
||||
(setq ausrichtLabels (strcat ausrichtLabels "\n" (car entry)))
|
||||
;; Ausrichtungs-Labels fuer popup_list aufbauen
|
||||
(setq ausrichtLabels "")
|
||||
(foreach entry *kreisel-ausrichtungen*
|
||||
(if (= ausrichtLabels "")
|
||||
(setq ausrichtLabels (car entry))
|
||||
(setq ausrichtLabels (strcat ausrichtLabels "\n" (car entry)))
|
||||
)
|
||||
)
|
||||
|
||||
;; Tiles initialisieren (Abstand aus vorherigem Versuch uebernehmen)
|
||||
(set_tile "name" (cdr (assoc "Bezeichnung" attribs)))
|
||||
(set_tile "abstand" dlg-abstand)
|
||||
(set_tile "hoehe" (cdr (assoc "HOEHE" attribs)))
|
||||
|
||||
(start_list "ausrichtung")
|
||||
(foreach entry *kreisel-ausrichtungen*
|
||||
(add_list (car entry))
|
||||
)
|
||||
(end_list)
|
||||
(set_tile "ausrichtung" (itoa (kreisel-rotation-to-idx rotation)))
|
||||
|
||||
(start_list "drehrichtung")
|
||||
(add_list "UZS")
|
||||
(add_list "GUZ")
|
||||
(end_list)
|
||||
(set_tile "drehrichtung" (if (equal (cdr (assoc "DREHRICHTUNG" attribs)) "GUZ") "1" "0"))
|
||||
|
||||
(start_list "kreiselart")
|
||||
(add_list "STANDARD")
|
||||
(add_list "PIN")
|
||||
(end_list)
|
||||
(set_tile "kreiselart" (if (equal (cdr (assoc "KREISELART" attribs)) "PIN") "1" "0"))
|
||||
|
||||
(set_tile "geruest_einzelmodul"
|
||||
(if (equal (cdr (assoc "GERUEST_EINZELMODUL" attribs)) "1") "1" "0"))
|
||||
|
||||
(start_list "geruest_typ")
|
||||
(foreach opt *ssg-geruest-optionen* (add_list opt))
|
||||
(end_list)
|
||||
(set_tile "geruest_typ" (itoa (ssg-geruest-typ-to-idx (cdr (assoc "GERUEST_TYP" attribs)))))
|
||||
|
||||
;; Actions
|
||||
(action_tile "accept"
|
||||
(strcat
|
||||
"(setq dlg-name (get_tile \"name\"))"
|
||||
"(setq dlg-abstand (get_tile \"abstand\"))"
|
||||
"(setq dlg-hoehe (get_tile \"hoehe\"))"
|
||||
"(setq dlg-ausrichtung (get_tile \"ausrichtung\"))"
|
||||
"(setq dlg-drehrichtung (get_tile \"drehrichtung\"))"
|
||||
"(setq dlg-kreiselart (get_tile \"kreiselart\"))"
|
||||
"(setq dlg-geruest-einzelmodul (get_tile \"geruest_einzelmodul\"))"
|
||||
"(setq dlg-geruest-typ (get_tile \"geruest_typ\"))"
|
||||
"(done_dialog 1)"
|
||||
)
|
||||
)
|
||||
(action_tile "cancel" "(done_dialog 0)")
|
||||
|
||||
(setq ergebnis (start_dialog))
|
||||
(unload_dialog dat)
|
||||
|
||||
(cond
|
||||
((/= ergebnis 1) (setq fertig T))
|
||||
((< (atof dlg-abstand) *kreisel-durchmesser*)
|
||||
(ssg-emsg (ssg-textf "kreisel-emsg-abstand-zu-klein"
|
||||
(list (rtos (atof dlg-abstand) 2 0) (rtos *kreisel-durchmesser* 2 0)))))
|
||||
(t (setq fertig T))
|
||||
)
|
||||
)
|
||||
|
||||
;; Tiles initialisieren
|
||||
(set_tile "name" (cdr (assoc "Bezeichnung" attribs)))
|
||||
(set_tile "abstand" (cdr (assoc "ABSTAND" attribs)))
|
||||
(set_tile "hoehe" (cdr (assoc "HOEHE" attribs)))
|
||||
|
||||
(start_list "ausrichtung")
|
||||
(foreach entry *kreisel-ausrichtungen*
|
||||
(add_list (car entry))
|
||||
)
|
||||
(end_list)
|
||||
(set_tile "ausrichtung" (itoa (kreisel-rotation-to-idx rotation)))
|
||||
|
||||
(start_list "drehrichtung")
|
||||
(add_list "UZS")
|
||||
(add_list "GUZ")
|
||||
(end_list)
|
||||
(set_tile "drehrichtung" (if (equal (cdr (assoc "DREHRICHTUNG" attribs)) "GUZ") "1" "0"))
|
||||
|
||||
(start_list "kreiselart")
|
||||
(add_list "STANDARD")
|
||||
(add_list "PIN")
|
||||
(end_list)
|
||||
(set_tile "kreiselart" (if (equal (cdr (assoc "KREISELART" attribs)) "PIN") "1" "0"))
|
||||
|
||||
(set_tile "geruest_einzelmodul"
|
||||
(if (equal (cdr (assoc "GERUEST_EINZELMODUL" attribs)) "1") "1" "0"))
|
||||
|
||||
(start_list "geruest_typ")
|
||||
(foreach opt *ssg-geruest-optionen* (add_list opt))
|
||||
(end_list)
|
||||
(set_tile "geruest_typ" (itoa (ssg-geruest-typ-to-idx (cdr (assoc "GERUEST_TYP" attribs)))))
|
||||
|
||||
;; Actions
|
||||
(action_tile "accept"
|
||||
(strcat
|
||||
"(setq dlg-name (get_tile \"name\"))"
|
||||
"(setq dlg-abstand (get_tile \"abstand\"))"
|
||||
"(setq dlg-hoehe (get_tile \"hoehe\"))"
|
||||
"(setq dlg-ausrichtung (get_tile \"ausrichtung\"))"
|
||||
"(setq dlg-drehrichtung (get_tile \"drehrichtung\"))"
|
||||
"(setq dlg-kreiselart (get_tile \"kreiselart\"))"
|
||||
"(setq dlg-geruest-einzelmodul (get_tile \"geruest_einzelmodul\"))"
|
||||
"(setq dlg-geruest-typ (get_tile \"geruest_typ\"))"
|
||||
"(done_dialog 1)"
|
||||
)
|
||||
)
|
||||
(action_tile "cancel" "(done_dialog 0)")
|
||||
|
||||
(setq ergebnis (start_dialog))
|
||||
(unload_dialog dat)
|
||||
|
||||
;; 4. Bei OK: Block loeschen und neu zeichnen
|
||||
(if (= ergebnis 1)
|
||||
(progn
|
||||
|
||||
@@ -1538,10 +1538,12 @@
|
||||
)
|
||||
|
||||
;; --- Omniflo / KettenFoerderer ---
|
||||
(defun c:OMNI_KettenFoerderer ()
|
||||
(princ "\n[DUMMY] KettenFoerderer")
|
||||
(princ)
|
||||
)
|
||||
;; Der Platzhalter c:OMNI_KettenFoerderer (reiner Dummy, gab nur "[DUMMY]
|
||||
;; KettenFoerderer" aus und war im Menue ausgegraut) wurde entfernt: der
|
||||
;; Kettenfoerderer ist seit 2026-10-22 als eigene Baugruppe umgesetzt, der
|
||||
;; Menueeintrag zeigt jetzt auf (ssg-ensure "KettenFoerderer") KETTENFOERDERER
|
||||
;; (Lisp/KettenFoerderer.lsp). Damit war der Dummy toter Code - auf ihn verwies
|
||||
;; nur noch der Menueeintrag selbst.
|
||||
|
||||
|
||||
;; --- Omniflo / Ladeschleifen ---
|
||||
|
||||
+89
-32
@@ -38,21 +38,22 @@ am Label-Anfang, bei Submenue-Schliessern hinter dem `<-` (`[<-~Label]`).
|
||||
|
||||
| Menuebereich | Eintraege | Definiert in |
|
||||
| --- | --- | --- |
|
||||
| Omniflo ▸ Anbaugruppen | `OMNI_KettenFoerderer` | `OmniModulInsert.lsp` |
|
||||
| Omniflo ▸ Boegen fuer Weichen | alle `OMNI_APBW_*` (14) | `OmniModulInsert.lsp` |
|
||||
| ILS ▸ Zusatzmodule/Kurven | `ILS_ETF_Etagenfoerderer`, `ILS_K{90,60,30}{L,R}{A,I}` (12), `ILS_Gefaellestrecke` | `SSG_LIB_Commands.lsp` |
|
||||
| Geruest | `GERUEST` (Gattertraeger-Platzhalter, derselbe Befehl wie Saeulen/Rohrabhaenger/Wandbefestigung) | `GeruestInsert.lsp` |
|
||||
|
||||
`OMNI_TEF_*` (UmlenkR/L, AntriebL/R, TEF Gerade) sind entgegen frueherem Stand
|
||||
**implementiert** (echtes `omni:insert-dxf`), nur `OMNI_KettenFoerderer` ist
|
||||
weiterhin Dummy.
|
||||
**implementiert** (echtes `omni:insert-dxf`). Der Menueeintrag KettenFoerderer ist
|
||||
ebenfalls aktiv (Modul `KettenFoerderer.lsp`, Beschreibung in `CLAUDE.md`).
|
||||
|
||||
Aktiv (implementiert) sind u.a.: Kreisel, Eckrad, VarioFoerderer (Standard/Etage/
|
||||
Linienzug), Gefaellestrecke, Geruest (Saeulen/Rohrabhaenger/Wandbefestigung/
|
||||
Rohr-Geruest-Traeger), TRO-Marker, Connections, BTMT Be-/Entladung, Scanner/
|
||||
Separator, Omniflo Boegen (APB)/TEF-Elemente/Aluprofil-Geraden (AP)/alle Weichen
|
||||
(W90/W45/WP/WK/WKomb)/Ladeschleifen, Export (Sivas/CSV), Werkzeuge (Block-/
|
||||
Text-Tools, Planquadrate) und die Tests.
|
||||
(W90/W45/WP/WK/WKomb)/Ladeschleifen/Schwenkschienen/Fahrstrecke, Kettenfoerderer,
|
||||
Export (Sivas/CSV), Werkzeuge (Block-/Text-Tools, Faehnchen + Stueckliste,
|
||||
DIN-Formate, Planquadrate) und die Tests. Die frueheren Dummy-Befehle fuer ILS-Kurven
|
||||
(`ILS_K*`), Etagenfoerderer (`ILS_ETF_*`) und `ILS_Gefaellestrecke` wurden samt
|
||||
Menueeintraegen entfernt.
|
||||
|
||||
---
|
||||
|
||||
@@ -383,6 +384,10 @@ Gefaellestrecke/`vf_core` geladen sein; Kern-Modul.
|
||||
| `extract-ks-from-block[-raw] name` | KS_EIN/KS_AUS-Punkte eines Blocks ermitteln (Cache `*ks-cache*`) |
|
||||
| `insert-block-by-ks name ks-nr pt` | Block anhand KS-Punkt einfuegen (nur Rz-Rotation) |
|
||||
| `insert-inclined-scaled-block` / `insert-rotated-block-with-ks` | Geneigten/rotierten Block mit KS-Offset einfuegen (Rz*Ry) |
|
||||
| `ks-xy-winkel ks-eintrag` | Richtung der X-Achse eines KS in der XY-Ebene (Grad); `nil` bei senkrechter Achse |
|
||||
| `ks-block-messen name` / `ks-versatz ks-data` | KS eines Blocks messen, ohne bleibende Einfuegung / Versatz KS_AUS-KS_EIN |
|
||||
| `insert-block-ks-skaliert name pt hz skala` | Wie `insert-block-by-ks`, zusaetzlich in X skaliert |
|
||||
| `insert-block-ks-matrix name pt R skala` | Einfuegen mit **freier 3x3-Rotationsmatrix** (`ks-rot-x/-y/-z`), z.B. fuer aufgerichtete Baugruppen |
|
||||
|
||||
---
|
||||
|
||||
@@ -578,9 +583,9 @@ umbiegen. Falls das bereits passiert ist, hilft nur ein manuelles
|
||||
|
||||
---
|
||||
|
||||
### `tests.lsp` – Testbefehle
|
||||
### `external_call.lsp` – Python-Aufruf testen
|
||||
|
||||
Testbefehle für die Python-Integration. Export-Funktionen wurden in `export.lsp` ausgelagert.
|
||||
Testbefehl für die Python-Integration (frueher `tests.lsp`). Export-Funktionen liegen in `export.lsp`.
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
| --- | --- |
|
||||
@@ -605,7 +610,7 @@ Verzeichnisstruktur: [`../tests/README.md`](../tests/README.md)):
|
||||
|
||||
Welche JSON-Angaben pro Element-Typ nötig sind (abgeleitet aus den
|
||||
Produktions-Routinen, nicht aus den Test-Wrappern), dokumentiert
|
||||
[`../tests/testdata/object_data.md`](../tests/testdata/object_data.md) –
|
||||
[`../doc/json-input-lisp.md`](../doc/json-input-lisp.md) (Nachfolger des geloeschten `tests/testdata/object_data.md`) –
|
||||
inkl. der Unterscheidung scriptbar vs. nur-interaktiv.
|
||||
|
||||
### LISP-Unit-Tests (`test_unit.lsp`)
|
||||
@@ -701,7 +706,7 @@ AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbind
|
||||
| Geraden | `OMNI_AP60`, `OMNI_AP110`, `OMNI_APG110` | Omniflo-Geradenstuecke |
|
||||
| Ladeschleifen | `OMNI_LADESCHLEIFE_AP110` | Ladeschleife aus `omniflo_ladeschleifen.json` ueber DCL-Dialog (`dcl/omniflo_ladeschleifen.dcl`) einfuegen; Daten per `ssg-json-laden` (Beschreibungen enthalten Kommas). Blockdatei `<Sivasnr>.dwg` unter `DXFM_OMNIFLO` (`omni:insert-dxf` faellt auf `.dwg` zurueck, wenn keine `.dxf` existiert). Per `OMNI_EDIT` editierbar |
|
||||
| TEF Elemente | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade` | Feste TEF-Bauteile ohne Sivas-Auswahl, direkt per `omni:insert-dxf` an gewaehltem Punkt eingefuegt (Dateien unter `DXFM_OMNIFLO`) |
|
||||
| Anbaugruppen ⚠️ | `OMNI_KettenFoerderer` | **Dummy** (noch nicht implementiert, im Menue ausgegraut); `OMNI_STOPPER`/`OMNI_SCANNER`/`OMNI_BUERSTENBREMSE` sind implementiert |
|
||||
| Anbaugruppen | `OMNI_STOPPER`, `OMNI_SCANNER`, `OMNI_BUERSTENBREMSE` | Implementiert |
|
||||
| Verbinder | `OMNI_TV_*` | Verbinder-DWG aus `data/omniflo/Verbinder` (dimensionsunabhaengig, `omni:insert-verbinder` -> `omni:insert-datei`, Punkt + Drehung interaktiv). Zuordnung Befehl -> DWG nach Dateiname, z.B. `OMNI_TV_W_AP60` -> `TV_W-AP60_oben`, `OMNI_TV_ENDPLATTE` -> `VB_ENDP_AP`, `OMNI_TV_W_AP60_KPL` -> `TV_W-AP60_kpl`, `OMNI_TV_ANSCHLAG` -> `VB_ENDP_AP_Spulenzug`, `OMNI_TV_SW_I_AP110` -> `TV_SW_I_SW-AP110`, `OMNI_TV_MUFFE` -> `VB_Muffe`. Alle 18 Eintraege aktiv |
|
||||
| Bogenweichen ⚠️ | `OMNI_APBW_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) |
|
||||
| Bearbeiten | `OMNI_EDIT` | Omniflo-Block selektieren und Attribute bearbeiten |
|
||||
@@ -712,13 +717,12 @@ nicht zu verwechseln mit den einzelnen `OMNI_TEF_*`-Befehlen oben.
|
||||
|
||||
---
|
||||
|
||||
### `SSG_LIB_Commands.lsp` – BTMT, Sensoren, Dummy-Befehle, Konfiguration und SSG_BLOCKEDIT
|
||||
### `SSG_LIB_Commands.lsp` – BTMT, Sensoren, Konfiguration und SSG_BLOCKEDIT
|
||||
|
||||
Sammeldatei fuer Menue-Befehle: teils Platzhalter fuer noch nicht implementierte
|
||||
Eintraege, teils bereits **echte** Funktionalitaet (BTMT Be-/Entladung, Sensoren,
|
||||
Konfiguration, Doppelklick-Dispatcher). Alle noch offenen Dummy-Menueintraege sind in
|
||||
`menu/SSG_LIB.mnu` mit `~` ausgegraut (siehe Abschnitt
|
||||
["Status: noch offene Menueintraege"](#status-noch-offene-menueintraege-im-menue-ausgegraut)).
|
||||
Sammeldatei fuer Menue-Befehle: BTMT Be-/Entladung, Sensoren, Eingang/Ausgang,
|
||||
Konfiguration und der Doppelklick-Dispatcher. Die frueheren Dummy-Befehle (ILS-Kurven,
|
||||
Etagenfoerderer) sind entfernt; noch offene Menueintraege anderer Module siehe Abschnitt
|
||||
["Status: noch offene Menueintraege"](#status-noch-offene-menueintraege-im-menue-ausgegraut).
|
||||
|
||||
**Sensoren einfuegen** (real, ueber `ils-insert-sensor` → wiederholtes `_.INSERT`
|
||||
mit interaktivem Einfuegepunkt/Rotation, Blockdatei via `ssg-ils-block-datei`):
|
||||
@@ -760,15 +764,6 @@ Sivas-Export zusaetzlich in den Summenzaehlern "Anzahl aller BTBeladung"/
|
||||
dieselbe `ils-insert-station`-Routine wie BTMT Be-/Entladung (frei platzierbar,
|
||||
Blöcke `Eingang_<DIM>.dwg`/`Ausgang_<DIM>.dwg` in `data/ils`).
|
||||
|
||||
Registrierte Dummy-Befehle:
|
||||
|
||||
| Gruppe | Befehle |
|
||||
| --- | --- |
|
||||
| ILS Zusatzmodule | `ILS_ETF_Etagenfoerderer`|
|
||||
| ILS Kurven angetrieben Aussen | `ILS_K90LA`, `ILS_K90RA`, `ILS_K60LA`, `ILS_K60RA`, `ILS_K30LA`, `ILS_K30RA` |
|
||||
| ILS Kurven angetrieben Innen | `ILS_K90LI`, `ILS_K90RI`, `ILS_K60LI`, `ILS_K60RI`, `ILS_K30LI`, `ILS_K30RI` |
|
||||
| ILS Gefaellestrecken-Kurven | `ILS_Gefaellestrecke` |
|
||||
|
||||
> `FOERDERANLAGE` ist nicht hier definiert – dieser Befehl ist in `VarioFoerderer.lsp` implementiert.
|
||||
|
||||
**Konfigurationsbefehle** (Menue → Konfiguration):
|
||||
@@ -776,11 +771,12 @@ Registrierte Dummy-Befehle:
|
||||
| Befehl | Beschreibung |
|
||||
| --- | --- |
|
||||
| `SSG_DIM_SWITCH` | Schaltet zwischen 2D/3D-Bloecken um (setzt `DXFM_DIM`, `DXFM_BLOCKS`, `DXFM_OMNIFLO`) |
|
||||
| `SSG_DIM_ALL_2D` / `SSG_DIM_ALL_3D` | Alle VF_n-/GF_n-Bloecke der Zeichnung nach 2D bzw. 3D umbauen |
|
||||
| `SSG_SPRACHE` | Oeffnet Dialog `sprache.dcl`, setzt `*ssg-lang*` und persistiert via `DXFM_LANG` (siehe [`ssg_lang.lsp`](#ssg_langlsp--sprachumschaltung-deutschenglisch)) |
|
||||
|
||||
**SSG_BLOCKEDIT** – Doppelklick/Kontextmenue-Dispatcher:
|
||||
|
||||
Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearbeitungsbefehl auf (Reihenfolge wichtig: `GR_*` **vor** dem Omniflo-Zweig, da Geruest-Bloecke ebenfalls ein TEILEART-Attribut tragen):
|
||||
Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearbeitungsbefehl auf (Reihenfolge wichtig: `GR_*` und `KF_*` **vor** dem Omniflo-Zweig, da diese Bloecke ebenfalls ein TEILEART-Attribut tragen koennen):
|
||||
|
||||
| Blockmuster | Aktion |
|
||||
| --- | --- |
|
||||
@@ -788,8 +784,11 @@ Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearb
|
||||
| `ECKRAD_*` | `EckradEdit` |
|
||||
| `GF_*` | `GEFAELLESTRECKE_EDIT` |
|
||||
| `VF_*` | `VARIOFOERDERER_EDIT` |
|
||||
| `GR_*` | Geruest – `BEDIT` (kein eigener Edit-Pfad; siehe `GeruestInsert.lsp`) |
|
||||
| `CONNECTION_*` | `CONNECTION_EDIT` |
|
||||
| `JAM_*` | `JAM_EDIT` |
|
||||
| `TRO_*` | `TRO_EDIT` |
|
||||
| `GR_*` | Geruest – nativer Attribut-Editor `_.EATTEDIT` (kein eigener Edit-Pfad; siehe `GeruestInsert.lsp`) |
|
||||
| `KF_*` | `KF_EDIT` |
|
||||
| Omniflo (TEILEART-Attribut, AP110*, numerisch) | `OMNI_EDIT` |
|
||||
| Sonstige | `BEDIT` (Block-Editor) |
|
||||
|
||||
@@ -800,18 +799,20 @@ Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearb
|
||||
Rohr-Geruest-Baugruppen (Saeulen, Rohrabhaenger, Wandbefestigung, Rohr-Geruest-Traeger)
|
||||
aus [`data/json/geruest.json`](../data/json/geruest.json) bzw.
|
||||
[`data/json/geruest_traeger.json`](../data/json/geruest_traeger.json) konfigurieren
|
||||
und einfuegen. Die Dialogdefinition wird **zur Laufzeit erzeugt**
|
||||
(`geruest-dcl-schreiben`, temporaere DCL-Datei) – es gibt keine feste
|
||||
`dcl/geruest.dcl`, weil je Anbauteil ein eigenes Mengenfeld gebraucht wird.
|
||||
und einfuegen. Das Dialog-Layout steht als **Vorlage** in `dcl/geruest.dcl` bzw.
|
||||
`dcl/geruest_traeger.dcl`; nur die datenabhaengigen Bloecke (Varianten-Radiobuttons,
|
||||
Mengenfeld je Anbauteil) werden zur Laufzeit an Markerzeilen `//@NAME@` eingesetzt
|
||||
(`ssg-dcl-vorlage-fuellen`, temporaere DCL-Datei).
|
||||
Ausfuehrliche Beschreibung (Konfigurationen, Attribut-Schema, Querstreben/Muffe,
|
||||
Traeger-Beschriftung): siehe `../CLAUDE.md` Abschnitt "AutoLISP-Module".
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
| --- | --- |
|
||||
| `c:GERUEST` | Dialog ohne Vorgabe-Bereich (Dropdown Rohrabhaenger/Saeulen/Wandbefestigung) |
|
||||
| `c:GERUEST_SAEULEN` / `c:GERUEST_ROHRABHAENGER` / `c:GERUEST_WANDBEFESTIGUNG` | Dialog mit vorgewaehltem Bereich (derselbe Dialog wie `GERUEST`) |
|
||||
| `c:GERUEST_SAEULEN` / `c:GERUEST_ROHRABHAENGER` / `c:GERUEST_WANDBEFESTIGUNG` | Je eigener Dialog fuer den Bereich (keine Umschaltung im Dialog) |
|
||||
| `c:GERUEST` | Ohne Bereich nur ein Hinweis (im Menue Platzhalter fuer den Gattertraeger) |
|
||||
| `c:GERUEST_TRAEGER` | Eigener fester Dialog (`dcl/geruest_traeger.dcl`): Rohr-Geruest-Traeger mit Linien-Logik (Start-/Endpunkt oder Laenge, Laengenabzuege, Querstreben/Muffe-Verteilung) |
|
||||
| `c:GERUEST_TRAEGER_BESCHRIFTEN` | Alle Traeger der Zeichnung neu beschriften (eigenes TEXT-Objekt, verknuepft per XDATA `SSG_GR_BESCHR`) |
|
||||
| `c:OMNI_FAHRSTRECKE` / `c:OMNI_FAHRSTRECKE_BESCHRIFTEN` | Omniflo-Fahrstrecke mit derselben Linien-Logik (Daten `omniflo_fahrstrecke.json`, Vorlage `dcl/fahrstrecke.dcl`) bzw. Neubeschriftung |
|
||||
|
||||
Block-Praefix `GR_<id>_<timestamp>` – **nicht kosmetisch**: `SSG_BLOCKEDIT` muss
|
||||
`GR_*` vor dem Omniflo-Zweig abfangen, da Geruest-Bloecke ebenfalls ein
|
||||
@@ -908,3 +909,59 @@ in assoziativen Arrays, MINSERT-Rastern und verschachtelten Bloecken. `LAGER_EXP
|
||||
ordnet jedes goh_rack zuerst ueber den Layer `LG_*_G<n>` seines obersten INSERTs
|
||||
(`lg-rk-top`), erst dann ueber die Geschosskontur zu. `LG_REGALE` zeigt die Zaehlung
|
||||
je Geschoss in der Befehlszeile.
|
||||
|
||||
---
|
||||
|
||||
### `Jam_Edit.lsp` – Staubereiche (SPS)
|
||||
|
||||
Staubereiche zeichnet sps_skel (`tro_annotate.py --anlage`) als Block `JAM_AREA`
|
||||
(Name `Jam<NNNN>_<k>`).
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
| --- | --- |
|
||||
| `c:JAM_EDIT` | Foerderer und laufende Nummer per Dialog (`dcl/jam_edit.dcl`) aendern; Knopf zurueck auf den abgeleiteten Wert, Warnung bei doppeltem Namen. Auch per Doppelklick (`SSG_BLOCKEDIT`, `JAM_*`) |
|
||||
|
||||
---
|
||||
|
||||
### `KettenFoerderer.lsp` – Kettenfoerderer/Schraegfoerderer Stahl
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
| --- | --- |
|
||||
| `c:KETTENFOERDERER` | Baut aus `KF_UM_<winkel>` -> `KF_LAENGE` -> `KF_AN_<winkel>` plus Draufsicht `KF_2D` einen Block `KF_<n>` (Dialog `dcl/kettenfoerderer.dcl`, Daten `data/json/kettenfoerderer.json`) |
|
||||
| `c:KF_EDIT` | `KF_n` bearbeiten und an derselben Stelle neu aufbauen (auch per Doppelklick) |
|
||||
| `c:KF_KS_PRUEFEN` | Diagnose (nicht im Menue) |
|
||||
|
||||
Details (aufgerichtete Geometrie, Attribut-Schema, Sivas-Export): `../CLAUDE.md`.
|
||||
|
||||
---
|
||||
|
||||
### Werkzeuge: `ssg_stueckliste.lsp`, `DinFormate.lsp`
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
| --- | --- |
|
||||
| `c:SSG_FAEHNCHEN_STUECKLISTE` | Positions-Faehnchen je Element und grob gruppierte Stuecklistentabelle, komplett aus der Zeichnung (kein Datei-Import) |
|
||||
| `c:DIN_FORMATE` | DIN-Rahmen A0-A4 und optional Schriftkopf (KOPF11, DE/EN/FR/IT) aus `cfg/rahmen/` einfuegen (Dialog `dcl/dinformate.dcl`) |
|
||||
|
||||
---
|
||||
|
||||
### Export-Hilfen: `count_sep_scan.lsp`, `check_hoehen.lsp`
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
| --- | --- |
|
||||
| `c:ZAEHLE_SEP_SCAN` | Scanner/Separatoren je Kreisel/VF/GF zaehlen und in `ANZAHL_SCANNER`/`ANZAHL_SEPARATOR` schreiben (laeuft auch vor jedem Export) |
|
||||
| `c:HOEHEN_CHECK` | Hoehen von Kreiseln/VF/GF messen, auf 0/negativ pruefen und in die Hoehen-Attribute schreiben |
|
||||
|
||||
---
|
||||
|
||||
### Entwickler-/Pflege-Module
|
||||
|
||||
| Datei | Befehle | Zweck |
|
||||
| --- | --- | --- |
|
||||
| `addattribute.lsp` | `ILS_ATTR_SYNC`, `ILS_ATTR_REPLACE` | ATTDEFs der Block-DWGs mit `data/ils/allocations.json` abgleichen |
|
||||
| `collect_attributes.lsp` | `ILS_ATTR_COLLECT` | ATTDEF-Werte aller DWGs nach `allocations_collected.json` schreiben |
|
||||
| `list_blocks.lsp` | `ILS_BLOCK_LIST` | Sub-Block-Definitionen aller DWGs auflisten (Kollisionen 2D/3D) |
|
||||
| `purge_blocks.lsp` | `ILS_BLOCK_PURGE` | Unbenutzte Bloecke/Layer in allen DWGs entfernen |
|
||||
| `ks_pruefung.lsp` | `KS_PRUEFEN` | KS_EIN/KS_AUS der 2D- gegen die 3D-Variante vergleichen (CSV) |
|
||||
| `menu-inventory.lsp` | `MenuInventory` | BricsCAD-Menuegruppen, Plugins, Startdateien auflisten |
|
||||
| `EtageVarioFoerderer.lsp` | - | Kompatibilitaets-Wrapper, laedt `vf_core.lsp` |
|
||||
| `tro_types.lsp` | - | Von `tro_annotate.py --emit-lisp` erzeugte TRO-Typliste |
|
||||
@@ -226,6 +226,7 @@
|
||||
(if (car (atoms-family 1 '("SSG-ENSURE")))
|
||||
(progn (ssg-ensure "Gefaellestrecke") (ssg-ensure "VarioFoerderer")))
|
||||
(setq enames '() n-gf 0 n-vf 0 n-skip 0)
|
||||
(setq *vfl-konvert-fehler* nil) ; Fehlschlaege der Linienzug-Konvertierung
|
||||
(ssg-start "SSG_DIM_BATCH" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
|
||||
(setvar "OSMODE" 0)
|
||||
;; Erst alle enames sammeln (entdel veraendert die Zeichnung waehrend der Iteration)
|
||||
@@ -247,12 +248,12 @@
|
||||
(if (gf-konvertiere-ent ent ziel-dim) (setq n-gf (1+ n-gf))))
|
||||
((wcmatch bname "VF_*")
|
||||
;; VF_-Bloecke nach Edit-Marker unterscheiden: Standard/Etage
|
||||
;; ueber vf-konvertiere-ent, Linienzug (Modus 1/2) ueber den
|
||||
;; ueber vf-konvertiere-ent, Linienzug (Modus 1/2/3) ueber den
|
||||
;; Journal-Replay-Konverter vfl-konvertiere-ent. Altbestand ohne
|
||||
;; bekannten Marker wird uebersprungen.
|
||||
(setq marker (car (vfs-xdata-lesen ent)))
|
||||
(cond
|
||||
((member marker '("linienzug" "linienzug2"))
|
||||
((member marker '("linienzug" "linienzug2" "linienzug3"))
|
||||
(if (vfl-konvertiere-ent ent ziel-dim) (setq n-vf (1+ n-vf))
|
||||
(setq n-skip (1+ n-skip))))
|
||||
((member marker '("standard" "etage"))
|
||||
@@ -264,6 +265,14 @@
|
||||
(ssg-end)
|
||||
(princ (ssg-textf "dim-batch-fertig"
|
||||
(list ziel-dim (itoa n-gf) (itoa n-vf) (itoa n-skip))))
|
||||
;; Fehlgeschlagene Linienzug-Bloecke gesammelt ausgeben (alter Block blieb
|
||||
;; jeweils unveraendert stehen, siehe vfl-konvertiere-ent)
|
||||
(if *vfl-konvert-fehler*
|
||||
(progn
|
||||
(princ (ssg-textf "dim-batch-fehlerliste"
|
||||
(list (itoa (length *vfl-konvert-fehler*)))))
|
||||
(foreach f *vfl-konvert-fehler*
|
||||
(princ (ssg-textf "dim-batch-fehler-zeile" (list (car f) (cdr f)))))))
|
||||
(princ)
|
||||
)
|
||||
|
||||
@@ -382,6 +391,23 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; Staubereiche (JAM_AREA) -> JAM_EDIT (DCL-Dialog)
|
||||
;; Ebenfalls aus der Beschriftung von sps_skel (tro_annotate.py --anlage);
|
||||
;; Foerderer und laufende Nummer des Staubereichs Jam<NNNN>_<k>.
|
||||
((wcmatch bname "JAM_*")
|
||||
(princ (ssg-textf "cmd-jam-bearbeiten" (list bname)))
|
||||
(if (and (null *ssg-Jam_Edit-loaded*) (atoms-family 1 '("SSG-ENSURE")))
|
||||
(ssg-ensure "Jam_Edit")
|
||||
)
|
||||
(if (atoms-family 1 '("C:JAM_EDIT"))
|
||||
(c:JAM_EDIT)
|
||||
(progn
|
||||
(princ (ssg-textf "tro-edit-modul-fehlt" (list "Jam_Edit.lsp")))
|
||||
(command "_.EATTEDIT")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; TRO-Marker (TRO_SYM_<Typ>) -> TRO_EDIT (DCL-Dialog)
|
||||
;; Die Marker kommen aus sps_skel (lib/tro_annotate.py) und tragen die
|
||||
;; Attribute ID und TYPE. Modul bei Bedarf nachladen, damit der Doppelklick
|
||||
@@ -418,6 +444,24 @@
|
||||
(ssg-end)
|
||||
)
|
||||
|
||||
;; Kettenfoerderer (KF_n, KettenFoerderer.lsp) -> KF_EDIT (DCL-Dialog mit
|
||||
;; Neuaufbau an derselben Stelle). MUSS - aus demselben Grund wie GR_* -
|
||||
;; vor dem Omniflo-Zweig stehen: traegt die Baugruppe ein TEILEART-
|
||||
;; Attribut, wuerde dort sonst der Omniflo-Elementdialog aufgehen.
|
||||
((wcmatch bname "KF_*")
|
||||
(princ (ssg-textf "cmd-kettenfoerderer-bearbeiten" (list bname)))
|
||||
(if (and (null *ssg-KettenFoerderer-loaded*) (atoms-family 1 '("SSG-ENSURE")))
|
||||
(ssg-ensure "KettenFoerderer")
|
||||
)
|
||||
(if (atoms-family 1 '("C:KF_EDIT"))
|
||||
(c:KF_EDIT)
|
||||
(progn
|
||||
(princ (ssg-textf "tro-edit-modul-fehlt" (list "KettenFoerderer.lsp")))
|
||||
(command "_.EATTEDIT")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Omniflo-Bloecke -> OMNI_EDIT
|
||||
;; Erkennung: TEILEART-Attribut vorhanden, AP110-Blockname oder rein numerisch
|
||||
((progn
|
||||
|
||||
+315
-19
@@ -16,10 +16,12 @@
|
||||
;;; - ENTER -> Markierungskreis (Layer *ch-mark-layer*),
|
||||
;;; Block spaeter manuell anpassen.
|
||||
;;;
|
||||
;;; Phase 3 - Buehne: liegt die rohe Montagehoehe ueber
|
||||
;;; *ch-buehne-schwelle-m* (Default 2,0 m), wird pro Block gefragt,
|
||||
;;; ob eine Buehne vorhanden ist; deren Hoehe wird abgezogen
|
||||
;;; (MONTAGEHOEHE_m = roh - Buehne).
|
||||
;;; Phase 3 - Buehne nach Kreisel-Familien (siehe Abschnitt PHASE 3):
|
||||
;;; liegt eine Familie ueber *ch-buehne-schwelle-m* (Default 3,0 m), wird
|
||||
;;; EINMAL pro Familie gefragt; die Buehnenhoehe wird von den Kreiseln und
|
||||
;;; den zugehoerigen VF/GF abgezogen (MONTAGEHOEHE_m = roh - Buehne).
|
||||
;;; Bloecke, die keiner Familie zuzuordnen sind, werden wie frueher
|
||||
;;; einzeln gefragt (ch-write-montage).
|
||||
;;;
|
||||
;;; PHASE 1-3 bewusst OHNE: QSAVE (Testmodus, UNDO moeglich).
|
||||
;;;
|
||||
@@ -42,7 +44,19 @@
|
||||
;; Schwelle (m): ab dieser Montagehoehe wird pro Block nach einer
|
||||
;; Buehne gefragt (typische Anlagenhoehe ~2 m; darueber liegt die
|
||||
;; Anlage vermutlich auf einer Buehne).
|
||||
(if (null *ch-buehne-schwelle-m*) (setq *ch-buehne-schwelle-m* 2.0))
|
||||
(if (null *ch-buehne-schwelle-m*) (setq *ch-buehne-schwelle-m* 3.0))
|
||||
|
||||
;; Phase 3 (Familien): maximaler Hoehenunterschied zweier Kreisel-Familien (mm),
|
||||
;; zwischen denen eine Strecke denselben Buehnenabzug bekommt, und
|
||||
;; Zuordnungstoleranzen Strecken-Ende -> Kreisel (XY-Abstand zur Kreiselachse
|
||||
;; ueber den Radradius hinaus, Hoehenabweichung in mm).
|
||||
(if (null *ch-fam-max-hoehendiff-mm*) (setq *ch-fam-max-hoehendiff-mm* 1500.0))
|
||||
(if (null *ch-zuordnung-xy-mm*) (setq *ch-zuordnung-xy-mm* 300.0))
|
||||
(if (null *ch-zuordnung-z-mm*) (setq *ch-zuordnung-z-mm* 100.0))
|
||||
|
||||
;; Register der in Phase 1/2 geschriebenen Bloecke fuer Phase 3:
|
||||
;; je Block (ent art lbl roh pein paus erledigt).
|
||||
(setq *ch-rec* nil)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; vf_core-KS-Helfer sicherstellen (extract-ks-from-block-raw).
|
||||
@@ -127,12 +141,19 @@
|
||||
(if entry (caddr (car entry)) nil)
|
||||
)
|
||||
|
||||
;;; Ganzer KS-Ursprung (x y z) oder nil.
|
||||
(defun ch-ks-pt (ksdata ksname / entry)
|
||||
(setq entry (cadr (assoc ksname ksdata)))
|
||||
(if entry (car entry) nil)
|
||||
)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; KS_EIN.Z / KS_AUS.Z eines Composite-Blocks (VF_n/GF_n) messen.
|
||||
;;; Rueckgabe: (kez kaz) - fehlende Werte = nil.
|
||||
;;; Rueckgabe: (kez kaz pein paus) - fehlende Werte = nil. pein/paus sind
|
||||
;;; die ganzen KS-Ursprungspunkte (fuer die Kreisel-Zuordnung in Phase 3).
|
||||
;;; ------------------------------------------------------------
|
||||
(defun ch-measure-vfgf (ename / obj subs nm ksdata kez kaz)
|
||||
(setq kez nil kaz nil)
|
||||
(defun ch-measure-vfgf (ename / obj subs nm ksdata kez kaz pein paus)
|
||||
(setq kez nil kaz nil pein nil paus nil)
|
||||
(setq obj (vlax-ename->vla-object ename))
|
||||
(setq subs (vl-catch-all-apply 'vlax-invoke (list obj 'Explode)))
|
||||
(if (and (not (vl-catch-all-error-p subs)) subs)
|
||||
@@ -145,10 +166,12 @@
|
||||
(cond
|
||||
((and (null kez) (wcmatch nm *ch-as-pattern*))
|
||||
(setq ksdata (extract-ks-from-block-raw sub))
|
||||
(setq kez (ch-ks-z ksdata "KS_EIN")))
|
||||
(setq kez (ch-ks-z ksdata "KS_EIN")
|
||||
pein (ch-ks-pt ksdata "KS_EIN")))
|
||||
((and (null kaz) (wcmatch nm *ch-es-pattern*))
|
||||
(setq ksdata (extract-ks-from-block-raw sub))
|
||||
(setq kaz (ch-ks-z ksdata "KS_AUS")))
|
||||
(setq kaz (ch-ks-z ksdata "KS_AUS")
|
||||
paus (ch-ks-pt ksdata "KS_AUS")))
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -158,7 +181,7 @@
|
||||
(vl-catch-all-apply 'vla-Delete (list sub))))
|
||||
)
|
||||
)
|
||||
(list kez kaz)
|
||||
(list kez kaz pein paus)
|
||||
)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
@@ -278,7 +301,275 @@
|
||||
)
|
||||
|
||||
;;; ============================================================
|
||||
;;; HAUPTBEFEHL (Phase 1 + 2)
|
||||
;;; PHASE 3 - Buehnen-Familien
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Kreisel, die sich beruehren (Rad/Rad, Rad/Laufprofil, gleiche Hoehe -
|
||||
;;; KREISEL_WEICHEN-Kern kreisel-bp-*), haben zwingend dieselbe Hoehe und
|
||||
;;; bilden eine FAMILIE. Pro Familie ueber der Schwelle wird EINMAL nach
|
||||
;;; der Buehne gefragt; deren Hoehe wird von den Kreiseln der Familie und
|
||||
;;; von allen VF/GF abgezogen, deren beide Enden in dieser Familie liegen.
|
||||
;;; Strecken zwischen zwei Familien bekommen den Abzug nur bei gleicher
|
||||
;;; Buehnenhoehe UND hoechstens *ch-fam-max-hoehendiff-mm* Hoehenunterschied.
|
||||
;;; Geschrieben wird nur MONTAGEHOEHE_m (aus der Rohhoehe, also wiederholbar);
|
||||
;;; HOEHE/HOEHE_VON_mm bleiben, damit csv:hoehen-aktualisieren nichts zurueck-
|
||||
;;; setzt.
|
||||
;;; ============================================================
|
||||
|
||||
;;; Wurzel eines Knotens in der Eltern-Alist (Union-Find ohne Pfadkompression).
|
||||
(defun ch-fam-wurzel (rep k / p)
|
||||
(while (and (setq p (cdr (assoc k rep))) (/= p k))
|
||||
(setq k p))
|
||||
k
|
||||
)
|
||||
|
||||
;;; Familien aus Knoten und Kanten (reiner Kern).
|
||||
;;; knoten = ((schluessel idnum) ...), kanten = ((schluesselA schluesselB) ...)
|
||||
;;; Rueckgabe: Liste von Familien (je Liste von Schluesseln). Mitglieder und
|
||||
;;; Familien sind nach kleinster ID-Nummer geordnet (Gleichstand: Reihenfolge
|
||||
;;; in knoten); unbekannte Schluessel in kanten werden uebergangen.
|
||||
(defun ch-familien (knoten kanten / rep ra rb idx sortiert fams w)
|
||||
(foreach k knoten (setq rep (cons (cons (car k) (car k)) rep)))
|
||||
(foreach e kanten
|
||||
(if (and (assoc (car e) rep) (assoc (cadr e) rep))
|
||||
(progn
|
||||
(setq ra (ch-fam-wurzel rep (car e))
|
||||
rb (ch-fam-wurzel rep (cadr e)))
|
||||
(if (/= ra rb)
|
||||
(setq rep (subst (cons ra rb) (assoc ra rep) rep))))))
|
||||
(setq idx 0)
|
||||
(foreach k knoten
|
||||
(setq sortiert (cons (list (cadr k) (car k) idx) sortiert)
|
||||
idx (1+ idx)))
|
||||
(setq sortiert (vl-sort sortiert 'ch-id<))
|
||||
(foreach s sortiert
|
||||
(setq w (ch-fam-wurzel rep (cadr s)))
|
||||
(if (assoc w fams)
|
||||
(setq fams (subst (append (assoc w fams) (list (cadr s))) (assoc w fams) fams))
|
||||
(setq fams (append fams (list (list w (cadr s)))))))
|
||||
(mapcar 'cdr fams)
|
||||
)
|
||||
|
||||
;;; Abzugsregel fuer eine Strecke zwischen zwei VERSCHIEDENEN Familien
|
||||
;;; (reiner Kern). b1/b2 = Buehnenhoehe der Familien in m (0 = keine),
|
||||
;;; z1/z2 = Familienhoehen in mm, maxdiff = erlaubter Unterschied in mm.
|
||||
;;; Rueckgabe (status . abzug_m): "kein" (beide ohne Buehne), "konflikt"
|
||||
;;; (verschiedene Buehnenhoehen), "hoehe" (Familien zu weit auseinander),
|
||||
;;; "abzug" (gleiche Buehne, abzug_m = b1).
|
||||
(defun ch-kreuz-abzug (b1 b2 z1 z2 maxdiff)
|
||||
(cond
|
||||
((and (equal b1 0.0 1e-6) (equal b2 0.0 1e-6)) (cons "kein" 0.0))
|
||||
((not (equal b1 b2 1e-6)) (cons "konflikt" 0.0))
|
||||
((> (abs (- z1 z2)) maxdiff) (cons "hoehe" 0.0))
|
||||
(t (cons "abzug" b1))
|
||||
)
|
||||
)
|
||||
|
||||
;;; Montagehoehe nach Buehnenabzug (reiner Kern). nil, wenn kein gueltiger
|
||||
;;; Abzug moeglich ist (b <= 0 oder b >= roh).
|
||||
(defun ch-abzug-anwenden (roh b)
|
||||
(if (and (> b 0.0) (< b roh)) (- roh b))
|
||||
)
|
||||
|
||||
;;; XY-Abstand eines Punktes von der Strecke a-b (reiner Kern).
|
||||
(defun ch-pkt-strecke-abstand (pt a b / lot tt)
|
||||
(setq lot (kreisel-bp-lot pt a b)
|
||||
tt (max 0.0 (min 1.0 (car lot))))
|
||||
(kreisel-bp-abst pt (kreisel-bp-plus a (kreisel-bp-mal (kreisel-bp-minus b a) tt)))
|
||||
)
|
||||
|
||||
;;; Naechster Kreisel/Eckrad zu einem Strecken-Endpunkt (reiner Kern).
|
||||
;;; pt = (x y [z]), z = Hoehe in mm, elemente = kreisel-bp-element-Records.
|
||||
;;; Treffer: XY-Abstand zur Achse <= Radradius + tolxy und |z - Kreiselhoehe|
|
||||
;;; <= tolz. Rueckgabe: Handle des naechsten Treffers oder nil.
|
||||
(defun ch-kreisel-finden (pt z elemente tolxy tolz / best bd d ac)
|
||||
(foreach e elemente
|
||||
(if (<= (abs (- z (kreisel-bp-get "z" e))) tolz)
|
||||
(progn
|
||||
(setq ac (kreisel-bp-get "achse" e)
|
||||
d (ch-pkt-strecke-abstand pt (car ac) (cadr ac)))
|
||||
(if (and (<= d (+ (kreisel-bp-get "r" e) tolxy))
|
||||
(or (null bd) (< d bd)))
|
||||
(setq bd d best (kreisel-bp-get "handle" e))))))
|
||||
best
|
||||
)
|
||||
|
||||
;;; Abzugsregel fuer eine Strecke aus den Familiensaetzen ihrer beiden Enden
|
||||
;;; (reiner Kern). fs/fe = (idx handles z b). Gleiche Familie -> ("innen" . b),
|
||||
;;; sonst Ergebnis von ch-kreuz-abzug.
|
||||
(defun ch-strecke-abzug (fs fe maxdiff)
|
||||
(if (= (car fs) (car fe))
|
||||
(cons "innen" (cadddr fs))
|
||||
(ch-kreuz-abzug (cadddr fs) (cadddr fe) (caddr fs) (caddr fe) maxdiff))
|
||||
)
|
||||
;;; Flache Schleife (reiner Kern): Strecke startet und endet am SELBEN Kreisel
|
||||
;;; (h1 = h2) und hat gleiche Anfangs-/Endhoehe (|z1 - z2| <= tol, mm). Ihre
|
||||
;;; Buehne laesst sich nicht aus der Familie ableiten und wird einzeln gefragt.
|
||||
(defun ch-schleife-p (h1 h2 z1 z2 tol)
|
||||
(and h1 h2 (= h1 h2) (<= (abs (- z1 z2)) tol))
|
||||
)
|
||||
|
||||
;;; ID-Nummer eines Elements (999999 ohne gueltige ID).
|
||||
(defun ch-id-nummer (id)
|
||||
(if (and id (/= id "") (> (atoi id) 0)) (atoi id) 999999)
|
||||
)
|
||||
|
||||
;;; Element-Record zu einem Handle.
|
||||
(defun ch-elem-zu-handle (h elemente / res)
|
||||
(foreach e elemente
|
||||
(if (and (null res) (= (kreisel-bp-get "handle" e) h)) (setq res e)))
|
||||
res
|
||||
)
|
||||
|
||||
;;; Kreisel-Modul (kreisel-bp-*) sicherstellen.
|
||||
(defun ch-ensure-kreisel ()
|
||||
(if (null (car (atoms-family 1 '("KREISEL-BP-BERECHNEN"))))
|
||||
(if (car (atoms-family 1 '("SSG-ENSURE")))
|
||||
(vl-catch-all-apply '(lambda () (ssg-ensure "KreiselInsert")))))
|
||||
(if (car (atoms-family 1 '("KREISEL-BP-BERECHNEN"))) t nil)
|
||||
)
|
||||
|
||||
;;; Montage-Rohwert schreiben (ohne Rueckfrage) und fuer Phase 3 vormerken.
|
||||
;;; pts = (pein paus) bei VF/GF, sonst nil. Rueckgabe: roh.
|
||||
(defun ch-montage-roh (ent art raw lbl pts)
|
||||
(ch-set-att ent "MONTAGEHOEHE_m" (rtos raw 2 3))
|
||||
(setq *ch-rec* (append *ch-rec*
|
||||
(list (list ent art lbl raw (car pts) (cadr pts)))))
|
||||
raw
|
||||
)
|
||||
|
||||
;;; Familie hervorheben (mode 3) bzw. zuruecknehmen (mode 4).
|
||||
(defun ch-fam-hervorheben (handles mode / e)
|
||||
(foreach h handles
|
||||
(if (setq e (handent h)) (redraw e mode)))
|
||||
)
|
||||
|
||||
;;; Buehnenhoehe (m) fuer eine Familie erfragen. nil = keine Buehne.
|
||||
;;; z = Familienhoehe in mm, prev = zuletzt eingegebene Buehne (Vorgabe) oder nil.
|
||||
(defun ch-frage-buehne (txt z prev / b ok)
|
||||
(if (ssg-in-yesno txt nil)
|
||||
(progn
|
||||
(while (not ok)
|
||||
(setq b (ssg-in-real (ssg-text "chh-buehne-hoehe") prev))
|
||||
(cond
|
||||
((null b) (setq ok T))
|
||||
((and (> b 0.0) (< b (/ z 1000.0))) (setq ok T))
|
||||
(t (princ (ssg-textf "chh-buehne-ungueltig" (list (rtos (/ z 1000.0) 2 3))))
|
||||
(setq b nil))))
|
||||
b))
|
||||
)
|
||||
|
||||
;;; Phase 3 ausfuehren: arbeitet das Register *ch-rec* ab. Bloecke ohne
|
||||
;;; Familie (Zuordnung unklar) fragen wie zuvor einzeln nach.
|
||||
(defun ch-phase3 ( / elems ber knoten kanten fams famdat h2f n-fam n-bue
|
||||
rep z b prev rec idx fs fe kr neu lbl h
|
||||
n-kr n-innen n-kreuz n-konf n-offen ents)
|
||||
(setq n-kr 0 n-innen 0 n-kreuz 0 n-konf 0 n-offen 0 n-fam 0 n-bue 0
|
||||
ents nil)
|
||||
(princ (ssg-text "chh-start"))
|
||||
(if (ch-ensure-kreisel)
|
||||
(progn
|
||||
(setq elems (kreisel-bp-elemente-sammeln)
|
||||
ber (car (kreisel-bp-berechnen elems (kreisel-bp-toleranz)
|
||||
(kreisel-bp-toleranz-z))))
|
||||
(setq knoten (mapcar '(lambda (el) (list (kreisel-bp-get "handle" el)
|
||||
(ch-id-nummer (kreisel-bp-get "id" el))))
|
||||
elems)
|
||||
kanten (mapcar '(lambda (tr) (list (kreisel-bp-get "handle" (kreisel-bp-get "a" tr))
|
||||
(kreisel-bp-get "handle" (kreisel-bp-get "b" tr))))
|
||||
ber))
|
||||
(setq fams (ch-familien knoten kanten))
|
||||
|
||||
;; --- je Familie einmal fragen ---
|
||||
(setq idx 0)
|
||||
(foreach fam fams
|
||||
(setq idx (1+ idx) n-fam (1+ n-fam)
|
||||
rep (ch-elem-zu-handle (car fam) elems)
|
||||
z (kreisel-bp-get "z" rep)
|
||||
b 0.0)
|
||||
(if (> (/ z 1000.0) *ch-buehne-schwelle-m*)
|
||||
(progn
|
||||
(ch-fam-hervorheben fam 3)
|
||||
(setq b (ch-frage-buehne
|
||||
(ssg-textf "chh-fam-frage"
|
||||
(list (itoa idx) (kreisel-bp-elem-text rep)
|
||||
(itoa (length fam)) (rtos (/ z 1000.0) 2 3)))
|
||||
z prev))
|
||||
(ch-fam-hervorheben fam 4)
|
||||
(if (null b) (setq b 0.0))
|
||||
(if (> b 0.0) (setq prev b n-bue (1+ n-bue)))))
|
||||
(setq famdat (cons (list idx fam z b) famdat))
|
||||
(foreach h fam (setq h2f (cons (cons h idx) h2f))))
|
||||
(setq famdat (reverse famdat))
|
||||
|
||||
;; --- Kreisel schreiben ---
|
||||
(foreach rec *ch-rec*
|
||||
(if (= (cadr rec) "KREISEL")
|
||||
(progn
|
||||
(setq h (cdr (assoc 5 (entget (car rec))))
|
||||
fs (cdr (assoc h h2f)))
|
||||
(if fs
|
||||
(progn
|
||||
(setq b (cadddr (assoc fs famdat)))
|
||||
(if (> b 0.0)
|
||||
(if (setq neu (ch-abzug-anwenden (nth 3 rec) b))
|
||||
(progn (ch-set-att (car rec) "MONTAGEHOEHE_m" (rtos neu 2 3))
|
||||
(setq n-kr (1+ n-kr)))))
|
||||
(setq ents (cons (car rec) ents)))))))
|
||||
|
||||
;; --- Strecken zuordnen ---
|
||||
(foreach rec *ch-rec*
|
||||
(if (and (member (cadr rec) '("VF" "GF")) (nth 4 rec) (nth 5 rec))
|
||||
(progn
|
||||
(setq lbl (nth 2 rec)
|
||||
fs (ch-kreisel-finden (nth 4 rec) (caddr (nth 4 rec)) elems
|
||||
*ch-zuordnung-xy-mm* *ch-zuordnung-z-mm*)
|
||||
fe (ch-kreisel-finden (nth 5 rec) (caddr (nth 5 rec)) elems
|
||||
*ch-zuordnung-xy-mm* *ch-zuordnung-z-mm*))
|
||||
(if (and fs fe)
|
||||
(if (ch-schleife-p fs fe (caddr (nth 4 rec)) (caddr (nth 5 rec)) 1.0)
|
||||
;; Flache Schleife am selben Kreisel: Buehne nicht ableitbar ->
|
||||
;; bleibt unentschieden und wird im Rest einzeln gefragt
|
||||
(princ (ssg-textf "chh-schleife" (list lbl)))
|
||||
(progn
|
||||
(setq fs (assoc (cdr (assoc fs h2f)) famdat)
|
||||
fe (assoc (cdr (assoc fe h2f)) famdat)
|
||||
kr (ch-strecke-abzug fs fe *ch-fam-max-hoehendiff-mm*))
|
||||
(setq ents (cons (car rec) ents))
|
||||
(cond
|
||||
((= (car kr) "konflikt")
|
||||
(setq n-konf (1+ n-konf))
|
||||
(princ (ssg-textf "chh-kreuz-konflikt"
|
||||
(list lbl (rtos (cadddr fs) 2 3) (rtos (cadddr fe) 2 3)))))
|
||||
((= (car kr) "hoehe")
|
||||
(setq n-konf (1+ n-konf))
|
||||
(princ (ssg-textf "chh-kreuz-hoehe"
|
||||
(list lbl (rtos (abs (- (caddr fs) (caddr fe))) 2 0)
|
||||
(rtos *ch-fam-max-hoehendiff-mm* 2 0)))))
|
||||
((> (cdr kr) 0.0)
|
||||
(if (setq neu (ch-abzug-anwenden (nth 3 rec) (cdr kr)))
|
||||
(progn
|
||||
(ch-set-att (car rec) "MONTAGEHOEHE_m" (rtos neu 2 3))
|
||||
(if (= (car kr) "innen")
|
||||
(setq n-innen (1+ n-innen))
|
||||
(setq n-kreuz (1+ n-kreuz))))
|
||||
(princ (ssg-textf "chh-strecke-neg"
|
||||
(list lbl (rtos (cdr kr) 2 3) (rtos (nth 3 rec) 2 3))))))
|
||||
))))))))
|
||||
(princ (ssg-text "chh-kein-kreisel")))
|
||||
|
||||
;; --- Rest: blockweise wie bisher ---
|
||||
(foreach rec *ch-rec*
|
||||
(if (not (member (car rec) ents))
|
||||
(progn
|
||||
(setq n-offen (1+ n-offen))
|
||||
(ch-write-montage (car rec) (nth 3 rec) (nth 2 rec)))))
|
||||
(princ (ssg-textf "chh-summe"
|
||||
(list (itoa n-fam) (itoa n-bue) (itoa n-kr) (itoa n-innen)
|
||||
(itoa n-kreuz) (itoa n-konf) (itoa n-offen))))
|
||||
)
|
||||
|
||||
;;; ============================================================
|
||||
;;; HAUPTBEFEHL (Phase 1 + 2, danach Phase 3)
|
||||
;;; ============================================================
|
||||
(defun c:HOEHEN_CHECK ( / ss i idx id items it ent ed nm lbl zc meas kez kaz
|
||||
montage inp delta mss
|
||||
@@ -292,6 +583,7 @@
|
||||
)
|
||||
)
|
||||
(setq n-kreisel 0 n-vf 0 n-gf 0 n-fixed 0 n-marked 0 n-fehler 0)
|
||||
(setq *ch-rec* nil)
|
||||
|
||||
;; Alte Markierungskreise entfernen (Idempotenz)
|
||||
(setq mss (ssget "_X" (list (cons 0 "CIRCLE") (cons 8 *ch-mark-layer*))))
|
||||
@@ -348,7 +640,7 @@
|
||||
(ch-move-z ent (- inp zc))
|
||||
(setq zc inp)
|
||||
(ch-set-att ent "HOEHE" (rtos zc 2 0))
|
||||
(setq montage (ch-write-montage ent (/ zc 1000.0) lbl))
|
||||
(setq montage (ch-montage-roh ent "KREISEL" (/ zc 1000.0) lbl nil))
|
||||
(setq n-fixed (1+ n-fixed))
|
||||
(princ (strcat "\n -> verschoben & gesetzt: HOEHE=" (rtos zc 2 0)
|
||||
" -> MONTAGEHOEHE_m=" (rtos montage 2 3))))
|
||||
@@ -362,7 +654,7 @@
|
||||
;; --- gueltig ---
|
||||
(progn
|
||||
(ch-set-att ent "HOEHE" (rtos zc 2 0))
|
||||
(setq montage (ch-write-montage ent (/ zc 1000.0) lbl))
|
||||
(setq montage (ch-montage-roh ent "KREISEL" (/ zc 1000.0) lbl nil))
|
||||
(princ (strcat "\n " lbl ": HOEHE=" (rtos zc 2 0)
|
||||
" -> MONTAGEHOEHE_m=" (rtos montage 2 3))))
|
||||
)
|
||||
@@ -399,10 +691,11 @@
|
||||
(progn
|
||||
(ch-set-att ent "HOEHE_VON_mm" (rtos kez 2 0))
|
||||
(ch-set-att ent "HOEHE_BIS_mm" (rtos kaz 2 0))
|
||||
(setq montage (ch-write-montage ent
|
||||
(setq montage (ch-montage-roh ent
|
||||
(if (wcmatch nm "GF_*") "GF" "VF")
|
||||
(if (wcmatch nm "GF_*")
|
||||
(/ kez 1000.0)
|
||||
(/ (+ kez kaz) 2000.0)) lbl))
|
||||
(/ (+ kez kaz) 2000.0)) lbl (cddr meas)))
|
||||
(setq n-fixed (1+ n-fixed))
|
||||
(princ (strcat "\n -> verschoben & gesetzt: VON=" (rtos kez 2 0)
|
||||
", BIS=" (rtos kaz 2 0)
|
||||
@@ -420,10 +713,11 @@
|
||||
(t
|
||||
(ch-set-att ent "HOEHE_VON_mm" (rtos kez 2 0))
|
||||
(ch-set-att ent "HOEHE_BIS_mm" (rtos kaz 2 0))
|
||||
(setq montage (ch-write-montage ent
|
||||
(setq montage (ch-montage-roh ent
|
||||
(if (wcmatch nm "GF_*") "GF" "VF")
|
||||
(if (wcmatch nm "GF_*")
|
||||
(/ kez 1000.0)
|
||||
(/ (+ kez kaz) 2000.0)) lbl))
|
||||
(/ (+ kez kaz) 2000.0)) lbl (cddr meas)))
|
||||
(princ (strcat "\n " lbl ": HOEHE_VON_mm=" (rtos kez 2 0)
|
||||
", HOEHE_BIS_mm=" (rtos kaz 2 0)
|
||||
" -> MONTAGEHOEHE_m=" (rtos montage 2 3))))
|
||||
@@ -431,6 +725,8 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
;; Phase 3: Buehnen-Familien (arbeitet das Register *ch-rec* ab)
|
||||
(ch-phase3)
|
||||
(princ (strcat "\n--------------------------------------------"
|
||||
"\n Kreisel: " (itoa n-kreisel)
|
||||
" VF: " (itoa n-vf)
|
||||
@@ -449,4 +745,4 @@
|
||||
)
|
||||
|
||||
(princ "\n>>> check_hoehen.lsp geladen (Phase 1-3). Befehl: HOEHEN_CHECK")
|
||||
(princ)
|
||||
(princ)
|
||||
@@ -2397,6 +2397,11 @@
|
||||
;; VB_*/TV_* = Omniflo-Verbinder (siehe pattern_verbinder in
|
||||
;; cfg/export.cfg, OMNI_TV_* in OmniModulInsert.lsp). export_sivas.py
|
||||
;; fuehrt sie ueber TEILEART/ARTINR im allgemeinen Omniflo-Zweig.
|
||||
;; KF_* = Kettenfoerderer/Schraegfoerderer Stahl (siehe
|
||||
;; pattern_kettenfoerderer in cfg/export.cfg, KettenFoerderer.lsp). Wie
|
||||
;; GR_* eine selbst zusammengebaute Baugruppe mit eigenen Attributen
|
||||
;; (TEILEART/ARTINR), darum eigenstaendig gesammelt - die drei Bausteine
|
||||
;; darin werden NICHT einzeln gezaehlt.
|
||||
;; Bloecke auf GEFRORENEN Layern (und die Hilfsobjekte gefrorener VF_n/GF_n)
|
||||
;; werden ausgelassen, solange *csv-gefrorene-ausschliessen* an ist (Standard,
|
||||
;; Dialog CSV_EXPORT_KONFIG); ausgeschaltete Layer zaehlen nicht als gefroren.
|
||||
@@ -2449,6 +2454,7 @@
|
||||
(wcmatch bname (export:pattern "pattern_ausgang" "Ausgang*"))
|
||||
(wcmatch bname (export:pattern "pattern_geruest" "GR_*"))
|
||||
(wcmatch bname (export:pattern "pattern_verbinder" "VB_*,TV_*"))
|
||||
(wcmatch bname (export:pattern "pattern_kettenfoerderer" "KF_*"))
|
||||
(wcmatch bname (export:pattern "pattern_unit_marker" "ZZ_UNIT_MARKER*"))
|
||||
;; Rein numerische Namen = Omniflo SivasNr (Boegen/Weichen)
|
||||
;; Rein LISP-intern (Python klassifiziert Omniflo stattdessen
|
||||
@@ -2915,8 +2921,48 @@
|
||||
)
|
||||
|
||||
|
||||
;; Vor dem Sivas-Export anbieten, den Hoehen-Check (HOEHEN_CHECK, check_hoehen.lsp)
|
||||
;; auszufuehren: Er setzt die Montagehoehen inkl. Buehnenabzug, den der Export
|
||||
;; selbst nicht kennt. Bewusst eine Rueckfrage (Vorgabe Ja, Enter startet den
|
||||
;; Check, "Nein" ueberspringt ihn) statt automatisch: der Check stellt Fragen
|
||||
;; und wuerde Hand-Korrekturen von MONTAGEHOEHE_m bei jedem Export ueberschreiben. Entfaellt ohne GUI und bei abgeschaltetem
|
||||
;; Schalter *csv-hoehencheck-fragen* (automatische Tests).
|
||||
(if (null *csv-hoehencheck-fragen*) (setq *csv-hoehencheck-fragen* T))
|
||||
|
||||
(defun csv:hoehencheck-anbieten ()
|
||||
(if (and *csv-hoehencheck-fragen*
|
||||
(ssg-gui-p)
|
||||
(car (atoms-family 1 '("SSG-IN-YESNO")))
|
||||
(ssg-in-yesno (ssg-text "exp-hoehencheck-frage") T))
|
||||
(progn
|
||||
(ssg-ensure "check_hoehen")
|
||||
(if (car (atoms-family 1 '("C:HOEHEN_CHECK")))
|
||||
(c:HOEHEN_CHECK)
|
||||
(princ (ssg-text "exp-hoehencheck-fehlt")))))
|
||||
)
|
||||
|
||||
;; Vor dem Sivas-Export die Zeichnung bereinigen (BricsCAD-Befehl BEREINIG /
|
||||
;; PURGE): entfernt unbenutzte Bloecke, Layer, Linientypen usw. samt
|
||||
;; verschachtelter Elemente. Sprachunabhaengig ueber -PURGE mit "_All".
|
||||
;; Schalter *csv-bereinigen-vor-export* (Standard an; Tests schalten ab, da
|
||||
;; die Zeichnung veraendert wird).
|
||||
(if (null *csv-bereinigen-vor-export*) (setq *csv-bereinigen-vor-export* 'an))
|
||||
|
||||
(defun csv:bereinigen ()
|
||||
(if (and (eq *csv-bereinigen-vor-export* 'an) (ssg-gui-p))
|
||||
(progn
|
||||
(princ (ssg-text "exp-bereinigen"))
|
||||
;; Zweimal, weil das Entfernen eines Blocks dessen Layer/Linientypen
|
||||
;; erst frei macht (zusaetzlich zur Nested-Option)
|
||||
(repeat 2
|
||||
(vl-catch-all-apply
|
||||
'(lambda () (command "_.-PURGE" "_All" "*" "_No"))))
|
||||
(princ))))
|
||||
|
||||
;; --- EXPORTSIVAS: Sivas-spezifischer CSV-Export mit Summierungszeilen ---
|
||||
(defun c:EXPORTSIVAS ()
|
||||
(csv:bereinigen)
|
||||
(csv:hoehencheck-anbieten)
|
||||
(csv:run-export "EXPORTSIVAS"
|
||||
(export:filename "sivas_script")
|
||||
(export:filename "sivas_csv")
|
||||
|
||||
@@ -1264,6 +1264,13 @@
|
||||
("L_VF_m" "0.000")
|
||||
("ANTRIEBFAHRTRICHTUNG" "Auf")
|
||||
("VF_WINKEL" "0")
|
||||
;; Hoehe je VF-SEGMENT in Metern (3 Nachkommastellen), kommagetrennt und
|
||||
;; Eintrag fuer Eintrag parallel zu L_VF_m/VF_WINKEL: Mittelwert aus KS_EIN
|
||||
;; und KS_AUS des jeweiligen geraden VF-Abschnitts (vf-vfhoehe-segment in
|
||||
;; vf_core.lsp, erfasst in vfs-vf-koerper). Zwischen Umlenk- und
|
||||
;; Motorstation koennen mehrere Abschnitte liegen (auf/ab/horizontal).
|
||||
;; Sivas-Merkmale 4433-4437 (bis zu fuenf Abschnitte je Gruppe).
|
||||
("VF_HOEHE_m" "0.000")
|
||||
("VF_Bogen_A_90" "0")
|
||||
("VF_Bogen_A_60" "0")
|
||||
("VF_Bogen_A_30" "0")
|
||||
|
||||
+13
-1
@@ -86,8 +86,20 @@
|
||||
;; Einheiten-Proxies selbst ab; Separator-/Element-
|
||||
;; Kopien sammeln sich dagegen an - Zeichnung mit
|
||||
;; eingeschaltetem Schalter nicht speichern.
|
||||
;; kf-zeit - Zwischenzeiten beim Aufruf von KETTENFOERDERER
|
||||
;; (Daten lesen / Dialogaufbau), siehe kf-zeit in
|
||||
;; KettenFoerderer.lsp. Standard 0 - nur einschalten,
|
||||
;; wenn der Dialog spuerbar verzoegert erscheint.
|
||||
;; testlauf - Laufprotokoll je Test von SSG_RUN_ALL_TESTS nach
|
||||
;; DXFM_LOG/testlauf_<name>.dbg (eigene Datei, nicht
|
||||
;; ueber *dbg-path*; jede Zeile sofort geschrieben,
|
||||
;; damit bei einem haengenden Test der letzte Schritt
|
||||
;; sichtbar ist). Standard 1 - kostet nur ein paar
|
||||
;; Zeilen je Test, siehe testrun:log in
|
||||
;; tests/test_run_all.lsp.
|
||||
;; ------------------------------------------------------------
|
||||
(foreach nm '(("vf-sepliste" . 1) ("csv_leave_proxies" . 0))
|
||||
(foreach nm '(("vf-sepliste" . 1) ("csv_leave_proxies" . 0) ("kf-zeit" . 0)
|
||||
("testlauf" . 1))
|
||||
(if (not (assoc (car nm) *dbg-schalter*))
|
||||
(setq *dbg-schalter* (cons nm *dbg-schalter*))))
|
||||
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
;; das ID-ATTDEF steht seit *geruest-attrib-defs* zur Verfuegung.
|
||||
;; VB_*/TV_* (Omniflo-Verbinder, siehe pattern_verbinder in
|
||||
;; cfg/export.cfg) ebenso - fest im Code wie GR_*.
|
||||
;; KF_* (Kettenfoerderer, siehe pattern_kettenfoerderer in cfg/export.cfg,
|
||||
;; KettenFoerderer.lsp) ebenso - das ID-ATTDEF kommt aus kf-attrib-defs, das
|
||||
;; auf dem gemeinsamen Strecken-Schema aufsetzt und darum ID bereits fuehrt.
|
||||
;; Gefaellebogen_* (siehe pattern_nested_bogen in cfg/export.cfg): einer der
|
||||
;; Bausteine einer GF-Kette, verpackt in VF_n/GF_n; wird beim Export ebenso
|
||||
;; als temporaere Kopie ausgepackt wie die uebrigen Vario_*/Staustrecke_*-
|
||||
@@ -84,6 +87,7 @@
|
||||
(wcmatch bname "Eingang*,Ausgang*")
|
||||
(wcmatch bname "GR_*")
|
||||
(wcmatch bname "VB_*,TV_*")
|
||||
(wcmatch bname "KF_*")
|
||||
(wcmatch bname "#*")
|
||||
)
|
||||
(ssadd ename ss-out)
|
||||
|
||||
+283
-4
@@ -72,11 +72,31 @@
|
||||
;; Block unter seinem effektiven, dim-suffigierten Namen und GIBT DIESEN ZURUECK,
|
||||
;; damit Aufrufer ihn zum Einfuegen (vla-InsertBlock/tblsearch) verwenden.
|
||||
;; Meldung nur bei Fehlschlag.
|
||||
(defun ensure-block-loaded (blockname / )
|
||||
(if (not (ssg-ils-block-laden blockname))
|
||||
(princ (ssg-textf "vfc-fehler-block-datei-fehlt" (list blockname)))
|
||||
;; Sonderfall Bloecke OHNE Dimensionssuffix (data/omniflo/<Dim>/, z.B. die
|
||||
;; Kettenfoerderer-Bausteine): ssg-ils-blockname wuerde "KF_UM_26" zu
|
||||
;; "KF_UM_26_2D" machen - das ist die Konvention der FLACHEN Ablage data/ils,
|
||||
;; die Omniflo-Ordner arbeiten stattdessen mit getrennten Verzeichnissen und
|
||||
;; unsuffigierten Namen. Liegt die Definition unter dem Rohnamen bereits in
|
||||
;; der Zeichnung und gibt es KEINE suffigierte Variante, wird der Rohname
|
||||
;; unveraendert verwendet. Die Bedingung ist bewusst eng gefasst (BEIDE Teile
|
||||
;; muessen zutreffen), damit die Dim-Aufloesung fuer alle data/ils-Bloecke
|
||||
;; unberuehrt bleibt: dort existiert die suffigierte Variante, sobald der
|
||||
;; Block geladen ist, und der erste Zweig greift nie.
|
||||
;; Realer Fehler, den das behebt: die KS-Messung eines KF-Bausteins lief ins
|
||||
;; Leere und meldete "KS_EIN/KS_AUS fehlt", obwohl beide KS im Block vorhanden
|
||||
;; waren - gesucht wurde nur ein Blockname, den es nicht gibt.
|
||||
(defun ensure-block-loaded (blockname / eff)
|
||||
(setq eff (ssg-ils-blockname blockname))
|
||||
(if (and (not (tblsearch "BLOCK" eff))
|
||||
(tblsearch "BLOCK" blockname))
|
||||
blockname
|
||||
(progn
|
||||
(if (not (ssg-ils-block-laden blockname))
|
||||
(princ (ssg-textf "vfc-fehler-block-datei-fehlt" (list blockname)))
|
||||
)
|
||||
eff
|
||||
)
|
||||
)
|
||||
(ssg-ils-blockname blockname)
|
||||
)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
@@ -379,6 +399,265 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; KS-ORIENTIERUNG + SKALIERTE KS-EINFUEGUNG
|
||||
;; ------------------------------------------------------------
|
||||
;; Ergaenzt fuer den Kettenfoerderer (KettenFoerderer.lsp): dort ist die
|
||||
;; Neigung KEIN freier Parameter, sondern steckt fest in der Geometrie der
|
||||
;; Blockvarianten (KF_UM_26 gegen KF_UM_30). Der Einbauwinkel eines
|
||||
;; Folgebausteins ergibt sich darum aus der RICHTUNG des KS_AUS seines
|
||||
;; Vorgaengers. Dafuer reicht der bisher allein ausgewertete KS-URSPRUNG
|
||||
;; nicht - die X-Achse des KS muss mit gelesen werden. extract-ks-from-block
|
||||
;; liefert sie als (origin x-end y-end z-end) bereits mit, sie wurde bislang
|
||||
;; nur von keinem Aufrufer genutzt.
|
||||
|
||||
;; Winkel der X-Achse eines KS-Eintrags in der XY-Ebene, in Grad (-180..180).
|
||||
;; ks-eintrag = (origin x-end y-end z-end), also genau der cadr-Teil eines
|
||||
;; extract-ks-from-block-Ergebnisses. Rueckgabe nil, wenn die X-Achse keine
|
||||
;; XY-Laenge hat (senkrecht stehendes KS) oder der Eintrag unbrauchbar ist.
|
||||
(defun ks-xy-winkel (ks-eintrag / org xend dx dy)
|
||||
(if (and ks-eintrag (listp ks-eintrag) (>= (length ks-eintrag) 2)
|
||||
(listp (car ks-eintrag)) (listp (cadr ks-eintrag)))
|
||||
(progn
|
||||
(setq org (car ks-eintrag) xend (cadr ks-eintrag))
|
||||
(setq dx (- (car xend) (car org))
|
||||
dy (- (cadr xend) (cadr org)))
|
||||
(if (< (+ (* dx dx) (* dy dy)) 1e-12)
|
||||
nil
|
||||
(/ (* 180.0 (atan dy dx)) pi)))
|
||||
nil))
|
||||
|
||||
;; Winkel auf -180..180 Grad normalisieren. Reiner Rechenkern.
|
||||
(defun ks-winkel-normalisieren (w)
|
||||
(if (null w)
|
||||
nil
|
||||
(progn
|
||||
(setq w (float w))
|
||||
(while (> w 180.0) (setq w (- w 360.0)))
|
||||
(while (<= w -180.0) (setq w (+ w 360.0)))
|
||||
w)))
|
||||
|
||||
;; Lokalen KS_AUS-KS_EIN-Versatz eines Blocks als (dx dy dz) liefern.
|
||||
;; ks-data = Ergebnis von extract-ks-from-block/ks-block-messen.
|
||||
;; Rueckgabe nil, wenn eines der beiden KS fehlt.
|
||||
(defun ks-versatz (ks-data / ein aus)
|
||||
(setq ein (cadr (assoc "KS_EIN" ks-data))
|
||||
aus (cadr (assoc "KS_AUS" ks-data)))
|
||||
(if (and ein aus)
|
||||
(list (- (car (car aus)) (car (car ein)))
|
||||
(- (cadr (car aus)) (cadr (car ein)))
|
||||
(- (caddr (car aus)) (caddr (car ein))))
|
||||
nil))
|
||||
|
||||
;; Misst KS_EIN/KS_AUS eines Blocks, ohne eine bleibende Einfuegung zu
|
||||
;; hinterlassen: der Block wird bei Massstab 1 am Ursprung eingefuegt,
|
||||
;; vermessen und wieder geloescht. extract-ks-from-block cached das Ergebnis
|
||||
;; je Blockname, der zweite Aufruf kostet also nichts mehr.
|
||||
;; Rueckgabe wie extract-ks-from-block (Blockkoordinaten), sonst nil.
|
||||
(defun ks-block-messen (blockname / eff temp-obj daten)
|
||||
(setq eff (ensure-block-loaded blockname))
|
||||
(if (tblsearch "BLOCK" eff)
|
||||
(progn
|
||||
(setq temp-obj (vla-InsertBlock modelspace
|
||||
(vlax-3D-point '(0 0 0)) eff 1.0 1.0 1.0 0))
|
||||
(setq daten (extract-ks-from-block temp-obj))
|
||||
(if (not (vlax-erased-p temp-obj)) (vla-Delete temp-obj))
|
||||
daten)
|
||||
nil))
|
||||
|
||||
;; --- Block per KS_EIN/KS_AUS einfuegen, in X SKALIERT (nur Rz-Rotation) ---
|
||||
;; Wie insert-block-by-ks, zusaetzlich mit X-Massstab skala - fuer laengen-
|
||||
;; variable Zwischenstuecke (Kettenfoerderer KF_LAENGE, dieselbe Rolle wie
|
||||
;; die Staustrecke beim VarioFoerderer). Die lokalen KS-Punkte werden VOR der
|
||||
;; Rotation in X mitskaliert; nur so liegt KS_EIN exakt auf einfuegepunkt und
|
||||
;; der zurueckgegebene KS_AUS traegt den skalierten Versatz.
|
||||
;; Rueckgabe: Weltpunkt von KS_AUS (fuer die Verkettung), sonst einfuegepunkt.
|
||||
(defun insert-block-ks-skaliert (blockname einfuegepunkt hz skala /
|
||||
block-obj ks-data ks-ein ks-aus rad-h chv shv
|
||||
ein-x ein-y ein-z aus-x dx-loc dy-loc dz-loc
|
||||
offset ausgang)
|
||||
(if (or (null einfuegepunkt) (not (listp einfuegepunkt)))
|
||||
(progn
|
||||
(princ (ssg-textf "vfc-fehler-ungueltiger-einfuegepunkt" (list blockname)))
|
||||
(exit))
|
||||
)
|
||||
(if (or (null skala) (<= skala 0.0)) (setq skala 1.0))
|
||||
(setq blockname (ensure-block-loaded blockname))
|
||||
(if (not (tblsearch "BLOCK" blockname))
|
||||
(progn
|
||||
(princ (ssg-textf "vfc-fehler-block-nicht-in-bibliothek-abgebrochen" (list blockname)))
|
||||
(exit))
|
||||
)
|
||||
(princ (ssg-textf "vfc-fuege-block-ein-hz" (list blockname (rtos (float hz) 2 1) (chr 176))))
|
||||
(setq rad-h (* (float hz) (/ pi 180.0)))
|
||||
(setq chv (cos rad-h) shv (sin rad-h))
|
||||
;; KS am UNSKALIERTEN Block messen (der Cache arbeitet je Blockname), die
|
||||
;; lokalen Punkte danach selbst in X skalieren.
|
||||
(setq ks-data (ks-block-messen blockname))
|
||||
(setq ks-ein (cadr (assoc "KS_EIN" ks-data)))
|
||||
(setq ks-aus (cadr (assoc "KS_AUS" ks-data)))
|
||||
(setq block-obj (vla-InsertBlock modelspace
|
||||
(vlax-3D-point '(0 0 0))
|
||||
blockname skala 1.0 1.0 0))
|
||||
(ssg-ils-block-auf-ebene block-obj blockname)
|
||||
(if (> (abs hz) 0.0001)
|
||||
(vla-TransformBy block-obj (vlax-tmatrix
|
||||
(list (list chv (- shv) 0 0)
|
||||
(list shv chv 0 0)
|
||||
(list 0 0 1 0)
|
||||
(list 0 0 0 1))))
|
||||
)
|
||||
(if (and ks-ein ks-aus)
|
||||
(progn
|
||||
(setq ein-x (* skala (car (car ks-ein)))
|
||||
ein-y (cadr (car ks-ein))
|
||||
ein-z (caddr (car ks-ein)))
|
||||
(setq aus-x (* skala (car (car ks-aus))))
|
||||
(setq offset (list
|
||||
(- (car einfuegepunkt) (- (* chv ein-x) (* shv ein-y)))
|
||||
(- (cadr einfuegepunkt) (+ (* shv ein-x) (* chv ein-y)))
|
||||
(- (caddr einfuegepunkt) ein-z)))
|
||||
(vla-Move block-obj
|
||||
(vlax-3D-point '(0 0 0))
|
||||
(vlax-3D-point offset))
|
||||
(setq dx-loc (- aus-x ein-x))
|
||||
(setq dy-loc (- (cadr (car ks-aus)) ein-y))
|
||||
(setq dz-loc (- (caddr (car ks-aus)) ein-z))
|
||||
(setq ausgang (list
|
||||
(+ (car einfuegepunkt) (- (* chv dx-loc) (* shv dy-loc)))
|
||||
(+ (cadr einfuegepunkt) (+ (* shv dx-loc) (* chv dy-loc)))
|
||||
(+ (caddr einfuegepunkt) dz-loc)))
|
||||
(ssg-sepliste-dbg
|
||||
(strcat "insert-block-ks-skaliert " blockname
|
||||
" hz=" (rtos (float hz) 2 2) " skala=" (rtos (float skala) 2 4)
|
||||
" einfuegepunkt=" (ssg-sepliste-dbg-pt einfuegepunkt)
|
||||
" offset(=Gruppencode 10)=" (ssg-sepliste-dbg-pt offset)
|
||||
" ausgang=" (ssg-sepliste-dbg-pt ausgang)))
|
||||
(princ (ssg-textf "vfc-ks-aus-xyz"
|
||||
(list (rtos (car ausgang) 2 2) (rtos (cadr ausgang) 2 2) (rtos (caddr ausgang) 2 2))))
|
||||
ausgang
|
||||
)
|
||||
(progn
|
||||
(princ (ssg-text "vfc-warnung-ks-nicht-gefunden"))
|
||||
einfuegepunkt
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; FREI ROTIERTE KS-EINFUEGUNG (beliebige 3x3-Matrix)
|
||||
;; ------------------------------------------------------------
|
||||
;; Verallgemeinerung von insert-block-by-ks/insert-block-ks-skaliert: statt
|
||||
;; einer festen Rz- bzw. Rz*Ry-Drehung nimmt sie eine FERTIGE 3x3-Rotations-
|
||||
;; matrix entgegen. Noetig geworden fuer AUFRECHT eingebaute Baugruppen: der
|
||||
;; Kettenfoerderer ist in der XY-Ebene gezeichnet (X = Fahrtrichtung,
|
||||
;; Y = Hoehe), soll aber im Modell stehen - seine Hoehe muss also nach Z. Das
|
||||
;; ist eine Drehung um X, die weder insert-block-by-ks (nur Rz) noch
|
||||
;; ssg-rot-matrix-zy (Rz*Ry) erzeugen kann.
|
||||
;;
|
||||
;; Bewusst matrixbasiert statt mit einem weiteren Winkelparameter: die
|
||||
;; Aufrichtung ist nur EIN Anwendungsfall, und jeder weitere haette eine
|
||||
;; weitere Spezialfunktion gebraucht. Den Aufrufern bleibt freigestellt,
|
||||
;; welche Drehungen sie kombinieren (beim Kettenfoerderer
|
||||
;; Rz(basis) * Rx(90) * Rz(eigen), siehe kf-matrix-aufrecht).
|
||||
|
||||
;; Elementare Rotationsmatrizen (3x3, Winkel in GRAD).
|
||||
(defun ks-rot-x (grad / r c s)
|
||||
(setq r (* (float grad) (/ pi 180.0)) c (cos r) s (sin r))
|
||||
(list (list 1.0 0.0 0.0)
|
||||
(list 0.0 c (- s))
|
||||
(list 0.0 s c )))
|
||||
|
||||
(defun ks-rot-y (grad / r c s)
|
||||
(setq r (* (float grad) (/ pi 180.0)) c (cos r) s (sin r))
|
||||
(list (list c 0.0 s )
|
||||
(list 0.0 1.0 0.0)
|
||||
(list (- s) 0.0 c )))
|
||||
|
||||
(defun ks-rot-z (grad / r c s)
|
||||
(setq r (* (float grad) (/ pi 180.0)) c (cos r) s (sin r))
|
||||
(list (list c (- s) 0.0)
|
||||
(list s c 0.0)
|
||||
(list 0.0 0.0 1.0)))
|
||||
|
||||
;; 3x3-Rotation in die 4x4-Form bringen, die vla-TransformBy erwartet.
|
||||
(defun ks-mat3->mat4 (R)
|
||||
(list (append (car R) '(0.0))
|
||||
(append (cadr R) '(0.0))
|
||||
(append (caddr R) '(0.0))
|
||||
'(0.0 0.0 0.0 1.0)))
|
||||
|
||||
;; --- Block per KS_EIN/KS_AUS einfuegen, frei rotiert und in X skaliert ---
|
||||
;; blockname Rohname (wird ueber ensure-block-loaded aufgeloest)
|
||||
;; einfuegepunkt Weltpunkt, auf den KS_EIN zu liegen kommt
|
||||
;; R 3x3-Rotationsmatrix (Blockkoordinaten -> Welt)
|
||||
;; skala X-Massstab (1.0 = unskaliert)
|
||||
;; Rueckgabe: Weltpunkt von KS_AUS (fuer die Verkettung), sonst einfuegepunkt.
|
||||
;;
|
||||
;; Reihenfolge wie bei den uebrigen Primitiven: am Ursprung einfuegen,
|
||||
;; skalieren, drehen, dann so verschieben, dass das GEDREHTE KS_EIN exakt auf
|
||||
;; einfuegepunkt liegt. Die lokalen KS-Punkte werden dabei zuerst in X
|
||||
;; mitskaliert - sonst zeigt der zurueckgegebene KS_AUS am skalierten Block
|
||||
;; vorbei.
|
||||
(defun insert-block-ks-matrix (blockname einfuegepunkt R skala /
|
||||
block-obj ks-data ks-ein ks-aus
|
||||
ein-lok aus-lok ein-welt aus-welt offset ausgang)
|
||||
(if (or (null einfuegepunkt) (not (listp einfuegepunkt)))
|
||||
(progn
|
||||
(princ (ssg-textf "vfc-fehler-ungueltiger-einfuegepunkt" (list blockname)))
|
||||
(exit))
|
||||
)
|
||||
(if (or (null skala) (<= skala 0.0)) (setq skala 1.0))
|
||||
(setq blockname (ensure-block-loaded blockname))
|
||||
(if (not (tblsearch "BLOCK" blockname))
|
||||
(progn
|
||||
(princ (ssg-textf "vfc-fehler-block-nicht-in-bibliothek-abgebrochen" (list blockname)))
|
||||
(exit))
|
||||
)
|
||||
(setq ks-data (ks-block-messen blockname))
|
||||
(setq ks-ein (cadr (assoc "KS_EIN" ks-data)))
|
||||
(setq ks-aus (cadr (assoc "KS_AUS" ks-data)))
|
||||
(setq block-obj (vla-InsertBlock modelspace
|
||||
(vlax-3D-point '(0 0 0))
|
||||
blockname skala 1.0 1.0 0))
|
||||
(ssg-ils-block-auf-ebene block-obj blockname)
|
||||
(vla-TransformBy block-obj (vlax-tmatrix (ks-mat3->mat4 R)))
|
||||
(if (and ks-ein ks-aus)
|
||||
(progn
|
||||
;; lokale KS-Punkte, in X mitskaliert
|
||||
(setq ein-lok (list (* skala (car (car ks-ein)))
|
||||
(cadr (car ks-ein))
|
||||
(caddr (car ks-ein))))
|
||||
(setq aus-lok (list (* skala (car (car ks-aus)))
|
||||
(cadr (car ks-aus))
|
||||
(caddr (car ks-aus))))
|
||||
(setq ein-welt (mat3-mul-vec3 R ein-lok))
|
||||
(setq aus-welt (mat3-mul-vec3 R aus-lok))
|
||||
(setq offset (list (- (car einfuegepunkt) (car ein-welt))
|
||||
(- (cadr einfuegepunkt) (cadr ein-welt))
|
||||
(- (caddr einfuegepunkt) (caddr ein-welt))))
|
||||
(vla-Move block-obj
|
||||
(vlax-3D-point '(0 0 0))
|
||||
(vlax-3D-point offset))
|
||||
(setq ausgang (list (+ (car einfuegepunkt) (- (car aus-welt) (car ein-welt)))
|
||||
(+ (cadr einfuegepunkt) (- (cadr aus-welt) (cadr ein-welt)))
|
||||
(+ (caddr einfuegepunkt) (- (caddr aus-welt) (caddr ein-welt)))))
|
||||
(ssg-sepliste-dbg
|
||||
(strcat "insert-block-ks-matrix " blockname
|
||||
" skala=" (rtos (float skala) 2 4)
|
||||
" einfuegepunkt=" (ssg-sepliste-dbg-pt einfuegepunkt)
|
||||
" ks_ein_welt=" (ssg-sepliste-dbg-pt ein-welt)
|
||||
" ks_aus_welt=" (ssg-sepliste-dbg-pt aus-welt)
|
||||
" ausgang=" (ssg-sepliste-dbg-pt ausgang)))
|
||||
ausgang
|
||||
)
|
||||
(progn
|
||||
(princ (ssg-text "vfc-warnung-ks-nicht-gefunden"))
|
||||
einfuegepunkt
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; SEPLISTE: Separator-/AS-/ES-Reihenfolge als XDATA am fertigen Wrapper
|
||||
;; ------------------------------------------------------------
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
(load (strcat base-path "OmniModulInsert.lsp") "OmniModulInsert.lsp nicht gefunden")
|
||||
(load (strcat base-path "Tro_Edit.lsp") "Tro_Edit.lsp nicht gefunden")
|
||||
(load (strcat base-path "Connection_Edit.lsp") "Connection_Edit.lsp nicht gefunden")
|
||||
(load (strcat base-path "Jam_Edit.lsp") "Jam_Edit.lsp nicht gefunden")
|
||||
(load (strcat base-path "SSG_LIB_Commands.lsp") "SSG_LIB_Commands.lsp nicht gefunden")
|
||||
;; Werkzeuge: ssg_texttools nutzt ssg_blocktools, beide nutzen ssg_input
|
||||
(load (strcat base-path "ssg_blocktools.lsp") "ssg_blocktools.lsp nicht gefunden")
|
||||
|
||||
@@ -218,6 +218,102 @@
|
||||
(defun vf-motorseite-aktuell ( / )
|
||||
(if (member *vf-motorseite* '("links" "rechts")) *vf-motorseite* "rechts"))
|
||||
|
||||
;; ============================================================
|
||||
;; VF-HOEHE JE SEGMENT (Attribut VF_HOEHE_m, Sivas 4433-4437)
|
||||
;; ============================================================
|
||||
;; Sivas erwartet je Streckengruppe bis zu fuenf Variofoerderer-Hoehen. Ein
|
||||
;; Eintrag gehoert zu EINEM VF-Segment (Koerper) - nicht zu einer ganzen
|
||||
;; Foerdereinheit und nicht zur ganzen Kette (Nutzer-Korrektur 2026-10-21):
|
||||
;;
|
||||
;; Hoehe = Mittelwert aus KS_EIN und KS_AUS DIESES Segments.
|
||||
;;
|
||||
;; Eine Kette, die durch Vario-Boegen in drei Abschnitte geteilt ist, bekommt
|
||||
;; dadurch drei Werte - die Liste laeuft Eintrag fuer Eintrag parallel zu
|
||||
;; L_VF_m, VF_WINKEL und ANTRIEBFAHRTRICHTUNG.
|
||||
;;
|
||||
;; Erfasst wird an genau EINER Stelle: vfs-vf-koerper baut ein Segment, kennt
|
||||
;; dessen KS_EIN als Eingangspunkt und liefert dessen KS_AUS zurueck. Alle
|
||||
;; Modi (Standard, Etage, Linienzug) bauen ihre VF-Koerper darueber, deshalb
|
||||
;; muss der verzweigte Bau-Pfad selbst nicht angefasst werden.
|
||||
;;
|
||||
;; Einheit: Meter mit 3 Nachkommastellen (wie L_VF_m), kommagetrennt ueber
|
||||
;; vfl-join-komma - Reihenfolge = Bau-Reihenfolge.
|
||||
(if (not (boundp '*vf-acc-vfhoehe*)) (setq *vf-acc-vfhoehe* '()))
|
||||
|
||||
(defun vf-vfhoehe-reset ()
|
||||
(setq *vf-acc-vfhoehe* '()))
|
||||
|
||||
;; Ein VF-Segment erfassen: z-ein = Z des KS_EIN, z-aus = Z des KS_AUS (mm).
|
||||
;; Fehlt einer der Werte, wird NICHTS angehaengt - sonst verschoebe sich die
|
||||
;; Liste gegen L_VF_m/VF_WINKEL und im Export landete eine Hoehe beim falschen
|
||||
;; Foerderer.
|
||||
(defun vf-vfhoehe-segment (z-ein z-aus)
|
||||
(if (and (numberp z-ein) (numberp z-aus))
|
||||
(setq *vf-acc-vfhoehe*
|
||||
(append *vf-acc-vfhoehe* (list (vf-meter-3 (/ (+ z-ein z-aus) 2.0)))))))
|
||||
|
||||
;; Bequemes Paar fuer die Bau-Pfade: vor dem Einbau den Startpunkt merken,
|
||||
;; danach mit dem Endpunkt abschliessen. Beide geben ihren Punkt zurueck,
|
||||
;; lassen sich also ohne zusaetzliche lokale Variable einsetzen:
|
||||
;;
|
||||
;; (vf-vfhoehe-merke pt)
|
||||
;; (setq pt (insert-inclined-scaled-block ...))
|
||||
;; (vf-vfhoehe-schliesse pt)
|
||||
;;
|
||||
;; Noetig, weil die VF-Segmente NICHT alle ueber vfs-vf-koerper laufen: die
|
||||
;; horizontalen Zwischenstuecke und die Modus-2-Fuellstuecke bauen direkt mit
|
||||
;; insert-inclined-scaled-block. Wurde dort nicht erfasst, fehlten ihre
|
||||
;; Hoehen und VF_HOEHE_m war kuerzer als L_VF_m (realer Befund 2026-10-21:
|
||||
;; L_VF_m hatte drei Eintraege, VF_HOEHE_m nur einen).
|
||||
;;
|
||||
;; REGEL: Jede Stelle, die (vfl-acc-vf-seg ...) aufruft, MUSS auch eine Hoehe
|
||||
;; erfassen - sonst verschiebt sich die Liste gegen L_VF_m/VF_WINKEL und im
|
||||
;; Sivas-Export landet eine Hoehe beim falschen Foerderer.
|
||||
(if (not (boundp '*vf-vfhoehe-merk*)) (setq *vf-vfhoehe-merk* nil))
|
||||
|
||||
(defun vf-vfhoehe-merke (pt)
|
||||
(setq *vf-vfhoehe-merk* (if (listp pt) (caddr pt) nil))
|
||||
pt)
|
||||
|
||||
(defun vf-vfhoehe-schliesse (pt)
|
||||
(vf-vfhoehe-segment *vf-vfhoehe-merk* (if (listp pt) (caddr pt) nil))
|
||||
(setq *vf-vfhoehe-merk* nil)
|
||||
pt)
|
||||
|
||||
;; SONDERFALL Standard/Etage: Hoehe ueber die GANZE Kette.
|
||||
;;
|
||||
;; Diese beiden Typen haben nur EINEN Motor und nur EINEN geraden
|
||||
;; VF-Abschnitt (Nutzer-Vorgabe 2026-10-21). Statt des Segmentwerts gilt dort
|
||||
;; der Mittelwert der ganzen Anlage:
|
||||
;; Anfang = KS_EIN des AS-Elements (Startpunkt der Anlage)
|
||||
;; Ende = KS_AUS des ES-Elements (Rueckgabewert der Einfuegefunktion)
|
||||
;;
|
||||
;; ERSETZT die Liste bewusst, statt anzuhaengen: vfs-vf-koerper hat beim Bau
|
||||
;; bereits den Segmentwert gesammelt, der hier nicht gelten soll. Ergebnis ist
|
||||
;; genau ein Eintrag.
|
||||
;;
|
||||
;; Gerechnet wird aus der GEBAUTEN Geometrie, nicht aus der Soll-Vorgabe
|
||||
;; (anders als MONTAGEHOEHE_m, dessen hoehe-bis aus deltaH abgeleitet ist).
|
||||
;; Beide Hoehen in mm.
|
||||
(defun vf-vfhoehe-kette (z-anfang z-ende)
|
||||
(if (and (numberp z-anfang) (numberp z-ende))
|
||||
(setq *vf-acc-vfhoehe* (list (vf-meter-3 (/ (+ z-anfang z-ende) 2.0))))
|
||||
(setq *vf-acc-vfhoehe* '())))
|
||||
|
||||
;; Millimeter -> Meter als String mit GENAU 3 Nachkommastellen.
|
||||
;;
|
||||
;; (rtos x 2 3) allein genuegt nicht: je nach DIMZIN schneidet es nachfolgende
|
||||
;; Nullen ab und liefert "2.5" statt "2.500" bzw. "-1" statt "-1.000" (real
|
||||
;; beobachtet im Testlauf). Fuer eine Merkmalsliste ist die feste Stellenzahl
|
||||
;; aber gewollt, darum wird hier aufgefuellt - unabhaengig von der
|
||||
;; Zeichnungseinstellung.
|
||||
(defun vf-meter-3 (mm / s pos)
|
||||
(setq s (rtos (/ (float mm) 1000.0) 2 3))
|
||||
(if (not (vl-string-search "." s)) (setq s (strcat s ".")))
|
||||
(setq pos (vl-string-search "." s))
|
||||
(while (< (- (strlen s) pos 1) 3) (setq s (strcat s "0")))
|
||||
s)
|
||||
|
||||
;; ============================================================
|
||||
;; TEIL 5: KS_EIN/KS_AUS EXTRAKTION
|
||||
;; ============================================================
|
||||
@@ -977,6 +1073,9 @@
|
||||
(cons "L_VF_m" (rtos (/ L_VF 1000.0) 2 3))
|
||||
(cons "ANTRIEBFAHRTRICHTUNG" richtung)
|
||||
(cons "VF_WINKEL" (itoa best-winkel))
|
||||
;; Hoehe der (einen) Foerdereinheit - beim Standard-/Etage-Typ
|
||||
;; fuellen vfs-vf-entry/-exit genau einen Listeneintrag.
|
||||
(cons "VF_HOEHE_m" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
(cons "ANZAHL_SEPARATOR" "2")
|
||||
(cons "ANZAHL_SCANNER" (itoa n-scanner))
|
||||
(cons "GERUEST_EINZELMODUL" geruest-einzelmodul)
|
||||
@@ -1013,6 +1112,10 @@
|
||||
horizontal-info winkelwahl best-winkel L_GF L_VF L_GF1 L_GF2
|
||||
verteilung-modus n-scanner hoehe-von hoehe-bis lastEnt
|
||||
vf-insert vf-endpunkt staustrecke-basis)
|
||||
;; VF-Hoehen-Akkumulator pro Anlage zuruecksetzen - sonst erbte die naechste
|
||||
;; Anlage die Hoehen der vorherigen. (Im Linienzug erledigt das
|
||||
;; vfl-acc-reset; Standard/Etage laufen nicht darueber.)
|
||||
(vf-vfhoehe-reset)
|
||||
(setq berechne-fn (vf-registry-berechne-fn typ))
|
||||
(setq einfuege-fn (vf-registry-einfuege-fn typ))
|
||||
(setq ergebnis (apply berechne-fn (list deltaL deltaH richtung seite)))
|
||||
@@ -1064,6 +1167,15 @@
|
||||
(setq vf-endpunkt
|
||||
(apply einfuege-fn
|
||||
(list deltaL deltaH richtung best-winkel L_GF1 L_GF2 L_VF startpunkt seite hz)))
|
||||
;; VF_HOEHE_m fuer Standard/Etage: Mittelwert ueber die GANZE Kette
|
||||
;; (AS-KS_EIN = startpunkt, ES-KS_AUS = Rueckgabe der Einfuegefunktion),
|
||||
;; weil es hier nur einen Motor und nur einen geraden VF-Abschnitt
|
||||
;; gibt. Ersetzt den beim Bau gesammelten Segmentwert - siehe
|
||||
;; vf-vfhoehe-kette. Der Linienzug laeuft NICHT hier durch und behaelt
|
||||
;; daher seine Segmentliste.
|
||||
(vf-vfhoehe-kette (caddr startpunkt)
|
||||
(if (and vf-endpunkt (listp vf-endpunkt))
|
||||
(caddr vf-endpunkt) nil))
|
||||
(setq vf-insert
|
||||
(vf-block-erstellen typ seite vf-nummer n-scanner
|
||||
hoehe-von hoehe-bis deltaH deltaL L_VF L_GF1 L_GF2
|
||||
|
||||
+11
-4
@@ -101,8 +101,8 @@
|
||||
(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). Aktiv referenziert in
|
||||
;; vf_linienzug.lsp (beide Aufrufstellen von vfl2-pruefe-eckwinkel).
|
||||
;; vf-linienzug-modus3 -> vfl-pfad-eckwinkel-pruefen). Aktiv referenziert in
|
||||
;; vf_linienzug.lsp (beide Aufrufstellen von vfl-pfad-eckwinkel-pruefen).
|
||||
(if (null *vfk-eckwinkel-toleranz*) (setq *vfk-eckwinkel-toleranz* 5.0))
|
||||
|
||||
;; Schwellwert (Grad), ab dem ein Frame noch als "flach" (~0 Grad) gilt.
|
||||
@@ -123,7 +123,7 @@
|
||||
;; (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, ...)
|
||||
;; vf_linienzug.lsp (vfl-body-zerlegung, vfl-zsolve-winkel-waehlen, ...)
|
||||
;; Diese vier NICHT vereinheitlichen ohne sorgfaeltige Pruefung - sie
|
||||
;; entstehen aus unterschiedlicher Bauteil-Zusammensetzung (siehe jeweiliger
|
||||
;; Kommentar im Modul), keine Kopiergleichheit.
|
||||
@@ -166,7 +166,7 @@
|
||||
;; 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. Das fruehere rohe 400.0-
|
||||
;; Duplikat (br-gf1 in vfl3-*) referenziert jetzt *vfl-gf-min-laenge*.
|
||||
;; Duplikat (br-gf1 in vfl-zsolve-*) referenziert jetzt *vfl-gf-min-laenge*.
|
||||
(if (null *vfk-gf-anschluss-mindestlaenge*) (setq *vfk-gf-anschluss-mindestlaenge* 400.0))
|
||||
|
||||
;; ============================================================
|
||||
@@ -303,6 +303,13 @@
|
||||
;; Ueberschreiten, kein Abbruch. Aktiv referenziert.
|
||||
(if (null *vfk-vf-laenge-max*) (setq *vfk-vf-laenge-max* 25000.0))
|
||||
|
||||
;; Hoechstzahl Vario-Kurven INNERHALB einer VF-Einheit (zwischen Umlenk- und
|
||||
;; Motorstation) - Nutzer-Regel 2026-10-22. Zwei Kurven bedeuten hoechstens
|
||||
;; drei VF-Geraden im selben Lauf; danach muss die Einheit mit einer
|
||||
;; Motorstation schliessen und eine neue mit Umlenkstation beginnen.
|
||||
;; Geprueft in vfl-m2-lauf-grenzen (vf_linienzug.lsp, Modus 2).
|
||||
(if (null *vfk-vf-kurven-max*) (setq *vfk-vf-kurven-max* 2))
|
||||
|
||||
(setq *vfk-konstanten-geladen* t)
|
||||
(princ)
|
||||
(princ)
|
||||
+2479
-252
File diff suppressed because it is too large.
Load diff
+47
-4
@@ -274,7 +274,18 @@
|
||||
((and (= (type v) 'STR) (= (strcase v) "AUTO")) (vsp-raus "NIL" nil))
|
||||
(T (vsp-zahl "REAL" v "eingang_hoehe"))))
|
||||
|
||||
(defun vsp-praeambel (kopf / punkt)
|
||||
;; Praeambel-Tokens: PT(Startpunkt) REAL(Starthoehe) STR(AS ja/nein)
|
||||
;; [STR(Winkel) STR(Seite) (PT|NIL)(Zufuehrungsachse)].
|
||||
;;
|
||||
;; Das Achsen-Feld "as_achse" ist OPTIONAL (Gegenstueck zu
|
||||
;; vfl-frage-as-winkel-seite-oder-achse und zu praeambel() in
|
||||
;; lib/vf_linienzug_grammatik.py):
|
||||
;; [x, y, z] -> PT (Zufuehrungsachse ueber einen zweiten Punkt)
|
||||
;; "ohne" -> NIL (bewusst ohne Achse gebaut)
|
||||
;; fehlt -> gar kein Token = Journalformat VOR 2026-10-21. Das replayt
|
||||
;; unveraendert; die Kettenrichtung kommt dann wie frueher aus
|
||||
;; dem naechsten Klick.
|
||||
(defun vsp-praeambel (kopf / punkt achse)
|
||||
(setq *vsp-wo* "start")
|
||||
(setq punkt (ssg-val kopf "start_punkt"))
|
||||
(if (and punkt (listp punkt) (>= (length punkt) 3))
|
||||
@@ -287,7 +298,13 @@
|
||||
(if (vsp-ja-p (ssg-val kopf "as"))
|
||||
(progn
|
||||
(vsp-wert-str (ssg-val kopf "as_winkel") "as_winkel")
|
||||
(vsp-code-raus *vsp-tab-seite* (ssg-val kopf "as_seite") "as_seite"))))
|
||||
(vsp-code-raus *vsp-tab-seite* (ssg-val kopf "as_seite") "as_seite")
|
||||
(setq achse (ssg-val kopf "as_achse"))
|
||||
(cond
|
||||
((and achse (listp achse) (>= (length achse) 3))
|
||||
(vsp-raus "PT" (mapcar 'float achse)))
|
||||
((equal achse "ohne") (vsp-raus "NIL" nil))
|
||||
))))
|
||||
|
||||
;; naechste: Felder der NAECHSTEN Top-Level-Sektion (oder nil) - wird nur fuer
|
||||
;; "Linie-GF" gebraucht (siehe dort). *vsp-es-verbraucht* (Ausgabe-Flag, vom
|
||||
@@ -664,6 +681,7 @@
|
||||
(setq *vsp-alt-headless* (if (boundp '*vfl-headless*) *vfl-headless*))
|
||||
(setq *vfl-wizard-mode* nil)
|
||||
(setq *vfl-headless* T)
|
||||
(setq *vsp-alt-gui* (if (boundp '*ssg-gui-aus*) *ssg-gui-aus*))
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AUS"))) (ssg-gui-aus))
|
||||
(setq *vsp-prompts* 0)
|
||||
(princ))
|
||||
@@ -676,7 +694,9 @@
|
||||
alert *vsp-alt-alert*)
|
||||
(setq *vfl-wizard-mode* *vsp-alt-wizard*)
|
||||
(setq *vfl-headless* *vsp-alt-headless*)
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AN"))) (ssg-gui-an))
|
||||
;; Vorzustand zurueck statt pauschal ssg-gui-an: unter SSG_RUN_ALL_TESTS
|
||||
;; muss die GUI fuer den Export danach aus bleiben.
|
||||
(setq *ssg-gui-aus* *vsp-alt-gui*)
|
||||
(princ))
|
||||
|
||||
|
||||
@@ -919,6 +939,29 @@
|
||||
;; sid = Kennung im Record, dim = "2D"/"3D" oder nil (Sitzung),
|
||||
;; fehler = Liste der Spec-Fehler (bei nil-Journal die Begruendung).
|
||||
;; Erwartet den Headless-Rahmen (vsp-headless-an) beim Aufrufer.
|
||||
;; Bau-Funktion AUS DEM JOURNAL ableiten (Rueckgabe: Funktions-Symbol).
|
||||
;; Bewusst abgeleitet statt als zusaetzliches Argument: vsp-bau-journal hat
|
||||
;; zwei Aufrufer, und AutoLISP verlangt exakte Argumentzahl - eine erweiterte
|
||||
;; Signatur muesste jeden davon nachziehen (siehe CLAUDE.md). Die Ableitung
|
||||
;; kann der Datenlage ausserdem nicht widersprechen, weil sie GENAU das
|
||||
;; Journal liest, das gleich abgespielt wird.
|
||||
;;
|
||||
;; Unterscheidung:
|
||||
;; kein SEGS -> Modus 1 (Fragenfluss, Menue-Codes)
|
||||
;; SEGS + STR "m2v2" -> Modus 2 (die Formatmarke schreibt nur
|
||||
;; vf-linienzug-modus2, vfl-m2-formatmarke)
|
||||
;; SEGS ohne "m2v2" -> Modus 3
|
||||
;; Ein Fehlgriff faellt sofort auf: der Ergebnis-Record meldet dann offene
|
||||
;; Eingaben bzw. glieder_soll <> glieder_ist.
|
||||
(defun vsp-bau-fn-fuer-journal (journal)
|
||||
(cond
|
||||
((not (vfl-journal-hat-segs-p journal)) 'vf-linienzug-modus)
|
||||
((vl-some (function (lambda (e)
|
||||
(and (equal (car e) "STR") (equal (cdr e) "m2v2"))))
|
||||
journal)
|
||||
'vf-linienzug-modus2)
|
||||
(t 'vf-linienzug-modus3)))
|
||||
|
||||
(defun vsp-bau-journal (sid journal dim fehler / rec vor-ent alt-error err
|
||||
offen hl meld ist-glieder soll-glieder diff
|
||||
ist-journal jdiff ent ed)
|
||||
@@ -958,7 +1001,7 @@
|
||||
(setq alt-error *error*)
|
||||
(vfl-journal-reset)
|
||||
(vfl-journal-replay-start journal)
|
||||
(setq err (vl-catch-all-apply 'vf-linienzug-modus '()))
|
||||
(setq err (vl-catch-all-apply (vsp-bau-fn-fuer-journal journal) '()))
|
||||
(setq offen (vsp-queue-rest))
|
||||
;; Diagnose VOR dem Reset sichern (vfl-journal-reset loescht sie).
|
||||
(setq ist-journal (reverse *vfl-journal*))
|
||||
|
||||
+22
-2
@@ -609,12 +609,30 @@
|
||||
;; EIN reines VF-Sub-Segment. Wichtig: es BEGINNT und ENDET auf der
|
||||
;; 3-Grad-Basisneigung, weil Ein- und Ausgangsbogen denselben Winkel haben.
|
||||
;; Dadurch lassen sich mehrere Sub-Segmente (und Vario-Kurven dazwischen)
|
||||
;; beliebig aneinanderreihen (siehe doc/VarioFoerderer_Linienzug_Prinzipien.md).
|
||||
;; beliebig aneinanderreihen.
|
||||
;;
|
||||
;; Die Regel dahinter: der Vertikalbogen am ENDE eines VF (vor der
|
||||
;; Motorstation) hat denselben Winkel wie der am ANFANG (nach der
|
||||
;; Umlenkstation), und der abschliessende Bogen bringt die Strecke auf 3 Grad
|
||||
;; NACH UNTEN - weil die Motorstation selbst mit 3 Grad geneigt eingebaut wird
|
||||
;; und der Anschluss sonst knickt. Dasselbe gilt am anderen Ende: Umlenkstation
|
||||
;; (VF-Start) und Separator+ES-Element (Kettenende) gibt es hardwareseitig nur
|
||||
;; fuer die Anfahrt auf dieser Standard-Fallend-Basis; eine Anfahrt auf
|
||||
;; STEIGENDER Basis ist physisch nicht vorgesehen.
|
||||
;; Anfang und Ende auf derselben Basis zu halten ist also keine Konvention,
|
||||
;; sondern die Voraussetzung dafuer, dass zwei Sub-Segmente ueberhaupt
|
||||
;; aneinanderpassen.
|
||||
;; best-winkel=0 => horizontales Sub-Segment (Boegen fest auf_3/ab_3).
|
||||
(defun vfs-vf-koerper (aktueller-punkt richtung best-winkel L_VF hz /
|
||||
bogen-name bogen-mass bogen-dx bogen-dz)
|
||||
bogen-name bogen-mass bogen-dx bogen-dz z-ein)
|
||||
(if (null hz) (setq hz 0.0))
|
||||
(setq hz (float hz))
|
||||
;; Hoehe DIESES VF-Segments (Attribut VF_HOEHE_m, Sivas 4433-4437):
|
||||
;; KS_EIN ist der Punkt beim Eintritt, KS_AUS der Rueckgabewert am Ende -
|
||||
;; der Mittelwert beider wird unten angehaengt. Eine Kette mit drei durch
|
||||
;; Vario-Boegen getrennten Abschnitten bekommt dadurch drei Werte, parallel
|
||||
;; zu L_VF_m und VF_WINKEL (Nutzer-Vorgabe 2026-10-21).
|
||||
(setq z-ein (caddr aktueller-punkt))
|
||||
|
||||
;; 5. 1. Vertikalbogen
|
||||
;; Sonderfall best-winkel=0 (horizontale Zwischenstrecke, siehe
|
||||
@@ -717,6 +735,8 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; Segment-Hoehe anhaengen: Mittelwert aus KS_EIN (z-ein) und KS_AUS.
|
||||
(vf-vfhoehe-segment z-ein (caddr aktueller-punkt))
|
||||
aktueller-punkt
|
||||
)
|
||||
|
||||
|
||||
@@ -2,62 +2,77 @@
|
||||
|
||||
AutoLISP-Makros (SSG_LIB) fuer BricsCAD Pro zur automatisierten Erstellung von Foerderanlagen-Layouts (ILS Kreisel, Omniflo, VarioFoerderer, Gefaellestrecke, Geruest).
|
||||
|
||||
**Einstieg:**
|
||||
|
||||
- [doc/faq.md](doc/faq.md) - haeufige Fragen und erste Schritte mit dem Programm
|
||||
- [doc/cad-datenaufbereitung.md](doc/cad-datenaufbereitung.md) - neue CAD-Bausteine anlegen: Koordinatensysteme, Platzierung, Datenablage
|
||||
|
||||
## Menustruktur (SSG_LIB)
|
||||
|
||||
```
|
||||
SSG_LIB
|
||||
├── ILS
|
||||
│ ├── Kreisel-Module
|
||||
│ │ ├── Einfuegen → KreiselInsert
|
||||
│ │ ├── Verbinden → KreiselConnect
|
||||
│ │ ├── Bearbeiten → KreiselEdit
|
||||
│ │ └── Eckrad → ILS_Eckrad
|
||||
│ │ ├── Einfuegen / Verbinden / Bearbeiten → KreiselInsert / KreiselConnect / KreiselEdit
|
||||
│ │ ├── Eckrad / Eckrad bearbeiten → ILS_Eckrad / EckradEdit
|
||||
│ │ └── Weichenpunkte ermitteln → KREISEL_WEICHEN
|
||||
│ ├── Zusatzmodul
|
||||
│ │ ├── BTMT-Beladung → ILS_BTMT_Beladung
|
||||
│ │ ├── BTMT-Entladung → ILS_BTMT_Entladung
|
||||
│ │ ├── Scanner einfuegen → ILS_SCANNER_INSERT
|
||||
│ │ └── Separator einfuegen → ILS_SEPARATOR_INSERT
|
||||
│ │ ├── BTMT-Beladung / -Entladung → ILS_BTMT_Beladung / ILS_BTMT_Entladung
|
||||
│ │ └── Scanner / Separator einfuegen → ILS_SCANNER_INSERT / ILS_SEPARATOR_INSERT
|
||||
│ ├── Foerderer
|
||||
│ │ ├── Standard → StandardVarioFoerderer / StandardVarioFoerderer3D
|
||||
│ │ ├── Etage → EtageVarioFoerderer / EtageVarioFoerderer3D
|
||||
│ │ ├── Streckengruppe (Linienzug) → LinienzugVarioFoerdererManuell / -Zielhoehe / -Stueckweise
|
||||
│ │ └── Vario_Kette_Merge / VARIOFOERDERER_NACHRUESTEN
|
||||
│ │ ├── Standard (Werte manuell / aus 3D-Linie) → StandardVarioFoerderer / StandardVarioFoerderer3D
|
||||
│ │ ├── Etage (Werte manuell / aus 3D-Linie) → EtageVarioFoerderer / EtageVarioFoerderer3D
|
||||
│ │ ├── Streckengruppe (Linienzug) → LinienzugVarioFoerdererManuell / -Zielhoehe / -Stueckweise
|
||||
│ │ └── Vario_Kette_Merge / VarioFoerderer nachruesten → Vario_Kette_Merge / VARIOFOERDERER_NACHRUESTEN
|
||||
│ └── Gefaellestrecke
|
||||
│ ├── einfach → GEFAELLESTRECKE_EINFACH
|
||||
│ ├── aus 3D-Linie → GEFAELLESTRECKE_3DLINIE
|
||||
│ └── aus Linienzug → GEFAELLESTRECKE_LINIENZUG
|
||||
│ ├── einfach / aus 3D-Linie / aus Linienzug → GEFAELLESTRECKE_EINFACH / _3DLINIE / _LINIENZUG
|
||||
│ └── QC Linie mit GF (auch U-Form) → QcLinieMitGf / QcLinieMitGfUForm
|
||||
├── Omniflo
|
||||
│ ├── Boegen APB110/APB60
|
||||
│ ├── Aluprofil Gerade (AP60/AP110/APG110)
|
||||
│ ├── Weichen (90/45/Parallel/Weichenkoerper/Weichenkombinationen)
|
||||
│ ├── TEF Elemente, Anbaugruppen, Verbinder, Boegen fuer Weichen
|
||||
│ ├── Element bearbeiten → OMNI_EDIT
|
||||
│ └── Ladeschleifen (AP110) → OMNI_LADESCHLEIFE_AP110
|
||||
│ ├── Fahrstrecke / Fahrstrecken beschriften → OMNI_FAHRSTRECKE / OMNI_FAHRSTRECKE_BESCHRIFTEN
|
||||
│ ├── Boegen APB110 / APB60, Aluprofil Gerade (AP60/AP110/APG110)
|
||||
│ ├── Weichen (90/45/Parallel/22.5, Delta, Star)
|
||||
│ ├── TEF Elemente (inkl. TEF Gerade auf Linie → TEF_FOERDERER_LINIE)
|
||||
│ ├── Anbaugruppen (Stopper, Scanner, Buerstenbremse)
|
||||
│ ├── Spez. Streckenelemente ▸ Tuerloesungen ▸ Schwenkschienen → OMNI_SCHW_400_*
|
||||
│ ├── KettenFoerderer → KETTENFOERDERER
|
||||
│ ├── Ladeschleifen → OMNI_LADESCHLEIFE_AP110
|
||||
│ ├── Verbinder → OMNI_TV_*
|
||||
│ ├── Boegen fuer Weichen (ausgegraut, Dummy) → OMNI_APBW_*
|
||||
│ └── Element bearbeiten → OMNI_EDIT
|
||||
├── Geruest
|
||||
│ ├── Rohr-Geruest-Traeger → GERUEST_TRAEGER
|
||||
│ ├── Saeulen / Rohrabhaenger / Wandbefestigung → GERUEST
|
||||
│ └── Funktionen ▸ Traeger beschriften → GERUEST_TRAEGER_BESCHRIFTEN
|
||||
│ ├── Rohr-Geruest-Traeger → GERUEST_TRAEGER
|
||||
│ ├── Saeulen / Rohrabhaenger / Wandbefestigung → GERUEST_SAEULEN / GERUEST_ROHRABHAENGER / GERUEST_WANDBEFESTIGUNG
|
||||
│ ├── Gattertraeger (Platzhalter) → GERUEST
|
||||
│ └── Funktionen ▸ Traeger beschriften → GERUEST_TRAEGER_BESCHRIFTEN
|
||||
├── SPS
|
||||
│ ├── TRO (Marker einfuegen/bearbeiten) → TRO_INSERT / TRO_EDIT
|
||||
│ └── Connections (einfuegen/bearbeiten, Eingang/Ausgang) → CONNECTION_INSERT / CONNECTION_EDIT / ILS_EINGANG_INSERT / ILS_AUSGANG_INSERT
|
||||
│ ├── TRO (Marker einfuegen/bearbeiten) → TRO_INSERT / TRO_EDIT
|
||||
│ ├── Connections (einfuegen/bearbeiten) → CONNECTION_INSERT / CONNECTION_EDIT
|
||||
│ └── Eingang / Ausgang → ILS_EINGANG_INSERT / ILS_AUSGANG_INSERT
|
||||
├── Export
|
||||
│ ├── Export Sivas → EXPORTSIVAS
|
||||
│ └── Export CSV → EXPORTCSV
|
||||
│ ├── Export Sivas → EXPORTSIVAS
|
||||
│ └── Export CSV → EXPORTCSV
|
||||
├── Konfiguration
|
||||
│ ├── Umschalten 2D und 3D → SSG_DIM_SWITCH
|
||||
│ ├── Sprache → SSG_SPRACHE
|
||||
│ └── Planquadrate an/aus → PLANQUADRATE_TOGGLE
|
||||
│ ├── Umschalten 2D und 3D → SSG_DIM_SWITCH
|
||||
│ ├── Alle Bloecke auf 2D / 3D → SSG_DIM_ALL_2D / SSG_DIM_ALL_3D
|
||||
│ ├── Sprache → SSG_SPRACHE
|
||||
│ ├── Planquadrate an/aus → PLANQUADRATE_TOGGLE
|
||||
│ └── CSV-Export → CSV_EXPORT_KONFIG
|
||||
├── Werkzeuge
|
||||
│ ├── Bloecke zaehlen/loeschen, Attribute ersetzen → ssg_blocktools
|
||||
│ └── Text ersetzen/parallel/Hoehe/Stil → ssg_texttools
|
||||
└── Tests (Testsuiten ausfuehren und exportieren)
|
||||
│ ├── Bloecke zaehlen / loeschen, Attribute ersetzen → SSG_BLOCK_COUNT / SSG_BLOCK_DELETE / SSG_ATTR_ERSETZEN
|
||||
│ ├── Text ersetzen / parallel / Hoehe / Stil → SSG_TEXT_ERSETZEN / _PARALLEL / _HOEHE / _STIL
|
||||
│ ├── Faehnchen + Stueckliste aus Zeichnung → SSG_FAEHNCHEN_STUECKLISTE
|
||||
│ └── Din Formate → DIN_FORMATE
|
||||
└── Tests (alle Testsuiten, einzelne Szenarien, Export CSV/Sivas ALL, KS 2D/3D pruefen)
|
||||
```
|
||||
|
||||
Doppelklick auf einen Block ruft `SSG_BLOCKEDIT` auf und verzweigt nach Blockname
|
||||
(Kreisel, Eckrad, VF_/GF_, KF_, Omniflo, GR_, TRO_, CONNECTION_, JAM_ → passender Edit-Befehl).
|
||||
|
||||
Vollstaendige, laufend aktualisierte Befehls-/Modulzuordnung: siehe `CLAUDE.md` (Abschnitt "Modulzuordnung im Menue") und `menu/SSG_LIB.mnu`.
|
||||
|
||||
## Lademechanismus
|
||||
|
||||
Module werden per Lazy-Loading ueber das Menuesystem geladen (`ssg-ensure` in `SSG_LIB.mnl`). Einmalige Einrichtung pro BricsCAD-Installation:
|
||||
Die Module werden beim Laden des Menues ueber `SSG_LIB.mnl` initialisiert (`ssg-ensure`, ueberspringt bereits geladene Module; einzelne Module wie `DrawPlanquadrate`, `DinFormate`, `Tro_Edit`, `Jam_Edit` werden erst beim ersten Aufruf nachgeladen). Einmalige Einrichtung pro BricsCAD-Installation:
|
||||
|
||||
1. `bin/setenv.bat` ausfuehren (setzt `DXFM_LISP` u.a.)
|
||||
2. BricsCAD starten
|
||||
@@ -70,16 +85,18 @@ Details und die Core-Ladereihenfolge: siehe `CLAUDE.md` Abschnitt "Lademechanism
|
||||
```text
|
||||
dxfmakros/
|
||||
├── Lisp/ # AutoLISP-Makros und Kernbibliotheken (Details: Lisp/README.md)
|
||||
├── bin/ # Hilfs-Skripte (setenv.bat, start_briscad.bat)
|
||||
├── bin/ # Hilfs-Skripte (setenv, start_briscad, run_tests, Python-Wrapper)
|
||||
├── cfg/ # Konfigurationsdateien
|
||||
├── data/ # JSON-Daten, DXF-Quellen, Block-Libraries - nicht im Git
|
||||
├── data/ # JSON-Komponentendaten, DWG-/DXF-Bloecke, Block-Libraries
|
||||
├── dcl/ # DCL-Dialogdefinitionen
|
||||
├── doc/ # Dokumentation (doc/plan Architektur/Analysen, doc/todo offene Fahrplaene)
|
||||
├── lang/ # Benutzertexte de_DE.json / en_GB.json (ssg-text)
|
||||
├── lib/ # Python-Skripte (DXF-Bearbeitung, Export)
|
||||
├── log/ # Logdateien - nicht im Git
|
||||
├── logs/ # Logdateien und .dbg-Ausgaben (DXFM_LOG) - nicht im Git
|
||||
├── menu/ # BricsCAD-Menudefinition (SSG_LIB.mnu, SSG_LIB.mnl)
|
||||
├── results/ # Ergebnisse / Exporte - nicht im Git
|
||||
├── tests/ # Testskripte und Referenzdaten
|
||||
├── tools/ # Einmal-Werkzeuge (z.B. Migration der Sprachtexte)
|
||||
├── LICENSE
|
||||
├── README.md
|
||||
└── requirements.txt
|
||||
@@ -110,11 +127,18 @@ Headless-Unit-Tests (file- und zeichnungsfrei):
|
||||
bin\run_tests.bat --lisp
|
||||
```
|
||||
|
||||
Python-Tests (in der `.venv`):
|
||||
|
||||
```bat
|
||||
pytest tests/
|
||||
bin\run_tests.bat --check
|
||||
```
|
||||
|
||||
Zeichnungs-/Szenario-Tests laufen interaktiv in BricsCAD ueber das Menue `Tests` bzw. `SSG_RUN_ALL_TESTS`. Details: `doc/LispTests.md`, `tests/README.md`.
|
||||
|
||||
## Dokumentation
|
||||
|
||||
Ausfuehrliche Modul- und Befehlsdokumentation: `CLAUDE.md` (Projektanweisungen) und `Lisp/README.md`. Weitere Anwender-/Entwickler-Themen direkt in `doc/` (u.a. `variofoerderer.md`, `csv-export.md`, `faq.md`, `kommandos.md`). Architektur-Analysen und Planungsdokumente in `doc/plan/` (u.a. `translate.md`, `Entwicklungsplan.md`), offene Fahrplaene/TODOs in `doc/todo/`.
|
||||
Ausfuehrliche Modul- und Befehlsdokumentation: `CLAUDE.md` (Projektanweisungen) und `Lisp/README.md`. Weitere Anwender-/Entwickler-Themen direkt in `doc/` (u.a. `kommandos.md` - Uebersicht aller Befehle und Skripte, `variofoerderer.md`, `vf_linienzug_modus1_anleitung.md`, `csv-export.md`, `json-input-lisp.md`, `faq.md`). Architektur-Analysen und Planungsdokumente in `doc/plan/` (u.a. `translate.md`, `Entwicklungsplan.md`), alle offenen TODOs gesammelt in `doc/todo.md` (Detail-Fahrplaene in `doc/todo/`).
|
||||
|
||||
## Lizenz
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
@echo off
|
||||
REM ================================================================
|
||||
REM create_tests.bat - ILS Testlauf
|
||||
REM
|
||||
REM Ablauf:
|
||||
REM 1. Umgebung setzen
|
||||
REM 2. Python: ILStest.dxf mit Linien erzeugen
|
||||
REM 3. BricsCAD: Kreisel einfuegen, exportieren, speichern
|
||||
REM 4. Python: Ergebnisse gegen Referenzen validieren
|
||||
REM ================================================================
|
||||
|
||||
call "%~dp0setenv.bat"
|
||||
|
||||
echo.
|
||||
echo ================================================================
|
||||
echo ILS TEST - Schritt 1: Basis-DXF erzeugen
|
||||
echo ================================================================
|
||||
python "%DXFM_TESTS%\create_ILStest_dxf.py" "%DXFM_TESTS%\ILStest.dxf"
|
||||
if errorlevel 1 (
|
||||
echo FEHLER: DXF-Erzeugung fehlgeschlagen!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo ================================================================
|
||||
echo ILS TEST - Schritt 2: BricsCAD starten und Kreisel erzeugen
|
||||
echo ================================================================
|
||||
echo BricsCAD wird gestartet mit dem Testskript...
|
||||
echo Nach Abschluss des Tests BricsCAD schliessen.
|
||||
echo.
|
||||
REM /b = Skript ausfuehren (NICHT /s - das ist der Support-Ordner-Schalter).
|
||||
start /wait "" "%BRICSCAD%" /b "%DXFM_TESTS%\ILS_test.scr"
|
||||
|
||||
echo.
|
||||
echo ================================================================
|
||||
echo ILS TEST - Schritt 3: Ergebnisse validieren
|
||||
echo ================================================================
|
||||
python "%DXFM_TESTS%\validate_tests.py" "%DXFM_RESULTS%" "%DXFM_TESTS%\references"
|
||||
|
||||
echo.
|
||||
pause
|
||||
@@ -86,6 +86,19 @@ if %DO_LISP%==1 (
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Laufende BricsCAD-Instanz? Dann NICHT starten: BricsCAD reicht einen
|
||||
REM /b-Start an die offene Instanz weiter, das Skript liefe in der
|
||||
REM Sitzung des Benutzers und das abschliessende _.QUIT haengt dort an
|
||||
REM der Speichern-Rueckfrage bzw. beendet die Sitzung.
|
||||
REM findstr statt find: steht Git-Bash im PATH, ist "find" das Unix-find.
|
||||
tasklist /FI "IMAGENAME eq bricscad.exe" /NH 2>nul | findstr /i "bricscad.exe" >nul
|
||||
if not errorlevel 1 (
|
||||
echo FEHLER: BricsCAD laeuft bereits. Der Testlauf wuerde in dieser
|
||||
echo Sitzung landen und sie am Ende mit QUIT beenden.
|
||||
echo Bitte BricsCAD schliessen und erneut starten.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Altes Ergebnis loeschen - fehlender Report = fehlgeschlagener Lauf
|
||||
if exist "%DXFM_TESTOUT%\unit_results.txt" del "%DXFM_TESTOUT%\unit_results.txt"
|
||||
|
||||
|
||||
Binary file not shown.
@@ -76,6 +76,15 @@
|
||||
# erkennt sie wie alle Omniflo-Teile ueber TEILEART "Omniflo ..." und schreibt
|
||||
# je Nummer aus ARTINR eine Omniflo-Zeile.
|
||||
#
|
||||
# pattern_kettenfoerderer: Kettenfoerderer/Schraegfoerderer Stahl
|
||||
# (KettenFoerderer.lsp, KF_<n>). Eine selbst zusammengebaute Baugruppe wie
|
||||
# GR_*, mit eigenen Attributen TEILEART ("Omniflo Kettenfoerderer ...") und
|
||||
# ARTINR - erkannt wird sie darum im allgemeinen Omniflo-Zweig von
|
||||
# export_sivas.py. Die drei Bausteine darin (Umlenkstation, skaliertes
|
||||
# Zwischenstueck, Antriebsstation) werden NICHT einzeln gezaehlt. Die im
|
||||
# Dialog gewaehlten Verbindungselemente stehen als Attribut
|
||||
# VERBINDUNGSELEMENTE am Block und landen im Merkmale-/details-JSON.
|
||||
#
|
||||
# pattern_nested_bogen/_streckenelement/_umlenkstation/_motorstation: die
|
||||
# uebrigen Bausteine einer VF_n/GF_n-Kette (Boegen, gerade Foerderer-/
|
||||
# Gefaellestrecken-Segmente, Umlenk-/Motorstation). Wie pattern_schleuselement
|
||||
@@ -136,6 +145,7 @@ pattern_gerade= AP110*, AP_110*, AP60*
|
||||
# Gerüst
|
||||
pattern_geruest= GR_*
|
||||
pattern_verbinder= VB_*, TV_*
|
||||
pattern_kettenfoerderer= KF_*
|
||||
|
||||
[python]
|
||||
# Interpreter fuer die Export-Skripte (lib/export_csv.py, lib/export_sivas.py).
|
||||
|
||||
@@ -168,6 +168,13 @@ gf_beschriftung = GF_Beschriftung, 7
|
||||
# Lisp/DrawPlanquadrate.lsp (DRAW_PLANQUADRATE).
|
||||
planquadrate = ZZ_Planquadrate, 8
|
||||
|
||||
# Kettenfoerderer (Schraegfoerderer Stahl), aus Umlenkstation + skaliertem
|
||||
# Zwischenstueck + Antriebsstation zusammengebauter Block KF_n - siehe
|
||||
# Lisp/KettenFoerderer.lsp (KETTENFOERDERER). Wie VF_n/GF_n eine
|
||||
# ZUSAMMENGEBAUTE Baugruppe ohne eigene Blockdatei, der Layer muss darum hier
|
||||
# stehen. Die drei Bausteine darin behalten ihre eigenen Layer.
|
||||
kettenfoerderer = Omni_Kettenfoerderer, 4
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Lagerplanung (LagerInsert.lsp, Bloecke LG_*)
|
||||
|
||||
+97
-4
@@ -28,19 +28,45 @@
|
||||
# (TRANSFORMS-Dict), die den ermittelten Rohwert
|
||||
# (Attribut- oder Default-Wert) in die Sivas-Anzeige
|
||||
# umwandelt (z.B. "0"/"1" -> "Ja"/"Nein"). Bekannte Namen:
|
||||
# ja_nein, geruest_typ_anzeige. Ein unbekannter Name
|
||||
# ja_nein, geruest_typ_anzeige, mm_zu_m, as_es_vorhanden,
|
||||
# as_es_winkel, as_seite, es_seite. Ein unbekannter Name
|
||||
# bricht NICHT ab, der Rohwert wird unveraendert
|
||||
# uebernommen (siehe sivas_mapping.anwenden).
|
||||
# Soll ein Merkmal ohne eigenes Attribut nur per Transform
|
||||
# entstehen, braucht die Zeile trotzdem den ":" vor dem
|
||||
# "|" ("WINKEL_AS : | as_es_vorhanden") - sonst gilt der
|
||||
# Transform-Name als Fallback-Attributname.
|
||||
# Transforms, die mit @braucht_attribs markiert sind
|
||||
# (as_seite/es_seite), sehen zusaetzlich alle uebrigen
|
||||
# Attribute des Blocks - noetig, wenn ein Merkmal von
|
||||
# einem ZWEITEN Attribut abhaengt (Seite nur, wenn der
|
||||
# zugehoerige Winkel ueberhaupt ein Element ausweist).
|
||||
#
|
||||
# Abschnittsnamen entsprechen den bisherigen build_*_details-Funktionen in
|
||||
# export_sivas.py: [gefaellestrecke], [kreisel], [eckrad], [geruest]. Die
|
||||
# geruest-typ-Anzeige-Tabelle (ASCII-Attributwert -> Sivas-Klartext mit
|
||||
# Umlauten) UND SEPARATOR_BEARBEITUNG_ANZEIGE bleiben eigene, kleine
|
||||
# Abschnitte weiter unten.
|
||||
# Anzeige-Tabellen (ASCII-Attributwert -> Sivas-Klartext/Optionswert:
|
||||
# [geruest_typ_anzeige], [as_es_winkel_anzeige]) UND
|
||||
# SEPARATOR_BEARBEITUNG_ANZEIGE bleiben eigene, kleine Abschnitte weiter
|
||||
# unten.
|
||||
#
|
||||
# [gefaellestrecke] und [variofoerderer] fuehren die AS-/ES-Merkmale
|
||||
# (4427-4432) absichtlich DOPPELT: GF_N- und VF_N-Bloecke tragen dieselben
|
||||
# Attribute des gemeinsamen Strecken-Schemas, und jeder Abschnitt soll fuer
|
||||
# sich lesbar bleiben. Aenderungen dort bitte in beiden nachziehen (der Test
|
||||
# tests/test_export_sivas_as_es.py::test_zuordnung_steht_in_der_config wacht
|
||||
# darueber).
|
||||
# ============================================================
|
||||
|
||||
[gefaellestrecke]
|
||||
2950= MONTAGEHOEHE_m : 0
|
||||
# AS-/ES-Element, Reihenfolge wie die Sivas-Hierarchie (identisch in
|
||||
# [variofoerderer]): 4431/4432 Ja/Nein schalten Winkel und Seite frei.
|
||||
4431= WINKEL_AS : | as_es_vorhanden
|
||||
4427= WINKEL_AS : | as_es_winkel
|
||||
4428= SEITE_AS : | as_seite
|
||||
4432= WINKEL_ES : | as_es_vorhanden
|
||||
4429= WINKEL_ES : | as_es_winkel
|
||||
4430= SEITE_ES : | es_seite
|
||||
4384= : Gefällestrecke
|
||||
4318= L_GF_m
|
||||
4391= GF_WINKEL
|
||||
@@ -79,12 +105,55 @@
|
||||
[geruest]
|
||||
Farbe= FARBE
|
||||
|
||||
[kettenfoerderer]
|
||||
# Kettenfoerderer / Schraegfoerderer Stahl (KF_n, Lisp/KettenFoerderer.lsp).
|
||||
# Merkmalnummern laut Merkmalstamm des Schraegfoerderers.
|
||||
#
|
||||
# 350 kommt aus FOERDERERTYP (Bauart im Klartext). Der Default greift nur
|
||||
# bei Altbestands-Bloecken ohne das Attribut.
|
||||
# 359 kommt aus WINKEL, das den Neigungswinkel als nackte Zahl fuehrt
|
||||
# ("26"/"30"); die Anzeige-Tabelle [kf_typ_anzeige] weiter unten macht
|
||||
# daraus den Sivas-Optionstext mit Gradzeichen. Grund fuer die
|
||||
# Zweiteilung: Block-Attribute bleiben laut Projektkonvention ASCII.
|
||||
# 353 (Anzahl der gleichen KF) steht ABSICHTLICH NICHT hier: der Wert
|
||||
# entsteht erst aus der Gruppierung baugleicher Bloecke
|
||||
# (kettenfoerderer_signature in export_sivas.py) und ist damit kein
|
||||
# flaches Attribut-Mapping - gleiche Bauart wie 3510/3512 beim Kreisel.
|
||||
# 356 und 361 nutzen den vorhandenen Transform ja_nein, die Attribute
|
||||
# fuehren "1"/"0".
|
||||
# 357 "Antriebsart" ist beim Kettenfoerderer FEST (1.1 kW): im Dialog ein
|
||||
# Dropdown mit genau einer, zwingend gewaehlten Option - das Attribut gibt es trotzdem, damit der Wert am
|
||||
# Block steht und nicht nur im Export auftaucht.
|
||||
# 354 "Farbe Foerderer" und 355 "Antriebsmotor Foerderer" sind ZWEI getrennte
|
||||
# Merkmale (nicht ein kombinierter Text) - im Dialog darum auch zwei
|
||||
# Felder, Attribute FARBE und ANTRIEBSMOTOR.
|
||||
# 354/355/391 tragen bereits den vollen Sivas-Optionstext im Attribut (die
|
||||
# Auswahllisten in data/json/kettenfoerderer.json liefern ihn so) -
|
||||
# darum kein Transform.
|
||||
350= FOERDERERTYP : Schrägförderer Stahl
|
||||
359= WINKEL : 26 | kf_typ_anzeige
|
||||
361= STANDARD_STEUERUNG : 0 | ja_nein
|
||||
354= FARBE : RAL 7035
|
||||
355= ANTRIEBSMOTOR : Europa 50 Hz
|
||||
357= ANTRIEBSART : 1.1 kW
|
||||
356= MOVIMOT : 0 | ja_nein
|
||||
360= H_EINBAUHOEHE_mm : 0
|
||||
391= VERBINDUNGSELEMENTE : Nein
|
||||
|
||||
[variofoerderer]
|
||||
# Nur die von der Segmentanzahl UNABHAENGIGEN Top-Level-Felder einer VF_N-
|
||||
# Streckengruppe (siehe build_variofoerderer_details in export_sivas.py).
|
||||
# Die Gefaelle-/Vario-Segmentpaare (4312-4392, 4353/4354/4386) haengen an der
|
||||
# Listenlaenge von L_GF_m/L_VF_m und bleiben Code.
|
||||
2950= MONTAGEHOEHE_m : 0
|
||||
# AS-/ES-Element, Reihenfolge wie die Sivas-Hierarchie (identisch in
|
||||
# [gefaellestrecke]): 4431/4432 Ja/Nein schalten Winkel und Seite frei.
|
||||
4431= WINKEL_AS : | as_es_vorhanden
|
||||
4427= WINKEL_AS : | as_es_winkel
|
||||
4428= SEITE_AS : | as_seite
|
||||
4432= WINKEL_ES : | as_es_vorhanden
|
||||
4429= WINKEL_ES : | as_es_winkel
|
||||
4430= SEITE_ES : | es_seite
|
||||
4329= GF_Bogen_L_90 : 0
|
||||
4330= GF_Bogen_L_60 : 0
|
||||
4331= GF_Bogen_L_30 : 0
|
||||
@@ -103,11 +172,35 @@ Farbe= FARBE
|
||||
3992= GERUEST_EINZELMODUL : 0 | ja_nein
|
||||
3993= GERUEST_TYP : Schoenenberger Geruest | geruest_typ_anzeige
|
||||
|
||||
[as_es_winkel_anzeige]
|
||||
# Attributwert WINKEL_AS/WINKEL_ES -> Optionswert der Sivas-Auswahlliste zu
|
||||
# Merkmal 4427/4429. Im Merkmalstamm heissen die Optionen "30 °"/"90 °" (mit
|
||||
# Leerzeichen vor dem Gradzeichen) - das Attribut in der Zeichnung bleibt die
|
||||
# nackte Zahl. Gleiche Bauart wie [geruest_typ_anzeige]: steht ein Winkel
|
||||
# hier NICHT drin, wird er unveraendert uebernommen.
|
||||
#
|
||||
# >>> Falls Sivas den Import mit "30 °" ablehnt, ist DIESE Tabelle die
|
||||
# >>> einzige Stelle zum Nachziehen (z.B. auf "30°" ohne Leerzeichen oder
|
||||
# >>> auf die nackte Zahl) - der Code bleibt unberuehrt.
|
||||
30= 30 °
|
||||
90= 90 °
|
||||
|
||||
[geruest_typ_anzeige]
|
||||
# ASCII-Attributwert (GERUEST_TYP) -> Sivas-Klartext mit Umlauten/Sonder-
|
||||
# zeichen (Attribute selbst bleiben ASCII, siehe CLAUDE.md-Konvention).
|
||||
Schoenenberger Geruest= Schönenberger-Gerüst
|
||||
|
||||
[kf_typ_anzeige]
|
||||
# Attributwert WINKEL (Neigungswinkel als nackte Zahl) -> Optionswert der
|
||||
# Sivas-Auswahlliste zu Merkmal 359. Gleiche Bauart wie
|
||||
# [geruest_typ_anzeige]/[as_es_winkel_anzeige]: steht ein Wert hier NICHT
|
||||
# drin, wird er unveraendert uebernommen.
|
||||
#
|
||||
# >>> Lehnt Sivas den Import ab, ist DIESE Tabelle die einzige Stelle zum
|
||||
# >>> Nachziehen (z.B. "26 °" mit Leerzeichen) - der Code bleibt unberuehrt.
|
||||
26= Schrägförderer Stahl 26°
|
||||
30= Schrägförderer Stahl 30°
|
||||
|
||||
[weichen]
|
||||
# ILS 2.0 Weiche (6216): eine Summenzeile, Werte aus den Kreisel-Beruehr-
|
||||
# punkten des LISP-Exports (kreisel_weichen.json). Ein Beruehrpunkt ist eine
|
||||
|
||||
@@ -8,7 +8,8 @@ der Wahrheit ist der Code in `lib/export_sivas.py` - diese Datei ist ein
|
||||
Backup/Nachschlagewerk, bei Aenderungen am Code bitte hier nachziehen.
|
||||
|
||||
Stand: abgeglichen mit `lib/export_sivas.py` nach der Umstellung von
|
||||
beschreibenden JSON-Keys auf reine Merkmalnummern (Sept. 2026).
|
||||
beschreibenden JSON-Keys auf reine Merkmalnummern (Sept. 2026), ergaenzt um
|
||||
die AS-/ES-Element-Merkmale 4427-4432 (Okt. 2026).
|
||||
|
||||
## ILS 2.0 Kreisel (SivasNr 6200, Dispogruppe 20)
|
||||
|
||||
@@ -59,6 +60,7 @@ immer 1. Sivas kennt je Streckengruppe nur EIN Gefaelle-Segment-Paar
|
||||
| 4381 | Streckengruppe - Anzahl der Separatoren - Variofoerderer | `ANZAHL_SEPARATOR` | **voller Blockwert** (Aufteilung noch offen, siehe 4337) |
|
||||
| 4382 | (dieselbe Bezeichnung wie 4338 im Merkmalstamm) | - | fest `SEPARATOR_BEARBEITUNG_ANZEIGE` |
|
||||
| 4383 | Streckengruppe - Anzahl der Scanner (Vario-Anteil) | `ANZAHL_SCANNER` | **voller Blockwert** |
|
||||
| 4427-4432 | AS-/ES-Element (vorhanden/Winkel/Seite) | `WINKEL_AS`/`SEITE_AS`/`WINKEL_ES`/`SEITE_ES` | siehe eigener Abschnitt unten |
|
||||
| 3992 | Geruest fuer Einzelmodul | `GERUEST_EINZELMODUL` | wie Kreisel |
|
||||
| 3993 | Geruestoption fuer Einzelmodul | `GERUEST_TYP` | wie Kreisel |
|
||||
|
||||
@@ -86,9 +88,56 @@ Stueckzahl der Gruppe steht im Merkmal 4311.
|
||||
| 4337 | Streckengruppe - Anzahl der Separatoren - Gefaellestrecke | `ANZAHL_SEPARATOR` | direkt (kein Split noetig, kein Vario-Anteil vorhanden) |
|
||||
| 4338 | Streckengruppe - Bearbeitung Gefaellestreckenteilstueck fuer Separator (829516050) | - | fest `SEPARATOR_BEARBEITUNG_ANZEIGE` |
|
||||
| 4339 | Streckengruppe - Anzahl der Scanner | `ANZAHL_SCANNER` | direkt |
|
||||
| 4427-4432 | AS-/ES-Element (vorhanden/Winkel/Seite) | `WINKEL_AS`/`SEITE_AS`/`WINKEL_ES`/`SEITE_ES` | siehe eigener Abschnitt unten |
|
||||
| 3992 | Geruest fuer Einzelmodul | `GERUEST_EINZELMODUL` | wie Kreisel |
|
||||
| 3993 | Geruestoption fuer Einzelmodul | `GERUEST_TYP` | wie Kreisel |
|
||||
|
||||
Die Gruppierung (`gefaellestrecke_signature`) beruecksichtigt AS-/ES-Element
|
||||
mit: zwei sonst baugleiche Gefaellestrecken mit AS links bzw. AS rechts
|
||||
bleiben getrennte Zeilen, sonst zeigte die gemeinsame Zeile nur die Seite des
|
||||
ersten Blocks.
|
||||
|
||||
## AS-/ES-Element (4427-4432) - gilt fuer VF_N UND GF_N
|
||||
|
||||
Die Zuordnung steht vollstaendig in `cfg/sivas.cfg` - mit denselben sechs
|
||||
Zeilen in `[gefaellestrecke]` UND `[variofoerderer]`, weil beide Blockarten
|
||||
dieselben Attribute des gemeinsamen Strecken-Schemas tragen
|
||||
(`*strecke-attr-front*` in `ssg_core.lsp`). In `export_sivas.py` stehen nur
|
||||
die Transform-Funktionen.
|
||||
|
||||
Sivas-Hierarchie (Merkmalstamm): 4431/4432 (`"Ja"`/`"Nein"`) sind die
|
||||
Oberknoten, Winkel und Seite haengen als Unterknoten darunter - darum auch
|
||||
diese Reihenfolge in der Config.
|
||||
|
||||
| Merkmalnr | Bezeichnung (Merkmalstamm) | Block-Attribut | Transform | Berechnung |
|
||||
|---|---|---|---|---|
|
||||
| 4431 | AS-Element | `WINKEL_AS` | `as_es_vorhanden` | `"Ja"`, wenn ein Winkel gesetzt ist, sonst `"Nein"` |
|
||||
| 4427 | AS-Element - Winkel | `WINKEL_AS` | `as_es_winkel` | Optionswert der Auswahlliste (`"30"` -> `"30 °"`, Tabelle `[as_es_winkel_anzeige]`); leer, wenn kein AS-Element |
|
||||
| 4428 | AS-Element - Seite | `SEITE_AS` | `as_seite` | kleingeschrieben (`"links"`/`"rechts"`); leer, wenn kein AS-Element |
|
||||
| 4432 | ES-Element | `WINKEL_ES` | `as_es_vorhanden` | wie 4431 |
|
||||
| 4429 | ES-Element - Winkel | `WINKEL_ES` | `as_es_winkel` | wie 4427 |
|
||||
| 4430 | ES-Element - Seite | `SEITE_ES` | `es_seite` | wie 4428 |
|
||||
|
||||
**Warum der Winkel ueber das Vorhandensein entscheidet und nicht die Seite:**
|
||||
das Schema laesst `WINKEL_AS`/`WINKEL_ES` leer, wenn kein Element gewaehlt
|
||||
wurde, waehrend `SEITE_AS`/`SEITE_ES` mit `"rechts"` immer einen Vorgabewert
|
||||
tragen. Ohne Element bleiben darum Winkel UND Seite leer - sonst stuende in
|
||||
Sivas eine Seite unter einem `"Nein"`-Knoten.
|
||||
|
||||
**Winkel-Schreibweise:** die Sivas-Auswahlliste fuehrt `"30 °"`/`"90 °"` (mit
|
||||
Leerzeichen vor dem Gradzeichen), das Block-Attribut dagegen die nackte Zahl.
|
||||
Die Uebersetzung steht als Tabelle `[as_es_winkel_anzeige]` in `sivas.cfg`
|
||||
(gleiche Bauart wie `[geruest_typ_anzeige]`) - weicht Sivas davon ab, ist das
|
||||
die einzige Stelle zum Nachziehen. Ein Winkel ohne Eintrag dort wird
|
||||
unveraendert uebernommen.
|
||||
|
||||
**Neu im Mapping-Mechanismus:** `4428`/`4430` brauchen ein ZWEITES Attribut
|
||||
(die Seite haengt am Winkel). Dafuer gibt es in `sivas_mapping.py` den
|
||||
Dekorator `@braucht_attribs` - ein so markierter Transform wird als
|
||||
`fn(wert, attribs)` statt `fn(wert)` aufgerufen und sieht damit die uebrigen
|
||||
Attribute des Blocks. Ohne diese Klammer muessten bedingte Merkmale wieder
|
||||
als Python-Code aus der Config herauswandern.
|
||||
|
||||
## ILS 2.0 Zusatzmodul (SivasNr 6215, Dispogruppe 20)
|
||||
|
||||
BTMT-Beladestationen UND Abwurfstationen (Klammerbuegel-Entladung) in EINER
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"kettenfoerderer": {
|
||||
"id": "Kettenfoerderer",
|
||||
"titel": "Kettenfoerderer (Schraegfoerderer Stahl)",
|
||||
"layer": "kettenfoerderer",
|
||||
"teileart": "Schraegfoerderer Stahl",
|
||||
"foerderertyp": "Schrägförderer Stahl",
|
||||
|
||||
"einbauhoehe": { "vorgabe": 1500, "min": 300, "max": 8000 },
|
||||
"laenge": { "min": 100, "max": 20000 },
|
||||
|
||||
"_hinweis_ansicht": "KF_2D liegt DECKUNGSGLEICH mit der Kette (KS_EIN auf KS_EIN der Umlenkung, KS_AUS auf KS_AUS des Antriebs) - die Baugruppe ist EIN Koerper. Den frueheren Versatz (versatz_y) gibt es nicht mehr, seit die Kette aufgerichtet eingebaut wird.",
|
||||
"ansicht_2d": { "block": "KF_2D" },
|
||||
|
||||
"_hinweis_antriebsart": "Merkmal 357 ist beim Kettenfoerderer FEST: die Liste hat genau EINEN Eintrag, der im Dialog als Dropdown erscheint und zwingend gewaehlt ist. Weitere Antriebsarten (z.B. 0.55 kW) waeren einfach eine weitere Zeile.",
|
||||
"antriebsart": [
|
||||
{ "name": "1.1 kW", "wert": "1.1 kW" }
|
||||
],
|
||||
|
||||
"farbe": [
|
||||
{ "name": "RAL 7035", "wert": "RAL 7035" },
|
||||
{ "name": "RAL 2000", "wert": "RAL 2000" },
|
||||
{ "name": "RAL 5018", "wert": "RAL 5018" },
|
||||
{ "name": "Sonderfarbe", "wert": "Sonderfarbe" }
|
||||
],
|
||||
|
||||
"antriebsmotor": [
|
||||
{ "name": "Europa 50 Hz", "wert": "Europa 50 Hz" }
|
||||
],
|
||||
|
||||
"movimot": [
|
||||
{ "name": "Nein", "wert": "0" },
|
||||
{ "name": "Ja", "wert": "1" }
|
||||
],
|
||||
|
||||
"standard_steuerung": [
|
||||
{ "name": "Nein", "wert": "0" },
|
||||
{ "name": "Ja", "wert": "1" }
|
||||
],
|
||||
|
||||
"verbindungselemente": [
|
||||
{ "name": "Verbindungselemente an AP", "wert": "Verbindungselemente an AP" },
|
||||
{ "name": "Verbindungselemente an ST", "wert": "Verbindungselemente an ST" },
|
||||
{ "name": "Nein", "wert": "Nein" }
|
||||
],
|
||||
|
||||
"varianten": [
|
||||
{
|
||||
"name": "Schraegfoerderer Stahl 26 Grad",
|
||||
"winkel": 26,
|
||||
"standard": true,
|
||||
"block_umlenkung": "KF_UM_26",
|
||||
"block_laenge": "KF_LAENGE",
|
||||
"block_antrieb": "KF_AN_26",
|
||||
"sivas_id": "6120"
|
||||
},
|
||||
{
|
||||
"name": "Schraegfoerderer Stahl 30 Grad",
|
||||
"winkel": 30,
|
||||
"block_umlenkung": "KF_UM_30",
|
||||
"block_laenge": "KF_LAENGE",
|
||||
"block_antrieb": "KF_AN_30",
|
||||
"sivas_id": "6120"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,52 @@
|
||||
// ============================================================
|
||||
// jam_edit.dcl - Staubereich bearbeiten
|
||||
// Aendert Foerderer und laufende Nummer eines JAM_AREA-Blocks, den die
|
||||
// Beschriftung aus sps_skel (lib/tro_annotate.py --anlage) eingefuegt hat.
|
||||
// Aufruf ueber c:JAM_EDIT (Lisp/Jam_Edit.lsp).
|
||||
// ============================================================
|
||||
|
||||
jam_edit : dialog {
|
||||
label = "Staubereich bearbeiten";
|
||||
|
||||
: column {
|
||||
|
||||
: text {
|
||||
key = "bereich";
|
||||
label = "";
|
||||
width = 50;
|
||||
}
|
||||
|
||||
: edit_box {
|
||||
key = "conveyor";
|
||||
label = "Foerderer (NNNN):";
|
||||
edit_width = 8;
|
||||
}
|
||||
|
||||
: edit_box {
|
||||
key = "number";
|
||||
label = "Laufende Nummer:";
|
||||
edit_width = 8;
|
||||
}
|
||||
|
||||
: row {
|
||||
: text {
|
||||
key = "auto";
|
||||
label = "";
|
||||
width = 30;
|
||||
}
|
||||
: button {
|
||||
key = "reset";
|
||||
label = "Abgeleitet uebernehmen";
|
||||
}
|
||||
}
|
||||
|
||||
: text {
|
||||
key = "hinweis";
|
||||
label = "";
|
||||
width = 50;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ok_cancel;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// ============================================================
|
||||
// kettenfoerderer.dcl - Kettenfoerderer (Schraegfoerderer Stahl)
|
||||
// Verwendet von KettenFoerderer.lsp (kf-dialog, Befehl KETTENFOERDERER).
|
||||
//
|
||||
// VORLAGE mit Markerzeilen: nur der Varianten-Block ist datenabhaengig und
|
||||
// wird zur Laufzeit an //@VARIANTEN@ eingesetzt (kf-dcl-ersetzungen ->
|
||||
// ssg-dcl-vorlage-fuellen in ssg_core, Temp-Datei). Grund: DCL kann
|
||||
// radio_button-Tiles weder zur Laufzeit erzeugen noch ihre Labels per
|
||||
// set_tile aendern - gleiches Vorgehen wie geruest_traeger.dcl.
|
||||
//
|
||||
// Varianten bewusst als Radiobuttons statt popup_list: es sind nur zwei
|
||||
// Werte (26/30 Grad), beide sollen ohne Aufklappen sichtbar sein.
|
||||
// Die Gruppenbeschriftung steht am boxed_row - ein zusaetzliches Label am
|
||||
// Tile waere doppelt gemoppelt.
|
||||
//
|
||||
// Die Beschriftungen folgen dem Sivas-Merkmalstamm, damit Dialog und
|
||||
// Stueckliste dieselbe Sprache sprechen (Merkmalnummer in Klammern):
|
||||
// Schraegfoerderer Stahl Typ (359) H - Einbauhoehe Schraegfoerderer (360)
|
||||
// Farbe Foerderer (354) Antriebsmotor Foerderer (355)
|
||||
// Antrieb mit Movimot (356) Verbindungselemente (391)
|
||||
// Farbe und Antriebsmotor sind dabei ZWEI eigenstaendige Merkmale
|
||||
// (Attribute FARBE und ANTRIEBSMOTOR), nicht ein kombinierter Text.
|
||||
//
|
||||
// Kein Geruest-Bereich: der Kettenfoerderer traegt sich selbst.
|
||||
// ============================================================
|
||||
|
||||
kettenfoerderer : dialog {
|
||||
label = "Kettenfoerderer";
|
||||
width = 62;
|
||||
|
||||
: boxed_radio_row {
|
||||
key = "variante";
|
||||
label = "Schraegfoerderer Stahl Typ";
|
||||
//@VARIANTEN@
|
||||
}
|
||||
|
||||
: boxed_column {
|
||||
label = "Geometrie";
|
||||
|
||||
: row {
|
||||
: edit_box {
|
||||
key = "hoehe";
|
||||
label = "H - Einbauhoehe Schraegfoerderer [ mm ]:";
|
||||
edit_width = 12;
|
||||
}
|
||||
// Zweite Eingabeart: Hoehe aus zwei gewaehlten Punkten messen.
|
||||
// Der Knopf schliesst den Dialog (done_dialog 2), der Aufrufer pickt
|
||||
// die Punkte und zeigt ihn mit dem Ergebnis erneut - aus einem
|
||||
// action_tile heraus laesst sich kein getpoint aufrufen.
|
||||
: button {
|
||||
key = "hoehe_messen";
|
||||
label = "aus 2 Punkten messen";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
: boxed_column {
|
||||
label = "Ausfuehrung";
|
||||
|
||||
// Reihenfolge wie im Sivas-Merkmalstamm: 361 vor 354 - Dialog,
|
||||
// Attributschema und Merkmalstamm bleiben damit in derselben Folge.
|
||||
: popup_list {
|
||||
key = "standard_steuerung";
|
||||
label = "mit Standard Steuerung:";
|
||||
width = 40;
|
||||
}
|
||||
|
||||
: popup_list {
|
||||
key = "farbe";
|
||||
label = "Farbe Foerderer:";
|
||||
width = 40;
|
||||
}
|
||||
|
||||
: popup_list {
|
||||
key = "antriebsmotor";
|
||||
label = "Antriebsmotor Foerderer:";
|
||||
width = 40;
|
||||
}
|
||||
|
||||
// Antriebsart (Merkmal 357): Dropdown mit genau EINER Option, die immer
|
||||
// gewaehlt ist - beim Kettenfoerderer ist sie fest 1.1 kW. Als Dropdown
|
||||
// statt als Textzeile, damit alle Merkmale gleich aussehen; kommt spaeter
|
||||
// eine zweite Antriebsart dazu, ist es nur eine weitere Zeile in der JSON.
|
||||
: popup_list {
|
||||
key = "antriebsart";
|
||||
label = "Antriebsart 0,55 / 1,1 kW:";
|
||||
width = 40;
|
||||
}
|
||||
|
||||
: popup_list {
|
||||
key = "movimot";
|
||||
label = "Antrieb mit Movimot:";
|
||||
width = 40;
|
||||
}
|
||||
|
||||
: popup_list {
|
||||
key = "verbindung";
|
||||
label = "Verbindungselemente:";
|
||||
width = 40;
|
||||
}
|
||||
}
|
||||
|
||||
ok_cancel;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// ============================================================
|
||||
// stueckliste.dcl - Optionen fuer Positionen + Stueckliste
|
||||
// Aufruf ueber c:SSG_FAEHNCHEN_STUECKLISTE (Lisp/ssg_stueckliste.lsp,
|
||||
// ssg-sl-dialog). Vorbelegung aus cfg/stueckliste.json bzw. dem letzten Lauf.
|
||||
// ============================================================
|
||||
|
||||
stueckliste : dialog {
|
||||
label = "Positionen + Stueckliste";
|
||||
|
||||
: boxed_column {
|
||||
label = "Layer der Positionen";
|
||||
: radio_column {
|
||||
key = "modus";
|
||||
: radio_button { key = "m_suffix"; label = "Bauteil-Layer + Suffix"; }
|
||||
: radio_button { key = "m_fest"; label = "Fester Layer"; }
|
||||
}
|
||||
: edit_box { key = "suffix"; label = "Suffix:"; edit_width = 20; }
|
||||
: edit_box { key = "fest"; label = "Fester Layer:"; edit_width = 20; }
|
||||
: text { label = "Regeln je Bauteiltyp: cfg/stueckliste.json"; }
|
||||
}
|
||||
|
||||
: boxed_column {
|
||||
label = "Stueckliste";
|
||||
: edit_box { key = "tab_layer"; label = "Tabellen-Layer:"; edit_width = 20; }
|
||||
: edit_box { key = "titel"; label = "Titel:"; edit_width = 30; }
|
||||
}
|
||||
|
||||
: boxed_column {
|
||||
label = "Nummerierung / Darstellung";
|
||||
: edit_box { key = "startnr"; label = "Erste Positionsnummer:"; edit_width = 10; }
|
||||
: edit_box { key = "faktor"; label = "Massstabsfaktor:"; edit_width = 10; }
|
||||
: toggle { key = "alle_pos";
|
||||
label = "Alle Positionen in der Fahne (100|101|...), jede Art.-Nr. nummeriert"; }
|
||||
}
|
||||
|
||||
: errtile { key = "error"; }
|
||||
ok_cancel;
|
||||
}
|
||||
+118
-7
@@ -181,6 +181,84 @@ vflw_as : dialog {
|
||||
}
|
||||
}
|
||||
|
||||
// Wie vflw_as, aber ZUSAETZLICH mit der Zufuehrungsachse (2. Punkt) in
|
||||
// DEMSELBEN Bildschirm - nur fuer das AS-Element am Kettenanfang von Modus 1
|
||||
// (Nutzer-Vorgabe 2026-10-21: "Achse und links/rechts gehoeren in ein
|
||||
// Fenster", beide zusammen legen AS-Lage UND Kettenrichtung fest: der 2.
|
||||
// Punkt gibt die KS_EIN-Achse, links/rechts die AS-Variante und damit die
|
||||
// KS_AUS-Richtung). Eigener Dialog statt einer dauerhaft ausgegrauten
|
||||
// Punkt-Zeile in vflw_as - denselben Dialog nutzt auch das ES-Element am
|
||||
// Kettenende, wo es gar keine Zufuehrungsachse gibt (gleiche Begruendung wie
|
||||
// bei vflw_winkel_seite vs. vflw_winkel_seite_30_90).
|
||||
// Punktwahl-Zeile nach dem Muster von vflw_punkt_zahl: der Button schliesst
|
||||
// den Dialog (done_dialog 2), danach laeuft (getpoint) auf der
|
||||
// Kommandozeile, danach wird der Dialog neu gezeigt - darum nutzt "back"
|
||||
// hier Code 3.
|
||||
vflw_as_achse : dialog {
|
||||
label = "VarioFoerderer Assistent";
|
||||
|
||||
: column {
|
||||
: text {
|
||||
key = "kopf";
|
||||
label = "";
|
||||
width = 60;
|
||||
}
|
||||
: toggle {
|
||||
key = "setzen";
|
||||
label = "Ja, setzen";
|
||||
}
|
||||
: boxed_radio_column {
|
||||
label = "Winkel:";
|
||||
key = "winkel";
|
||||
: radio_button { key = "winkel_90"; label = "90 Grad"; value = "1"; }
|
||||
: radio_button { key = "winkel_30"; label = "30 Grad"; }
|
||||
}
|
||||
// Beschriftungen bewusst NEUTRAL: derselbe Dialog dient dem AS-Element
|
||||
// am Kettenanfang (vorwaerts) UND dem ES-Element am Kettenende
|
||||
// (rueckwaerts bauen, 2026-10-22). Welches Element gemeint ist, sagt die
|
||||
// Kopfzeile ("kopf").
|
||||
: boxed_radio_column {
|
||||
label = "Seite (Element schleust nach):";
|
||||
key = "seite";
|
||||
: radio_button { key = "seite_links"; label = "Links"; value = "1"; }
|
||||
: radio_button { key = "seite_rechts"; label = "Rechts"; }
|
||||
}
|
||||
: boxed_column {
|
||||
label = "Fahrtrichtung (2. Punkt):";
|
||||
// Startpunkt der Kette - er ist der Sitz des AS-Elements UND der
|
||||
// Ausgangspunkt der Achse; waehrend der Punktwahl haengt das
|
||||
// Gummiband an ihm (vfl-getpoint mit Basispunkt).
|
||||
: text {
|
||||
key = "start_anzeige";
|
||||
label = "";
|
||||
width = 46;
|
||||
}
|
||||
: row {
|
||||
: button {
|
||||
key = "pick";
|
||||
label = "2. Punkt waehlen...";
|
||||
fixed_width = true;
|
||||
width = 20;
|
||||
}
|
||||
: text {
|
||||
key = "pt_anzeige";
|
||||
label = "(ohne Achse: Richtung aus dem naechsten Klick)";
|
||||
width = 46;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
: row {
|
||||
alignment = centered;
|
||||
: button { key = "back"; label = "Zurueck"; fixed_width = true; width = 12; }
|
||||
spacer;
|
||||
: button { key = "accept"; label = "Ok Weiter"; is_default = true; fixed_width = true; width = 12; }
|
||||
spacer;
|
||||
: button { key = "cancel"; label = "Abbrechen"; is_cancel = true; fixed_width = true; width = 12; }
|
||||
}
|
||||
}
|
||||
|
||||
// Winkel (30/60/90) + Seite - fuer GF-Bogen, wo alle drei Winkel geometrisch
|
||||
// gueltig sind. Fuer AS-/ES-Element (wo 60 Grad NIE gueltig ist) stattdessen
|
||||
// vflw_winkel_seite_30_90 verwenden (siehe vflw-gruppe-winkel-seite-impl/
|
||||
@@ -402,6 +480,12 @@ vflw_gf_laenge_modus : dialog {
|
||||
: radio_button { key = "modus_hoehe"; label = "Zielhoehe festlegen (Laenge wird berechnet)"; }
|
||||
: radio_button { key = "modus_steigend"; label = "Steigende GF (Sonderfall, bis 3 Grad)"; }
|
||||
: radio_button { key = "modus_qc"; label = "QC Linie mit GF (automatische Auf-Ab-Berechnung)"; }
|
||||
// Nur am Kettenanfang mit AS-Element UND festgelegter Zufuehrungsachse
|
||||
// waehlbar - sonst fehlt die Bezugsachse fuer den Abstand. Wird in
|
||||
// vflw-gruppe-gf-laenge-modus-impl per mode_tile deaktiviert (anders
|
||||
// als eine NIE waehlbare Kachel ist diese kontextabhaengig, siehe
|
||||
// "sepnach" in vflw_sep_gf).
|
||||
: radio_button { key = "modus_parallel"; label = "Parallel zum Kreisel weiterbauen (Abstand)"; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,9 +547,19 @@ vflw_sep_gf : dialog {
|
||||
key = "sepvor";
|
||||
label = "Separator VOR dieser Gefaellestrecke";
|
||||
}
|
||||
: toggle {
|
||||
key = "sepnach";
|
||||
label = "Separator NACH dieser Gefaellestrecke";
|
||||
// Steht am Kettenende ein ES-Element, ist "Separator NACH" gesperrt -
|
||||
// der Hinweis dahinter sagt warum, in EINER Zeile mit dem Ankreuzfeld
|
||||
// (gleiche Anordnung wie in vflw_seg_linie_m2). Sonst leer (set_tile "").
|
||||
: row {
|
||||
: toggle {
|
||||
key = "sepnach";
|
||||
label = "Separator NACH dieser Gefaellestrecke";
|
||||
}
|
||||
: text {
|
||||
key = "sephinweis";
|
||||
label = "";
|
||||
width = 62;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,7 +1100,13 @@ vflw_seg_linie_m2 : dialog {
|
||||
: boxed_column {
|
||||
label = "Separator (nur bei GF):";
|
||||
: toggle { key = "sep_vor"; label = "Separator VOR diesem GF-Stueck"; }
|
||||
: toggle { key = "sep_nach"; label = "Separator NACH diesem GF-Stueck"; }
|
||||
// Begruendung, wenn "NACH" gesperrt ist (ES folgt direkt), in EINER
|
||||
// Zeile hinter dem Ankreuzfeld - sonst liest sie sich wie eine eigene
|
||||
// Aussage statt wie die Erklaerung zu genau diesem Feld. Sonst leer.
|
||||
: row {
|
||||
: toggle { key = "sep_nach"; label = "Separator NACH diesem GF-Stueck"; }
|
||||
: text { key = "sephinweis"; label = ""; width = 62; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1116,13 +1216,24 @@ vflw_m2_lauf_anfang : dialog {
|
||||
label = "";
|
||||
width = 60;
|
||||
}
|
||||
// Reihenfolge nach Haeufigkeit (Nutzer-Wunsch 2026-10-23): der
|
||||
// Regelfall zuerst, der Sonderfall "offener Anfang" zuletzt. Die
|
||||
// radio_button-KEYS bleiben dabei unveraendert; journalisiert wird der
|
||||
// am Key haengende WERT ("mit-gf1"/"direkt"/"ohne", siehe
|
||||
// vfl-m2-anfang-norm), nicht die Position - Umsortieren und Umnummerieren
|
||||
// sind damit folgenlos fuer bestehende Ketten.
|
||||
: boxed_radio_column {
|
||||
label = "Lauf beginnen mit:";
|
||||
key = "anfang";
|
||||
: radio_button { key = "anfang_offen"; label = "Ohne Umlenkstation (offener Anfang, spaeter fortsetzen)"; }
|
||||
: radio_button { key = "anfang_umlenk"; label = "Umlenkstation direkt (kein GF1/Separator)"; }
|
||||
: radio_button { key = "anfang_umlenk_gf1"; label = "Umlenkstation mit GF1 + Separator"; value = "1"; }
|
||||
// Nummern wie in der Konsolenausgabe, damit Dialog und Protokoll
|
||||
// dieselbe Option gleich benennen.
|
||||
: radio_button { key = "anfang_umlenk_gf1"; label = "1 - Umlenkstation mit GF1 + Separator"; value = "1"; }
|
||||
: radio_button { key = "anfang_umlenk"; label = "2 - Umlenkstation direkt (kein GF1/Separator)"; }
|
||||
: radio_button { key = "anfang_offen"; label = "3 - Ohne Umlenkstation (offener Anfang, spaeter fortsetzen/verschmelzen)"; }
|
||||
}
|
||||
// Begruendung, wenn "Ohne Umlenkstation" gesperrt ist (AS gesetzt).
|
||||
// Breit genug fuer den vollen Satz - bei width = 60 wurde er abgeschnitten.
|
||||
: text { key = "anfanghinweis"; label = ""; width = 76; }
|
||||
}
|
||||
|
||||
ok_cancel;
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
# Datenaufbereitung der CAD-Bausteine
|
||||
|
||||
Kurzanleitung fuer alle, die neue CAD-Modelle (DWG/DXF-Bausteine) fuer die
|
||||
SSG_LIB-Makros anlegen oder bestehende ersetzen.
|
||||
|
||||
Hier finden Sie Antworten auf folgende Fragen:
|
||||
|
||||
1. [Wo sind Koordinatensysteme anzusetzen?](#1-wo-sind-koordinatensysteme-anzusetzen)
|
||||
2. [Wie muessen sie heissen?](#2-wie-muessen-die-koordinatensysteme-heissen)
|
||||
3. [Wie werden 3D-Modelle anhand der 2.5D-Skelette platziert?](#3-grundidee-platzierung-ueber-das-25d-skelett)
|
||||
4. [Wo und wie werden die Dateien abgelegt?](#4-datenablage-und-benennung)
|
||||
|
||||
Am Ende steht eine [Checkliste](#5-checkliste-fuer-ein-neues-modell).
|
||||
|
||||
---
|
||||
|
||||
## 1. Wo sind Koordinatensysteme anzusetzen?
|
||||
|
||||
Ein Koordinatensystem (KS) markiert einen **Anschlusspunkt**: die Stelle, an
|
||||
der ein Baustein an seinen Vorgaenger bzw. Nachfolger andockt. Es sitzt
|
||||
immer **auf der Mittellinie der Foerderstrecke** (dem Skelett, siehe
|
||||
Abschnitt 3), genau am Uebergang zum Nachbarteil.
|
||||
|
||||
**Aufbau eines KS** - ein kleiner Block mit drei LINEs, alle ab demselben
|
||||
Ursprung:
|
||||
|
||||
| Achse | Farbe | Laenge | Richtung |
|
||||
|---|---|---|---|
|
||||
| X | rot (1) | 1 | Foerderrichtung (bzw. Anschlussrichtung, siehe unten) |
|
||||
| Y | gruen (3) | 2 | quer dazu, nach links |
|
||||
| Z | blau (5) | 3 | nach oben, aus der Zeichenebene |
|
||||
|
||||
Die Makros erkennen die Achsen **nur an der Linienlaenge** (1 = X, 2 = Y,
|
||||
3 = Z; X darf auch 100 lang sein). Farben dienen nur der Lesbarkeit. Der
|
||||
KS-Block liegt auf Layer `_KOORDINATENSYSTEME` und muss **direkt** (eine
|
||||
Ebene tief) im Baustein eingefuegt sein, nicht in einem weiteren Unterblock.
|
||||
|
||||
### ILS-Kettenbausteine (Vario, Gefaelle, AS/ES, Staustrecke, Separator ...)
|
||||
|
||||
- **`KS_EIN`** am Einlauf, **`KS_AUS`** am Auslauf.
|
||||
- Bei **beiden** zeigt die X-Achse **in Foerderrichtung**. Beim Verketten
|
||||
kommt das `KS_EIN` des Nachfolgers auf das `KS_AUS` des Vorgaengers; die
|
||||
Richtung des Folgebausteins wird aus der X-Achse von `KS_AUS` gemessen
|
||||
(z.B. beim Kettenfoerderer).
|
||||
- Laengenvariable Teile (Staustrecke, `KF_LAENGE`) liegen entlang **+X** und
|
||||
werden in X skaliert - `KS_EIN` bei X=0, `KS_AUS` am Ende der
|
||||
Referenzlaenge (z.B. 1000 mm).
|
||||
|
||||
### Omniflo-Boegen und -Weichen
|
||||
|
||||
- Anschluss-KS heissen **`K1` bis `K4`**. Die X-Achse zeigt jeweils **in
|
||||
das Element hinein** (tangential zur Linie).
|
||||
- Zuordnung:
|
||||
|
||||
| KS | Boegen | Weichen |
|
||||
|---|---|---|
|
||||
| K1 | Beginn der obersten waagerechten Linie, X nach rechts | Beginn der untersten senkrechten Linie, X nach oben |
|
||||
| K2 | anderes Kettenende | Ende des linken Bogenzweigs |
|
||||
| K3 | - | Ende des rechten Bogenzweigs (nur bei 2+ Boegen) |
|
||||
| K4 | - | oberes Ende der K1-Linie (nicht bei Doppel-/Dreifach-/Deltaweiche) |
|
||||
|
||||
- K1-K4 muessen nicht von Hand gezeichnet werden: `lib/set_koords.py --set-all`
|
||||
setzt sie geometrisch, vorher setzt `bin\set_einfuegepunkt.bat`
|
||||
(`lib/set_einfuegepkt.py`) den Einfuegepunkt. Details: [tools.md](tools.md).
|
||||
|
||||
### Bausteine ohne KS
|
||||
|
||||
Einzeln frei platzierte Teile (Kreisel-Raeder `AN8`/`SP8`, BTMT-Stationen,
|
||||
Scanner, Eingang/Ausgang, Geruestteile) brauchen kein KS. Hier zaehlt nur
|
||||
der **Einfuegepunkt** (Basispunkt der DWG), siehe Abschnitt 3.
|
||||
|
||||
---
|
||||
|
||||
## 2. Wie muessen die Koordinatensysteme heissen?
|
||||
|
||||
| Name | Verwendung |
|
||||
|---|---|
|
||||
| `KS_EIN` | Einlauf eines ILS-Kettenbausteins |
|
||||
| `KS_AUS` | Auslauf eines ILS-Kettenbausteins |
|
||||
| `K1` ... `K4` | Anschluesse von Omniflo-Boegen/-Weichen |
|
||||
|
||||
- Genau diese Schreibweise, **ohne** `_2D`/`_3D`-Suffix (die KS-Bloecke sind
|
||||
dimensionsunabhaengig und in 2D- und 3D-Variante identisch).
|
||||
- Je Baustein jedes KS **nur einmal**.
|
||||
- `KSYS_EIN`/`KSYS_AUS` werden aus Altbestaenden noch gelesen, fuer neue
|
||||
Modelle aber nicht mehr verwenden.
|
||||
|
||||
---
|
||||
|
||||
## 3. Grundidee: Platzierung ueber das 2.5D-Skelett
|
||||
|
||||
**Skelett** = die Mittellinie der Foerderstrecke als einfache Linien/Boegen.
|
||||
"2.5D", weil es eine flache Grundriss-Geometrie ist, deren Punkte zusaetzlich
|
||||
eine Hoehe (Z) tragen - keine echte 3D-Konstruktion.
|
||||
|
||||
Das Prinzip hat zwei Seiten:
|
||||
|
||||
**a) Im Baustein selbst** ist das Skelett die Bezugsgeometrie:
|
||||
|
||||
- Die 2D-Variante *ist* das Skelett (plus Symbolik).
|
||||
- Das 3D-Modell enthaelt **dieselben 2D-Skelettlinien** in seiner
|
||||
Grundebene. Einfuegepunkt und KS liegen auf diesem Skelett - deshalb
|
||||
sind sie in 2D- und 3D-Variante **deckungsgleich** und die Varianten
|
||||
beliebig austauschbar. Die Omniflo-Werkzeuge (`set_einfuegepkt.py`,
|
||||
`set_koords.py`) werten genau diese Skelettlinien aus; ohne sie
|
||||
funktionieren sie bei 3D-Dateien nicht.
|
||||
- Gezeichnet wird in der Lage "Foerderrichtung = +X, Z nach oben". Einzige
|
||||
Ausnahme: aufrecht eingebaute Teile wie der Kettenfoerderer (`KF_*`)
|
||||
sind in XY gezeichnet (Y = Hoehe) und werden vom Makro aufgerichtet.
|
||||
|
||||
**b) In der Anlage** liefert der Anwender bzw. das Makro das Skelett
|
||||
(geklickte Punkte, gezeichneter Linienzug, Hoehen). Die Makros setzen die
|
||||
Bausteine darauf nacheinander:
|
||||
|
||||
1. `KS_EIN` des Bausteins auf den aktuellen Skelettpunkt legen.
|
||||
2. Drehen: um Z nach der Grundriss-Richtung des Segments, um Y nach dessen
|
||||
Neigung (Rz * Ry).
|
||||
3. Laengenteile in X auf die Segmentlaenge skalieren.
|
||||
4. Weltlage von `KS_AUS` lesen = Startpunkt des naechsten Bausteins.
|
||||
|
||||
Freistehende Teile ohne KS werden nur mit Einfuegepunkt + Drehung gesetzt
|
||||
(z.B. `AN8` mit dem Basispunkt in der Radmitte).
|
||||
|
||||
Weil 3D-Modell und 2D-Symbol am selben Skelett haengen, kann jede Anlage
|
||||
wahlweise in 2D oder 3D aufgebaut und spaeter umgeschaltet werden.
|
||||
|
||||
---
|
||||
|
||||
## 4. Datenablage und Benennung
|
||||
|
||||
Grundregeln:
|
||||
|
||||
- **Eine Datei je Baustein**, Dateiname = Blockname.
|
||||
- Namen nur **ASCII, ohne Umlaute und Leerzeichen** (`ae`/`oe`/`ue`, `_`
|
||||
als Trenner).
|
||||
- Der Basispunkt der DWG ist der Einfuegepunkt (s. Abschnitt 3).
|
||||
|
||||
| Bereich | Ablage | Benennung |
|
||||
|---|---|---|
|
||||
| ILS (Kreisel, Vario, Gefaelle, AS/ES, Stationen, Sensoren) | `data/ils/` **flach** | `<Name>_2D.dwg` und `<Name>_3D.dwg`, z.B. `AS_Element_30_links_3D.dwg`. Fehlt die 2D-Datei, wird automatisch die 3D-Datei genommen |
|
||||
| Omniflo-Boegen/-Weichen | `data/omniflo/2D/` bzw. `data/omniflo/3D/` | Sivas-Nummer, `.dxf`, z.B. `821104024.dxf`; Kombinationen mit `+`, z.B. `821104024+0_B10081.dxf` |
|
||||
| Omniflo-Verbinder | `data/omniflo/Verbinder/` | dimensionsunabhaengig, z.B. `TV_AP60-ST_kpl.dwg` |
|
||||
| Kettenfoerderer | `data/omniflo/2D/` | ohne Suffix: `KF_UM_26`, `KF_AN_30`, `KF_LAENGE`, `KF_2D` |
|
||||
| Geruest | `data/geruest/` | Artikelnummer, z.B. `821006031.dwg`; Platzhalter `dummy_*.dwg` |
|
||||
| DIN-Rahmen/Schriftkoepfe | `cfg/rahmen/` | `A0.DWG` ... `Kopf11.dwg` |
|
||||
|
||||
**Zugehoerige Daten** (Masse, Sivas-/Artikelnummern, Auswahllisten) liegen
|
||||
nicht in der DWG, sondern in `data/json/` - z.B. `omniflo_boegen.json`,
|
||||
`omniflo_weichen.json`, `geruest.json`, `kettenfoerderer.json`. Ein neues
|
||||
Omniflo- oder Geruestteil ist erst auswaehlbar, wenn es dort eingetragen ist.
|
||||
|
||||
**Attribute und Layer:**
|
||||
|
||||
- Bloecke, die nur eingefuegt werden, tragen ihren Ziel-Layer als Attribut
|
||||
**`LAYER`** (Vorgaben je Block in `data/ils/allocations.json`, z.B.
|
||||
`AN8_2D` -> `ILS_ANTR`, `AN8_3D` -> `_3D_ILS_ANTR`).
|
||||
- Ein leeres **`ID`**-Attribut mit anlegen - nur dann kann die automatische
|
||||
ID-Vergabe fuer den Export es befuellen.
|
||||
- Omniflo-Teile brauchen fuer den Export `TEILEART` (`Omniflo ...`) und
|
||||
`ARTINR`.
|
||||
- Layer/Farbe zusammengebauter Baugruppen (`KREISEL_n`, `VF_n`, `GF_n`)
|
||||
stehen nicht im Modell, sondern in `cfg/layer.cfg`.
|
||||
|
||||
---
|
||||
|
||||
## 5. Checkliste fuer ein neues Modell
|
||||
|
||||
- [ ] Dateiname nach Tabelle in Abschnitt 4, ASCII, im richtigen Ordner
|
||||
- [ ] ILS: 2D- **und** 3D-Variante, Basispunkt und KS deckungsgleich
|
||||
- [ ] 3D-Modell enthaelt die 2D-Skelettlinien
|
||||
- [ ] Foerderrichtung entlang +X, Z nach oben
|
||||
- [ ] Kettenbaustein: `KS_EIN`/`KS_AUS` direkt im Block, X in Foerderrichtung,
|
||||
Achslaengen 1/2/3
|
||||
- [ ] Omniflo: `set_einfuegepkt.py` und `set_koords.py --set-all` gelaufen,
|
||||
Kontrolle per `--show-omniflo`
|
||||
- [ ] Attribute `LAYER` und leeres `ID` vorhanden (Omniflo zusaetzlich
|
||||
`TEILEART`, `ARTINR`)
|
||||
- [ ] Eintrag in der passenden JSON unter `data/json/` bzw. `allocations.json`
|
||||
- [ ] In BricsCAD einmal ueber das Menue einfuegen/verketten und pruefen,
|
||||
dass der Anschluss sauber sitzt
|
||||
@@ -7,8 +7,7 @@ und die Treiber in `tests/test_*.lsp`, die sie lesen.
|
||||
|
||||
Die zugehoerigen LISP-Routinen mit Signaturen stehen in
|
||||
[lisp_methods.md](lisp_methods.md). Diese Seite ersetzt das fruehere
|
||||
`tests/testdata/object_data.md` (geloescht in Commit `e147b89`, auf das Code-
|
||||
Kommentare teilweise noch verweisen).
|
||||
`tests/testdata/object_data.md` (geloescht in Commit `e147b89`).
|
||||
|
||||
**Feldnamen als Python-Konstanten**: `lib/testdata_schema.py` buendelt die
|
||||
Feldnamen/festen Werte der Abschnitte 1 (Kreisel), 2 (Einzelbloecke), 3 (VF
|
||||
|
||||
+34
-7
@@ -37,7 +37,9 @@ Gross-/Kleinschreibung spielt an der Kommandozeile keine Rolle.
|
||||
| `KreiselLabelSetup` | Beschriftung einstellen (Hoehe, Farbe, Abstand, Schriftart) |
|
||||
| `KreiselLabelPos` | Versatz der Beschriftung (dx/dy) einstellen |
|
||||
| `KreiselLabelHoehe` | Texthoehe der Beschriftung einstellen |
|
||||
| `ILS_Eckrad` | Eckrad an einem Tangentenpunkt mit Richtung einfuegen |
|
||||
| `ILS_Eckrad` | Eckrad einfuegen (Dialog `eckrad_edit.dcl`, ohne GUI Konsolen-Rueckfall) |
|
||||
| `EckradEdit` | Bestehendes Eckrad per Dialog bearbeiten (auch per Doppelklick) |
|
||||
| `KREISEL_WEICHEN` | Beruehrpunkte/Weichen und Kollisionen aller Kreisel/Eckraeder gleicher Hoehe ermitteln, Marker setzen |
|
||||
|
||||
### VarioFoerderer (`VarioFoerderer.lsp` -> `vf_core`/`vf_standard`/`vf_etage`/`vf_linienzug`/`vf_spec`)
|
||||
|
||||
@@ -97,18 +99,28 @@ Gross-/Kleinschreibung spielt an der Kommandozeile keine Rolle.
|
||||
| `OMNI_WKomb_Delta_1400`, `OMNI_WKomb_Delta_1600`, `OMNI_WKomb_Star` | Weichenkombinationen (Delta, Stern) |
|
||||
| `OMNI_APBW_R400_45_140`, `OMNI_APBW_R400_675_260`, `OMNI_APBW_R550_45_77`, `OMNI_APBW_R550_45_194`, `OMNI_APBW_R550_225_360`, `OMNI_APBW_R550_225_410A`/`B`/`C`, `OMNI_APBW_R550_675_58`/`_125`/`_208`/`_360`, `OMNI_APBW_R650_90_300`, `OMNI_APBW_R750_90_200` | Boegen fuer Weichen (fest, ohne Dialog) |
|
||||
| `OMNI_TEF_UmlenkL`/`R`, `OMNI_TEF_AntriebL`/`R`, `OMNI_TEF_Gerade` | TEF-Elemente (fest, ohne Drehung) |
|
||||
| `OMNI_SCHW_400_L`/`_R`, `OMNI_SCHW_400_L_SENSORIK`/`_R_SENSORIK` | Schwenkschienen fuer Schiebetueren (Menue Spez. Streckenelemente -> Tuerloesungen) |
|
||||
| `OMNI_STOPPER`, `OMNI_SCANNER`, `OMNI_BUERSTENBREMSE` | Anbaugruppen |
|
||||
| `OMNI_TV_W_W`, `OMNI_TV_W_AP60`, `OMNI_TV_W_AP60_KPL`, `OMNI_TV_W_AP110`, `OMNI_TV_W_AP110_W`, `OMNI_TV_50`, `OMNI_TV_80`, `OMNI_TV_ENDPLATTE`, `OMNI_TV_ANSCHLAG`, `OMNI_TV_MUFFE`, `OMNI_TV_A_AP110_AP60`, `OMNI_TV_A_AP60_ST`, `OMNI_TV_A_AP110_ST`, `OMNI_TV_SW_II_SW_SW`, `OMNI_TV_SW_I_AP110`, `OMNI_TV_SW_III_AP110_SW`, `OMNI_TV_SW_IV_AP60`, `OMNI_TV_SW_IV_ST` | Verbinder |
|
||||
| `OMNI_LADESCHLEIFE_AP110` | Ladeschleife (Dialog `omniflo_ladeschleifen.dcl`) |
|
||||
| `OMNI_KettenFoerderer` | Platzhalter (noch ohne Funktion) |
|
||||
| `OMNI_EDIT` | Omniflo-Element per Dialog bearbeiten; auch per Doppelklick |
|
||||
| `OMNI_FAHRSTRECKE` (`GeruestInsert.lsp`) | Omniflo-Fahrstrecke mit Linien-Logik wie `GERUEST_TRAEGER` (Dialog `fahrstrecke.dcl`) |
|
||||
| `OMNI_FAHRSTRECKE_BESCHRIFTEN` | Alle Fahrstrecken der Zeichnung neu beschriften |
|
||||
|
||||
### Kettenfoerderer (`KettenFoerderer.lsp`)
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
|---|---|
|
||||
| `KETTENFOERDERER` | Kettenfoerderer/Schraegfoerderer Stahl per Dialog (`kettenfoerderer.dcl`) als Block `KF_<n>` bauen; Menue Omniflo -> KettenFoerderer |
|
||||
| `KF_EDIT` | `KF_n`-Block bearbeiten und neu aufbauen; auch per Doppelklick |
|
||||
| `KF_KS_PRUEFEN` | Diagnose (nicht im Menue): KS-Lage der Kettenfoerderer-Bausteine pruefen |
|
||||
|
||||
### Geruest (`GeruestInsert.lsp`)
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
|---|---|
|
||||
| `GERUEST` | Geruest-Dialog (Bereich frei waehlbar) |
|
||||
| `GERUEST_SAEULEN` / `GERUEST_ROHRABHAENGER` / `GERUEST_WANDBEFESTIGUNG` | Derselbe Dialog, im jeweiligen Bereich geoeffnet |
|
||||
| `GERUEST_SAEULEN` / `GERUEST_ROHRABHAENGER` / `GERUEST_WANDBEFESTIGUNG` | Je eigener Dialog aus der Vorlage `geruest.dcl` (keine Umschaltung zwischen den Bereichen) |
|
||||
| `GERUEST` | Ohne Bereich nur ein Hinweis; im Menue Platzhalter fuer den Gattertraeger |
|
||||
| `GERUEST_TRAEGER` | Rohr-Geruest-Traeger: Dialog (`geruest_traeger.dcl`), danach Start-/Endpunkt oder Laenge bis ESC/Enter |
|
||||
| `GERUEST_TRAEGER_BESCHRIFTEN` | Alle Traeger der Zeichnung neu beschriften, verwaiste Beschriftungen entfernen |
|
||||
|
||||
@@ -120,6 +132,7 @@ Gross-/Kleinschreibung spielt an der Kommandozeile keine Rolle.
|
||||
| `TRO_EDIT` | ID/TYPE eines TRO-Markers per Dialog aendern |
|
||||
| `CONNECTION_INSERT` | Verbindungspfeil (Fluss) zwischen zwei Elementen zeichnen |
|
||||
| `CONNECTION_EDIT` | Quelle/Ziel einer Verbindung aendern |
|
||||
| `JAM_EDIT` (`Jam_Edit.lsp`) | Staubereich (`JAM_AREA` aus sps_skel) bearbeiten: Foerderer und laufende Nummer; auch per Doppelklick |
|
||||
|
||||
### Export und IDs (`export.lsp`, `ssg_id.lsp`, `count_sep_scan.lsp`, `check_hoehen.lsp`)
|
||||
|
||||
@@ -132,7 +145,7 @@ Gross-/Kleinschreibung spielt an der Kommandozeile keine Rolle.
|
||||
| `IDSCHECK` | Alle Bloecke auf doppelte IDs pruefen und korrigieren |
|
||||
| `IDGENERATE` | Gewaehltem Block eine neue ID zuweisen |
|
||||
| `ZAEHLE_SEP_SCAN` | Scanner/Separatoren je Kreisel/VF/GF zaehlen und in ANZAHL_SCANNER/ANZAHL_SEPARATOR schreiben (laeuft auch automatisch vor jedem Export) |
|
||||
| `HOEHEN_CHECK` | Hoehen von Kreiseln/VF/GF messen und in HOEHE/HOEHE_VON_mm/HOEHE_BIS_mm/MONTAGEHOEHE_m schreiben |
|
||||
| `HOEHEN_CHECK` | Hoehen von Kreiseln/VF/GF messen und in HOEHE/HOEHE_VON_mm/HOEHE_BIS_mm/MONTAGEHOEHE_m schreiben; Phase 3: Buehnenabzug einmal pro Kreisel-Familie (beruehrende Kreisel gleicher Hoehe), wirkt auf Kreisel und die VF/GF der Familie |
|
||||
| `CALLPYTHON` (`external_call.lsp`) | Test des LISP->Python-Aufrufs (`lib/testpycall.py`) |
|
||||
|
||||
### Konfiguration, Planquadrate, Doppelklick
|
||||
@@ -145,9 +158,22 @@ Gross-/Kleinschreibung spielt an der Kommandozeile keine Rolle.
|
||||
| `DRAW_PLANQUADRATE` | Planquadrat-Raster (Block `ZZ_PLANQUADRATE`) zeichnen bzw. neu aufbauen |
|
||||
| `DELETE_PLANQUADRATE` | Planquadrat-Raster entfernen |
|
||||
| `PLANQUADRATE_TOGGLE` | Raster an/aus (zeichnen, falls keins existiert, sonst entfernen) |
|
||||
| `SSG_BLOCKEDIT` | Doppelklick-/Kontextmenue-Dispatcher: Kreisel, Omniflo, GF_*, VF_*, GR_*, TRO_* auf den passenden Edit-Befehl |
|
||||
| `SSG_BLOCKEDIT` | Doppelklick-/Kontextmenue-Dispatcher: Kreisel, Eckrad, Omniflo, GF_*, VF_*, KF_*, GR_*, TRO_*, JAM_* auf den passenden Edit-Befehl |
|
||||
| `EATTEDIT` | Ueberschreibt den nativen Befehl, leitet an `SSG_BLOCKEDIT` weiter (Fallback `_.EATTEDIT`) |
|
||||
|
||||
### Werkzeuge (`ssg_blocktools.lsp`, `ssg_texttools.lsp`, `ssg_stueckliste.lsp`, `DinFormate.lsp`)
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
|---|---|
|
||||
| `SSG_BLOCK_COUNT` | Blockeinfuegungen im aktuellen Layout zaehlen (Pick, Muster oder Statistik) |
|
||||
| `SSG_BLOCK_DELETE` | Alle Einfuegungen eines Blocks loeschen (mit Rueckfrage) |
|
||||
| `SSG_ATTR_ERSETZEN` | Attributwerte zeichnungsweit oder in einer Auswahl suchen und ersetzen |
|
||||
| `SSG_TEXT_ERSETZEN` | Suchen/Ersetzen in TEXT, MTEXT und Attributen |
|
||||
| `SSG_TEXT_PARALLEL` | Text parallel zu Linie/Polylinie/Bogen setzen |
|
||||
| `SSG_TEXT_HOEHE` / `SSG_TEXT_STIL` | Texthoehe bzw. Textstil aendern |
|
||||
| `SSG_FAEHNCHEN_STUECKLISTE` | Positions-Faehnchen und Stuecklistentabelle aus den gewaehlten Elementen der Zeichnung |
|
||||
| `DIN_FORMATE` | DIN-Rahmen (A0-A4) und optional Schriftkopf einfuegen |
|
||||
|
||||
### Layer-Werkzeuge (`ssg_layer.lsp`)
|
||||
|
||||
| Befehl | Beschreibung |
|
||||
@@ -202,6 +228,8 @@ Aus dem Menue "Tests" bzw. der Kommandozeile; Details in `doc/LispTests.md`.
|
||||
| `TEST_MUBEA` | Mubea-Nachbau aus `tests/testdata/mubea.json` |
|
||||
| `TEST_DEMATIC_ARVATO` | Dematic/Arvato-Nachbau (Flowpuffer/Kreisel) |
|
||||
| `TEST_SHOWROOM_ILS` | ILS-3.0-Showroom-Nachbau (Kreisel, Gefaellestrecken; Hoehen noch Platzhalter) |
|
||||
| `TEST_LASTENT` | `ssg-lastent-ohne-attribute` (kopierter Attribut-Block verliert keine Attribute) |
|
||||
| `TEST_STUECKLISTE` | Faehnchen + Stueckliste aus der Zeichnung |
|
||||
| `TEST_TEST_SYSTEM` | Testanlage `test_system` nachbauen (9 Kreisel, Separatoren, BTMT) - Vorlage fuer sps_skel |
|
||||
|
||||
---
|
||||
@@ -218,7 +246,6 @@ Alle Skripte rufen zuerst `setenv.bat` (bzw. `setenv.sh`) auf.
|
||||
| `install_py.bat` / `install_py.sh` | `.venv` anlegen und `requirements.txt` installieren (nur wenn noch nicht vorhanden) |
|
||||
| `activate_venv.bat` / `activate_venv.sh` | `.venv` aktivieren, Python-Version und Pakete anzeigen |
|
||||
| `run_tests.bat` | Testausfuehrung, siehe unten |
|
||||
| `create_tests.bat` | Kompletter ILS-Testlauf: Basis-DXF erzeugen, BricsCAD mit `ILS_test.scr`, Ergebnisse validieren |
|
||||
| `set_einfuegepunkt.bat [schalter]` | Wrapper fuer `lib/set_einfuegepkt.py` (siehe `doc/tools.md`) |
|
||||
| `set_coords.bat [schalter]` | Wrapper fuer `lib/set_koords.py` (siehe `doc/tools.md`) |
|
||||
| `dbg2lsp.bat [argumente]` | Wrapper fuer `lib/dbg2lsp.py` (siehe `doc/dbg2lsp.md`) |
|
||||
|
||||
@@ -1,33 +1,38 @@
|
||||
# Kapitel 1: Meilensteinplanung
|
||||
|
||||
Status-Stand: 2026-10-26 (DONE = im Menue nutzbar und im Sivas-/CSV-Export erfasst).
|
||||
|
||||
## Meilenstein 1: ILS für die Projektierung
|
||||
- ILS Kreisel DONE
|
||||
- ILS Eckrad DONE
|
||||
- ILS Varioförder DONE
|
||||
- ILS Gefällestrecke
|
||||
- ILS Weichen
|
||||
- ILS Horizontalvariobögen (30,60,90 r und l, innen und aussen angetrieben)
|
||||
- ILS Gefällebögen (30,60,90 r und l)
|
||||
- ILS Varioförder DONE (Standard, Etage, Streckengruppe/Linienzug Modus 1-3, QC-Linie mit GF)
|
||||
- ILS Gefällestrecke DONE (einfach, aus 3D-Linie, aus Linienzug; Doppelklick-Edit)
|
||||
- ILS Weichen TEILWEISE (Weichenpunkte zwischen Kreiseln ermitteln: KREISEL_WEICHEN, Export Merkmal 4403 + Weichenzeile; keine eigene Weichen-Geometrie)
|
||||
- ILS Horizontalvariobögen (30,60,90 r und l, innen und aussen angetrieben) TEILWEISE (als Vario-Kurve innerhalb der Streckengruppe; die frueheren Einzelbefehle ILS_K* wurden entfernt)
|
||||
- ILS Gefällebögen (30,60,90 r und l) TEILWEISE (als GF-Bogen innerhalb von Streckengruppe/Gefaellestrecke-Linienzug)
|
||||
- BTMT Beladung und Entladung DONE (Einfuegen + Sivas-/CSV-Export)
|
||||
- CSV Export aller ILS Elemente
|
||||
- CSV Export aller ILS Elemente DONE (EXPORTCSV / EXPORTSIVAS)
|
||||
|
||||
## Meilenstein 2: Ersatz von Bihler Gerüst
|
||||
- Gerüst
|
||||
+ Abhänger (3 Quetschung, 6 Abhängung oben, 4 Abhängung unten, 4 Befestiung oben, 3 Farben, Variable Länge)
|
||||
+ T-Abhänger mit Flansch-Rohr (3 Spannpratze, 3 Farben, Variable Länge)
|
||||
+ Säulen (2 Arten, 3 Farben, 2 Einbauwinkel Platte, 5 Haltearm, 4 Einbauwinkel Arm, 8 Klemmring, Länge Bodensäule)
|
||||
+ Wandbefestigung (4 Varianten, 3 Befestigungen)
|
||||
+ Träger (RT/DRT) - (4 Varianten, 3 Farben, Muffe, Längenabzug Anfang/Ende)
|
||||
- CSV Export aller Gerüst Komponenten
|
||||
+ Abhänger (3 Quetschung, 6 Abhängung oben, 4 Abhängung unten, 4 Befestiung oben, 3 Farben, Variable Länge) DONE (GERUEST_ROHRABHAENGER)
|
||||
+ T-Abhänger mit Flansch-Rohr (3 Spannpratze, 3 Farben, Variable Länge) DONE (Variante der Rohrabhaenger)
|
||||
+ Säulen (2 Arten, 3 Farben, 2 Einbauwinkel Platte, 5 Haltearm, 4 Einbauwinkel Arm, 8 Klemmring, Länge Bodensäule) DONE (GERUEST_SAEULEN)
|
||||
+ Wandbefestigung (4 Varianten, 3 Befestigungen) DONE (GERUEST_WANDBEFESTIGUNG)
|
||||
+ Träger (RT/DRT) - (4 Varianten, 3 Farben, Muffe, Längenabzug Anfang/Ende) DONE (GERUEST_TRAEGER inkl. Beschriftung)
|
||||
+ Gatterträger OFFEN (Menue-Platzhalter)
|
||||
- CSV Export aller Gerüst Komponenten DONE (`pattern_geruest = GR_*`)
|
||||
- TOS von Gerüst-Import ins Sivas
|
||||
|
||||
## Meilenstein 3: Ersatz von Bihler Omniflo
|
||||
- Omniflo Bögen (27) DONE
|
||||
- Omniflo Weichen (80) DONE
|
||||
- Omniflo Verbinder (18 Varianten)
|
||||
- Kettenförderer (3 Teile: Ein/Auslauf und Verbindung)
|
||||
- TEF Geraden aus Omniflo Geraden (Umwandlungsmakro)
|
||||
- CSV Export aller Omniflo Elemente
|
||||
- Omniflo Verbinder (18 Varianten) DONE (OMNI_TV_*)
|
||||
- Kettenförderer (3 Teile: Ein/Auslauf und Verbindung) DONE (KETTENFOERDERER / KF_EDIT)
|
||||
- TEF Geraden aus Omniflo Geraden (Umwandlungsmakro) TEILWEISE (TEF_FOERDERER_LINIE belegt eine Linie mit TEF-Geraden; Umwandlung bestehender Omniflo-Geraden fehlt)
|
||||
- Omniflo Fahrstrecke, Ladeschleifen, Schwenkschienen DONE
|
||||
- Bögen für Weichen (OMNI_APBW_*) OFFEN (Dummy, im Menue ausgegraut)
|
||||
- CSV Export aller Omniflo Elemente DONE
|
||||
|
||||
## Meilenstein 4: Flex
|
||||
- Erstellung der .dwg Dateien von Bögen, Geraden, Förderer
|
||||
@@ -46,7 +51,7 @@
|
||||
- Erzeugung eines Puffers aus einer Flächenangabe/Recheck
|
||||
- Positionierung von Separatoren und Scannern aus dem Streckenverlauf/Fördereranbindung
|
||||
- Makro zur Erzeugung eines Arbeitsplatzes (Varioförderer ab, 180 Grad Bogen, Varoförderer auf)
|
||||
- Varioförder als Etagenförderer (anderer ES und AS Elemente)
|
||||
- Varioförder als Etagenförderer (anderer ES und AS Elemente) DONE (VF-Typ Etage)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ Erweiterung (AutoLISP-Konvention: Alist statt echtem Struct):
|
||||
| `vfl-modus-abbruch-sichern` | vf_linienzug.lsp | 9 |
|
||||
| `vf-winkel-solve` | vf_core.lsp | 8 |
|
||||
| `vfs-mitte-teil`, `vfl-vf-einheit`, `vfl-vf-einheit-abschluss` | standard/linienzug | je 7 |
|
||||
| `vfs-vf-koerper`, `vfl-insert-es-element`, `vfl3-es-fueller` | standard/linienzug | je 5-6 |
|
||||
| `vfs-vf-koerper`, `vfl-insert-es-element`, `vfl-zsolve-es-fueller` | standard/linienzug | je 5-6 |
|
||||
| die vier `insert-hz-*`-Funktionen | vf_etage.lsp | je 4-6 |
|
||||
|
||||
## Struct-Kandidaten
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
# Offene TODOs
|
||||
|
||||
Zentrale Sammlung aller offenen Punkte. Wo ein eigener Fahrplan in `doc/todo/`
|
||||
existiert, steht hier nur die Kurzfassung mit Verweis. Erledigtes wird
|
||||
entfernt (Historie steht in git), nicht abgehakt stehen gelassen.
|
||||
|
||||
Stand: 2026-10-26. Wird woechentlich (freitags) mit der Doku geprueft, siehe
|
||||
`CLAUDE.md` -> Konventionen.
|
||||
|
||||
---
|
||||
|
||||
## 1. VarioFoerderer / Linienzug
|
||||
|
||||
- **Stufe 3 Winkelwahl: "Ab"-Zweig** (`vf_standard.lsp`, Kommentar bei der
|
||||
Fuellstueck-Berechnung): nur "Auf" implementiert, "Ab" bleibt bewusst offen,
|
||||
bis ein konkreter Bedarfsfall vorliegt. Ebenso `schon-flach` in Stufe 3.
|
||||
|
||||
## 2. Export / Sivas
|
||||
|
||||
- **Separator-/Scanner-Aufteilung GF/VF** in Streckengruppen: Merkmale
|
||||
4337/4339 (Gefaelle-Anteil) stehen fest auf `"0"`, 4381/4383 (Vario-Anteil)
|
||||
tragen den kompletten Blockwert. Haengt an einer Ueberarbeitung der
|
||||
Separator-/Scanner-Zuordnung im Zeichnungsmodell.
|
||||
-> `cfg/sivas_merkmal_zuordnung.md` ("Offener Punkt")
|
||||
- **TOS von Geruest-Import ins Sivas** (Entwicklungsplan Meilenstein 2).
|
||||
|
||||
## 3. Geruest
|
||||
|
||||
- **Gattertraeger**: nur Menue-Platzhalter auf `GERUEST` (zeigt einen Hinweis).
|
||||
Daten sollen spaeter in `data/json/geruest_traeger.json`.
|
||||
- **Edit-Pfad `GERUEST_EDIT`** fehlt: Doppelklick auf `GR_*` oeffnet nur
|
||||
`EATTEDIT`, kein Neuaufbau ueber den Dialog.
|
||||
|
||||
## 4. Omniflo
|
||||
|
||||
- **Boegen fuer Weichen `OMNI_APBW_*`** (14 Befehle): Dummy, im Menue
|
||||
ausgegraut.
|
||||
- **TEF-Geraden aus Omniflo-Geraden** (Umwandlungsmakro): bisher nur
|
||||
`TEF_FOERDERER_LINIE` (Linie mit TEF-Geraden belegen), keine Umwandlung
|
||||
bestehender Omniflo-Geraden.
|
||||
|
||||
## 5. ILS
|
||||
|
||||
- **ILS-Weichen als Geometrie**: Weichenpunkte werden ermittelt und exportiert
|
||||
(`KREISEL_WEICHEN`), eine eigene Weichen-Geometrie gibt es nicht.
|
||||
- **Horizontal-Variobogen / Gefaellebogen als eigenstaendige Befehle**: nur
|
||||
innerhalb der Streckengruppe (Vario-Kurve, GF-Bogen); die frueheren
|
||||
Dummy-Befehle `ILS_K*` sind entfernt.
|
||||
|
||||
## 6. Tests
|
||||
|
||||
- **`tests/test_vf_geometrie.py`** braucht BricsCAD-erzeugte DXF-Referenzdaten,
|
||||
die headless fehlen -> schlaegt ohne vorherigen CAD-Lauf fehl.
|
||||
- CAD-Laeufe `TEST_VF_SPEC` und `VF_SPEC_BAU` + `tests/test_vf_spec.py`
|
||||
gegen `tests/output/hundm05_results.json` (Beweis "Spec-Pfad ==
|
||||
Journal-Pfad" auf Geometrie-Ebene). -> `doc/todo/plan-vf-interactive.md`
|
||||
|
||||
## 7. Spaetere Meilensteine (Entwicklungsplan)
|
||||
|
||||
Nur Ueberschriften, Details in `doc/plan/Entwicklungsplan.md`:
|
||||
|
||||
- Meilenstein 4: Flex (DWGs, Produktprogramm, CSV-Export, TOS)
|
||||
- Meilenstein 5: 3D-Modelle (Omniflo Bogen/Weiche, Geruest-Modelle)
|
||||
- Meilenstein 6: Metafunktionen (Geruest ueber Bereich, Strecke aus Polylinie,
|
||||
Kreisel-Verbindung auf unterschiedlicher Hoehe, Puffer aus Flaeche,
|
||||
Separator-/Scanner-Positionierung, Arbeitsplatz-Makro)
|
||||
@@ -0,0 +1,124 @@
|
||||
# VF-Linienzug ohne GUI/Konsole - Stufe 2 (Funktionstrennung)
|
||||
|
||||
**Stand:** 2026-10-29 · **ZURUECKGESTELLT** - aus `doc/todo.md` entfernt, die
|
||||
Datei bleibt als Fahrplan liegen.
|
||||
|
||||
## Warum zurueckgestellt
|
||||
|
||||
Stufe 2 sollte den **Journal-Replay-Umweg** ueberfluessig machen: Bauteile
|
||||
direkt mit Daten aufrufen statt Fragen aus einer Queue beantworten zu lassen.
|
||||
Dieser Umweg ist aber keiner mehr. Ein Linienzug-Journal traegt mit `SEGS` die
|
||||
komplette Segment-Essenz und laesst sich OHNE Zeichnung abspielen - mit
|
||||
derselben Begruendung wurde am 2026-10-27 bereits der Spec-Uebersetzer fuer
|
||||
Modus 2/3 gestrichen (4a19ac0, `doc/todo/spec-modus2-3.md`). Die
|
||||
Modus-2-Regressionstests (`c:TEST_LINIENZUG_MODUS2`, seit 2026-10-29 fuenf
|
||||
Faelle) laufen headless ueber genau diesen Replay-Pfad: er ist nicht der
|
||||
Engpass, sondern die funktionierende Loesung.
|
||||
|
||||
Dazu kommt das Risiko. Die offenen Schritte 5c/6/8/9/10 fassen den Code an, in
|
||||
dem die REIHENFOLGE SELBST GEOMETRIE IST (siehe "Warum es heikel ist" unten) -
|
||||
und ein Teil dieser Fehler ist in der Zeichnung unsichtbar und faellt erst im
|
||||
Sivas-Export auf. Hoher Einsatz, kein Funktionsgewinn.
|
||||
|
||||
**Wieder aufnehmen, wenn** einer dieser Faelle eintritt:
|
||||
- einzelne Bauteile sollen ohne Journal aufrufbar sein (z.B. ein Generator,
|
||||
der Ketten aus Fremddaten baut und die Frage-Reihenfolge nicht kennen will);
|
||||
- der Replay-Pfad wird zu langsam oder zu fehleranfaellig;
|
||||
- `vfl-spec-ausfuehren` wird von irgendwo erwartet (heute: nirgends).
|
||||
|
||||
**Prioritaet beim Wiederaufnehmen:** niedrig - bringt Architektur, keine neue
|
||||
Funktion.
|
||||
|
||||
Herausgeloester Arbeitsauftrag aus dem Gesamtplan
|
||||
[plan-vf-interactive.md](plan-vf-interactive.md) (Teil 5 "Stufe 2: echte
|
||||
Funktionstrennung"). Dort stehen die ausfuehrliche Begruendung, die
|
||||
Knotenform und die Risikoliste; diese Datei ist die Abarbeitungsliste.
|
||||
|
||||
## Ausgangslage (Stufe 1, fertig)
|
||||
|
||||
Linienzug-Ketten lassen sich bereits ohne Dialog bauen (`VF_SPEC_BAU`,
|
||||
[vf_spec.lsp](../../Lisp/vf_spec.lsp)) - allerdings ueber einen Umweg:
|
||||
|
||||
1. Die **Spec** (Kette in Domaenenwerten) wird von `vsp-journal` in ein
|
||||
Eingabe-Journal uebersetzt - also in die Antworten, die ein Anwender
|
||||
gegeben haette.
|
||||
2. `vsp-bau-journal` startet per `vfl-journal-replay-start` den ganz normalen
|
||||
interaktiven Bau `vf-linienzug-modus` ([vf_linienzug.lsp](../../Lisp/vf_linienzug.lsp)).
|
||||
3. Jede Frage wird aus der Replay-Queue beantwortet.
|
||||
|
||||
Das funktioniert und ist per `TEST_HUNDM05` im CAD verifiziert - der Bau
|
||||
selbst "weiss" aber nichts von Daten, er fragt weiter, nur antwortet die Queue.
|
||||
|
||||
## Ziel (Stufe 2)
|
||||
|
||||
Die Funktionen in `vf_linienzug.lsp` mischen **Fragen** und **Geometrie
|
||||
bauen**. Stufe 2 trennt das:
|
||||
|
||||
- **reiner Bauteil** (Suffix `-bauen` bzw. `-setzen`): nimmt Parameter,
|
||||
baut Geometrie, fragt nichts;
|
||||
- die **Frage-Schale** behaelt den bisherigen Namen und ruft den Bauteil auf
|
||||
- dadurch aendert sich keine Aufrufstelle in Modus 1/2/3.
|
||||
|
||||
Am Ende ruft `vfl-spec-ausfuehren` die Bauteile direkt mit den Spec-Werten
|
||||
auf, ohne Journal-Replay.
|
||||
|
||||
## Stand der Schritte
|
||||
|
||||
Zeilennummern Stand 2026-10-26 (die `:NNNN`-Angaben im Gesamtplan sind
|
||||
veraltet).
|
||||
|
||||
| Schritt | Inhalt | Stand |
|
||||
|---|---|---|
|
||||
| 0 | `vfl-ziel-report` (vf_linienzug.lsp:7864) aus zwei identischen Bloecken gezogen | erledigt |
|
||||
| 1 | Winkelwahl `vfl-winkel-gueltige` (:3071) / `vfl-winkel-nach-index` + Kanal `*vfl-winkel-idx-vorgabe*` | erledigt |
|
||||
| 2 | `vfl-es-masse-setzen` (:7557) | erledigt |
|
||||
| 3 | `vfl-hor-koerper-bauen` (:5989), Schale `vfl-baue-horizontal-koerper` (:6152) | erledigt |
|
||||
| 4 | `vfl-body-abschluss-bauen` (:6502) | erledigt |
|
||||
| 5a/5b | VF-Einheit Eingang/Ausgang: `vfl-vf-eingang-bauen` (:6728), `vfl-vf-ausgang-bauen` (:6742) | erledigt |
|
||||
| **5c** | Schleifenrumpf von `vfl-vf-einheit` (:6772) - die Sub-Stuecke der VF-Einheit als Bauteil | **offen** |
|
||||
| **6** | Daten-Executor fuer die VF-Einheit (baut sie direkt aus Daten) | **offen** |
|
||||
| 7 | Spec + Serializer + Assertion: `vsp-journal-diff` (vf_spec.lsp:900) prueft Spec-Journal gegen das beim Bau aufgezeichnete Token fuer Token | Assertion erledigt |
|
||||
| **8** | Einheit-Abschluss: `vfl-vf-einheit-abschluss` (:7889) | **offen** |
|
||||
| **9** | Kettenebene, ein Glied-Zweig pro Commit: GF-Bogen -> ES -> Horizontal-VF -> Linie-GF -> Linie-VF -> Linie | **offen** |
|
||||
| **10** | `vfl-spec-ausfuehren` - der direkte Daten-Pfad (existiert noch nicht) | **offen** |
|
||||
| 11 | Dasselbe fuer Modus 2 | **Vorbedingung erfuellt 2026-10-27**: zwei echte Modus-2-Journale liegen als `tests/testdata/linienzug_modus2_{variokurve,gfbogen}.json` vor, abgespielt von `c:TEST_LINIENZUG_MODUS2`. Der Schritt selbst ist noch offen |
|
||||
|
||||
## Warum es heikel ist
|
||||
|
||||
Bei den offenen Schritten ist die **Reihenfolge selbst Geometrie**
|
||||
(Gesamtplan, Abschnitt "Wo Geometrie still kippen kann"), u.a.:
|
||||
|
||||
- die dL-Subtraktionskette ist je Schritt mit
|
||||
`(max *vfk-restlaenge-min-clamp* ...)` geklammert, also
|
||||
reihenfolgeabhaengig;
|
||||
- die `vfl-acc-*`-Aufrufe muessen an derselben Stelle in derselben
|
||||
Reihenfolge bleiben, sonst vertauschen sich `L_VF_m`/`L_GF_m`/`GF_WINKEL`
|
||||
- in der Zeichnung unsichtbar, im Sivas-Export falsch;
|
||||
- `*vfl-as-winkel*`/`*vfl-es-winkel*` werden lazy von den Blocknamen-Bauern
|
||||
gelesen - spaeter gesetzt heisst falscher Block;
|
||||
- `ziel-gf2` vs. `L_GF2-bau` im Ausgang - geht es verloren, entsteht still
|
||||
die falsche GF2 hinter dem Motor.
|
||||
|
||||
Ausdruecklich nicht anfassen: siehe Gesamtplan, Abschnitt "Ausdruecklich
|
||||
nicht anfassen" (u.a. alle Journal-Konsumenten, `vfl-in-*`-Wrapper,
|
||||
Wizard-Schicht, Abbruch-Pfad).
|
||||
|
||||
## Ablauf je Schritt
|
||||
|
||||
1. Umbauen (Frage-Schale behaelt Namen, Bauteil wortwoertlich umziehen,
|
||||
keine Umsortierung).
|
||||
2. CAD-Lauf: `TEST_HUNDM05` (save dxf), `TEST_VF_SPEC`, `TEST_LINIENZUG`.
|
||||
3. `pytest tests/test_vf_geometrie.py` gegen
|
||||
`tests/reference/hundm05_attribute.json` - nennt bei Abweichung Kette
|
||||
und Feld. Referenz nur nach geprueftem Lauf auffrischen
|
||||
(`lib/dxf_vf_abbild.py --schreibe-referenz`).
|
||||
4. Nach Geometrie-Schritten (5c, 9) zusaetzlich DXF-Diff und
|
||||
Sivas-Export-Vergleich.
|
||||
5. Ein Schritt pro Commit - sonst ist ein Fehler keinem Schritt mehr
|
||||
zuzuordnen.
|
||||
|
||||
## Wann angehen
|
||||
|
||||
Erst bei konkretem Bedarf: einzelne Bauteile ohne Journal aufrufen, oder der
|
||||
Replay-Umweg wird zu langsam bzw. zu fehleranfaellig. Bis dahin genuegt
|
||||
Stufe 1.
|
||||
@@ -1,7 +1,21 @@
|
||||
# TODO: Modus-2-Solver auf achsenweise Laengen-Bilanz umstellen
|
||||
# Modus-2-Solver: achsenweise Laengen-Bilanz
|
||||
|
||||
Status: **Vorschlag / noch nicht umgesetzt** (2026-09-18). Mit dem Entwickler zu
|
||||
besprechen, bevor der Solver angefasst wird. Reiner Plan - kein Code geaendert.
|
||||
Status: **ERLEDIGT 2026-10-29.** Gefaltete Laeufe (U-Form) werden gebaut; am
|
||||
selben Pfad gemessen 0.56 mm (9 Grad) und 0.7 mm (12 Grad) quer, beide
|
||||
Regressionsketten weiter OK. Der Abschnitt "Stand 2026-10-29" und der "Nachtrag
|
||||
2026-10-29" am Ende beschreiben Loesung und Herleitung.
|
||||
|
||||
Die Datei bleibt BEWUSST liegen, obwohl der Auftrag abgeschlossen ist: vier
|
||||
Kommentare in `Lisp/vf_linienzug.lsp` verweisen auf diesen Pfad (Suche nach
|
||||
`modus2-achsenweise-bilanz`). Sie dokumentiert damit nicht mehr einen Plan,
|
||||
sondern WARUM der Solver so bilanziert, wie er es tut - einschliesslich der
|
||||
fehlgeschlagenen Versuche, damit sie niemand ein zweites Mal unternimmt.
|
||||
|
||||
Alles unterhalb dieser Zeile ist der urspruengliche Plan von 2026-09-18 und
|
||||
seine Zwischenstaende. Die dort genannten Zeilennummern sind veraltet; Phase B
|
||||
von `vf-linienzug-modus2` findet man per Suche nach `climber-span`. Die damals
|
||||
vorgeschlagene Zwischenloesung (gefaltete Laeufe mit Meldung abweisen) wurde
|
||||
NICHT umgesetzt und ist gegenstandslos - solche Laeufe funktionieren jetzt.
|
||||
|
||||
## Kurzfassung
|
||||
|
||||
@@ -44,7 +58,7 @@ ganze Hoehe traegt, und rechnet die geneigte Laenge skalar:
|
||||
|
||||
```lisp
|
||||
;; vf_linienzug.lsp:9990 - Solver bekommt die SKALARE Spanne
|
||||
(setq wahl3 (vfl3-waehle-winkel climber-span dH-adj feste-vf))
|
||||
(setq wahl3 (vfl-zsolve-winkel-waehlen climber-span dH-adj feste-vf))
|
||||
;; feste-vf = Umlenk + Separator (+ Motor) -- ein fester Fussabdruck
|
||||
|
||||
;; vf_linienzug.lsp:10070 - Kletterer bekommt br-lvf proportional
|
||||
@@ -120,3 +134,260 @@ Gefaltete VF-Laeufe (mehr als eine Achsenrichtung im VF-Bereich, z.B. U-Form)
|
||||
erkennen und mit klarer Meldung abweisen, statt still falsche Geometrie zu
|
||||
bauen - analog zur bereits vorhandenen "nur EIN VF-Lauf"-Abweisung
|
||||
(`vfl-m3-vf-lauf-alert`). Macht das Limit ehrlich sichtbar, kleiner Eingriff.
|
||||
|
||||
---
|
||||
|
||||
## Stand 2026-10-27 (nach Commit ce4ad0f)
|
||||
|
||||
**Teilweise entschaerft, Kern bleibt offen.**
|
||||
|
||||
Die Budget-Arbeit vom 26./27.10. hat genau das Prinzip eingefuehrt, das
|
||||
dieses Dokument fordert - aber nur fuer DREI Posten. Sie werden jetzt dem
|
||||
Segment zugeschlagen, auf dem sie physisch stehen, statt skalar von der
|
||||
Gesamtspanne abgezogen zu werden:
|
||||
|
||||
| Posten | wie | Stelle |
|
||||
|---|---|---|
|
||||
| AS-Element | gemessener Fussabdruck, nur `vf-start` | `as-along-fix` |
|
||||
| Abschlussbogen + Motorstation | nur `vf-ende` | `abschluss-fp` |
|
||||
| Eck-Differenz (gezeichneter Bogen gegen Bauteil) | Alist je Segmentindex | `vfl-eck-korrekturen` / `vfl-eck-extra` |
|
||||
|
||||
`vfl-eck-extra` ist dabei bereits die hier geforderte Form: ein Zuschlag **je
|
||||
Segment**, nicht ein Skalar fuer den ganzen Lauf. Er fliesst in alle vier
|
||||
Budgets (Spannweite, Kletterer, Fueller, Rueckanker).
|
||||
|
||||
**Skalar geblieben sind genau die zwei Posten, die den U-Form-Fehler
|
||||
verursachen:**
|
||||
|
||||
- `feste-vf` (Umlenkstation 500 + Separator 300, ggf. + Motor) - wird in
|
||||
`vfl-zsolve-winkel-waehlen` als EIN Wert uebergeben
|
||||
- `gf-total` (GF1) - bei "alles am Einlauf" gross, und genau diese Summe
|
||||
fehlt dem Kletterer im anderen Schenkel
|
||||
|
||||
Das oben beschriebene Symptom (dY = +2645 mm) bleibt daher bestehen. Der
|
||||
naechste Schritt waere, diese beiden ebenfalls dem Segment zuzuordnen, auf
|
||||
dem sie stehen - also dieselbe Umstellung wie bei AS und Motorstation, nur
|
||||
fuer den Lauf-EINGANG.
|
||||
|
||||
Hinweis zur Fehlersuche: Seit ce4ad0f meldet die Konsole jeden Zuschlag
|
||||
namentlich (`AS-Fussabdruck ... von Segment N abgezogen`,
|
||||
`Abschluss-Fussabdruck ...`, `Eck-Korrektur ... auf Segment N`). Eine
|
||||
FEHLENDE Zeile ist das Warnsignal - so wurde ein 2,4-mm-Rest gefunden. Fuer
|
||||
die U-Form-Diagnose sind diese Zeilen der schnellste Einstieg.
|
||||
|
||||
---
|
||||
|
||||
## Stand 2026-10-28: Fueller-Seite geloest, Solver-Seite offen
|
||||
|
||||
### Geloest und gemessen
|
||||
|
||||
`vfl-m2-eingang-fp`: GF1 + Separator + Umlenkstation + Uebergangsbogen stehen
|
||||
auf dem Segment `vf-start`. Ist dieses Segment ein FUELLER (der Kletterer
|
||||
liegt hinter einer Kurve), bekam der Fueller bisher die volle Restlaenge, als
|
||||
staende dort nichts. Jetzt werden sie abgezogen.
|
||||
|
||||
Ist das Eingangs-Segment selbst der Kletterer - der gerade Normalfall -, gibt
|
||||
die Funktion hart 0.0 zurueck; der funktionierende Fall kann sich also nicht
|
||||
aendern. Gemessen am U-Form-Testfall: **Querabweichung 8005 -> 1424 mm**,
|
||||
Segment 1 danach auf 0,2 mm genau belegt.
|
||||
|
||||
### Noch offen: der Solver rechnet GF und Stationen gegen die falsche Achse
|
||||
|
||||
Rest 1424 mm. Segment 5 (Kletterer) legt 6475,5 mm zurueck, verfuegbar waeren
|
||||
7899,8 - der Solver reserviert dort Platz fuer Umlenkstation, Separator und
|
||||
den GF1-Anteil, die auf Segment 1 stehen.
|
||||
|
||||
### Fehlgeschlagene Versuche (nicht wiederholen)
|
||||
|
||||
Drei Anlaeufe am 2026-10-27/28, jeder an einer anderen Kopplung gescheitert:
|
||||
|
||||
1. **`feste-vf` kleiner uebergeben.** Geht nicht: `feste-hz` fliesst in
|
||||
`vf-winkel-AB` (vf_standard.lsp:241/245) sowohl als `feste*cos3` in die
|
||||
LAENGE als auch als `feste*sin3` in die HOEHE. Die Hoehe ist real - die
|
||||
Teile senken die Kette ab, egal auf welchem Schenkel sie stehen. Nur der
|
||||
Laengenanteil darf verschoben werden.
|
||||
2. **Spanne vorab korrigieren und iterieren.** Geht nicht direkt:
|
||||
`vfl-zsolve-winkel-waehlen` enthaelt die WINKELFRAGE an den Nutzer - eine
|
||||
Iteration wuerde mehrfach fragen. Und die Korrektur ist pro Winkel
|
||||
verschieden, weil jeder Winkel ein anderes `L_GF` ergibt.
|
||||
3. **Stiller Nachrechner nach der GF-Verteilungsfrage** (Code vorhanden, per
|
||||
`(setq nachrechnen-k 4)` deaktiviert). Technisch sauber: kein Dialog,
|
||||
Fragenfolge und Journal unveraendert, Konvergenz in 4 Runden
|
||||
(3278 -> 4372 -> 4737 -> 4859 -> 4899 mm). ABER er kollidiert mit
|
||||
**`filler-A-len`**: dieser Fueller belegt im Kletter-Segment genau den
|
||||
Platz, den das halbe GF1 dort frei laesst. Nimmt man GF1 aus der
|
||||
Kletterer-Spanne heraus, wird Fueller-A trotzdem gebaut - zusaetzlich zum
|
||||
echten GF1 auf demselben Segment. Gemessen: Fueller nach der
|
||||
Umlenkstation -369 mm (auf 100 geklemmt), Kette 746 mm daneben.
|
||||
Kleinerer Endfehler, aber entartete Geometrie - deshalb zurueckgenommen.
|
||||
|
||||
### Daraus fuer den naechsten Anlauf
|
||||
|
||||
Der Nachrechner ist vermutlich der richtige Weg, aber **`filler-A-len` muss
|
||||
mitbehandelt werden**: er gehoert zur Annahme "GF1 liegt im Kletter-Segment"
|
||||
und darf bei gefaltetem Lauf nicht mehr entstehen. Wer das angeht, sollte
|
||||
beide Mechanismen zusammen betrachten, nicht nacheinander.
|
||||
|
||||
Testfall vorhanden: U-Form 5855 / 270 / 7806 mm (Kletterer hinter zwei
|
||||
90-Grad-Kurven), Soll-Querabweichung ~0, Stand heute 1424 mm. Die beiden
|
||||
geraden Referenzketten in `c:TEST_LINIENZUG_MODUS2` schuetzen den Normalfall.
|
||||
|
||||
---
|
||||
|
||||
## Stand 2026-10-29: Eingangs-Segment exakt, Kletterer-Segment offen
|
||||
|
||||
### Zusaetzlich geloest (gegenueber dem Stand vom 2026-10-28)
|
||||
|
||||
**Fueller-A entfaellt bei gefaltetem Lauf**, und `vfl-m2-eingang-fp` zieht
|
||||
seitdem `br-gf1` ab statt `gf-total`. Beides gehoert zusammen:
|
||||
|
||||
`filler-A-len` fuellt den Platz, den ein halbiertes GF1 auf DERSELBEN Achse
|
||||
frei laesst - er gehoert zur Annahme "GF1 und GF2 liegen auf einer Geraden".
|
||||
Bei gefaltetem Lauf wurde er auf dem Eingangs-Segment ZUSAETZLICH zu GF1
|
||||
gebaut; zusammen mit GF2 im Kletterer-Schenkel entstanden damit 1.5 x
|
||||
gf-total Gefaellestrecke bei einem Budget von gf-total.
|
||||
|
||||
Ergebnis, am U-Form-Testfall nachgerechnet (9 Grad, Verteilung 1/2+1/2):
|
||||
|
||||
```
|
||||
Segment 1: AS 425,8 + GF1 1370,3 + Sep 299,6 + Umlenk 499,3
|
||||
+ Bogen 199,9 + Fueller 3153,7 = 5948,6 mm
|
||||
Budget: 5855 + 93,8 (Eck-Korrektur) = 5948,8 mm
|
||||
```
|
||||
|
||||
Das Eingangs-Segment ist damit **auf 0,2 mm exakt belegt**, und im Protokoll
|
||||
steht nur noch EIN Fueller statt zwei.
|
||||
|
||||
### Was offen bleibt
|
||||
|
||||
Das KLETTERER-Segment. Gemessen im selben Lauf: Segment 5 belegt 6965,8 mm,
|
||||
verfuegbar waeren 7899,8 - es fehlen **934 mm**, exakt die Endabweichung.
|
||||
|
||||
Der Solver bekommt als Spanne 7704,16 mm und verplant darin u.a. GF1
|
||||
(1370,3) sowie Umlenkstation + Separator (798,9) - Teile, die auf Segment 1
|
||||
stehen. Umgekehrt enthaelt seine Spanne NICHT den Abschluss-Fussabdruck
|
||||
(ab_3 + Motorstation, 695 mm), weil dieser nur von FUELLER-Segmenten
|
||||
abgezogen wird (`fill-len`) und das Kletterer-Segment keines ist.
|
||||
|
||||
**Der Restfehler skaliert mit `L_GF`** und damit mit dem gewaehlten Winkel -
|
||||
unabhaengig bestaetigt durch zwei Laeufe auf demselben Pfad:
|
||||
|
||||
| Winkel | L_GF | Querabweichung |
|
||||
|---|---|---|
|
||||
| 6 Grad | 1093 | 90 mm |
|
||||
| 9 Grad | 2744 | 934 mm |
|
||||
|
||||
Praktische Folge: Mit flachem Winkel ist der gefaltete Lauf heute brauchbar,
|
||||
mit steilem nicht.
|
||||
|
||||
### Hinweis zur Methodik fuer den naechsten Anlauf
|
||||
|
||||
Zwei Laeufe sind nur vergleichbar, wenn **Winkel UND GF-Verteilung gleich**
|
||||
sind. Mehrere Messreihen dieser Sitzung waren nicht deutbar, weil sich
|
||||
zwischendurch der Winkel geaendert hatte und der Restfehler mit `L_GF`
|
||||
skaliert. Vor einer Aenderung also eine feste Kombination festlegen
|
||||
(Vorschlag: 12 Grad, Verteilung 1/2+1/2) und nur die vergleichen.
|
||||
|
||||
---
|
||||
|
||||
## Nachtrag 2026-10-29: Loesungsansatz vom Nutzer
|
||||
|
||||
Der Abschnitt darueber beschreibt den Stand VOR dem folgenden Umbau; er bleibt
|
||||
als Herleitung stehen.
|
||||
|
||||
Nutzer-Vorgabe: *"nach der zweiten VF-Kurve den passenden Winkel neu aus dem
|
||||
KS_AUS der Kurve und dem Zielpunkt rechnen"* und *"da GF2 feststeht, steht auch
|
||||
die fuer Auf/Ab verbleibende Laenge fest - passender Winkel plus eine
|
||||
ausgleichende GF"*.
|
||||
|
||||
Das ist die Umkehrung der bisherigen Logik und trifft den Kern: bisher wurde
|
||||
ALLES vorab global verplant und der aufgelaufene Fehler landete am Kettenende.
|
||||
Richtig ist, die letzten freien Groessen aus der GEMESSENEN Ist-Lage zu
|
||||
bestimmen. Je nachdem, was das letzte Segment ist, sind das verschiedene
|
||||
Groessen:
|
||||
|
||||
| Letztes Segment | feste Groesse | freie Groessen |
|
||||
|---|---|---|
|
||||
| flacher Fueller | - | Richtung + Fuellerlaenge |
|
||||
| Auf/Ab-Koerper (U-Form) | Laenge (aus dem Pfad) | Winkel (diskret) + GF-Ausgleich |
|
||||
|
||||
### Umgesetzt
|
||||
|
||||
**1. Flacher Fueller als Schlussstueck** - neue Funktion
|
||||
`vfl-zsolve-schluss-ziel`. Bisher loeste `vfl-zsolve-es-fueller` nur die LAENGE
|
||||
und uebernahm die Richtung aus dem gezeichneten Pfad. Eine Laenge verschiebt die
|
||||
Kette aber nur ENTLANG ihrer Achse - steht der reale Kurvenausgang seitlich
|
||||
NEBEN der gezeichneten Geraden, laeuft die gebaute Achse parallel zur Zielachse
|
||||
und der Querversatz ist unerreichbar. Gibt man die Richtung mit frei, stehen
|
||||
zwei Unbekannte zwei Gleichungen (X und Y) gegenueber, geschlossen loesbar:
|
||||
|
||||
```
|
||||
D = Ziel - KS_AUS(letzte Kurve)
|
||||
A = sqrt(|D|^2 - P^2) ; P = Querversatz des ES-Fussabdrucks
|
||||
fill = A - C
|
||||
hz = Winkel(D) - atan2(P, A)
|
||||
```
|
||||
|
||||
`C` und `P` sind von `hz` unabhaengig, weil `vfl-zsolve-es-vektor` Vektor und
|
||||
Bezugsrahmen um denselben Winkel dreht - deshalb ist keine Iteration noetig.
|
||||
Scheitert der Solve (Ziel naeher als `P`), bleibt der bisherige Weg. Unit-Tests:
|
||||
`tu-tests-vfl-schluss` (file-frei ueber `es-block = nil`).
|
||||
|
||||
**2. Eingangs-Hardware bei gefaltetem Lauf** - der am 2026-10-28 zurueck-
|
||||
genommene Spannen-Zuschlag ist wieder da. Begruendung fuer die Ruecknahme war
|
||||
die Kollision mit `filler-A-len`; dieser Blocker ist entfallen, seit Fueller-A
|
||||
bei gefaltetem Lauf gar nicht mehr entsteht. Zugeschlagen wird weiterhin NUR
|
||||
der Laengenanteil (`entry-fixed * cos3`), nie `feste-vf` selbst - dessen
|
||||
`sin3`-Hoehenanteil ist real.
|
||||
|
||||
**3. Abschluss-Hardware auf dem Kletterer** (`kletter-ende-fp`) - endet der Lauf
|
||||
auf einem FUELLER, zieht `vfl-zsolve-es-fueller` Motorstation + Separator + ES
|
||||
beim Loesen der Fuellerlaenge selbst ab. Endet er auf einem KLETTERER, gibt es
|
||||
diesen Fueller nicht: die drei Teile werden dort gebaut, standen aber in keinem
|
||||
Budget. Abgezogen wird dasselbe wie in dessen Konstante `cc`, OHNE den
|
||||
ab_3-Bogen (der steckt in diesem Fall schon in `uebergang-fp`).
|
||||
|
||||
**4. GF1-Fremdanteil** (Nachrechner wieder aktiv, 8 statt 4 Runden) - `gf-total`
|
||||
ist ein ERGEBNIS des Winkel-Solves, sein auf dem Eingangs-Schenkel stehender
|
||||
Teil laesst sich dort noch nicht abziehen (Henne-Ei). Der Nachrechner loest bei
|
||||
UNVERAENDERTEM Winkel neu und konvergiert mit Faktor ~1/3.
|
||||
|
||||
### Der entscheidende Punkt: 3 und 4 wirken nur GEMEINSAM
|
||||
|
||||
| Posten | im Budget des Solvers | steht real auf dem Kletterer |
|
||||
|---|---|---|
|
||||
| GF1 | ja | nein - liegt im Eingangs-Schenkel |
|
||||
| Motor + Separator + ES | nein | ja |
|
||||
|
||||
Die beiden Betraege heben sich TEILWEISE auf. Wer nur einen davon korrigiert,
|
||||
verschiebt den Fehler bloss in die andere Richtung - genau das war der
|
||||
746-mm-Befund vom 2026-10-28, der damals wie eine Verschlechterung aussah.
|
||||
Gemessen am 9-Grad-Lauf: GF1 1636.9 - (Motor+Sep+ES) 1235.1 = 401.8 mm, exakt
|
||||
die damalige Restabweichung von 401.7 mm.
|
||||
|
||||
### Messergebnis
|
||||
|
||||
| Lauf | vorher | nachher |
|
||||
|---|---|---|
|
||||
| U-Form 9 Grad | 1424 -> 934 mm | **0.56 mm** |
|
||||
| U-Form 12 Grad | - | **0.7 mm** |
|
||||
| Variante A (Vario-Kurve) | OK | OK |
|
||||
| Variante B (GF-Bogen) | OK | OK |
|
||||
|
||||
Zwei verschiedene Winkel auf demselben Pfad - der Restfehler skaliert also
|
||||
nicht mehr mit `L_GF`, die Bilanz selbst stimmt.
|
||||
|
||||
### Regression auf dem Weg dorthin (Lehrstueck)
|
||||
|
||||
`kletter-ende-fp` schlug zunaechst auch in Variante B zu und verkuerzte deren
|
||||
Segment 1 um 798.9 mm. Dort ist `vf-start = vf-ende = 0`: der VF-Lauf besteht
|
||||
aus EINEM Segment, die Segmente 2..5 sind Back-Lauf. Damit ist der Kletterer
|
||||
zugleich Laufende, der Abzug griff - obwohl ohne flache Zone die Motorstation
|
||||
bereits in `feste-vf` steckt und Separator + ES vom Back-Lauf reserviert werden.
|
||||
Die drei Bedingungen am `if` (`hor-pairs > 0`, `vf-ende = n-1`, `es-vorhanden`)
|
||||
sind deshalb keine Vorsichtsmassnahme, sondern benennen genau die Faelle, in
|
||||
denen sonst doppelt gebucht wird.
|
||||
|
||||
Auffindbar war die Ursache nur, weil Segment 1 von Variante B bei `hz=0` liegt:
|
||||
eine Verkuerzung dieses Segments uebersetzt sich 1:1 in `dX`, und `IST - SOLL =
|
||||
(-799.11 | -104.68)` aus `logs/vfl_modus2.dbg` zeigte die reine X-Verschiebung.
|
||||
@@ -5,6 +5,14 @@
|
||||
verifiziert, `TEST_HUNDM05` aktiv in `tests/alltests.json`; Stufe 2
|
||||
Schritte 0-4 + 7-Assertion fertig, 5/6/8/9/10 offen, 11 zurueckgestellt.
|
||||
**Herkunft:** Planungslauf (Plan-Modus) vom 2026-09-02, hier eingecheckt zur Nachverfolgung.
|
||||
**Pruefung 2026-10-26:** Stand unveraendert - Stufe 2 Schritte 5c/6/8/9/10
|
||||
(u.a. `vfl-spec-ausfuehren`) und die Spec-Uebersetzer fuer Modus 2/3 sind
|
||||
weiterhin nicht gebaut. Die Spec-Uebersetzer fuer Modus 2/3 (auf
|
||||
`SEGS`-Basis, Abschnitt 4.4 ersetzt) sind ausgelagert nach
|
||||
[spec-modus2-3.md](spec-modus2-3.md).
|
||||
**Abarbeitungsliste Stufe 2:** herausgeloest nach
|
||||
[linienzug-ohne-gui.md](linienzug-ohne-gui.md) (aktuelle Zeilennummern,
|
||||
Ablauf je Schritt); Teil 5 hier bleibt die ausfuehrliche Referenz.
|
||||
|
||||
## Fortschritt
|
||||
|
||||
@@ -88,9 +96,9 @@ Doppelklick-Edit, `SSG_DIM_SWITCH`) ist unveraendert. Das `"disabled": true`
|
||||
der hundm05-Zeile in `tests/alltests.json` ist weg, der Test laeuft aktiv
|
||||
mit.
|
||||
|
||||
**Bewusst nicht umgestellt**: `vfl-konvertiere-ent` (Batch-2D/3D) laeuft
|
||||
weiter ohne `*vfl-headless*` - eine Live-Rueckfrage ist dort bisher gewolltes
|
||||
Verhalten. Kandidat fuer Stufe 1, wenn der Ergebnis-Record steht.
|
||||
**Nachtrag 2026-10-26**: `vfl-konvertiere-ent` (Batch-2D/3D) laeuft jetzt
|
||||
ebenfalls unter `*vfl-headless*`; der alte Block wird erst nach erfolgreichem
|
||||
Neubau geloescht (Details `doc/variofoerderer.md`, Abschnitt Headless).
|
||||
|
||||
## Kontext
|
||||
|
||||
@@ -149,8 +157,11 @@ Modus-uebergreifende Blocker:
|
||||
- **`ATTREQ`/`ATTDIA`**: ohne `0` fragt das `(command "_.INSERT" ...)` in den
|
||||
Einfuegeprimitiven nach Attributwerten - der wahrscheinlichste Haenger.
|
||||
|
||||
Namensfalle: die `vfl3-*`-Helfer (:5093-5276) gehoeren zu **Modus 2**, die
|
||||
`vfl2-*`-Helfer (:4703-4804) zu **Modus 3**.
|
||||
Namensschema (seit 2026-10-22 rollenbasiert statt nach Modus-Nummer, die
|
||||
frueheren Praefixe `vfl3-`/`vfl2-` waren zur Menue-Nummerierung vertauscht):
|
||||
die `vfl-zsolve-*`-Helfer rechnen die Hoehen durch und gehoeren zu **Modus 2**;
|
||||
die `vfl-pfad-*`-Helfer arbeiten auf dem gezeichneten Pfad und werden von
|
||||
**Modus 2 UND Modus 3** genutzt.
|
||||
|
||||
---
|
||||
|
||||
@@ -339,6 +350,11 @@ gesammelten Meldungen aus P1.
|
||||
|
||||
### 4.4 Modus 2 und Modus 3
|
||||
|
||||
> **Ueberholt (2026-10-26):** Modus 2/3 journalisieren seit 2026-09-18
|
||||
> `SEGS` statt `OBJS`, Modus 3 hat Journal + Doppelklick-Edit. Aktueller
|
||||
> Entwurf und Schritte: [spec-modus2-3.md](spec-modus2-3.md). Der folgende
|
||||
> Text bleibt nur als Historie.
|
||||
|
||||
Modus 2: Spec traegt `("pfad-handles" ...)` (Entity-Handles der LINE/ARC-Trasse)
|
||||
plus `("segmente" ...)` in Pfadreihenfolge. Vor dem Bau wird die Segmentzahl
|
||||
gegen die aufgeloesten Handles geprueft und bei Fehlbestand abgebrochen - die
|
||||
@@ -695,7 +711,7 @@ Architektur, nicht Funktion.
|
||||
|
||||
### Ausdruecklich nicht anfassen
|
||||
|
||||
`vf-linienzug-modus3` + alle `vfl2-*`; die `vfl-in-*`-Wrapper und `vfl-menu*`;
|
||||
`vf-linienzug-modus3` + alle `vfl-pfad-*`; die `vfl-in-*`-Wrapper und `vfl-menu*`;
|
||||
`vfl-entry->string` und das XDATA-Layout/die Marker; **alle Journal-Konsumenten**
|
||||
(brauchen sie Aenderungen, ist die Invariante gebrochen - das ist der
|
||||
Lackmustest); die reinen `vfs-*`/`berechne-*` in `vf_standard.lsp` (via
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
# TODO: Spec-Uebersetzer fuer VF-Linienzug Modus 2 und 3
|
||||
|
||||
> **Stand 2026-10-27: Auftrag weitgehend erledigt bzw. bewusst gestrichen.**
|
||||
> Siehe Abschnitt "Entscheidung 2026-10-27" am Ende. Der Text darunter ist
|
||||
> die urspruengliche Planung und bleibt als Begruendung stehen - er
|
||||
> beschreibt NICHT mehr den offenen Stand.
|
||||
|
||||
**Stand:** 2026-10-26 · **Prioritaet:** mittel - einzige fehlende
|
||||
FUNKTION im Daten-Pfad (Modus-2/3-Ketten sind nur interaktiv baubar).
|
||||
|
||||
Herausgeloester Rest von Stufe 1 aus [plan-vf-interactive.md](plan-vf-interactive.md)
|
||||
(dort Abschnitt 4.4, der hiermit ersetzt ist). Schwester-Auftrag:
|
||||
[linienzug-ohne-gui.md](linienzug-ohne-gui.md) (Stufe 2).
|
||||
|
||||
## Ausgangslage
|
||||
|
||||
Der Daten-Pfad `VF_SPEC_BAU` ([vf_spec.lsp](../../Lisp/vf_spec.lsp)) kann nur
|
||||
Modus 1:
|
||||
|
||||
- `vsp-journal` (vf_spec.lsp:568) kennt nur den Fragenfluss/die Menue-Codes
|
||||
von `vf-linienzug-modus` (z.B. `*vsp-tab-gf-laenge-modus*`, :56).
|
||||
- `vsp-bau-journal` (:939) ruft fest `vf-linienzug-modus` auf (:978).
|
||||
|
||||
Modus 2 (`vf-linienzug-modus2`, Pfad + Zielhoehe, Marker `"linienzug2"`) und
|
||||
Modus 3 (`vf-linienzug-modus3`, Vorwaerts-Nachbau, Marker `"linienzug3"`)
|
||||
fragen grundlegend anders: erst Pfad-Auswahl (`vfl-in-segmente`), dann je
|
||||
Segment ein Klassifizierungs-Dialog (`vflw_seg_linie_m2`/`_m3`,
|
||||
`vflw_seg_bogen`). Dafuer gibt es weder Uebersetzer noch Bau-Aufruf.
|
||||
|
||||
Doppelklick-Edit/Neuaufbau funktioniert fuer beide Modi bereits
|
||||
(`vfl-edit-ent-voll`) - es fehlt nur der Bau aus einer Spec-Datei.
|
||||
|
||||
## Korrektur des alten Entwurfs (Plan 4.4, Stand 2026-09-02)
|
||||
|
||||
| alter Entwurf | heute (seit 2026-09-18) |
|
||||
|---|---|
|
||||
| Modus-2-Spec traegt `pfad-handles` (Entity-Handles, Journal-Art `OBJS`), vor dem Bau gegen die reale Zeichnung geprueft | Modus 2 UND 3 journalisieren die **Segment-Essenz** als Journal-Art `SEGS`: je Segment 9 Felder `typ hz laenge bwinkel bseite spx spy epx epy` (`vfl-segs->string`/`vfl-string->segs`, vf_linienzug.lsp). Die Kette ist selbst-enthalten, die Original-LINE/ARC werden nicht mehr gebraucht |
|
||||
| Modus 3 ohne Journal-XDATA, kein Doppelklick-Edit, keine 2D/3D-Konvertierung; Nachruestung zurueckgestellt | Modus 3 schreibt Marker `"linienzug3"` und ist per Doppelklick editierbar |
|
||||
| "Eine Gerade direkt nach einer Vario-Kurve wird nicht gefragt - der Uebersetzer leitet das ab" | gilt vermutlich weiter, am echten Journal pruefen |
|
||||
|
||||
Folge fuer den Entwurf: Die Spec fuer Modus 2/3 traegt eine **Segmentliste**
|
||||
statt Objekt-Handles plus die Klassifizierung je Segment (Typ, GF-Neigung
|
||||
bzw. Wert, Bogen-Variante) und die Praeambel (Startpunkt, Starthoehe,
|
||||
AS/ES). Sie ist damit wie Modus 1 **ohne Zeichnung** pruefbar.
|
||||
|
||||
## Schritte
|
||||
|
||||
Die Stand-Spalte ist auf 2026-10-29 nachgezogen (sie fuehrte bis dahin
|
||||
faelschlich noch alle sieben Schritte als offen, obwohl der Kopf dieser Datei
|
||||
das Gegenteil sagt).
|
||||
|
||||
| Schritt | Inhalt | Stand |
|
||||
|---|---|---|
|
||||
| 1 | Referenz-Journale erzeugen: in BricsCAD 2-3 typische Ketten je Modus (2 und 3) bauen, Zeichnung unter `tests/testdata/` ablegen. Abdecken: GF- und VF-Segmente, Bogen, AS/ES ja/nein, bei Modus 3 altes und neues AS/ES-Format | **fuer Modus 2 erledigt** (5 Ketten, `tests/testdata/linienzug_modus2_*.json`, abgespielt von `c:TEST_LINIENZUG_MODUS2`). Fuer Modus 3 auf Nutzer-Entscheidung 2026-10-29 **gestrichen** |
|
||||
| 2 | Python-Lesepfad: `lib/vf_journal_export.py` (+ `vf_linienzug_grammatik.py`) lernen `linienzug2`/`linienzug3` mit `SEGS` (heute: "unbekannter Code") | **erledigt** (4a19ac0, Marker-Trennung + Rohtokens) |
|
||||
| 3 | Spec-Form fuer Modus 2/3 festlegen (flaches JSON, lesbar von `ssg-load-json`, Segmente als Einzeiler) | **gestrichen** - siehe Entscheidung |
|
||||
| 4 | Python-Rundlauf `spec_aus_journal`/`journal_aus_spec` fuer Modus 2/3 in `lib/vf_spec_export.py`, Test in `tests/test_vf_spec.py`: Journal -> Spec -> Journal tokengleich | **gestrichen** |
|
||||
| 5 | LISP: `vsp-journal` je Modus (Dispatch ueber Spec-Feld `modus`), `vsp-pruefen` um Modus-2/3-Regeln erweitern | **gestrichen** |
|
||||
| 6 | `vsp-bau-journal`: Bau-Funktion nach Modus waehlen (`vf-linienzug-modus2`/`-modus3`), Ergebnis-Record wie Modus 1 (`prompts` = 0, `journal_diff` leer) | **erledigt** (4a19ac0, Dispatch aus dem Journal statt per Spec-Feld) |
|
||||
| 7 | CAD-Test analog `TEST_HUNDM05` + Eintrag in `tests/alltests.json`; file-freie Teile als `tu-*` in `tests/test_unit.lsp` | **als Journal-Replay erledigt** fuer Modus 2 (`c:TEST_LINIENZUG_MODUS2`), fuer Modus 3 gestrichen |
|
||||
|
||||
## Hinweise
|
||||
|
||||
- Korrektheitskriterium Modus 3 ist "gleiches rein, gleiches raus", NICHT
|
||||
"trifft den Zielpunkt" - der Ist/Soll-Ende-Report weicht schon im
|
||||
interaktiven Bau ab.
|
||||
- Alte `"linienzug2"`-Bloecke mit `OBJS`-Journal (vor 2026-09-18) sind
|
||||
nicht mehr editierbar und taugen NICHT als Referenz.
|
||||
- Neue `vfl-in-*`-Wrapper mit `ssget`/`get*` im statischen Waechter
|
||||
`tests/test_vf_headless_statisch.py` eintragen.
|
||||
- Werte selbstbeschreibend in der Spec (Winkel 30/60/90, nicht Index) -
|
||||
siehe CLAUDE.md, Konventionen.
|
||||
|
||||
---
|
||||
|
||||
## Entscheidung 2026-10-27 (nach Commit 4a19ac0)
|
||||
|
||||
**Die Spec fuer Modus 2/3 wird NICHT gebaut.** Der Grund ist erst durch den
|
||||
Modus-2-Regressionstest (cf626d7) sichtbar geworden:
|
||||
|
||||
Modus-2/3-Journale tragen mit `SEGS` die komplette Segment-Essenz und sind
|
||||
damit **ohne Zeichnung abspielbar** - `vfl-journal-replay-start` +
|
||||
`vf-linienzug-modus2` genuegt, wie `c:TEST_LINIENZUG_MODUS2` zeigt. Der
|
||||
Hauptnutzen einer Spec (Domaenenwerte statt Menue-Codes) faellt damit
|
||||
weitgehend weg: `SEGS` ist bereits Geometrie im Klartext, kein Menue-Code.
|
||||
|
||||
Fuer Modus 1 bleibt die Spec sinnvoll - dessen Journal besteht aus
|
||||
Menue-Ziffern ("5" = "Neue Linie BIS Kettenende"), die ohne Uebersetzung
|
||||
unlesbar sind.
|
||||
|
||||
### Umgesetzt (die lohnenden Teile)
|
||||
|
||||
| Schritt | Stand |
|
||||
|---|---|
|
||||
| 1 Referenz-Journale | **erledigt** - `tests/testdata/linienzug_modus2_{variokurve,gfbogen}.json`, aus einem echten Lauf |
|
||||
| 2 Python liest `linienzug2`/`3` | **erledigt** - `vf_journal_export.py` trennt nach Marker, Modus 2/3 als Rohtokens. Vorher lief die Modus-1-Grammatik auch darueber und brach ab |
|
||||
| 6 Bau-Funktion nach Modus | **erledigt** - `vsp-bau-fn-fuer-journal` leitet sie aus dem Journal ab (kein SEGS = 1, SEGS + Marke `m2v2` = 2, SEGS ohne = 3) |
|
||||
| 7 CAD-Test | **erledigt als Journal-Replay** statt als Spec-Test: `c:TEST_LINIENZUG_MODUS2`, zwei Varianten derselben Strecke |
|
||||
|
||||
### Gestrichen
|
||||
|
||||
Schritte 3, 4 und 5 (Spec-Form, Python-Rundlauf, `vsp-journal` je Modus).
|
||||
Sie lohnen erst, wenn jemand Modus-2/3-Ketten aus EXTERNEN Daten *erzeugen*
|
||||
will - heute tut das niemand. Selbst `dxf_anlage_export.py` schreibt fuer
|
||||
Modus-1-Linienzuege das Journal unveraendert durch (`"typ":
|
||||
"linienzug_journal"`) statt eine Spec zu bauen.
|
||||
|
||||
### Stattdessen: das eigentliche Risiko direkt entschaerft
|
||||
|
||||
Die Spec haette *eine* echte Schwachstelle abgedeckt - positionsabhaengige
|
||||
Menue-Ziffern im Journal. Das ist stattdessen an der Quelle geloest: die
|
||||
Segment-Antworten sind jetzt selbstbeschreibende Werte (`gf`/`vf`,
|
||||
`gf-bogen`/`vario-kurve`, `aussen`/`innen`, gemeinsamer Normalisierer
|
||||
`vfl-wert-norm`). Ein Umsortieren der Optionen deutet damit keine
|
||||
gespeicherte Kette mehr um - genau das war beim Lauf-Anfang (833a4b6) real
|
||||
passiert. Bruchteil des Aufwands, gleicher Schutz.
|
||||
|
||||
### Modus 3: abgeschlossen mit bewusst bleibendem Risiko (2026-10-29)
|
||||
|
||||
**Dasselbe fuer Modus 3** - dessen Segment-Klassifizierung benutzt weiterhin
|
||||
Menue-Ziffern ("1".."4", roh verglichen und genauso ins Journal geschrieben).
|
||||
Nicht mit umgestellt wurde sie, weil fuer Modus 3 kein aufgezeichnetes Journal
|
||||
und damit kein Sicherheitsnetz existiert - bei Modus 2 haben die
|
||||
Referenzketten bewiesen, dass Bestandsketten die Umstellung unveraendert
|
||||
ueberstehen (sie tragen bis heute die alten Ziffern).
|
||||
|
||||
**Nutzer-Entscheidung 2026-10-29:** fuer Modus 3 wird VORERST kein Testfall
|
||||
angelegt - *"bei Problemen im Einsatz testen wir und korrigieren dann"*. Die
|
||||
Umstellung auf selbstbeschreibende Werte unterbleibt damit bis auf Weiteres,
|
||||
und der Punkt ist aus `doc/todo.md` entfernt: er wartet nicht auf Arbeit,
|
||||
sondern auf einen Anlass.
|
||||
|
||||
Praktisch heisst das: Taucht in Modus 3 ein Fehler auf, der nach einer Kette
|
||||
aus der Zeichnung heraus untersucht werden muss, ist der erste Schritt
|
||||
`lib/vf_journal_export.py` auf diese Zeichnung - damit liegt genau das
|
||||
Journal vor, das hier als Sicherheitsnetz fehlt, und die Umstellung waere
|
||||
dann derselbe Handgriff wie bei Modus 2.
|
||||
|
||||
Das Risiko bleibt aber bestehen und wandert dorthin, wo es gefaehrlich wird:
|
||||
als Warnblock direkt ueber der Segment-Auswahl in `vf_linienzug.lsp`
|
||||
(Suche nach "ACHTUNG beim Aendern der folgenden Auswahllisten"). Wer die
|
||||
Modus-3-Optionen umsortiert, ergaenzt oder entfernt, deutet damit jedes
|
||||
gespeicherte `linienzug3`-Journal still um. Eine TODO-Zeile haette diesen
|
||||
Leser nicht erreicht, ein Kommentar an der Aenderungsstelle schon.
|
||||
+30
-10
@@ -387,7 +387,7 @@ arbeiten auf bereits in der Zeichnung vorhandener Geometrie statt auf freier
|
||||
Klick-Eingabe — fuer eine GUI eher Import/Solver-Werkzeuge als klassische
|
||||
Formulare.
|
||||
|
||||
### Modus 2 — Pfad + Zielhoehe (Solver)
|
||||
### Modus 2 — aus 3D Linie MIT Zielhoehe (Solver)
|
||||
|
||||
| Feld | Steuerelement | Werte |
|
||||
|---|---|---|
|
||||
@@ -400,15 +400,28 @@ Formulare.
|
||||
| -> Vario-Kurve-Variante | Dropdown | Aussen / Innen |
|
||||
| GF-Verteilung | Dropdown | alles am Einlauf (GF1) / 1/2 GF1 + 1/2 GF2 |
|
||||
|
||||
### Modus 3 — Vorwaerts-Nachbau (Legacy, wird umgebaut)
|
||||
### Modus 3 — aus 3D Linie OHNE Zielhoehe (Vorwaerts-Bau)
|
||||
|
||||
Baut dieselbe gezeichnete Geometrie wie Modus 2, aber VORWAERTS mit
|
||||
vorgegebenen Winkeln: die Endhoehe ist hier ein Ergebnis, kein Ziel. Genau
|
||||
das ist sein Anwendungsfall — wenn es keine feste Zielhoehe gibt.
|
||||
|
||||
| Feld | Steuerelement | Werte |
|
||||
|---|---|---|
|
||||
| Startpunkt (3D) | Punktwahl | KS_EIN AUS-Element / Kettenanfang |
|
||||
| Gefaellewinkel | Zahl (Grad) | wird auch aus 2 gewaehlten 3D-Punkten vorgeschlagen |
|
||||
| AUS-Element Seite | Dropdown | links / rechts |
|
||||
| Separator vor EIN? | Dropdown | Ja/Nein |
|
||||
| Einfuegen bestaetigen | Dropdown | Ja/Nein |
|
||||
| Startpunkt (3D) + Starthoehe | Punktwahl + Zahl | Kettenanfang |
|
||||
| AS-Element bauen? | Ja/Nein | bei Nein beginnt die Kette direkt am Startpunkt |
|
||||
| -> AS Winkel + Seite | Dropdown | 30/90 Grad · links/rechts (ein Dialog zusammen mit "bauen?") |
|
||||
| ES-Element bauen? | Ja/Nein | **vor** dem Bau gefragt, damit der ES-Fussabdruck von der letzten Geraden abgezogen werden kann |
|
||||
| -> ES Winkel + Seite | Dropdown | 30/90 Grad · links/rechts |
|
||||
| Pfad-Objekte | Objektauswahl | Linien + Boegen der Trasse |
|
||||
| Je gerades Segment: Typ | Dropdown | GF / VF-Ab / VF-Auf / VF-Horizontal |
|
||||
| -> GF-Neigung bzw. Vario-Winkel | Zahl (Grad) | kontextabhaengig |
|
||||
| Je Bogen-Segment: Typ | Dropdown | GF-Bogen / Vario-Kurve (+ Variante) |
|
||||
|
||||
Ketten, die vor dem 2026-10-22 gebaut wurden, kennen die beiden
|
||||
"bauen?"-Fragen noch nicht; sie werden beim Doppelklick automatisch erkannt
|
||||
und in der alten Reihenfolge nachgebaut (siehe `alt-journal` in
|
||||
`vf-linienzug-modus3`).
|
||||
|
||||
---
|
||||
|
||||
@@ -623,9 +636,16 @@ Beispiel: `tests/test_hm_recformat.lsp` (5 echte Ketten aus `data/polylines.dxf`
|
||||
setzt alle drei Schalter mit Save/Restore, ersetzt `getpoint`/`getstring`/
|
||||
`getint`/`getreal`/`alert` zusaetzlich durch **zaehlende** Stubs (Netz fuer
|
||||
Prompts ausserhalb der Wrapper) und schreibt `prompts`, `headless_fehler` und
|
||||
`meldungen` in `tests/output/hm_recformat_results.json`. Noch nicht umgestellt:
|
||||
`vfl-konvertiere-ent` (Batch-2D/3D-Konvertierung) laeuft weiter ohne
|
||||
`*vfl-headless*` - dort ist eine Live-Rueckfrage bisher gewolltes Verhalten.
|
||||
`meldungen` in `tests/output/hm_recformat_results.json`.
|
||||
|
||||
Auch `vfl-konvertiere-ent` (Batch-2D/3D-Konvertierung `SSG_DIM_ALL_2D`/`_3D`,
|
||||
Modus 1/2/3) laeuft seit 2026-10-26 unter `*vfl-headless*` (Wizard und GUI
|
||||
aus, Save/Restore). Reicht ein Journal nicht, bricht der Neubau mit
|
||||
Fundstelle ab statt mitten im Batch live zu fragen. Der ALTE Block bleibt
|
||||
dabei stehen und wird erst geloescht, wenn ein neuer `VF_n`-INSERT entstanden
|
||||
ist; bei einem Fehlschlag raeumt `vfl-konvert-aufraeumen` alles seit der
|
||||
Startmarke Erzeugte wieder weg (keine losen Teile). Die Gruende sammelt
|
||||
`*vfl-konvert-fehler*`, der Batch gibt sie am Ende als Liste aus.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -105,6 +105,63 @@ Zwischen-Etappe, es geht in derselben VF-Einheit weiter (Vario-Kurve,
|
||||
weiteres gerades Stueck, Auf/Ab). "Ja" beendet die VF-Einheit mit einer
|
||||
Motorstation - optional zusaetzlich mit ES-Element (echtes Kettenende).
|
||||
|
||||
### 3a. Neu seit 2026-10-21: Zufuehrungsachse und "Parallel zum Kreisel"
|
||||
|
||||
Die Tabelle oben zitiert eine aeltere Aufzeichnung. Zwei Dinge sind seitdem
|
||||
dazugekommen (aeltere Ketten bleiben unveraendert editierbar - das Journal
|
||||
erkennt am Eintragstyp, welche Fragen damals gestellt wurden):
|
||||
|
||||
**Zufuehrungsachse (2. Punkt) - jetzt bei BEIDEN AS-Winkeln.** Nach Winkel
|
||||
und Seite (Eintrag 4/5) fragt der AS-Dialog zusaetzlich einen zweiten Punkt
|
||||
ab; im Assistenten stehen alle drei Angaben in EINEM Fenster
|
||||
(`vflw_as_achse`). Die beiden Angaben beschreiben verschiedene Dinge und
|
||||
legen das AS erst zusammen vollstaendig fest:
|
||||
|
||||
| Angabe | legt fest |
|
||||
|---|---|
|
||||
| 2. Punkt | Richtung der KS_EIN-Achse = die Zufuehrung, z.B. die Kreisel-Laufrichtung. Der Startpunkt bleibt der Sitz des AS-Elements, der zweite Punkt gibt nur die Richtung. |
|
||||
| links/rechts | AS-Variante und damit die KS_AUS-Richtung, also wohin die Kette nach dem Ausschleusen laeuft. |
|
||||
|
||||
Der Dialog zeigt den Startpunkt mit an (er ist der Sitz des AS-Elements UND
|
||||
der Ausgangspunkt der Achse); waehrend der Punktwahl haengt das Gummiband an
|
||||
ihm. Mit dem gesetzten Punkt ist der Dialog fertig und schliesst direkt - die
|
||||
ermittelte Achsrichtung meldet die Konsole. Nur ein mit ESC abgebrochener
|
||||
Pick zeigt den Dialog noch einmal (mit den vorher gewaehlten Werten), damit
|
||||
nach einem Fehlklick nichts verloren geht.
|
||||
|
||||
Die Achse ist **optional**: ohne Punkt laeuft alles wie frueher ueber die
|
||||
Richtung des naechsten Klicks. Frueher ersetzte die Achse beim 30-Grad-
|
||||
Element die Seitenfrage (die Seite wurde aus der Lage des naechsten Punkts
|
||||
erraten); das gilt nur noch beim Nachbau alter Ketten.
|
||||
|
||||
**"Parallel zum Kreisel weiterbauen"** - 5. Option der Frage "Wie soll die
|
||||
Laenge dieser Gefaellestrecke bestimmt werden?" (Eintrag 30). Sie erscheint
|
||||
nur am Kettenanfang mit AS-Element UND festgelegter Zufuehrungsachse, weil
|
||||
sie beides als Bezug braucht. Gebaut wird AS -> kurzes GF-Stueck -> GF-Bogen,
|
||||
sodass die Kette danach parallel zur Zufuehrungsachse weiterlaeuft. Einzige
|
||||
Eingabe ist der **Abstand**, gemessen senkrecht zur Zufuehrungsachse von
|
||||
KS_EIN des AS bis KS_AUS des Bogens; die Laenge des GF-Stuecks dazwischen
|
||||
wird daraus berechnet. Ein Separator zwischen GF-Stueck und Bogen wird
|
||||
bewusst NICHT gesetzt, damit der Abstand exakt getroffen wird. Der Bogen wird
|
||||
nicht geraten, sondern so gewaehlt, dass er den gemessenen Grundriss-Schwenk
|
||||
des AS-Blocks genau aufhebt - immer zur Gegenseite der AS-Seite:
|
||||
|
||||
| AS | Bogen |
|
||||
|---|---|
|
||||
| 30 Grad links | 30 Grad rechts |
|
||||
| 30 Grad rechts | 30 Grad links |
|
||||
| 90 Grad links | 90 Grad rechts |
|
||||
| 90 Grad rechts | 90 Grad links |
|
||||
|
||||
Diese Tabelle ist das ERGEBNIS der Messung, keine gepflegte Zuordnung im
|
||||
Code - sie bleibt auch dann richtig, wenn ein Element anders vermessen ist
|
||||
als hier erwartet.
|
||||
|
||||
Direkt nach dem Bogen kommt die gewohnte Frage "Ist das das Kettenende?"
|
||||
(Ja mit ES / Ja ohne ES / Nein, weiterbauen) - hier ausnahmsweise NACH dem
|
||||
Bau, weil es keine gepickte Laenge gibt, von der ein ES-Fussabdruck
|
||||
abzuziehen waere.
|
||||
|
||||
## 4. Stufe 1 / Stufe 2 - wie die letzte Strecke berechnet wird
|
||||
|
||||
Am Kettenende (Eintrag 61/62) ist die Aufgabe: von der aktuellen Position/
|
||||
|
||||
+128
-9
@@ -9,6 +9,7 @@
|
||||
"vfl-as-auto-erkannt": "\n>>> Startpunkt liegt auf KS_AUS einer bestehenden %1-Kette - kein AS-Element noetig.",
|
||||
"vfl-familie-neutral": "GF/VF",
|
||||
"vfl-sep-nach-durch-es-ueberschrieben": "\n>>> Separator NACH ignoriert - das ES-Element bringt beim Kettenende bereits seinen eigenen Separator mit (sonst zwei Separatoren hintereinander).",
|
||||
"vfl-sep-gf-es-automatisch": "(Ein Separator zwischen GF und ES wird automatisch gesetzt.)",
|
||||
"vfl-echo-position": "\n>>> Position: X=%1 Y=%2 Z=%3",
|
||||
"vfl-echo-wahl": "\n>>> Gewaehlt: %1",
|
||||
"vfl-aus-seite-header": "\n\nAUS-Element (AS_Element_*) - Seite waehlen:",
|
||||
@@ -55,6 +56,27 @@
|
||||
"vfl-gf-laenge-modus-opt-hoehe": "\n 2 - Zielhoehe festlegen (Laenge wird berechnet)",
|
||||
"vfl-gf-laenge-modus-opt-steigend": "\n 3 - Steigende GF (Sonderfall, bis 3 Grad)",
|
||||
"vfl-gf-laenge-modus-opt-qc": "\n 4 - QC Linie mit GF (automatische Auf-Ab-Berechnung)",
|
||||
"vfl-gf-laenge-modus-opt-parallel": "\n 5 - Parallel zum Kreisel weiterbauen (nur Abstand eingeben)",
|
||||
"vfl-richtung-header": "\n\nIn welche Richtung soll gebaut werden?",
|
||||
"vfl-richtung-opt-vor": "\n 1 - Vorwaerts bauen (der gewaehlte Punkt ist der Kettenanfang)",
|
||||
"vfl-richtung-opt-rueck": "\n 2 - Rueckwaerts bauen (der gewaehlte Punkt ist das Kettenende, ES-Austritt)",
|
||||
"vfl-prompt-es-achse-p2": "\n\nFahrtrichtung - 2. Punkt (gibt nur die Richtung, der Endpunkt bleibt): ",
|
||||
"vfl-es-basislinie-info": "\n Abfuehrungsachse (Fahrtrichtung): %1 Grad.",
|
||||
"vfl-rueck-menu-linie-gf": "\n 1 - Neue Linie: GF (Gefaellestrecke)",
|
||||
"vfl-rueck-laenge-opt-anfangspunkt": "\n 1 - Kettenanfang waehlen (Laenge ergibt sich, Anfangshoehe wird gerechnet)",
|
||||
"vfl-rueck-laenge-opt-anfangshoehe": "\n 2 - Anfangshoehe festlegen (Laenge wird berechnet)",
|
||||
"vfl-rueck-prompt-anfangspunkt": "\n\nKettenanfang waehlen (Richtung steht ueber die Abfuehrungsachse fest): ",
|
||||
"vfl-rueck-prompt-anfangshoehe": "\nGewuenschte Hoehe am Kettenanfang (mm) <%1>: ",
|
||||
"vfl-rueck-alert-hoehe-zu-klein": "Der Kettenanfang muss HOEHER liegen als das Kettenende - eine Gefaellestrecke faellt in Fahrtrichtung.",
|
||||
"vfl-rueck-erfolg-punkt": "\n>>> Rueckwaerts gebaut: GF-Stueck %1 mm (horizontal), Anfangshoehe %2 mm.",
|
||||
"vfl-rueck-erfolg-hoehe": "\n>>> Rueckwaerts gebaut: GF-Stueck %1 mm (horizontal), Anfangshoehe %2 mm.",
|
||||
"vfl-rueck-erfolg-parallel": "\n>>> Rueckwaerts, parallel zum Kreisel: GF-Stueck %1 mm (horizontal), Bogen %2 Grad %3.",
|
||||
"vfl-par-prompt-abstand": "\n\nAbstand zum Kreisel (mm, senkrecht zur Zufuehrungsachse, von AS-KS_EIN bis Bogen-KS_AUS): ",
|
||||
"vfl-par-nur-kettenanfang": "'Parallel zum Kreisel' geht nur am Kettenanfang mit AS-Element UND festgelegter Zufuehrungsachse (2. Punkt im AS-Dialog).",
|
||||
"vfl-par-kein-bogen": "Kein GF-Bogen hebt den AS-Schwenk von %1 Grad auf (Seite %2) - parallel zum Kreisel nicht schliessbar.",
|
||||
"vfl-par-kein-versatz": "Das AS-Element schwenkt nicht aus der Zufuehrungsachse heraus - so laesst sich kein Abstand erreichen.",
|
||||
"vfl-par-zu-klein": "Abstand %1 mm zu klein: AS und Bogen allein brauchen schon %2 mm. Bitte groesseren Abstand waehlen.",
|
||||
"vfl-par-erfolg": "\n>>> Parallel zum Kreisel: GF-Stueck %1 mm (horizontal), Bogen %2 Grad %3, erreichter Abstand %4 mm.",
|
||||
"vfl-qc-nur-kettenanfang": "\nFEHLER: 'QC Linie mit GF' ist nur am Kettenanfang moeglich (braucht eine eigene AS-Seite) - bitte anderen Modus waehlen.",
|
||||
"vfl-qc-prompt-richtung": "\n\nRichtung waehlen (Gerade, auf der AS-Eintritt und ES-Austritt liegen sollen) - Punkt in Fahrtrichtung anklicken: ",
|
||||
"vfl-qc-ks-ein-gemessen": "\n>>> AS KS_EIN (Referenzgerade) gemessen: X=%1 Y=%2 Z=%3",
|
||||
@@ -99,6 +121,11 @@
|
||||
"vfl-es-setzen-frage": "\n\nES-Element setzen?",
|
||||
"vfl-es-nein-zielpunkt": "\n 2 - Nein (Kette endet direkt am Zielpunkt)",
|
||||
"vfl-prompt-endpunkt-fahrtrichtung": "\n\nEndpunkt entlang Fahrtrichtung waehlen (bestimmt die Laenge): ",
|
||||
"vfl-prompt-as-achse-p2": "\n\nZufuehrungsachse - 2. Punkt (gibt nur die Richtung, der Startpunkt bleibt): ",
|
||||
"vfl-basislinie-punkte-gleich": "\n Die beiden Punkte sind identisch - keine Richtung bestimmbar. Abbruch.",
|
||||
"vfl-basislinie-info": "\n Zufuehrungsachse (Fahrtrichtung): %1 Grad.",
|
||||
"vfl-basislinie-ohne": "\n Keine Zufuehrungsachse festgelegt - die Richtung ergibt sich aus dem naechsten Klick.",
|
||||
"vfl-as-seite-ermittelt": "\n AS-Seite aus der Lage des naechsten Punkts: %1",
|
||||
"vfl-endpunkt-modus-header": "\n\nWie soll der Endpunkt bestimmt werden?",
|
||||
"vfl-endpunkt-modus-opt-linie": "\n 1 - Ziellinie zeichnen (2 Punkte) - der Schnittpunkt bestimmt die Laenge",
|
||||
"vfl-prompt-ziellinie-p1": "\n\nZiellinie - 1. Punkt (beliebige Richtung, Z wird ignoriert): ",
|
||||
@@ -122,7 +149,9 @@
|
||||
"vfl-edit-kette-header": "\n\nLinienzug mit %1 Glied(ern):",
|
||||
"vfl-edit-abgespielt": "\n>>> %1 Glied(er) werden abgespielt, %2 zurueckgenommen - danach interaktiv weiter.",
|
||||
"vfl-edit2-reset-info": "\n>>> Linienzug (Modus 2) wird mit den gespeicherten Angaben identisch neu aufgebaut...",
|
||||
"vfl-konvert-fehler": "\n>>> FEHLER bei der Umwandlung von %1: %2 - der alte Block ist entfernt, die Teil-Geometrie liegt frei in der Zeichnung.",
|
||||
"vfl-konvert-fehler": "\n>>> FEHLER bei der Umwandlung von %1: %2 - der alte Block bleibt unveraendert stehen.",
|
||||
"vfl-konvert-grund-journal": "Journal reicht nicht aus (%1)",
|
||||
"vfl-konvert-grund-kein-block": "kein Block erzeugt",
|
||||
"vfl-restore-prompt-auswahl": "\nLose Linienzug-Geometrie waehlen (die Sektions-XDATA der Objekte wird ausgelesen):",
|
||||
"vfl-restore-keine-sektionen": "\n>>> In der Auswahl steckt keine Sektions-XDATA (SSG_VF_EDIT_SEG) - daraus laesst sich keine Kette wiederherstellen.",
|
||||
"vfl-restore-luecke": "\n>>> WARNUNG: Sektion %1 fehlt in der Auswahl - nur die Glieder 1..%2 werden wiederhergestellt.",
|
||||
@@ -169,7 +198,7 @@
|
||||
"vfl-soll-xyz": "\n Soll: X=%1 Y=%2 Z=%3",
|
||||
"vfl-ist-xyz": "\n Ist : X=%1 Y=%2 Z=%3",
|
||||
"vfl-abweichung-xyz": "\n Abweichung: dX=%1 dY=%2 dZ=%3 mm",
|
||||
"vfl-m3-titel": "\n VF-LINIENZUG - Modus 2: Pfad + Ziel-Hoehe (fertig; Anker + Solver + Bau)",
|
||||
"vfl-m3-titel": "\n VF-LINIENZUG - Modus 2: aus 3D Linie MIT Zielhoehe (Anker + Solver + Bau)",
|
||||
"vfl-m3-alert-gf-modul": "Gefaellestrecke-Modul nicht geladen!",
|
||||
"vfl-m3-pfad-waehlen": "\n\nPfad-Objekte waehlen (Linien/Boegen):",
|
||||
"vfl-m3-keine-objekte": "\nKeine Objekte gewaehlt - Abbruch.",
|
||||
@@ -224,13 +253,24 @@
|
||||
"vfl-m3-kletter-zu-kurz-flach": "\n Kein Kletter-Winkel passt (Segment zu kurz) -> Lauf wird komplett flach gebaut, Hoehe wandert in GF1.",
|
||||
"vfl-m3-kletter-flach-gf": "\n Flache Zone: GF-Kompensation (GF1) = %1 mm",
|
||||
"vfl-m3-alert-vf-zu-lang": "VF-Lauf ist %1 m lang (Grenze %2 m) - bitte neu planen (z.B. Zwischen-Motorstation einfuegen).",
|
||||
"vfl-m2-einheit-grenze": "Diese VF-Einheit ist so nicht baubar.\n\nGemessen: %1 m Laenge, %2 Vario-Kurven.\nErlaubt je Einheit (zwischen Umlenk- und Motorstation): hoechstens %3 m und %4 Vario-Kurven.\n\nBitte den Bogen in Segment %5 als GF-Bogen klassifizieren - dann endet die erste Einheit davor mit einer Motorstation und die zweite beginnt danach mit einer Umlenkstation.",
|
||||
"vfl-m2-einheit-grenze-unteilbar": "Diese VF-Einheit ist so nicht baubar.\n\nGemessen: %1 m Laenge, %2 Vario-Kurven.\nErlaubt je Einheit (zwischen Umlenk- und Motorstation): hoechstens %3 m und %4 Vario-Kurven.\n\nEs gibt keinen Bogen, an dem sich der Lauf teilen liesse - bitte den Pfad kuerzer fassen oder eine Ecke einplanen, an der die Einheit enden kann.",
|
||||
"vfl-m3-warnung-fueller-eingang-zu-kurz": "\n WARNUNG: Fueller direkt nach der Umlenkstation zu kurz (%1 mm < Minimum %2 mm) - nur Minimalabstand gebaut, Zielposition nicht exakt erreicht.",
|
||||
"vfl-m3-warnung-fueller-ausgang-zu-kurz": "\n WARNUNG: Fueller direkt vor der Motorstation zu kurz (%1 mm < Minimum %2 mm) - nur Minimalabstand gebaut, Zielposition nicht exakt erreicht.",
|
||||
"vfl-m3-lauf-anfang-header": "\n\nDer VF-Lauf ist der Anfang des gewaehlten Pfads. Lauf beginnen mit:",
|
||||
"vfl-m3-lauf-anfang-opt-offen": "\n 1 - Ohne Umlenkstation (offener Anfang, spaeter fortsetzen/verschmelzen)",
|
||||
"vfl-m3-lauf-anfang-opt-offen": "\n 3 - Ohne Umlenkstation (offener Anfang, spaeter fortsetzen/verschmelzen)",
|
||||
"vfl-m3-lauf-anfang-opt-umlenk": "\n 2 - Umlenkstation direkt (kein GF1/Separator)",
|
||||
"vfl-m3-lauf-anfang-opt-umlenk-gf1": "\n 3 - Umlenkstation mit GF1 + Separator",
|
||||
"vfl-m3-lauf-anfang-opt-umlenk-gf1": "\n 1 - Umlenkstation mit GF1 + Separator",
|
||||
"vfl-m2-uebergang-bogen-fehlt": "Uebergangsbogen %1 fehlt in der Bogen-Tabelle - der Block ist nicht ladbar oder hat kein messbares KS. Der Lauf wird ohne seinen Laengenanteil gebaut und faellt dadurch um dessen Laenge zu lang aus.",
|
||||
"vfl-m2-segwert-unbekannt": "Segment %1 nicht lesbar: Kette %2 enthaelt einen unbekannten Klassifizierungswert. Aufbau abgebrochen - ein geratener Segmenttyp wuerde die Kette falsch neu bauen.",
|
||||
"vfl-m2-eck-korrektur": "\n Eck-Korrektur %1 mm auf Segment %2 (gezeichneter Bogen gegen Fussabdruck des Eck-Bauteils).",
|
||||
"vfl-m2-abschluss-fussabdruck": "\n Abschluss-Fussabdruck %1 mm von Segment %2 abgezogen (Abschlussbogen + Motorstation stehen darauf).",
|
||||
"vfl-m2-kletter-ende-fussabdruck": "\n Kletter-Ende: %1 mm von Segment %2 abgezogen (Motorstation + Separator + ES stehen auf dem Kletterer, nicht auf einem Fueller).",
|
||||
"vfl-m2-as-fussabdruck": "\n AS-Fussabdruck %1 mm von Segment %2 abgezogen (das AS-Element steht selbst darauf).",
|
||||
"vfl-m2-anfang-wert-unbekannt": "Lauf-Anfang nicht lesbar: Kette %1 enthaelt den unbekannten Wert %2. Aufbau abgebrochen - eine geratene Anfangsvariante wuerde die Kette falsch neu bauen.",
|
||||
"vfl-m3-lauf-anfang-offen-hinweis": "\n Anfang bleibt bewusst offen - keine Umlenkstation/GF1/Separator gebaut, spaeter fortsetzen oder per Vario_Kette_Merge verbinden.",
|
||||
"vfl-m2-anfang-offen-gesperrt-zeile": "\n (nicht waehlbar - mit AS-Element braucht der Lauf eine Umlenkstation)",
|
||||
"vfl-m2-anfang-offen-gesperrt": "Mit AS-Element ist ein offener Anfang nicht moeglich - der Lauf braucht dann eine Umlenkstation.",
|
||||
"vfl-m3-lauf-abschluss-header": "\n\nDer VF-Lauf ist das Ende des gewaehlten Pfads. Lauf beenden mit:",
|
||||
"vfl-m3-lauf-abschluss-opt-offen": "\n 1 - Ohne Motorstation (offenes Ende, spaeter fortsetzen/verschmelzen)",
|
||||
"vfl-m3-lauf-abschluss-opt-motor": "\n 2 - Motorstation setzen (kein ES-Element)",
|
||||
@@ -246,6 +286,7 @@
|
||||
"vfl-m3-gf2-ausgleich": "\n GF2 (gemessener Ausgleich): L=%1 mm",
|
||||
"vfl-m3-kurve-back-uebersprungen": "\n >>> [M3a] Vario-Kurve im Back-Lauf - uebersprungen.",
|
||||
"vfl-m3-nichts-gebaut": "\nNichts gebaut - Abbruch.",
|
||||
"vfl-m3-alt-journal": "\n Hinweis: Diese Kette stammt aus der Zeit vor den Fragen AS bauen / ES bauen - sie wird in der alten Reihenfolge nachgebaut.",
|
||||
"vfl-m3-fertig-header": "\n>>> VF-Linienzug (Modus 2) gebaut! <<<",
|
||||
"vfl-m3-ziel-soll": "\n Ziel (Soll): X=%1 Y=%2 Z=%3",
|
||||
"vfl-m3-es-ist": "\n ES (Ist): X=%1 Y=%2 Z=%3",
|
||||
@@ -280,6 +321,7 @@
|
||||
"kreisel-edit-bestehend": "\n-> Bestehend: Abstand=%1 Drehung=%2 Art=%3",
|
||||
"kreisel-edit-dialog-fehlt": "Dialog nicht verfuegbar: %1",
|
||||
"kreisel-eingefuegt": "\n-> Kreisel #%1 eingefügt: %2 (Höhe=%3)",
|
||||
"kreisel-emsg-abstand-zu-klein": "Abstand zu klein! (%1 < %2) - die Endkreise wuerden sich beruehren/ueberschneiden.",
|
||||
"kreisel-emsg-distanz-klein": "Distanz zu klein! (%1 < %2)",
|
||||
"kreisel-hoehe-aus-3dpunkt": "\n-> Hoehe aus 3D-Punkt uebernommen: %1",
|
||||
"kreisel-hoehe-aus-basispunkt": "\n-> Höhe aus Basispunkt übernommen: %1",
|
||||
@@ -633,6 +675,8 @@
|
||||
"dim-switch-blocks": "\n DXFM_BLOCKS = %1",
|
||||
"dim-switch-omniflo": "\n DXFM_OMNIFLO = %1",
|
||||
"dim-batch-fertig": "\nUmwandlung auf %1 abgeschlossen: %2 GF, %3 VF neu aufgebaut (%4 bereits in Zieldimension).",
|
||||
"dim-batch-fehlerliste": "\n%1 Linienzug-Block/Bloecke NICHT umgewandelt (unveraendert stehen gelassen):",
|
||||
"dim-batch-fehler-zeile": "\n - %1: %2",
|
||||
"sprache-gewechselt": "\nSprache umgeschaltet auf: %1",
|
||||
"cmd-block-auswaehlen": "\nBlock auswaehlen: ",
|
||||
"cmd-kein-block-ausgewaehlt": "\nKein Block ausgewaehlt.",
|
||||
@@ -685,6 +729,9 @@
|
||||
"plq-geloescht": "\n[DELETE_PLANQUADRATE] Planquadrat-Raster entfernt (%1 Einfuegung(en)).",
|
||||
"plq-nichts-zu-loeschen": "\n[DELETE_PLANQUADRATE] Kein Planquadrat-Raster in der Zeichnung vorhanden.",
|
||||
"exp-check-ids": "\n[%1] Pruefe und vergebe IDs...",
|
||||
"exp-hoehencheck-frage": "\nVor dem Export den Hoehen-Check (Montagehoehe/Buehnen) ausfuehren?",
|
||||
"exp-bereinigen": "\nBereinige Zeichnung (PURGE: unbenutzte Bloecke, Layer, Linientypen) ...",
|
||||
"exp-hoehencheck-fehlt": "\nHinweis: HOEHEN_CHECK nicht verfuegbar - Export laeuft ohne Hoehen-Check.",
|
||||
"exp-hoehen-aktualisiert": "\nHoehen-Attribute von %1 verschobenen Bloecken aus der Z-Koordinate neu gesetzt.",
|
||||
"exp-sep-proxy-fehler": "\n[EXPORT] WARNUNG: Kopie von '%1' aus Block '%2' fehlgeschlagen (%3) - dieses Element fehlt im Export.",
|
||||
"exp-sep-zuordnung": "\n[%1] verpackte Separator-Kopie(n): ZUORDNUNG aus der ID des Wrapper-Blocks gesetzt.",
|
||||
@@ -913,6 +960,16 @@
|
||||
"tro-insert-kein-block": "Kein Symbol fuer diesen Typ in der Zeichnung (%1) - bitte tro_annotate.py mit diesem Typ laufen lassen.",
|
||||
"tro-insert-prompt-punkt": "\nEinfuegepunkt: ",
|
||||
"tro-insert-eingefuegt": "\nTRO eingefuegt: ID = %1, TYP = %2",
|
||||
"cmd-jam-bearbeiten": "\nStaubereich bearbeiten: %1",
|
||||
"jam-edit-kein-jam": "Block %1 ist kein Staubereich (erwartet JAM_*).",
|
||||
"jam-edit-dialog-fehlt": "Dialogdatei nicht gefunden:\n%1\nDXFM_DCL pruefen (setenv.bat).",
|
||||
"jam-edit-bereich": "Staubereich %1 vor %2 (Eingang %3)",
|
||||
"jam-edit-auto": "Abgeleitet: %1",
|
||||
"jam-edit-hinweis": "In die SCL: tro_annotate --read-jams, danach scl_skeleton.",
|
||||
"jam-edit-foerderer-ungueltig": "Der Foerderer muss vierstellig sein (z. B. 0054) - nichts geaendert.",
|
||||
"jam-edit-nummer-ungueltig": "Die laufende Nummer muss eine ganze Zahl ab 1 sein - nichts geaendert.",
|
||||
"jam-edit-gespeichert": "\nStaubereich gespeichert: %1 (%2)",
|
||||
"jam-edit-doppelt": "\nACHTUNG: %1 gibt es schon in dieser Zeichnung (%2).",
|
||||
"vfl-abbruch-gesichert": "\n>>> Linienzug abgebrochen: %1 Objekt(e) als Block gesichert (per Doppelklick editierbar/fortsetzbar).",
|
||||
"vfl-zurueck-glied-verworfen": "\n>>> Zurueck: letztes Kettenglied wird verworfen - bitte neu beantworten.",
|
||||
"vfl-abbruch-nichts-gebaut": "\n>>> Abgebrochen - es wurde noch keine Geometrie erzeugt.",
|
||||
@@ -929,13 +986,13 @@
|
||||
"vfc-warnung-untermodule-nicht-geladen": "\n[vf_core] WARNUNG: DXFM_LISP nicht gesetzt - Untermodule konnten nicht geladen werden!",
|
||||
"vfc-linienzug-modus-header": "\n\nLinienzug-Modus waehlen:",
|
||||
"vfc-linienzug-modus-1": "\n 1 - Manuelle Eingabe (Punkte klicken)",
|
||||
"vfc-linienzug-modus-2": "\n 2 - 3D-Objekte + Ziel-Hoehe (Randwert-Solver, fertig)",
|
||||
"vfc-linienzug-modus-3": "\n 3 - 3D-Objekte stueckweise (Vorwaerts-Nachbau, in Arbeit)",
|
||||
"vfc-linienzug-modus-2": "\n 2 - aus 3D Linie MIT Zielhoehe (Hoehen werden gerechnet)",
|
||||
"vfc-linienzug-modus-3": "\n 3 - aus 3D Linie OHNE Zielhoehe (Vorwaerts-Bau mit vorgegebenen Winkeln)",
|
||||
"prompt-wahl-1-3": "\nIhre Wahl (1/2/3) [1]: ",
|
||||
"vfl-qc-uform-nicht-implementiert": "\nFEHLER: 'QC Linie mit GF und U-Form' ist noch nicht implementiert - bitte Option 4 oder einen anderen Modus waehlen.",
|
||||
"vfc-typ-standard-beschreibung": "Standard VarioFoerderer (AS/ES 90 Grad, horizontal versetzt)",
|
||||
"vfc-typ-etage-beschreibung": "Etage VarioFoerderer (AS/ES 30 Grad, direkt uebereinander)",
|
||||
"vfc-typ-linienzug-beschreibung": "Streckengruppe (gemischte GF/VF-Kette; Modus 1 manuell / Modus 2 Ziel-Hoehe fertig / Modus 3 stueckweise in Arbeit)",
|
||||
"vfc-typ-linienzug-beschreibung": "Streckengruppe (gemischte GF/VF-Kette; Modus 1 manuell / Modus 2 aus 3D Linie mit Zielhoehe / Modus 3 aus 3D Linie ohne Zielhoehe)",
|
||||
"vfs-schritt6-horizontal": "\n\n6/11: Horizontale Zwischenstrecke (0 Grad, L=%1 mm)",
|
||||
"vfs-schritt6-steigung": "\n\n6/11: Steigungsstrecke (%1 Grad, L=%2 mm)",
|
||||
"vfs-schritt6-gefaelle": "\n\n6/11: Gefaellestrecke (%1 Grad, L=%2 mm)",
|
||||
@@ -964,7 +1021,7 @@
|
||||
"vfe-step14": "\n\n14/15: Separator (300mm, cur-hz=%1)",
|
||||
"vfe-step15": "\n\n15/15: %1 (Ende, verkettet cur-hz=%2)",
|
||||
"vfe-eingefuegt": "\n>>> Etage-VarioFoerderer eingefuegt! <<<",
|
||||
"vfl-vwnb-titel": "\n VF-LINIENZUG - Modus 3: 3D-Objekte stueckweise (Vorwaerts-Nachbau, in Arbeit)",
|
||||
"vfl-vwnb-titel": "\n VF-LINIENZUG - Modus 3: aus 3D Linie OHNE Zielhoehe (Vorwaerts-Bau)",
|
||||
"vfl-vwnb-aus-seite-menu": "\n\nAUS-Element - Seite waehlen:\n 1 - Links\n 2 - Rechts",
|
||||
"vfl-vwnb-alert-eckwinkel": "Kein passender Bogen: Eck-Winkel %1 Grad ist nicht ~30/60/90.\nBitte die Winkel der Linien anpassen.",
|
||||
"vfl-vwnb-alert-keine-gerade": "Pfad enthaelt keine Gerade - eine Kette muss mit einer Geraden beginnen.",
|
||||
@@ -1120,6 +1177,16 @@
|
||||
"kreisel-bp-zeile": "\n Weiche %1: %2 <-> %3 [%4] bei X=%5 Y=%6 Z=%7",
|
||||
"kreisel-bp-kollision": "\n KOLLISION %1: %2 <-> %3 [%4] bei X=%5 Y=%6 Z=%7",
|
||||
"kreisel-bp-marker": "\n%1 Marker gezeichnet (Layer %2).",
|
||||
"chh-start": "\n--- Phase 3: Buehnen-Familien ---",
|
||||
"chh-kein-kreisel": "\n Hinweis: Kreisel-Modul nicht verfuegbar - nur blockweise Abfrage.",
|
||||
"chh-fam-frage": "\n Familie %1 (%2, %3 Kreisel, Montagehoehe %4 m): liegt auf einer Buehne?",
|
||||
"chh-schleife": "\n %1: flache Schleife am selben Kreisel (VON = BIS) - wird einzeln gefragt.",
|
||||
"chh-buehne-hoehe": "Buehnenhoehe in m",
|
||||
"chh-buehne-ungueltig": "\n ! Buehnenhoehe muss > 0 und < %1 m sein.",
|
||||
"chh-kreuz-konflikt": "\n ! %1: Enden in Familien mit verschiedener Buehnenhoehe (%2 / %3 m) - nicht geaendert.",
|
||||
"chh-kreuz-hoehe": "\n ! %1: Familienhoehen unterscheiden sich um %2 mm (> %3 mm) - nicht geaendert.",
|
||||
"chh-strecke-neg": "\n ! %1: Buehne %2 m >= Montagehoehe %3 m - nicht geaendert.",
|
||||
"chh-summe": "\n Phase 3: %1 Familie(n), %2 mit Buehne; angepasst: Kreisel %3, Strecken innerhalb %4, zwischen Familien %5; Konflikte %6; einzeln gefragt %7",
|
||||
"exp-kreisel-weichen": "\n[%1] Kreisel-Weichenpunkte: %2 Beruehrung(en), %3 Kollision(en) -> %4",
|
||||
"exp-kreisel-kollision": "\n[%1] WARNUNG: %2 Kreisel-Kollision(en) - Befehl KREISEL_WEICHEN zeigt sie an.",
|
||||
"lg-daten-fehlt": "\n[Lager] Datendatei nicht gefunden: %1 - es gelten die eingebauten Vorgaben.",
|
||||
@@ -1219,6 +1286,58 @@
|
||||
"lg-regel-profil-fehlt": "\n[Lager] Regelprofil %1 nicht gefunden (%2).",
|
||||
"lg-regel-profil-ungepflegt": "\n[Lager] WARNUNG: Regelprofil %1 ist nicht gepflegt - es gelten die geerbten Werte.",
|
||||
"lg-regel-unbekannt": "\n[Lager] Regel %1 nicht im Profil.",
|
||||
"lg-regel-liste-kopf": "\nRegelprofil %1: %2 Regeln (Kontext: erhoehte Brandgefaehrdung ohne Loeschanlage)"
|
||||
"lg-regel-liste-kopf": "\nRegelprofil %1: %2 Regeln (Kontext: erhoehte Brandgefaehrdung ohne Loeschanlage)",
|
||||
"kf-fehler-daten-fehlt": "\nFEHLER: Kettenfoerderer-Daten nicht gefunden: %1",
|
||||
"kf-fehler-daten-leer": "\nFEHLER: Kettenfoerderer-Daten konnten nicht gelesen werden.",
|
||||
"kf-fehler-block-datei": "\nFEHLER: Blockdatei fuer %1 nicht gefunden (erwartet in data/omniflo/<Dimension>/).",
|
||||
"kf-fehler-ks-fehlt": "In mindestens einem Baustein fehlt KS_EIN oder KS_AUS - die Kette kann nicht verkettet werden. Befehl KF_KS_PRUEFEN zeigt, welcher Block betroffen ist.",
|
||||
"kf-fehler-hoehe-zu-klein": "Die Einbauhoehe ist zu klein: Umlenk- und Antriebsstation bringen bereits mehr Hoehe mit, als gefordert ist. Bitte groessere Hoehe waehlen.",
|
||||
"kf-fehler-laenge-unter-min": "Das Zwischenstueck waere kuerzer als zulaessig. Bitte groessere Einbauhoehe waehlen.",
|
||||
"kf-fehler-laenge-ueber-max": "Das Zwischenstueck waere laenger als zulaessig. Bitte kleinere Einbauhoehe waehlen.",
|
||||
"kf-fehler-winkel-null": "Der gemessene Einbauwinkel des Zwischenstuecks ist waagerecht - damit laesst sich keine Hoehe erreichen. Bitte die KS-Lage der Bloecke pruefen (KF_KS_PRUEFEN).",
|
||||
"kf-fehler-dcl": "Dialogdatei kettenfoerderer.dcl nicht gefunden.",
|
||||
"kf-prompt-messpunkt-1": "\nErsten Messpunkt waehlen (Hoehenbezug unten): ",
|
||||
"kf-prompt-messpunkt-2": "\nZweiten Messpunkt waehlen (Hoehenbezug oben): ",
|
||||
"kf-messung-ergebnis": "\n>>> Gemessen: Hoehendifferenz dZ = %1 mm (zur Kontrolle dY = %2 mm).",
|
||||
"kf-konsole-hoehe-hinweis": "\n(0 eingeben, um die Hoehe aus zwei Punkten zu messen)",
|
||||
"kf-2d-gebaut": "\n>>> Draufsicht %1 eingefuegt: Schraeglaenge %2 mm, Neigung %3 Grad.",
|
||||
"kf-2d-laenge-null": "\nDraufsicht uebersprungen: die Kette hat keine messbare Grundrisslaenge.",
|
||||
"kf-2d-ks-fehlt": "\nDraufsicht uebersprungen: %1 hat kein messbares KS_EIN/KS_AUS.",
|
||||
"kf-prompt-startpunkt": "\nEinfuegepunkt waehlen (KS_EIN der Draufsicht; die Seitenansicht entsteht darueber): ",
|
||||
"kf-prompt-drehung": "\nDrehwinkel der Kette: ",
|
||||
"kf-abgebrochen": "\nAbgebrochen.",
|
||||
"kf-fertig": "\n>>> %1 erstellt: Einbauhoehe %2 mm, Zwischenstueck %3 mm.",
|
||||
"kf-konsole-variante-header": "\n\nSchraegfoerderer Stahl Typ waehlen:",
|
||||
"kf-konsole-option": "\n %1 - %2",
|
||||
"kf-konsole-variante-prompt": "\nSchraegfoerderer Stahl Typ",
|
||||
"kf-konsole-hoehe-prompt": "\nH - Einbauhoehe Schraegfoerderer [mm]",
|
||||
"kf-konsole-verbindung-header": "\n\nVerbindungselemente waehlen:",
|
||||
"kf-konsole-verbindung-prompt": "\nVerbindungselemente",
|
||||
"kf-konsole-farbe-header": "\n\nFarbe Foerderer waehlen:",
|
||||
"kf-konsole-farbe-prompt": "\nFarbe",
|
||||
"kf-konsole-antriebsmotor-header": "\n\nAntriebsmotor Foerderer waehlen:",
|
||||
"kf-konsole-antriebsmotor-prompt": "\nAntriebsmotor Foerderer",
|
||||
"kf-variante-label": "%1 %2",
|
||||
"kf-variante-label-standard": "%1 %2 (Standard)",
|
||||
"kf-konsole-movimot-header": "\n\nAntrieb mit Movimot?",
|
||||
"kf-konsole-movimot-prompt": "\nAntrieb mit Movimot",
|
||||
"kf-konsole-steuerung-header": "\n\nMit Standard Steuerung?",
|
||||
"kf-konsole-steuerung-prompt": "\nMit Standard Steuerung",
|
||||
"kf-pruef-kopf": "\n\n=== KF_KS_PRUEFEN: KS-Lage der Kettenfoerderer-Bloecke ===",
|
||||
"kf-pruef-variante": "\n\n--- Variante: %1 ---",
|
||||
"kf-pruef-block": "\n %1: KS_EIN (%2, %3) Richtung %4 | KS_AUS (%5, %6) Richtung %7",
|
||||
"kf-pruef-block-fehlt": "\n %1: Blockdatei nicht gefunden.",
|
||||
"kf-pruef-ks-fehlt": "\n %1: KS unvollstaendig - KS_EIN: %2, KS_AUS: %3",
|
||||
"kf-pruef-ks-fehlt-kurz": "\n[KF] KS_EIN/KS_AUS nicht lesbar am Baustein: %1 (Befehl KF_KS_PRUEFEN zeigt Einzelheiten)",
|
||||
"kf-pruef-fehler": "\n Geometrie nicht ermittelbar: %1",
|
||||
"kf-pruef-geo": "\n Einbauwinkel (Grad): Umlenkung %1, Zwischenstueck %2, Antrieb %3\n Hoehenbeitrag (mm): Umlenkung %4, Antrieb %5\n Zwischenstueck nativ (mm): dx %6, dy %7",
|
||||
"kf-pruef-ja": "vorhanden",
|
||||
"kf-pruef-nein": "FEHLT",
|
||||
"kf-edit-waehlen": "\nKettenfoerderer (KF_n) zum Bearbeiten waehlen: ",
|
||||
"kf-edit-kein-kf": "Der gewaehlte Block ist kein Kettenfoerderer (KF_n).",
|
||||
"kf-edit-fertig": "\n>>> %1 neu aufgebaut als %2.",
|
||||
"cmd-kettenfoerderer-bearbeiten": "\n>>> Kettenfoerderer %1 wird bearbeitet ...",
|
||||
"vfl-m2-nachrechnen": "\n Gefalteter Lauf: Laengen bei gleichem Winkel neu aufgeteilt - GF %1 -> %2 mm, Kletterstrecke %3 mm (GF1 liegt im Eingangs-Schenkel und verbraucht die Kletterer-Spanne nicht).",
|
||||
"vfl-m2-nachrechnen-fehl": "Der gewaehlte Winkel %1 Grad geht mit der korrigierten Laengenbilanz nicht mehr auf. Die Kette wird mit der urspruenglichen Aufteilung gebaut und kann daher am Ende zu frueh enden - bitte den Ist/Soll-Vergleich pruefen oder einen anderen Winkel waehlen."
|
||||
}
|
||||
}
|
||||
+128
-9
@@ -9,6 +9,7 @@
|
||||
"vfl-as-auto-erkannt": "\n>>> Start point lies on the KS_AUS of an existing %1 chain - no AS element needed.",
|
||||
"vfl-familie-neutral": "GF/VF",
|
||||
"vfl-sep-nach-durch-es-ueberschrieben": "\n>>> Separator AFTER ignored - the ES element already brings its own separator at the chain end (otherwise two separators in a row).",
|
||||
"vfl-sep-gf-es-automatisch": "(A separator between GF and ES is inserted automatically.)",
|
||||
"vfl-echo-position": "\n>>> Position: X=%1 Y=%2 Z=%3",
|
||||
"vfl-echo-wahl": "\n>>> Selected: %1",
|
||||
"vfl-aus-seite-header": "\n\nOUT element (AS_Element_*) - select side:",
|
||||
@@ -55,6 +56,27 @@
|
||||
"vfl-gf-laenge-modus-opt-hoehe": "\n 2 - Set target height (length will be calculated)",
|
||||
"vfl-gf-laenge-modus-opt-steigend": "\n 3 - Rising GF (special case, up to 3 degrees)",
|
||||
"vfl-gf-laenge-modus-opt-qc": "\n 4 - QC line with GF (automatic up/down calculation)",
|
||||
"vfl-gf-laenge-modus-opt-parallel": "\n 5 - Continue parallel to the carousel (distance only)",
|
||||
"vfl-richtung-header": "\n\nIn which direction should the chain be built?",
|
||||
"vfl-richtung-opt-vor": "\n 1 - Build forwards (the picked point is the start of the chain)",
|
||||
"vfl-richtung-opt-rueck": "\n 2 - Build backwards (the picked point is the end of the chain, ES outlet)",
|
||||
"vfl-prompt-es-achse-p2": "\n\nTravel direction - 2nd point (defines the direction only, the end point stays): ",
|
||||
"vfl-es-basislinie-info": "\n Outfeed axis (travel direction): %1 degrees.",
|
||||
"vfl-rueck-menu-linie-gf": "\n 1 - New line: GF (gravity section)",
|
||||
"vfl-rueck-laenge-opt-anfangspunkt": "\n 1 - Pick start of chain (length results, start height is calculated)",
|
||||
"vfl-rueck-laenge-opt-anfangshoehe": "\n 2 - Set start height (length will be calculated)",
|
||||
"vfl-rueck-prompt-anfangspunkt": "\n\nPick the start of the chain (direction is fixed by the outfeed axis): ",
|
||||
"vfl-rueck-prompt-anfangshoehe": "\nDesired height at the start of the chain (mm) <%1>: ",
|
||||
"vfl-rueck-alert-hoehe-zu-klein": "The start of the chain must be HIGHER than its end - a gravity section falls in the travel direction.",
|
||||
"vfl-rueck-erfolg-punkt": "\n>>> Built backwards: GF section %1 mm (horizontal), start height %2 mm.",
|
||||
"vfl-rueck-erfolg-hoehe": "\n>>> Built backwards: GF section %1 mm (horizontal), start height %2 mm.",
|
||||
"vfl-rueck-erfolg-parallel": "\n>>> Backwards, parallel to the carousel: GF section %1 mm (horizontal), bend %2 degrees %3.",
|
||||
"vfl-par-prompt-abstand": "\n\nDistance to the carousel (mm, perpendicular to the feed axis, from AS KS_EIN to bend KS_AUS): ",
|
||||
"vfl-par-nur-kettenanfang": "'Parallel to the carousel' only works at the start of a chain with an AS element AND a defined feed axis (2nd point in the AS dialog).",
|
||||
"vfl-par-kein-bogen": "No GF bend cancels the AS plan turn of %1 degrees (side %2) - cannot close parallel to the carousel.",
|
||||
"vfl-par-kein-versatz": "The AS element does not turn away from the feed axis - no distance can be reached this way.",
|
||||
"vfl-par-zu-klein": "Distance %1 mm too small: AS and bend alone already need %2 mm. Please choose a larger distance.",
|
||||
"vfl-par-erfolg": "\n>>> Parallel to the carousel: GF section %1 mm (horizontal), bend %2 degrees %3, resulting distance %4 mm.",
|
||||
"vfl-qc-nur-kettenanfang": "\nERROR: 'QC line with GF' is only possible at the chain start (needs its own AS side) - please choose a different mode.",
|
||||
"vfl-qc-prompt-richtung": "\n\nChoose direction (line on which AS entry and ES exit shall lie) - click a point in the travel direction: ",
|
||||
"vfl-qc-ks-ein-gemessen": "\n>>> AS KS_EIN (reference line) measured: X=%1 Y=%2 Z=%3",
|
||||
@@ -99,6 +121,11 @@
|
||||
"vfl-es-setzen-frage": "\n\nPlace ES element?",
|
||||
"vfl-es-nein-zielpunkt": "\n 2 - No (chain ends directly at the target point)",
|
||||
"vfl-prompt-endpunkt-fahrtrichtung": "\n\nSelect end point along travel direction (defines the length): ",
|
||||
"vfl-prompt-as-achse-p2": "\n\nFeed axis - 2nd point (defines the direction only, the start point stays): ",
|
||||
"vfl-basislinie-punkte-gleich": "\n The two points are identical - no direction can be derived. Aborting.",
|
||||
"vfl-basislinie-info": "\n Feed axis (travel direction): %1 degrees.",
|
||||
"vfl-basislinie-ohne": "\n No feed axis defined - the direction follows from the next click.",
|
||||
"vfl-as-seite-ermittelt": "\n AS side from the position of the next point: %1",
|
||||
"vfl-endpunkt-modus-header": "\n\nHow should the end point be determined?",
|
||||
"vfl-endpunkt-modus-opt-linie": "\n 1 - Draw target line (2 points) - the intersection defines the length",
|
||||
"vfl-prompt-ziellinie-p1": "\n\nTarget line - 1st point (any direction, Z is ignored): ",
|
||||
@@ -122,7 +149,9 @@
|
||||
"vfl-edit-kette-header": "\n\nChain with %1 segment(s):",
|
||||
"vfl-edit-abgespielt": "\n>>> %1 segment(s) replayed, %2 undone - then continue interactively.",
|
||||
"vfl-edit2-reset-info": "\n>>> Rebuilding this Modus-2 chain identically from the saved inputs...",
|
||||
"vfl-konvert-fehler": "\n>>> ERROR converting %1: %2 - the old block is gone, the partial geometry is loose in the drawing.",
|
||||
"vfl-konvert-fehler": "\n>>> ERROR converting %1: %2 - the old block is left unchanged.",
|
||||
"vfl-konvert-grund-journal": "journal is insufficient (%1)",
|
||||
"vfl-konvert-grund-kein-block": "no block created",
|
||||
"vfl-restore-prompt-auswahl": "\nSelect the loose chain geometry (the section XDATA of the objects is read):",
|
||||
"vfl-restore-keine-sektionen": "\n>>> The selection carries no section XDATA (SSG_VF_EDIT_SEG) - no chain can be restored from it.",
|
||||
"vfl-restore-luecke": "\n>>> WARNING: section %1 is missing from the selection - only segments 1..%2 will be restored.",
|
||||
@@ -169,7 +198,7 @@
|
||||
"vfl-soll-xyz": "\n Target: X=%1 Y=%2 Z=%3",
|
||||
"vfl-ist-xyz": "\n Actual: X=%1 Y=%2 Z=%3",
|
||||
"vfl-abweichung-xyz": "\n Deviation: dX=%1 dY=%2 dZ=%3 mm",
|
||||
"vfl-m3-titel": "\n VF LINE PATH - Mode 2: path + target height (finished; anchors + solver + build)",
|
||||
"vfl-m3-titel": "\n VF LINE PATH - Mode 2: from 3D line WITH target height (anchors + solver + build)",
|
||||
"vfl-m3-alert-gf-modul": "Gefaellestrecke module not loaded!",
|
||||
"vfl-m3-pfad-waehlen": "\n\nSelect path objects (lines/arcs):",
|
||||
"vfl-m3-keine-objekte": "\nNo objects selected - aborting.",
|
||||
@@ -224,13 +253,24 @@
|
||||
"vfl-m3-kletter-zu-kurz-flach": "\n No climb angle fits (segment too short) -> run is built entirely flat, height is absorbed by GF1.",
|
||||
"vfl-m3-kletter-flach-gf": "\n Flat zone: GF compensation (GF1) = %1 mm",
|
||||
"vfl-m3-alert-vf-zu-lang": "VF run is %1 m long (limit %2 m) - please re-plan (e.g. insert an intermediate motor station).",
|
||||
"vfl-m2-einheit-grenze": "This VF unit cannot be built like this.\n\nMeasured: %1 m length, %2 vario curves.\nAllowed per unit (between deflection and motor station): at most %3 m and %4 vario curves.\n\nPlease classify the bend in segment %5 as a GF bend - the first unit then ends before it with a motor station and the second one starts after it with a deflection station.",
|
||||
"vfl-m2-einheit-grenze-unteilbar": "This VF unit cannot be built like this.\n\nMeasured: %1 m length, %2 vario curves.\nAllowed per unit (between deflection and motor station): at most %3 m and %4 vario curves.\n\nThere is no bend at which the run could be split - please shorten the path or plan a corner where the unit can end.",
|
||||
"vfl-m3-warnung-fueller-eingang-zu-kurz": "\n WARNING: filler right after the reversing station is too short (%1 mm < minimum %2 mm) - only the minimum clearance was built, target position not reached exactly.",
|
||||
"vfl-m3-warnung-fueller-ausgang-zu-kurz": "\n WARNING: filler right before the motor station is too short (%1 mm < minimum %2 mm) - only the minimum clearance was built, target position not reached exactly.",
|
||||
"vfl-m3-lauf-anfang-header": "\n\nThe VF run is the start of the selected path. Start the run with:",
|
||||
"vfl-m3-lauf-anfang-opt-offen": "\n 1 - No reversing station (open start, continue/merge later)",
|
||||
"vfl-m3-lauf-anfang-opt-offen": "\n 3 - No reversing station (open start, continue/merge later)",
|
||||
"vfl-m3-lauf-anfang-opt-umlenk": "\n 2 - Reversing station directly (no GF1/separator)",
|
||||
"vfl-m3-lauf-anfang-opt-umlenk-gf1": "\n 3 - Reversing station with GF1 + separator",
|
||||
"vfl-m3-lauf-anfang-opt-umlenk-gf1": "\n 1 - Reversing station with GF1 + separator",
|
||||
"vfl-m2-uebergang-bogen-fehlt": "Transition bend %1 is missing from the bend table - the block cannot be loaded or has no measurable KS. The run is built without its length share and therefore comes out too long by that amount.",
|
||||
"vfl-m2-segwert-unbekannt": "Segment %1 cannot be read: chain %2 contains an unknown classification value. Build aborted - guessing a segment type would rebuild the chain incorrectly.",
|
||||
"vfl-m2-eck-korrektur": "\n Corner correction %1 mm on segment %2 (drawn arc versus footprint of the corner component).",
|
||||
"vfl-m2-abschluss-fussabdruck": "\n Closing footprint %1 mm deducted from segment %2 (closing bend + motor station sit on it).",
|
||||
"vfl-m2-kletter-ende-fussabdruck": "\n Climbing end: %1 mm deducted from segment %2 (motor station + separator + ES sit on the climber, not on a filler).",
|
||||
"vfl-m2-as-fussabdruck": "\n AS footprint %1 mm deducted from segment %2 (the AS element sits on it).",
|
||||
"vfl-m2-anfang-wert-unbekannt": "Cannot read run start: chain %1 contains the unknown value %2. Build aborted - guessing a start variant would rebuild the chain incorrectly.",
|
||||
"vfl-m3-lauf-anfang-offen-hinweis": "\n Start deliberately left open - no reversing station/GF1/separator built; continue later or join with Vario_Kette_Merge.",
|
||||
"vfl-m2-anfang-offen-gesperrt-zeile": "\n (not selectable - with an AS element the run needs a reversing station)",
|
||||
"vfl-m2-anfang-offen-gesperrt": "With an AS element an open start is not possible - the run then needs a reversing station.",
|
||||
"vfl-m3-lauf-abschluss-header": "\n\nThe VF run is the end of the selected path. End the run with:",
|
||||
"vfl-m3-lauf-abschluss-opt-offen": "\n 1 - No motor station (open end, continue/merge later)",
|
||||
"vfl-m3-lauf-abschluss-opt-motor": "\n 2 - Set motor station (no ES element)",
|
||||
@@ -246,6 +286,7 @@
|
||||
"vfl-m3-gf2-ausgleich": "\n GF2 (measured compensation): L=%1 mm",
|
||||
"vfl-m3-kurve-back-uebersprungen": "\n >>> [M3a] Vario curve in back run - skipped.",
|
||||
"vfl-m3-nichts-gebaut": "\nNothing built - aborting.",
|
||||
"vfl-m3-alt-journal": "\n Note: this chain predates the build AS / build ES questions - it is rebuilt in the old order.",
|
||||
"vfl-m3-fertig-header": "\n>>> VF line path (mode 2) built! <<<",
|
||||
"vfl-m3-ziel-soll": "\n Target (nominal): X=%1 Y=%2 Z=%3",
|
||||
"vfl-m3-es-ist": "\n ES (actual): X=%1 Y=%2 Z=%3",
|
||||
@@ -280,6 +321,7 @@
|
||||
"kreisel-edit-bestehend": "\n-> Existing: Distance=%1 Rotation=%2 Type=%3",
|
||||
"kreisel-edit-dialog-fehlt": "Dialog not available: %1",
|
||||
"kreisel-eingefuegt": "\n-> Kreisel #%1 inserted: %2 (height=%3)",
|
||||
"kreisel-emsg-abstand-zu-klein": "Distance too small! (%1 < %2) - the end circles would touch/overlap.",
|
||||
"kreisel-emsg-distanz-klein": "Distance too small! (%1 < %2)",
|
||||
"kreisel-hoehe-aus-3dpunkt": "\n-> Height taken from 3D point: %1",
|
||||
"kreisel-hoehe-aus-basispunkt": "\n-> Height taken from base point: %1",
|
||||
@@ -633,6 +675,8 @@
|
||||
"dim-switch-blocks": "\n DXFM_BLOCKS = %1",
|
||||
"dim-switch-omniflo": "\n DXFM_OMNIFLO = %1",
|
||||
"dim-batch-fertig": "\nConversion to %1 complete: %2 GF, %3 VF rebuilt (%4 already in target dimension).",
|
||||
"dim-batch-fehlerliste": "\n%1 polyline block(s) NOT converted (left unchanged):",
|
||||
"dim-batch-fehler-zeile": "\n - %1: %2",
|
||||
"sprache-gewechselt": "\nLanguage switched to: %1",
|
||||
"cmd-block-auswaehlen": "\nSelect block: ",
|
||||
"cmd-kein-block-ausgewaehlt": "\nNo block selected.",
|
||||
@@ -685,6 +729,9 @@
|
||||
"plq-geloescht": "\n[DELETE_PLANQUADRATE] Planquadrat grid removed (%1 insertion(s)).",
|
||||
"plq-nichts-zu-loeschen": "\n[DELETE_PLANQUADRATE] No Planquadrat grid found in the drawing.",
|
||||
"exp-check-ids": "\n[%1] Checking and assigning IDs...",
|
||||
"exp-hoehencheck-frage": "\nRun the height check (mounting height/platforms) before the export?",
|
||||
"exp-bereinigen": "\nPurging drawing (unused blocks, layers, linetypes) ...",
|
||||
"exp-hoehencheck-fehlt": "\nNote: HOEHEN_CHECK not available - export runs without height check.",
|
||||
"exp-hoehen-aktualisiert": "\nHeight attributes of %1 moved blocks reset from their Z coordinate.",
|
||||
"exp-sep-proxy-fehler": "\n[EXPORT] WARNING: copying '%1' out of block '%2' failed (%3) - this element is missing from the export.",
|
||||
"exp-sep-zuordnung": "\n[%1] packed separator copy/copies: ZUORDNUNG set from the wrapper block ID.",
|
||||
@@ -913,6 +960,16 @@
|
||||
"tro-insert-kein-block": "No symbol for this type in the drawing (%1) - run tro_annotate.py with this type first.",
|
||||
"tro-insert-prompt-punkt": "\nInsertion point: ",
|
||||
"tro-insert-eingefuegt": "\nTRO inserted: ID = %1, TYPE = %2",
|
||||
"cmd-jam-bearbeiten": "\nEdit jam area: %1",
|
||||
"jam-edit-kein-jam": "Block %1 is not a jam area (expected JAM_*).",
|
||||
"jam-edit-dialog-fehlt": "Dialog file not found:\n%1\nCheck DXFM_DCL (setenv.bat).",
|
||||
"jam-edit-bereich": "Jam area %1 in front of %2 (entry %3)",
|
||||
"jam-edit-auto": "Derived: %1",
|
||||
"jam-edit-hinweis": "Into the SCL: tro_annotate --read-jams, then scl_skeleton.",
|
||||
"jam-edit-foerderer-ungueltig": "The conveyor must have four digits (e.g. 0054) - nothing changed.",
|
||||
"jam-edit-nummer-ungueltig": "The running number must be a whole number from 1 - nothing changed.",
|
||||
"jam-edit-gespeichert": "\nJam area saved: %1 (%2)",
|
||||
"jam-edit-doppelt": "\nWARNING: %1 already exists in this drawing (%2).",
|
||||
"vfl-abbruch-gesichert": "\n>>> Chain cancelled: %1 object(s) saved as a block (editable/resumable via double-click).",
|
||||
"vfl-zurueck-glied-verworfen": "\n>>> Back: discarding the last chain element - please answer it again.",
|
||||
"vfl-abbruch-nichts-gebaut": "\n>>> Cancelled - no geometry was created yet.",
|
||||
@@ -929,13 +986,13 @@
|
||||
"vfc-warnung-untermodule-nicht-geladen": "\n[vf_core] WARNING: DXFM_LISP not set - submodules could not be loaded!",
|
||||
"vfc-linienzug-modus-header": "\n\nSelect line-path mode:",
|
||||
"vfc-linienzug-modus-1": "\n 1 - Manual entry (click points)",
|
||||
"vfc-linienzug-modus-2": "\n 2 - 3D objects + target height (boundary-value solver, finished)",
|
||||
"vfc-linienzug-modus-3": "\n 3 - 3D objects step by step (forward reconstruction, work in progress)",
|
||||
"vfc-linienzug-modus-2": "\n 2 - from 3D line WITH target height (heights are calculated)",
|
||||
"vfc-linienzug-modus-3": "\n 3 - from 3D line WITHOUT target height (forward build with given angles)",
|
||||
"prompt-wahl-1-3": "\nYour choice (1/2/3) [1]: ",
|
||||
"vfl-qc-uform-nicht-implementiert": "\nERROR: 'QC line with GF and U-shape' is not yet implemented - please choose option 4 or a different mode.",
|
||||
"vfc-typ-standard-beschreibung": "Standard VarioFoerderer (AS/ES 90 degrees, offset horizontally)",
|
||||
"vfc-typ-etage-beschreibung": "Etage VarioFoerderer (AS/ES 30 degrees, directly stacked)",
|
||||
"vfc-typ-linienzug-beschreibung": "Route group (mixed GF/VF chain; mode 1 manual / mode 2 target height finished / mode 3 step by step work in progress)",
|
||||
"vfc-typ-linienzug-beschreibung": "Route group (mixed GF/VF chain; mode 1 manual / mode 2 from 3D line with target height / mode 3 from 3D line without target height)",
|
||||
"vfs-schritt6-horizontal": "\n\n6/11: Horizontal intermediate section (0 deg, L=%1 mm)",
|
||||
"vfs-schritt6-steigung": "\n\n6/11: Incline section (%1 deg, L=%2 mm)",
|
||||
"vfs-schritt6-gefaelle": "\n\n6/11: Slope section (%1 deg, L=%2 mm)",
|
||||
@@ -964,7 +1021,7 @@
|
||||
"vfe-step14": "\n\n14/15: Separator (300mm, cur-hz=%1)",
|
||||
"vfe-step15": "\n\n15/15: %1 (end, chained cur-hz=%2)",
|
||||
"vfe-eingefuegt": "\n>>> Etage VarioFoerderer inserted! <<<",
|
||||
"vfl-vwnb-titel": "\n VF LINE PATH - Mode 3: 3D objects step by step (forward reconstruction, work in progress)",
|
||||
"vfl-vwnb-titel": "\n VF LINE PATH - Mode 3: from 3D line WITHOUT target height (forward build)",
|
||||
"vfl-vwnb-aus-seite-menu": "\n\nOUT element - select side:\n 1 - Left\n 2 - Right",
|
||||
"vfl-vwnb-alert-eckwinkel": "No matching arc: corner angle %1 deg is not ~30/60/90.\nPlease adjust the angles of the lines.",
|
||||
"vfl-vwnb-alert-keine-gerade": "Path contains no straight - a chain must begin with a straight.",
|
||||
@@ -1120,6 +1177,16 @@
|
||||
"kreisel-bp-zeile": "\n Switch %1: %2 <-> %3 [%4] at X=%5 Y=%6 Z=%7",
|
||||
"kreisel-bp-kollision": "\n COLLISION %1: %2 <-> %3 [%4] at X=%5 Y=%6 Z=%7",
|
||||
"kreisel-bp-marker": "\n%1 markers drawn (layer %2).",
|
||||
"chh-start": "\n--- Phase 3: platform families ---",
|
||||
"chh-kein-kreisel": "\n Note: Kreisel module not available - per-block questions only.",
|
||||
"chh-fam-frage": "\n Family %1 (%2, %3 Kreisel, mounting height %4 m): is it on a platform?",
|
||||
"chh-schleife": "\n %1: flat loop on the same Kreisel (VON = BIS) - asked individually.",
|
||||
"chh-buehne-hoehe": "Platform height in m",
|
||||
"chh-buehne-ungueltig": "\n ! Platform height must be > 0 and < %1 m.",
|
||||
"chh-kreuz-konflikt": "\n ! %1: ends in families with different platform heights (%2 / %3 m) - unchanged.",
|
||||
"chh-kreuz-hoehe": "\n ! %1: family heights differ by %2 mm (> %3 mm) - unchanged.",
|
||||
"chh-strecke-neg": "\n ! %1: platform %2 m >= mounting height %3 m - unchanged.",
|
||||
"chh-summe": "\n Phase 3: %1 family(ies), %2 on a platform; adjusted: Kreisel %3, sections within family %4, between families %5; conflicts %6; asked individually %7",
|
||||
"exp-kreisel-weichen": "\n[%1] Kreisel switch points: %2 contact(s), %3 collision(s) -> %4",
|
||||
"exp-kreisel-kollision": "\n[%1] WARNING: %2 Kreisel collision(s) - command KREISEL_WEICHEN shows them.",
|
||||
"lg-daten-fehlt": "\n[Storage] Data file not found: %1 - built-in defaults apply.",
|
||||
@@ -1219,6 +1286,58 @@
|
||||
"lg-regel-profil-fehlt": "\n[Storage] Rule profile %1 not found (%2).",
|
||||
"lg-regel-profil-ungepflegt": "\n[Storage] WARNING: rule profile %1 is not maintained - inherited values apply.",
|
||||
"lg-regel-unbekannt": "\n[Storage] Rule %1 not in profile.",
|
||||
"lg-regel-liste-kopf": "\nRule profile %1: %2 rules (context: increased fire risk without extinguishing system)"
|
||||
"lg-regel-liste-kopf": "\nRule profile %1: %2 rules (context: increased fire risk without extinguishing system)",
|
||||
"kf-fehler-daten-fehlt": "\nERROR: chain conveyor data not found: %1",
|
||||
"kf-fehler-daten-leer": "\nERROR: chain conveyor data could not be read.",
|
||||
"kf-fehler-block-datei": "\nERROR: block file for %1 not found (expected in data/omniflo/<dimension>/).",
|
||||
"kf-fehler-ks-fehlt": "At least one component is missing KS_EIN or KS_AUS - the chain cannot be linked. Command KF_KS_PRUEFEN shows which block is affected.",
|
||||
"kf-fehler-hoehe-zu-klein": "The installation height is too small: the deflection and drive stations already contribute more height than requested. Please choose a greater height.",
|
||||
"kf-fehler-laenge-unter-min": "The intermediate section would be shorter than permitted. Please choose a greater installation height.",
|
||||
"kf-fehler-laenge-ueber-max": "The intermediate section would be longer than permitted. Please choose a smaller installation height.",
|
||||
"kf-fehler-winkel-null": "The measured installation angle of the intermediate section is horizontal - no height can be gained. Please check the KS positions of the blocks (KF_KS_PRUEFEN).",
|
||||
"kf-fehler-dcl": "Dialog file kettenfoerderer.dcl not found.",
|
||||
"kf-prompt-messpunkt-1": "\nSelect first measuring point (lower reference): ",
|
||||
"kf-prompt-messpunkt-2": "\nSelect second measuring point (upper reference): ",
|
||||
"kf-messung-ergebnis": "\n>>> Measured: height difference dZ = %1 mm (for reference dY = %2 mm).",
|
||||
"kf-konsole-hoehe-hinweis": "\n(enter 0 to measure the height from two points)",
|
||||
"kf-2d-gebaut": "\n>>> Plan view %1 inserted: slope length %2 mm, inclination %3 deg.",
|
||||
"kf-2d-laenge-null": "\nPlan view skipped: the chain has no measurable plan length.",
|
||||
"kf-2d-ks-fehlt": "\nPlan view skipped: %1 has no measurable KS_EIN/KS_AUS.",
|
||||
"kf-prompt-startpunkt": "\nSelect insertion point (KS_EIN of the plan view; the side view is built above it): ",
|
||||
"kf-prompt-drehung": "\nRotation angle of the chain: ",
|
||||
"kf-abgebrochen": "\nCancelled.",
|
||||
"kf-fertig": "\n>>> %1 created: installation height %2 mm, intermediate section %3 mm.",
|
||||
"kf-konsole-variante-header": "\n\nSelect inclined steel conveyor type:",
|
||||
"kf-konsole-option": "\n %1 - %2",
|
||||
"kf-konsole-variante-prompt": "\nInclined steel conveyor type",
|
||||
"kf-konsole-hoehe-prompt": "\nH - installation height of inclined conveyor [mm]",
|
||||
"kf-konsole-verbindung-header": "\n\nSelect connecting elements:",
|
||||
"kf-konsole-verbindung-prompt": "\nConnecting elements",
|
||||
"kf-konsole-farbe-header": "\n\nSelect conveyor colour:",
|
||||
"kf-konsole-farbe-prompt": "\nColour",
|
||||
"kf-konsole-antriebsmotor-header": "\n\nSelect conveyor drive motor:",
|
||||
"kf-konsole-antriebsmotor-prompt": "\nConveyor drive motor",
|
||||
"kf-variante-label": "%1 %2",
|
||||
"kf-variante-label-standard": "%1 %2 (default)",
|
||||
"kf-konsole-movimot-header": "\n\nDrive with Movimot?",
|
||||
"kf-konsole-movimot-prompt": "\nDrive with Movimot",
|
||||
"kf-konsole-steuerung-header": "\n\nWith standard control system?",
|
||||
"kf-konsole-steuerung-prompt": "\nWith standard control system",
|
||||
"kf-pruef-kopf": "\n\n=== KF_KS_PRUEFEN: KS positions of the chain conveyor blocks ===",
|
||||
"kf-pruef-variante": "\n\n--- Variant: %1 ---",
|
||||
"kf-pruef-block": "\n %1: KS_EIN (%2, %3) direction %4 | KS_AUS (%5, %6) direction %7",
|
||||
"kf-pruef-block-fehlt": "\n %1: block file not found.",
|
||||
"kf-pruef-ks-fehlt": "\n %1: KS incomplete - KS_EIN: %2, KS_AUS: %3",
|
||||
"kf-pruef-ks-fehlt-kurz": "\n[KF] KS_EIN/KS_AUS not readable on component: %1 (command KF_KS_PRUEFEN shows details)",
|
||||
"kf-pruef-fehler": "\n Geometry could not be determined: %1",
|
||||
"kf-pruef-geo": "\n Installation angles (deg): deflection %1, intermediate %2, drive %3\n Height contribution (mm): deflection %4, drive %5\n Intermediate section native (mm): dx %6, dy %7",
|
||||
"kf-pruef-ja": "present",
|
||||
"kf-pruef-nein": "MISSING",
|
||||
"kf-edit-waehlen": "\nSelect chain conveyor (KF_n) to edit: ",
|
||||
"kf-edit-kein-kf": "The selected block is not a chain conveyor (KF_n).",
|
||||
"kf-edit-fertig": "\n>>> %1 rebuilt as %2.",
|
||||
"cmd-kettenfoerderer-bearbeiten": "\n>>> Editing chain conveyor %1 ...",
|
||||
"vfl-m2-nachrechnen": "\n Folded run: lengths redistributed at the same angle - GF %1 -> %2 mm, climbing section %3 mm (GF1 sits in the entry leg and does not consume the climber span).",
|
||||
"vfl-m2-nachrechnen-fehl": "The chosen angle of %1 degrees no longer works with the corrected length balance. The chain is built with the original distribution and may therefore end too early - please check the actual/target comparison or pick a different angle."
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ Edit-Befehl (Doppelklick) zum Neuaufbau liest. Typischer Ablauf: Scanner-
|
||||
Vorlage nachbauen, in BricsCAD von Hand korrigieren/ergaenzen, Zeichnung als
|
||||
DXF speichern und mit diesem Skript die Testdaten aktualisieren.
|
||||
|
||||
Je Wrapper (Felder wie in tests/testdata/object_data.md bzw. mubea.json):
|
||||
Je Wrapper (Felder wie in doc/json-input-lisp.md bzw. mubea.json):
|
||||
|
||||
KREISEL_n -> Kreisel ("function": "insert", x/y/z = Einfuegepunkt,
|
||||
abstand = Mittenabstand AN8-SP8 aus der Blockdefinition,
|
||||
|
||||
@@ -6,7 +6,7 @@ dxf_scan_components.py - Erkennt ILS-/Omniflo-Komponenten in einem FREMDEN DXF.
|
||||
Gedacht fuer Projekt-Zeichnungen, die NICHT von unseren Makros erzeugt wurden
|
||||
(also ohne die Wrapper-Bloecke KREISEL_*, VF_*, GF_*). Das Skript sucht die
|
||||
Bauteile ueber Blocknamen-Muster, rechnet ihre Position in Weltkoordinaten um
|
||||
und schreibt das Ergebnis im JSON-Schema aus tests/testdata/object_data.md -
|
||||
und schreibt das Ergebnis im JSON-Schema aus doc/json-input-lisp.md -
|
||||
also so, dass die Anlage per JSON-Treiber mit den Produktionsmakros
|
||||
nachgebaut werden kann (Vorbild: tests/testdata/mubea.json, das bisher von
|
||||
Hand aus einem DXF abgeleitet wurde).
|
||||
@@ -1697,7 +1697,7 @@ def gf_eintraege_aus_linien(linien, as_liste, kreisel=None, sep_liste=None,
|
||||
def baue_eintraege(treffer, defaults, boegen, weichen,
|
||||
bekannte_bloecke=None, linien=None, kreisel_hoehen=None,
|
||||
kreisel_achsen=None, flach=False):
|
||||
"""Erkannte Vorkommen auf die Schemata aus object_data.md abbilden.
|
||||
"""Erkannte Vorkommen auf die Schemata aus json-input-lisp.md abbilden.
|
||||
|
||||
kreisel_hoehen: Liste (x, y, z) vom Anwender - z gilt fuer den Kreisel,
|
||||
dessen Einfuegepunkt (Eintrag x/y) hoechstens KREISEL_HOEHE_TOL entfernt
|
||||
@@ -2082,7 +2082,7 @@ def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Erkennt ILS-/Omniflo-Komponenten in einem fremden DXF "
|
||||
"und schreibt sie im JSON-Schema aus "
|
||||
"tests/testdata/object_data.md.")
|
||||
"doc/json-input-lisp.md.")
|
||||
parser.add_argument("dxf", help="Quellzeichnung (binaeres oder ASCII-DXF)")
|
||||
parser.add_argument("data_dir", help="Datenverzeichnis mit json/")
|
||||
parser.add_argument("output", help="Ziel-JSON")
|
||||
|
||||
@@ -42,6 +42,7 @@ from export_neighbors import (
|
||||
compute_kreisel_touch_switches,
|
||||
lisp_touch_switches,
|
||||
load_lisp_kreisel_weichen,
|
||||
einsortieren_freie_separatoren,
|
||||
compute_sep_kette,
|
||||
compute_kreisel_umlauf,
|
||||
SENSOR_TEILEARTEN,
|
||||
@@ -1543,6 +1544,12 @@ def process_blocks(blocks, lookup, dbg=None, lisp_weichen=None):
|
||||
if item.get("teileart", "") == "ILS 2.0 Scanner" and separator_id:
|
||||
item["merkmale"]["Naechster Separator"] = separator_id
|
||||
|
||||
# Freie Separatoren, deren Zuordnung eine VF_n/GF_n nennt, die aber nicht
|
||||
# beim Bau der Strecke entstanden sind (fehlen darum in ihrer sepliste),
|
||||
# nach Lage in die Kette aufnehmen - nur fuer diesen Lauf, die XDATA am
|
||||
# Block bleibt unveraendert (siehe einsortieren_freie_separatoren).
|
||||
einsortieren_freie_separatoren(items, NEIGHBOR_TOLERANCE_MM, dbg=dbg)
|
||||
|
||||
# Ketteninterne Separator-/AS-/ES-Reihenfolge aus der neuen "sepliste"-
|
||||
# XDATA (siehe ssg-sepliste-xdata-schreiben) - leeres dict, wenn keine
|
||||
# Strecke eine sepliste traegt (reiner Altbestand ohne neue XDATA).
|
||||
|
||||
@@ -1255,6 +1255,194 @@ def _asel_collision_boxes(item, half_tol, box_dims):
|
||||
# Ersetzt das bisherige Raten der Ketten-internen Reihenfolge (die Linie
|
||||
# selbst wird nicht exportiert) durch die tatsaechliche Bau-Reihenfolge.
|
||||
|
||||
def sepliste_einsortier_positionen(kette_xy, kandidaten):
|
||||
"""Reiner Rechenkern fuer einsortieren_freie_separatoren: wohin gehoert
|
||||
jeder Kandidat in eine vorhandene Kette?
|
||||
|
||||
kette_xy = [(x, y), ...] Lage der Kettenglieder in Kettenfolge (AS ...
|
||||
ES), mindestens zwei Punkte. Sie bilden einen Polygonzug - so
|
||||
folgt die Zuordnung auch einer Kette, die um eine Kurve laeuft,
|
||||
statt nur einer Geraden AS->ES.
|
||||
kandidaten = [(key, x, y), ...]
|
||||
|
||||
Jeder Kandidat wird dem naechstgelegenen Abschnitt (Glied i -> i+1)
|
||||
zugeordnet. Liegt er dabei VOR dem ersten oder HINTER dem letzten Glied,
|
||||
wird er verworfen - eingefuegt wird nur zwischen AS und ES.
|
||||
|
||||
Rueckgabe (einfuegen, verworfen): einfuegen = {i: [key, ...]} - nach
|
||||
Glied i einzufuegen, untereinander in Kettenrichtung sortiert;
|
||||
verworfen = [key, ...].
|
||||
"""
|
||||
abschnitte = []
|
||||
for i in range(len(kette_xy) - 1):
|
||||
(ax, ay), (bx, by) = kette_xy[i], kette_xy[i + 1]
|
||||
dx, dy = bx - ax, by - ay
|
||||
l2 = dx * dx + dy * dy
|
||||
if l2 > 1e-12:
|
||||
abschnitte.append((i, ax, ay, dx, dy, l2))
|
||||
letzter = len(kette_xy) - 2
|
||||
|
||||
einfuegen = {}
|
||||
verworfen = []
|
||||
for key, x, y in kandidaten:
|
||||
best = None
|
||||
for i, ax, ay, dx, dy, l2 in abschnitte:
|
||||
t = ((x - ax) * dx + (y - ay) * dy) / l2
|
||||
tc = min(max(t, 0.0), 1.0)
|
||||
d = math.hypot(x - (ax + tc * dx), y - (ay + tc * dy))
|
||||
if best is None or d < best[0] - 1e-9:
|
||||
best = (d, i, t)
|
||||
if best is None:
|
||||
verworfen.append(key)
|
||||
continue
|
||||
_d, i, t = best
|
||||
if (i == 0 and t <= 0.0) or (i == letzter and t >= 1.0):
|
||||
verworfen.append(key)
|
||||
continue
|
||||
einfuegen.setdefault(i, []).append((min(max(t, 0.0), 1.0), key))
|
||||
|
||||
return ({i: [key for _t, key in sorted(liste)] for i, liste in einfuegen.items()},
|
||||
verworfen)
|
||||
|
||||
|
||||
def _kettenglied_xy(entry, item, strecke):
|
||||
"""Lage eines sepliste-Glieds fuer den Polygonzug: AS/ES ueber K1/K2 der
|
||||
Strecke (Ein-/Auslauf - der ZZ_ASES_MARKER sitzt auf dem Einfuegepunkt
|
||||
des Elements und kann bis ~600 mm seitlich davon liegen), sonst bzw.
|
||||
ohne K1/K2 der Bounding-Box-Mittelpunkt des vertretenden Items."""
|
||||
typ = entry.get("typ", "")
|
||||
if typ in ("AS", "ES"):
|
||||
k1_xy, k2_xy = _asel_kos_xy(strecke)
|
||||
pt = k1_xy if typ == "AS" else k2_xy
|
||||
if pt is not None:
|
||||
return pt
|
||||
bbox = (item or {}).get("_bbox")
|
||||
if not bbox:
|
||||
return None
|
||||
return (bbox.get("cx", 0.0), bbox.get("cy", 0.0))
|
||||
|
||||
|
||||
def einsortieren_freie_separatoren(items, tolerance_mm, dbg=None):
|
||||
"""Nimmt freie Separatoren in die sepliste ihrer VF_n/GF_n-Strecke auf.
|
||||
|
||||
Die sepliste entsteht beim BAU der Strecke (ssg-sepliste-sammeln) und
|
||||
kennt nur die Separatoren, die dabei erzeugt wurden. Ein eigenstaendiger
|
||||
Separator_SP-Block, der spaeter (oder aus einer frueheren Fassung der
|
||||
Strecke) auf ihr liegt, fehlt darin - obwohl seine ZUORDNUNG
|
||||
(cs-zuordnung-lauf) die Strecke nennt. Ohne diesen Schritt fehlt er in
|
||||
TrackIds und Nachbarn (realer Fall Mubea VF_3: 0037/0038 zwischen 0062
|
||||
und 0063).
|
||||
|
||||
Aufgenommen wird ein Separator nur, wenn
|
||||
- seine Zuordnung die Strecke nennt,
|
||||
- er in keiner sepliste steht,
|
||||
- sein Mittelpunkt in der Bounding-Box der Strecke liegt (+ tolerance_mm/2),
|
||||
- er laengs der Kette zwischen AS und ES liegt
|
||||
(sepliste_einsortier_positionen).
|
||||
|
||||
Bewusst NUR im Speicher dieses Exportlaufs: die sepliste-XDATA am Block
|
||||
bleibt das Bauprotokoll. Lisp ordnet ihre Eintraege den eingebauten
|
||||
Bausteinen ueber die Anzahl je Typ zu (csv:sepliste-kette-paare) und
|
||||
fuehrt reservierte AS/ES-IDs unter der lfdnr - ein in die XDATA
|
||||
eingefuegter fremder Separator verschoebe beides. Ausserdem schreibt jeder
|
||||
Neuaufbau der Strecke die XDATA neu; hier wird bei jedem Export frisch
|
||||
aus dem aktuellen Zeichnungsstand gerechnet.
|
||||
|
||||
Aendert items in-place: item["sepliste"] der Strecke bekommt neue
|
||||
SEP-Eintraege (lfdnr "frei<TeileId>", "id" = TeileId des Separators,
|
||||
"frei": True); der Separator bekommt "_in_strecke_kette" (Strecken-
|
||||
TeileId, damit compute_kreisel_umlauf ihn nicht zusaetzlich einem
|
||||
Kreisel zuschlaegt), das Merkmal "Einsortiert in" (Strecken-TeileId,
|
||||
in der CSV-Spalte Merkmale) und einen Hinweis in "warnung".
|
||||
Muss NACH der Separator-Zuordnung und VOR compute_sep_kette laufen.
|
||||
"""
|
||||
half_tol = tolerance_mm / 2.0
|
||||
by_teileid = {it.get("teileid", ""): it for it in items if it.get("teileid", "")}
|
||||
in_ketten = set()
|
||||
for it in items:
|
||||
if it.get("teileart", "") in GF_VF_TEILEARTEN:
|
||||
for e in it.get("sepliste") or []:
|
||||
eid = str(e.get("id", "")).strip()
|
||||
if eid:
|
||||
in_ketten.add(eid)
|
||||
|
||||
if dbg:
|
||||
dbg("=== einsortieren_freie_separatoren ===")
|
||||
|
||||
for strecke in items:
|
||||
if strecke.get("teileart", "") not in GF_VF_TEILEARTEN:
|
||||
continue
|
||||
sepliste = strecke.get("sepliste")
|
||||
sbbox = strecke.get("_bbox")
|
||||
if not sepliste or not sbbox:
|
||||
continue
|
||||
sid = strecke.get("teileid", "")
|
||||
sbounds = _bounds(sbbox, half_tol)
|
||||
|
||||
kandidaten = []
|
||||
for it in items:
|
||||
if it.get("teileart", "") != "ILS 2.0 Separator":
|
||||
continue
|
||||
tid = it.get("teileid", "")
|
||||
if not tid or tid in in_ketten:
|
||||
continue
|
||||
zuordnung = ((it.get("merkmale") or {}).get("Zuordnung")
|
||||
or it.get("_zuordnung_attr") or "").strip()
|
||||
if zuordnung != sid:
|
||||
continue
|
||||
bbox = it.get("_bbox")
|
||||
if not bbox:
|
||||
continue
|
||||
cx, cy = bbox.get("cx", 0.0), bbox.get("cy", 0.0)
|
||||
if not (sbounds[0] <= cx <= sbounds[1] and sbounds[2] <= cy <= sbounds[3]):
|
||||
if dbg:
|
||||
dbg(f" Strecke {sid}: Separator {tid} ausserhalb der Strecken-BBox "
|
||||
f"- nicht einsortiert")
|
||||
continue
|
||||
kandidaten.append((tid, cx, cy))
|
||||
if not kandidaten:
|
||||
continue
|
||||
|
||||
kette_xy = []
|
||||
for e in sepliste:
|
||||
pt = _kettenglied_xy(e, by_teileid.get(str(e.get("id", "")).strip()), strecke)
|
||||
if pt is None:
|
||||
break
|
||||
kette_xy.append(pt)
|
||||
if len(kette_xy) != len(sepliste) or len(kette_xy) < 2:
|
||||
if dbg:
|
||||
dbg(f" Strecke {sid}: Kettenglieder nicht vollstaendig lokalisierbar "
|
||||
f"- freie Separatoren {[k[0] for k in kandidaten]} nicht einsortiert")
|
||||
continue
|
||||
|
||||
einfuegen, verworfen = sepliste_einsortier_positionen(kette_xy, kandidaten)
|
||||
if dbg and verworfen:
|
||||
dbg(f" Strecke {sid}: {verworfen} liegen nicht zwischen AS und ES "
|
||||
f"- nicht einsortiert")
|
||||
if not einfuegen:
|
||||
continue
|
||||
|
||||
neu = []
|
||||
for i, entry in enumerate(sepliste):
|
||||
neu.append(entry)
|
||||
for tid in einfuegen.get(i, []):
|
||||
neu.append({"typ": "SEP", "lfdnr": f"frei{tid}", "id": tid, "frei": True})
|
||||
sep = by_teileid[tid]
|
||||
sep["_in_strecke_kette"] = sid
|
||||
# Fuer Folgewerkzeuge (sps_skel: sepliste-Gegenprobe): dieser
|
||||
# Separator steht in TrackIds, aber nicht im Bauprotokoll.
|
||||
sep.setdefault("merkmale", {})["Einsortiert in"] = sid
|
||||
hinweis = (f"nicht im Bau von {sid} erzeugt - per Lage in dessen "
|
||||
f"Kette einsortiert")
|
||||
bisherige = sep.get("warnung", "")
|
||||
sep["warnung"] = f"{bisherige}; {hinweis}" if bisherige else hinweis
|
||||
in_ketten.add(tid)
|
||||
strecke["sepliste"] = neu
|
||||
if dbg:
|
||||
dbg(f" Strecke {sid}: Kette jetzt "
|
||||
f"{' -> '.join(str(e.get('id', '')) for e in neu)}")
|
||||
|
||||
|
||||
def compute_sep_kette(items, dbg=None):
|
||||
"""Baut je VF_n/GF_n-Item MIT "sepliste" die ketteninterne Vorgaenger-/
|
||||
Nachfolger-Beziehung AS -> Sep1 -> ... -> SepN -> ES.
|
||||
@@ -1392,6 +1580,11 @@ def compute_kreisel_umlauf(items, tolerance_mm, durchmesser_mm=800.0,
|
||||
for item in items:
|
||||
if item.get("teileart", "") not in KREISEL_UMLAUF_TEILEARTEN:
|
||||
continue
|
||||
# Freier Separator, den einsortieren_freie_separatoren in die Kette
|
||||
# einer Strecke aufgenommen hat - gehoert nicht zusaetzlich auf einen
|
||||
# Kreisel, auch wenn seine Box einen beruehrt.
|
||||
if item.get("_in_strecke_kette"):
|
||||
continue
|
||||
teileid = item.get("teileid", "")
|
||||
bbox = item.get("_bbox")
|
||||
if not bbox:
|
||||
|
||||
+243
-3
@@ -58,6 +58,7 @@ items_zusammenfassen. output.csv selbst bleibt unveraendert.
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
from export_blockpatterns import (load_patterns, load_export_cfg, cfg_path_from_env,
|
||||
matches_any, csv_quote, safe_float, safe_int)
|
||||
@@ -101,14 +102,36 @@ def get_id(block):
|
||||
# Sprachdatei, da rein Sivas-seitig.
|
||||
GERUEST_TYP_ANZEIGE = sivas_mapping.load_flat_mapping("geruest_typ_anzeige")
|
||||
|
||||
# Kettenfoerderer: Attribut WINKEL fuehrt den Neigungswinkel als nackte Zahl
|
||||
# ("26"/"30"), Sivas-Merkmal 359 erwartet den Optionstext mit Gradzeichen.
|
||||
# Gleiche Bauart und derselbe Grund wie GERUEST_TYP_ANZEIGE.
|
||||
KF_TYP_ANZEIGE = sivas_mapping.load_flat_mapping("kf_typ_anzeige")
|
||||
|
||||
# TeileArt-Spalte der Kettenfoerderer-Zeilen. Fester Wert statt Block-Attribut:
|
||||
# er ist fuer jeden Kettenfoerderer gleich, stuende also an jedem Block nur
|
||||
# redundant herum. Die Erkennung laeuft ueber den Blocknamen
|
||||
# (pattern_kettenfoerderer), nicht ueber TEILEART. Ein Block, der das Attribut
|
||||
# doch mitbringt (Altbestand), hat weiterhin Vorrang.
|
||||
KF_TEILEART = "Schraegfoerderer Stahl"
|
||||
|
||||
SEPARATOR_BEARBEITUNG_ANZEIGE = "ohne HARTCOAT HRC 50 ± 5"
|
||||
|
||||
# Sivas-Merkmale "Streckengruppe - Variofoerderer 001..005 - Hoehe in Meter".
|
||||
# Reihenfolge = Bau-Reihenfolge der Foerdereinheiten in VF_HOEHE_m.
|
||||
VF_HOEHE_MERKMALE = ("4433", "4434", "4435", "4436", "4437")
|
||||
|
||||
|
||||
def geruest_typ_anzeige(wert):
|
||||
"""Wandelt den ASCII-Attributwert GERUEST_TYP in die Sivas-Anzeige um."""
|
||||
return GERUEST_TYP_ANZEIGE.get(wert, wert)
|
||||
|
||||
|
||||
def kf_typ_anzeige(wert):
|
||||
"""Wandelt den Kettenfoerderer-Winkel ("26"/"30") in die Sivas-Anzeige
|
||||
zu Merkmal 359 um ("Schrägförderer Stahl 26°")."""
|
||||
return KF_TYP_ANZEIGE.get(str(wert).strip(), wert)
|
||||
|
||||
|
||||
def ja_nein(flag_1_0):
|
||||
"""Wandelt ein "0"/"1"-Attribut in die Sivas-Anzeige "Ja"/"Nein" um."""
|
||||
return "Ja" if flag_1_0 == "1" else "Nein"
|
||||
@@ -120,14 +143,95 @@ def mm_zu_m(wert_mm):
|
||||
return str(round(safe_float(wert_mm, 0.0) / 1000.0, 3))
|
||||
|
||||
|
||||
# --- AS-/ES-Element (Merkmale 4427-4432) ---------------------------------
|
||||
# Zuordnung komplett in cfg/sivas.cfg ([gefaellestrecke]/[variofoerderer]),
|
||||
# hier stehen nur die Transforms. Die Sivas-Hierarchie ist: 4431/4432
|
||||
# ("AS-Element"/"ES-Element", Ja/Nein) schalten die Unterknoten Winkel
|
||||
# (4427/4429) und Seite (4428/4430) frei.
|
||||
#
|
||||
# Ob ein Element vorhanden ist, entscheidet AUSSCHLIESSLICH WINKEL_AS/
|
||||
# WINKEL_ES: das gemeinsame Strecken-Schema (*strecke-attr-front* in
|
||||
# ssg_core.lsp) laesst den Winkel leer, wenn kein Element gewaehlt wurde.
|
||||
# SEITE_AS/SEITE_ES taugen dafuer NICHT - sie tragen mit "rechts" immer einen
|
||||
# Schema-Vorgabewert. Ohne Element bleiben Winkel UND Seite leer, damit in
|
||||
# Sivas keine Seite unter einem "Nein"-Knoten haengt.
|
||||
|
||||
# Attributwert -> Sivas-Optionswert der Auswahlliste ("30"/"90" -> "30 °"/
|
||||
# "90 °", siehe Merkmalstamm). Wie [geruest_typ_anzeige] in der Config, damit
|
||||
# die exakte Schreibweise ohne Code-Aenderung nachgezogen werden kann.
|
||||
AS_ES_WINKEL_ANZEIGE = sivas_mapping.load_flat_mapping("as_es_winkel_anzeige")
|
||||
|
||||
|
||||
def winkel_text(wert):
|
||||
"""Elementwinkel ganzzahlig normiert ("90.0" -> "90"), ohne Sivas-
|
||||
Anzeigeform. Basis fuer as_es_winkel UND fuer die Gruppierung (dort darf
|
||||
die Anzeigeform keine Rolle spielen). Leerer Wert bleibt leer."""
|
||||
wert = str(wert or "").strip()
|
||||
if not wert:
|
||||
return ""
|
||||
zahl = safe_float(wert, None)
|
||||
return wert if zahl is None else str(int(zahl))
|
||||
|
||||
|
||||
def as_es_vorhanden(winkel):
|
||||
"""Merkmal 4431/4432: "Ja", sobald ein Elementwinkel gesetzt ist."""
|
||||
return "Ja" if winkel_text(winkel) else "Nein"
|
||||
|
||||
|
||||
def as_es_winkel(winkel):
|
||||
"""Merkmal 4427/4429: Elementwinkel in der Sivas-Schreibweise der
|
||||
Auswahlliste (cfg/sivas.cfg [as_es_winkel_anzeige]). Ein Winkel ohne
|
||||
Eintrag dort wird unveraendert (nur ganzzahlig normiert) uebernommen."""
|
||||
winkel = winkel_text(winkel)
|
||||
return AS_ES_WINKEL_ANZEIGE.get(winkel, winkel)
|
||||
|
||||
|
||||
def _seite_text(seite, winkel):
|
||||
"""Gemeinsamer Kern von as_seite/es_seite: Seite nur, wenn es das Element
|
||||
ueberhaupt gibt."""
|
||||
if not winkel_text(winkel):
|
||||
return ""
|
||||
return str(seite or "").strip().lower()
|
||||
|
||||
|
||||
@sivas_mapping.braucht_attribs
|
||||
def as_seite(wert, attribs):
|
||||
"""Merkmal 4428: AS-Seite, aber nur bei vorhandenem AS-Element."""
|
||||
return _seite_text(wert, attribs.get("WINKEL_AS", ""))
|
||||
|
||||
|
||||
@sivas_mapping.braucht_attribs
|
||||
def es_seite(wert, attribs):
|
||||
"""Merkmal 4430: ES-Seite, aber nur bei vorhandenem ES-Element."""
|
||||
return _seite_text(wert, attribs.get("WINKEL_ES", ""))
|
||||
|
||||
|
||||
# --- Transform-Namen, wie sie in cfg/sivas.cfg hinter "|" stehen koennen ---
|
||||
TRANSFORMS = {
|
||||
"ja_nein": ja_nein,
|
||||
"geruest_typ_anzeige": geruest_typ_anzeige,
|
||||
"kf_typ_anzeige": kf_typ_anzeige,
|
||||
"mm_zu_m": mm_zu_m,
|
||||
"as_es_vorhanden": as_es_vorhanden,
|
||||
"as_es_winkel": as_es_winkel,
|
||||
"as_seite": as_seite,
|
||||
"es_seite": es_seite,
|
||||
}
|
||||
|
||||
|
||||
def as_es_signatur(attribs):
|
||||
"""AS-/ES-Anteil des Gruppierungsschluessels (siehe
|
||||
gefaellestrecke_signature). Nutzt dieselben Transforms wie der Export,
|
||||
damit Schluessel und Zeileninhalt nicht auseinanderlaufen: ohne Element
|
||||
ist die Seite leer und darf dann auch nicht trennen."""
|
||||
return (as_es_vorhanden(attribs.get("WINKEL_AS", "")),
|
||||
winkel_text(attribs.get("WINKEL_AS", "")),
|
||||
as_seite(attribs.get("SEITE_AS", ""), attribs),
|
||||
as_es_vorhanden(attribs.get("WINKEL_ES", "")),
|
||||
winkel_text(attribs.get("WINKEL_ES", "")),
|
||||
es_seite(attribs.get("SEITE_ES", ""), attribs))
|
||||
|
||||
|
||||
def streckengruppe_objekt_text(attribs):
|
||||
"""Merkmal 4300 "Streckengruppe": "mehrere Objekte", wenn der Block ein
|
||||
kombinierter Streckengruppe-Block (Gefaelle+Vario, TYP-Attribut
|
||||
@@ -191,12 +295,54 @@ def eckrad_signature(block):
|
||||
)
|
||||
|
||||
|
||||
def kettenfoerderer_signature(block):
|
||||
"""
|
||||
Schluessel zur Gruppierung gleichartiger Kettenfoerderer (KF_n): baugleiche
|
||||
Bloecke landen in EINER Sivas-Zeile, deren Anzahl das Merkmal 353 ("Anzahl
|
||||
der gleichen Schraegfoerderer") traegt.
|
||||
|
||||
In den Schluessel gehoert JEDES Attribut, aus dem ein Merkmal der Zeile
|
||||
entsteht - sonst verschmelzen zwei unterschiedlich ausgefuehrte Foerderer
|
||||
zu einer Zeile, und die Merkmale des ERSTEN Blocks gelten fuer beide
|
||||
(gleiche Ueberlegung wie bei gefaellestrecke_signature/as_es_signatur).
|
||||
Die Kommentare nennen darum je Attribut die Merkmalnummer; einzige
|
||||
Ausnahme ist 353, das erst aus der Gruppengroesse entsteht.
|
||||
|
||||
Das ist zugleich die Voraussetzung dafuer, dass items_zusammenfassen (fuer
|
||||
die _zusammengefasst.csv) zwei KF-Zeilen NIE verschmelzen kann: gleiche
|
||||
Merkmale wuerden schon hier dieselbe Gruppe ergeben. Sonst wuerde dort
|
||||
"anzahl" addiert, waehrend 353 unveraendert stehen bliebe.
|
||||
|
||||
Die Laenge des Zwischenstuecks (L_KF_mm) ist eine FOLGE der Einbauhoehe und
|
||||
steht darum nicht eigens im Schluessel.
|
||||
"""
|
||||
attribs = block.get("attribs", {})
|
||||
return (
|
||||
attribs.get("WINKEL", "26"), # 359
|
||||
attribs.get("STANDARD_STEUERUNG", "0"), # 361
|
||||
attribs.get("FOERDERERTYP", ""), # 350
|
||||
attribs.get("H_EINBAUHOEHE_mm", "0"), # 360
|
||||
attribs.get("FARBE", ""), # 354
|
||||
attribs.get("ANTRIEBSMOTOR", ""), # 355
|
||||
attribs.get("ANTRIEBSART", ""), # 357
|
||||
attribs.get("MOVIMOT", "0"), # 356
|
||||
attribs.get("VERBINDUNGSELEMENTE", "Nein"), # 391
|
||||
attribs.get("ARTINR", ""),
|
||||
)
|
||||
|
||||
|
||||
def gefaellestrecke_signature(block):
|
||||
"""
|
||||
Schluessel zur Gruppierung gleichartiger Gefaellestrecken: Bloecke mit
|
||||
identischen Massen (Hoehe, Laenge, Winkel, Separatoren, Scanner, Typ,
|
||||
Geruest fuer Einzelmodul/Geruestoption) landen in derselben Sivas-Zeile -
|
||||
nur IDs/Bezeichnung unterscheiden sich.
|
||||
Geruest fuer Einzelmodul/Geruestoption, AS-/ES-Element) landen in
|
||||
derselben Sivas-Zeile - nur IDs/Bezeichnung unterscheiden sich.
|
||||
|
||||
AS-/ES-Element (Merkmale 4427-4432) gehoeren mit in den Schluessel: die
|
||||
Merkmale der Zeile entstehen aus dem ERSTEN Block der Gruppe, zwei sonst
|
||||
baugleiche Gefaellestrecken mit AS links bzw. AS rechts wuerden sonst zu
|
||||
einer Zeile mit nur einer der beiden Seiten verschmelzen (siehe
|
||||
as_es_signatur).
|
||||
"""
|
||||
attribs = block.get("attribs", {})
|
||||
return (
|
||||
@@ -209,6 +355,7 @@ def gefaellestrecke_signature(block):
|
||||
attribs.get("TYP", "Gefaellestrecke"),
|
||||
attribs.get("GERUEST_EINZELMODUL", "0"),
|
||||
attribs.get("GERUEST_TYP", "Schoenenberger Geruest"),
|
||||
as_es_signatur(attribs),
|
||||
)
|
||||
|
||||
|
||||
@@ -292,6 +439,20 @@ def build_variofoerderer_details(block):
|
||||
details["4354"] = vf_richtung[0].lower() if vf_richtung else ""
|
||||
details["4386"] = str(int(vf_winkel[0])) if vf_winkel else ""
|
||||
|
||||
# Hoehe je Foerdereinheit (4433-4437, "Variofoerderer 001-005 - Hoehe in
|
||||
# Meter"). Quelle ist das Attribut VF_HOEHE_m: eine kommagetrennte Liste
|
||||
# in Bau-Reihenfolge, je Eintrag der Mittelwert aus KS_EIN der
|
||||
# Umlenkstation und KS_AUS der Motorstation (siehe vf-vfhoehe-anfang/-ende
|
||||
# in Lisp/vf_core.lsp). Einheit Meter, 3 Nachkommastellen - wie L_VF_m.
|
||||
#
|
||||
# Mehr als fuenf Foerdereinheiten kann Sivas hier nicht abbilden; die
|
||||
# ueberzaehligen werden bewusst weggelassen statt zusammengefasst, damit
|
||||
# kein Merkmal einen erfundenen Wert traegt. Fehlende Eintraege bleiben
|
||||
# ganz weg (kein leeres Merkmal).
|
||||
vf_hoehen = parse_float_list(attribs.get("VF_HOEHE_m", ""))
|
||||
for nummer, hoehe in zip(VF_HOEHE_MERKMALE, vf_hoehen):
|
||||
details[nummer] = "%.3f" % hoehe
|
||||
|
||||
return {k: str(v) for k, v in details.items()}
|
||||
|
||||
|
||||
@@ -299,6 +460,7 @@ SIVAS_MAPPING_KREISEL = sivas_mapping.load_section_mapping("kreisel")
|
||||
SIVAS_MAPPING_ECKRAD = sivas_mapping.load_section_mapping("eckrad")
|
||||
SIVAS_MAPPING_GERUEST = sivas_mapping.load_section_mapping("geruest")
|
||||
SIVAS_MAPPING_WEICHEN = sivas_mapping.load_section_mapping("weichen")
|
||||
SIVAS_MAPPING_KETTENFOERDERER = sivas_mapping.load_section_mapping("kettenfoerderer")
|
||||
|
||||
|
||||
def build_kreisel_details(block):
|
||||
@@ -326,6 +488,21 @@ def build_eckrad_details(block):
|
||||
return sivas_mapping.anwenden(SIVAS_MAPPING_ECKRAD, attribs, TRANSFORMS)
|
||||
|
||||
|
||||
def build_kettenfoerderer_details(block, anzahl=1):
|
||||
"""Merkmale-Dict fuer eine Gruppe baugleicher Kettenfoerderer (KF_n,
|
||||
Lisp/KettenFoerderer.lsp).
|
||||
|
||||
350/359/354/356/360/391 kommen flach aus cfg/sivas.cfg [kettenfoerderer].
|
||||
353 ("Anzahl der gleichen Schraegfoerderer") entsteht erst hier aus der
|
||||
Gruppengroesse und kann darum nicht im Mapping stehen - gleiche Bauart wie
|
||||
3510/3512 beim Kreisel.
|
||||
"""
|
||||
attribs = block.get("attribs", {})
|
||||
details = sivas_mapping.anwenden(SIVAS_MAPPING_KETTENFOERDERER, attribs, TRANSFORMS)
|
||||
details["353"] = str(anzahl)
|
||||
return details
|
||||
|
||||
|
||||
# def build_geruest_details(block):
|
||||
#"""Merkmale-Dict fuer eine GR_-Geruest-Baugruppe (siehe pattern_geruest in
|
||||
#cfg/export.cfg, GeruestInsert.lsp *geruest-attrib-defs*). ARTINR/
|
||||
@@ -444,6 +621,8 @@ def process_blocks(blocks, anzahl_weichen_ils=0):
|
||||
btmt_beladung_ids = [] # IDs aller BTMT-Beladung*-Bloecke (eine gruppierte Zeile)
|
||||
btmt_entladung_ids = [] # IDs aller SC_Entladung*-Bloecke (eine gruppierte Zeile)
|
||||
geruest_list = [] # Liste von GR_-Geruest-Baugruppenbloecken, je einer Zeile
|
||||
# Kettenfoerderer: kettenfoerderer_signature(block) -> {"block", "ids", "anzahl"}
|
||||
kettenfoerderer_groups = {}
|
||||
|
||||
counters = {
|
||||
"anzahl_kreisel": 0,
|
||||
@@ -466,6 +645,7 @@ def process_blocks(blocks, anzahl_weichen_ils=0):
|
||||
"anzahl_btbeladung": 0,
|
||||
"anzahl_abwurfstationen": 0,
|
||||
"anzahl_geruest": 0,
|
||||
"anzahl_kettenfoerderer": 0,
|
||||
}
|
||||
|
||||
for block in blocks:
|
||||
@@ -515,6 +695,22 @@ def process_blocks(blocks, anzahl_weichen_ils=0):
|
||||
counters["anzahl_geruest"] += 1
|
||||
continue
|
||||
|
||||
# --- Kettenfoerderer / Schraegfoerderer Stahl (KF_n) ---
|
||||
# MUSS vor dem allgemeinen Omniflo-Zweig stehen: die KF-Baugruppe
|
||||
# traegt TEILEART "Omniflo Kettenfoerderer ..." und wuerde dort sonst
|
||||
# ueber ARTINR aufgeloest - ihre eigenen Merkmale (350/353/354/356/
|
||||
# 359/360/391) gingen dabei verloren. Anders als das Geruest werden
|
||||
# BAUGLEICHE Foerderer zu einer Zeile zusammengefasst, weil Merkmal
|
||||
# 353 genau diese Stueckzahl verlangt.
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_kettenfoerderer", [])):
|
||||
sig = kettenfoerderer_signature(block)
|
||||
if sig not in kettenfoerderer_groups:
|
||||
kettenfoerderer_groups[sig] = {"block": block, "ids": [], "anzahl": 0}
|
||||
kettenfoerderer_groups[sig]["anzahl"] += 1
|
||||
kettenfoerderer_groups[sig]["ids"].append(get_id(block))
|
||||
counters["anzahl_kettenfoerderer"] += 1
|
||||
continue
|
||||
|
||||
# --- Omniflo Gerade (AP110) ---
|
||||
# VOR dem allgemeinen Omniflo-Zweig: Geraden tragen ggf. ebenfalls
|
||||
# TEILEART "Omniflo ...", brauchen aber die Laengensumme.
|
||||
@@ -773,7 +969,7 @@ def process_blocks(blocks, anzahl_weichen_ils=0):
|
||||
"sivasnr": artinr,
|
||||
"sivasnr_quoted": True,
|
||||
"bezeichnung": attribs.get("BEZEICHNUNG", ""),
|
||||
"dispgruppe": 20,
|
||||
"dispgruppe": 30,
|
||||
"anzahl": anzahl,
|
||||
"laenge_mm": attribs.get("LAENGE", ""),
|
||||
"ids": [get_id(block)],
|
||||
@@ -781,6 +977,31 @@ def process_blocks(blocks, anzahl_weichen_ils=0):
|
||||
})
|
||||
nr += 1
|
||||
|
||||
# Kettenfoerderer / Schraegfoerderer Stahl (KF_n) - eine Zeile je Gruppe
|
||||
# BAUGLEICHER Foerderer, deren Groesse als Merkmal 353 mitgefuehrt wird.
|
||||
# Die Sivasnr kommt - wie beim Geruest - aus dem ARTINR-Attribut (gepflegt
|
||||
# als "sivas_id" je Variante in data/json/kettenfoerderer.json); ist dort
|
||||
# nichts hinterlegt, bleibt die Spalte leer und die Zeile traegt allein
|
||||
# ihre Merkmale. Die drei Bausteine des Foerderers (Umlenkstation,
|
||||
# skaliertes Zwischenstueck, Antriebsstation) bekommen KEINE eigenen
|
||||
# Zeilen - der Schraegfoerderer ist in Sivas EIN Artikel.
|
||||
for gruppe in kettenfoerderer_groups.values():
|
||||
block = gruppe["block"]
|
||||
attribs = block.get("attribs", {})
|
||||
items.append({
|
||||
"nr": nr,
|
||||
"teileart": attribs.get("TEILEART") or attribs.get("FOERDERERTYP") or KF_TEILEART,
|
||||
"sivasnr": attribs.get("ARTINR", ""),
|
||||
"sivasnr_quoted": True,
|
||||
"bezeichnung": attribs.get("Bezeichnung", ""),
|
||||
"dispgruppe": 20,
|
||||
"anzahl": gruppe["anzahl"],
|
||||
"laenge_mm": attribs.get("L_KF_mm", ""),
|
||||
"ids": gruppe["ids"],
|
||||
"details": build_kettenfoerderer_details(block, gruppe["anzahl"]),
|
||||
})
|
||||
nr += 1
|
||||
|
||||
# VarioFoerderer-Compound-Bloecke (VF_N) - je Block eine eigene Zeile mit
|
||||
# vollstaendigen Gefaelle-/Angetrieben-Teilgruppen (immer TYP "Streckengruppe").
|
||||
for block in vario_list:
|
||||
@@ -964,6 +1185,13 @@ def zusammengefasster_dateiname(output_csv):
|
||||
return f"{stamm}_zusammengefasst{endung}"
|
||||
|
||||
|
||||
def dispogruppen_dateiname(output_csv, dispo):
|
||||
"""z.B. "500651_sivas.csv", "10" -> "500651_sivas_zusammengefasst_dispo10.csv"."""
|
||||
stamm, endung = os.path.splitext(output_csv)
|
||||
sauber = re.sub(r"[^0-9A-Za-z_-]", "_", str(dispo)) or "leer"
|
||||
return f"{stamm}_zusammengefasst_dispo{sauber}{endung}"
|
||||
|
||||
|
||||
def items_zusammenfassen(items):
|
||||
"""Fasst Zeilen zusammen, die sich nur in Nr, Anzahl und IDs
|
||||
unterscheiden: Anzahl wird addiert, die IDs werden (ohne Dubletten, in
|
||||
@@ -1041,6 +1269,18 @@ def main():
|
||||
print(f"[export_sivas] Zusammengefasste CSV geschrieben: {output_csv_zus} "
|
||||
f"({len(items_zus)} Zeilen)")
|
||||
|
||||
# Je Dispogruppe eine eigene zusammengefasste Datei, z.B.
|
||||
# "<stamm>_zusammengefasst_dispo10.csv" (Nr je Datei neu gezaehlt).
|
||||
for dispo in sorted({str(i["dispgruppe"]) for i in items_zus}):
|
||||
teil = [i for i in items_zus if str(i["dispgruppe"]) == dispo]
|
||||
teil = [dict(i, nr=n) for n, i in enumerate(teil, 1)]
|
||||
pfad = dispogruppen_dateiname(output_csv, dispo)
|
||||
with open(pfad, "w", encoding="utf-8") as f:
|
||||
f.write(header + "\n")
|
||||
for item in teil:
|
||||
f.write(format_csv_line(item) + "\n")
|
||||
print(f"[export_sivas] Dispogruppe {dispo}: {pfad} ({len(teil)} Zeilen)")
|
||||
|
||||
# Zweite, lesbare Kopie fuer die manuelle Pruefung (Merkmalnummer +
|
||||
# Bezeichnung aus cfg/Merkmalsstamm_in_Sivas.xlsx) - wird von Sivas
|
||||
# selbst NICHT eingelesen, nur output_csv ist der eigentliche Import.
|
||||
|
||||
@@ -9,7 +9,7 @@ Hintergrund: data/polylines.dxf enthaelt 5 LWPOLYLINE-Objekte auf Layer
|
||||
"Z-6" - Streckenzuege, die reale Foerderer-Pfade der HundM05-Zeichnung
|
||||
nachbilden (siehe data/polylines.md, von Hand ausgewertet). Dieses Skript
|
||||
macht dieselbe Auswertung reproduzierbar und maschinenlesbar, als Grundlage
|
||||
fuer einen neuen Testfall (siehe tests/testdata/object_data.md fuer das
|
||||
fuer einen neuen Testfall (siehe doc/json-input-lisp.md fuer das
|
||||
allgemeine JSON-Schema).
|
||||
|
||||
Eine Polylinie kann auf einer gekippten Ebene liegen (Gruppencode
|
||||
|
||||
+25
-5
@@ -97,14 +97,31 @@ def load_flat_mapping(section, cfg_path=None):
|
||||
return {}
|
||||
|
||||
|
||||
def braucht_attribs(fn):
|
||||
"""Markiert einen Transform, der NEBEN seinem Rohwert auch das komplette
|
||||
Attribut-Dict des Blocks braucht - er wird dann als fn(wert, attribs)
|
||||
aufgerufen statt als fn(wert).
|
||||
|
||||
Noetig fuer Merkmale, deren Wert von einem ZWEITEN Attribut abhaengt: die
|
||||
AS-/ES-Seite (4428/4430) darf nur gefuellt werden, wenn der zugehoerige
|
||||
WINKEL_AS/WINKEL_ES ueberhaupt ein Element ausweist. Ohne diese Klammer
|
||||
muessten solche Merkmale wieder aus der Config heraus in Python-Code
|
||||
wandern - genau das soll sivas.cfg vermeiden.
|
||||
"""
|
||||
fn.braucht_attribs = True
|
||||
return fn
|
||||
|
||||
|
||||
def anwenden(section_mapping, attribs, transforms):
|
||||
"""Wendet eine per load_section_mapping() gelesene Zuordnung auf ein
|
||||
Block-Attribut-Dict an.
|
||||
|
||||
transforms: dict transform_name -> Funktion(wert) -> wert. Ein in der
|
||||
Config genannter, aber hier unbekannter Transform-Name wird ignoriert
|
||||
(Rohwert bleibt unveraendert) statt abzubrechen - ein Tippfehler in
|
||||
sivas.cfg darf den Export nicht zum Stillstand bringen.
|
||||
transforms: dict transform_name -> Funktion(wert) -> wert. Ein mit
|
||||
@braucht_attribs markierter Transform wird stattdessen als
|
||||
fn(wert, attribs) aufgerufen und sieht damit die uebrigen Attribute des
|
||||
Blocks. Ein in der Config genannter, aber hier unbekannter Transform-Name
|
||||
wird ignoriert (Rohwert bleibt unveraendert) statt abzubrechen - ein
|
||||
Tippfehler in sivas.cfg darf den Export nicht zum Stillstand bringen.
|
||||
|
||||
Rueckgabe: dict merkmal -> wert. Ohne Transform wird der Rohwert zu str()
|
||||
gewandelt (bisheriges Verhalten der build_*_details-Funktionen: alles
|
||||
@@ -124,7 +141,10 @@ def anwenden(section_mapping, attribs, transforms):
|
||||
if transform:
|
||||
fn = transforms.get(transform)
|
||||
if fn is not None:
|
||||
ergebnis[merkmal] = fn(wert)
|
||||
if getattr(fn, "braucht_attribs", False):
|
||||
ergebnis[merkmal] = fn(wert, attribs)
|
||||
else:
|
||||
ergebnis[merkmal] = fn(wert)
|
||||
continue
|
||||
ergebnis[merkmal] = str(wert)
|
||||
return ergebnis
|
||||
@@ -65,6 +65,11 @@ PREFIX = "[vf_journal_export]"
|
||||
|
||||
XDATA_APP = "SSG_VF_EDIT"
|
||||
MARKER = "linienzug"
|
||||
# Marker -> Modus-Nummer. "linienzug" (Modus 1) hat ein Frage-Antwort-
|
||||
# Protokoll (Grammatik in vf_linienzug_grammatik.py); "linienzug2"/"3" werden
|
||||
# als Rohtokens ausgegeben - fuer sie gibt es bewusst keine Grammatik, ihre
|
||||
# SEGS-Eintraege machen sie ohnehin selbst-enthalten.
|
||||
MARKER_MODUS = {"linienzug": 1, "linienzug2": 2, "linienzug3": 3}
|
||||
|
||||
# Steuerzeichen-Notation des Eintrags-Trenners im ASCII-DXF (siehe Kopf).
|
||||
TRENNER = "^J"
|
||||
@@ -322,6 +327,19 @@ class ProtokollSink(Sink):
|
||||
self.add("point_abs", "getpoint Startpunkt der Kette (absoluter "
|
||||
"Weltpunkt, einziger Anker der ganzen Kette)", wert=punkt)
|
||||
|
||||
def as_achse(self, punkt):
|
||||
# Zweiter absoluter Punkt - gibt NUR die Richtung der Zufuehrung,
|
||||
# der Startpunkt bleibt der Sitz des AS-Elements. "nil" heisst: die
|
||||
# Frage wurde gestellt und bewusst uebergangen (die Kettenrichtung
|
||||
# kommt dann aus dem naechsten Klick).
|
||||
if punkt is None:
|
||||
self.add("nil", "getpoint Zufuehrungsachse - 2. Punkt: keiner "
|
||||
"gewaehlt, Richtung kommt aus dem naechsten Klick")
|
||||
else:
|
||||
self.add("point_abs", "getpoint Zufuehrungsachse - 2. Punkt "
|
||||
"(gibt nur die Richtung, der Startpunkt bleibt)",
|
||||
wert=punkt)
|
||||
|
||||
def linie(self, dl, hz, frage):
|
||||
was = _vorlage(_LINIE_TEXT, frage)
|
||||
if hz is None:
|
||||
@@ -541,6 +559,58 @@ def baue_testfaelle(inserts, strecken, startpunkt_fix, quelle_datei,
|
||||
return faelle
|
||||
|
||||
|
||||
def baue_tokenfaelle(inserts, quelle_datei):
|
||||
"""Modus-2/3-Ketten als TOKEN-Records (flache Liste, Kopf + Eintraege).
|
||||
|
||||
Warum nicht wie Modus 1 als Frage-Antwort-Protokoll: dafuer braeuchte es
|
||||
eine Grammatik des Modus-2/3-Fragenflusses, die es (bewusst, siehe
|
||||
doc/todo/spec-modus2-3.md) nicht gibt. Die Tokens selbst sind aber bereits
|
||||
aussagekraeftig - vor allem traegt SEGS die komplette Segment-Essenz, womit
|
||||
die Kette OHNE Zeichnung abspielbar ist.
|
||||
|
||||
Ausgabeformat ist genau das, was tests/test_linienzug.lsp
|
||||
(c:TEST_LINIENZUG_MODUS2) einliest:
|
||||
{"art": "PT", "x": .., "y": .., "z": ..}
|
||||
{"art": "REAL", "wert": ..} {"art": "INT", "wert": ..}
|
||||
{"art": "STR", "wert": ".."} {"art": "SEGS", "wert": ".."}
|
||||
Die Metadaten-Zeile (beschreibung/erwartung_*) ist bewusst NICHT dabei -
|
||||
die wird je Testfall von Hand gepflegt und soll beim Neuerzeugen nicht
|
||||
stillschweigend ueberschrieben werden.
|
||||
"""
|
||||
faelle = []
|
||||
for nr, e in enumerate(sorted(inserts, key=lambda i: i["x"]), start=1):
|
||||
toks = tokens_aus_journal(e["journal_roh"])
|
||||
modus = MARKER_MODUS.get(e["marker"], 0)
|
||||
kopf = {
|
||||
"test_id": "VF_%s_M%d_%02d" % (TEST_ID_ANLAGE, modus, nr),
|
||||
"anlagetyp": e["marker"],
|
||||
"modus": modus,
|
||||
"anzahl_eingaben": len(toks),
|
||||
"block": e["block"],
|
||||
"dxf_handle": e["handle"],
|
||||
"beschreibung": ("Linienzug Modus %d, %d Journal-Eintraege - "
|
||||
"Rohtokens, siehe doc/todo/spec-modus2-3.md"
|
||||
% (modus, len(toks))),
|
||||
"quelle": ("INSERT %s (Block %s) in %s, XDATA-App %s, Marker %s"
|
||||
% (e["handle"], e["block"],
|
||||
os.path.basename(quelle_datei), XDATA_APP,
|
||||
e["marker"])),
|
||||
}
|
||||
faelle.append(kopf)
|
||||
for art, wert in toks:
|
||||
if art == "PT":
|
||||
x, y, z = [float(v) for v in wert.split(",")]
|
||||
faelle.append({"art": "PT", "x": round(x, RUND),
|
||||
"y": round(y, RUND), "z": round(z, RUND)})
|
||||
elif art == "REAL":
|
||||
faelle.append({"art": "REAL", "wert": float(wert)})
|
||||
elif art == "INT":
|
||||
faelle.append({"art": "INT", "wert": int(wert)})
|
||||
else:
|
||||
faelle.append({"art": art, "wert": wert})
|
||||
return faelle
|
||||
|
||||
|
||||
def arrays_einzeilig(text):
|
||||
"""Rein numerische JSON-Arrays auf eine Zeile ziehen (wie
|
||||
dxf_scan_components.py) - ssg-parse-json-array (Lisp/ssg_core.lsp) liest
|
||||
@@ -585,9 +655,20 @@ def main():
|
||||
print("%s %d verbundene Strecken im Sivas-Export"
|
||||
% (PREFIX, len(strecken)))
|
||||
|
||||
faelle = baue_testfaelle(inserts, strecken,
|
||||
not args.kein_startpunkt_fix, args.dxf,
|
||||
args.output)
|
||||
# Nach Modus trennen: nur Modus 1 hat eine Grammatik. Frueher lief die
|
||||
# Modus-1-Grammatik auch ueber "linienzug2"/"3" (der startswith-Filter
|
||||
# laesst sie durch) und brach mit "Token 6: STEP erwartet" ab.
|
||||
m1 = [e for e in inserts if MARKER_MODUS.get(e["marker"]) == 1]
|
||||
m23 = [e for e in inserts if MARKER_MODUS.get(e["marker"]) in (2, 3)]
|
||||
faelle = []
|
||||
if m1:
|
||||
faelle.extend(baue_testfaelle(m1, strecken,
|
||||
not args.kein_startpunkt_fix, args.dxf,
|
||||
args.output))
|
||||
if m23:
|
||||
print("%s %d Modus-2/3-Kette(n) als Rohtokens (keine Grammatik, "
|
||||
"siehe doc/todo/spec-modus2-3.md)" % (PREFIX, len(m23)))
|
||||
faelle.extend(baue_tokenfaelle(m23, args.dxf))
|
||||
koepfe = [f for f in faelle if "test_id" in f]
|
||||
for f in koepfe:
|
||||
print("%s %s %s (%s) %d Eingaben"
|
||||
|
||||
@@ -287,6 +287,12 @@ class Sink(object):
|
||||
def praeambel_start(self):
|
||||
"""Kettenkopf beginnt (Startpunkt/Starthoehe/AS-Element)."""
|
||||
|
||||
def as_achse(self, punkt):
|
||||
"""Zufuehrungsachse des AS-Elements verbraucht (2. Punkt, gibt nur
|
||||
die Richtung). punkt = [x, y, z] oder None, wenn die Kette bewusst
|
||||
OHNE Achse gebaut wurde. Wird gar nicht gerufen, wenn das Journal
|
||||
diese Frage noch nicht kennt (vor 2026-10-21)."""
|
||||
|
||||
def praeambel_ende(self):
|
||||
"""Kettenkopf fertig."""
|
||||
|
||||
@@ -518,9 +524,31 @@ class Kern(object):
|
||||
self.sink.real_feld("hoehe", self.real(), "start_hoehe")
|
||||
if self._ja("as", "AS-Element setzen", "as"):
|
||||
self.sink.roh_feld("as_winkel", self.nimm("STR"), "as_winkel")
|
||||
self._code("as_seite", SEITE, "AS-Seite", "as_seite")
|
||||
# Drei Journal-Formate, unterscheidbar an der Eintragsart (siehe
|
||||
# vfl-frage-as-winkel-seite-oder-achse):
|
||||
# PT direkt nach dem Winkel -> Alt-Achse ohne Seitenfrage
|
||||
# (30-Grad-Element, 2026-10-14
|
||||
# bis 10-20); die Seite wurde
|
||||
# damals aus der Lage des
|
||||
# naechsten Punkts ermittelt.
|
||||
# STR, dann PT bzw. NIL -> Format ab 2026-10-21: Seite UND
|
||||
# (optionale) Zufuehrungsachse.
|
||||
# STR, dann etwas anderes -> Altbestand ohne Achsenfrage.
|
||||
if self.art() == "PT":
|
||||
self._as_achse()
|
||||
else:
|
||||
self._code("as_seite", SEITE, "AS-Seite", "as_seite")
|
||||
if self.art() == "PT":
|
||||
self._as_achse()
|
||||
elif self.art() == "NIL":
|
||||
self.nimm("NIL")
|
||||
self.sink.as_achse(None)
|
||||
self.sink.praeambel_ende()
|
||||
|
||||
def _as_achse(self):
|
||||
"""Zufuehrungsachse: zweiter Punkt, der NUR die Richtung gibt."""
|
||||
self.sink.as_achse([float(v) for v in self.nimm("PT").split(",")])
|
||||
|
||||
def sektionen(self):
|
||||
while self.pos < len(self.tok):
|
||||
label = self.nimm("STEP")
|
||||
|
||||
@@ -87,6 +87,11 @@ def tokens_aus_protokoll(eintraege):
|
||||
tok.append(("STR", str(e["wert"])))
|
||||
elif typ == "step":
|
||||
tok.append(("STEP", str(e["wert"])))
|
||||
elif typ == "nil":
|
||||
# Eine Frage, die gestellt und bewusst uebergangen wurde (bisher
|
||||
# nur die Zufuehrungsachse des AS-Elements) - im Journal ein
|
||||
# "NIL"-Eintrag ohne Wert.
|
||||
tok.append(("NIL", None))
|
||||
else:
|
||||
raise ValueError("unbekannter Eintragstyp: %r" % typ)
|
||||
return tok
|
||||
@@ -255,6 +260,14 @@ class SpecSink(Sink):
|
||||
def punkt_abs(self, punkt):
|
||||
self.ziel["punkt"] = punkt
|
||||
|
||||
def as_achse(self, punkt):
|
||||
# Zufuehrungsachse des AS-Elements. "ohne" ist NICHT dasselbe wie ein
|
||||
# fehlendes Feld: "ohne" heisst "die Frage wurde gestellt und bewusst
|
||||
# uebergangen" (NIL im Journal), ein fehlendes Feld heisst "das
|
||||
# Journal kennt die Frage gar nicht" (vor 2026-10-21). Nur so bleibt
|
||||
# der Rundlauf Journal -> Spec -> Journal tokengleich.
|
||||
self.ziel["as_achse"] = punkt if punkt is not None else "ohne"
|
||||
|
||||
def linie(self, dl, hz, frage):
|
||||
self.ziel["dl"] = dl
|
||||
if hz is not None:
|
||||
@@ -398,6 +411,14 @@ class SpecSchreiber(object):
|
||||
self.raus("STR", str(self.feld(start, "as_winkel")))
|
||||
self.raus("STR", code_aus_wert(SEITE, self.feld(start, "as_seite"),
|
||||
"as_seite"))
|
||||
# Optional, Gegenstueck zu SpecSink.as_achse und zu
|
||||
# vsp-praeambel in Lisp/vf_spec.lsp: Liste -> PT, "ohne" -> NIL,
|
||||
# fehlt -> gar kein Token (Journalformat vor 2026-10-21).
|
||||
achse = start.get("as_achse")
|
||||
if isinstance(achse, (list, tuple)):
|
||||
self.raus("PT", ",".join(_zahl(v) for v in achse))
|
||||
elif achse == "ohne":
|
||||
self.raus("NIL", None)
|
||||
|
||||
def sektion(self, sek, erster, naechste=None):
|
||||
label = self.feld(sek, "glied")
|
||||
@@ -641,6 +662,11 @@ def flache_objekte(spec_id, spec, kopf_extra=None):
|
||||
if start["as"]:
|
||||
kopf["as_winkel"] = start["as_winkel"]
|
||||
kopf["as_seite"] = start["as_seite"]
|
||||
# Nur schreiben, wenn vorhanden - ein fehlendes Feld ist die
|
||||
# bewusste Aussage "Journalformat ohne Achsenfrage" (siehe
|
||||
# SpecSink.as_achse), kein Datenverlust.
|
||||
if "as_achse" in start:
|
||||
kopf["as_achse"] = start["as_achse"]
|
||||
for k, v in (kopf_extra or collections.OrderedDict()).items():
|
||||
kopf[k] = v
|
||||
objekte.append(kopf)
|
||||
|
||||
+4
-4
@@ -118,7 +118,7 @@
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00030">
|
||||
<Macro>
|
||||
<Name>3D Objekte stueckweise (in Arbeit)</Name>
|
||||
<Name>aus 3D Linie ohne Zielhoehe</Name>
|
||||
<Command>^C^C(ssg-ensure "VarioFoerderer") LinienzugVarioFoerdererStueckweise</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
@@ -401,7 +401,7 @@
|
||||
<MenuMacro UID="MM_00095">
|
||||
<Macro>
|
||||
<Name>KettenFoerderer</Name>
|
||||
<Command>^C^C(ssg-ensure "OmniModulInsert") OMNI_KettenFoerderer</Command>
|
||||
<Command>^C^C(ssg-ensure "KettenFoerderer") KETTENFOERDERER</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00096">
|
||||
@@ -1155,7 +1155,7 @@
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>3D Objekte stueckweise (in Arbeit)</NameRef>
|
||||
<NameRef>aus 3D Linie ohne Zielhoehe</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00030"/>
|
||||
</MenuItem>
|
||||
@@ -1217,7 +1217,7 @@
|
||||
<PopMenuRef pUID="PM_00084"/>
|
||||
<PopMenuRef pUID="PM_00088"/>
|
||||
<PopMenuItem>
|
||||
<NameRef>~KettenFoerderer</NameRef>
|
||||
<NameRef>KettenFoerderer</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00095"/>
|
||||
</MenuItem>
|
||||
|
||||
@@ -156,8 +156,17 @@
|
||||
(ssg-ensure "VarioFoerderer")
|
||||
(ssg-ensure "EtageVarioFoerderer")
|
||||
(ssg-ensure "export")
|
||||
;; Hoehen-Check vorladen: EXPORTSIVAS bietet ihn per Rueckfrage an und ruft
|
||||
;; c:HOEHEN_CHECK im selben Lauf auf (ein Nachladen waere dort erst nach
|
||||
;; Rueckkehr zum Top-Level sichtbar).
|
||||
(ssg-ensure "check_hoehen")
|
||||
(ssg-ensure "external_call")
|
||||
(ssg-ensure "OmniModulInsert")
|
||||
;; Kettenfoerderer vorladen statt lazy: der erste Menueklick musste sonst
|
||||
;; das Laden des Moduls mitbezahlen, der Dialog erschien dadurch spuerbar
|
||||
;; verzoegert. Das Modul ist klein, der Startaufschlag faellt nicht ins
|
||||
;; Gewicht. (Zum Nachmessen: Schalter "kf-zeit", siehe KettenFoerderer.lsp)
|
||||
(ssg-ensure "KettenFoerderer")
|
||||
;; Tro_Edit wird nicht vorgeladen - der Dispatcher SSG_BLOCKEDIT und die
|
||||
;; Menuemakros holen es per (ssg-ensure "Tro_Edit") bei Bedarf nach.
|
||||
(ssg-ensure "SSG_LIB_Commands")
|
||||
|
||||
+4
-3
@@ -27,7 +27,7 @@
|
||||
[->Streckengruppe]
|
||||
[Werte manuell]^C^C(ssg-ensure "VarioFoerderer") LinienzugVarioFoerdererManuell
|
||||
[aus 3D Linie mit Zielhoehe]^C^C(ssg-ensure "VarioFoerderer") LinienzugVarioFoerdererZielhoehe
|
||||
[<-3D Objekte stueckweise (in Arbeit)]^C^C(ssg-ensure "VarioFoerderer") LinienzugVarioFoerdererStueckweise
|
||||
[<-aus 3D Linie ohne Zielhoehe]^C^C(ssg-ensure "VarioFoerderer") LinienzugVarioFoerdererStueckweise
|
||||
[Vario_Kette_Merge]^C^C(ssg-ensure "VarioFoerderer") Vario_Kette_Merge
|
||||
[<-VarioFoerderer nachruesten (Marker)]^C^C(ssg-ensure "VarioFoerderer") VARIOFOERDERER_NACHRUESTEN
|
||||
[->Gefaellestrecke]
|
||||
@@ -92,7 +92,7 @@
|
||||
[Schwenkschiene Schiebetür R]^C^C(ssg-ensure "OmniModulInsert") OMNI_SCHW_400_R
|
||||
[Schwenkschiene Schiebetür L mit Sensorik]^C^C(ssg-ensure "OmniModulInsert") OMNI_SCHW_400_L_SENSORIK
|
||||
[<-<-<-Schwenkschiene Schiebetür R mit Sensorik]^C^C(ssg-ensure "OmniModulInsert") OMNI_SCHW_400_R_SENSORIK
|
||||
[~KettenFoerderer]^C^C(ssg-ensure "OmniModulInsert") OMNI_KettenFoerderer
|
||||
[KettenFoerderer]^C^C(ssg-ensure "KettenFoerderer") KETTENFOERDERER
|
||||
[Ladeschleifen]^C^C(ssg-ensure "OmniModulInsert") OMNI_LADESCHLEIFE_AP110
|
||||
[->Verbinder]
|
||||
[TV W-AP110 kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110
|
||||
@@ -164,6 +164,7 @@
|
||||
[Ausgang]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_AUSGANG_INSERT
|
||||
[<-SPS Schliessen]^C^C
|
||||
[->Export]
|
||||
[Hoehen-Check (Montagehoehe/Buehne)]^C^C(ssg-ensure "check_hoehen") HOEHEN_CHECK
|
||||
[Export Sivas]^C^C(ssg-ensure "export") EXPORTSIVAS
|
||||
[<-Export CSV]^C^C(ssg-ensure "export") EXPORTCSV
|
||||
[->Konfiguration]
|
||||
@@ -192,7 +193,7 @@
|
||||
[--]
|
||||
[Kreisel]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_kreisel.lsp")) (c:TEST_KREISEL)
|
||||
[Foerderer]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_foerderer.lsp")) (c:TEST_FOERDERER)
|
||||
[Foerderer-Linienzug]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_linienzug.lsp")) (c:TEST_LINIENZUG) (c:TEST_LINIENZUG_STUFE2)
|
||||
[Foerderer-Linienzug]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_linienzug.lsp")) (c:TEST_LINIENZUG) (c:TEST_LINIENZUG_STUFE2) (c:TEST_LINIENZUG_MODUS2)
|
||||
[Omniflo]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo.lsp")) (c:TEST_OMNIFLO)
|
||||
[Omniflo Strecke]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo_strecke.lsp")) (c:TEST_OMNIFLO_STRECKE)
|
||||
[Gefaellestrecke]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_gefaellestrecke.lsp")) (c:TEST_GEFAELLESTRECKE)
|
||||
|
||||
+147
@@ -87,6 +87,153 @@ dem gewuenschten Modus:
|
||||
Lauf ohne manuellen Zusatzschritt, aber ohne gleichzeitige visuelle Kontrolle
|
||||
aller Zeichnungen am Ende. Sinnvoll fuer reine CI-artige Validierung.
|
||||
|
||||
## Anordnung der Linienzug-Testketten
|
||||
|
||||
Der Menueeintrag **Tests -> Foerderer-Linienzug** faehrt drei Befehle
|
||||
nacheinander (`TEST_LINIENZUG`, `TEST_LINIENZUG_STUFE2`,
|
||||
`TEST_LINIENZUG_MODUS2`) und baut dabei **sieben** Ketten. Damit sie
|
||||
nebeneinander auf einer Grundlinie entstehen statt verstreut, tragen die
|
||||
Testdaten versetzte Startpunkte - 20 m Abstand, alle auf `Y = 0`:
|
||||
|
||||
| X | Z | Kette | Datei |
|
||||
|---|---|---|---|
|
||||
| 0 | 2154 | Modus 1, Standardfall | `linienzug_tests.json` |
|
||||
| 20000 | 2154 | Modus 1, Stufe-2-Fallback | `linienzug_tests_stufe2.json` |
|
||||
| 40000 | 0 | Variante A (Vario-Kurve) | `linienzug_modus2_variokurve.json` |
|
||||
| 60000 | 0 | Variante B (GF-Bogen) | `linienzug_modus2_gfbogen.json` |
|
||||
| 80000 | 355 | U-Form 1 (GF alles am Einlauf) | `..._uform_gf1.json` |
|
||||
| 100000 | 711 | U-Form 2 (1/2 + 1/2) | `..._uform_halb.json` |
|
||||
| 120000 | 709 | U-Form 3 (steilerer Winkel) | `..._uform_halb_steil.json` |
|
||||
|
||||
Die Koordinaten sind also **nicht** die der aufgezeichneten Laeufe, die
|
||||
uebrige Geometrie schon. Verschoben wurde rein translatorisch: Laengen,
|
||||
Winkel und die geprueften Abweichungen sind davon unabhaengig. `Z` blieb
|
||||
jeweils stehen - die Starthoehe ist ein Eingabewert des Solvers, kein
|
||||
Layout-Parameter.
|
||||
|
||||
Technisch unterscheiden sich die beiden Datenarten: die Modus-1-Skripte
|
||||
brauchen nur ihren EINEN `point_abs` (alles Weitere ist `point_rel` mit
|
||||
`dL`/`hz`), waehrend bei Modus 2 sowohl die `PT`-Eintraege ALS AUCH die
|
||||
Pfadkoordinaten in `SEGS` (Felder 6..9) mitwandern muessen - sonst zeigt der
|
||||
Pfad woanders hin als Start und Ziel.
|
||||
|
||||
## Referenzfaelle Linienzug Modus 2 (`c:TEST_LINIENZUG_MODUS2`)
|
||||
|
||||
Fuenf aufgezeichnete Laeufe, die als zwei Paare gebildet sind: A/B
|
||||
unterscheiden die Eck-BAUTEILART, U-Form 1..3 den gefalteten Lauf nach
|
||||
GF-Verteilung und Winkel. Ausgefuehrt ueber Menue -> Tests ->
|
||||
Foerderer-Linienzug.
|
||||
|
||||
### Erster und zweiter Fall: Eck-Bauteilart
|
||||
|
||||
Zwei Laeufe auf **demselben gezeichneten Pfad**, die sich nur in der
|
||||
Segment-Klassifizierung unterscheiden. Sie decken die beiden Eck-Bauteilarten
|
||||
ab (waagerecht eingebaute Vario-Kurve und geneigt eingebauter Gefaellebogen)
|
||||
und haben am 2026-10-26 sieben Budget-Fehler aufgedeckt, die ein einzelner
|
||||
Lauf nicht gezeigt haette - erst der VERGLEICH zweier Varianten machte
|
||||
sichtbar, dass eine Korrektur am falschen Segment landete.
|
||||
|
||||
**Gezeichneter Pfad** (5 Objekte, Boegen als R500-Verrundung):
|
||||
|
||||
| Segment | Art | Mass |
|
||||
|---|---|---|
|
||||
| 1 | Linie | L = 9700 mm, hz = 0 |
|
||||
| 2 | Bogen | 90 Grad rechts, R500 |
|
||||
| 3 | Linie | L = 4296 mm, hz = -90 |
|
||||
| 4 | Bogen | 30 Grad links, R500 |
|
||||
| 5 | Linie | L = 1466 mm, hz = -60 |
|
||||
|
||||
**Gemeinsame Eingaben:** AS-Element ja, 90 Grad, links. ES-Element ja,
|
||||
30 Grad, rechts. Lauf beginnen mit "Umlenkstation mit GF1 + Separator",
|
||||
GF-Verteilung "alles am Einlauf", keine zusaetzlichen Separatoren.
|
||||
|
||||
| | Variante A | Variante B |
|
||||
|---|---|---|
|
||||
| Segment 2 | **Vario-Kurve** (aussen) | **GF-Bogen** |
|
||||
| Segment 3 | VF (automatisch nach Kurve) | GF |
|
||||
| Segment 4 | GF-Bogen | GF-Bogen |
|
||||
| Segment 5 | GF | GF |
|
||||
| VF-Lauf | Segment 1..3 | Segment 1..1 |
|
||||
|
||||
**Soll-Ergebnis fuer BEIDE Varianten:**
|
||||
|
||||
- `Quer zur Achse` **~0** (gemessen 0.2 mm - das ist die Aufloesung der
|
||||
Blockmessung, kein Restfehler)
|
||||
- `dZ` **0**
|
||||
- `Laengs KS_AUS-Achse` darf abweichen (~104 mm) - das ist die Ausladung des
|
||||
ES-Elements und ausdruecklich zulaessig.
|
||||
|
||||
Die Regel dahinter: **quer zur KS_AUS-Achse MUSS 0 sein, laengs darf
|
||||
abweichen, dZ MUSS 0 sein.** Beides zugleich geht nicht - entweder liegt die
|
||||
letzte Gerade auf der gezeichneten Linie und der ES-`KS_AUS` landet seitlich
|
||||
daneben, oder umgekehrt. Entschieden ist: der Hauptstrang bleibt gerade, der
|
||||
seitliche Versatz des ES-Elements ist dessen Bauform und kein Fehler.
|
||||
|
||||
**`laengs` wird trotzdem geprueft** - nicht als Genauigkeits-, sondern als
|
||||
FORMkriterium (`erwartung_laengs_mm` in den Testdaten, Toleranz 5 mm). Der Wert
|
||||
ist die Ausladung des ES-Elements und damit je Fall eine Konstante: 104.68 mm
|
||||
bei `ES_Element_30`, 637.58 mm bei `ES_Element_90`.
|
||||
Grund: am 2026-10-29 loeste ein Experiment den Schluss-Fueller gegen Richtung
|
||||
UND Laenge und traf den Zielpunkt dadurch in X und Y exakt - um den Preis, dass
|
||||
es die letzte Gerade um 6.15 Grad verdrehte. `quer` und `dZ` waren dabei NULL,
|
||||
der Test meldete brav OK, und der schiefe Schenkel fiel nur beim Blick in die
|
||||
Zeichnung auf. Ein verdrehter Hauptstrang zielt auf den Endpunkt und drueckt
|
||||
`laengs` von ~638 mm auf ~0 - genau daran ist er zu erkennen.
|
||||
Die Pruefung selbst ist gegengeprueft: mit einer kuenstlich auf 0.01 mm
|
||||
gesetzten Toleranz kippen alle fuenf Faelle auf ABWEICHUNG.
|
||||
|
||||
Im Protokoll muessen die Zuschlags-Zeilen erscheinen: `AS-Fussabdruck`,
|
||||
`Eck-Korrektur` je Ecke, und bei Variante A zusaetzlich
|
||||
`Abschluss-Fussabdruck`. **Eine FEHLENDE Zeile ist das Warnsignal** - sie
|
||||
bedeutet, dass ein Eck-Bauteil nicht messbar war und die Ecke unkorrigiert
|
||||
blieb (so wurde der 2.4-mm-Rest bei Variante B gefunden).
|
||||
|
||||
> **Automatisiert seit 2026-10-27** als `c:TEST_LINIENZUG_MODUS2` (Menue:
|
||||
> Tests -> Foerderer-Linienzug). Der Pfad muss dafuer NICHT gezeichnet werden:
|
||||
> ein Modus-2-Journal traegt einen `SEGS`-Eintrag mit der kompletten
|
||||
> Segment-Essenz und ist damit von den Original-Objekten unabhaengig - der
|
||||
> Test spielt schlicht das mit `lib/vf_journal_export.py` ausgelesene Journal
|
||||
> ab. Die reinen Rechenkerne sind zusaetzlich file-frei abgedeckt
|
||||
> (`tu-tests-vfl-parallel` in `test_unit.lsp`: `vfl-eck-zerlegen`,
|
||||
> `vfl-es-achs-reserve`, `vfl-projiziere-neigung` - jeweils mit den echten
|
||||
> Messwerten aus diesen beiden Laeufen).
|
||||
|
||||
### Dritter bis fuenfter Fall: gefalteter Lauf (U-Form)
|
||||
|
||||
Aufgezeichnet 2026-10-29, Datendateien `tests/testdata/linienzug_modus2_uform_*.json`.
|
||||
|
||||
Der Pfad wechselt ueber zwei 90-Grad-Vario-Kurven **dreimal die
|
||||
Fahrtrichtung**; die Kletterstrecke liegt dadurch in einem ANDEREN Schenkel als
|
||||
der Lauf-Eingang. Genau diese Konstellation war bis 2026-10-29 falsch
|
||||
bilanziert (gemessen 1424 mm quer), weil Posten dem falschen Schenkel
|
||||
zugerechnet wurden.
|
||||
|
||||
| Segment | Art | Mass |
|
||||
|---|---|---|
|
||||
| 1 | Linie | L = 5855 mm, hz = 90 |
|
||||
| 2 | Bogen | 90 Grad rechts, R500 -> **Vario-Kurve aussen** |
|
||||
| 3 | Linie | L = 270 mm, hz = 0 (automatisch VF) |
|
||||
| 4 | Bogen | 90 Grad rechts, R500 -> **Vario-Kurve aussen** |
|
||||
| 5 | Linie | L = 7806 mm, hz = -90 (der Kletterer) |
|
||||
|
||||
| Fall | GF-Verteilung | Winkel-Option | Testdatei |
|
||||
|---|---|---|---|
|
||||
| U-Form 1 | alles am Einlauf (GF1) | 2 | `..._uform_gf1.json` |
|
||||
| U-Form 2 | 1/2 GF1 + 1/2 GF2 | 2 (= 9 Grad) | `..._uform_halb.json` |
|
||||
| U-Form 3 | 1/2 GF1 + 1/2 GF2 | 3 (steiler) | `..._uform_halb_steil.json` |
|
||||
|
||||
**Warum drei und nicht einer:** die GF-VERTEILUNG entscheidet, ob ueberhaupt
|
||||
Gefaellestrecke im fremden Schenkel steht (und damit, ob Nachrechner und das
|
||||
unterdrueckte Fueller-A greifen) - mit "alles am Einlauf" liegt das gesamte GF1
|
||||
dort, mit 1/2+1/2 nur die Haelfte. Der WINKEL ist noetig, weil der Restfehler
|
||||
der alten Bilanz mit `L_GF` skalierte: bei 6 Grad waren es 90 mm, bei 9 Grad
|
||||
934 mm. Zwei Laeufe mit demselben Winkel haetten den Fehler also beinahe
|
||||
verdeckt.
|
||||
|
||||
Soll-Ergebnis wie oben: `quer` und `dZ` jeweils ~0 (gemessen 0.56 mm bei
|
||||
9 Grad und 0.7 mm bei der steileren Option), `laengs` ~638 mm - das ist die
|
||||
Ausladung des `ES_Element_90_links` und in allen drei Faellen gleich.
|
||||
|
||||
## alltests.json — Testregistry
|
||||
|
||||
Die Datei `tests/alltests.json` ist die zentrale Registry aller Test-Module.
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];IDs;details
|
||||
1;"ILS 2.0 Strecke";"6220";"VF_13";20;1;;"0013";{"Anlagenhöhe in Meter": "-1.5", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.0", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.707", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.055", "Streckengruppe - Varioförderer 001-Richtung": "ab", "Streckengruppe - Varioförderer 001- Winkel": "39", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
2;"ILS 2.0 Strecke";"6220";"VF_12";20;1;;"0012";{"Anlagenhöhe in Meter": "0.5", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.084", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.0", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.478", "Streckengruppe - Varioförderer 001-Richtung": "auf", "Streckengruppe - Varioförderer 001- Winkel": "21", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
3;"ILS 2.0 Strecke";"6220";"VF_11";20;1;;"0011";{"Anlagenhöhe in Meter": "1.5", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.166", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.166", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.207", "Streckengruppe - Varioförderer 001-Richtung": "auf", "Streckengruppe - Varioförderer 001- Winkel": "51", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
4;"ILS 2.0 Strecke";"6220";"VF_10";20;1;;"0010";{"Anlagenhöhe in Meter": "-1", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.541", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.541", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "2.731", "Streckengruppe - Varioförderer 001-Richtung": "ab", "Streckengruppe - Varioförderer 001- Winkel": "27", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
5;"ILS 2.0 Strecke";"6220";"VF_9";20;1;;"0009";{"Anlagenhöhe in Meter": "1", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.206", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.206", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.07", "Streckengruppe - Varioförderer 001-Richtung": "auf", "Streckengruppe - Varioförderer 001- Winkel": "39", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
6;"ILS 2.0 Strecke";"6220";"VF_8";20;1;;"0008";{"Anlagenhöhe in Meter": "-2", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.15", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.15", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "4.067", "Streckengruppe - Varioförderer 001-Richtung": "ab", "Streckengruppe - Varioförderer 001- Winkel": "45", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
7;"ILS 2.0 Strecke";"6220";"VF_7";20;1;;"0007";{"Anlagenhöhe in Meter": "-1.5", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.354", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.354", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.055", "Streckengruppe - Varioförderer 001-Richtung": "ab", "Streckengruppe - Varioförderer 001- Winkel": "39", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
8;"ILS 2.0 Strecke";"6220";"VF_6";20;1;;"0006";{"Anlagenhöhe in Meter": "-1", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.013", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.013", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.701", "Streckengruppe - Varioförderer 001-Richtung": "ab", "Streckengruppe - Varioförderer 001- Winkel": "21", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
9;"ILS 2.0 Strecke";"6220";"VF_5";20;1;;"0005";{"Anlagenhöhe in Meter": "-0.5", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.486", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.486", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.056", "Streckengruppe - Varioförderer 001-Richtung": "ab", "Streckengruppe - Varioförderer 001- Winkel": "9", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
10;"ILS 2.0 Strecke";"6220";"VF_4";20;1;;"0004";{"Anlagenhöhe in Meter": "1.5", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.166", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.166", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.207", "Streckengruppe - Varioförderer 001-Richtung": "auf", "Streckengruppe - Varioförderer 001- Winkel": "51", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
11;"ILS 2.0 Strecke";"6220";"VF_3";20;1;;"0003";{"Anlagenhöhe in Meter": "1", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.206", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.206", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.07", "Streckengruppe - Varioförderer 001-Richtung": "auf", "Streckengruppe - Varioförderer 001- Winkel": "39", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
12;"ILS 2.0 Strecke";"6220";"VF_2";20;1;;"0002";{"Anlagenhöhe in Meter": "0.5", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.042", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.042", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "3.478", "Streckengruppe - Varioförderer 001-Richtung": "auf", "Streckengruppe - Varioförderer 001- Winkel": "21", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
13;"ILS 2.0 Strecke";"6220";"VF_1";20;1;;"0001";{"Anlagenhöhe in Meter": "0", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "0.615", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "0.615", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "2.74", "Streckengruppe - Varioförderer 001-Richtung": "auf", "Streckengruppe - Varioförderer 001- Winkel": "9", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
14;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"Automation": "Ja", "Anzahl der Kreisel": "0", "Anzahl der Separatoren - Kreisel ohne PINBAND": "0", "Anzahl der Kreisel mit PINBAND": "0", "Anzahl der Separatoren - Kreisel mit PINBAND": "0", "Anzahl der Verbindungskreisel": "0", "Längen aller Kreisel": "0.00", "Anzahl der Weichen": "0", "Anzahl der Eckräder": "0", "Anzahl der einzelnen Gefällestrecken": "0", "Anzahl der einzelnen Vario-Förderer": "0", "Anzahl der Streckengruppen": "13", "Längen aller Gefällestrecken": "0.00", "Anzahl der Motoren in Vario - Förderer": "13", "Längen aller Vario - Förderer": "41.915000000000006", "Anzahl der ETFs": "0", "Längen aller ETFS und Zusatzstücke (Gefällestrecken)": "0.0", "Anzahl der Separatoren in der Anlage": "26", "Anzahl der Scanner in der Anlage": "0", "Zusatzmodul - Anzahl der BT-Beladung": "0", "Zusatzmodul - Anzahl der Abwurfstation": "0", "Pneumatik": "Ja"}
|
||||
1;"ILS 2.0 Strecke";"6220";"VF_13";20;1;;"0013";{"2950": "-1.5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.0", "4391": "3", "4314": "Ja", "4319": "0.707", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.055", "4354": "ab", "4386": "39", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
2;"ILS 2.0 Strecke";"6220";"VF_12";20;1;;"0012";{"2950": "0.5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.084", "4391": "3", "4314": "Ja", "4319": "0.0", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.478", "4354": "auf", "4386": "21", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
3;"ILS 2.0 Strecke";"6220";"VF_11";20;1;;"0011";{"2950": "1.5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.166", "4391": "3", "4314": "Ja", "4319": "0.166", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.207", "4354": "auf", "4386": "51", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
4;"ILS 2.0 Strecke";"6220";"VF_10";20;1;;"0010";{"2950": "-1", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.541", "4391": "3", "4314": "Ja", "4319": "0.541", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "2.731", "4354": "ab", "4386": "27", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
5;"ILS 2.0 Strecke";"6220";"VF_9";20;1;;"0009";{"2950": "1", "4431": "Ja", "4427": "90 °", "4428": "rechts", "4432": "Ja", "4429": "90 °", "4430": "rechts", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.206", "4391": "3", "4314": "Ja", "4319": "0.206", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.07", "4354": "auf", "4386": "39", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
6;"ILS 2.0 Strecke";"6220";"VF_8";20;1;;"0008";{"2950": "-2", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.15", "4391": "3", "4314": "Ja", "4319": "0.15", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "4.067", "4354": "ab", "4386": "45", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
7;"ILS 2.0 Strecke";"6220";"VF_7";20;1;;"0007";{"2950": "-1.5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.354", "4391": "3", "4314": "Ja", "4319": "0.354", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.055", "4354": "ab", "4386": "39", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
8;"ILS 2.0 Strecke";"6220";"VF_6";20;1;;"0006";{"2950": "-1", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.013", "4391": "3", "4314": "Ja", "4319": "0.013", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.701", "4354": "ab", "4386": "21", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
9;"ILS 2.0 Strecke";"6220";"VF_5";20;1;;"0005";{"2950": "-0.5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.486", "4391": "3", "4314": "Ja", "4319": "0.486", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.056", "4354": "ab", "4386": "9", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488", "4437": "-0.512"}
|
||||
10;"ILS 2.0 Strecke";"6220";"VF_4";20;1;;"0004";{"2950": "1.5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.166", "4391": "3", "4314": "Ja", "4319": "0.166", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.207", "4354": "auf", "4386": "51", "4433": "-0.012", "4434": "0.488", "4435": "0.988", "4436": "1.488"}
|
||||
11;"ILS 2.0 Strecke";"6220";"VF_3";20;1;;"0003";{"2950": "1", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.206", "4391": "3", "4314": "Ja", "4319": "0.206", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.07", "4354": "auf", "4386": "39", "4433": "-0.012", "4434": "0.488", "4435": "0.988"}
|
||||
12;"ILS 2.0 Strecke";"6220";"VF_2";20;1;;"0002";{"2950": "0.5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.042", "4391": "3", "4314": "Ja", "4319": "0.042", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "3.478", "4354": "auf", "4386": "21", "4433": "-0.012", "4434": "0.488"}
|
||||
13;"ILS 2.0 Strecke";"6220";"VF_1";20;1;;"0001";{"2950": "0", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "0", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.615", "4391": "3", "4314": "Ja", "4319": "0.615", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "2.74", "4354": "auf", "4386": "9", "4433": "-0.012"}
|
||||
14;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"4000": "Ja", "4400": "0", "4413": "0", "4401": "0", "4414": "0", "4402": "0", "4419": "0.00", "4403": "0", "4404": "0", "4425": "0", "4426": "0", "4407": "13", "4418": "0.00", "4408": "13", "4420": "41.915000000000006", "4409": "0", "4417": "0.0", "4410": "26", "4411": "0", "4421": "0", "4422": "0", "4100": "Ja"}
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 50.
|
@@ -1,6 +1,6 @@
|
||||
Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];IDs;details
|
||||
1;"ILS 2.0 Gefaellestrecke";"6220";"GF_8";20;1;;"0008";{"Anlagenhöhe in Meter": "5", "Streckengruppe": "ein Objekt", "Gefällestrecke oder Vario-Förderer": "Gefällestrecke", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "9.261", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "1", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
2;"ILS 2.0 Gefaellestrecke";"6220";"GF_7";20;1;;"0007";{"Anlagenhöhe in Meter": "2", "Streckengruppe": "mehrere Objekte", "Gefällestrecke oder Vario-Förderer": "Gefällestrecke", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "7.274,5.264", "Streckengruppe - Gefällestrecke 001 -Winkel": "0.2,0.2", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "2", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
3;"ILS 2.0 Gefaellestrecke";"6220";"GF_6";20;1;;"0006";{"Anlagenhöhe in Meter": "5", "Streckengruppe": "ein Objekt", "Gefällestrecke oder Vario-Förderer": "Gefällestrecke", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "8.838", "Streckengruppe - Gefällestrecke 001 -Winkel": "2.8", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "1", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
4;"ILS 2.0 Gefaellestrecke";"6220";"GF_5, GF_4, GF_3, GF_2, GF_1";20;1;;"0005, 0004, 0003, 0002, 0001";{"Anlagenhöhe in Meter": "5", "Streckengruppe": "ein Objekt", "Gefällestrecke oder Vario-Förderer": "Gefällestrecke", "Strecken- zu fertigende Menge": "5", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "8.851", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "1", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Gerüst für Einzelmodul": "Nein", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
5;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"Automation": "Ja", "Anzahl der Kreisel": "0", "Anzahl der Separatoren - Kreisel ohne PINBAND": "0", "Anzahl der Kreisel mit PINBAND": "0", "Anzahl der Separatoren - Kreisel mit PINBAND": "0", "Anzahl der Verbindungskreisel": "0", "Längen aller Kreisel": "0.00", "Anzahl der Weichen": "0", "Anzahl der Eckräder": "0", "Anzahl der einzelnen Gefällestrecken": "8", "Anzahl der einzelnen Vario-Förderer": "0", "Anzahl der Streckengruppen": "0", "Längen aller Gefällestrecken": "62.35", "Anzahl der Motoren in Vario - Förderer": "0", "Längen aller Vario - Förderer": "0.0", "Anzahl der ETFs": "0", "Längen aller ETFS und Zusatzstücke (Gefällestrecken)": "0.0", "Anzahl der Separatoren in der Anlage": "9", "Anzahl der Scanner in der Anlage": "0", "Zusatzmodul - Anzahl der BT-Beladung": "0", "Zusatzmodul - Anzahl der Abwurfstation": "0", "Pneumatik": "Ja"}
|
||||
1;"ILS 2.0 Gefaellestrecke";"6220";"GF_8";20;1;;"0008";{"2950": "5", "4431": "Ja", "4427": "30 °", "4428": "links", "4432": "Ja", "4429": "30 °", "4430": "links", "4384": "Gefällestrecke", "4318": "9.261", "4391": "3", "4337": "1", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "ein Objekt", "4311": "1"}
|
||||
2;"ILS 2.0 Gefaellestrecke";"6220";"GF_7";20;1;;"0007";{"2950": "2", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4384": "Gefällestrecke", "4318": "7.274,5.264", "4391": "0.2,0.2", "4337": "2", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1"}
|
||||
3;"ILS 2.0 Gefaellestrecke";"6220";"GF_6";20;1;;"0006";{"2950": "5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4384": "Gefällestrecke", "4318": "8.838", "4391": "2.8", "4337": "1", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "ein Objekt", "4311": "1"}
|
||||
4;"ILS 2.0 Gefaellestrecke";"6220";"GF_5, GF_4, GF_3, GF_2, GF_1";20;1;;"0005, 0004, 0003, 0002, 0001";{"2950": "5", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4384": "Gefällestrecke", "4318": "8.851", "4391": "3", "4337": "1", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "3992": "Nein", "3993": "Schönenberger-Gerüst", "4300": "ein Objekt", "4311": "5"}
|
||||
5;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"4000": "Ja", "4400": "0", "4413": "0", "4401": "0", "4414": "0", "4402": "0", "4419": "0.00", "4403": "0", "4404": "0", "4425": "8", "4426": "0", "4407": "0", "4418": "62.35", "4408": "0", "4420": "0.0", "4409": "0", "4417": "0.0", "4410": "9", "4411": "0", "4421": "0", "4422": "0", "4100": "Ja"}
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 57.
|
@@ -5,20 +5,20 @@ Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;Boundingb
|
||||
4;"ILS 2.0 Strecke";"0004";"VF_4";"H/1-J/4";1;"18465.07, 4300.26, 2119.66";"2518.90, 6404.92, 848.78";"f///EdR0IN4QAAAAAAAAAAAA";"AqAYAC2kAFQk";"AwJzAC2kAFQk";"";"";"0006-L";"0038, 0039, 0040, 0041";"nur ein Partner";"";{"Typ": "Streckengruppe", "Seite_AS": "links", "Seite_ES": "links", "Winkel": "3,3", "VF_Winkel": "0,0,18", "DeltaH_mm": "0", "DeltaL_mm": "1907", "L_VF_m": "0.269,0.458,1.663", "L_GF_m": "4.166,1.658", "Montagehoehe_m": "2.154", "Hoehe_Von_mm": "2154", "Hoehe_Bis_mm": "2154", "Antriebfahrtrichtung": "horizontal,horizontal,Auf", "Anzahl_Separator": "2", "Anzahl_Scanner": "0"}
|
||||
5;"ILS 2.0 Strecke";"0005";"VF_5";"J/1-K/4";1;"22239.27, 4299.16, 2119.66";"2518.90, 6404.92, 848.78";"f///EdAoIN4QAAAAAAAAAAAA";"AzOGAC2ZAFQk";"A5XhAC2ZAFQk";"";"";"0006-L";"0042, 0043, 0044, 0045";"nur ein Partner";"";{"Typ": "Streckengruppe", "Seite_AS": "links", "Seite_ES": "links", "Winkel": "3,3", "VF_Winkel": "0,0,18", "DeltaH_mm": "0", "DeltaL_mm": "1907", "L_VF_m": "0.269,0.458,1.663", "L_GF_m": "4.166,1.658", "Montagehoehe_m": "2.154", "Hoehe_Von_mm": "2154", "Hoehe_Bis_mm": "2154", "Antriebfahrtrichtung": "horizontal,horizontal,Auf", "Anzahl_Separator": "4", "Anzahl_Scanner": "1"}
|
||||
6;"ILS 2.0 Kreisel";"0006";"Kreisel1";"A/1-M/1";1;"13594.00, 767.00, 2154.00";"24100.00, 800.00, 1.00";"F49AC7QYIN4QAAAAAAAAAAAA";"";"";"";"";"0005, 0004, 0003, 0002, 0001";"0021, 0022, 0007, 0008, 0024, 0029, 0010, 0030, 0033, 0012, 0034, 0037, 0014, 0038, 0041, 0016, 0042, 0045, 0018, 0020, 0023";"";"";{"Abstand (Kreiselachse A - Kreiselachse) in Meter": "23.3", "Anzahl der Separatoren": "4", "Kreiselart": "STANDARD", "Anzahl der Scanner": "4", "Anzahl der Rampen": "0", "Höhe in m": "2.15", "Drehrichtung": "UZS", "Drehung": 0, "Name": "Kreisel1", "Geruest fuer Einzelmodul": true}
|
||||
7;"ILS 2.0 Separator";"0007";"Separator :20";"A/1";1;"2414.95, 365.00, 2155.50";"209.90, 150.00, 3.00";"I+84BZHIIN4QAAAAAAAAAAAA";"AFv+AA5CAFQk";"";"";"";"0022, 0008";"";"";"";{"Zuordnung": "0006-R", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 0, "Typ": ""}
|
||||
7;"ILS 2.0 Separator";"0007";"Separator :20";"A/1";1;"2414.95, 365.00, 2155.50";"209.90, 150.00, 3.00";"I+84BZHIIN4QAAAAAAAAAAAA";"AFv+AA5CAFQk";"";"";"";"0022, 0008";"";"";"";{"Zuordnung": "0001", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 0, "Typ": ""}
|
||||
8;"ILS 2.0 Separator";"0008";"Separator :19";"B/1";1;"4056.38, 1165.90, 2155.50";"209.90, 150.00, 3.00";"Ps9qEcpMIN4QAAAAAAAAf///";"AKDLAC2LAFQk";"";"";"";"0007, 0024";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
9;"ILS 2.0 Scanner";"0009";"Scanner :6";"B/1";1;"4095.50, 804.10, 2154.00";"150.00, 280.00, 1.00";"Pn4MEcNEIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0008"}
|
||||
10;"ILS 2.0 Separator";"0010";"Separator :18";"D/1";1;"8555.49, 1169.50, 2155.50";"209.90, 150.00, 3.00";"f///EdhcIN4QAAAAAAAAf///";"AVCKAC2vAFQk";"";"";"";"0029, 0030";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
11;"ILS 2.0 Scanner";"0011";"Scanner :5";"D/1";1;"8598.69, 807.70, 2154.00";"150.00, 280.00, 1.00";"f///EdFUIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0010"}
|
||||
10;"ILS 2.0 Separator";"0010";"Separator :18";"D/1";1;"8555.49, 1169.50, 2155.50";"209.90, 150.00, 3.00";"f///EdhcIN4QAAAAAAAAf///";"AVCKAC2vAFQk";"";"";"";"0029, 0030";"";"";"";{"Zuordnung": "0002", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
11;"ILS 2.0 Scanner";"0011";"Scanner :5";"D/1";1;"8598.69, 807.70, 2154.00";"150.00, 280.00, 1.00";"f///EdFUIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"";{"Zuordnung": "0002", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0010"}
|
||||
12;"ILS 2.0 Separator";"0012";"Separator :17";"F/1";1;"12631.71, 1168.20, 2155.50";"209.90, 150.00, 3.00";"f///EdNIIN4QAAAAAAAAf///";"Ae/EAC2iAFQk";"";"";"";"0033, 0034";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
13;"ILS 2.0 Scanner";"0013";"Scanner :4";"F/1";1;"12669.10, 806.40, 2154.00";"150.00, 280.00, 1.00";"f///EcxAIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0012"}
|
||||
14;"ILS 2.0 Separator";"0014";"Separator :16";"H/1";1;"16799.72, 1171.70, 2155.50";"209.90, 150.00, 3.00";"f///EeD0IN4QAAAAAAAAf///";"ApKUAC3FAFQk";"";"";"";"0037, 0038";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
15;"ILS 2.0 Scanner";"0015";"Scanner :3";"H/1";1;"16839.52, 809.80, 2154.00";"150.00, 280.00, 1.00";"f///EdmIIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"Distanz-Zuordnung unsicher: 0006 (3270mm) vs. 0004 (3527mm)";{"Zuordnung": "0006-L", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0014"}
|
||||
16;"ILS 2.0 Separator";"0016";"Separator :15";"J/1";1;"20577.16, 1166.20, 2155.50";"209.90, 150.00, 3.00";"f///Ect4IN4QAAAAAAAAf///";"AyYjAC2OAFQk";"";"";"";"0041, 0042";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
17;"ILS 2.0 Scanner";"0017";"Scanner :2";"J/1";1;"20807.70, 804.30, 2154.00";"150.00, 280.00, 1.00";"f///EcQMIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"";{"Zuordnung": "0005", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0016"}
|
||||
17;"ILS 2.0 Scanner";"0017";"Scanner :2";"J/1";1;"20807.70, 804.30, 2154.00";"150.00, 280.00, 1.00";"f///EcQMIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0016"}
|
||||
18;"ILS 2.0 Separator";"0018";"Separator :14";"L/1";1;"23678.05, 1170.60, 2155.50";"209.90, 150.00, 3.00";"f///EdyoIN4QAAAAAAAAf///";"A59EAC26AFQk";"";"";"";"0045, 0020";"";"";"";{"Zuordnung": "0005", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
19;"ILS 2.0 Scanner";"0019";"Scanner :1";"L/1";1;"23780.80, 808.80, 2154.00";"150.00, 280.00, 1.00";"f///EdWgIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0018"}
|
||||
20;"ILS 2.0 Separator";"0020";"Separator :13";"L/1";1;"24570.15, 1167.20, 2155.50";"209.90, 150.00, 3.00";"f///Ec9gIN4QAAAAAAAAf///";"A8IdAC2YAFQk";"";"";"";"0018, 0023";"";"";"";{"Zuordnung": "0006-L", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
19;"ILS 2.0 Scanner";"0019";"Scanner :1";"L/1";1;"23780.80, 808.80, 2154.00";"150.00, 280.00, 1.00";"f///EdWgIN4QAAAAAAAApX2I";"";"";"";"";"";"";"";"";{"Zuordnung": "0005", "ARTINR": "829534306", "Höhe": "2154", "Drehung": 270, "Typ": "", "Naechster Separator": "0018"}
|
||||
20;"ILS 2.0 Separator";"0020";"Separator :13";"L/1";1;"24570.15, 1167.20, 2155.50";"209.90, 150.00, 3.00";"f///Ec9gIN4QAAAAAAAAf///";"A8IdAC2YAFQk";"";"";"";"0018, 0023";"";"";"";{"Zuordnung": "0005", "ARTINR": "200000077", "Höhe": "2154", "Drehung": 180, "Typ": ""}
|
||||
21;"ILS 2.0 BTMT Beladung";"0021";"BTMT Beladung :2";"B/1-C/1";1;"5532.67, 265.14, 2109.31";"652.35, 408.38, 316.02";"ULuUBaYYIN4QAAAAAAAAf/7S";"AON9AANLAFSv";"AMu/AA6CAFQk";"";"";"0023, 0022";"";"";"";{"ARTINR": "829662012", "Höhe": "2154", "Drehung": 179}
|
||||
22;"ILS 2.0 BTMT Beladung";"0022";"BTMT Beladung :1";"B/1";1;"4503.25, 269.77, 2109.31";"651.33, 406.70, 316.02";"QQVQBbW4IN4QAAAAAAAAf/8o";"ALtMAAOBAFSv";"AKOGAA6oAFQk";"";"";"0021, 0007";"";"";"";{"ARTINR": "829662012", "Höhe": "2154", "Drehung": 179}
|
||||
23;"ILS 2.0 BTMT Entladung";"0023";"BTMT Entladung :1";"L/1-M/1";1;"25014.37, 1545.51, 2001.09";"1475.51, 961.98, 467.01";"f///Edt8IN4QAAAAAAAAARVf";"A7q4AC1/AFQk";"A+0BAE7eAEX5";"";"";"0020, 0021";"";"";"";{"ARTINR": "400100156", "Höhe": "2154", "Drehung": 1}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 233.
|
@@ -1,9 +1,9 @@
|
||||
Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];IDs;details
|
||||
1;"ILS 2.0 Kreisel";"6200";"Kreisel12";20;1;;"0006";{"2952": "2.154", "3510": "Kreisel", "3511": "1", "3512": "23.3", "3515": "4", "3517": "4", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
1;"ILS 2.0 Kreisel";"6200";"Kreisel1";20;1;;"0006";{"2952": "2.154", "3511": "1", "3515": "4", "3517": "4", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "3510": "Kreisel", "3512": "23.3"}
|
||||
2;"ILS 2.0 Zusatzmodul";"6215";"";20;1;;"0022, 0021, 0023";{"3501": "Ja", "3503": "2", "3502": "Ja", "3504": "1"}
|
||||
3;"ILS 2.0 Strecke";"6220";"VF_9";20;1;;"0005";{"2950": "2.154", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "4", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "1", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
4;"ILS 2.0 Strecke";"6220";"VF_8";20;1;;"0004";{"2950": "2.154", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
5;"ILS 2.0 Strecke";"6220";"VF_7";20;1;;"0003";{"2950": "2.154", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
6;"ILS 2.0 Strecke";"6220";"VF_6";20;1;;"0002";{"2950": "2.154", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "3", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "1", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
7;"ILS 2.0 Strecke";"6220";"VF_5";20;1;;"0001";{"2950": "2.154", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.727", "4391": "3", "4314": "Ja", "4319": "0.201", "4392": "3", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "2", "4353": "3.704", "4354": "horizontal", "4386": "0", "4373": "0", "4374": "0", "4375": "1", "4376": "2", "4377": "0", "4378": "1", "4381": "5", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
3;"ILS 2.0 Strecke";"6220";"VF_5";20;1;;"0005";{"2950": "2.154", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "4", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "1", "3992": "Ja", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4433": "1.800", "4434": "1.800", "4435": "2.071"}
|
||||
4;"ILS 2.0 Strecke";"6220";"VF_4";20;1;;"0004";{"2950": "2.154", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4433": "1.800", "4434": "1.800", "4435": "2.071"}
|
||||
5;"ILS 2.0 Strecke";"6220";"VF_3";20;1;;"0003";{"2950": "2.154", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4433": "1.800", "4434": "1.800", "4435": "2.071"}
|
||||
6;"ILS 2.0 Strecke";"6220";"VF_2";20;1;;"0002";{"2950": "2.154", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "3", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "1", "3992": "Ja", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4433": "1.800", "4434": "1.800", "4435": "2.071"}
|
||||
7;"ILS 2.0 Strecke";"6220";"VF_1";20;1;;"0001";{"2950": "2.154", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "1", "4376": "2", "4377": "0", "4378": "1", "4381": "5", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "0.727", "4391": "3", "4314": "Ja", "4319": "0.201", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "2", "4353": "3.704", "4354": "horizontal", "4386": "0", "4433": "1.980", "4434": "1.980", "4435": "1.875", "4436": "2.076", "4437": "2.282"}
|
||||
8;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"4000": "Ja", "4400": "1", "4413": "4", "4401": "0", "4414": "0", "4402": "0", "4419": "23.30", "4403": "0", "4404": "0", "4425": "0", "4426": "0", "4407": "5", "4418": "0.00", "4408": "17", "4420": "0.0", "4409": "0", "4417": "0.0", "4410": "20", "4411": "6", "4421": "2", "4422": "1", "4100": "Ja"}
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 54.
|
@@ -3,7 +3,7 @@
|
||||
"test_id": "KR_Kreuz_Q1_0Grad",
|
||||
"status": "executed",
|
||||
"block_name": "KREISEL_1_STANDARD_2000",
|
||||
"block_handle": "13A",
|
||||
"block_handle": "186",
|
||||
"insert_point": [500, 500, 2500],
|
||||
"actual_attributes": {
|
||||
"ID": "0001",
|
||||
@@ -28,7 +28,7 @@
|
||||
"test_id": "KR_Kreuz_Q2_90Grad",
|
||||
"status": "executed",
|
||||
"block_name": "KREISEL_2_STANDARD_3000",
|
||||
"block_handle": "187",
|
||||
"block_handle": "1D7",
|
||||
"insert_point": [-500, 500, 2500],
|
||||
"actual_attributes": {
|
||||
"ID": "0002",
|
||||
@@ -53,7 +53,7 @@
|
||||
"test_id": "KR_Kreuz_Q3_180Grad",
|
||||
"status": "executed",
|
||||
"block_name": "KREISEL_3_STANDARD_4000",
|
||||
"block_handle": "1D3",
|
||||
"block_handle": "227",
|
||||
"insert_point": [-500, -500, 2500],
|
||||
"actual_attributes": {
|
||||
"ID": "0003",
|
||||
@@ -78,7 +78,7 @@
|
||||
"test_id": "KR_Kreuz_Q4_270Grad",
|
||||
"status": "executed",
|
||||
"block_name": "KREISEL_4_STANDARD_5000",
|
||||
"block_handle": "21F",
|
||||
"block_handle": "277",
|
||||
"insert_point": [500, -500, 2500],
|
||||
"actual_attributes": {
|
||||
"ID": "0004",
|
||||
@@ -103,7 +103,7 @@
|
||||
"test_id": "KR_Schraeg_Q1_30Grad",
|
||||
"status": "executed",
|
||||
"block_name": "KREISEL_5_STANDARD_3000",
|
||||
"block_handle": "26B",
|
||||
"block_handle": "2C7",
|
||||
"insert_point": [3000, 3000, 3000],
|
||||
"actual_attributes": {
|
||||
"ID": "0005",
|
||||
@@ -128,7 +128,7 @@
|
||||
"test_id": "KR_Pin_Q1_0Grad",
|
||||
"status": "executed",
|
||||
"block_name": "KREISEL_6_PIN_3000",
|
||||
"block_handle": "2BC",
|
||||
"block_handle": "31C",
|
||||
"insert_point": [500, 6000, 1500],
|
||||
"actual_attributes": {
|
||||
"ID": "0006",
|
||||
@@ -153,7 +153,7 @@
|
||||
"test_id": "KR_Pin_Q1_90Grad",
|
||||
"status": "executed",
|
||||
"block_name": "KREISEL_7_PIN_4000",
|
||||
"block_handle": "30C",
|
||||
"block_handle": "370",
|
||||
"insert_point": [-500, 6500, 1500],
|
||||
"actual_attributes": {
|
||||
"ID": "0007",
|
||||
@@ -178,7 +178,7 @@
|
||||
"test_id": "KR_Pin_Q1_30Grad_Schraeg",
|
||||
"status": "executed",
|
||||
"block_name": "KREISEL_8_PIN_3000",
|
||||
"block_handle": "35C",
|
||||
"block_handle": "3C4",
|
||||
"insert_point": [3000, 8000, 1500],
|
||||
"actual_attributes": {
|
||||
"ID": "0008",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];IDs;details
|
||||
1;"ILS 2.0 Kreisel";"6200";"Kreisel8, Kreisel6";20;2;;"0008, 0006";{"2952": "1.5", "3510": "Kreisel mit PINBAND", "3511": "1", "3512": "3.0", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
2;"ILS 2.0 Kreisel";"6200";"Kreisel7";20;1;;"0007";{"2952": "1.5", "3510": "Kreisel mit PINBAND", "3511": "1", "3512": "4.0", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
3;"ILS 2.0 Kreisel";"6200";"Kreisel5, Kreisel2";20;2;;"0005, 0002";{"2952": "3", "3510": "Kreisel", "3511": "1", "3512": "3.0", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
4;"ILS 2.0 Kreisel";"6200";"Kreisel4";20;1;;"0004";{"2952": "2.5", "3510": "Kreisel", "3511": "1", "3512": "5.0", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
5;"ILS 2.0 Kreisel";"6200";"Kreisel3";20;1;;"0003";{"2952": "2.5", "3510": "Kreisel", "3511": "1", "3512": "4.0", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
6;"ILS 2.0 Kreisel";"6200";"Kreisel1";20;1;;"0001";{"2952": "2.5", "3510": "Kreisel", "3511": "1", "3512": "2.0", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst"}
|
||||
7;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"4000": "Ja", "4400": "8", "4413": "0", "4401": "3", "4414": "0", "4402": "0", "4419": "27.00", "4403": "0", "4404": "0", "4425": "0", "4426": "0", "4407": "0", "4418": "0.00", "4408": "0", "4420": "0.0", "4409": "0", "4417": "0.0", "4410": "0", "4411": "0", "4421": "0", "4422": "0", "4100": "Ja"}
|
||||
1;"ILS 2.0 Kreisel";"6200";"Kreisel8, Kreisel6";20;2;;"0008, 0006";{"2952": "1.5", "3511": "1", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "3510": "Kreisel mit PINBAND", "3512": "3.0"}
|
||||
2;"ILS 2.0 Kreisel";"6200";"Kreisel7";20;1;;"0007";{"2952": "1.5", "3511": "1", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "3510": "Kreisel mit PINBAND", "3512": "4.0"}
|
||||
3;"ILS 2.0 Kreisel";"6200";"Kreisel5";20;1;;"0005";{"2952": "3", "3511": "1", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "3510": "Kreisel", "3512": "3.0"}
|
||||
4;"ILS 2.0 Kreisel";"6200";"Kreisel4";20;1;;"0004";{"2952": "2.5", "3511": "1", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "3510": "Kreisel", "3512": "5.0"}
|
||||
5;"ILS 2.0 Kreisel";"6200";"Kreisel3";20;1;;"0003";{"2952": "2.5", "3511": "1", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "3510": "Kreisel", "3512": "4.0"}
|
||||
6;"ILS 2.0 Kreisel";"6200";"Kreisel2";20;1;;"0002";{"2952": "2.5", "3511": "1", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "3510": "Kreisel", "3512": "3.0"}
|
||||
7;"ILS 2.0 Kreisel";"6200";"Kreisel1";20;1;;"0001";{"2952": "2.5", "3511": "1", "3515": "0", "3517": "0", "3519": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "3510": "Kreisel", "3512": "2.0"}
|
||||
8;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"4000": "Ja", "4400": "8", "4413": "0", "4401": "3", "4414": "0", "4402": "0", "4419": "27.00", "4403": "0", "4404": "0", "4425": "0", "4426": "0", "4407": "0", "4418": "0.00", "4408": "0", "4420": "0.0", "4409": "0", "4417": "0.0", "4410": "0", "4411": "0", "4421": "0", "4422": "0", "4100": "Ja"}
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 69.
|
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"test_id": "LZ_Standard",
|
||||
"status": "OK",
|
||||
"schritte_gesamt": 37,
|
||||
"schritte_gesamt": 34,
|
||||
"schritte_offen": 0
|
||||
}
|
||||
]
|
||||
@@ -1,3 +1,3 @@
|
||||
Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];IDs;details
|
||||
1;"ILS 2.0 Strecke";"6220";"VF_1";20;1;;"0001";{"Anlagenhöhe in Meter": "2.154", "Streckengruppe": "mehrere Objekte", "Strecken- zu fertigende Menge": "1", "Streckengruppe - Gefällestrecke": "Ja", "Streckengruppe - Gefällestrecke 001-Länge in Meter": "4.166", "Streckengruppe - Gefällestrecke 001 -Winkel": "3", "Streckengruppe - Gefällestrecke 002": "Ja", "Streckengruppe - Gefällestrecke 002-Länge in Meter": "1.658", "Streckengruppe - Gefällestrecke 002- Winkel": "3", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke links 30°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 90°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 60°": "0", "Streckengruppe - Anzahl der Kurven - Gefällestrecke rechts 30°": "0", "Streckengruppe - Anzahl der Separatoren - Gefällestrecke": "0", "Streckengruppe - Bearbeitung Gefällestreckenteilstück für Separator (829516050)": "ohne HARTCOAT HRC 50 ± 5", "Streckengruppe - Anzahl der Scanner": "0", "Streckengruppe - Varioförderer": "Ja", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (links)": "0", "Streckengruppe - Anzahl der Motoren für Vario-Förderer (rechts)": "1", "Streckengruppe - Varioförderer 001-Länge in Meter": "0.269", "Streckengruppe - Varioförderer 001-Richtung": "horizontal", "Streckengruppe - Varioförderer 001- Winkel": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 90°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Außenbogen 30°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 90°": "2", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 60°": "0", "Streckengruppe - Anzahl der Kurven - Varioförderer Innenbogen 30°": "0", "Streckengruppe - Anzahl der Separatoren - Varioförderer": "2", "Gerüst für Einzelmodul": "Ja", "Gerüstoption für Einzelmodul": "Schönenberger-Gerüst"}
|
||||
2;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"Automation": "Ja", "Anzahl der Kreisel": "0", "Anzahl der Separatoren - Kreisel ohne PINBAND": "0", "Anzahl der Kreisel mit PINBAND": "0", "Anzahl der Separatoren - Kreisel mit PINBAND": "0", "Anzahl der Verbindungskreisel": "0", "Längen aller Kreisel": "0.00", "Anzahl der Weichen": "0", "Anzahl der Eckräder": "0", "Anzahl der einzelnen Gefällestrecken": "0", "Anzahl der einzelnen Vario-Förderer": "0", "Anzahl der Streckengruppen": "1", "Längen aller Gefällestrecken": "0.00", "Anzahl der Motoren in Vario - Förderer": "3", "Längen aller Vario - Förderer": "0.0", "Anzahl der ETFs": "0", "Längen aller ETFS und Zusatzstücke (Gefällestrecken)": "0.0", "Anzahl der Separatoren in der Anlage": "2", "Anzahl der Scanner in der Anlage": "0", "Zusatzmodul - Anzahl der BT-Beladung": "0", "Zusatzmodul - Anzahl der Abwurfstation": "0", "Pneumatik": "Ja"}
|
||||
1;"ILS 2.0 Strecke";"6220";"VF_1";20;1;;"0001";{"2950": "2.154", "4431": "Ja", "4427": "90 °", "4428": "links", "4432": "Ja", "4429": "90 °", "4430": "links", "4329": "0", "4330": "0", "4331": "0", "4332": "0", "4333": "0", "4334": "0", "4373": "0", "4374": "0", "4375": "0", "4376": "2", "4377": "0", "4378": "0", "4381": "2", "4382": "ohne HARTCOAT HRC 50 ± 5", "4383": "0", "3992": "Ja", "3993": "Schönenberger-Gerüst", "4300": "mehrere Objekte", "4311": "1", "4312": "Ja", "4318": "4.166", "4391": "3", "4314": "Ja", "4319": "1.658", "4392": "3", "4337": "0", "4338": "ohne HARTCOAT HRC 50 ± 5", "4339": "0", "4340": "Ja", "4341": "0", "4342": "1", "4353": "0.269", "4354": "horizontal", "4386": "0", "4433": "1.800", "4434": "1.800", "4435": "2.071"}
|
||||
2;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";"";20;1;;"";{"4000": "Ja", "4400": "0", "4413": "0", "4401": "0", "4414": "0", "4402": "0", "4419": "0.00", "4403": "0", "4404": "0", "4425": "0", "4426": "0", "4407": "1", "4418": "0.00", "4408": "3", "4420": "0.0", "4409": "0", "4417": "0.0", "4410": "2", "4411": "0", "4421": "0", "4422": "0", "4100": "Ja"}
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 49.
|
@@ -183,6 +183,7 @@
|
||||
(if (findfile csv-pfad) (vl-file-delete csv-pfad))
|
||||
(if (findfile sivas-pfad) (vl-file-delete sivas-pfad))
|
||||
|
||||
(setq *csv-hoehencheck-fragen* nil) ;; keine Rueckfrage im Testlauf
|
||||
(princ (strcat "\n[TEST_EXPORT_ALL] CSV-Export -> " csv-name))
|
||||
(c:EXPORTCSV)
|
||||
(setq csv-ok (export_all:wait-for-file csv-pfad 30.0))
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_export_freie_separatoren.py - freie Separatoren in der Kette einer Strecke.
|
||||
Laeuft komplett ohne BricsCAD (reine Python-Logik, siehe lib/export_neighbors.py).
|
||||
|
||||
Szenario nach einem realen Mubea-Befund (VF_3 = 0015): die sepliste aus dem
|
||||
Bau kennt nur AS 0061, SEP 0062, SEP 0063, ES 0064. Die eigenstaendigen
|
||||
Separatoren 0037/0038 liegen auf der Strecke, ihre Zuordnung nennt 0015 - sie
|
||||
fehlten aber in TrackIds und Nachbarn. einsortieren_freie_separatoren nimmt
|
||||
sie nach Lage auf.
|
||||
|
||||
Alle Daten sind hier fest eingetragen (Stand des Mubea-Exports 2026-10-28) und
|
||||
werden aus keiner Datei gelesen - aendert sich die Mubea-Zeichnung, bleibt
|
||||
dieser Test unberuehrt. Er prueft den Algorithmus, nicht die Szene.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
|
||||
|
||||
from export_neighbors import ( # noqa: E402
|
||||
compute_sep_kette,
|
||||
einsortieren_freie_separatoren,
|
||||
sepliste_einsortier_positionen,
|
||||
)
|
||||
from export_csv import ( # noqa: E402
|
||||
map_sepliste_kette_items,
|
||||
resolve_umlauf_und_sepliste_nachbarn,
|
||||
write_separatorliste_merkmale,
|
||||
)
|
||||
|
||||
TOL_MM = 100.0
|
||||
|
||||
|
||||
def _sep(teileid, x, y, zuordnung):
|
||||
return {
|
||||
"teileart": "ILS 2.0 Separator",
|
||||
"teileid": teileid,
|
||||
"merkmale": {"Zuordnung": zuordnung},
|
||||
"nachbarn": "",
|
||||
"_bbox": {"cx": x, "cy": y, "cz": 0.0, "dx": 150.0, "dy": 210.0},
|
||||
}
|
||||
|
||||
|
||||
def _ases(teileart, teileid, x, y, zuordnung):
|
||||
return {
|
||||
"teileart": teileart,
|
||||
"teileid": teileid,
|
||||
"_zuordnung": zuordnung,
|
||||
"merkmale": {},
|
||||
"nachbarn": "",
|
||||
"_bbox": {"cx": x, "cy": y, "cz": 0.0, "dx": 200.0, "dy": 200.0},
|
||||
}
|
||||
|
||||
|
||||
def _mubea_vf3():
|
||||
strecke = {
|
||||
"teileart": "ILS 2.0 Strecke",
|
||||
"teileid": "0015",
|
||||
"nachbarn": "0002-L",
|
||||
"merkmale": {},
|
||||
"k1": "", "k2": "",
|
||||
"_bbox": {"cx": -631.28, "cy": 6543.11, "cz": 1624.70,
|
||||
"dx": 1018.09, "dy": 12791.0},
|
||||
"sepliste": [
|
||||
{"typ": "AS", "lfdnr": 1, "id": "0061"},
|
||||
{"typ": "SEP", "lfdnr": 2, "id": "0062"},
|
||||
{"typ": "SEP", "lfdnr": 3, "id": "0063"},
|
||||
{"typ": "ES", "lfdnr": 4, "id": "0064"},
|
||||
],
|
||||
}
|
||||
return [
|
||||
strecke,
|
||||
_ases("ILS Ausschleuselement", "0061", -400.00, 270.54, "0015"),
|
||||
_sep("0062", -898.87, 1134.60, "0015"),
|
||||
_sep("0063", -702.98, 12307.81, "0015"),
|
||||
_ases("ILS Einschleuselement", "0064", -400.00, 12832.58, "0015"),
|
||||
_sep("0037", -1026.00, 10723.05, "0015"),
|
||||
_sep("0038", -1026.00, 5250.05, "0015"),
|
||||
]
|
||||
|
||||
|
||||
def _by_id(items, teileid):
|
||||
return next(it for it in items if it.get("teileid") == teileid)
|
||||
|
||||
|
||||
def _pipeline(items):
|
||||
einsortieren_freie_separatoren(items, TOL_MM)
|
||||
sep_kette = compute_sep_kette(items)
|
||||
sep_kette_by_key = map_sepliste_kette_items(items, sep_kette)
|
||||
write_separatorliste_merkmale(items, sep_kette_by_key)
|
||||
resolve_umlauf_und_sepliste_nachbarn(items, {}, sep_kette, sep_kette_by_key, {})
|
||||
return items
|
||||
|
||||
|
||||
class TestEinsortierPositionen:
|
||||
"""Reiner Rechenkern, ohne Items."""
|
||||
|
||||
KETTE = [(0.0, 0.0), (0.0, 1000.0), (0.0, 5000.0), (0.0, 6000.0)]
|
||||
|
||||
def test_zwei_kandidaten_im_selben_abschnitt_sortiert(self):
|
||||
einfuegen, verworfen = sepliste_einsortier_positionen(
|
||||
self.KETTE, [("B", 50.0, 4000.0), ("A", -50.0, 2000.0)])
|
||||
assert einfuegen == {1: ["A", "B"]}
|
||||
assert verworfen == []
|
||||
|
||||
def test_vor_as_und_hinter_es_verworfen(self):
|
||||
einfuegen, verworfen = sepliste_einsortier_positionen(
|
||||
self.KETTE, [("vor", 0.0, -500.0), ("hinter", 0.0, 6500.0)])
|
||||
assert einfuegen == {}
|
||||
assert sorted(verworfen) == ["hinter", "vor"]
|
||||
|
||||
def test_kette_um_eine_kurve(self):
|
||||
"""Polygonzug statt Gerade AS->ES: ein Separator auf dem zweiten
|
||||
Schenkel einer L-Kette gehoert in DEN Abschnitt, nicht nach
|
||||
seiner Projektion auf die Diagonale."""
|
||||
kette = [(0.0, 0.0), (0.0, 3000.0), (3000.0, 3000.0)]
|
||||
einfuegen, _ = sepliste_einsortier_positionen(kette, [("S", 1500.0, 3050.0)])
|
||||
assert einfuegen == {1: ["S"]}
|
||||
|
||||
def test_entartete_kette(self):
|
||||
einfuegen, verworfen = sepliste_einsortier_positionen(
|
||||
[(0.0, 0.0), (0.0, 0.0)], [("S", 10.0, 10.0)])
|
||||
assert einfuegen == {}
|
||||
assert verworfen == ["S"]
|
||||
|
||||
|
||||
class TestMubeaVf3:
|
||||
|
||||
def test_trackids_mit_freien_separatoren(self):
|
||||
items = _pipeline(_mubea_vf3())
|
||||
assert _by_id(items, "0015").get("trackids") == \
|
||||
"0061, 0062, 0038, 0037, 0063, 0064"
|
||||
|
||||
def test_nachbarn_der_kette(self):
|
||||
items = _pipeline(_mubea_vf3())
|
||||
assert _by_id(items, "0062")["nachbarn"] == "0061, 0038"
|
||||
assert _by_id(items, "0038")["nachbarn"] == "0062, 0037"
|
||||
assert _by_id(items, "0037")["nachbarn"] == "0038, 0063"
|
||||
assert _by_id(items, "0063")["nachbarn"] == "0037, 0064"
|
||||
|
||||
def test_hinweis_am_freien_separator(self):
|
||||
items = _pipeline(_mubea_vf3())
|
||||
assert "0015" in _by_id(items, "0037").get("warnung", "")
|
||||
assert _by_id(items, "0062").get("warnung", "") == ""
|
||||
|
||||
def test_merkmal_einsortiert_in(self):
|
||||
items = _pipeline(_mubea_vf3())
|
||||
assert _by_id(items, "0037")["merkmale"].get("Einsortiert in") == "0015"
|
||||
assert _by_id(items, "0038")["merkmale"].get("Einsortiert in") == "0015"
|
||||
assert "Einsortiert in" not in _by_id(items, "0062")["merkmale"]
|
||||
|
||||
def test_fremde_zuordnung_bleibt_draussen(self):
|
||||
items = _mubea_vf3()
|
||||
_by_id(items, "0037")["merkmale"]["Zuordnung"] = "0002-L"
|
||||
_pipeline(items)
|
||||
assert _by_id(items, "0015").get("trackids") == "0061, 0062, 0038, 0063, 0064"
|
||||
|
||||
def test_ausserhalb_der_strecken_bbox_bleibt_draussen(self):
|
||||
items = _mubea_vf3()
|
||||
_by_id(items, "0038")["_bbox"]["cx"] = -3000.0
|
||||
_pipeline(items)
|
||||
assert _by_id(items, "0015").get("trackids") == "0061, 0062, 0037, 0063, 0064"
|
||||
|
||||
def test_ohne_ids_kein_einsortieren(self):
|
||||
"""Altbestand ohne aufgeloeste IDs: Glieder nicht lokalisierbar ->
|
||||
sepliste bleibt wie gebaut."""
|
||||
items = _mubea_vf3()
|
||||
for e in _by_id(items, "0015")["sepliste"]:
|
||||
e["id"] = ""
|
||||
einsortieren_freie_separatoren(items, TOL_MM)
|
||||
assert len(_by_id(items, "0015")["sepliste"]) == 4
|
||||
@@ -0,0 +1,181 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_export_sivas_as_es.py - Sivas-Merkmale 4427-4432 (AS-/ES-Element) fuer
|
||||
Gefaellestrecke (GF_N) und Streckengruppe (VF_N).
|
||||
|
||||
Pruefpunkte: Vorhandensein haengt am Winkel (nicht an der Seite, die immer
|
||||
einen Vorgabewert traegt), der Winkel wird in die Sivas-Schreibweise der
|
||||
Auswahlliste uebersetzt, ohne Element bleiben Winkel UND Seite leer, die
|
||||
Zuordnung steht vollstaendig in cfg/sivas.cfg, und die GF-Gruppierung trennt
|
||||
Bloecke mit unterschiedlichem AS-/ES-Element.
|
||||
|
||||
Laeuft komplett ohne BricsCAD (reine Python-Logik).
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
|
||||
|
||||
import export_sivas # noqa: E402
|
||||
import sivas_mapping # noqa: E402
|
||||
|
||||
# Sivas-Schreibweise der Winkel-Auswahlliste (cfg/sivas.cfg
|
||||
# [as_es_winkel_anzeige]) - die Tests vergleichen gegen die Config, damit ein
|
||||
# Nachziehen der Schreibweise dort nicht die halbe Testdatei bricht.
|
||||
W30 = export_sivas.as_es_winkel("30")
|
||||
W90 = export_sivas.as_es_winkel("90")
|
||||
|
||||
|
||||
def _strecke(nr, typ="Gefaellestrecke", **attr):
|
||||
"""GF_N-/VF_N-Block mit dem gemeinsamen Strecken-Attributschema."""
|
||||
attribs = {"ID": f"000{nr}", "Bezeichnung": f"GF_{nr}", "ARTINR": "6220",
|
||||
"MONTAGEHOEHE_m": "2.000", "HOEHE_VON_mm": "2000",
|
||||
"HOEHE_BIS_mm": "1000", "TYP": typ,
|
||||
"L_GF_m": "3.000", "GF_WINKEL": "3",
|
||||
"SEITE_AS": "links", "WINKEL_AS": "90",
|
||||
"SEITE_ES": "links", "WINKEL_ES": "90"}
|
||||
attribs.update(attr)
|
||||
return {"block_name": f"GF_{nr}", "x": 0.0, "y": 0.0, "z": 2000.0,
|
||||
"rotation": 0.0, "attribs": attribs}
|
||||
|
||||
|
||||
def test_as_es_vorhanden_mit_winkel_und_seite():
|
||||
details = export_sivas.build_gefaellestrecke_details(_strecke(1))
|
||||
assert details["4431"] == "Ja"
|
||||
assert details["4427"] == W90
|
||||
assert details["4428"] == "links"
|
||||
assert details["4432"] == "Ja"
|
||||
assert details["4429"] == W90
|
||||
assert details["4430"] == "links"
|
||||
|
||||
|
||||
def test_zuordnung_steht_in_der_config():
|
||||
"""Die sechs Merkmale muessen in BEIDEN Strecken-Abschnitten von
|
||||
sivas.cfg stehen (GF_N und VF_N lesen dieselben Attribute)."""
|
||||
for abschnitt in ("gefaellestrecke", "variofoerderer"):
|
||||
mapping = sivas_mapping.load_section_mapping(abschnitt)
|
||||
for merkmal, attribut, transform in (
|
||||
("4431", "WINKEL_AS", "as_es_vorhanden"),
|
||||
("4427", "WINKEL_AS", "as_es_winkel"),
|
||||
("4428", "SEITE_AS", "as_seite"),
|
||||
("4432", "WINKEL_ES", "as_es_vorhanden"),
|
||||
("4429", "WINKEL_ES", "as_es_winkel"),
|
||||
("4430", "SEITE_ES", "es_seite")):
|
||||
assert merkmal in mapping, f"{merkmal} fehlt in [{abschnitt}]"
|
||||
ist_attribut, _alt, _default, ist_transform = mapping[merkmal]
|
||||
assert ist_attribut == attribut, f"[{abschnitt}] {merkmal}"
|
||||
assert ist_transform == transform, f"[{abschnitt}] {merkmal}"
|
||||
assert ist_transform in export_sivas.TRANSFORMS
|
||||
|
||||
|
||||
def test_winkel_in_sivas_schreibweise():
|
||||
"""4427/4429 tragen den Optionswert der Auswahlliste, nicht die nackte
|
||||
Attributzahl (Vorgabe aus cfg/sivas.cfg [as_es_winkel_anzeige])."""
|
||||
details = export_sivas.build_gefaellestrecke_details(
|
||||
_strecke(1, WINKEL_AS="30", WINKEL_ES="90.0"))
|
||||
assert details["4427"] == W30
|
||||
assert details["4429"] == W90
|
||||
# Unbekannter Winkel faellt auf die ganzzahlige Rohzahl zurueck
|
||||
assert export_sivas.as_es_winkel("60.0") in (W30, W90, "60")
|
||||
|
||||
|
||||
def test_ohne_winkel_kein_element_und_keine_seite():
|
||||
"""Leerer WINKEL_AS = kein AS-Element; die Seite darf dann NICHT
|
||||
durchgereicht werden (SEITE_AS traegt mit "rechts" immer einen
|
||||
Schema-Vorgabewert)."""
|
||||
details = export_sivas.build_gefaellestrecke_details(
|
||||
_strecke(1, WINKEL_AS="", SEITE_AS="rechts"))
|
||||
assert details["4431"] == "Nein"
|
||||
assert details["4427"] == ""
|
||||
assert details["4428"] == ""
|
||||
# ES bleibt davon unberuehrt
|
||||
assert details["4432"] == "Ja"
|
||||
assert details["4430"] == "links"
|
||||
|
||||
|
||||
def test_seite_rechts():
|
||||
details = export_sivas.build_gefaellestrecke_details(
|
||||
_strecke(1, SEITE_AS="rechts", SEITE_ES="rechts"))
|
||||
assert details["4428"] == "rechts"
|
||||
assert details["4430"] == "rechts"
|
||||
|
||||
|
||||
def test_variofoerderer_hat_dieselben_merkmale():
|
||||
block = _strecke(1, typ="Streckengruppe", L_VF_m="2.000", VF_WINKEL="0",
|
||||
ANTRIEBFAHRTRICHTUNG="Auf", MOTORSEITE="rechts",
|
||||
WINKEL_AS="30", SEITE_AS="rechts")
|
||||
details = export_sivas.build_variofoerderer_details(block)
|
||||
assert details["4431"] == "Ja"
|
||||
assert details["4427"] == W30
|
||||
assert details["4428"] == "rechts"
|
||||
assert details["4429"] == W90
|
||||
|
||||
|
||||
def test_gruppierung_trennt_nach_as_seite():
|
||||
"""Sonst baugleiche Gefaellestrecken mit AS links bzw. rechts duerfen
|
||||
nicht in einer Sivas-Zeile landen (die Zeile wuerde nur eine der beiden
|
||||
Seiten zeigen)."""
|
||||
links = export_sivas.gefaellestrecke_signature(_strecke(1, SEITE_AS="links"))
|
||||
rechts = export_sivas.gefaellestrecke_signature(_strecke(2, SEITE_AS="rechts"))
|
||||
assert links != rechts
|
||||
assert links == export_sivas.gefaellestrecke_signature(_strecke(3, SEITE_AS="links"))
|
||||
|
||||
|
||||
def test_gruppierung_trennt_nach_as_winkel():
|
||||
assert (export_sivas.gefaellestrecke_signature(_strecke(1, WINKEL_AS="30"))
|
||||
!= export_sivas.gefaellestrecke_signature(_strecke(2, WINKEL_AS="90")))
|
||||
|
||||
|
||||
def test_gruppierung_ohne_element_ignoriert_die_seite():
|
||||
"""Ohne AS-Element ist die Seite bedeutungslos und steht auch nicht in der
|
||||
Zeile - sie darf die Gruppierung dann nicht aufspalten."""
|
||||
assert (export_sivas.gefaellestrecke_signature(
|
||||
_strecke(1, WINKEL_AS="", SEITE_AS="links"))
|
||||
== export_sivas.gefaellestrecke_signature(
|
||||
_strecke(2, WINKEL_AS="", SEITE_AS="rechts")))
|
||||
|
||||
|
||||
def test_reihenfolge_im_details_json():
|
||||
"""Die sechs Merkmale stehen im details-JSON direkt HINTER 2950
|
||||
(Anlagenhoehe) - so vorgegeben, und so steht es in beiden Abschnitten von
|
||||
sivas.cfg. Die Reihenfolge der JSON-Keys folgt der Zeilenreihenfolge der
|
||||
Config (configparser und dict erhalten beide die Einfuegereihenfolge)."""
|
||||
erwartet = ["2950", "4431", "4427", "4428", "4432", "4429", "4430"]
|
||||
gf = list(export_sivas.build_gefaellestrecke_details(_strecke(1)))
|
||||
vf = list(export_sivas.build_variofoerderer_details(
|
||||
_strecke(2, typ="Streckengruppe", L_VF_m="2.000")))
|
||||
assert gf[:len(erwartet)] == erwartet
|
||||
assert vf[:len(erwartet)] == erwartet
|
||||
|
||||
|
||||
def test_altbestand_ohne_die_attribute():
|
||||
"""Bloecke aus Zeichnungen, die vor der Einfuehrung von WINKEL_AS gebaut
|
||||
wurden, haben die Attribute gar nicht - dann greift der leere Default und
|
||||
es wird "Nein" gemeldet (statt KeyError). Das ist die einzig moegliche
|
||||
Aussage: Sivas kennt nur Ja/Nein, kein "unbekannt"."""
|
||||
block = _strecke(1)
|
||||
for tag in ("WINKEL_AS", "SEITE_AS", "WINKEL_ES", "SEITE_ES"):
|
||||
del block["attribs"][tag]
|
||||
details = export_sivas.build_gefaellestrecke_details(block)
|
||||
assert details["4431"] == "Nein"
|
||||
assert details["4432"] == "Nein"
|
||||
assert details["4427"] == details["4428"] == ""
|
||||
assert details["4429"] == details["4430"] == ""
|
||||
|
||||
|
||||
def test_transform_mit_attribs_kontext():
|
||||
"""Der @braucht_attribs-Transform muss das komplette Attribut-Dict sehen -
|
||||
sonst koennte die Seite ihre Abhaengigkeit vom Winkel nicht pruefen."""
|
||||
assert getattr(export_sivas.as_seite, "braucht_attribs", False)
|
||||
assert getattr(export_sivas.es_seite, "braucht_attribs", False)
|
||||
assert not getattr(export_sivas.ja_nein, "braucht_attribs", False)
|
||||
|
||||
mapping = {"4428": ("SEITE_AS", None, "", "as_seite")}
|
||||
attribs = {"SEITE_AS": "links", "WINKEL_AS": "90"}
|
||||
assert sivas_mapping.anwenden(mapping, attribs, export_sivas.TRANSFORMS) \
|
||||
== {"4428": "links"}
|
||||
attribs_ohne = {"SEITE_AS": "links", "WINKEL_AS": ""}
|
||||
assert sivas_mapping.anwenden(mapping, attribs_ohne, export_sivas.TRANSFORMS) \
|
||||
== {"4428": ""}
|
||||
@@ -100,7 +100,7 @@ def test_geruest_unveraendert():
|
||||
assert zeilen["825002022"]["anzahl"] == 2
|
||||
assert zeilen["825002022"]["teileart"] == "Geruest Saeule 2 Zoll"
|
||||
assert zeilen["825002022"]["ids"] == ["0060"]
|
||||
assert zeilen["825002022"]["dispgruppe"] == 20
|
||||
assert zeilen["825002022"]["dispgruppe"] == 30
|
||||
# Ohne TEILEFARBE kein Farb-Merkmal
|
||||
assert zeilen["825002022"]["details"] == {}
|
||||
|
||||
|
||||
@@ -26,12 +26,14 @@
|
||||
;; also genau die Werte, mit denen die Ketten in BricsCAD gebaut wurden.
|
||||
;;
|
||||
;; JSON-Aufbau (FLACH, weil ssg-load-json zeilenweise liest - Details in
|
||||
;; tests/testdata/object_data.md Abschnitt 8):
|
||||
;; doc/json-input-lisp.md Abschnitt 6):
|
||||
;; Kopf-Objekt (traegt "test_id"): test_id, anlagetyp, modus,
|
||||
;; anzahl_eingaben, block, dxf_handle, startpunkt_mm,
|
||||
;; rotation_grad, beschreibung, sivas_* , erwartung_hinweis
|
||||
;; Eingabe-Objekt (traegt "typ"): point_abs | point_rel | real | int |
|
||||
;; string | step - in exakter Frage-Reihenfolge
|
||||
;; string | step | nil - in exakter Frage-Reihenfolge
|
||||
;; ("nil" = Frage gestellt und bewusst uebergangen, z.B.
|
||||
;; keine Zufuehrungsachse gewaehlt)
|
||||
;; Ein Kopf-Objekt beginnt eine Kette, die folgenden Eingabe-Objekte gehoeren
|
||||
;; dazu (hmrec:gruppiere).
|
||||
;;
|
||||
@@ -291,6 +293,13 @@
|
||||
(list (cons "STR" (hmrec:als-string (ssg-val e "wert")))))
|
||||
((= typ "step")
|
||||
(list (cons "STEP" (hmrec:als-string (ssg-val e "wert")))))
|
||||
;; Eine Frage, die gestellt und bewusst uebergangen wurde (bisher nur die
|
||||
;; Zufuehrungsachse des AS-Elements, siehe ProtokollSink.as_achse in
|
||||
;; lib/vf_journal_export.py) - im Journal ein wertloser "NIL"-Eintrag.
|
||||
;; Er MUSS mitlaufen: beim Replay poppt ihn vfl-in-point, sonst zoege
|
||||
;; dieser Aufruf den naechsten Wert aus der Queue (Desync).
|
||||
((= typ "nil")
|
||||
(list (cons "NIL" nil)))
|
||||
(T nil)
|
||||
)
|
||||
)
|
||||
@@ -468,6 +477,7 @@
|
||||
;; aufgehen und warten).
|
||||
(setq *hmrec-alt-wizard* (if (boundp '*vfl-wizard-mode*) *vfl-wizard-mode*))
|
||||
(setq *vfl-wizard-mode* nil)
|
||||
(setq *hmrec-alt-gui* (if (boundp '*ssg-gui-aus*) *ssg-gui-aus*))
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AUS"))) (ssg-gui-aus))
|
||||
;; Headless-Riegel der Produktion einschalten: eine erschoepfte Replay-Queue
|
||||
;; ist dann ein harter, lokalisierter Abbruch statt eines stillen Rueckfalls
|
||||
@@ -488,7 +498,7 @@
|
||||
alert *hmrec-alt-alert*)
|
||||
(setq *vfl-wizard-mode* *hmrec-alt-wizard*)
|
||||
(setq *vfl-headless* *hmrec-alt-headless*)
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AN"))) (ssg-gui-an))
|
||||
(setq *ssg-gui-aus* *hmrec-alt-gui*) ; Vorzustand, nicht pauschal an
|
||||
(princ)
|
||||
)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Zwei Ebenen:
|
||||
|
||||
Die Testdaten stammen aus lib/vf_journal_export.py (Journale der VF_n-Bloecke
|
||||
aus data/polylines.dxf, XDATA-App SSG_VF_EDIT) und nicht aus Handarbeit -
|
||||
Schema siehe tests/testdata/object_data.md Abschnitt 8.
|
||||
Schema siehe doc/json-input-lisp.md Abschnitt 6.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
;; hundm05.json auch andere Objekte der Anlage stehen - erkennbar an
|
||||
;; "function". Format wie in tests/testdata/kreisel_tests.json, damit die
|
||||
;; Felder nicht zweimal beschrieben werden muessen (Schema: siehe
|
||||
;; tests/testdata/object_data.md Abschnitt 1).
|
||||
;; doc/json-input-lisp.md Abschnitt 1).
|
||||
;; vsp-gruppieren ignoriert diese Objekte, sie stoeren die Ketten also nicht.
|
||||
;; lib/vf_spec_export.py uebernimmt sie beim Neuerzeugen der Spec-Daten
|
||||
;; unveraendert ans Dateiende (sonst waeren sie beim naechsten Lauf weg).
|
||||
@@ -61,7 +61,7 @@
|
||||
;; Unterstuetzt: Kreisel (function "insert", wie test_kreisel.lsp) und
|
||||
;; beliebige eigenstaendige Bloecke ueber "block" (Separator/Scanner sowie
|
||||
;; BTMT-Beladung/SC_Entladung, wie in mubea.json - Schema tests/testdata/
|
||||
;; object_data.md Abschnitt 5). Unterscheidung ueber das Feld "block": nur
|
||||
;; json-input-lisp.md Abschnitt 2). Unterscheidung ueber das Feld "block": nur
|
||||
;; Bloecke haben es, Kreisel-Eintraege nicht. hundm05:bau-sensor ist dabei
|
||||
;; blockname-agnostisch (reiner _.INSERT), der "kind"-Wert "sensor" bleibt
|
||||
;; als Sammelbegriff fuer "kein Kreisel" bestehen (siehe dort).
|
||||
@@ -125,7 +125,7 @@
|
||||
"kreisel-insert-script lieferte nil"))))))
|
||||
|
||||
;; Separator/Scanner/BTMT-Beladung/SC_Entladung bauen ("block"-Eintraege,
|
||||
;; siehe object_data.md Abschnitt 5). ils-insert-sensor/ils-insert-station
|
||||
;; siehe json-input-lisp.md Abschnitt 2). ils-insert-sensor/ils-insert-station
|
||||
;; (SSG_LIB_Commands.lsp) sind dafuer NICHT scriptbar (fragen Punkt/Rotation
|
||||
;; per getpoint/pause in einer Schleife) - wir bauen den _.INSERT darum
|
||||
;; direkt selbst nach, wie mubea:build-separator-one in tests/test_mubea.lsp
|
||||
|
||||
@@ -59,7 +59,11 @@ def spec_ergebnisse(alle_ergebnisse):
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def kreisel_ergebnisse(alle_ergebnisse):
|
||||
raus = [r for r in alle_ergebnisse if r.get("kind") == "kreisel"]
|
||||
"""Ergebnisse ALLER nachgetragenen Anlagenteile (Gegenstueck zu
|
||||
kreisel_objekte) - nicht nur kind "kreisel": Separatoren, Scanner und
|
||||
BTMT kommen als kind "sensor" zurueck. Der Name ist historisch."""
|
||||
raus = [r for r in alle_ergebnisse
|
||||
if r.get("kind", "linienzug") != "linienzug"]
|
||||
if not raus:
|
||||
pytest.skip("keine Kreisel-Ergebnisse (Lauf vor dem Nachtragen "
|
||||
"weiterer Anlagenteile?)")
|
||||
@@ -180,7 +184,7 @@ class TestSpecBau:
|
||||
# ============================================================
|
||||
# tests/testdata/hundm05.json enthaelt neben den Ketten auch andere Objekte
|
||||
# der Anlage - Format wie tests/testdata/kreisel_tests.json (Schema in
|
||||
# tests/testdata/object_data.md Abschnitt 1). Gebaut werden sie von
|
||||
# doc/json-input-lisp.md Abschnitt 1). Gebaut werden sie von
|
||||
# hundm05:bau-zusatzobjekte in tests/test_hundm05.lsp.
|
||||
|
||||
class TestZusatzobjekte:
|
||||
|
||||
+239
-6
@@ -13,6 +13,7 @@
|
||||
;; "typ" ist ein Eingabe-Schritt in exakter Aufruf-Reihenfolge:
|
||||
;; {"typ":"point_abs","wert":[x,y,z]} absoluter Punkt (getpoint)
|
||||
;; {"typ":"point_rel","dL":..,"hz":..} Basispunkt + dL entlang Richtung hz
|
||||
;; {"typ":"point_none"} getpoint ohne Punkt (Enter -> nil)
|
||||
;; {"typ":"real","wert":..} getreal
|
||||
;; {"typ":"int","wert":..} getint
|
||||
;; {"typ":"string","wert":".."} getstring
|
||||
@@ -53,17 +54,23 @@
|
||||
;; Skript-Eintrag (P dL hz) -> Basispunkt + dL entlang Richtung hz (Grad),
|
||||
;; sodass die Projektion in vfl-neue-linie-messen
|
||||
;; exakt dL ergibt.
|
||||
;; Skript-Eintrag KEIN -> nil (Enter ohne Punkt, z.B. optionale
|
||||
;; AS-Zufuehrungsachse nicht gesetzt)
|
||||
(defun tlz-getpoint (a b / spec base rad)
|
||||
(setq spec (tlz-pop))
|
||||
(setq base (if (and a (listp a)) a '(0.0 0.0 0.0)))
|
||||
(if (and (listp spec) (= (car spec) 'A))
|
||||
(list (float (cadr spec)) (float (caddr spec)) (float (cadddr spec)))
|
||||
(cond
|
||||
((= spec 'KEIN) nil)
|
||||
((and (listp spec) (= (car spec) 'A))
|
||||
(list (float (cadr spec)) (float (caddr spec)) (float (cadddr spec))))
|
||||
(T
|
||||
(progn
|
||||
(setq rad (* (float (caddr spec)) (/ pi 180.0)))
|
||||
(list (+ (car base) (* (float (cadr spec)) (cos rad)))
|
||||
(+ (cadr base) (* (float (cadr spec)) (sin rad)))
|
||||
(caddr base))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(defun tlz-getstring (a) (tlz-pop))
|
||||
@@ -84,6 +91,8 @@
|
||||
(setq q (cons (cons 'A (ssg-val schritt "wert")) q)))
|
||||
((= typ "point_rel")
|
||||
(setq q (cons (list 'P (ssg-val schritt "dL") (ssg-val schritt "hz")) q)))
|
||||
((= typ "point_none")
|
||||
(setq q (cons 'KEIN q)))
|
||||
((= typ "real")
|
||||
(setq q (cons (float (ssg-val schritt "wert")) q)))
|
||||
((= typ "int")
|
||||
@@ -139,7 +148,7 @@
|
||||
;; ebenfalls nur einen einzigen Testfall pro Lauf kennt).
|
||||
(defun tlz-run-datei (json-datei test-id befehl-anzeige /
|
||||
daten meta schritte-anz rest-anz status
|
||||
old-vgp old-gs old-gi old-gr err)
|
||||
old-vgp old-gs old-gi old-gr err old-gui)
|
||||
(if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek))
|
||||
(if (null (car (atoms-family 1 '("VF-LINIENZUG-MODUS"))))
|
||||
(progn
|
||||
@@ -176,6 +185,7 @@
|
||||
;; GUI aus: keine Wizard-DCL-Dialoge waehrend des automatischen Replays -
|
||||
;; die Eingaben kommen aus der Mock-Queue (getstring/getint/getreal), siehe
|
||||
;; ssg-gui-aus/ssg-gui-p in ssg_core.lsp und vfl-wizard-mode-p.
|
||||
(setq old-gui (if (boundp '*ssg-gui-aus*) *ssg-gui-aus*))
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AUS"))) (ssg-gui-aus))
|
||||
|
||||
;; --- Eingabe-Funktionen sichern und durch Mocks ersetzen ---
|
||||
@@ -192,9 +202,11 @@
|
||||
|
||||
;; --- Eingabe-Funktionen wiederherstellen (IMMER) ---
|
||||
(setq vfl-getpoint old-vgp getstring old-gs getint old-gi getreal old-gr)
|
||||
;; GUI wieder einschalten (auch nach Fehler), damit eine folgende interaktive
|
||||
;; Sitzung nicht headless bleibt.
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AN"))) (ssg-gui-an))
|
||||
;; GUI-Zustand von VOR dem Test wiederherstellen (auch nach Fehler) - NICHT
|
||||
;; pauschal einschalten: unter SSG_RUN_ALL_TESTS ist sie fuer den ganzen
|
||||
;; Batch aus, und ein pauschales ssg-gui-an liess den anschliessenden
|
||||
;; EXPORTSIVAS nach Hoehen-Check/Bereinigen fragen (Lauf hing).
|
||||
(setq *ssg-gui-aus* old-gui)
|
||||
|
||||
(setq rest-anz (length *tlz-q*))
|
||||
|
||||
@@ -255,3 +267,224 @@
|
||||
(tlz-run-datei json-datei "LZ_Stufe2_Kettenende" "TEST_LINIENZUG_STUFE2")
|
||||
(princ)
|
||||
)
|
||||
|
||||
|
||||
;; ============================================================
|
||||
;; MODUS 2 (aus 3D-Linie mit Zielhoehe) - Replay echter Laeufe
|
||||
;; ============================================================
|
||||
;; Anders als die Modus-1-Faelle oben braucht Modus 2 KEINE Mocks und KEINEN
|
||||
;; gezeichneten Pfad: sein Journal traegt einen SEGS-Eintrag mit der kompletten
|
||||
;; Segment-Essenz (Typ, Richtung, Laenge, Eckwinkel, Seite, Start/Ende), ist
|
||||
;; also von den Original-Objekten unabhaengig - dieselbe Eigenschaft, auf der
|
||||
;; schon vfl-konvertiere-ent beruht (vfl-journal-hat-segs-p). Der Test spielt
|
||||
;; daher das echte, aus der Zeichnung ausgelesene Journal ab.
|
||||
;;
|
||||
;; Die Faelle sind zwei BEWUSST gebildete Paare, kein Sammelsurium:
|
||||
;;
|
||||
;; A/B (Ecke als Vario-Kurve bzw. als GF-Bogen) - derselbe Pfad, nur die
|
||||
;; 90-Grad-Ecke einmal waagerecht und einmal geneigt eingebaut. Sie laufen
|
||||
;; durch verschiedene Zweige (mit und ohne flache Zone), und genau der
|
||||
;; VERGLEICH hat am 2026-10-26/27 Fehler aufgedeckt, die ein einzelner
|
||||
;; Lauf nicht gezeigt haette (ES-Fussabdruck am falschen Segment: 878 mm
|
||||
;; nur in der GF-Bogen-Variante).
|
||||
;;
|
||||
;; U-Form 1..3 (gefalteter Lauf) - der Pfad wechselt ueber zwei 90-Grad-
|
||||
;; Vario-Kurven dreimal die Fahrtrichtung, die Kletterstrecke liegt
|
||||
;; dadurch in einem ANDEREN Schenkel als der Lauf-Eingang. Hier variieren
|
||||
;; GF-VERTEILUNG (alles am Einlauf vs. 1/2+1/2) und WINKEL. Beides ist
|
||||
;; noetig: die Verteilung entscheidet, ob ueberhaupt GF im fremden
|
||||
;; Schenkel steht (Nachrechner, Fueller-A), und der Restfehler der alten
|
||||
;; Bilanz skalierte mit L_GF, also mit dem Winkel (6 Grad 90 mm, 9 Grad
|
||||
;; 934 mm) - zwei Laeufe mit demselben Winkel haetten das verdeckt.
|
||||
;;
|
||||
;; Einen Fall zu loeschen nimmt dem Test den jeweiligen Vergleich und damit
|
||||
;; seinen Wert.
|
||||
;;
|
||||
;; Aufgezeichnet mit lib/vf_journal_export.py aus echten BricsCAD-Laeufen
|
||||
;; (A/B am 2026-10-27, U-Form am 2026-10-29).
|
||||
;; Pruefkriterium (Nutzer-Vorgabe 2026-10-26): quer zur ES-KS_AUS-Achse und dZ
|
||||
;; MUESSEN ~0 sein, laengs DARF abweichen (Ausladung des ES-Elements).
|
||||
|
||||
(setq *tlz-m2-toleranz* 1.0) ; mm; 0.2 ist die Messaufloesung der Blockmasse
|
||||
|
||||
;; Toleranz fuer den LAENGS-Wert gegen "erwartung_laengs_mm" aus den Testdaten.
|
||||
;; Der Wert ist die Ausladung des ES-Elements und damit je Fall eine Konstante
|
||||
;; (gemessen: 104.68 mm bei ES_Element_30, 637.58 mm bei ES_Element_90) - 5 mm
|
||||
;; reichen also fuer Rundung, ohne echte Abweichungen durchzulassen.
|
||||
;;
|
||||
;; Warum ueberhaupt geprueft, wo laengs doch ausdruecklich abweichen DARF:
|
||||
;; Am 2026-10-29 loeste ein Experiment den Schluss-Fueller gegen Richtung UND
|
||||
;; Laenge und traf den Zielpunkt dadurch in X und Y exakt - um den Preis, dass
|
||||
;; es die letzte Gerade um 6.15 Grad verdrehte (sichtbar schiefer Schenkel im
|
||||
;; U-Form-Fall). quer und dZ waren dabei NULL, der Test meldete OK; gefunden
|
||||
;; wurde der Fehler nur mit dem Auge in der Zeichnung.
|
||||
;; laengs ist der Wert, der das verraet: ein verdrehter Hauptstrang zielt auf
|
||||
;; den Endpunkt und drueckt laengs von ~638 mm auf ~0. Die Pruefung ist also
|
||||
;; kein zweites Genauigkeitskriterium, sondern ein Formkriterium - sie stellt
|
||||
;; sicher, dass der ES-Versatz noch da ist, wo er hingehoert.
|
||||
(setq *tlz-m2-laengs-toleranz* 5.0)
|
||||
|
||||
;; Wert als String - eigene Kopie statt hmrec:als-string aus
|
||||
;; test_hm_recformat.lsp: diese Datei soll fuer sich allein ladbar bleiben.
|
||||
(defun tlz-m2-str (v)
|
||||
(cond ((null v) "")
|
||||
((= (type v) 'STR) v)
|
||||
((= (type v) 'INT) (itoa v))
|
||||
((= (type v) 'REAL) (rtos v 2 6))
|
||||
(T (vl-princ-to-string v))))
|
||||
|
||||
;; Ein JSON-Record -> Journal-Eintrag (kind . wert), nil bei Metadaten-Zeile.
|
||||
(defun tlz-m2-eintrag->journal (e / art)
|
||||
(setq art (ssg-val e "art"))
|
||||
(cond
|
||||
((null art) nil)
|
||||
((= art "PT") (cons "PT" (list (float (ssg-val e "x"))
|
||||
(float (ssg-val e "y"))
|
||||
(float (ssg-val e "z")))))
|
||||
((= art "REAL") (cons "REAL" (float (ssg-val e "wert"))))
|
||||
((= art "INT") (cons "INT" (fix (ssg-val e "wert"))))
|
||||
;; SEGS traegt im Journal eine LISTE von Segment-Records, nicht den
|
||||
;; String - genau diese Umwandlung macht auch der XDATA-Decoder
|
||||
;; (vfl-journal-string->entry). Ohne sie bekommt vfl-in-segmente den
|
||||
;; Rohstring und der erste mapcar darauf stirbt (real 2026-10-27).
|
||||
((= art "SEGS") (cons "SEGS" (vfl-string->segs (tlz-m2-str (ssg-val e "wert")))))
|
||||
(T (cons art (tlz-m2-str (ssg-val e "wert"))))))
|
||||
|
||||
;; Einen Modus-2-Fall abspielen. Rueckgabe: (status laengs quer dz offen).
|
||||
(defun tlz-m2-run (json-datei test-id anzeige /
|
||||
daten journal meta offen err status abw j
|
||||
old-headless old-gui quer dz laengs
|
||||
soll-laengs laengs-ok)
|
||||
(if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek))
|
||||
(princ (strcat "\n\n--- " anzeige " ---"))
|
||||
;; Vorbelegen, damit der Ergebnis-Record auch im Fehlerzweig Zahlen hat -
|
||||
;; sonst stirbt das abschliessende rtos an nil (real passiert 2026-10-27).
|
||||
(setq laengs 0.0 quer 999.0 dz 999.0 offen 0 status "FEHLER")
|
||||
(setq daten (ssg-load-json json-datei))
|
||||
(if (null daten)
|
||||
(progn (princ (strcat "\n FEHLER: Testdaten fehlen: " json-datei))
|
||||
(setq status "FEHLER"))
|
||||
(progn
|
||||
(setq meta (car daten))
|
||||
(setq journal '())
|
||||
(foreach e daten
|
||||
(setq j (tlz-m2-eintrag->journal e))
|
||||
(if j (setq journal (cons j journal))))
|
||||
(setq journal (reverse journal))
|
||||
(princ (strcat "\n Journal-Eintraege: " (itoa (length journal))))
|
||||
(if meta (princ (strcat "\n Szenario: " (ssg-val meta "kurz"))))
|
||||
|
||||
(ssg-start anzeige '(("OSMODE") ("ATTREQ") ("ATTDIA")))
|
||||
(setvar "OSMODE" 0) (setvar "ATTREQ" 0) (setvar "ATTDIA" 0)
|
||||
;; GUI aus (keine Wizard-Dialoge) UND headless: eine erschoepfte
|
||||
;; Replay-Queue ist damit ein harter Abbruch MIT Fundstelle statt eines
|
||||
;; stillen Rueckfalls auf eine Live-Abfrage, die im Batch haengen wuerde.
|
||||
(setq old-gui *ssg-gui-aus* old-headless *vfl-headless*)
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AUS"))) (ssg-gui-aus))
|
||||
(setq *vfl-headless* T *vfl-m2-abweichung* nil)
|
||||
|
||||
(vfl-journal-replay-start journal)
|
||||
(setq err (vl-catch-all-apply 'vf-linienzug-modus2 '()))
|
||||
|
||||
(setq *vfl-headless* old-headless *ssg-gui-aus* old-gui)
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AN"))) (if (null old-gui) (ssg-gui-an)))
|
||||
|
||||
(setq offen (length *vfl-replay-queue*))
|
||||
(setq abw (if (boundp '*vfl-m2-abweichung*) *vfl-m2-abweichung* nil))
|
||||
(setq laengs (if abw (car abw) 0.0)
|
||||
quer (if abw (cadr abw) 999.0)
|
||||
dz (if abw (caddr abw) 999.0))
|
||||
(cond
|
||||
((vl-catch-all-error-p err)
|
||||
(setq status "FEHLER")
|
||||
(princ (strcat "\n FEHLER: " (vl-catch-all-error-message err))))
|
||||
((null abw)
|
||||
(setq status "FEHLER")
|
||||
(princ "\n FEHLER: keine Abweichung gemessen (Bau nicht beendet)."))
|
||||
(T
|
||||
(princ (strcat "\n laengs=" (rtos laengs 2 1)
|
||||
" quer=" (rtos quer 2 1)
|
||||
" dZ=" (rtos dz 2 1) " mm"))
|
||||
(if (> offen 0)
|
||||
(princ (strcat "\n WARNUNG: " (itoa offen)
|
||||
" Journal-Eintraege NICHT verbraucht (Ablauf weicht ab).")))
|
||||
;; laengs gegen den erwarteten ES-Versatz pruefen, sofern die
|
||||
;; Testdaten einen nennen (siehe *tlz-m2-laengs-toleranz*).
|
||||
(setq soll-laengs (if meta (ssg-val meta "erwartung_laengs_mm") nil))
|
||||
(setq laengs-ok
|
||||
(if (numberp soll-laengs)
|
||||
(<= (abs (- laengs (float soll-laengs))) *tlz-m2-laengs-toleranz*)
|
||||
T))
|
||||
(if (not laengs-ok)
|
||||
(princ (strcat "\n WARNUNG: laengs " (rtos laengs 2 1)
|
||||
" statt erwarteter " (rtos (float soll-laengs) 2 1)
|
||||
" mm - der Hauptstrang zeigt nicht mehr in die"
|
||||
" gezeichnete Richtung (ES-Versatz verschwunden?).")))
|
||||
(setq status
|
||||
(if (and (<= (abs quer) *tlz-m2-toleranz*)
|
||||
(<= (abs dz) *tlz-m2-toleranz*)
|
||||
laengs-ok
|
||||
(= offen 0))
|
||||
"OK" "ABWEICHUNG"))
|
||||
(princ (strcat "\n -> " status
|
||||
" (Soll: |quer| und |dZ| <= " (rtos *tlz-m2-toleranz* 2 1)
|
||||
" mm, laengs = "
|
||||
(if (numberp soll-laengs)
|
||||
(strcat (rtos (float soll-laengs) 2 0) " +/- "
|
||||
(rtos *tlz-m2-laengs-toleranz* 2 0) " mm")
|
||||
"frei")
|
||||
")"))))
|
||||
(ssg-end)))
|
||||
(list status laengs quer dz offen))
|
||||
|
||||
;; Testfall-Tabelle: (Dateiname test-id Anzeigename). Ein weiterer Fall ist
|
||||
;; damit EINE Zeile - der Ablauf darunter ist generisch. Reihenfolge =
|
||||
;; Ausgabereihenfolge; die beiden Paare stehen bewusst beieinander.
|
||||
(setq *tlz-m2-faelle*
|
||||
(list
|
||||
(list "linienzug_modus2_variokurve.json" "LZ_M2_variokurve"
|
||||
"Variante A: Ecke = Vario-Kurve")
|
||||
(list "linienzug_modus2_gfbogen.json" "LZ_M2_gfbogen"
|
||||
"Variante B: Ecke = GF-Bogen")
|
||||
(list "linienzug_modus2_uform_gf1.json" "LZ_M2_uform_gf1"
|
||||
"U-Form 1: GF alles am Einlauf")
|
||||
(list "linienzug_modus2_uform_halb.json" "LZ_M2_uform_halb"
|
||||
"U-Form 2: GF 1/2 + 1/2")
|
||||
(list "linienzug_modus2_uform_halb_steil.json" "LZ_M2_uform_halb_steil"
|
||||
"U-Form 3: GF 1/2 + 1/2, steilere Winkel-Option")))
|
||||
|
||||
(defun c:TEST_LINIENZUG_MODUS2 ( / basis fall r erg zeilen anzahl-ok)
|
||||
;; Doppelte Backslashes: "\t" waere in AutoLISP ein TABULATOR, der Pfad
|
||||
;; wuerde zu "...dxfmakros<TAB>ests<TAB>estdata" (real passiert 2026-10-27).
|
||||
(setq basis (strcat (getenv "DXFMAKRO") "\\tests\\testdata\\"))
|
||||
(princ "\n================================================================")
|
||||
(princ (strcat "\n TEST_LINIENZUG_MODUS2 - " (itoa (length *tlz-m2-faelle*))
|
||||
" Ketten aus echten BricsCAD-Laeufen"))
|
||||
(princ "\n================================================================")
|
||||
(setq erg '() zeilen '() anzahl-ok 0)
|
||||
(foreach fall *tlz-m2-faelle*
|
||||
(setq r (tlz-m2-run (strcat basis (car fall)) (cadr fall) (caddr fall)))
|
||||
(if (= (car r) "OK") (setq anzahl-ok (1+ anzahl-ok)))
|
||||
(setq erg (cons (list (caddr fall) (car r)) erg))
|
||||
(setq zeilen
|
||||
(cons (strcat " { \"test_id\": \"" (cadr fall)
|
||||
"\", \"status\": \"" (car r)
|
||||
"\", \"quer_mm\": " (rtos (caddr r) 2 2)
|
||||
", \"dz_mm\": " (rtos (cadddr r) 2 2)
|
||||
", \"laengs_mm\": " (rtos (cadr r) 2 2) " }")
|
||||
zeilen)))
|
||||
(setq erg (reverse erg) zeilen (reverse zeilen))
|
||||
(princ "\n\n================================================================")
|
||||
(princ "\n ERGEBNIS")
|
||||
(princ "\n----------------------------------------------------------------")
|
||||
(foreach e erg
|
||||
(princ (strcat "\n " (car e) ": " (cadr e))))
|
||||
(princ (strcat "\n----------------------------------------------------------------"
|
||||
"\n " (itoa anzahl-ok) " von " (itoa (length *tlz-m2-faelle*))
|
||||
" OK"))
|
||||
(princ "\n================================================================")
|
||||
;; Ergebnis fuer run-all (Konvention wie linienzug:export-results).
|
||||
;; ssg-join aus ssg_core - die Zeilen sind bereits fertige JSON-Objekte.
|
||||
(setq *linienzug-m2-test-results* (ssg-join zeilen ",\n"))
|
||||
(princ)
|
||||
)
|
||||
@@ -140,7 +140,7 @@
|
||||
;; --- Vario (VF_*): L_GF/L_VF fuer gegebenes deltaL+deltaH+winkel loesen, dann bauen ---
|
||||
;; deltaL ist (wie bei der Gefaellestrecke) die horizontale PROJIZIERTE
|
||||
;; Gesamtlaenge des VF (Vorlauf L_GF1 + Foerderer L_VF + Nachlauf L_GF2 +
|
||||
;; Boegen/AS-ES-Elemente), analog foerderer_tests.json/object_data.md 3.1 -
|
||||
;; Boegen/AS-ES-Elemente), analog foerderer_tests.json/json-input-lisp.md 3 -
|
||||
;; KEIN abgeleiteter Wert. "winkel" erzwingt einen bestimmten Bogenwinkel aus
|
||||
;; der Kandidatenliste von berechne-alle-winkel (wie foerderer:winkel-
|
||||
;; erzwingen in test_foerderer.lsp), statt den automatisch kleinsten
|
||||
@@ -295,7 +295,7 @@
|
||||
;; --- Eine einzelne Gefaellestrecke bauen (Modus 1) ---
|
||||
;; Aufbau AUSSCHLIESSLICH aus Anfangspunkt (start-mm) und horizontaler
|
||||
;; Gesamtlaenge deltaL - KEIN Endpunkt (wie Produktion/gefaellestrecke.dcl
|
||||
;; Modus 1, siehe object_data.md 2.1). L_stau wird aus deltaL abgeleitet
|
||||
;; Modus 1, siehe json-input-lisp.md 4.1). L_stau wird aus deltaL abgeleitet
|
||||
;; (identische Formel wie test_gefaellestrecke.lsp):
|
||||
;; L_stau = (deltaL - aus-dx - ein-dx - sep_x) / cos(v)
|
||||
;; sep_x = 300 * cos(v), v = Element-Winkel (winkel_grad, Default 3 Grad)
|
||||
|
||||
+119
-8
@@ -69,7 +69,56 @@
|
||||
;; --- Hilfsfunktion: String-Wert aus JSON-Objekt-Zeile lesen ---
|
||||
;; Sucht "key": "value" in obj-str und gibt value zurueck.
|
||||
;; Rueckgabe: String (nicht leer) oder nil (key fehlt, null, leer).
|
||||
(defun alltests:get-str (obj-str key / pat pos val-start val-end val)
|
||||
;; ------------------------------------------------------------
|
||||
;; Laufprotokoll je Test (Debug-Schalter "testlauf", Standard EIN)
|
||||
;; ------------------------------------------------------------
|
||||
;; DXFM_LOG/testlauf_<name>.dbg - eine Datei je Test, bei jedem Lauf neu.
|
||||
;; Bewusst NICHT ueber dbgopen/*dbg-path*: die getesteten Module oeffnen und
|
||||
;; schliessen dort ihre eigenen .dbg-Dateien (vfl_modus1.dbg ...) und wuerden
|
||||
;; das Protokoll mitten im Test umlenken. Jede Zeile wird SOFORT angehaengt
|
||||
;; (kein Puffer) - haengt ein Test, steht der letzte erreichte Schritt drin.
|
||||
(if (not (boundp '*testrun-log*)) (setq *testrun-log* nil))
|
||||
|
||||
(defun testrun:log-start (name / dir fh)
|
||||
(setq *testrun-log* nil)
|
||||
(if (and (car (atoms-family 1 '("DBG-SCHALTER-P"))) (dbg-schalter-p "testlauf"))
|
||||
(progn
|
||||
(setq dir (cond ((getenv "DXFM_LOG")) ((strcat (getenv "DXFMAKRO") "/logs"))))
|
||||
(vl-mkdir dir)
|
||||
(setq *testrun-log* (strcat dir "/testlauf_" name ".dbg"))
|
||||
(if (setq fh (open *testrun-log* "w"))
|
||||
(progn (write-line (strcat "=== TESTLAUF " name " ===") fh) (close fh))
|
||||
(setq *testrun-log* nil))))
|
||||
*testrun-log*)
|
||||
|
||||
(defun testrun:log (text / fh)
|
||||
(if (and *testrun-log* (setq fh (open *testrun-log* "a")))
|
||||
(progn
|
||||
(write-line (strcat (if (car (atoms-family 1 '("DBG-TIMESTAMP"))) (dbg-timestamp) "")
|
||||
" " text)
|
||||
fh)
|
||||
(close fh)))
|
||||
(princ))
|
||||
|
||||
;; Schalter, die in einem Testlauf eine Rueckfrage ausloesen koennen.
|
||||
(defun testrun:zustand ()
|
||||
(strcat "GUI=" (if (and (boundp '*ssg-gui-aus*) *ssg-gui-aus*) "aus" "AN")
|
||||
" hoehencheck-fragen=" (vl-princ-to-string (if (boundp '*csv-hoehencheck-fragen*) *csv-hoehencheck-fragen*))
|
||||
" bereinigen=" (vl-princ-to-string (if (boundp '*csv-bereinigen-vor-export*) *csv-bereinigen-vor-export*))
|
||||
" wizard=" (vl-princ-to-string (if (boundp '*vfl-wizard-mode*) *vfl-wizard-mode*))
|
||||
" DWGNAME=" (getvar "DWGNAME")))
|
||||
|
||||
;; Dateiname ohne fuehrenden Praefix (sonst unveraendert). Gegenstueck zu
|
||||
;; export:dwg-praefix, den der Export selbst vor den Namen setzt.
|
||||
(defun testrun:ohne-praefix (dateiname praefix)
|
||||
(if (and praefix
|
||||
(/= praefix "")
|
||||
(> (strlen dateiname) (strlen praefix))
|
||||
(= (strcase (substr dateiname 1 (strlen praefix))) (strcase praefix)))
|
||||
(substr dateiname (1+ (strlen praefix)))
|
||||
dateiname))
|
||||
|
||||
(defun alltests:get-str(obj-str key / pat pos val-start val-end val)
|
||||
(setq pat (strcat "\"" key "\": \""))
|
||||
(setq pos (vl-string-search pat obj-str))
|
||||
(if pos
|
||||
@@ -151,7 +200,8 @@
|
||||
namen befehl datei export-fn new-doc
|
||||
out-path dwg-pfad dxf-pfad old-json test-result
|
||||
old-filenames csv-name sivas-name csv-pfad
|
||||
sivas-pfad csv-ok sivas-ok old-filedia)
|
||||
sivas-pfad csv-ok sivas-ok old-filedia
|
||||
praefix old-hoehencheck old-bereinigen)
|
||||
|
||||
(setq tests-pfad (strcat (getenv "DXFMAKRO") "/tests"))
|
||||
(setq tests-out-dir (strcat tests-pfad "/output"))
|
||||
@@ -209,6 +259,13 @@
|
||||
;; oeffnet DCL-/Wizard-Dialoge, die den automatischen Lauf blockieren wuerden.
|
||||
;; Am Ende wieder einschalten. Siehe ssg-gui-aus/-an in ssg_core.lsp.
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AUS"))) (ssg-gui-aus))
|
||||
;; Rueckfragen des Exports (export.lsp) fuer den ganzen Lauf abschalten -
|
||||
;; zusaetzlich zur GUI-Sperre, damit auch ein Test, der die GUI wieder
|
||||
;; einschaltet, den Export nicht anhalten kann.
|
||||
(setq old-hoehencheck (if (boundp '*csv-hoehencheck-fragen*) *csv-hoehencheck-fragen*)
|
||||
old-bereinigen (if (boundp '*csv-bereinigen-vor-export*) *csv-bereinigen-vor-export*))
|
||||
(setq *csv-hoehencheck-fragen* nil
|
||||
*csv-bereinigen-vor-export* 'aus)
|
||||
|
||||
;; Tests laden und ausfuehren
|
||||
;; Jeder Test bekommt eine eigene neue Zeichnung (statt die aktuelle
|
||||
@@ -261,11 +318,25 @@
|
||||
(setq modelspace (vla-get-modelspace new-doc))
|
||||
;; Block-Library-Flag zuruecksetzen (Bloecke sind pro Zeichnung neu zu laden)
|
||||
(setq *lib-initialized* nil)
|
||||
;; Nummernzaehler zuruecksetzen: der Lauf bleibt im LISP-Namensraum des
|
||||
;; Startdokuments, die Zaehler (max aus Zeichnung UND Zaehler, +1) liefen
|
||||
;; sonst ueber alle Tests weiter - VF_5/Kreisel12 statt VF_1/Kreisel1 in
|
||||
;; einer frischen Zeichnung, die Namen hingen damit von der
|
||||
;; Testreihenfolge ab und jeder Referenz-Diff wurde unruhig.
|
||||
(setq #VF_LetzteNr 0 #GF_LetzteNr 0 #Kreisel_LetzteNr 0 #Eckrad_LetzteNr 0)
|
||||
|
||||
(testrun:log-start name)
|
||||
(testrun:log (strcat "Test " (itoa idx) "/" (itoa anz) ": " befehl
|
||||
" Modul=" (if module module "-")
|
||||
" save=" (if save-fmt save-fmt "-")
|
||||
" Modus=" (if auto-export "Automatik" "Kontrolle")))
|
||||
(testrun:log (strcat "Vor Test: " (testrun:zustand)))
|
||||
|
||||
(if (findfile datei)
|
||||
(progn
|
||||
(load datei)
|
||||
;; Test mit Fehlerbehandlung ausfuehren
|
||||
(testrun:log (strcat "Starte " befehl))
|
||||
(setq test-result
|
||||
(vl-catch-all-apply
|
||||
'(lambda ()
|
||||
@@ -275,12 +346,18 @@
|
||||
)
|
||||
)
|
||||
(if (vl-catch-all-error-p test-result)
|
||||
(princ (strcat "\n FEHLER in " befehl ": "
|
||||
(vl-catch-all-error-message test-result)))
|
||||
)
|
||||
(progn
|
||||
(princ (strcat "\n FEHLER in " befehl ": "
|
||||
(vl-catch-all-error-message test-result)))
|
||||
(testrun:log (strcat "FEHLER in " befehl ": "
|
||||
(vl-catch-all-error-message test-result))))
|
||||
(testrun:log (strcat befehl " beendet")))
|
||||
(testrun:log (strcat "Nach Test: " (testrun:zustand)))
|
||||
|
||||
;; JSON-Export (immer)
|
||||
(apply export-fn (list tests-out-dir))
|
||||
(testrun:log (strcat "Ergebnis-JSON " name "_results.json: "
|
||||
(if (findfile old-json) "vorhanden" "FEHLT")))
|
||||
|
||||
(setq out-path (strcat tests-out-dir "/" name "_tests"))
|
||||
|
||||
@@ -328,31 +405,59 @@
|
||||
;; Nur die beiden CSV-Namen ersetzen, alle uebrigen Keys
|
||||
;; (z.B. kreisel_weichen_datei) unveraendert uebernehmen -
|
||||
;; eine hart nachgebaute Liste verliert sonst neue Keys.
|
||||
;; Nach vla-saveas (save "dwg") ist die Zeichnung benannt
|
||||
;; (DWGTITLED=1, DWGNAME=<name>_tests.dwg), und der Export
|
||||
;; setzt selbst "<name>_tests_" davor (export:dwg-praefix).
|
||||
;; Diesen Praefix hier abziehen, sonst entsteht
|
||||
;; "<name>_tests_<name>_tests_export.csv" und das Warten auf
|
||||
;; csv-pfad laeuft ins Timeout. DXFOUT benennt die Zeichnung
|
||||
;; nicht um -> Praefix leer, Name bleibt vollstaendig.
|
||||
(setq praefix (export:dwg-praefix))
|
||||
(setq old-filenames *export-filenames*)
|
||||
(setq *export-filenames*
|
||||
(mapcar
|
||||
'(lambda (p)
|
||||
(cond ((= (car p) "sivas_csv") (cons "sivas_csv" sivas-name))
|
||||
((= (car p) "csv_csv") (cons "csv_csv" csv-name))
|
||||
(cond ((= (car p) "sivas_csv")
|
||||
(cons "sivas_csv" (testrun:ohne-praefix sivas-name praefix)))
|
||||
((= (car p) "csv_csv")
|
||||
(cons "csv_csv" (testrun:ohne-praefix csv-name praefix)))
|
||||
(T p)))
|
||||
old-filenames))
|
||||
|
||||
;; Unmittelbar vor dem Export erneut erzwingen: export.lsp setzt
|
||||
;; *csv-hoehencheck-fragen* beim (Nach-)Laden von nil auf T, und
|
||||
;; ein Test kann die GUI wieder eingeschaltet haben.
|
||||
(if (not (and (boundp '*ssg-gui-aus*) *ssg-gui-aus*))
|
||||
(progn
|
||||
(testrun:log "WARNUNG: GUI war nach dem Test wieder AN - fuer den Export abgeschaltet")
|
||||
(princ "\n WARNUNG: GUI war nach dem Test wieder an - abgeschaltet.")
|
||||
(ssg-gui-aus)))
|
||||
(setq *csv-hoehencheck-fragen* nil
|
||||
*csv-bereinigen-vor-export* 'aus)
|
||||
(testrun:log (strcat "Vor Export: " (testrun:zustand)))
|
||||
|
||||
(princ (strcat "\n CSV-Export -> " csv-name))
|
||||
(testrun:log (strcat "EXPORTCSV -> " csv-pfad))
|
||||
(c:EXPORTCSV)
|
||||
(setq csv-ok (testrun:wait-for-file csv-pfad 30.0))
|
||||
(princ (if csv-ok "\n CSV OK" "\n CSV TIMEOUT/FEHLER"))
|
||||
(testrun:log (if csv-ok "EXPORTCSV OK" "EXPORTCSV TIMEOUT/FEHLER - Datei nicht entstanden"))
|
||||
|
||||
(princ (strcat "\n Sivas-Export -> " sivas-name))
|
||||
(testrun:log (strcat "EXPORTSIVAS -> " sivas-pfad))
|
||||
(c:EXPORTSIVAS)
|
||||
(setq sivas-ok (testrun:wait-for-file sivas-pfad 30.0))
|
||||
(princ (if sivas-ok "\n Sivas OK" "\n Sivas TIMEOUT/FEHLER"))
|
||||
(testrun:log (if sivas-ok "EXPORTSIVAS OK" "EXPORTSIVAS TIMEOUT/FEHLER - Datei nicht entstanden"))
|
||||
|
||||
(setq *export-filenames* old-filenames)
|
||||
|
||||
;; Zeichnung schliessen: der urspruenglich schon offene Tab
|
||||
;; bleibt unangetastet, BricsCAD erzeugt daher kein neues
|
||||
;; Blank-Dokument samt Modul-/Menue-Reload.
|
||||
(testrun:log "Zeichnung schliessen")
|
||||
(vla-close new-doc :vlax-false)
|
||||
(testrun:log "Test fertig")
|
||||
)
|
||||
|
||||
;; ==========================================================
|
||||
@@ -414,7 +519,9 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(princ (strcat "\n WARNUNG: " datei " nicht gefunden - uebersprungen"))
|
||||
(progn
|
||||
(princ (strcat "\n WARNUNG: " datei " nicht gefunden - uebersprungen"))
|
||||
(testrun:log (strcat "WARNUNG: " datei " nicht gefunden - uebersprungen")))
|
||||
)
|
||||
) ;; end (progn ...) des aktiven Zweigs
|
||||
) ;; end (if (cdr (assoc "disabled" entry)) ...)
|
||||
@@ -422,6 +529,10 @@
|
||||
|
||||
;; GUI wieder einschalten (Batch fertig).
|
||||
(if (car (atoms-family 1 '("SSG-GUI-AN"))) (ssg-gui-an))
|
||||
;; nil = "nie gesetzt" (export.lsp belegt dann mit der Vorgabe vor)
|
||||
(setq *csv-hoehencheck-fragen* (if old-hoehencheck old-hoehencheck T)
|
||||
*csv-bereinigen-vor-export* (if old-bereinigen old-bereinigen 'an))
|
||||
(setq *testrun-log* nil)
|
||||
|
||||
(setq *export-test-override* nil)
|
||||
|
||||
|
||||
+762
-2
@@ -399,6 +399,342 @@
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; TESTS: vf_linienzug.lsp - "Parallel zum Kreisel" (Rechenkerne)
|
||||
;; ------------------------------------------------------------
|
||||
;; Die Bau-Funktion vfl-gf-parallel-kreisel braucht eine Zeichnung (sie misst
|
||||
;; AS und Bogen an echten Bloecken); ihre beiden Rechenkerne sind davon frei
|
||||
;; und stehen deshalb hier:
|
||||
;; vfl-par-bogen-waehlen - welcher Bogen hebt den AS-Schwenk auf?
|
||||
;; vfl-par-gf-laenge - wie lang wird das GF-Stueck dazwischen?
|
||||
;; Die Plan-Turn-Werte unten sind die Vorzeichen-Konvention aus
|
||||
;; vf-element-plan-turn (KS_EIN -> KS_AUS in der XY-Ebene, links positiv).
|
||||
(defun tu-tests-vfl-parallel ( / _b30 _b60 _b90 _kand _l _plan _plan3 _g _p _w _ez _plan2)
|
||||
(princ "\n[vf_linienzug Parallel zum Kreisel]")
|
||||
|
||||
;; --- Bogenwahl: der Bogen muss den AS-Schwenk GENAU aufheben ---
|
||||
;; Rechts-Boegen schwenken negativ, Links-Boegen positiv.
|
||||
(setq _b30 '(30 . -30.0) _b60 '(60 . -60.0) _b90 '(90 . -90.0))
|
||||
(setq _kand (list _b30 _b60 _b90))
|
||||
;; AS links 30 Grad (Schwenk +30) -> 30-Grad-Bogen nach rechts
|
||||
(tu-eq "vfl-par-bogen/as30-rechts" 30 (vfl-par-bogen-waehlen 30.0 _kand 2.0))
|
||||
;; AS links 90 Grad (Schwenk +90) -> 90-Grad-Bogen nach rechts
|
||||
(tu-eq "vfl-par-bogen/as90-rechts" 90 (vfl-par-bogen-waehlen 90.0 _kand 2.0))
|
||||
;; Generisch: auch ein 60-Grad-Schwenk findet seinen Bogen - die Zuordnung
|
||||
;; folgt den gemessenen Bloecken, nicht einer gepflegten Tabelle.
|
||||
(tu-eq "vfl-par-bogen/as60-rechts" 60 (vfl-par-bogen-waehlen 60.0 _kand 2.0))
|
||||
;; kleine Messabweichung bleibt in der Toleranz
|
||||
(tu-eq "vfl-par-bogen/toleranz-ok" 30 (vfl-par-bogen-waehlen 31.2 _kand 2.0))
|
||||
;; ausserhalb der Toleranz: lieber nil als ein schiefer Bogen
|
||||
(tu-nil "vfl-par-bogen/zu-weit-weg" (vfl-par-bogen-waehlen 45.0 _kand 2.0))
|
||||
(tu-nil "vfl-par-bogen/leere-liste" (vfl-par-bogen-waehlen 30.0 '() 2.0))
|
||||
;; Gegenseite: Links-Boegen heben einen negativen AS-Schwenk auf
|
||||
(setq _kand (list '(30 . 30.0) '(60 . 60.0) '(90 . 90.0)))
|
||||
(tu-eq "vfl-par-bogen/as-rechts30-links" 30 (vfl-par-bogen-waehlen -30.0 _kand 2.0))
|
||||
|
||||
;; --- GF-Laenge: abstand = perp-as + L*k + perp-bogen ---
|
||||
;; Glatter Fall: k = 1 (AS schwenkt 90 Grad aus der Achse), feste Anteile
|
||||
;; zusammen 500 -> fuer 2000 mm Abstand bleiben 1500 mm GF.
|
||||
(tu-eqf "vfl-par-laenge/k1" 1500.0 (vfl-par-gf-laenge 2000.0 200.0 300.0 1.0))
|
||||
;; Gegenseite: k negativ -> der Abstand zaehlt auf der anderen Seite, der
|
||||
;; Betrag der Eingabe bleibt derselbe (Seite kommt aus der AS-Variante).
|
||||
(tu-eqf "vfl-par-laenge/k-negativ" 1500.0
|
||||
(vfl-par-gf-laenge 2000.0 -200.0 -300.0 -1.0))
|
||||
;; Schraege Ausschleusung: k = sin(60 Grad)
|
||||
(setq _l (vfl-par-gf-laenge 2000.0 0.0 0.0 (sin (/ (* 60.0 pi) 180.0))))
|
||||
(tu-eqf "vfl-par-laenge/k-sin60" (/ 2000.0 (sin (/ (* 60.0 pi) 180.0))) _l)
|
||||
;; Abstand kleiner als der feste Anteil -> negative Laenge (der Aufrufer
|
||||
;; meldet das als "Abstand zu klein", die Rechnung selbst raet nicht).
|
||||
(tu-true "vfl-par-laenge/zu-klein-negativ"
|
||||
(< (vfl-par-gf-laenge 100.0 200.0 300.0 1.0) 0.0))
|
||||
;; AS schwenkt gar nicht aus der Achse -> keine Loesung
|
||||
(tu-nil "vfl-par-laenge/kein-versatz" (vfl-par-gf-laenge 2000.0 0.0 0.0 0.0))
|
||||
|
||||
;; --- Grenzen einer VF-Einheit (Modus 2) ---
|
||||
;; Zwischen Umlenk- und Motorstation: hoechstens 2 Vario-Kurven und 25 m.
|
||||
;; Plan-Eintraege: ("Linie" hz laenge ...) / ("Bogen" hz chord ...) - nur
|
||||
;; Typ und Laenge (3. Feld) zaehlen hier.
|
||||
(setq _plan (list '("Linie" 0.0 9000.0 "VF") '("Bogen" 0.0 500.0)
|
||||
'("Linie" 0.0 8000.0 "VF") '("Bogen" 0.0 500.0)
|
||||
'("Linie" 0.0 6000.0 "VF")))
|
||||
;; 24000 mm, 2 Kurven -> alles im Rahmen
|
||||
(setq _g (vfl-m2-lauf-grenzen _plan 0 4 25000.0 2))
|
||||
(tu-eqf "vfl-m2-grenzen/laenge" 24000.0 (nth 0 _g))
|
||||
(tu-eq "vfl-m2-grenzen/kurven" 2 (nth 1 _g))
|
||||
(tu-nil "vfl-m2-grenzen/ok" (nth 2 _g))
|
||||
;; Dritte Kurve -> an ihr (Index 5) teilen, obwohl die Laenge noch passt
|
||||
(setq _plan3 (append _plan (list '("Bogen" 0.0 400.0) '("Linie" 0.0 300.0 "VF"))))
|
||||
(tu-eq "vfl-m2-grenzen/dritte-kurve" 5 (nth 2 (vfl-m2-lauf-grenzen _plan3 0 6 25000.0 2)))
|
||||
;; Zu lang -> am ersten Bogen teilen, nach dem die Grenze reisst (Index 3:
|
||||
;; bis dahin sind 9000+500+8000 = 17500 drin, die Grenze liegt bei 15000).
|
||||
(tu-eq "vfl-m2-grenzen/zu-lang" 3 (nth 2 (vfl-m2-lauf-grenzen _plan 0 4 15000.0 2)))
|
||||
;; Eine einzige lange Gerade: zu lang, aber kein Bogen zum Teilen -> -1
|
||||
(tu-eq "vfl-m2-grenzen/unteilbar" -1
|
||||
(nth 2 (vfl-m2-lauf-grenzen (list '("Linie" 0.0 30000.0 "VF")) 0 0 25000.0 2)))
|
||||
|
||||
;; --- Vorgabewert aus einem Prompt ziehen (Dialog-Feld vorbelegen) ---
|
||||
;; Die Konsolen-Prompts tragen ihre Vorgabe in Klammern; der Zahlen-Dialog
|
||||
;; liest sie daraus. Gesucht ist die LETZTE Klammergruppe MIT Zahl - die
|
||||
;; echten Texte enthalten davor "<" ohne Partner ("0 < Winkel <= 3") und
|
||||
;; runde Klammern mit Fliesstext, beides darf nicht stoeren.
|
||||
(tu-eq "vflw-vorgabe/neigungswinkel" "3"
|
||||
(vflw-vorgabe-aus-prompt "\nNeigungswinkel (Grad, 0 < Winkel <= 3) [3]: "))
|
||||
(tu-eq "vflw-vorgabe/neigungswinkel-berechnet" "3"
|
||||
(vflw-vorgabe-aus-prompt
|
||||
"\nNeigungswinkel (Grad, 0 < Winkel <= 3) [3] (deltaL wird berechnet und eingefuegt): "))
|
||||
(tu-eq "vflw-vorgabe/spitze-klammer" "2154.0"
|
||||
(vflw-vorgabe-aus-prompt "\nGewuenschte Hoehe am Kettenanfang (mm) <2154.0>: "))
|
||||
(tu-eq "vflw-vorgabe/negativ" "-12.5"
|
||||
(vflw-vorgabe-aus-prompt "Hoehendifferenz <-12.5>: "))
|
||||
;; Ohne Klammergruppe bleibt das Feld leer (nil), nicht geraten.
|
||||
(tu-nil "vflw-vorgabe/ohne-vorgabe"
|
||||
(vflw-vorgabe-aus-prompt "\nAbstand zum Kreisel (mm, senkrecht zur Achse): "))
|
||||
(tu-nil "vflw-vorgabe/keine-zahl"
|
||||
(vflw-vorgabe-aus-prompt "Bitte Namen eingeben [frei]: "))
|
||||
|
||||
;; --- Modus-2-Lauf-Anfang: Journal-Wert normieren ---
|
||||
;; Die Antwort wird als selbstbeschreibender Wert gefuehrt, damit ein
|
||||
;; Umsortieren/Umnummerieren der Optionen bestehende Ketten nicht
|
||||
;; umdeutet. Alte Ketten tragen dort noch die Ziffern der ALTEN Folge -
|
||||
;; die Zuordnung dafuer steht als Tabelle in *vfl-m2-anfang-alt* und wird
|
||||
;; hier komplett durchlaufen, statt einzelne Faelle abzuschreiben.
|
||||
(foreach _p *vfl-m2-anfang-alt*
|
||||
(tu-eq (strcat "vfl-m2-anfang/alt-" (car _p))
|
||||
(cdr _p) (vfl-m2-anfang-norm (car _p))))
|
||||
;; Jeder Tabellenwert muss auch ein gueltiger heutiger Wert sein - sonst
|
||||
;; laeuft eine Alt-Kette in den Unbekannt-Abbruch.
|
||||
(foreach _p *vfl-m2-anfang-alt*
|
||||
(tu-true (strcat "vfl-m2-anfang/alt-ziel-gueltig-" (car _p))
|
||||
(and (member (cdr _p) *vfl-m2-anfang-werte*) t)))
|
||||
;; Neue Werte gehen unveraendert durch.
|
||||
(foreach _w *vfl-m2-anfang-werte*
|
||||
(tu-eq (strcat "vfl-m2-anfang/neu-" _w) _w (vfl-m2-anfang-norm _w)))
|
||||
;; Unbekanntes wird NICHT geraten - nil heisst fuer den Aufrufer Abbruch.
|
||||
(tu-nil "vfl-m2-anfang/unbekannte-ziffer" (vfl-m2-anfang-norm "4"))
|
||||
(tu-nil "vfl-m2-anfang/leer" (vfl-m2-anfang-norm ""))
|
||||
(tu-nil "vfl-m2-anfang/tippfehler" (vfl-m2-anfang-norm "mit_gf1"))
|
||||
(tu-nil "vfl-m2-anfang/kein-string" (vfl-m2-anfang-norm 3))
|
||||
(tu-nil "vfl-m2-anfang/nil" (vfl-m2-anfang-norm nil))
|
||||
|
||||
;; --- Eck-Korrektur: gezeichneter Bogen gegen Eck-Bauteil ---
|
||||
;; Die Ecke des Pfads wird durch ein reales Bauteil ersetzt, dessen
|
||||
;; Fussabdruck abweichen darf. Die Differenz wird auf die Richtungen der
|
||||
;; beiden angrenzenden Geraden zerlegt. Werte aus dem echten Lauf vom
|
||||
;; 2026-10-26: 90-Grad-Ecke, Pfad R500 (Sehne 707.1 -> 500/-500), gebaute
|
||||
;; Vario-Kurve wirkt wie R406.2 -> je 93.78 mm auf beide Nachbargeraden.
|
||||
(setq _ez (vfl-eck-zerlegen 500.0 -500.0 406.22 -406.22 (- (/ pi 2.0))))
|
||||
(tu-eqf "vfl-eck-zerlegen/90-grad-davor" 93.78 (car _ez))
|
||||
(tu-eqf "vfl-eck-zerlegen/90-grad-danach" 93.78 (cadr _ez))
|
||||
;; 30-Grad-Ecke links, Gefaellebogen R500 trifft den Pfad fast exakt:
|
||||
;; nur 0.85 mm, und zwar ausschliesslich auf der Geraden DAVOR.
|
||||
(setq _ez (vfl-eck-zerlegen 250.0 66.99 249.15 66.99 (/ pi 6.0)))
|
||||
(tu-eqf "vfl-eck-zerlegen/30-grad-davor" 0.85 (car _ez))
|
||||
(tu-eqf "vfl-eck-zerlegen/30-grad-danach" 0.0 (cadr _ez))
|
||||
;; Deckungsgleiches Bauteil -> kein Zuschlag auf keiner Seite.
|
||||
(setq _ez (vfl-eck-zerlegen 500.0 -500.0 500.0 -500.0 (- (/ pi 2.0))))
|
||||
(tu-eqf "vfl-eck-zerlegen/gleich-davor" 0.0 (car _ez))
|
||||
(tu-eqf "vfl-eck-zerlegen/gleich-danach" 0.0 (cadr _ez))
|
||||
;; Ohne Schwenk ist die Zerlegung nicht eindeutig - nil statt Division durch 0.
|
||||
(tu-nil "vfl-eck-zerlegen/ohne-schwenk"
|
||||
(vfl-eck-zerlegen 100.0 0.0 90.0 0.0 0.0))
|
||||
;; GF-Boegen werden GENEIGT eingebaut: ihr Grundriss-Fussabdruck ist kuerzer
|
||||
;; als flach gemessen, und genau diese Differenz muss in die Eck-Korrektur.
|
||||
;; Werte aus dem echten Lauf 2026-10-26: Gefaellebogen_rechts_90_R500 flach
|
||||
;; dx=500 dz=-28.6, bei 3 Grad eingebaut 497.8 - die 2.2 mm blieben vorher
|
||||
;; als Rest am Kettenende stehen. Negatives dz muss dabei VERKUERZEN.
|
||||
(tu-eqf "vfl-projiziere-neigung/gf-bogen-3-grad"
|
||||
(- (* 500.0 (cos (* 3.0 (/ pi 180.0))))
|
||||
(* 28.6 (sin (* 3.0 (/ pi 180.0)))))
|
||||
(car (vfl-projiziere-neigung 500.0 -28.6 3.0)))
|
||||
(tu-true "vfl-projiziere-neigung/gf-bogen-kuerzer-als-flach"
|
||||
(< (car (vfl-projiziere-neigung 500.0 -28.6 3.0)) 500.0))
|
||||
;; Waagerecht eingebaut (Vario-Kurve) bleibt der Fussabdruck unveraendert.
|
||||
(tu-eqf "vfl-projiziere-neigung/waagerecht" 500.0
|
||||
(car (vfl-projiziere-neigung 500.0 -28.6 0.0)))
|
||||
|
||||
;; --- Bau-Funktion aus dem Journal ableiten (vf_spec.lsp) ---
|
||||
;; vsp-bau-journal waehlt die Modus-Funktion anhand des Journals, statt sie
|
||||
;; als zusaetzliches Argument zu bekommen (exakte Argumentzahl, siehe
|
||||
;; CLAUDE.md). Kein SEGS = Modus 1; SEGS mit der Formatmarke "m2v2" =
|
||||
;; Modus 2 (nur vf-linienzug-modus2 schreibt sie); SEGS ohne = Modus 3.
|
||||
(tu-true "vsp-bau-fn/ohne-segs-ist-modus1"
|
||||
(eq (vsp-bau-fn-fuer-journal
|
||||
(list (cons "PT" '(0.0 0.0 0.0)) (cons "STR" "1")))
|
||||
'vf-linienzug-modus))
|
||||
(tu-true "vsp-bau-fn/segs-mit-marke-ist-modus2"
|
||||
(eq (vsp-bau-fn-fuer-journal
|
||||
(list (cons "PT" '(0.0 0.0 0.0)) (cons "SEGS" '(("Linie")))
|
||||
(cons "STR" "m2v2") (cons "STR" "2")))
|
||||
'vf-linienzug-modus2))
|
||||
(tu-true "vsp-bau-fn/segs-ohne-marke-ist-modus3"
|
||||
(eq (vsp-bau-fn-fuer-journal
|
||||
(list (cons "PT" '(0.0 0.0 0.0)) (cons "SEGS" '(("Linie")))
|
||||
(cons "STR" "2")))
|
||||
'vf-linienzug-modus3))
|
||||
;; Die Marke zaehlt nur als STR-Eintrag - ein gleichlautender Wert in einem
|
||||
;; anderen Eintragstyp darf nicht faelschlich auf Modus 2 schliessen lassen.
|
||||
(tu-true "vsp-bau-fn/marke-nur-als-str"
|
||||
(eq (vsp-bau-fn-fuer-journal
|
||||
(list (cons "SEGS" '(("Linie"))) (cons "INT" "m2v2")))
|
||||
'vf-linienzug-modus3))
|
||||
|
||||
;; --- Segment-Klassifizierung: Wert statt Menue-Ziffer ---
|
||||
;; Gemeinsamer Normalisierer fuer alle selbstbeschreibenden Antworten.
|
||||
;; Bestandsketten tragen die Alt-Ziffer, neue Ketten den Wert; beide Mengen
|
||||
;; sind disjunkt. Unbekanntes gibt nil - der Aufrufer bricht dann ab.
|
||||
(foreach _p *vfl-m2-linie-alt*
|
||||
(tu-eq (strcat "vfl-wert-norm/linie-alt-" (car _p)) (cdr _p)
|
||||
(vfl-wert-norm (car _p) *vfl-m2-linie-werte* *vfl-m2-linie-alt*)))
|
||||
(foreach _p *vfl-m2-bogen-alt*
|
||||
(tu-eq (strcat "vfl-wert-norm/bogen-alt-" (car _p)) (cdr _p)
|
||||
(vfl-wert-norm (car _p) *vfl-m2-bogen-werte* *vfl-m2-bogen-alt*)))
|
||||
(foreach _p *vfl-m2-variante-alt*
|
||||
(tu-eq (strcat "vfl-wert-norm/variante-alt-" (car _p)) (cdr _p)
|
||||
(vfl-wert-norm (car _p) *vfl-m2-variante-werte* *vfl-m2-variante-alt*)))
|
||||
;; Neue Werte gehen unveraendert durch.
|
||||
(foreach _w *vfl-m2-bogen-werte*
|
||||
(tu-eq (strcat "vfl-wert-norm/bogen-neu-" _w) _w
|
||||
(vfl-wert-norm _w *vfl-m2-bogen-werte* *vfl-m2-bogen-alt*)))
|
||||
;; Jeder Alt-Zielwert muss ein gueltiger heutiger Wert sein, sonst laeuft
|
||||
;; eine Bestandskette in den Unbekannt-Abbruch.
|
||||
(foreach _p *vfl-m2-linie-alt*
|
||||
(tu-true (strcat "vfl-wert-norm/linie-ziel-gueltig-" (car _p))
|
||||
(and (member (cdr _p) *vfl-m2-linie-werte*) t)))
|
||||
;; Typ und Variante benutzten frueher BEIDE "1"/"2" und waren im Journal
|
||||
;; nicht zu unterscheiden - die neuen Wertevorraete muessen disjunkt sein.
|
||||
(tu-nil "vfl-wert-norm/bogen-und-variante-disjunkt"
|
||||
(vl-some (function (lambda (w) (if (member w *vfl-m2-variante-werte*) w)))
|
||||
*vfl-m2-bogen-werte*))
|
||||
(tu-nil "vfl-wert-norm/unbekannt-gibt-nil"
|
||||
(vfl-wert-norm "3" *vfl-m2-linie-werte* *vfl-m2-linie-alt*))
|
||||
(tu-nil "vfl-wert-norm/kein-string"
|
||||
(vfl-wert-norm 1 *vfl-m2-linie-werte* *vfl-m2-linie-alt*))
|
||||
|
||||
;; --- Gefalteter VF-Lauf erkennen (Schenkel = Fahrtrichtungen) ---
|
||||
;; Der Modus-2-Solver bilanziert skalar ueber EINE Achse. Liegt der Lauf
|
||||
;; gefaltet (U-Form), sitzen die festen Teile in einem anderen Schenkel als
|
||||
;; die Kletterstrecke und die Kette wird sichtbar falsch gebaut. Bis die
|
||||
;; Bilanz achsenweise rechnet, wird so ein Lauf abgewiesen - diese
|
||||
;; Erkennung entscheidet darueber.
|
||||
;; Plan-Eintraege: Linie = ("Linie" hz laenge typ ...), Bogen = ("Bogen" hz ...)
|
||||
(setq _plan2 (list (list "Linie" 0.0 9700.0 "VF" nil)
|
||||
(list "Bogen" 0.0 707.1 90 "rechts" "Vario-Kurve" "aussen")
|
||||
(list "Linie" -90.0 4296.0 "VF" nil)))
|
||||
(tu-eq "vfl-m2-schenkel/u-form-zwei-richtungen" 2
|
||||
(length (vfl-m2-schenkel _plan2 0 2)))
|
||||
(tu-true "vfl-m2-gefaltet/u-form" (vfl-m2-gefaltet-p _plan2 0 2))
|
||||
;; Gerader Lauf: eine Richtung, auch ueber mehrere Geraden hinweg.
|
||||
(setq _plan2 (list (list "Linie" 0.0 9700.0 "VF" nil)
|
||||
(list "Linie" 0.0 2000.0 "VF" nil)))
|
||||
(tu-eq "vfl-m2-schenkel/gerade-eine-richtung" 1
|
||||
(length (vfl-m2-schenkel _plan2 0 1)))
|
||||
(tu-nil "vfl-m2-gefaltet/gerade" (vfl-m2-gefaltet-p _plan2 0 1))
|
||||
;; Zurueck auf dieselbe Richtung zaehlt als NEUER Schenkel - die Kette ist
|
||||
;; dann seitlich versetzt, die Laengen liegen nicht mehr auf einer Linie.
|
||||
(setq _plan2 (list (list "Linie" 0.0 3000.0 "VF" nil)
|
||||
(list "Bogen" 0.0 707.1 90 "rechts" "Vario-Kurve" "aussen")
|
||||
(list "Linie" -90.0 1000.0 "VF" nil)
|
||||
(list "Bogen" -90.0 707.1 90 "links" "Vario-Kurve" "aussen")
|
||||
(list "Linie" 0.0 3000.0 "VF" nil)))
|
||||
(tu-eq "vfl-m2-schenkel/u-form-drei" 3
|
||||
(length (vfl-m2-schenkel _plan2 0 4)))
|
||||
;; Winkel werden normalisiert: 270 und -90 sind dieselbe Richtung.
|
||||
(setq _plan2 (list (list "Linie" -90.0 1000.0 "VF" nil)
|
||||
(list "Linie" 270.0 1000.0 "VF" nil)))
|
||||
(tu-eq "vfl-m2-schenkel/270-gleich-minus90" 1
|
||||
(length (vfl-m2-schenkel _plan2 0 1)))
|
||||
|
||||
;; --- Eingangs-Hardware auf einem Fueller-Segment ---
|
||||
;; Steht der Lauf-Eingang (GF1 + Separator + Umlenkstation + Bogen) auf
|
||||
;; einem FUELLER, muss dessen Laenge abgezogen werden - sonst bekommt der
|
||||
;; Fueller die volle Restlaenge, als staende dort nichts (real 2026-10-27:
|
||||
;; 5855 mm Plan, 10668 mm belegt, Kette 8005 mm daneben).
|
||||
;; Ist das Eingangs-Segment selbst der Kletterer, steckt dieselbe Laenge
|
||||
;; schon in feste-vf - dann MUSS der Abzug 0 sein, sonst doppelt.
|
||||
(tu-eqf "vfl-m2-eingang-fp/kletterer-kein-abzug" 0.0
|
||||
(vfl-m2-eingang-fp 0 0 '(0) 3726.34 (* 3.0 (/ pi 180.0))))
|
||||
;; Anderes Segment als der Eingang: ebenfalls nichts.
|
||||
(tu-eqf "vfl-m2-eingang-fp/fremdes-segment" 0.0
|
||||
(vfl-m2-eingang-fp 2 0 '(2) 3726.34 (* 3.0 (/ pi 180.0))))
|
||||
;; Eingang ist Fueller (Kletterer liegt woanders): GF1 + 300 + 500,
|
||||
;; projiziert auf 3 Grad, plus der Uebergangsbogen aus der Tabelle.
|
||||
;; Die DIFFERENZ zweier Aufrufe prueft den GF-Anteil exakt und kommt ohne
|
||||
;; die Bogen-Tabelle aus - die ist im file-freien Unit-Test leer
|
||||
;; (init-bibliothek laeuft hier nicht), der Bogenanteil faellt also weg.
|
||||
;; Eine absolute Schranke waere dadurch umgebungsabhaengig gewesen.
|
||||
(tu-eqf "vfl-m2-eingang-fp/gf-anteil-exakt"
|
||||
(* 3726.34 (cos (* 3.0 (/ pi 180.0))))
|
||||
(- (vfl-m2-eingang-fp 0 0 '(2) 3726.34 (* 3.0 (/ pi 180.0)))
|
||||
(vfl-m2-eingang-fp 0 0 '(2) 0.0 (* 3.0 (/ pi 180.0)))))
|
||||
;; Separator + Umlenkstation sind IMMER dabei, auch ohne GF und ohne Tabelle.
|
||||
(setq _l (vfl-m2-eingang-fp 0 0 '(2) 0.0 (* 3.0 (/ pi 180.0))))
|
||||
(tu-true "vfl-m2-eingang-fp/stationen-immer-dabei"
|
||||
(>= _l (* (+ *vfk-separator-laenge* *vfk-stations-laenge*)
|
||||
(cos (* 3.0 (/ pi 180.0))))))
|
||||
|
||||
;; --- Fremdanteil der Gefaellestrecke (fuer den stillen Nachrechner) ---
|
||||
;; Wieviel der vom Solver berechneten GF liegt NICHT auf dem Schenkel des
|
||||
;; Kletterers? Nur das darf dessen Spanne wieder zugeschlagen werden.
|
||||
;; Liegt der Eingang auf dem Kletterer selbst (gerader Normalfall), ist
|
||||
;; nichts fremd - dann MUSS 0 herauskommen, sonst wuerde der funktionierende
|
||||
;; Fall veraendert.
|
||||
(tu-eqf "vfl-m2-gf-fremd/eingang-ist-kletterer" 0.0
|
||||
(vfl-m2-gf-fremdanteil 3726.34 1 T))
|
||||
(tu-eqf "vfl-m2-gf-fremd/alles-einlauf" 3726.34
|
||||
(vfl-m2-gf-fremdanteil 3726.34 1 nil))
|
||||
(tu-eqf "vfl-m2-gf-fremd/halb-halb" 1863.17
|
||||
(vfl-m2-gf-fremdanteil 3726.34 2 nil))
|
||||
;; Alles am Auslauf (Modus 3, erzwungen bei offenem Anfang): die GF liegt
|
||||
;; dann beim Kletterer, nichts ist fremd.
|
||||
(tu-eqf "vfl-m2-gf-fremd/alles-auslauf" 0.0
|
||||
(vfl-m2-gf-fremdanteil 3726.34 3 nil))
|
||||
|
||||
;; --- ES-Reservierung auf die KS_AUS-Achse ---
|
||||
;; Vorgabe: quer zur KS_AUS-Achse MUSS 0 sein, laengs darf abweichen.
|
||||
;; Der reine Laengsanteil reicht dafuer NICHT - er laesst den bauteileigenen
|
||||
;; Querversatz stehen. Werte aus dem echten Lauf 2026-10-26:
|
||||
;; ES_Element_30_rechts an einer Geraden mit hz=-60, Schwenk -30 Grad,
|
||||
;; Fussabdruck (laengs 575.84 | quer -52.54). Reserve 484.8 statt 575.8 -
|
||||
;; die Gerade wird also rund 91 mm laenger und hebt den Querversatz auf.
|
||||
(tu-eqf "vfl-es-achs-reserve/echt-30-grad" 484.838050570331
|
||||
(vfl-es-achs-reserve 575.84 -52.54 -60.0 -30.0))
|
||||
;; Ohne Querversatz bleibt es beim reinen Laengsanteil.
|
||||
(tu-eqf "vfl-es-achs-reserve/ohne-quer" 500.0
|
||||
(vfl-es-achs-reserve 500.0 0.0 -60.0 -30.0))
|
||||
;; Ohne Schwenk faellt die Achse mit der Fahrtrichtung zusammen - dann gibt
|
||||
;; es keinen aufhebbaren Querversatz und der Laengsanteil ist richtig
|
||||
;; (Nenner 0, Rueckfall statt Division durch null).
|
||||
(tu-eqf "vfl-es-achs-reserve/ohne-schwenk" 575.84
|
||||
(vfl-es-achs-reserve 575.84 -52.54 -60.0 0.0))
|
||||
;; Richtungsunabhaengig: dieselbe Geometrie um 90 Grad gedreht gibt
|
||||
;; denselben Wert - die Reserve haengt an den Winkeln zueinander, nicht
|
||||
;; an der Lage im Welt-KS.
|
||||
(tu-eqf "vfl-es-achs-reserve/gedreht" 484.838050570331
|
||||
(vfl-es-achs-reserve 575.84 -52.54 30.0 -30.0))
|
||||
|
||||
;; --- Rueckwaerts bauen: Punkt entgegen der Fahrtrichtung zuruecksetzen ---
|
||||
;; vfl-rueck-punkt ist der Rechenkern des Rueckwaerts-Baus: zu einem
|
||||
;; BEKANNTEN Endpunkt den Startpunkt eines Bausteins finden. Vorwaerts gilt
|
||||
;; P_next = P + (L*cos hz, L*sin hz, -L*tan w) - hier also mit umgekehrtem
|
||||
;; Vorzeichen. Die Hoehe muss STEIGEN (der Vorgaenger liegt hoeher).
|
||||
(tu-eqf "vfl-rueck-punkt/ost-flach"
|
||||
(list 0.0 0.0 0.0) (vfl-rueck-punkt '(1000.0 0.0 0.0) 0.0 1000.0 0.0))
|
||||
(tu-eqf "vfl-rueck-punkt/nord-flach"
|
||||
(list 0.0 0.0 0.0) (vfl-rueck-punkt '(0.0 1000.0 0.0) 90.0 1000.0 0.0))
|
||||
;; 45 Grad Gefaelle: 1000 mm horizontal zurueck = 1000 mm hoeher
|
||||
(tu-eqf "vfl-rueck-punkt/45-grad"
|
||||
(list 0.0 0.0 1000.0) (vfl-rueck-punkt '(1000.0 0.0 0.0) 0.0 1000.0 45.0))
|
||||
;; Rundlauf: vorwaerts wieder auf den Ausgangspunkt (3 Grad, schraeg)
|
||||
(setq _l (vfl-rueck-punkt '(5000.0 3000.0 1800.0) 30.0 2000.0 3.0))
|
||||
(tu-eqf "vfl-rueck-punkt/rundlauf-x" 5000.0
|
||||
(+ (car _l) (* 2000.0 (cos (/ (* 30.0 pi) 180.0)))))
|
||||
(tu-eqf "vfl-rueck-punkt/rundlauf-y" 3000.0
|
||||
(+ (cadr _l) (* 2000.0 (sin (/ (* 30.0 pi) 180.0)))))
|
||||
(tu-eqf "vfl-rueck-punkt/rundlauf-z" 1800.0
|
||||
(- (caddr _l) (* 2000.0 (/ (sin (/ (* 3.0 pi) 180.0)) (cos (/ (* 3.0 pi) 180.0))))))
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; TESTS: vf_linienzug.lsp - Laenge aus einer Ziellinie (X/Y)
|
||||
;; ------------------------------------------------------------
|
||||
@@ -446,6 +782,86 @@
|
||||
(+ (cadr _ks) (sin (/ pi 6.0))) 0.0)))
|
||||
(tu-true "vfl-laenge-bis-ziellinie/realfall-plausibel"
|
||||
(and _l (> _l 1430.0) (< _l 1431.0)))
|
||||
|
||||
;; --- AS-Seite aus der Lage des naechsten Punkts zur Basislinie ---
|
||||
;; Basislinie zeigt nach +X; ein Ziel mit +Y liegt links davon, mit -Y rechts.
|
||||
(tu-eq "vfl-seite-aus-lage/links"
|
||||
"links" (vfl-seite-aus-lage '(0.0 0.0 0.0) '(1000.0 0.0 0.0) '(500.0 800.0 0.0)))
|
||||
(tu-eq "vfl-seite-aus-lage/rechts"
|
||||
"rechts" (vfl-seite-aus-lage '(0.0 0.0 0.0) '(1000.0 0.0 0.0) '(500.0 -800.0 0.0)))
|
||||
;; Richtung der Basislinie umdrehen -> Seite dreht mit
|
||||
(tu-eq "vfl-seite-aus-lage/basislinie-umgedreht"
|
||||
"rechts" (vfl-seite-aus-lage '(1000.0 0.0 0.0) '(0.0 0.0 0.0) '(500.0 800.0 0.0)))
|
||||
;; schraege Basislinie (45 Grad): Ziel oberhalb davon liegt links
|
||||
(tu-eq "vfl-seite-aus-lage/schraeg"
|
||||
"links" (vfl-seite-aus-lage '(0.0 0.0 0.0) '(1000.0 1000.0 0.0) '(0.0 1000.0 0.0)))
|
||||
;; Z spielt keine Rolle (rein planare Entscheidung)
|
||||
(tu-eq "vfl-seite-aus-lage/z-ignoriert"
|
||||
"rechts" (vfl-seite-aus-lage '(0.0 0.0 5000.0) '(1000.0 0.0 -200.0) '(500.0 -800.0 999.0)))
|
||||
|
||||
;; --- VF-Hoehe je SEGMENT (Attribut VF_HOEHE_m, Sivas 4433-4437) ---
|
||||
;; Ein Eintrag je GERADEM VF-Abschnitt: Mittelwert aus dessen KS_EIN und
|
||||
;; KS_AUS, in METERN mit 3 Nachkommastellen. Zwischen Umlenk- und
|
||||
;; Motorstation koennen mehrere Abschnitte liegen (auf/ab/horizontal), die
|
||||
;; Liste laeuft darum parallel zu L_VF_m und VF_WINKEL.
|
||||
(vf-vfhoehe-reset)
|
||||
(tu-eq "vf-vfhoehe/leer-nach-reset" "" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
|
||||
;; 2000 mm und 3000 mm -> Mittel 2500 mm -> "2.500"
|
||||
(vf-vfhoehe-segment 2000.0 3000.0)
|
||||
(tu-eq "vf-vfhoehe/mittelwert-meter" "2.500" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
|
||||
;; Drei Abschnitte wie im realen Block (L_VF_m hatte dort 3 Eintraege):
|
||||
;; horizontal, horizontal, steigend - alle drei bekommen einen Wert.
|
||||
(vf-vfhoehe-reset)
|
||||
(vf-vfhoehe-segment 2076.0 2076.0) ; horizontal
|
||||
(vf-vfhoehe-segment 2076.0 2076.0) ; horizontal
|
||||
(vf-vfhoehe-segment 2076.0 2600.0) ; steigend -> Mittel 2338
|
||||
(tu-eq "vf-vfhoehe/drei-abschnitte"
|
||||
"2.076,2.076,2.338" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
|
||||
;; Unvollstaendige Messung haengt NICHTS an - sonst verschoebe sich die
|
||||
;; Liste gegen L_VF_m und eine Hoehe landete beim falschen Foerderer.
|
||||
(vf-vfhoehe-reset)
|
||||
(vf-vfhoehe-segment 1000.0 2000.0)
|
||||
(vf-vfhoehe-segment nil 3000.0)
|
||||
(vf-vfhoehe-segment 4000.0 nil)
|
||||
(tu-eq "vf-vfhoehe/unvollstaendig-ignoriert" "1.500" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
|
||||
;; negative Hoehen (Kette unter Null) muessen durchgehen
|
||||
(vf-vfhoehe-reset)
|
||||
(vf-vfhoehe-segment -500.0 -1500.0)
|
||||
(tu-eq "vf-vfhoehe/negativ" "-1.000" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
(vf-vfhoehe-reset)
|
||||
|
||||
;; vf-meter-3: GENAU 3 Nachkommastellen, unabhaengig von DIMZIN.
|
||||
;; (rtos x 2 3) allein kuerzt nachfolgende Nullen ("2.5", "-1") - real im
|
||||
;; Testlauf aufgetreten, deshalb eigene Formatierung.
|
||||
(tu-eq "vf-meter-3/glatt" "2.500" (vf-meter-3 2500.0))
|
||||
(tu-eq "vf-meter-3/ganzzahlig" "3.000" (vf-meter-3 3000.0))
|
||||
(tu-eq "vf-meter-3/negativ" "-1.000" (vf-meter-3 -1000.0))
|
||||
(tu-eq "vf-meter-3/null" "0.000" (vf-meter-3 0.0))
|
||||
(tu-eq "vf-meter-3/drei-stellen" "1.234" (vf-meter-3 1234.0))
|
||||
|
||||
;; --- SONDERFALL Standard/Etage: Hoehe ueber die GANZE Kette ---
|
||||
;; Nur ein Motor und nur ein gerader VF-Abschnitt, darum zaehlt dort
|
||||
;; AS-KS_EIN .. ES-KS_AUS statt des Segmentwerts (Nutzer-Vorgabe 2026-10-21).
|
||||
(vf-vfhoehe-reset)
|
||||
(vf-vfhoehe-kette 1000.0 3000.0)
|
||||
(tu-eq "vf-vfhoehe-kette/mittelwert" "2.000" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
|
||||
;; ERSETZT den beim Bau gesammelten Segmentwert, haengt ihn NICHT an -
|
||||
;; sonst stuenden fuer eine Standard-Anlage zwei Hoehen in der Liste.
|
||||
(vf-vfhoehe-reset)
|
||||
(vf-vfhoehe-segment 5000.0 5000.0) ; Segmentwert aus vfs-vf-koerper
|
||||
(vf-vfhoehe-kette 1000.0 3000.0)
|
||||
(tu-eq "vf-vfhoehe-kette/ersetzt-segmentwert" "2.000" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
|
||||
;; fehlender Endpunkt -> lieber leer als geraten
|
||||
(vf-vfhoehe-reset)
|
||||
(vf-vfhoehe-kette 1000.0 nil)
|
||||
(tu-eq "vf-vfhoehe-kette/ohne-endpunkt-leer" "" (vfl-join-komma *vf-acc-vfhoehe*))
|
||||
(vf-vfhoehe-reset)
|
||||
)
|
||||
|
||||
|
||||
@@ -2278,6 +2694,349 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; TESTS: KettenFoerderer.lsp + ssg_ks_insert.lsp (KS-Orientierung)
|
||||
;; ------------------------------------------------------------
|
||||
;; Reine Rechenkerne des Kettenfoerderers: Hoehenbilanz, Massstab,
|
||||
;; Grenzpruefung, KS-Winkel. Alles ohne Zeichnung und ohne Blockdateien -
|
||||
;; die zeichnungsabhaengigen Teile (kf-geometrie-messen, kf-kette-bauen)
|
||||
;; brauchen BricsCAD und bleiben dem Befehl KF_KS_PRUEFEN vorbehalten.
|
||||
(defun tu-tests-kf ( / _l _s _defs)
|
||||
(princ "\n[KettenFoerderer]")
|
||||
(if (not (car (atoms-family 1 '("KF-LAENGE-BERECHNEN"))))
|
||||
(tu-record nil "KettenFoerderer-Modul geladen"
|
||||
"KettenFoerderer.lsp nicht geladen - siehe tests/test_unit.scr")
|
||||
(progn
|
||||
;; --- ks-winkel-normalisieren: auf -180..180 falten ---
|
||||
(tu-eqf "ks-winkel-norm/190" -170.0 (ks-winkel-normalisieren 190.0))
|
||||
(tu-eqf "ks-winkel-norm/-190" 170.0 (ks-winkel-normalisieren -190.0))
|
||||
(tu-eqf "ks-winkel-norm/26" 26.0 (ks-winkel-normalisieren 26.0))
|
||||
(tu-eqf "ks-winkel-norm/360" 0.0 (ks-winkel-normalisieren 360.0))
|
||||
(tu-nil "ks-winkel-norm/nil" (ks-winkel-normalisieren nil))
|
||||
|
||||
;; --- ks-xy-winkel: X-Achse eines KS-Eintrags (origin x-end y-end z-end)
|
||||
(tu-eqf "ks-xy-winkel/entlang-X" 0.0
|
||||
(ks-xy-winkel '((0.0 0.0 0.0) (1.0 0.0 0.0) (0.0 2.0 0.0) (0.0 0.0 3.0))))
|
||||
(tu-eqf "ks-xy-winkel/entlang-Y" 90.0
|
||||
(ks-xy-winkel '((0.0 0.0 0.0) (0.0 1.0 0.0) (-2.0 0.0 0.0) (0.0 0.0 3.0))))
|
||||
;; versetzter Ursprung: nur die RICHTUNG zaehlt, nicht die Lage
|
||||
(tu-eqf "ks-xy-winkel/versetzt-45" 45.0
|
||||
(ks-xy-winkel (list '(100.0 50.0 0.0) '(101.0 51.0 0.0) '(99.0 51.0 0.0) '(100.0 50.0 1.0))))
|
||||
;; senkrechte X-Achse (keine XY-Laenge) -> nil statt Division durch 0
|
||||
(tu-nil "ks-xy-winkel/senkrecht"
|
||||
(ks-xy-winkel '((0.0 0.0 0.0) (0.0 0.0 1.0) (0.0 2.0 0.0) (0.0 0.0 3.0))))
|
||||
|
||||
;; --- kf-hz-folge: Folgebaustein an KS_AUS des Vorgaengers ausrichten ---
|
||||
;; Vorgaenger zeigt 26 Grad, Folgebaustein ist waagerecht gezeichnet (0)
|
||||
(tu-eqf "kf-hz-folge/26-auf-0" 26.0 (kf-hz-folge 26.0 0.0))
|
||||
;; Folgebaustein ist selbst schon um 26 Grad gezeichnet -> keine Drehung
|
||||
(tu-eqf "kf-hz-folge/26-auf-26" 0.0 (kf-hz-folge 26.0 26.0))
|
||||
;; fehlende Eigenrichtung -> Baustein uebernimmt die Vorgaengerrichtung
|
||||
(tu-eqf "kf-hz-folge/ohne-beta" 26.0 (kf-hz-folge 26.0 nil))
|
||||
(tu-nil "kf-hz-folge/ohne-phi" (kf-hz-folge nil 0.0))
|
||||
|
||||
;; --- kf-dy-eingebaut: Hoehenbeitrag nach Rz(hz) und X-Massstab ---
|
||||
;; waagerechter Baustein, waagerecht eingebaut -> kein Hoehengewinn
|
||||
(tu-eqf "kf-dy/0-grad" 0.0 (kf-dy-eingebaut 1000.0 0.0 0.0 1.0))
|
||||
;; 1000 mm unter 30 Grad -> 500 mm (sin 30 = 0.5)
|
||||
(tu-eqf "kf-dy/30-grad" 500.0 (kf-dy-eingebaut 1000.0 0.0 30.0 1.0))
|
||||
;; derselbe Baustein doppelt skaliert -> doppelter Hoehengewinn
|
||||
(tu-eqf "kf-dy/30-grad-skaliert-2" 1000.0 (kf-dy-eingebaut 1000.0 0.0 30.0 2.0))
|
||||
;; senkrecht eingebaut -> die volle Laenge als Hoehe
|
||||
(tu-eqf "kf-dy/90-grad" 1000.0 (kf-dy-eingebaut 1000.0 0.0 90.0 1.0))
|
||||
|
||||
;; --- kf-laenge-berechnen: Hoehenbilanz nach der Laenge aufloesen ---
|
||||
;; H=1000, Stationen tragen nichts bei, 30 Grad -> L = 1000/sin30 = 2000
|
||||
(tu-eqf "kf-laenge/30-grad-glatt" 2000.0
|
||||
(kf-laenge-berechnen 1000.0 0.0 0.0 0.0 30.0))
|
||||
;; Stationen tragen 100+150 bei -> nur 750 mm bleiben fuer das Stueck
|
||||
(tu-eqf "kf-laenge/mit-stationen" 1500.0
|
||||
(kf-laenge-berechnen 1000.0 100.0 150.0 0.0 30.0))
|
||||
;; Gegenprobe: die errechnete Laenge ergibt wieder genau H
|
||||
(setq _l (kf-laenge-berechnen 1000.0 100.0 150.0 0.0 30.0))
|
||||
(tu-eqf "kf-laenge/rundlauf-ergibt-H" 1000.0
|
||||
(+ 100.0 150.0 (kf-dy-eingebaut _l 0.0 30.0 1.0)))
|
||||
;; bereits geneigt gezeichnetes Zwischenstueck: dy-nativ wird abgezogen
|
||||
;; (dy-nativ skaliert NICHT mit, nur X wird skaliert)
|
||||
(tu-eqf "kf-laenge/mit-dy-nativ" 1800.0
|
||||
(kf-laenge-berechnen 1000.0 0.0 0.0 (/ 100.0 (cos (/ pi 6.0))) 30.0))
|
||||
;; waagerecht -> keine Hoehe erreichbar
|
||||
(tu-nil "kf-laenge/0-grad-unloesbar"
|
||||
(kf-laenge-berechnen 1000.0 0.0 0.0 0.0 0.0))
|
||||
|
||||
;; --- kf-skala-berechnen ---
|
||||
(tu-eqf "kf-skala/2000-von-1000" 2.0 (kf-skala-berechnen 2000.0 1000.0))
|
||||
(tu-nil "kf-skala/ohne-nativlaenge" (kf-skala-berechnen 2000.0 0.0))
|
||||
(tu-nil "kf-skala/ohne-laenge" (kf-skala-berechnen nil 1000.0))
|
||||
|
||||
;; --- kf-laenge-pruefen: Grenzen aus der JSON ---
|
||||
(tu-nil "kf-pruefen/in-ordnung" (kf-laenge-pruefen 2000.0 100.0 20000.0))
|
||||
(tu-eq "kf-pruefen/zu-kurz" "kf-fehler-laenge-unter-min"
|
||||
(kf-laenge-pruefen 50.0 100.0 20000.0))
|
||||
(tu-eq "kf-pruefen/zu-lang" "kf-fehler-laenge-ueber-max"
|
||||
(kf-laenge-pruefen 99999.0 100.0 20000.0))
|
||||
;; negative Laenge = Stationen bringen mehr Hoehe mit als gefordert
|
||||
(tu-eq "kf-pruefen/negativ" "kf-fehler-hoehe-zu-klein"
|
||||
(kf-laenge-pruefen -10.0 100.0 20000.0))
|
||||
(tu-eq "kf-pruefen/nil" "kf-fehler-winkel-null"
|
||||
(kf-laenge-pruefen nil 100.0 20000.0))
|
||||
|
||||
;; --- kf-zahl: JSON-Wert als Zahl (Parser liefert Zahl ODER String) ---
|
||||
(tu-eqf "kf-zahl/int" 26.0 (kf-zahl 26))
|
||||
(tu-eqf "kf-zahl/real" 26.0 (kf-zahl 26.0))
|
||||
(tu-eqf "kf-zahl/string" 26.0 (kf-zahl "26"))
|
||||
(tu-nil "kf-zahl/nil" (kf-zahl nil))
|
||||
|
||||
;; --- kf-attrib-defs: VF-Schema + KF-Zusatz, KEIN Tag doppelt ---
|
||||
(setq _defs (kf-attrib-defs))
|
||||
(tu-true "kf-attrib-defs/hat-ID" (assoc "ID" _defs))
|
||||
(tu-true "kf-attrib-defs/hat-FOERDERERTYP" (assoc "FOERDERERTYP" _defs))
|
||||
(tu-true "kf-attrib-defs/hat-WINKEL" (assoc "WINKEL" _defs))
|
||||
(tu-true "kf-attrib-defs/hat-STANDARD_STEUERUNG"
|
||||
(assoc "STANDARD_STEUERUNG" _defs))
|
||||
;; Reihenfolge wie im Sivas-Merkmalstamm: 361 folgt direkt auf den Typ,
|
||||
;; STANDARD_STEUERUNG steht also unmittelbar hinter WINKEL
|
||||
(tu-eq "kf-attrib-defs/361-folgt-auf-winkel" "STANDARD_STEUERUNG"
|
||||
(car (nth (1+ (kf-tag-index "WINKEL" _defs)) _defs)))
|
||||
;; FOERDERERTYP ist die BAUART im Klartext, der Winkel steht in WINKEL
|
||||
(tu-eq "kf-attrib-defs/FOERDERERTYP-ist-bauart" "Schraegfoerderer Stahl"
|
||||
(cadr (assoc "FOERDERERTYP" _defs)))
|
||||
(tu-true "kf-attrib-defs/hat-MOVIMOT" (assoc "MOVIMOT" _defs))
|
||||
;; Farbe und Antriebsmotor sind ZWEI Eigenschaften (Sivas 354 bzw. 355), nicht
|
||||
;; ein kombiniertes AUSFUEHRUNG-Attribut
|
||||
(tu-true "kf-attrib-defs/hat-FARBE" (assoc "FARBE" _defs))
|
||||
(tu-true "kf-attrib-defs/hat-ANTRIEBSMOTOR" (assoc "ANTRIEBSMOTOR" _defs))
|
||||
(tu-nil "kf-attrib-defs/kein-AUSFUEHRUNG" (assoc "AUSFUEHRUNG" _defs))
|
||||
;; Der Kettenfoerderer traegt sich selbst - die Geruest-Tags aus dem
|
||||
;; VF-Schema werden bewusst NICHT mitgefuehrt
|
||||
(tu-nil "kf-attrib-defs/kein-GERUEST_EINZELMODUL"
|
||||
(assoc "GERUEST_EINZELMODUL" _defs))
|
||||
(tu-nil "kf-attrib-defs/kein-GERUEST_TYP" (assoc "GERUEST_TYP" _defs))
|
||||
;; Jeder Tag darf nur EINMAL vorkommen (zwei ATTDEFs gleichen Tags waeren
|
||||
;; im Block ungueltig, ssg-attrib-set-on traefe nur den ersten).
|
||||
(setq _s 0)
|
||||
(foreach _d _defs (if (= (car _d) "FOERDERERTYP") (setq _s (1+ _s))))
|
||||
(tu-eq "kf-attrib-defs/FOERDERERTYP-nur-einmal" 1 _s)
|
||||
(setq _s 0)
|
||||
(foreach _d _defs (if (= (car _d) "ARTINR") (setq _s (1+ _s))))
|
||||
(tu-eq "kf-attrib-defs/ARTINR-nur-einmal" 1 _s)
|
||||
(setq _s 0)
|
||||
(foreach _d _defs (if (= (car _d) "ARTINR") (setq _s (1+ _s))))
|
||||
(tu-eq "kf-attrib-defs/ARTINR-nur-einmal" 1 _s)
|
||||
;; Der Winkel steht ALLEIN in FOERDERERTYP - kein zweites Winkel-Tag
|
||||
(tu-nil "kf-attrib-defs/kein-KF_WINKEL" (assoc "KF_WINKEL" _defs))
|
||||
(tu-nil "kf-attrib-defs/kein-KF_TYP" (assoc "KF_TYP" _defs))
|
||||
;; Das Schema ist EIGENSTAENDIG, nicht vom VF-Streckenschema geerbt -
|
||||
;; keines der VF-Tags darf durchschlagen
|
||||
(tu-nil "kf-attrib-defs/kein-SEITE_AS" (assoc "SEITE_AS" _defs))
|
||||
(tu-nil "kf-attrib-defs/kein-ANZAHL_VF" (assoc "ANZAHL_VF" _defs))
|
||||
(tu-nil "kf-attrib-defs/kein-TEILEART" (assoc "TEILEART" _defs))
|
||||
(tu-eq "kf-attrib-defs/LAYER-ist-F-3" "F-3" (cadr (assoc "LAYER" _defs)))
|
||||
|
||||
;; --- kf-variante-finden: ueber den Winkel, auch als String ---
|
||||
(tu-eq "kf-variante-finden/26" "A"
|
||||
(cdr (assoc "name"
|
||||
(kf-variante-finden 26
|
||||
'((("winkel" . 26) ("name" . "A"))
|
||||
(("winkel" . 30) ("name" . "B")))))))
|
||||
(tu-eq "kf-variante-finden/30-als-string" "B"
|
||||
(cdr (assoc "name"
|
||||
(kf-variante-finden 30
|
||||
'((("winkel" . "26") ("name" . "A"))
|
||||
(("winkel" . "30") ("name" . "B")))))))
|
||||
(tu-nil "kf-variante-finden/unbekannt"
|
||||
(kf-variante-finden 45 '((("winkel" . 26) ("name" . "A")))))
|
||||
|
||||
;; --- kf-antriebsart (Merkmal 357): Dropdown mit EINER Option ---
|
||||
;; Der Wert kommt aus dem ERSTEN Listeneintrag - nicht aus dem Code.
|
||||
(tu-eq "kf-antriebsart/aus-daten" "1.1 kW"
|
||||
(kf-antriebsart '(("antriebsart" (("name" . "1.1 kW") ("wert" . "1.1 kW"))))))
|
||||
;; eine zweite Option aendert die Vorgabe NICHT (Index 0 bleibt massgebend)
|
||||
(tu-eq "kf-antriebsart/erster-eintrag-gewinnt" "1.1 kW"
|
||||
(kf-antriebsart '(("antriebsart" (("name" . "1.1 kW") ("wert" . "1.1 kW"))
|
||||
(("name" . "0.55 kW") ("wert" . "0.55 kW"))))))
|
||||
;; Liste fehlt -> Rueckfall, aber als STRING (nicht T/nil)
|
||||
(tu-eq "kf-antriebsart/ohne-eintrag" "1.1 kW" (kf-antriebsart '(("titel" . "x"))))
|
||||
(tu-true "kf-antriebsart/ist-string"
|
||||
(= (type (kf-antriebsart '(("titel" . "x")))) 'STR))
|
||||
;; Dezimalpunkt, kein Komma (Nutzervorgabe)
|
||||
(tu-nil "kf-antriebsart/kein-komma"
|
||||
(vl-string-search "," (kf-antriebsart '(("titel" . "x")))))
|
||||
|
||||
;; --- kf-drehung-gesamt: Drehwinkel fuer KF_EDIT ---
|
||||
;; Regression: der Drehwinkel wird beim Bau in die Geometrie eingerechnet,
|
||||
;; die Blockreferenz selbst hat IMMER Drehung 0 (ssg-block-wrap-welt).
|
||||
;; KF_EDIT las nur Gruppencode 50 und baute eine mit 90 Grad gebaute
|
||||
;; Kette ungedreht neu. Der gebaute Winkel steht jetzt als XDATA.
|
||||
(tu-eqf "kf-drehung/nur-xdata" 90.0 (kf-drehung-gesamt 90.0 0.0))
|
||||
;; Referenz nachtraeglich von Hand um 90 Grad gedreht (Gruppencode 50 in
|
||||
;; Bogenmass) -> beides addiert sich
|
||||
(tu-eqf "kf-drehung/xdata-plus-referenz" 180.0
|
||||
(kf-drehung-gesamt 90.0 (/ pi 2.0)))
|
||||
;; Altbestand ohne XDATA: nur die Referenzdrehung (bisheriges Verhalten)
|
||||
(tu-eqf "kf-drehung/ohne-xdata" 45.0 (kf-drehung-gesamt nil (/ pi 4.0)))
|
||||
;; nichts bekannt -> 0, kein Absturz und kein nil
|
||||
(tu-eqf "kf-drehung/nichts" 0.0 (kf-drehung-gesamt nil nil))
|
||||
(tu-true "kf-drehung/ist-zahl" (numberp (kf-drehung-gesamt nil nil)))
|
||||
;; Summe ueber 180 Grad wird auf -180..180 gefaltet (270 = -90)
|
||||
(tu-eqf "kf-drehung/normalisiert" -90.0
|
||||
(kf-drehung-gesamt 180.0 (/ pi 2.0)))
|
||||
;; ganze Zahl aus der XDATA (nicht real) darf nicht abstuerzen
|
||||
(tu-eqf "kf-drehung/ganzzahl" 30.0 (kf-drehung-gesamt 30 0.0))
|
||||
|
||||
;; --- kf-neigung-aus-punkten: Kern der 3D-Aufrichtung ---
|
||||
;; Liefert (Schraeglaenge Neigungswinkel) aus Ketten-Start und -Ende.
|
||||
;; Die Kette wird AUFGERICHTET eingebaut, die Hoehe laeuft also in Z.
|
||||
;; 3-4-5-Dreieck: 3000 waagerecht, 4000 hoch -> 5000 schraeg
|
||||
(tu-eqf "kf-neigung/3-4-5-laenge" 5000.0
|
||||
(car (kf-neigung-aus-punkten '(0.0 0.0 0.0) '(3000.0 0.0 4000.0) 0.0)))
|
||||
;; 45 Grad: gleiche Betraege waagerecht und hoch
|
||||
(tu-eqf "kf-neigung/45-grad" 45.0
|
||||
(cadr (kf-neigung-aus-punkten '(0.0 0.0 0.0) '(1000.0 0.0 1000.0) 0.0)))
|
||||
;; waagerecht -> Winkel 0, Laenge = Horizontalabstand
|
||||
(tu-eqf "kf-neigung/waagerecht" '(2000.0 0.0)
|
||||
(kf-neigung-aus-punkten '(0.0 0.0 0.0) '(2000.0 0.0 0.0) 0.0))
|
||||
;; Der Horizontalanteil wird auf die KETTENRICHTUNG projiziert, nicht
|
||||
;; auf die Welt-X-Achse: bei 90 Grad Basisdrehung laeuft die Kette in Y.
|
||||
;; Ohne Projektion kaeme hier 0 heraus und der Winkel waere 90 statt 45.
|
||||
(tu-eqf "kf-neigung/gedreht-90" '(1414.213562 45.0)
|
||||
(kf-neigung-aus-punkten '(0.0 0.0 0.0) '(0.0 1000.0 1000.0) 90.0))
|
||||
;; fallende Kette -> negativer Winkel
|
||||
(tu-eqf "kf-neigung/fallend" -45.0
|
||||
(cadr (kf-neigung-aus-punkten '(0.0 0.0 1000.0) '(1000.0 0.0 0.0) 0.0)))
|
||||
;; Start = Ende -> nil statt Division durch 0
|
||||
(tu-nil "kf-neigung/nulllaenge"
|
||||
(kf-neigung-aus-punkten '(5.0 5.0 5.0) '(5.0 5.0 5.0) 0.0))
|
||||
|
||||
;; --- kf-matrix-aufrecht: Y_lokal wird zu Z_welt ---
|
||||
;; Das ist die Kernaussage der Aufrichtung. Geprueft wird sie an den
|
||||
;; Bildern der Einheitsvektoren, nicht an den Matrixeintraegen - so
|
||||
;; bleibt der Test lesbar und unabhaengig von der Schreibweise.
|
||||
(tu-eqf "kf-matrix/Y-lokal-wird-Z-welt" '(0.0 0.0 1.0)
|
||||
(mat3-mul-vec3 (kf-matrix-aufrecht 0.0 0.0) '(0.0 1.0 0.0)))
|
||||
;; Die Fahrtrichtung (X) bleibt bei Basisdrehung 0 die Welt-X-Achse
|
||||
(tu-eqf "kf-matrix/X-bleibt-X" '(1.0 0.0 0.0)
|
||||
(mat3-mul-vec3 (kf-matrix-aufrecht 0.0 0.0) '(1.0 0.0 0.0)))
|
||||
;; Basisdrehung 90 Grad dreht die Fahrtrichtung in die Welt-Y-Achse,
|
||||
;; die Hoehe bleibt dabei in Z
|
||||
(tu-eqf "kf-matrix/basis-90-dreht-X-nach-Y" '(0.0 1.0 0.0)
|
||||
(mat3-mul-vec3 (kf-matrix-aufrecht 90.0 0.0) '(1.0 0.0 0.0)))
|
||||
(tu-eqf "kf-matrix/basis-90-haelt-Z" '(0.0 0.0 1.0)
|
||||
(mat3-mul-vec3 (kf-matrix-aufrecht 90.0 0.0) '(0.0 1.0 0.0)))
|
||||
|
||||
;; --- Standard-Variante: steht in den DATEN, nicht im Code ---
|
||||
(tu-true "kf-variante-standard-p/markiert"
|
||||
(kf-variante-standard-p '(("winkel" . 26) ("standard" . T))))
|
||||
(tu-nil "kf-variante-standard-p/ohne-feld"
|
||||
(kf-variante-standard-p '(("winkel" . 30))))
|
||||
;; Index fuer die Vorauswahl - auch wenn der Standard NICHT der erste ist
|
||||
(tu-eq "kf-standard-index/zweiter" 1
|
||||
(kf-standard-index '((("winkel" . 26))
|
||||
(("winkel" . 30) ("standard" . T)))))
|
||||
(tu-eq "kf-standard-index/erster" 0
|
||||
(kf-standard-index '((("winkel" . 26) ("standard" . T))
|
||||
(("winkel" . 30)))))
|
||||
;; keine Variante markiert -> erste, statt nil (der Dialog braucht einen Index)
|
||||
(tu-eq "kf-standard-index/keiner" 0
|
||||
(kf-standard-index '((("winkel" . 26)) (("winkel" . 30)))))
|
||||
|
||||
;; --- kf-punkt-differenzen: zweite Hoehen-Eingabeart (2 Punkte) ---
|
||||
;; Gemessen wird die Differenz in Z - die Baugruppe steht aufgerichtet im
|
||||
;; Modell. Zurueckgegeben wird (dz dy): die HOEHE zuerst, dY nur zur
|
||||
;; Kontrolle (wer in einer Draufsicht pickt, sieht dz = 0).
|
||||
(tu-eqf "kf-punkt-diff/dz" '(1500.0 0.0)
|
||||
(kf-punkt-differenzen '(0.0 0.0 0.0) '(2000.0 0.0 1500.0)))
|
||||
;; Vorzeichen egal - die Reihenfolge der Punkte darf keine Rolle spielen
|
||||
(tu-eqf "kf-punkt-diff/umgekehrt" '(1500.0 0.0)
|
||||
(kf-punkt-differenzen '(2000.0 0.0 1500.0) '(0.0 0.0 0.0)))
|
||||
;; in einer Draufsicht gepickt: dz = 0, dY gross
|
||||
(tu-eqf "kf-punkt-diff/draufsicht" '(0.0 1200.0)
|
||||
(kf-punkt-differenzen '(0.0 0.0 0.0) '(3000.0 1200.0 0.0)))
|
||||
;; Punkte ohne Z (2D-Pick) duerfen nicht abstuerzen: dz ist dann 0
|
||||
(tu-eqf "kf-punkt-diff/ohne-z" '(0.0 800.0)
|
||||
(kf-punkt-differenzen '(0.0 0.0) '(100.0 800.0)))
|
||||
(tu-nil "kf-punkt-diff/nil" (kf-punkt-differenzen nil '(1.0 2.0 3.0)))
|
||||
|
||||
;; --- kf-auswahl-wert: "wert" vor "name", Vorgabe bei leerem Index ---
|
||||
(tu-eq "kf-auswahl-wert/wert" "Nein"
|
||||
(kf-auswahl-wert '((("name" . "Nein") ("wert" . "Nein"))) 0 "X"))
|
||||
(tu-eq "kf-auswahl-wert/ausserhalb" "X"
|
||||
(kf-auswahl-wert '((("name" . "Nein") ("wert" . "Nein"))) 5 "X"))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; TESTS: check_hoehen.lsp - Phase 3 (Buehnen-Familien), reine Kerne
|
||||
;; ------------------------------------------------------------
|
||||
(defun tu-tests-hoehen-fam ( / _els)
|
||||
(princ "\n[check_hoehen/Phase 3 Familien]")
|
||||
|
||||
;; --- ch-familien: transitive Verbindung, Sortierung nach ID-Nummer ---
|
||||
(tu-eq "ch-familien/einzeln-und-kette"
|
||||
'(("b") ("c" "a" "d") ("e"))
|
||||
(ch-familien '(("a" 3) ("b" 1) ("c" 2) ("d" 5) ("e" 4))
|
||||
'(("a" "c") ("c" "d") ("x" "a"))))
|
||||
(tu-eq "ch-familien/kette-ueber-mittleren"
|
||||
'(("a" "b" "c"))
|
||||
(ch-familien '(("a" 1) ("b" 2) ("c" 3)) '(("a" "b") ("b" "c"))))
|
||||
(tu-eq "ch-familien/ohne-kanten"
|
||||
'(("a") ("b"))
|
||||
(ch-familien '(("a" 1) ("b" 2)) nil))
|
||||
(tu-eq "ch-familien/ring"
|
||||
'(("a" "b" "c"))
|
||||
(ch-familien '(("a" 1) ("b" 2) ("c" 3)) '(("a" "b") ("b" "c") ("c" "a"))))
|
||||
|
||||
;; --- ch-kreuz-abzug ---
|
||||
(tu-eq "ch-kreuz-abzug/kein" '("kein" . 0.0) (ch-kreuz-abzug 0.0 0.0 5000.0 5000.0 1500.0))
|
||||
(tu-eq "ch-kreuz-abzug/konflikt" '("konflikt" . 0.0) (ch-kreuz-abzug 1.5 0.0 5000.0 5000.0 1500.0))
|
||||
(tu-eq "ch-kreuz-abzug/konflikt2" '("konflikt" . 0.0) (ch-kreuz-abzug 1.5 2.0 5000.0 5000.0 1500.0))
|
||||
(tu-eq "ch-kreuz-abzug/hoehe" '("hoehe" . 0.0) (ch-kreuz-abzug 1.5 1.5 5000.0 6600.0 1500.0))
|
||||
(tu-eq "ch-kreuz-abzug/grenze" '("abzug" . 1.5) (ch-kreuz-abzug 1.5 1.5 5000.0 6500.0 1500.0))
|
||||
(tu-eq "ch-kreuz-abzug/abzug" '("abzug" . 1.5) (ch-kreuz-abzug 1.5 1.5 5000.0 5200.0 1500.0))
|
||||
|
||||
;; --- ch-strecke-abzug (Familiensaetze: idx handles z b) ---
|
||||
(tu-eq "ch-strecke-abzug/innen"
|
||||
'("innen" . 1.5)
|
||||
(ch-strecke-abzug '(1 ("a") 5000.0 1.5) '(1 ("a") 5000.0 1.5) 1500.0))
|
||||
(tu-eq "ch-strecke-abzug/innen-ohne-buehne"
|
||||
'("innen" . 0.0)
|
||||
(ch-strecke-abzug '(1 ("a") 5000.0 0.0) '(1 ("a") 5000.0 0.0) 1500.0))
|
||||
(tu-eq "ch-strecke-abzug/zwischen"
|
||||
'("abzug" . 1.5)
|
||||
(ch-strecke-abzug '(1 ("a") 5000.0 1.5) '(2 ("b") 5400.0 1.5) 1500.0))
|
||||
|
||||
;; --- ch-schleife-p: gleicher Kreisel + gleiche Hoehe ---
|
||||
(tu-true "ch-schleife-p/gleicher-kreisel-flach" (ch-schleife-p "K1" "K1" 5000.0 5000.0 1.0))
|
||||
(tu-true "ch-schleife-p/toleranz" (ch-schleife-p "K1" "K1" 5000.0 5000.8 1.0))
|
||||
(tu-nil "ch-schleife-p/hoehenunterschied" (ch-schleife-p "K1" "K1" 5000.0 4800.0 1.0))
|
||||
(tu-nil "ch-schleife-p/anderer-kreisel" (ch-schleife-p "K1" "K2" 5000.0 5000.0 1.0))
|
||||
(tu-nil "ch-schleife-p/kein-kreisel" (ch-schleife-p nil nil 5000.0 5000.0 1.0))
|
||||
|
||||
;; --- ch-abzug-anwenden ---
|
||||
(tu-eqf "ch-abzug-anwenden/normal" 2.5 (ch-abzug-anwenden 3.5 1.0))
|
||||
(tu-nil "ch-abzug-anwenden/gleich" (ch-abzug-anwenden 3.5 3.5))
|
||||
(tu-nil "ch-abzug-anwenden/groesser" (ch-abzug-anwenden 3.5 4.0))
|
||||
(tu-nil "ch-abzug-anwenden/null" (ch-abzug-anwenden 3.5 0.0))
|
||||
|
||||
;; --- ch-kreisel-finden: Kreisel r=400, Achse (400,0)-(2400,0) bzw. (400,5000)-(2400,5000) ---
|
||||
(setq _els (list (tu-bp-el "KREISEL" 0.0 0.0 5000.0 0.0 2000.0 "K1")
|
||||
(tu-bp-el "KREISEL" 0.0 5000.0 5000.0 0.0 2000.0 "K2")))
|
||||
(tu-eq "ch-kreisel-finden/auf-achse"
|
||||
"K1" (ch-kreisel-finden '(1000.0 100.0 5000.0) 5000.0 _els 300.0 100.0))
|
||||
(tu-eq "ch-kreisel-finden/zweiter"
|
||||
"K2" (ch-kreisel-finden '(1000.0 4900.0 5000.0) 5000.0 _els 300.0 100.0))
|
||||
(tu-eq "ch-kreisel-finden/hinter-dem-rad"
|
||||
"K1" (ch-kreisel-finden '(-200.0 0.0 5000.0) 5000.0 _els 300.0 100.0))
|
||||
(tu-nil "ch-kreisel-finden/zu-weit"
|
||||
(ch-kreisel-finden '(1000.0 1000.0 5000.0) 5000.0 _els 300.0 100.0))
|
||||
(tu-nil "ch-kreisel-finden/falsche-hoehe"
|
||||
(ch-kreisel-finden '(1000.0 0.0 5300.0) 5300.0 _els 300.0 100.0))
|
||||
)
|
||||
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; TESTS: ssg_core.lsp - Polygon-Helfer (reine 2D-Berechnung)
|
||||
;; ------------------------------------------------------------
|
||||
@@ -2720,11 +3479,12 @@
|
||||
(princ "\n================================================================")
|
||||
|
||||
(foreach fn '("tu-tests-core" "tu-tests-lang" "tu-tests-id" "tu-tests-vfcore"
|
||||
"tu-tests-etage" "tu-tests-vfl-es" "tu-tests-vfl-ziellinie"
|
||||
"tu-tests-etage" "tu-tests-vfl-es" "tu-tests-vfl-parallel"
|
||||
"tu-tests-vfl-ziellinie"
|
||||
"tu-tests-export" "tu-tests-hoehen" "tu-tests-gf" "tu-tests-omni" "tu-tests-kreisel" "tu-tests-kreisel-bp"
|
||||
"tu-tests-sepliste" "tu-tests-json" "tu-tests-geruest"
|
||||
"tu-tests-sepscan" "tu-tests-vfl-segs" "tu-tests-vfl-abbruch"
|
||||
"tu-tests-werkzeuge" "tu-tests-poly" "tu-tests-lager")
|
||||
"tu-tests-werkzeuge" "tu-tests-poly" "tu-tests-lager" "tu-tests-kf" "tu-tests-hoehen-fam")
|
||||
(tu-run-block fn))
|
||||
|
||||
(princ "\n\n----------------------------------------------------------------")
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
; Modul, gehoert dessen load-Zeile HIER dazu (nicht in test_unit.lsp).
|
||||
(load (strcat (getenv "DXFM_LISP") "/GeruestInsert.lsp") "GeruestInsert.lsp nicht gefunden")
|
||||
(load (strcat (getenv "DXFM_LISP") "/count_sep_scan.lsp") "count_sep_scan.lsp nicht gefunden")
|
||||
(load (strcat (getenv "DXFM_LISP") "/KettenFoerderer.lsp") "KettenFoerderer.lsp nicht gefunden")
|
||||
(load (strcat (getenv "DXFM_LISP") "/check_hoehen.lsp") "check_hoehen.lsp nicht gefunden")
|
||||
(load (strcat (getenv "DXFMAKRO") "/tests/test_unit.lsp"))
|
||||
(c:TEST_UNIT)
|
||||
(command "_.QUIT")
|
||||
@@ -175,10 +175,12 @@ EINGABE_ERLAUBT = {
|
||||
"vfl-in-selection": {"ssget": 1},
|
||||
"vfl-in-segmente": {"ssget": 1}, # Modus-3-Wrapper: Live-Auswahl -> Segment-Essenz (SEGS), Replay aus Journal
|
||||
"vfl-winkel-live": {"getint": 1}, # livefn fuer vfl-in-value
|
||||
"vfl-menu-strwert": {"getstring": 1}, # livefn fuer vfl-in-value (Wert statt Index)
|
||||
# --- Wizard-Schicht (DCL); bei ssg-gui-aus greift sie nicht ---
|
||||
"vflw-zahl": {"getreal": 1}, # Fallback ohne Dialog
|
||||
"vflw-zahl-impl": {"new_dialog": 1},
|
||||
"vflw-wahl-impl": {"new_dialog": 1},
|
||||
"vflw-radio-wahl-impl": {"new_dialog": 1},
|
||||
"vflw-gruppe-as-impl": {"new_dialog": 1},
|
||||
"vflw-gruppe-gefaelle-impl": {"new_dialog": 1},
|
||||
"vflw-gruppe-punkt-hoehe-impl": {"new_dialog": 1},
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
[
|
||||
{
|
||||
"beschreibung": "Linienzug Modus 2, Variante B: 90-Grad-Ecke als GF-BOGEN (geneigt eingebaut). Deckt die Neigungs-Projektion der Eck-Korrektur ab (vfl-projiziere-neigung) und den Zweig OHNE flache Zone, in dem der ES-Fussabdruck frueher faelschlich vom VF-Lauf abgezogen wurde (878 mm). Aufgezeichnet 2026-10-27 aus einem echten BricsCAD-Lauf. Startpunkt fuer die Testreihe versetzt: alle Koordinaten (Start-/Zielpunkt und Pfadsegmente) um einen gemeinsamen Vektor verschoben, damit TEST_LINIENZUG_MODUS2 die Ketten nebeneinander auf einer Grundlinie baut statt verstreut. Reine Translation - Laengen, Winkel und die geprueften Abweichungen sind davon unabhaengig; Z bleibt unveraendert, weil die Starthoehe ein Eingabewert des Solvers ist.",
|
||||
"test_id": "LZ_M2_gfbogen",
|
||||
"kurz": "Ecke als GF-Bogen",
|
||||
"erwartung_quer_mm": 0,
|
||||
"erwartung_dz_mm": 0,
|
||||
"erwartung_laengs_mm": 105,
|
||||
"erwartung_hinweis": "quer zur ES-KS_AUS-Achse MUSS ~0 sein und dZ ~0; laengs darf abweichen - das ist die Ausladung des ES-Elements und kein Fehler. Beides zugleich geht nicht: entweder liegt die letzte Gerade auf der gezeichneten Linie und der KS_AUS landet seitlich daneben, oder umgekehrt. Entschieden ist - der Hauptstrang bleibt gerade."
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 60000.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 0.0
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "90"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 71000.0,
|
||||
"y": -6315.123197,
|
||||
"z": 184.3
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 184.3
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "30"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "SEGS",
|
||||
"wert": "Linie|0|9700|0|links|60000|0|69700|0;Bogen|0|707.106781|90|rechts|69700|0|70200|-500;Linie|-90|4295.507955|0|links|70200|-500|70200|-4795.507955;Bogen|-90|258.819045|30|links|70200|-4795.507955|70266.987298|-5045.507955;Linie|-60|1466.025404|0|links|70266.987298|-5045.507955|71000|-6315.123197"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "m2v2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 3.0
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 3.0
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "mit-gf1"
|
||||
},
|
||||
{
|
||||
"art": "INT",
|
||||
"wert": 1
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
}
|
||||
]
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"beschreibung": "Linienzug Modus 2, GEFALTETER Lauf (U-Form): der Pfad wechselt ueber zwei 90-Grad-Vario-Kurven dreimal die Fahrtrichtung, die Kletterstrecke liegt dadurch in einem ANDEREN Schenkel als der Lauf-Eingang. GF-Verteilung 1 (alles am Einlauf, GF1) - diese Verteilung war bis 2026-10-29 durch keinen Test abgedeckt. Aufgezeichnet 2026-10-29 aus einem echten BricsCAD-Lauf. Startpunkt fuer die Testreihe versetzt: alle Koordinaten (Start-/Zielpunkt und Pfadsegmente) um einen gemeinsamen Vektor verschoben, damit TEST_LINIENZUG_MODUS2 die Ketten nebeneinander auf einer Grundlinie baut statt verstreut. Reine Translation - Laengen, Winkel und die geprueften Abweichungen sind davon unabhaengig; Z bleibt unveraendert, weil die Starthoehe ein Eingabewert des Solvers ist.",
|
||||
"test_id": "LZ_M2_uform_gf1",
|
||||
"kurz": "U-Form, GF alles am Einlauf",
|
||||
"erwartung_quer_mm": 0,
|
||||
"erwartung_dz_mm": 0,
|
||||
"erwartung_laengs_mm": 638,
|
||||
"erwartung_hinweis": "quer zur ES-KS_AUS-Achse MUSS ~0 sein und dZ ~0; laengs darf abweichen - das ist die Ausladung des ES-Elements und kein Fehler. Der laengs-Wert von rund 638 mm ist die Ausladung des ES_Element_90_links und in allen drei U-Form-Faellen gleich; geprueft werden nur quer und dZ."
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 80000.0,
|
||||
"y": 0.0,
|
||||
"z": 355.289671
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 355.3
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "90"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 81269.916932,
|
||||
"y": 0.0,
|
||||
"z": 355.289671
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 355.3
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "90"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "SEGS",
|
||||
"wert": "Linie|90|5854.769733|0|links|80000|0|80000|5854.769733;Bogen|90|707.106781|90|rechts|80000|5854.769733|80500|6354.769733;Linie|0|269.916931|0|links|80500|6354.769733|80769.916932|6354.769733;Bogen|0|707.106781|90|rechts|80769.916932|6354.769733|81269.916932|5854.769733;Linie|-90|5854.769733|0|links|81269.916932|5854.769733|81269.916932|0"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "m2v2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vf"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vario-kurve"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "aussen"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vario-kurve"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "aussen"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "mit-gf1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "3"
|
||||
},
|
||||
{
|
||||
"art": "INT",
|
||||
"wert": 2
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
}
|
||||
]
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"beschreibung": "Linienzug Modus 2, GEFALTETER Lauf (U-Form), GF-Verteilung 2 (1/2 GF1 + 1/2 GF2). DAS ist der Lauf, an dem die Laengenbilanz des gefalteten Laufs entwickelt und gemessen wurde: 1424 -> 934 -> 402 -> 0.56 mm quer (9 Grad). Er deckt alle vier Teilstuecke zugleich ab - Eingangs-Hardware im fremden Schenkel, kletter-ende-fp, GF1-Fremdanteil (Nachrechner) und das unterdrueckte Fueller-A. Aufgezeichnet 2026-10-29 aus einem echten BricsCAD-Lauf. Startpunkt fuer die Testreihe versetzt: alle Koordinaten (Start-/Zielpunkt und Pfadsegmente) um einen gemeinsamen Vektor verschoben, damit TEST_LINIENZUG_MODUS2 die Ketten nebeneinander auf einer Grundlinie baut statt verstreut. Reine Translation - Laengen, Winkel und die geprueften Abweichungen sind davon unabhaengig; Z bleibt unveraendert, weil die Starthoehe ein Eingabewert des Solvers ist.",
|
||||
"test_id": "LZ_M2_uform_halb",
|
||||
"kurz": "U-Form, GF 1/2+1/2",
|
||||
"erwartung_quer_mm": 0,
|
||||
"erwartung_dz_mm": 0,
|
||||
"erwartung_laengs_mm": 638,
|
||||
"erwartung_hinweis": "quer zur ES-KS_AUS-Achse MUSS ~0 sein und dZ ~0; laengs darf abweichen - das ist die Ausladung des ES-Elements und kein Fehler. Der laengs-Wert von rund 638 mm ist die Ausladung des ES_Element_90_links und in allen drei U-Form-Faellen gleich; geprueft werden nur quer und dZ."
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 100000.0,
|
||||
"y": 0.0,
|
||||
"z": 710.579341
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 710.6
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "90"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 101269.916932,
|
||||
"y": -1951.333591,
|
||||
"z": 710.579341
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 710.6
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "90"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "SEGS",
|
||||
"wert": "Linie|90|5854.769733|0|links|100000|0|100000|5854.769733;Bogen|90|707.106781|90|rechts|100000|5854.769733|100500|6354.769733;Linie|0|269.916931|0|links|100500|6354.769733|100769.916932|6354.769733;Bogen|0|707.106781|90|rechts|100769.916932|6354.769733|101269.916932|5854.769733;Linie|-90|7806.103325|0|links|101269.916932|5854.769733|101269.916932|-1951.333591"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "m2v2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vf"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vario-kurve"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "aussen"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vario-kurve"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "aussen"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "mit-gf1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "3"
|
||||
},
|
||||
{
|
||||
"art": "INT",
|
||||
"wert": 2
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"beschreibung": "Linienzug Modus 2, GEFALTETER Lauf (U-Form) wie LZ_M2_uform_halb, aber mit der naechststeileren Winkel-Option. Der Restfehler der alten Bilanz skalierte mit L_GF und damit mit dem Winkel (6 Grad: 90 mm, 9 Grad: 934 mm) - zwei Winkel auf derselben Pfadfamilie sichern deshalb mehr ab als zwei Laeufe mit demselben. Aufgezeichnet 2026-10-29 aus einem echten BricsCAD-Lauf. Startpunkt fuer die Testreihe versetzt: alle Koordinaten (Start-/Zielpunkt und Pfadsegmente) um einen gemeinsamen Vektor verschoben, damit TEST_LINIENZUG_MODUS2 die Ketten nebeneinander auf einer Grundlinie baut statt verstreut. Reine Translation - Laengen, Winkel und die geprueften Abweichungen sind davon unabhaengig; Z bleibt unveraendert, weil die Starthoehe ein Eingabewert des Solvers ist.",
|
||||
"test_id": "LZ_M2_uform_halb_steil",
|
||||
"kurz": "U-Form, GF 1/2+1/2, steilere Winkel-Option",
|
||||
"erwartung_quer_mm": 0,
|
||||
"erwartung_dz_mm": 0,
|
||||
"erwartung_laengs_mm": 638,
|
||||
"erwartung_hinweis": "quer zur ES-KS_AUS-Achse MUSS ~0 sein und dZ ~0; laengs darf abweichen - das ist die Ausladung des ES-Elements und kein Fehler. Der laengs-Wert von rund 638 mm ist die Ausladung des ES_Element_90_links und in allen drei U-Form-Faellen gleich; geprueft werden nur quer und dZ."
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 120000.0,
|
||||
"y": 0.0,
|
||||
"z": 709.285191
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 709.3
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "90"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 121269.916932,
|
||||
"y": 0.077406,
|
||||
"z": 709.275779
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 709.3
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "90"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "SEGS",
|
||||
"wert": "Linie|90|5854.769733|0|links|120000|-21.403816|120000|5833.365917;Bogen|90|707.106781|90|rechts|120000|5833.365917|120500|6333.365917;Linie|0|269.916931|0|links|120500|6333.365917|120769.916932|6333.365917;Bogen|0|707.106781|90|rechts|120769.916932|6333.365917|121269.916932|5833.365917;Linie|-90|5854.769733|0|links|121269.916932|5833.365917|121269.916932|-21.403816"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "m2v2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vf"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vario-kurve"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "aussen"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "vario-kurve"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "aussen"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "mit-gf1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "3"
|
||||
},
|
||||
{
|
||||
"art": "INT",
|
||||
"wert": 3
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
}
|
||||
]
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
[
|
||||
{
|
||||
"beschreibung": "Linienzug Modus 2, Variante A: 90-Grad-Ecke als VARIO-KURVE (waagerecht eingebaut), Segment 3 dadurch automatisch VF. Deckt die flache Zone ab (Abschluss-Fussabdruck Bogen+Motorstation) und die Eck-Korrektur von 93.8 mm je Nachbargerade. Aufgezeichnet 2026-10-27 aus einem echten BricsCAD-Lauf. Startpunkt fuer die Testreihe versetzt: alle Koordinaten (Start-/Zielpunkt und Pfadsegmente) um einen gemeinsamen Vektor verschoben, damit TEST_LINIENZUG_MODUS2 die Ketten nebeneinander auf einer Grundlinie baut statt verstreut. Reine Translation - Laengen, Winkel und die geprueften Abweichungen sind davon unabhaengig; Z bleibt unveraendert, weil die Starthoehe ein Eingabewert des Solvers ist.",
|
||||
"test_id": "LZ_M2_variokurve",
|
||||
"kurz": "Ecke als Vario-Kurve",
|
||||
"erwartung_quer_mm": 0,
|
||||
"erwartung_dz_mm": 0,
|
||||
"erwartung_laengs_mm": 105,
|
||||
"erwartung_hinweis": "quer zur ES-KS_AUS-Achse MUSS ~0 sein und dZ ~0; laengs darf abweichen - das ist die Ausladung des ES-Elements und kein Fehler. Beides zugleich geht nicht: entweder liegt die letzte Gerade auf der gezeichneten Linie und der KS_AUS landet seitlich daneben, oder umgekehrt. Entschieden ist - der Hauptstrang bleibt gerade."
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 40000.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 0.0
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "90"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "PT",
|
||||
"x": 51000.0,
|
||||
"y": -6315.123197,
|
||||
"z": 184.3
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 184.3
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "30"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "SEGS",
|
||||
"wert": "Linie|0|9700|0|links|40000|0|49700|0;Bogen|0|707.106781|90|rechts|49700|0|50200|-500;Linie|-90|4295.507955|0|links|50200|-500|50200|-4795.507955;Bogen|-90|258.819045|30|links|50200|-4795.507955|50266.987298|-5045.507955;Linie|-60|1466.025404|0|links|50266.987298|-5045.507955|51000|-6315.123197"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "m2v2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
},
|
||||
{
|
||||
"art": "REAL",
|
||||
"wert": 3.0
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "2"
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "mit-gf1"
|
||||
},
|
||||
{
|
||||
"art": "INT",
|
||||
"wert": 1
|
||||
},
|
||||
{
|
||||
"art": "STR",
|
||||
"wert": "1"
|
||||
}
|
||||
]
|
||||
Vendored
+11
-2
@@ -8,14 +8,19 @@
|
||||
},
|
||||
{
|
||||
"typ": "point_abs",
|
||||
"wert": [-1289.407125, 95.871332, 2154],
|
||||
"kommentar": "getpoint Startpunkt der Kette"
|
||||
"wert": [0.0, 0.0, 2154],
|
||||
"kommentar": "getpoint Startpunkt der Kette - fuer die Testreihe auf X=0/Y=0 versetzt, damit die Ketten aller Linienzug-Tests nebeneinander auf einer Grundlinie entstehen statt verstreut. Unkritisch, weil dies der EINZIGE absolute Punkt des Skripts ist: alle weiteren Punkte sind relativ (point_rel mit dL/hz), die Geometrie also unveraendert. Z bleibt stehen - das ist die Starthoehe und ein echter Eingabewert."
|
||||
},
|
||||
{
|
||||
"typ": "real",
|
||||
"wert": 2154.0,
|
||||
"kommentar": "getreal Hoehe (Z) Startpunkt"
|
||||
},
|
||||
{
|
||||
"typ": "string",
|
||||
"wert": "1",
|
||||
"kommentar": "getstring Bau-Richtung (1 = vorwaerts) - seit 2026-10-25 (Commit fb56794, Rueckwaerts-Bau). Die Frage steht VOR der AS-Praeambel. Fuer JOURNALE ist sie abwaertskompatibel (fehlt der Eintrag, gilt das Journal als Alt-Format), fuer dieses MOCK-Skript aber nicht: der Mock beantwortet jede getstring-Abfrage aus der Queue, eine fehlende Antwort verschiebt also alles Folgende um eine Position. Sichtbar wurde das als Abbruch in cdr mit dem String 5, weil die Achsen-Punktabfrage dann diesen String zog statt eines Punktes."
|
||||
},
|
||||
{
|
||||
"typ": "string",
|
||||
"wert": "1",
|
||||
@@ -31,6 +36,10 @@
|
||||
"wert": "1",
|
||||
"kommentar": "getstring AS-Seite (links)"
|
||||
},
|
||||
{
|
||||
"typ": "point_none",
|
||||
"kommentar": "getpoint AS-Zufuehrungsachse (2. Punkt, optional seit 2026-10-21) - Enter ohne Punkt, Kette laeuft wie frueher ueber den naechsten Klick"
|
||||
},
|
||||
{
|
||||
"typ": "string",
|
||||
"wert": "5",
|
||||
|
||||
+11
-2
@@ -8,14 +8,19 @@
|
||||
},
|
||||
{
|
||||
"typ": "point_abs",
|
||||
"wert": [21377.904954, -10300, 2067],
|
||||
"kommentar": "getpoint Startpunkt der Kette"
|
||||
"wert": [20000.0, 0.0, 2067],
|
||||
"kommentar": "getpoint Startpunkt der Kette - fuer die Testreihe auf X=20000/Y=0 versetzt, damit die Ketten aller Linienzug-Tests nebeneinander auf einer Grundlinie entstehen statt verstreut. Unkritisch, weil dies der EINZIGE absolute Punkt des Skripts ist: alle weiteren Punkte sind relativ (point_rel mit dL/hz), die Geometrie also unveraendert. Z bleibt stehen - das ist die Starthoehe und ein echter Eingabewert."
|
||||
},
|
||||
{
|
||||
"typ": "real",
|
||||
"wert": 2154.0,
|
||||
"kommentar": "getreal Hoehe (Z) Startpunkt"
|
||||
},
|
||||
{
|
||||
"typ": "string",
|
||||
"wert": "1",
|
||||
"kommentar": "getstring Bau-Richtung (1 = vorwaerts) - seit 2026-10-25 (Commit fb56794, Rueckwaerts-Bau). Siehe gleichlautenden Eintrag in linienzug_tests.json: fuer Journale abwaertskompatibel, fuer dieses Mock-Skript nicht."
|
||||
},
|
||||
{
|
||||
"typ": "string",
|
||||
"wert": "1",
|
||||
@@ -31,6 +36,10 @@
|
||||
"wert": "1",
|
||||
"kommentar": "getstring AS-Seite (links)"
|
||||
},
|
||||
{
|
||||
"typ": "point_none",
|
||||
"kommentar": "getpoint AS-Zufuehrungsachse (2. Punkt, optional seit 2026-10-21) - Enter ohne Punkt"
|
||||
},
|
||||
{
|
||||
"typ": "string",
|
||||
"wert": "5",
|
||||
|
||||
Vendored
+2
-1
@@ -8,6 +8,7 @@
|
||||
"abstand": 5000,
|
||||
"rotation": 0.0,
|
||||
"typ": "STANDARD",
|
||||
"drehrichtung": "GUZ",
|
||||
"expect_block_prefix": "KREISEL_",
|
||||
"expect_hoehe": "1554",
|
||||
"expect_kreiselart": "STANDARD",
|
||||
@@ -22,7 +23,7 @@
|
||||
"abstand": 20015,
|
||||
"rotation": 90.0,
|
||||
"typ": "STANDARD",
|
||||
"drehrichtung": "GUZ",
|
||||
"drehrichtung": "UZS",
|
||||
"expect_block_prefix": "KREISEL_",
|
||||
"expect_hoehe": "1554",
|
||||
"expect_kreiselart": "STANDARD",
|
||||
|
||||
Reference in new issue
Block a user