Files
dxfmakros/Lisp
s.ayadi 45044cdcba Add TRO marker editing to SSG_LIB
The TRO markers written by sps_skel (lib/tro_annotate.py) are blocks
TRO_SYM_<type> carrying ID and TYPE as attributes. This wires them into the
existing SSG_LIB mechanisms rather than adding new ones.

The double-click hook and the EATTEDIT override already exist: ***DOUBLECLICK
routes [INSERT] to SSG_BLOCKEDIT, and c:EATTEDIT is undefined and forwarded to
the same dispatcher. So all that was missing was a branch:

  Blockname TRO_*  ->  c:TRO_EDIT (Lisp/Tro_Edit.lsp)  ->  dcl/tro_edit.dcl

Tro_Edit.lsp follows the conventions of the other edit commands: DCL path from
DXFM_DCL, ssg-start/ssg-end around the command, ssg-attrib-read and
ssg-attrib-set-on for the attributes, all user-visible text via ssg-text/
ssg-textf with keys in lang/de_DE.json and en_GB.json. Implied selection is read
before ssg-start, since ssg-start clears it - the same note Gefaellestrecke.lsp
carries.

TYPE is a picklist rather than free text so it cannot drift from the type
catalogue. The list comes from Lisp/tro_types.lsp, generated on the sps_skel side
by "tro_annotate.py --emit-lisp" into DXFM_LISP. If that file is absent the
dialog offers the block's current type and still works.

Loading is lazy: the module is not preloaded in the MNL. The menu macros and the
dispatcher pull it with (ssg-ensure "Tro_Edit") on first use, and the dispatcher
falls back to native EATTEDIT if the module cannot be found. ssg_load.lsp loads
it for the non-menu path.

Menu: SSG_LIB > TRO with "Marker bearbeiten" and "Bearbeiten (Auto)", plus an
entry in the POP501 edit context menu.

The dialog changes attributes only. The marker shape belongs to the block
definition of the type and FB_BLOCK is derived from it, so both follow on the next
tro_annotate.py run; the dialog states this and the command prints a reminder when
the type was changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 15:41:06 +02:00
..
2026-08-03 15:41:06 +02:00
2026-08-03 15:41:06 +02:00

Lisp AutoLISP-Bibliotheken (SSG_LIB)

AutoLISP-Routinen für BricsCAD Pro zur automatisierten Erstellung von Förderanlagen-Layouts. Destilliert aus den historischen ACADSST-Makros (Schönenberger Systeme GmbH) und erweitert für die SSG_LIB-Befehle.


Menue einrichten und Module laden

Module werden automatisch ueber SSG_LIB.mnl geladen, sobald das Menue einmalig in BricsCAD registriert wurde:

Einmalige Einrichtung (BricsCAD-Kommandozeile):

_MENULOAD   →  menu/SSG_LIB.mnu auswaehlen

BricsCAD laedt daraufhin automatisch SSG_LIB.mnl, welches alle Module per ssg-ensure initialisiert (Kern: ssg_core/lang/dbg/dialog/layer, dann alle Feature-Module). Details: siehe ../CLAUDE.md Abschnitt "Lademechanismus".

Manuell laden (Notfall / Entwicklung):

(load "C:/10-Develop/gitrepos/dxfmakros/Lisp/ssg_load.lsp")

ssg_load.lsp laedt alle Module in der richtigen Reihenfolge ohne Menueabhaengigkeit.


Status: noch offene Menueintraege (im Menue ausgegraut)

Die folgenden Menueintraege rufen aktuell nur eine Dummy-Funktion auf (Meldung [DUMMY], keine Geometrie). Sie sind in menu/SSG_LIB.mnu mit ~ ausgegraut und werden erst bei echter Implementierung wieder aktiviert. Der ~-Marker steht am Label-Anfang, bei Submenue-Schliessern hinter dem <- ([<-~Label]).

Menuebereich Eintraege Definiert in
ILS ▸ Zusatzmodul BTMT-Beladung, BTMT-Entladung SSG_LIB_Commands.lsp
ILS ▸ Foerderer Durch TEF angetriebene Strecke; Kurven 90/60/30 links/rechts angetrieben Aussen + Innen (12) SSG_LIB_Commands.lsp
ILS ▸ Gefaellestrecke Kurven 90/60/30 links/rechts Gefaellestrecke (6) SSG_LIB_Commands.lsp
Omniflo ▸ TEF Elemente UmlenkR/L, AntriebL/R, TEF Gerade, KettenFoerderer (6) OmniModulInsert.lsp
Omniflo ▸ Verbinder alle OMNI_TV_* (18) OmniModulInsert.lsp
Omniflo ▸ Boegen fuer Weichen alle OMNI_APBW_* (14) OmniModulInsert.lsp

