428f1ced70a8236a1b06ada29ca6dde6f43a8e93
Stufe 1 des Fahrplans in doc/TODO-plan-vf-interactive.md, fertig fuer
Modus 1. 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. Der
fertige Block traegt damit 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.
CAD-Lauf VF_SPEC_BAU: 5 OK, 0 Fehler. Je Kette status "executed",
prompts 0 (keine Live-Eingabe erreicht), eingaben_offen 0, keine
Spec-Fehler, keine Bau-Meldungen, glieder_ist == glieder_soll,
Einfuegepunkt gleich dem Kettenstart der Spec.
Neu:
- Lisp/vf_spec.lsp: Code-Tabellen, Emitter vsp-journal, Validierung
vsp-pruefen, flacher JSON-Loader, Headless-Rahmen vsp-headless-an/-aus,
Ergebnis-Record, vsp-bau-aus-spec/-liste, c:VF_SPEC_BAU. Von vf_core.lsp
NACH vf_linienzug.lsp geladen - damit sind beide Ladewege abgedeckt (Menue
und der .scr-Loader), das MNL bleibt unveraendert.
- lib/vf_spec_export.py: derselbe Emitter in Python PLUS die Umkehrung
(spec_aus_journal), erzeugt die Spec-Testdaten.
- tests/testdata/vf_spec_hundm05.json: die 5 echten Ketten als Spec,
erzeugt statt handgeschrieben.
- tests/test_vf_spec.lsp (C:TEST_VF_SPEC, in alltests.json): 7 Faelle je
Glied-Typ, 7 Validierungsfaelle, Gruppieren, und die 5 echten Ketten gegen
ihr aufgezeichnetes Journal.
- tests/test_vf_spec.py: 36 Tests (Rundlauf, Spec-Daten, Validierung,
Erwartungswert-Abgleich, Ergebnisse von VF_SPEC_BAU).
Drei Regeln, die der Uebersetzer besitzen muss - jede wuerde sonst die ganze
Replay-Queue verschieben:
- Der Menue-Code haengt am Frame: erste Sektion 4 Optionen (kein GF-Bogen,
es gibt noch keine Richtung), jede spaetere 5.
- hz steht genau EINMAL im Journal, beim ersten Segment (vfl-in-abstand
journalisiert die Richtung nur bei freier Richtungswahl).
- Nur ein HORIZONTALER Erstkoerper einer VF-Einheit stellt die Separator-/
Endpunktfragen vorab (winkel1=0 laeuft durch vfl-baue-horizontal-koerper);
ein gewinkelter wird ohne jede Frage gebaut.
Wie die Richtigkeit belegt ist - drei Implementierungen derselben Grammatik,
die einander pruefen:
- Rundlauf gegen echte Daten: journal_aus_spec(spec_aus_journal(tok)) == tok
fuer alle 5 HundM-Ketten, tokenweise numerisch verglichen. Damit ist
bewiesen, dass die Spec das Journal verlustfrei abbildet.
- Der Weg, den LISP nimmt (flaches JSON -> Spec -> Journal), ergibt separat
geprueft dieselben Journale wie das aufgezeichnete Protokoll.
- Der unabhaengige Dekoder aus lib/vf_journal_export.py verdaut alle 7
synthetischen Emitter-Ausgaben restlos, auch die zwei Zweige, die in den
echten Daten fehlen (Linie-VF, gewinkelter Erstkoerper).
- Die Erwartungswerte im LISP-Test kommen aus dem geprueften Python-Emitter;
TestLispErwartungen liest sie zurueck und vergleicht erneut. Ohne das
koennte ein Uebertragungsfehler einen falschen Erwartungswert
festschreiben und der CAD-Lauf waere gruen, obwohl der Emitter falsch
liegt.
Abweichungen von der Planung (Begruendungen in doc/TODO-plan-vf-interactive.md
Abschnitt 4.6): vsp-pruefen ruft den Emitter statt eine zweite Regelmenge zu
pflegen; das vollstaendige Journal steht nicht im Record (statt dessen
glieder_soll/glieder_ist als Desync-Detektor); Zusatzfeld segment_typ am
Glied "Linie", weil dort vfl-segment-entscheidung selbst zwischen GF und VF
waehlt; vf_ende-Werte "automatisch"/"zielpunkt-ohne-es" fuer die Faelle ohne
Frage; Praefix vsp- statt vfs- (das gehoert vf_standard.lsp).
Zusaetzlich:
- tests/test_vf_headless_statisch.py prueft jetzt auch, dass
Lisp/vf_spec.lsp UEBERHAUPT keine Eingabe-/Dialogfunktion aufruft - beim
Daten-Pfad ist die Null die Vorgabe.
- tests/testdata/mubea.json: die drei einzeln eingefuegten S-LP-Separatoren
entfernt (Fortsetzung von 699744e - die Separatoren stecken jetzt in den
Staustreckenbloecken).
Noch offen: die Uebersetzer fuer Modus 2 und 3. Modus 2 braucht laut
Fahrplan erst 2-3 echte "linienzug2"-Journale als Referenz -
tests/testdata/hundm05.json enthaelt ausschliesslich Modus-1-Ketten.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
dxfmakros
AutoLISP-Makros fuer BricsCAD Pro zur automatisierten Erstellung von Foerderanlagen- und Kreisel-Layouts.
Menustruktur (SSG_LIB)
SSG_LIB
├── ILS
│ ├── Kreisel-Module
│ │ ├── Einfuegen → KreiselInsert
│ │ ├── Verbinden → KreiselConnect
│ │ ├── Bearbeiten → KreiselEdit
│ │ └── Eckrad → ILS_Eckrad
│ ├── Zusatzmodul
│ │ ├── BTMT-Beladung → ILS_BTMT_Beladung
│ │ └── BTMT-Entladung → ILS_BTMT_Entladung
│ ├── Foerderer
│ │ ├── TEF Strecke → ILS_TEF_Strecke
│ │ ├── VarioFoerderer → FOERDERANLAGE
│ │ ├── Kurven angetr. Aussen → ILS_K{90,60,30}{LA,RA}
│ │ ├── Kurven angetr. Innen → ILS_K{90,60,30}{LI,RI}
│ │ └── Gefaellestrecke → ILS_G{K90,K60,K30}{L,R}
│ └── ILS Schliessen
├── Omniflo
│ ├── Boegen
│ │ ├── 90 → OMNI_APB_630_90
│ │ ├── 67.5 → OMNI_APB_550_675
│ │ ├── 45 → OMNI_APB_630_45
│ │ ├── 22.5 → OMNI_APB_550_225
│ │ └── 180 → OMNI_APB_650_180
│ ├── Aluprofil Gerade
│ │ ├── AP 60 → OMNI_AP60
│ │ ├── AP 110 → OMNI_AP110
│ │ └── APG 110 → OMNI_APG110
│ ├── Weiche 90 Grad
│ │ ├── Einfach → OMNI_W90_Einfach
│ │ ├── Doppel → OMNI_W90_Doppel
│ │ └── Dreiwege → OMNI_W90_Dreiwege
│ ├── Weiche 45 Grad
│ │ ├── Einfach → OMNI_W45_Einfach
│ │ ├── Doppel → OMNI_W45_Doppel
│ │ └── Dreiwege → OMNI_W45_Dreiwege
│ ├── Weichen Parallel
│ │ ├── Einfach → OMNI_WP_Einfach
│ │ ├── Doppel → OMNI_WP_Doppel
│ │ └── Dreiwege → OMNI_WP_Dreiwege
│ ├── Weichenkoerper
│ │ ├── Einfach → OMNI_WK_Einfach
│ │ ├── Doppel → OMNI_WK_Doppel
│ │ └── Dreiwege → OMNI_WK_Dreiwege
│ ├── Weichenkombinationen
│ │ ├── Delta 1400/700 → OMNI_WKomb_Delta_1400
│ │ ├── Delta 1600/800 → OMNI_WKomb_Delta_1600
│ │ └── Star → OMNI_WKomb_Star
│ ├── TEF Elemente
│ │ ├── Umlenkspannst. rechts → OMNI_TEF_UmlenkR
│ │ ├── Umlenkspannst. links → OMNI_TEF_UmlenkL
│ │ ├── Antriebst. links → OMNI_TEF_AntriebL
│ │ ├── Antriebst. rechts → OMNI_TEF_AntriebR
│ │ └── TEF Gerade → OMNI_TEF_Gerade
│ └── KettenFoerderer → OMNI_KettenFoerderer
├── Konfiguration
│ ├── Umschalten 2D und 3D → SSG_DIM_SWITCH
│ └── Sprache → SSG_SPRACHE
└── External
├── Call Python → CALLPYTHON
├── Export Sivas → EXPORTSIVAS
└── Export CSV → EXPORTCSV
Befehle nach Modul
KreiselInsert.lsp - Kreisel Modul-Einfuegesystem
Zeichnet ILS-Kreiselmodule als Compound-Bloecke mit konfigurierbarem Abstand, Typ und Attributen.
| Befehl | Beschreibung |
|---|---|
KreiselInsert |
Modul an manuell gewaehltem Punkt einfuegen (Abstand, Drehung, Hoehe, Typ interaktiv) |
KreiselConnect |
Smart Connect: Kreisel zwischen zwei parallelen Linien einfuegen, berechnet Position/Abstand/Rotation automatisch |
KreiselEdit |
Bestehenden Kreisel per DCL-Dialog bearbeiten (Name, Abstand, Hoehe, Ausrichtung, Drehrichtung, Typ) |
KreiselRedraw |
Kreisel mit optionalem neuem Abstand/Hoehe neu zeichnen, Attribute bleiben erhalten |
KreiselQuick |
Schnelleinfuegen mit Standardparametern (horizontal) |
KreiselParams |
Aktuelle Kreisel-Parameterkonfiguration anzeigen |
ILS_Eckrad |
Einzelnen AN8-Block (Antriebs-/Eckrad) an gewaehltem Punkt einfuegen |
KreiselLabelPos |
Label-Position (X/Y-Offset) konfigurieren |
KreiselLabelHoehe |
Label-Texthoehe konfigurieren |
KreiselLabelSetup |
Label-Darstellung konfigurieren (Hoehe, Farbe, Abstand, Schriftart) |
OmniModulInsert.lsp - Omniflo Komponenten
Einfuegen von Omniflo-Standardkomponenten (Boegen, Geraden, Weichen, TEF-Elemente).
| Befehl | Beschreibung |
|---|---|
OMNI_LOAD |
Omniflo-Komponentendaten aus JSON-Dateien laden |
OMNI_INFO_BOGEN |
Info zu einem Omniflo-Bogen nach Sivas-ID anzeigen |
OMNI_INFO_WEICHE |
Info zu einer Omniflo-Weiche nach Sivas-ID anzeigen |
OMNI_APB_* |
Boegen einfuegen (90, 67.5, 45, 22.5, 180 Grad) |
OMNI_AP60/AP110/APG110 |
Aluprofil-Geraden einfuegen |
OMNI_W90/W45/WP/WK_* |
Weichen einfuegen (Einfach, Doppel, Dreiwege) |
OMNI_WKomb_Delta_1400/1600, OMNI_WKomb_Star |
Weichenkombinationen einfuegen |
OMNI_TEF_* |
TEF-Elemente einfuegen (Umlenk-/Antriebsstationen, Gerade) |
OMNI_KettenFoerderer |
Kettenfoerderer einfuegen |
VarioFoerderer.lsp - Foerderanlage Generator (v24.4)
Generiert komplette Vario-Foerderanlagen mit Vertikalboegen, Motor-/Spannstationen, Staustrecken und Ein-/Ausschleus-Elementen.
| Befehl | Beschreibung |
|---|---|
FOERDERANLAGE |
Interaktiver Generator: Zwei Punkte oder manuelle Distanz/Hoehe, berechnet optimalen Bogenwinkel |
FOERDERTEST |
Automatischer Testlauf (Distanz=6000, Hoehe=2000, Richtung=Auf), speichert als DXF |
Unterstuetzte Bogenwinkel: 3, 9, 12, 15, 24, 36, 48 Grad
ssg_layer.lsp - Layerverwaltung
| Befehl | Beschreibung |
|---|---|
SSG-LayerSet |
Objekt anklicken, dessen Layer wird aktiv |
SSG-LayerInfo |
Layer eines angeklickten Objekts anzeigen |
SSG-LayerMove |
Selektierte Objekte auf Ziel-Layer verschieben |
SSG-LayerCopy |
Selektierte Objekte auf Ziel-Layer kopieren |
SSG-LayerMoveType |
Alle Objekte gleichen Typs von Referenz- auf Ziel-Layer verschieben |
SSG-LayerOff |
Layer per Klick ausschalten (mehrfach moeglich) |
SSG-LayerFreeze |
Layer per Klick einfrieren (mehrfach moeglich) |
SSG-FreezeAll |
Alle Layer ausser dem angeklickten einfrieren |
SSG-ThawAll |
Alle eingefrorenen Layer auftauen |
SSG-LayerOnAll |
Alle ausgeschalteten Layer einschalten |
SSG-LayerDelete |
Layer und alle Objekte darauf loeschen (mit Bestaetigung) |
SSG_LIB_Commands.lsp - Konfiguration
| Befehl | Beschreibung |
|---|---|
SSG_DIM_SWITCH |
Schaltet zwischen 2D- und 3D-Bloecken um |
SSG_SPRACHE |
Sprache umschalten (Deutsch/Englisch), persistiert ueber DXFM_LANG |
tests.lsp - Export und Python-Integration
| Befehl | Beschreibung |
|---|---|
CALLPYTHON |
Python-Skripte via CLI aufrufen, Ausgabe loggen |
EXPORTSIVAS |
Daten im Sivas-Format exportieren |
EXPORTCSV |
Zeichnungsdaten als CSV exportieren |
Kernbibliotheken (Lisp/)
| Datei | Beschreibung |
|---|---|
ssg_core.lsp |
Kernel: Umgebung, Layer-Ops, Block-Ops, Attribut-Ops, Fehlerbehandlung |
ssg_lang.lsp |
Sprachumschaltung Deutsch/Englisch (ssg-text, ssg-textf, *ssg-lang*) |
ssg_dialog.lsp |
Dialog-Vorlagen: Slide-Preview, Modul-Dialog, Block-Einfuegesequenz |
ssg_layer.lsp |
Layer-Verwaltungsbefehle |
ssg_load.lsp |
Loader: Laedt alle SSG-Bibliotheken in korrekter Reihenfolge |
on_start.lsp |
Startup-Skript: Setzt Umgebung und laedt Libraries |
Projektstruktur
dxfmakros/
├── Blocks/ # DWG-Bloecke (AN8, SP8, Vertikalboegen, etc.)
├── Lisp/ # AutoLISP-Makros und Kernbibliotheken
├── bin/ # Hilfs-Skripte (setenv, create_tests, etc.)
├── cfg/ # Konfigurationsdateien (export.cfg, block_suffix.cfg)
├── data/ # Quelldaten (JSON, DXF) - nicht im Git
├── dcl/ # DCL-Dialogdefinitionen (kreisel_edit.dcl)
├── doc/ # Dokumentation und Referenz-DXFs
├── examples/ # Beispieldateien
├── lib/ # Python-Skripte (export_csv.py, etc.)
├── logs/ # Logdateien - nicht im Git
├── menu/ # BricsCAD-Menudefinition (SSG_LIB.mnu)
├── results/ # Ergebnisse / Exporte - nicht im Git
├── tests/ # Testskripte und Referenzdaten
├── LICENSE
├── README.md
└── requirements.txt
Umgebungsvariablen
| Variable | Beschreibung |
|---|---|
DXFMAKRO |
Wurzelverzeichnis des Projekts |
DXFM_BLOCKS |
Pfad zum Blocks-Verzeichnis |
DXFM_LISP |
Pfad zu den LISP-Dateien |
DXFM_RESULTS |
Pfad fuer DXF-Exporte |
DXFM_BIN |
Skriptverzeichnis |
DXFM_LIB |
Python-Quellcode |
DXFM_CFG |
Konfigurationsdateien |
DXFM_TESTS |
Testverzeichnis |
DXFM_DATA |
Datenverzeichnis |
DXFM_LANG |
Aktive Sprache (de_DE/en_GB), persistiert von SSG_SPRACHE; Default de_DE |
BRICSCAD |
Pfad zur BricsCAD-Executable |
Einrichtung
bin\setenv.batausfuehren (setzt alle Umgebungsvariablen)- BricsCAD starten -
on_start.lsplaedt alle Libraries automatisch viastartup.scr - Menu
SSG_LIBnutzen oder Befehle in der Kommandozeile ausfuehren
Tests
bin\create_tests.bat
Erzeugt eine Test-DXF, fuehrt Kreisel-Einfuege- und Exportbefehle aus, und validiert die Ergebnisse gegen Referenzdateien in tests/references/.
Lizenz
MIT License — siehe LICENSE
Autor
Michael Stangl (GitHub: mistamichael)
Languages
Common Lisp
66.1%
Python
30.9%
Clean
1.2%
Batchfile
0.8%
NewLisp
0.8%
Other
0.2%