Files
dxfmakros/Lisp
y.wang 833a4b60a6 fix: Lauf-Anfang als selbstbeschreibender Wert, Dialog-Hinweise lesbar
Die Frage "Lauf beginnen mit" (Modus 2) journalisiert jetzt den WERT
("mit-gf1"/"direkt"/"ohne") statt der Auswahl-Ziffer. Anlass war die
Umstellung der Optionsreihenfolge auf Regelfall zuerst: mit einer Ziffer
haette dieselbe "3" vor und nach der Umstellung Verschiedenes bedeutet,
eine bestehende Kette waere beim Doppelklick still mit einer ANDEREN
Anfangsvariante neu gebaut worden. Alte Ketten laufen ueber die Tabelle
*vfl-m2-anfang-alt* weiter; ein Wert, der weder Alt-Ziffer noch gueltiger
Wert ist, bricht den Aufbau ab und nennt Kette und Wert, statt eine
Variante zu raten.

Weiter aus der Modus-2-Arbeit:
- Laengenbudget je VF-Einheit (max. 25 m, max. 2 Vario-Kurven,
  *vfk-vf-kurven-max*), bei Ueberschreitung automatischer Schnitt
- nach einer VF-Geraden ist der Bogentyp waehlbar (GF-Bogen/Vario-Kurve)
- Segmentnummer steht im Kopf jedes Dialogs
- "Separator NACH" ist am letzten GF-Stueck vor einem ES gesperrt, der
  automatische Separator wird dort erklaert
- "Ohne Umlenkstation" ist mit AS-Element gesperrt
- Fuellerlaenge nur noch dann aus dem Rueckanker, wenn der VF-Lauf das
  Pfadende ist

Dialoge: Hinweis steht in Klammern hinter dem Ankreuzfeld statt darunter,
Lauf-Anfang-Optionen tragen die Nummern der Konsolenliste, die
Begruendungszeile ist breit genug und wird nicht mehr abgeschnitten.

14 neue Unit-Tests zur Wert-Normierung (durchlaufen die Alt-Tabelle).
Sprachdateien 1205/1205 synchron.

Offen: der Fuellerlaengen-Fix ist in BricsCAD noch nicht nachgemessen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-23 15:39:57 +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-Reihenfolge (muss vor den Feature-Modulen stehen): ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, ssg_id, ssg_ks_insert (Letzteres wird von Gefaellestrecke UND VarioFoerderer genutzt). Details: siehe ../CLAUDE.md Abschnitt "Lademechanismus".

Manuell laden (Notfall / Entwicklung, z.B. fuer .scr-Testskripte):

(load (strcat (getenv "DXFMAKRO") "/Lisp/ssg_load.lsp"))

ssg_load.lsp ist der Headless-Loader (genutzt von tests/test_unit.scr u.ae.) und laedt dieselbe Kern-Reihenfolge wie SSG_LIB.mnl, 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
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). 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.


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)

Ziel-Layer je Baugruppe (cfg/layer.cfg):

Für Baugruppen, die ein Makro aus Einzelteilen zusammenbaut (KREISEL_n, ECKRAD_n, VF_n, GF_n) und für die selbst gezeichnete Hilfsgeometrie (Kreisel-Tangenten, PIN-Linien, Beschriftungstexte) gibt es keine Blockdatei in data/ und damit kein LAYER-Attribut – ihr Ziel-Layer und die Layerfarbe kommen aus cfg/layer.cfg. Nur eingefügte Blöcke nehmen dagegen ihr LAYER-Attribut als Vorgabe. Alle Funktionen liefern nil, wenn nichts konfiguriert ist; der Layer bleibt dann unangetastet (kein Fehler bei fehlender cfg/layer.cfg).