Aktiv (implementiert) sind u.a.: Kreisel, Eckrad, VarioFoerderer, EtageVarioFoerderer, Gefaellestrecke, Omniflo Boegen (APB), Aluprofil-Geraden (AP), alle Weichen (W90/W45/WP/WK/WKomb), Export (Sivas/CSV) und die Tests.


Dateien

ssg_core.lsp Kernbibliothek

Grundfunktionen für Umgebungssicherung, Benutzerinteraktion, Layer, Blöcke, Attribute und JSON-Konfiguration. Muss als erstes geladen werden.

Umgebungssicherung:

Funktion Beschreibung
ssg-start titel vars Systemvariablen sichern, CMDECHO aus, Undo-Gruppe öffnen
ssg-end Systemvariablen wiederherstellen, Undo-Gruppe schließen
ssg-errhan em Fehlerhandler räumt auf und ruft ssg-end auf

Benutzer-Abfragen:

Funktion Beschreibung
ssg-ques text defa Ja/Nein-Abfrage; defa=T → Default Ja, nil → Default Nein
ssg-emsg text Fehlermeldung mit optionalem Signalton (ssg-bell)

Layer-Hilfsfunktionen:

Funktion Beschreibung
ssg-get-layer text Layer eines angeklickten Objektes ermitteln
ssg-layer-ss name typ Auswahlsatz aller Objekte eines Layers (optional nach Typ filtern)
ssg-make-layer name farbe aktiv Layer anlegen (falls nicht vorhanden) und optional aktivieren
ssg-ss-foreach ss func Iteration über Auswahlsatz func für jeden Entity-Name
ssg-ss-redraw ss modus Auswahlsatz hervorheben (3), invertieren (4) oder normal (0)
ssg-ss-add src dest Auswahlsatz src zu dest hinzufügen (in-place, mit Highlight)

Block-Operationen:

Funktion Beschreibung
ssg-timestamp Zeitstempel als YYYYMMDDHHMMSS-String erzeugen
ssg-make-blockname pt Eindeutigen Blocknamen aus Einfügepunkt + Zeitstempel erzeugen
ssg-insert-block layer farbe pfad pt xs ys rot Layer anlegen und Block einfügen
ssg-make-block pt rotation ss Auswahlsatz als Block definieren und gleich einfügen

ILS-Blockdateien laden (2D/3D):

Funktion Beschreibung
ssg-ils-dim-aktuell Gültige Dimension: *ssg-ils-dim*DXFM_DIM"3D"
ssg-ils-blockname[-dim] roh [dim] Effektiver Blockname mit Suffix _2D/_3D
ssg-ils-block-datei[-dim] roh [dim] Pfad zu data/ils/<blockname>.dwg (3D-Fallback)
ssg-ils-block-laden[-dim] roh [dim] Blockdefinition sicherstellen; Rückgabe = effektiver Name
ssg-block-refresh-reset roh Redefine-Sperre lösen (nil = alle Blöcke) → DWG wird neu gelesen

Jede Block-DWG wird einmal pro Zeichnung aus der Datei neu definiert (Redefine); danach greift eine Sperre (*ssg-block-refreshed*, siehe ssg-block-refreshed-p/ -set). Ohne sie las jede einzelne Element-Einfügung die DWG erneut von der Platte und regenerierte alle bereits platzierten Referenzen bei den großen 3D-Blöcken (AS_Element_90_links_3D ~52 MB) waren Tests wie TEST_MUBEA dadurch minutenlang beschäftigt. Wurde eine Block-DWG während der laufenden Sitzung geändert, hebt ssg-block-refresh-reset die Sperre auf.

Attribut-Operationen:

