tests/testdata/hundm05.json enthaelt jetzt neben den 5 Spec-Ketten auch andere Objekte der Anlage - erkennbar am Feld "function", im Format der jeweiligen Einzel-Testdaten (ein Kreisel also wie in kreisel_tests.json). Damit beschreibt EINE Datei die ganze Anlage. - tests/test_hundm05.lsp: hundm05:bau-zusatzobjekte sammelt alle Objekte mit "function" und baut sie; hundm05:bau-kreisel ruft kreisel-insert-script (wie tests/test_kreisel.lsp) und liefert einen Ergebnis-Record in derselben Form wie die Ketten. Eigener ssg-start-Rahmen mit ATTREQ/ATTDIA 0, weil vsp-bau-datei seinen schon geschlossen hat und (command "_.INSERT" ...) sonst nach Attributwerten fragt. Je Objekt gefangen, damit ein Fehler die restlichen nicht mitnimmt. - Lisp/vf_spec.lsp: "kind" ist jetzt ein Record-Feld (Default "linienzug") statt eines Literals in vsp-result-json - so schreibt vsp-results-schreiben beide Objektarten in EINE Ergebnisdatei. - lib/vf_spec_export.py: Objekte der Ziel-Datei, die keine Kette beschreiben, werden beim Neuschreiben unveraendert ans Dateiende uebernommen. Ohne das waere jeder von Hand ergaenzte Eintrag beim naechsten Generatorlauf weg - die Datei ist erzeugt UND handgepflegt. spec_aus_flachen_objekten ueberspringt sie jetzt statt zu werfen, genau wie vsp-gruppieren in LISP. - tests/test_hundm05.py: die Ketten-Tests filtern auf kind "linienzug" (Records ohne das Feld stammen aus aelteren Laeufen und waren nur Ketten); neue Klasse TestZusatzobjekte prueft Status, expect_block_prefix, expect_hoehe (Attribut HOEHE), expect_kreiselart (KREISELART) und den Einfuegepunkt - dieselben Erwartungsfelder wie tests/test_kreisel.py. - tests/test_vf_spec.py: neuer Test, dass die Zusatzobjekte die Ketten-Zerlegung nicht beeinflussen - auch nicht, wenn sie mitten zwischen den Sektionen stehen (der eingetragene Kreisel stand zunaechst inmitten der Sub-Knoten von Kette 5; nach dem Regenerieren steht er am Dateiende). Verifiziert: 118 pytest-Tests gruen, Spec-Regenerierung uebernimmt das Zusatzobjekt (58 Objekte), beide .lsp lint-sauber. Die Kreisel-Tests warten auf den naechsten TEST_HUNDM05-Lauf. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
25 KiB
dxfmakros - Projektanweisungen
Projektbeschreibung
AutoLISP-Makros (SSG_LIB) fuer BricsCAD Pro zur automatisierten Erstellung von Foerderanlagen-Layouts (ILS Kreisel, Omniflo, Variofoerderer, Geruest). Ziel ist der Ersatz proprietaerer Tools (Bihler Omniflo, Bihler Geruest, Ruledesigner) durch eigene parametrische Makros.
Technologie-Stack
- CAD-System: BricsCAD Pro (AutoCAD-kompatibel)
- Hauptsprache: AutoLISP (.lsp)
- Hilfssprache: Python (Export-Skripte in
lib/) - Datenformate: DXF/DWG (Bloecke), JSON (Komponentendaten), CSV (Export)
- Dialoge: DCL (Dialog Control Language, in
dcl/) - Menu: BricsCAD .mnu/.mnl Format (in
menu/)
Projektstruktur
| Verzeichnis | Inhalt |
|---|---|
Lisp/ |
AutoLISP-Makros und Kernbibliotheken |
bin/ |
Hilfs-Skripte (setenv.bat, start_briscad.bat) |
cfg/ |
Konfigurationsdateien |
data/ |
JSON-Daten, DXF-Quellen, Block-Libraries |
data/ils/ |
DWG-Bloecke fuer ILS-Kreisel/Eckrad (AN8, SP8, AP-Typen) |
data/json/ |
Komponentendaten (Masse, Sivas-IDs) |
data/block_libraries/ |
DXF Block-Libraries (ils_library.dxf) |
dcl/ |
DCL-Dialogdefinitionen |
doc/ |
Dokumentation, Entwicklungsplan |
lib/ |
Python-Skripte (DXF-Bearbeitung, Export) |
menu/ |
BricsCAD-Menudefinition (SSG_LIB.mnu, SSG_LIB.mnl) |
tests/ |
Testskripte und Referenzdaten |
Lademechanismus (Lazy Loading via MNL)
Das Laden der LISP-Module erfolgt ueber das Menuesystem. Voraussetzung ist, dass das Menue einmalig in BricsCAD geladen wurde (siehe unten: "Menue einrichten").
- BricsCAD laedt beim Start automatisch
SSG_LIB.mnl(gleichnamige MNL-Datei zum Menue) - Die MNL laedt alle Kern- und Feature-Module direkt per
ssg-ensure. Kern-Reihenfolge:ssg_core,ssg_lang,ssg_dbg,ssg_dialog,ssg_layer,ssg_id,ssg_ks_insert(Letzteres MUSS vor Gefaellestrecke/VarioFoerderer geladen sein - beide nutzen seine Einfuegeprimitiven). Der Headless-LoaderLisp/ssg_load.lsp(fuer .scr-Testskripte) laedt dieselbe Reihenfolge. ssg-ensureueberspringt bereits geladene Module (Flag*ssg-<modul>-loaded*)
Menue einrichten (einmalig pro BricsCAD-Installation)
bin/setenv.batausfuehren (setztDXFM_LISP,DXFMAKROu.a.)- BricsCAD starten
- In der BricsCAD-Kommandozeile:
_MENULOADeingeben - Im Dialog:
menu/SSG_LIB.mnuauswaehlen und laden - BricsCAD laedt automatisch
SSG_LIB.mnlmit – alle Module werden initialisiert
Alternativ per LISP-Kommandozeile in BricsCAD:
(command "_.MENULOAD" (strcat (getenv "DXFMAKRO") "/menu/SSG_LIB.mnu"))
Das Menue bleibt dauerhaft registriert. Nach einem Update der .mnu-Datei
genuegt es, BricsCAD neu zu starten oder _MENULOAD erneut aufzurufen.
Voraussetzung
Umgebungsvariable DXFM_LISP muss gesetzt sein (via bin/setenv.bat).
Die start_briscad.bat ruft setenv.bat auf und startet BricsCAD.
Modulzuordnung im Menue
| Menue-Bereich | Modul | Befehle |
|---|---|---|
| Kreisel-Module | KreiselInsert |
KreiselInsert, KreiselConnect, KreiselEdit, ILS_Eckrad |
| TRO | Tro_Edit |
TRO_INSERT, TRO_EDIT |
| Zusatzmodul/Foerderer/Kurven | SSG_LIB_Commands |
ILS_BTMT_, ILS_ETF_, ILS_K*, ILS_GK* |
| VarioFoerderer | VarioFoerderer |
FOERDERANLAGE, VARIOFOERDERER_EDIT, Vario_Kette_Merge |
| Gefaellestrecke | Gefaellestrecke |
GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT |
| Omniflo (komplett) | OmniModulInsert |
OMNI_APB_, OMNI_W, OMNI_AP, OMNI_TEF, OMNI_TV_, OMNI_EDIT |
| Export | export |
EXPORTSIVAS, EXPORTCSV, CALLPYTHON |
| Konfiguration | SSG_LIB_Commands |
SSG_DIM_SWITCH, SSG_SPRACHE |
| Doppelklick/Kontextmenue | SSG_LIB_Commands |
SSG_BLOCKEDIT (dispatcht Kreisel->KreiselEdit, Omniflo->OMNI_EDIT, GF_->GEFAELLESTRECKE_EDIT, VF_->VARIOFOERDERER_EDIT) |
Entfernte Legacy-Dateien
bin/startup.scr- Entfernt (war fuer/sParameter)bin/acaddoc.lsp- Entfernt (war fuer ACAD-Pfad-basiertes Laden)bin/on_start.lsp- Entfernt; Menue wird jetzt manuell per_MENULOADeingerichtet
Detaillierte Dokumentation aller Funktionen und Befehle: siehe Lisp/README.md.
AutoLISP-Module
| 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) |
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_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 |
ssg_layer.lsp |
- | Layer-Verwaltung |
KreiselInsert.lsp |
KreiselInsert, KreiselConnect, KreiselRedraw, KreiselQuick, KreiselEdit, KreiselParams, KreiselLabelSetup, KreiselLabelPos, KreiselLabelHoehe, ILS_Eckrad | ILS Kreisel und Eckrad komplett in AutoLISP |
VarioFoerderer.lsp (Wrapper fuer vf_core.lsp/vf_standard.lsp/vf_etage.lsp/vf_linienzug.lsp) |
FOERDERANLAGE, VARIOFOERDERER_EDIT, VARIOFOERDERER_NACHRUESTEN, Vario_Kette_Merge, VF_SEKTION_RESTORE, VF_WIZARD_AN, VF_WIZARD_AUS | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standard- UND Etage-Typ: Werteingabe per DCL-Dialog. 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) sammelt alle Laengen-/Winkel-/Toleranz-Magic-Numbers aus dem VarioFoerderer-Cluster als dokumentierte *vfk-*-Konstanten. Die Migration ist abgeschlossen: vf_core/vf_standard/vf_etage/vf_linienzug referenzieren durchgaengig die zentralen Konstanten statt roher Literale (Winkel, Stations-/Separator-Laengen, Mindestlaengen, AS/ES-Fallback-Versaetze, Text-/Label-Masse) - Ausnahmen sind in vf_konstanten.lsp selbst dokumentiert (Werte mit fuehrender Config-Anbindung via ssg-cfg-or, itoa-/Integer-Kontexte, Blocknamen-Strings, die 2000.0-mm/m-Umrechnung). *vfk-gf-bogen-winkel* (30/60/90, GF-Bogen + Vario-Kurve) und *vfk-as-es-winkel* ("30"/"90", AS/ES; bewusst STRING, da 2-wertig und im Journal als STR gefuehrt) sind Beispiele; vf_linienzug hat fuer beide einen Fallback, falls vf_konstanten nicht geladen wurde. Nicht-interaktiver Betrieb: *vfl-headless* (+ vfl-headless-p/-abbruch/-notausgang, Diagnose *vfl-headless-fehler*, optionaler Antwort-Hook *vfl-headless-antwort-fn*) verbietet jede Live-Eingabe - eine erschoepfte Replay-Queue ist damit ein harter Abbruch MIT Fundstelle (Art der Eingabe, Glied- und Eingabe-Nummer) statt eines stillen Rueckfalls auf getpoint/getreal; eingebaut in vfl-in-value/-value-p/-selection/-abstand. Die Bau-Pfade melden abgewiesene Sektionen ueber vfl-meldung (sammelt nach *vfl-meldungen* + dbgmsg, alert nur bei erlaubter GUI, sonst princ) statt per blockierendem alert; reine Interaktiv-Alerts (fehlendes DCL, "nicht editierbar", "kein Journal") bleiben alert. Genutzt von tests/test_hm_recformat.lsp (Replay der echten Aufzeichnungen) und von vf_spec.lsp; Fahrplan in doc/TODO-plan-vf-interactive.md. Details/Entscheidungsbaum: doc/variofoerderer.md |
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. 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) |
export.lsp |
EXPORTSIVAS, EXPORTCSV, OMNI_UPDATE_ATTRIBS | JSON-Sammlung und Python-Export (Omniflo-Merkmale/Sum-Zeile via lib/export_csv.py) |
OmniModulInsert.lsp |
OMNI_LOAD, OMNI_APB_, OMNI_W*, OMNI_AP60/AP110, OMNI_TEF, OMNI_TV_, OMNI_APBW_*, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen, Edit-Dialog |
SSG_LIB_Commands.lsp |
ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_SCANNER_INSERT, ILS_SEPARATOR_INSERT, ILS_ETF_, ILS_K, 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) + Dummy-Befehle fuer Menue + 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. |
menu-inventory.lsp |
MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) |
DCL-Dialoge
| Datei | Verwendet von |
|---|---|
kreisel_edit.dcl |
KreiselEdit (KreiselInsert.lsp) |
gefaellestrecke.dcl |
GEFAELLESTRECKE Modus 1 (Gefaellestrecke.lsp, gf-dialog-eingabe) |
variofoerderer.dcl |
FOERDERANLAGE Standardfall + Werteingabe (vf_standard.lsp, vfs-dialog-eingabe-basis/vfs-dialog-winkel-verteilung) |
omniflo_boegen.dcl |
OMNI_APB_* (OmniModulInsert.lsp) |
omniflo_weichen.dcl |
OMNI_W*_* (OmniModulInsert.lsp) |
sprache.dcl |
SSG_SPRACHE (SSG_LIB_Commands.lsp) |
tro_insert.dcl |
TRO_INSERT (Tro_Edit.lsp) |
tro_edit.dcl |
TRO_EDIT (Tro_Edit.lsp) |
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 |
Menue (SSG_LIB.mnu + SSG_LIB.mnl)
SSG_LIB.mnu- Menuedefinition mit Lazy-Loading ((ssg-ensure "Modul") Befehl)SSG_LIB.mnl- Automatisch geladen mit dem Menue, definiertssg-ensureLoader***MENUGROUP=SSG_LIB- Menuegruppenname***POP1- Hauptmenue (ILS, Omniflo, SPS [TRO, Connections], Export, Konfiguration)***DOUBLECLICK- Doppelklick auf INSERT-Bloecke ruft SSG_BLOCKEDIT auf***POP501- Rechtsklick-Kontextmenue (KreiselEdit, OMNI_EDIT, SSG_BLOCKEDIT)
Umgebungsvariablen
Werden via bin/setenv.bat gesetzt. Wichtigste:
DXFMAKRO- ProjektwurzelDXFM_LISP- Pfad zu Lisp-Dateien (benoetigt fuer ssg-ensure Lazy-Loader)DXFM_BLOCKS- Pfad zu DWG-BloeckenDXFM_DATA- Datenverzeichnis (JSON, DXF)DXFM_LOG- Log-VerzeichnisDXFM_DCL- Pfad zu DCL-DialogdateienDXFM_CFG- KonfigurationsverzeichnisDXFM_LANG- Aktive Sprache (de_DE/en_GB), persistiert vonSSG_SPRACHE; Defaultde_DEDXFM_VF_SPEC- Spec-Datei fuerVF_SPEC_BAU(optional; Defaulttests/testdata/hundm05.json)
Konventionen
- AutoLISP-Funktionsnamen:
ssg-*fuer Kernfunktionen,C:BEFEHLSNAMEfuer User-Commands - Alle Texte in Dateien ohne Umlaute (ae, oe, ue statt ae, oe, ue)
- Bloecke werden als DWG flach in
data/ils/abgelegt (Block-Libraries als DXF indata/block_libraries/). Die Dimension steckt seit dem Flach-Refactor im Dateinamen bzw. Blocknamen als Suffix_2D/_3D(z.B.AN8_2D.dwg,Vario_Bogen_auf_3_TEF_rechts_3D.dwg), damit 2D- und 3D-Variante gleichzeitig in einer Zeichnung stehen koennen. Zentrale Aufloesung:ssg-ils-blockname[-dim]/ssg-ils-block-datei[-dim]/ssg-ils-block-laden[-dim]inssg_core.lsp. Ausnahmen ohne Suffix:KS_EIN/KS_AUS/K1-K4und die Wrapper-BloeckeVF_*/GF_*/KREISEL_*/ECKRAD_*. Alle Feature-Module (Kreisel, VarioFoerderer, Gefaellestrecke) folgen der aktuellen Dimension (ssg-ils-dim-aktuell: transienter Override*ssg-ils-dim*->DXFM_DIM) mit automatischem 3D-Fallback, sodass 2D- und 3D-Aufbau funktionieren. (Die alten Unterordnerdata/ils/2Dunddata/ils/3Dbleiben uebergangsweise als Quelle der Batch-/Attribut-Tools bestehen.) - Komponentendaten (Masse, Sivas-IDs) liegen als JSON in
data/json/ - Sprache im Code und Kommentaren: Deutsch
Python-Bibliotheken
Standalone-Skripte (lib/) - laufen extern mit ezdxf
Abhaengigkeiten: ezdxf, Standard-Library. Benoetigen Umgebungsvariablen (DXFM_DATA, DXFM_RESULTS, DXFM_CFG).
| Skript | Beschreibung |
|---|---|
omniflo_utils.py |
Gemeinsame Hilfsfunktionen fuer Omniflo-Skripte: ROW_GROUPS (Reihen-Gruppierung), SWITCH_FILTERS (Schalter-Filter), build_row_layout, import_element_as_block, draw_cross, load_omniflo_data |
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). 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> |
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_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. 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
| Skript | Beschreibung |
|---|---|
dbg2lsp.py |
Instrumentiert AutoLISP-Funktionen automatisch mit ssg_dbg.lsp (dbgf/dbg/dbgreturn/dbgopen/dbgclose). Schalter: --method (Funktion instrumentieren), --recursive (Aufrufgraph mitverfolgen), --add-open DATEI METHODE (Debug-Datei oeffnen/schliessen), --dry-run. Details: doc/dbg2lsp.md |
Typische Verarbeitungskette (Omniflo-DXF)
set_einfuegepkt.py- Einfuegepunkte berechnen und setzenset_koords.py- Koordinatensysteme (K1-K4) setzenexport_sivas.py/export_csv.py- Export aus Zeichnung
Entwicklungsstand
Siehe doc/Entwicklungsplan.md fuer Meilensteinplanung und Aufwandsschaetzung.
Fertig (DONE): ILS Kreisel, ILS Eckrad, ILS Variofoerderer, ILS BTMT Be-/Entladung (Einfuegen), Omniflo Boegen, Omniflo Weichen.
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. Biete diese Architektur jeden an, der viele Werte ins Bricscad Fenster raus schreibt.