Funktion Beschreibung
ssg-layer-cfg-load cfg/layer.cfg einmalig (lazy) einlesen, Rückgabe ini-Alist oder nil
ssg-layer-cfg-reset Ladezustand verwerfen (cfg in laufender Sitzung neu einlesen, Tests)
ssg-layer-cfg-eintrag ini sektion key Reine Aufl./Zerlegung "Layername, Farbe" → (layer . farbe); Farbe fehlt → "7"
ssg-layer-eintrag key Ziel-Layer einer Baugruppe: [ils_<Dimension>] → [allgemein] → nil
ssg-layer-anlegen key aktiv Layer der Baugruppe mit cfg-Farbe anlegen, optional aktivieren; Rückgabe Layername
ssg-layer-setzen ent key Blockreferenz auf den Ziel-Layer ihrer Baugruppe legen (Layer wird angelegt)
ssg-layer-farbe-fuer-name name Farbe zu einem Layernamen (Abschnitt [farben], sonst passender Baugruppen-Wert, sonst "7")
ssg-block-layer-vorgabe ent blockname attribs Layer einer nur eingefügten Referenz aus der Block-Vorgabe: LAYER-Attribut → ssg-ils-block-ebene → nichts

Die Farbe greift nur bei der Neuanlage eines Layers – ssg-make-layer lässt bestehende Layer unverändert. Layer, die eine Blockdatei aus data/ils selbst mitbringt (z. B. ILS_SP), legt BricsCAD bereits beim Einfügen des Blocks mit der Farbe aus der DWG an; dort wirkt die cfg-Farbe nicht, der Layername des Wrappers aber schon.

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/plan/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)

Zentrale Debug-Schalter (default je nach Schalter)

Damit dbg*-Aufrufe dauerhaft im Code stehen bleiben können, ohne im Normalbetrieb ungeplant .dbg-Dateien zu erzeugen, gibt es eine zentrale Schalter-Sammlung (*dbg-schalter*, Symbol → 0/1). Eine Routine öffnet ihre Debug-Datei nur, wenn ihr Schalter eingeschaltet ist. Unbekannte/neue Schalter gelten implizit als 0/aus; die VF-Linienzug-Schalter unten sind bewusst mit Default 1/an vorregistriert (siehe Tabelle).

Funktion Beschreibung
dbg-schalter-on name Schalter name einschalten (1)
dbg-schalter-off name Schalter name ausschalten (0)
dbg-schalter-p name T wenn eingeschaltet, sonst nil
dbg-schalter-open name filename envvar Öffnet die Datei nur wenn Schalter=1; gibt T/nil zurück
dbg-schalter-liste Alle bekannten Schalter + Zustand ausgeben

Bekannte Schalter:

Schalter Default Modul Loggt nach
"vfl-modus1" AN (1) Linienzug Modus 1 (manuelle Eingabe, vf-linienzug-modus) DXFM_LOG/vfl_modus1.dbg
"vfl-modus2" AN (1) Linienzug Modus 2 (3D-Objekte + Ziel-Höhe, vf-linienzug-modus2) DXFM_LOG/vfl_modus2.dbg
"vfl-modus3" AN (1) Linienzug Modus 3 (Vorwärts-Nachbau, vf-linienzug-modus3) DXFM_LOG/vfl_modus3.dbg

Alle drei Modi loggen automatisch jede interaktive Eingabe, weil sie durchgehend über die gemeinsamen Wrapper vfl-in-point/-string/-real/ -int/-value/-selection gehen, die zentral in vfl-journal-record protokolliert werden – keine einzelne Aufrufstelle im Bau-Ablauf musste dafür angefasst werden. Da der Default AN ist, wird bei jedem Aufruf von FOERDERANLAGE → linienzug ohne weiteres Zutun mitgeloggt; bei Bedarf einzeln abschaltbar mit (dbg-schalter-off "vfl-modus1") usw.

;; Standardmaessig bereits an - nur zur Kontrolle:
(dbg-schalter-liste)
;; ... FOERDERANLAGE -> linienzug -> Modus 1/2/3 durchspielen ...
;; -> Datei DXFM_LOG/vfl_modus<N>.dbg enthält Session + alle Eingaben
(dbg-schalter-off "vfl-modus1")   ; bei Bedarf einzeln abschalten