Funktion Beschreibung
ssg-attrib-set tag wert ersetzen Ein Attribut der letzten Einfügung setzen oder anfügen
ssg-attrib-set-many alist Mehrere Attribute der letzten Einfügung auf einmal setzen
ssg-attrib-set-on ent alist Attribute eines bestimmten INSERT-Entity setzen (nicht entlast)
ssg-attrib-read ent Alle Attribute eines INSERT-Entity als Assoziationsliste lesen
ssg-attrib-read-dwg pfad Block temporär einfügen, ATTRIBs lesen, Block wieder löschen
ssg-attrib-defaults defs Default-Attribute aus Definitionsliste ((TAG DEFAULT) ...) erzeugen
ssg-attrib-merge given defs Übergebene Attribute mit Defaults zusammenführen
ssg-attrib-make-defs defs hoehe Unsichtbare ATTDEF-Entities erzeugen (für Block-Definition)
ssg-attrib-alist-to-defs alist Assoziationsliste (TAG . Wert) in ATTDEF-Definitionsliste umwandeln
ssg-attrib-by-handle handle tag wert ersetzen Attribut eines Blocks anhand seines Entity-Handles suchen und ändern

Dialog-Hilfsfunktionen:

Funktion Beschreibung
ssg-dialog-run dcl id init-fn accept-fn Generischer DCL-Dialog: laden, initialisieren, starten, entladen

Zoom-Hilfsfunktionen:

Funktion Beschreibung
ssg-zoom-save Aktuelle View-Größe merken
ssg-zoom-restore Auf gemerkte View-Größe zurückschalten (nur wenn verändert)

JSON-Konfigurationssystem:

Liest data/json/component_defaults.json beim Laden über ssg-load-config. Die Config wird in der globalen Variable *ssg-config* gehalten.

Funktion Beschreibung
ssg-load-config Config aus $DXFM_DATA/json/component_defaults.json laden
ssg-cfg section key Wert aus Config lesen, nil wenn nicht vorhanden
ssg-cfg-or section key default Wert aus Config lesen, default als Fallback

Interne Parser-Funktionen (nicht direkt aufrufen): ssg-read-file-lines, ssg-cfg-trim, ssg-cfg-split-comma, ssg-cfg-parse-value, ssg-cfg-parse-array, ssg-cfg-parse-kv, ssg-cfg-parse-nested


ssg_lang.lsp Sprachumschaltung (Deutsch/Englisch)

Zentrale Textverwaltung fuer benutzersichtbare Meldungen. Kern-Modul, wird direkt nach ssg_core geladen. Wird schrittweise auf weitere Module ausgerollt (siehe doc/translate.md).

Funktion Beschreibung
ssg-text key Liefert Text zu key in *ssg-lang*, Fallback de_DE, dann Key selbst
ssg-textf key werte Wie ssg-text, ersetzt Platzhalter %1 %2 ... durch werte (Liste)

Sprache umschalten: Befehl SSG_SPRACHE (Menue → Konfiguration → Sprache) setzt *ssg-lang* live und persistiert via (setenv "DXFM_LANG" ...). Default ohne DXFM_LANG ist "de_DE".


ssg_dbg.lsp Debug-Logging

Dateibasiertes Debug-Log mit gepuffertem Schreiben. dbgf/dbg/dbgmsg puffern im Speicher, dbgreturn flusht auf die Platte (open/append/close).