Muster in einer Routine:

(setq dbg-an (dbg-schalter-open "vfl-modus3" "vfl_modus3.dbg" "DXFM_LOG"))
(if dbg-an (dbgmsg "FRAGE: ..."))
;; ... get* ...
(if dbg-an (progn (dbgmsg "ANTWORT:") (dbg 'wert) (dbgflush)))
;; am Ende:
(if dbg-an (progn (dbgreturn ergebnis) (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 2–3)
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_input.lsp – Generische Eingabe-Wrapper

Abfragen mit Vorgabewert (<..> im Prompt, Enter = Vorgabe). Steht neben den VF-spezifischen vfl-in-* (vf_linienzug.lsp); diese bleiben unveraendert. Kein Journal, aber ein optionaler Hook. ESC bricht wie ueblich ueber *error* ab.

Funktion Beschreibung
ssg-in-real text default Reelle Zahl (getreal), Vorgabe ohne ueberfluessige Nullen angezeigt
ssg-in-int text default Ganzzahl (getint)
ssg-in-string text default String mit Leerzeichen; Enter ohne Eingabe liefert die Vorgabe (ohne Vorgabe nil)
ssg-in-point text default base Punkt, base = Gummiband-Basispunkt oder nil
ssg-in-dist text default base Abstand (getdist)
ssg-in-keyword text schluessel default Schluesselwort im initget-Format, z.B. "Alle Auswahl"
ssg-in-yesno text default Ja/Nein, T = Ja; default T = Enter bedeutet Ja. Woerter aus ssg-text "in-yesno-keys"
ssg-in-default wert default, ssg-in-fmt-real, ssg-in-fmt-pt, ssg-in-prompt, ssg-in-first-word, ssg-in-second-word Reine Hilfsfunktionen (in tests/test_unit.lsp getestet)

Hook (z.B. fuer ein Eingabe-Journal): (setq *ssg-in-hook* 'meine-funktion) mit (defun meine-funktion (art prompt wert) ...); art ist "REAL", "INT", "STRING", "POINT", "DIST", "KEYWORD" oder "YESNO". Ein Hook, der einen Fehler wirft, wird abgeschaltet.


ssg_id.lsp – Eindeutige Block-IDs

Jedes exportierbare Element bekommt ein Attribut ID mit einer eindeutigen, vierstelligen Nummer. Kern-Modul (nach ssg_layer, vor ssg_ks_insert).

Befehl / Funktion Beschreibung
c:IDGENERATE Weist dem zuletzt eingefuegten Block eine neue ID zu
c:IDSCHECK Prueft alle Bloecke auf doppelte IDs und korrigiert sie
ssg-id-format n Zahl als 4-stelligen String formatieren (1 → "0001")
ssg-id-max Hoechste bereits vergebene ID in der Zeichnung
ssg-id-generate ent Neue ID erzeugen und auf den Block setzen
ssg-id-check-all Zeichnungsweit auf Doubletten pruefen und korrigieren
ssg-id-collect-blocks Alle ID-faehigen INSERT-Entities sammeln (gleiche Muster wie csv:collect-export-blocks, inkl. Separator/Scanner/BTMT)

ssg_ks_insert.lsp – KS-Extraktion und Block-Einfuegeprimitiven

Gemeinsame Basis fuer VarioFoerderer (vf_core.lsp) UND Gefaellestrecke – frueher in beiden Modulen dupliziert, jetzt einzige Quelle. Muss laut MNL vor Gefaellestrecke/vf_core geladen sein; Kern-Modul.

Funktion Beschreibung
vec-length v Laenge eines 3er-Vektors
ks-line-axis laenge Achsenkennung (X/Y/Z) aus Linienlaenge der KS-Hilfslinie
ks-normalize-name nm Historische KS-Blocknamen (KSYS_EIN/-AUS) auf KS_EIN/KS_AUS normalisieren
ks-relativize / ks-absolutize KS-Punkte zwischen relativem und Welt-Koordinatensystem umrechnen
ensure-block-loaded name Block aus der Bibliothek einmalig ins aktive Dokument laden
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

ssg_blocktools.lsp – Block-Werkzeuge

Ursprung: ACADSST TOOLS.LSP (BLKANZAHL, BLKENTF), DINGEN2 (g-bli), ssg.lsp (suchen-aendern). Arbeitet im aktuellen Layout-Reiter. Blocknamen werden ueber den wirksamen Namen verglichen (dynamische Bloecke); Muster mit wcmatch (*, ?, #, ohne Gross-/Kleinschreibung).

Befehl Beschreibung
SSG_BLOCK_COUNT Block anklicken, Name fuer ein Muster, oder Enter fuer eine Statistik aller Bloecke
SSG_BLOCK_DELETE Alle Einfuegungen eines Blocks/Musters loeschen; Rueckfrage (Vorgabe Nein), Einfuegungen auf gesperrten Layern bleiben stehen; eine Undo-Gruppe
SSG_ATTR_ERSETZEN Attributwerte suchen/ersetzen: Bereich (Alle mit Blockname-Muster / Auswahl), Tag-Muster, Suchtext, Ersatz, Modus Teil (Teilstring) oder Gesamt (ganzer Wert). Zeigt vorab die Anzahl und fragt nach
Funktion Beschreibung
ssg-bt-inserts muster Entity-Liste aller Einfuegungen im Layout (optional nach Muster)
ssg-bt-statistik muster ((NAME . ANZAHL) ...) alphabetisch
ssg-bt-attr-ersetzen-ent ent tag suche ersatz teil-p probe-p Attribute EINER Einfuegung ersetzen bzw. nur zaehlen (probe-p); Rueckgabe Anzahl
ssg-bt-attr-ersetzen-liste ents tag suche ersatz teil-p probe-p Dasselbe fuer eine Entity-Liste
ssg-bt-wert-neu wert suche ersatz teil-p Reiner Kern: neuer Wert oder nil (unveraendert); beachtet Gross-/Kleinschreibung
ssg-bt-name-passt-p, ssg-bt-zaehle-namen, ssg-bt-muster-escape Reine Hilfsfunktionen (getestet)

ssg_texttools.lsp – Text-Werkzeuge

Ursprung: ACADSST CHGTEXT.LSP, PARTEXT.LSP, ALTHOEHE.LSP, ALTSTIL.LSP. Laden nach ssg_blocktools (nutzt ssg-bt-wert-neu und ssg-bt-attr-ersetzen-liste). Arbeitet in der XY-Ebene des Welt-KS.

Befehl Beschreibung
SSG_TEXT_ERSETZEN Suchen/Ersetzen in TEXT, MTEXT und Block-Attributen; Bereich Alle (Layout) oder Auswahl; Vorschau mit Anzahl, Rueckfrage
SSG_TEXT_PARALLEL Linie/Polylinie/Bogen anklicken, Text wird parallel (lesbar, nie auf dem Kopf) mit Abstand gesetzt; Hoehe, Abstand und letzter Text werden fuer die Sitzung gemerkt; Enter beendet
SSG_TEXT_HOEHE Texthoehe gewaehlter TEXT/MTEXT aendern
SSG_TEXT_STIL Textstil gewaehlter TEXT/MTEXT aendern (Stil muss existieren)

Reine Kerne (getestet): ssg-tt-lesbarer-winkel (Winkel 90 Grad bis 270 Grad um 180 Grad drehen, Ergebnis in [0, 2 pi)), ssg-tt-versetzt.

Nicht uebernommen aus Walz: Export/Import von Texten (besser per Python/ezdxf), KREISTXT, TXTBOXED, CHTEXT/ASCTEXT/PTEXT (Autodesk 1990, durch BricsCAD-Standard ersetzt).


ssg_load.lsp – Laderoutine

Headless-Loader fuer .scr-Testskripte (z.B. tests/test_unit.scr). Laedt alle Kern- und Feature-Module in derselben Reihenfolge wie SSG_LIB.mnl, ohne Menueabhaengigkeit. 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 (Wrapper)

Kompatibilitäts-Wrapper, der vf_core.lsp lädt (Plugin-Dispatcher-Architektur über *vf-typ-registry*; lädt seinerseits vf_konstanten.lsp, vf_standard.lsp, vf_etage.lsp, vf_linienzug.lsp, danach vf_spec.lsp). Parametrischer Generator für ILS Vario-Förderanlagen (Typen Standard/Etage/Linienzug). Liest Block-Geometrie aus einer DWG-Bibliothek (DXFM_BLOCKS) über die Primitiven aus ssg_ks_insert.lsp. Alle Konstanten (Abstände, Winkel, Skalierung) werden über ssg-cfg-or (component_defaults.json, Sektion vario) bzw. die zentralen *vfk-*-Konstanten aus vf_konstanten.lsp gelesen.

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

  • Typ „standard“ und „etage“ + Werteingabe: laufen über denselben, typ-parametrisierten Dialog-Ablauf (vf-dialog-ablauf in vf_core.lsp; vfs-standard-dialog-ablauf/vfe-etage-dialog-ablauf sind nur noch duenne Wrapper darauf) mit den Dialogen vfs-dialog-eingabe-basis/ vfs-dialog-winkel-verteilung (dcl/variofoerderer.dcl): Dialog 1 erfasst deltaL, Förderrichtung, Einfügehöhe/deltaH, Fahrtrichtung und Seite/Motorseite; Dialog 2 lässt Winkel und L_GF-Verteilung (vorne/hinten) wählen. Startpunkt (X/Y) wird vorher in der Zeichnung gepickt.
  • Typ „standard“/„etage“ + 3D-Linie laufen ueber denselben Basis-Dialog statt rein interaktiv auf der Konsole.
  • Typ „linienzug“ (Streckengruppe, vf-linienzug-modus in vf_linienzug.lsp) hat drei Modi (manuell/Wizard, 3D-Objekte+Zielhoehe, Vorwaerts-Nachbau) und zeichnet jede Eingabe in einem Journal auf (XDATA SSG_VF_EDIT am VF_n-Block); Standard laeuft per Default ueber DCL-Dialoge (VF_WIZARD_AN/VF_WIZARD_AUS schalten um). Details, Journal-Format, Headless-Modus (*vfl-headless*) und Spec-basierter Bau ohne Dialog (vf_spec.lsp, VF_SPEC_BAU): siehe ../doc/variofoerderer.md und ../CLAUDE.md.

Bearbeiten (c:VARIOFOERDERER_EDIT): Doppelklick auf einen VF_n-Block – bzw. Rechtsklick-Kontextmenü/SSG_BLOCKEDIT – dispatcht per XDATA-Marker ("standard"/"etage"/"linienzug") in den passenden Neuaufbau-Zweig (vfe-edit-ent fuer Etage, vfl-edit-ent fuer Linienzug) und öffnet dieselben Dialoge, vorbelegt mit den aktuellen Parametern; der Block wird am selben Startpunkt neu aufgebaut (neue VF_n-Nummer). Altbestand-Blöcke ohne Marker werden mit einer Meldung abgewiesen, statt sie zu verändern. Winkel und L_GF1 werden aus den Sivas-Attributen (VF_WINKEL, L_GF_m) vorbelegt.

Die Block-Einfuege-Primitiven (ensure-block-loaded, insert-block-by-ks, insert-inclined-scaled-block, insert-rotated-block-with-ks u.a.) sind seit der Konsolidierung zentral in ssg_ks_insert.lsp definiert (von vf_core.lsp, Gefaellestrecke.lsp und TEFInsert.lsp genutzt). Weitere interne Helfer: init-bibliothek (Block-Bibliothek aus DWG laden), get-line-start-end-points ename, punkt-differenz p1 p2.


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).


TEFInsert.lsp – TEF-Geradenstuecke entlang einer Linie

Befehl: c:TEF_FOERDERER_LINIE. Zeichnet eine Linie zwischen zwei gewaehlten Punkten und reiht darauf 1000-mm-TEF-Geradenelemente (0_B10030 aus DXFM_OMNIFLO) aneinander; ist die Linienlaenge kein exaktes Vielfaches, wird ein zusaetzliches, zurueckverschobenes Element eingefuegt, sodass der Foerderer exakt am Linienende endet (keine Luecke, kein abgeschnittenes Element). Die Linie darf geneigt sein (3D) – Elemente werden dann analog zu vf_core.lsp/ssg_ks_insert.lsp (Rz*Ry-Rotation) gekippt eingefuegt. Nicht zu verwechseln mit den einzelnen OMNI_TEF_*-Befehlen in OmniModulInsert.lsp.


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; legt vorher fuer in VF_n/GF_n/KREISEL_n verpackte Separator_SP_2D/_3D-Sub-INSERTs (Sensor-Symbol; siehe ssg-collect-nested-inserts in ssg_core.lsp - NICHT der interne Staustrecke_Separator_SP-Trennsteg) je eine echte, temporaere Kopie an derselben Stelle an (csv:sep-proxies-erzeugen, Position/Drehung/Skalierung ueber alle Verschachtelungsebenen hinweg identisch zum Vorbild - kein kosmetischer Versatz mehr, der die geometrische Sensor-Zuordnung verfaelschen wuerde), damit sie ganz normal ueber ssg-id-check-all/csv:collect-export-blocks erfasst werden, und entfernt sie danach wieder (csv:sep-proxies-loeschen). Die verpackten AS-/ES-Schleuselemente derselben Kette bekommen stattdessen einen DAUERHAFTEN Marker (csv:asmark-aktualisieren, siehe unten); beide Wege teilen sich die Platzierungsrechnung (csv:nested-welt-records + csv:block-einfuegen-welt). Reihenfolge ist wesentlich: erst ssg-id-check-all (Wrapper-IDs endgueltig), dann die Kopien/Marker (ZUORDNUNG direkt beim Erzeugen), dann csv:ketten-verarbeiten (IDs in Kettenfolge, Separator-Typ, sepliste-Stellvertreter), dann ein zweites ssg-id-check-all (Restnummerierung)
csv:asmark-aktualisieren AS-/ES-Kettenenden sichtbar machen: setzt an jedes verpackte AS_Element*/ES_Element* einer VF_n/GF_n-Kette ein kleines Rechteck (Block ZZ_ASES_MARKER, Groesse aus cfg/export.cfg [Marker], Layer aus cfg/layer.cfg ases_marker), das nach dem Export stehen bleibt. Unsichtbare Attribute ID/ZUORDNUNG/TYP/LFDNR/ELEMENT/ARTINR; die ID fuellt ssg-id-check-all und der naechste Export uebernimmt sie, ein AS/ES behaelt seine TeileId also ueber Laeufe hinweg. Baut bei jedem Export alle Marker neu auf (Wiederfinden ueber ZUORDNUNG+TYP+LFDNR) und entfernt verwaiste
csv:ketten-verarbeiten sep-proxies element-proxies asmarks Je VF_n/GF_n aus DERSELBEN KS-geordneten Kette (csv:kette-von, einmal je Lauf berechnet): Einheiten-Proxies (group_vf_gf), IDs in Kettenfolge, Separator-Typ VF/GF (csv:kette-sep-typen -> *cs-sep-typ-by-handle*) und der Stellvertreter jedes sepliste-Eintrags (*csv-sepliste-id-by-handle*, Key = Wrapper-Handle; csv:block-to-json liest dessen ID beim Schreiben als Feld id)
csv:sepliste-kette-paare eintraege typen Zuordnung sepliste-Eintrag -> Kettenbaustein ueber die Reihenfolge je Typ (k-tes AS/SEP/ES der sepliste = k-tes der KS-Kette), ohne die (teils gespiegelten) sepliste-Koordinaten. Reine Rechenfunktion, getestet in tests/test_unit.lsp
csv:element-familien EINZIGE Tabelle Familie -> Blockmuster (pattern_nested_* aus cfg/export.cfg) fuer Suche (csv:pattern-nested-element) UND Klassifizierung (csv:element-teileart, darauf aufbauend csv:kette-typ)
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:EXPORTCSV → lib/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 einfuegen: Basispunkt (AN-Seite), Abstand als Gummiband-Linie (deren Richtung = Rotation), Hoehe, Kreiselart
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, Parameter per DCL-Dialog (eckrad_edit.dcl; ohne GUI Konsolen-Rueckfall)
c:EckradEdit Eckrad ueber DCL-Dialog bearbeiten (Bezeichnung, Hoehe, Drehung, Drehrichtung, Geruest; kein Abstand/Typ), Neuaufbau mit gleicher Nummer
c:KREISEL_WEICHEN Beruehrpunkte (= ILS-Weichen) aller Kreisel/Eckraeder gleicher Hoehe ermitteln: Rad/Rad und Rad/Laufprofil auf der freien Radseite, Toleranz toleranz_beruehrung/toleranz_hoehe (component_defaults.json). Ueberschneidungen und Seite-an-Seite-Kreisel werden als Kollision gemeldet. Konsolenliste + Kreis-Marker (Layer kreisel_weiche/kreisel_kollision), ein neuer Lauf ersetzt die Marker. Derselbe Kern (kreisel-bp-ermitteln) liefert beim Export kreisel_weichen.json fuer export_csv.py/export_sivas.py

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
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_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

Daneben zeichnet TEFInsert.lsp (TEF_FOERDERER_LINIE) eine Kette von TEF-Geradenelementen (1000 mm) entlang einer frei gewaehlten Linie – nicht zu verwechseln mit den einzelnen OMNI_TEF_*-Befehlen oben.


SSG_LIB_Commands.lsp – BTMT, Sensoren, Dummy-Befehle, 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").

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")

BTMT Be-/Entladestation einfuegen (real, ueber ils-insert-station):

Befehl ROH-Block Datei (3D) Beschreibung
ILS_BTMT_Beladung BTMT-Beladung BTMT-Beladung_3D.dwg Beladestation wiederholt einfuegen (ENTER/ESC beendet)
ILS_BTMT_Entladung SC_Entladung SC_Entladung_3D.dwg Entladestation wiederholt einfuegen (ENTER/ESC beendet)

Ablauf je Einfuegung: Einfuegepunkt abfragen → _.INSERT mit interaktiver Drehung (pause) → Layer aus dem LAYER-Attribut bzw. der eigenen Ebene der Blockdefinition setzen (ils-block-layer-setzen, gleiche Konvention wie omni:insert-dxf/tefl-insert-element) → ssg-id-generate, falls der Block ein ID-Attribut fuehrt.

Die Blockdefinition kommt aus ssg-ils-block-laden (aktuelle Dimension *ssg-ils-dim* → DXFM_DIM → 3D, DWG wird nur einmal pro Zeichnung gelesen); eingefuegt wird der zurueckgegebene dim-suffigierte Blockname. Fehlt die Datei der gewuenschten Dimension, greift der 3D-Fallback mit Warnung – aktuell fuer BTMT-Beladung_2D.dwg; sobald diese Datei in data/ils/ liegt, wird sie im 2D-Modus ohne Codeaenderung verwendet (SC_Entladung_2D.dwg existiert bereits).

Beide Stationen werden ueber pattern_btmt_beladung/pattern_btmt_entladung (cfg/export.cfg) von ssg-id-collect-blocks (ssg_id.lsp) UND von csv:collect-export-blocks (export.lsp) erfasst und erscheinen im Sivas-/ CSV-Export als eigene TeileArt-Zeilen ("ILS 2.0 BTMT Beladung"/"ILS 2.0 BTMT Entladung" bzw. "BT - Beladung ..."/"Abwurf fuer Klammerbuegel ..."); im Sivas-Export zusaetzlich in den Summenzaehlern "Anzahl aller BTBeladung"/ "Anzahl aller Abwurfstationen" der ILS-Automation-Zeile.

Eingang-/Ausgang-Symbol: ILS_EINGANG_INSERT/ILS_AUSGANG_INSERT nutzen 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):

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 (Reihenfolge wichtig: GR_* vor dem Omniflo-Zweig, da Geruest-Bloecke ebenfalls ein TEILEART-Attribut tragen):

Blockmuster Aktion
KREISEL_* KreiselEdit
ECKRAD_* EckradEdit
GF_* GEFAELLESTRECKE_EDIT
VF_* VARIOFOERDERER_EDIT
GR_* Geruest – BEDIT (kein eigener Edit-Pfad; siehe GeruestInsert.lsp)
TRO_* TRO_EDIT
Omniflo (TEILEART-Attribut, AP110*, numerisch) OMNI_EDIT
Sonstige BEDIT (Block-Editor)

GeruestInsert.lsp – Geruest-Baugruppen

Rohr-Geruest-Baugruppen (Saeulen, Rohrabhaenger, Wandbefestigung, Rohr-Geruest-Traeger) aus data/json/geruest.json bzw. 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. 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_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)

Block-Praefix GR_<id>_<timestamp> – nicht kosmetisch: SSG_BLOCKEDIT muss GR_* vor dem Omniflo-Zweig abfangen, da Geruest-Bloecke ebenfalls ein TEILEART-Attribut tragen. Export-Pattern pattern_geruest = GR_* (cfg/export.cfg).


Tro_Edit.lsp – TRO-Marker

TRO-Marker (Block TRO_SYM_<Typ>) fuer sps_skel/lib/tro_annotate.py.

Befehl Beschreibung
c:TRO_INSERT Bestehende Blockdefinition an gewaehltem Punkt einfuegen, setzt ID/TYPE; bricht ab, wenn der Typ noch keine Blockdefinition in der Zeichnung hat (entsteht nur ueber tro_annotate.py)
c:TRO_EDIT ID/TYPE eines bestehenden Markers per Dialog aendern

Typliste kommt aus tro_types.lsp (von tro_annotate.py --emit-lisp nach DXFM_LISP geschrieben). SSG_BLOCKEDIT leitet Blocknamen TRO_* zu TRO_EDIT.


Connection_Edit.lsp – Verbindungen (SPS)

Verbindungslinien zwischen zwei Punkten/Bausteinen fuer SPS-Dokumentation.

Befehl Beschreibung
c:CONNECTION_INSERT Verbindung zwischen zwei Punkten einfuegen (Laenge/Winkel/Mitte werden berechnet)
c:CONNECTION_EDIT Bestehende Verbindung bearbeiten

DrawPlanquadrate.lsp – Planquadrat-Raster

Zeichnet auf Z=0 ein Planquadrat-Linienraster (senkrecht/waagerecht) im Abstand/Zaehlschema der aktiven [Planquadrate]-Konfiguration aus cfg/export.cfg – dieselbe Quelle wie lib/export_planquadrat.py fuer den CSV-Export. Bereich und Ursprung kommen aus der Bounding-Box derselben Blockmenge wie EXPORTCSV (csv:collect-export-blocks), nicht aus dem reinen Einfuegepunkt oder den Zeichnungs-Extents. Lazy geladen ueber (ssg-ensure "DrawPlanquadrate"), nicht Teil der Core-Ladereihenfolge.

Befehl Beschreibung
c:DRAW_PLANQUADRATE Raster neu aufbauen (entfernt zuerst einen evtl. vorhandenen Block)
c:DELETE_PLANQUADRATE Raster-Block entfernen
c:PLANQUADRATE_TOGGLE Dispatcht auf Zeichnen bzw. Loeschen, je nachdem ob der Block existiert

Das fertige Raster (Linien + Zaehl-Texte) wird zu einem einzigen Block ZZ_PLANQUADRATE bei (0,0,0) zusammengefasst; Layer aus cfg/layer.cfg.