Funktion Beschreibung
dbgopen filename envvar Debug-Datei öffnen (Verzeichnis via Umgebungsvariable, z.B. "DXFM_LOG")
dbgclose Puffer schreiben und Datei schließen
dbgon Debug-Ausgabe aktivieren
dbgoff Debug-Ausgabe deaktivieren (verhindert Dateianlage wenn vor dbgopen)
dbgf funcname Funktionseintritt loggen, Einrückung erhöhen
dbgreturn retval Funktionsaustritt loggen, Puffer flushen, Rückgabewert durchreichen
dbg varname Variable oder Wert loggen: (dbg 'x) oder (dbg wert)
dbgmsg text Freitext-Nachricht loggen
dbgp text Alias für dbgmsg
dbgflush Puffer sofort schreiben (ohne dbgreturn, z.B. in Startup-Code)

Beispiel:

(dbgopen "test.dbg" "DXFM_LOG")
(dbgf "meine-funktion")
(dbg 'x)
(dbgreturn ergebnis)   ; schreibt Puffer auf Platte
(dbgclose)

ssg_dialog.lsp Dialog-Pattern für Modul-Einfüge-Makros

Kapselt das wiederkehrende DCL-Muster: Dialog mit Vorschaubild, Radio-Auswahl, Block einfügen, Attribute setzen. Setzt ssg_core.lsp voraus.

Funktion Beschreibung
ssg-dia-show-slide tile lib name Vorschau-Slide im image-Tile anzeigen (Hintergrundfarbe aus Config: infrastruktur/dialog_preview_bg_color)
ssg-dia-update-preview tile idx lib liste Vorschau anhand Index-String aus Radio-/List-Tile aktualisieren
ssg-modul-dialog dcl id sel-tile start-val prev-tile lib slides extra-init extra-read Vollständiger Modul-Dialog: lädt DCL, setzt Tiles, verknüpft Vorschau, liefert gewählten Index
ssg-insert-modul layer farbe pfad attribs rotation Standardsequenz: Layer anlegen → Punkt abfragen → Block einfügen → Attribute setzen

Die Datei enthält außerdem ein auskommentiertes Template für neue c:BEFEHL-Definitionen nach dem SSG-Muster.


ssg_layer.lsp Interaktive Layer-Verwaltung

Benutzerfreundliche BricsCAD-Befehle für Layer-Operationen. Alle Befehle sichern die Umgebung über ssg-start/ssg-end. Setzt ssg_core.lsp voraus.

Hilfsfunktionen:

Funktion Beschreibung
ssg-layer-list-all Alle Layernamen als Liste
ssg-layer-info-all Alle Layer als Assoziationslisten (Name, Farbe, Linientyp, Flags)
ssg-layer-visible-p name Sichtbarkeitsstatus prüfen (T = sichtbar)
ssg-layer-safe-p name gruppe Prüfen ob Layer ausgeschaltet werden darf (nicht aktiver Layer)
ssg-layer-group name Gruppen-Kennung aus Layernamen extrahieren (Position 23)
ssg-layer-rename-group name neu Neuen Layernamen mit geänderter Gruppen-Kennung berechnen
ssg-layer-group-move alt neu Alle Objekte einer Layergruppe auf neue Gruppen-Kennung verschieben

BricsCAD-Befehle:

Befehl Beschreibung
c:SSG-LayerSet Layer des angeklickten Objektes als aktiven Layer setzen
c:SSG-LayerInfo Layer des angeklickten Objektes anzeigen
c:SSG-LayerMove Auswahlsatz auf Layer eines anderen Objektes verschieben
c:SSG-LayerCopy Auswahlsatz kopieren und Kopie auf Ziel-Layer legen
c:SSG-LayerMoveType Alle Objekte des gleichen Typs auf dem gleichen Layer verschieben
c:SSG-LayerOff Layer durch Anklicken ausschalten (Schleife bis Enter)
c:SSG-LayerFreeze Layer durch Anklicken einfrieren (Schleife bis Enter)
c:SSG-FreezeAll Alle Layer außer einem einfrieren
c:SSG-ThawAll Alle Layer auftauen
c:SSG-LayerOnAll Alle ausgeschalteten Layer einschalten
c:SSG-LayerDelete Layer mit Sicherheitsabfrage löschen (Objekte + Layer)

ssg_load.lsp Laderoutine

Lädt alle Module in der richtigen Reihenfolge. Ermittelt den Pfad automatisch über findfile. Ruft direkt nach ssg_core.lsp die Funktion ssg-load-config auf, damit die JSON-Konfiguration für alle nachfolgenden Module verfügbar ist.


VarioFoerderer.lsp Vario-Förderer

Kompatibilitäts-Wrapper, der vf_core.lsp lädt (Plugin-Dispatcher-Architektur; lädt seinerseits vf_standard.lsp, vf_etage.lsp, vf_linienzug.lsp). Parametrischer Generator für ILS Vario-Förderanlagen. Liest Block-Geometrie aus einer DWG-Bibliothek (DXFM_BLOCKS). Alle Konstanten (Abstände, Winkel, Skalierung) werden via ssg-cfg-or aus component_defaults.json (Sektion vario) gelesen.

Befehl: c:FOERDERANLAGE / c:VarioFoerderer wählt zuerst den Anlagen-Typ (Standard/Etage/Linienzug):

  • Typ „standard“ + Werteingabe: läuft über den DCL-Dialog dcl/variofoerderer.dcl (zwei Dialoge, vfs-standard-dialog-ablauf in vf_standard.lsp): Dialog 1 (vfs-dialog-eingabe-basis) erfasst deltaL, deltaH, Förderrichtung (Auf/Ab), Einfügehöhe, Fahrtrichtung und Seite; anschließend berechnet berechne-standard die gültigen Winkel-Varianten, und Dialog 2 (vfs-dialog-winkel-verteilung) lässt Winkel und L_GF-Verteilung (vorne/hinten) wählen. Startpunkt (X/Y) wird wie bei der Gefällestrecke vorher in der Zeichnung gepickt.
  • Typ „standard“ + 3D-Linie, sowie Typ „etage“ und „linienzug“ bleiben vollständig interaktiv (Kommandozeile), unverändert gegenüber dem bisherigen Ablauf.

Bearbeiten (c:VARIOFOERDERER_EDIT): Doppelklick auf einen VF_n-Block bzw. Rechtsklick-Kontextmenü/SSG_BLOCKEDIT öffnet dieselben Dialoge, vorbelegt mit den aktuellen Parametern, und baut die Strecke bei OK am selben Startpunkt neu auf (neue VF_n-Nummer). Da VF_n-Blöcke auch von Etage- und Linienzug-Anlagen erzeugt werden (deren komplexere Geometrie ein einfacher Neuaufbau zerstören würde), markiert vfs-xdata-schreiben nur per Standard-Dialog erstellte Blöcke mit XDATA (App SSG_VF_EDIT, Fahrtrichtung hz); Blöcke ohne diese Markierung weist c:VARIOFOERDERER_EDIT mit einer Meldung ab, statt sie zu verändern. Winkel und L_GF1 werden aus den Sivas-Attributen (VF_WINKEL, L_GF_m) vorbelegt (Verteilung stets als „Eigene Werte“ mit dem exakten aktuellen L_GF1).

Wichtige interne Funktionen (werden auch von Gefaellestrecke.lsp genutzt):

Funktion Beschreibung
init-bibliothek Block-Bibliothek aus DWG laden und Geometriedaten extrahieren
ensure-block-loaded name Block aus Bibliothek in aktives Dokument laden (einmalig)
insert-block-by-ks name ks-nr pt Block anhand Koordinatensystem-Punkt einfügen
insert-inclined-scaled-block name laenge winkel pt Geneigten, skalierten Block einfügen
insert-rotated-block-with-ks name rot pt Rotierten Block mit KS-Offset einfügen
get-line-start-end-points ename Start- und Endpunkt einer LINE-Entity ermitteln
punkt-differenz p1 p2 Differenzvektor zweier Punkte

Gefaellestrecke.lsp Gefällestrecken-Generator

Erzeugt eine einfache Förderanlage mit festem Gefällewinkel: AUS-Element → Staustrecke (skaliert) → Separator → EIN-Element

Setzt VarioFoerderer.lsp voraus (nutzt dessen init-bibliothek, insert-block-by-ks und weitere Hilfsfunktionen). Alle Defaults (default_delta_l, default_winkel, separator_breite) kommen aus Config-Sektion gefaelle.

Befehl: c:GEFAELLESTRECKE

Drei Modi:

  • Modus 1: Startpunkt (X/Y) picken, restliche Parameter über den DCL-Dialog dcl/gefaellestrecke.dcl eingeben (ΔL, Einfügehöhe Z, Gefällewinkel, Fahrtrichtung, AUS-/EIN-Element je Winkel 30/90 und Seite links/rechts). Die Einfügehöhe aus dem Dialog setzt die Z-Koordinate des Startpunkts.
  • Modus 2: Bestehende 3D-Linie wählen (ΔL und Fahrtrichtung werden daraus berechnet), restliche Parameter interaktiv über die Kommandozeile.
  • Modus 3: Linienzug aus LINE-/ARC-Objekten; ARC-Segmente werden durch Gefällebogen-Blöcke ersetzt, Winkel aus ΔH und Geometrie berechnet.

Dialog-Hilfsfunktionen: gf-dialog-eingabe (lädt/liest den DCL-Dialog, liefert (deltaL winkel hz-winkel as-seite es-seite einfuegehoehe as-winkel es-winkel dim geruest-einzelmodul geruest-typ) oder nil bei Abbruch) und gf-modus12-abschluss (gemeinsamer Abschluss für Modus 1+2: setzt die Element-Masse per vf-set-as-masse/vf-set-es-masse, berechnet die Staustreckenlänge, zeigt die Zusammenfassung und ruft gefaellestrecke-einfuegen).

Die AUS-/EIN-Element-Varianten (30/90 Grad, links/rechts) liegen als DWG-Blöcke AS_Element_<30|90>_<links|rechts> bzw. ES_Element_… flach in data/ils/ (Dimension im Dateinamen als Suffix _2D/_3D, aufgelöst über ssg-ils-block-datei); ihre Maße werden direkt aus dem Block gemessen (vf-element-masse), es gibt dafür keine JSON-Tabelle.

Bearbeiten (c:GEFAELLESTRECKE_EDIT): Doppelklick auf einen Gefällestrecken-Block (GF_n) bzw. Rechtsklick-Kontextmenü/SSG_BLOCKEDIT öffnet denselben DCL-Dialog, vorbelegt mit den aktuellen Parametern, und baut die Strecke bei OK am selben Startpunkt neu auf. Damit Fahrtrichtung und Element-Winkel (30/90) verlustfrei rekonstruiert werden, schreibt gefaellestrecke-einfuegen diese beim Erstellen als XDATA (App SSG_GF_EDIT, Helfer gf-xdata-schreiben/gf-xdata-lesen) auf das GF_n-INSERT bewusst nicht in den Sivas-Attributsatz, damit der Export unverändert bleibt. Ältere Blöcke ohne XDATA werden aus den Attributen vorbelegt (Fahrtrichtung 0°, Element-Winkel 90° als Vorgabe). Der Neuaufbau läuft über gf-rebuild (nicht-interaktiv, ohne Konsolen-Rückfrage).


export.lsp Export-Funktionen

Sammelt INSERT-Blöcke aus der Zeichnung und exportiert sie als JSON oder ruft Python-Skripte für den Sivas-Export auf.

Befehl / Funktion Beschreibung
c:EXPORTSIVAS Alle Blöcke als JSON sammeln und export_sivas.py aufrufen (Sivas-CSV)
c:EXPORTCSV Alle Blöcke als JSON sammeln und export_csv.py aufrufen (einfache Item-Liste, inkl. Omniflo Bogen/Weiche/Gerade und abschließender "Omniflo Sum"-Zeile)
csv:collect-export-blocks Alle INSERT-Blöcke der Zeichnung als JSON-Array sammeln
csv:run-export py-skript json-datei output-csv Python-Skript mit gesammelten Daten aufrufen
csv:read-attribs ename Attribute eines INSERT als JSON-Objekt lesen
c:OMNI_UPDATE_ATTRIBS HOEHE/DREHUNG aller Omniflo-Elemente aus der Zeichnung aktualisieren

Der Omniflo-CSV-Export (Bogen/Weiche/Gerade, inkl. Merkmale-Aufbau und Sum-Zeile) läuft seit Entfernung von c:OMNI_EXPORT ausschließlich über c:EXPORTCSVlib/export_csv.py (build_bogen_merkmale, build_weiche_merkmale, build_gerade_merkmale, build_omni_sum_merkmale).

Ausgabeordner: c:EXPORTSIVAS/c:EXPORTCSV schreiben immer nach DXFM_RESULTS. TEST_EXPORT_ALL (siehe tests/test_export_all.lsp) leitet waehrend des Testlaufs stattdessen nach DXFM_TESTOUT um, über die reine Lisp-Sitzungsvariable *export-test-override* (wird von csv:run-export zusaetzlich zu DXFM_RESULTS abgefragt und danach garantiert wieder auf nil zurueckgesetzt, auch bei einem Fehler, ueber vl-catch-all-apply).

Wichtig: Der Umweg über *export-test-override* ist bewusst gewaehlt und kein (setenv "DXFM_RESULTS" ...). In BricsCAD/AutoCAD schreibt (setenv ...) nicht nur in den Windows-Prozess, sondern dauerhaft in die Profil-Registry der Anwendung der Wert überlebt damit jeden Neustart und jedes setenv.bat, bis er erneut per (setenv) überschrieben wird. Ein einziger (setenv "DXFM_RESULTS" ...)-Aufruf (z. B. ein frueherer, unvollstaendiger Testlauf) würde DXFM_RESULTS für alle künftigen Sitzungen unwiderruflich auf den Testordner umbiegen. Falls das bereits passiert ist, hilft nur ein manuelles (setenv "DXFM_RESULTS" "<richtiger Pfad>") in BricsCAD, um den Profil-Wert zu korrigieren.


tests.lsp Testbefehle

Testbefehle für die Python-Integration. Export-Funktionen wurden in export.lsp ausgelagert.

Befehl Beschreibung
c:CALLPYTHON testpycall.py via _.SHELL aufrufen und Rückgabe einlesen (Integrationstest LISP↔Python)

Tests

Zwei Test-Ebenen, beide gesteuert über bin\run_tests.bat (Details und Verzeichnisstruktur: ../tests/README.md):

  1. LISP-Unit-Tests (tests/test_unit.lsp) prüfen reine Standardfunktionen direkt in AutoLISP, ohne Zeichnung.
  2. Zeichnungsbasierte Integrationstests (tests/test_*.lsp + tests/test_*.py) erzeugen Blöcke in BricsCAD und validieren das Ergebnis anschließend mit pytest/ezdxf. Module: test_kreisel, test_foerderer, test_linienzug, test_gefaellestrecke, test_omniflo, test_omniflo_strecke und test_mubea (Gesamtmodell: Kreisel + Vario + Gefällestrecken + Separatoren aus tests/testdata/mubea.json in einer Zeichnung; über SSG_RUN_ALL_TESTS bzw. Menü „Tests → Mubea Gesamtmodell").

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 inkl. der Unterscheidung scriptbar vs. nur-interaktiv.

LISP-Unit-Tests (test_unit.lsp)

Testen reine Hilfsfunktionen solche, die nur aus ihren Argumenten ein Ergebnis berechnen und keine Zeichnungsdatenbank, Auswahlsätze, Dialoge oder Blockdateien brauchen (String-, Zahl-, Vektor-, Listen- und Alist-Helfer). Abgedeckt werden Funktionen aus ssg_core, ssg_lang, ssg_id, vf_core, export, Gefaellestrecke, OmniModulInsert und KreiselInsert.

Aufruf über die Kommandozeile (startet BricsCAD headless):

bin\run_tests.bat --lisp

run_tests.bat --lisp löscht das alte Ergebnis, startet BricsCAD mit tests/test_unit.scr (lädt ssg_load.lsp + test_unit.lsp, ruft TEST_UNIT auf und beendet BricsCAD), gibt danach tests/output/unit_results.txt aus und liefert Exit-Code 1, wenn ein Test fehlschlägt oder kein Report entsteht.

Aufruf direkt in BricsCAD (SSG_LIB geladen):

(load (strcat (getenv "DXFMAKRO") "/tests/test_unit.lsp"))
TEST_UNIT

Aufbau eines Testfalls. test_unit.lsp enthält ein Mini-Framework: jeder Testfall ruft eine Funktion auf und vergleicht das Ergebnis gegen einen erwarteten Wert. Die Assertion-Helfer zählen Treffer/Fehler mit und schreiben je eine PASS/FAIL-Zeile:

Helfer Vergleich
tu-eq name erwartet ist exakt (equal) Strings, Ganzzahlen, Listen davon
tu-eqf name erwartet ist numerisch mit Toleranz 1e-6 Fliesskomma, auch verschachtelte Listen
tu-true name ist Ergebnis ist nicht nil
tu-nil name ist Ergebnis ist nil

Beispiel Formatierung einer ID und ein Vektor-Kreuzprodukt:

(tu-eq  "ssg-id-format/1"      "0001"          (ssg-id-format 1))
(tu-eqf "vec3-cross/x-cross-y" '(0.0 0.0 1.0)  (vec3-cross '(1.0 0.0 0.0) '(0.0 1.0 0.0)))

Die Testfälle sind in tu-tests-<modul>-Funktionen gruppiert; c:TEST_UNIT ruft alle nacheinander auf, gibt eine Zusammenfassung (Gesamt / PASS / FAIL) aus und schreibt den Report unit_results.txt mit einer abschließenden Zeile RESULT: OK bzw. RESULT: FAIL (die run_tests.bat auswertet).

Neuen Testfall ergänzen: in der passenden tu-tests-<modul>-Funktion eine tu-eq/tu-eqf/tu-true/tu-nil-Zeile hinzufügen. Für ein neues Modul eine eigene tu-tests-<modul>-Funktion anlegen und in c:TEST_UNIT aufrufen. Getestet werden sollten nur Funktionen ohne Zeichnungs-/Dialog-Umfeld alles mit ssget/entget/entmake/command/vla-*/entsel/DCL gehört in die zeichnungsbasierten Integrationstests.


KreiselInsert.lsp ILS Kreisel und Eckrad

AutoLISP-Implementierung fuer ILS Kreisel und Eckrad. Enthaelt alle Befehle fuer Einfuegen, Verbinden, Neuzeichnen und Bearbeiten.

Befehl Beschreibung
c:KreiselInsert Kreisel-Block an Punkt einfuegen (mit Dialog fuer Parameter)
c:KreiselConnect Zwei Punkte waehlen, Kreisel dazwischen einfuegen
c:KreiselRedraw Bestehenden Kreisel mit neuen Parametern neu zeichnen
c:KreiselQuick Schnelleinfuegung mit Standardwerten
c:KreiselEdit Kreisel-Attribute ueber DCL-Dialog bearbeiten
c:KreiselParams Aktuelle Kreisel-Parameter anzeigen
c:KreiselLabelSetup Schriftart, Hoehe und Farbe fuer Kreisel-Beschriftung konfigurieren
c:KreiselLabelPos Label-Offset (dx/dy) setzen
c:KreiselLabelHoehe Label-Hoehe aendern
c:ILS_Eckrad Eckrad an Tangentenpunkt einfuegen

OmniModulInsert.lsp Omniflo-Komponenten

AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen. Liest JSON-Daten aus omniflo_boegen.json und omniflo_weichen.json. Alle Konstanten via ssg-cfg-or aus Config.

Befehlsgruppe Befehle Beschreibung
Daten OMNI_LOAD, OMNI_INFO_BOGEN, OMNI_INFO_WEICHE JSON-Daten laden und abfragen
Boegen OMNI_APB_630_90, OMNI_APB_550_675, OMNI_APB_630_45, OMNI_APB_550_225, OMNI_APB_650_180 Omniflo-Boegen ueber DCL-Dialog einfuegen
Weichen OMNI_W90_*, OMNI_W45_*, OMNI_WP_*, OMNI_WK_*, OMNI_WKomb_* Omniflo-Weichen (Einfach/Doppel/Dreiwege, Delta, Stern)
Geraden OMNI_AP60, OMNI_AP110, OMNI_APG110 Omniflo-Geradenstuecke
TEF ⚠️ OMNI_TEF_UmlenkR/L, OMNI_TEF_AntriebL/R, OMNI_TEF_Gerade, OMNI_KettenFoerderer Dummy (noch nicht implementiert, im Menue ausgegraut)
Transferwagen ⚠️ OMNI_TV_* Dummy (noch nicht implementiert, im Menue ausgegraut)
Bogenweichen ⚠️ OMNI_APBW_* Dummy (noch nicht implementiert, im Menue ausgegraut)
Bearbeiten OMNI_EDIT Omniflo-Block selektieren und Attribute bearbeiten

SSG_LIB_Commands.lsp Dummy-Befehle, Sensoren, Konfiguration und SSG_BLOCKEDIT

Sammeldatei fuer Menue-Befehle: teils Platzhalter fuer noch nicht implementierte Eintraege, teils bereits echte Funktionalitaet (Sensoren, Konfiguration, Doppelklick-Dispatcher). Alle noch offenen Dummy-Menueintraege sind in menu/SSG_LIB.mnu mit ~ ausgegraut (siehe Abschnitt "Status: noch offene Menueintraege").

Sensoren einfuegen (real, ueber ils-insert-sensor → wiederholtes _.INSERT mit interaktivem Einfuegepunkt/Rotation, Blockdatei via ssg-ils-block-datei):

Befehl Block Beschreibung
ILS_SCANNER_INSERT Scanner Scanner wiederholt einfuegen (ENTER/ESC beendet)
ILS_SEPARATOR_INSERT Separator_SP Separator wiederholt einfuegen (Menue „Separator einfuegen")

Registrierte Dummy-Befehle:

Gruppe Befehle
ILS Zusatzmodule ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_ETF_Etagenfoerderer, ILS_TEF_Strecke
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, ILS_GK90L, ILS_GK90R, ILS_GK60L, ILS_GK60R, ILS_GK30L, ILS_GK30R

FOERDERANLAGE ist nicht hier definiert dieser Befehl ist in VarioFoerderer.lsp implementiert.

Konfigurationsbefehle (Menue → Konfiguration):

Befehl Beschreibung
SSG_DIM_SWITCH Schaltet zwischen 2D/3D-Bloecken um (setzt DXFM_DIM, DXFM_BLOCKS, DXFM_OMNIFLO)
SSG_SPRACHE Oeffnet Dialog sprache.dcl, setzt *ssg-lang* und persistiert via DXFM_LANG (siehe ssg_lang.lsp)

SSG_BLOCKEDIT Doppelklick/Kontextmenue-Dispatcher:

Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearbeitungsbefehl auf:

Blockmuster Aktion
KREISEL_* KreiselEdit
ECKRAD_* BEDIT (Block-Editor)
Omniflo (TEILEART-Attribut, AP110*, numerisch) OMNI_EDIT
Sonstige BEDIT (Block-Editor)