68ad56ec6c
Kern-Ladereihenfolge ergaenzt (ssg_id, ssg_ks_insert, ssg_input), Dummy-Status-Tabelle korrigiert (OMNI_TEF_* ist implementiert, nur OMNI_KettenFoerderer/OMNI_TV_*/OMNI_APBW_* und ein paar ILS-Kurven-Platzhalter sind noch Dummy). Fehlende Module ergaenzt: ssg_id.lsp, ssg_ks_insert.lsp, TEFInsert.lsp, GeruestInsert.lsp, Tro_Edit.lsp, Connection_Edit.lsp, DrawPlanquadrate.lsp. VarioFoerderer-Abschnitt an die Submodul-Aufsplittung (vf_core/vf_standard/vf_etage/vf_linienzug/vf_konstanten/vf_spec) und den Wizard/Journal/Headless-Mechanismus angepasst. SSG_BLOCKEDIT-Dispatchtabelle um GF_*/VF_*/GR_*/TRO_* ergaenzt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
865 lines
48 KiB
Markdown
865 lines
48 KiB
Markdown
# 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):**
|
||
```lisp
|
||
(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 ▸ Anbaugruppen | `OMNI_KettenFoerderer` | `OmniModulInsert.lsp` |
|
||
| Omniflo ▸ Verbinder | alle `OMNI_TV_*` (18) | `OmniModulInsert.lsp` |
|
||
| Omniflo ▸ Boegen fuer Weichen | alle `OMNI_APBW_*` (14) | `OmniModulInsert.lsp` |
|
||
| ILS ▸ Zusatzmodule/Kurven | `ILS_ETF_Etagenfoerderer`, `ILS_K{90,60,30}{L,R}{A,I}` (12), `ILS_Gefaellestrecke` | `SSG_LIB_Commands.lsp` |
|
||
| Geruest | `GERUEST` (Gattertraeger-Platzhalter, derselbe Befehl wie Saeulen/Rohrabhaenger/Wandbefestigung) | `GeruestInsert.lsp` |
|
||
|
||
`OMNI_TEF_*` (UmlenkR/L, AntriebL/R, TEF Gerade) sind entgegen frueherem Stand
|
||
**implementiert** (echtes `omni:insert-dxf`), nur `OMNI_KettenFoerderer` ist
|
||
weiterhin Dummy.
|
||
|
||
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/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:
|
||
|
||
```lisp
|
||
(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.
|
||
|
||
```lisp
|
||
;; 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:
|
||
|
||
```lisp
|
||
(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) |
|
||
|
||
---
|
||
|
||
### `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`](../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`](../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`](#ssg_ks_insertlsp--ks-extraktion-und-block-einfuegeprimitiven)
|
||
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`](../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`](../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`](../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):
|
||
|
||
```cmd
|
||
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):
|
||
|
||
```lisp
|
||
(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:
|
||
|
||
```lisp
|
||
(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 |
|
||
| Ladeschleifen | `OMNI_LADESCHLEIFE_AP110` | Ladeschleife aus `omniflo_ladeschleifen.json` ueber DCL-Dialog (`dcl/omniflo_ladeschleifen.dcl`) einfuegen; Daten per `ssg-json-laden` (Beschreibungen enthalten Kommas). Blockdatei `<Sivasnr>.dwg` unter `DXFM_OMNIFLO` (`omni:insert-dxf` faellt auf `.dwg` zurueck, wenn keine `.dxf` existiert). Per `OMNI_EDIT` editierbar |
|
||
| TEF Elemente | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade` | Feste TEF-Bauteile ohne Sivas-Auswahl, direkt per `omni:insert-dxf` an gewaehltem Punkt eingefuegt (Dateien unter `DXFM_OMNIFLO`) |
|
||
| Anbaugruppen ⚠️ | `OMNI_KettenFoerderer` | **Dummy** (noch nicht implementiert, im Menue ausgegraut); `OMNI_STOPPER`/`OMNI_SCANNER`/`OMNI_BUERSTENBREMSE` sind implementiert |
|
||
| 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 |
|
||
|
||
Daneben zeichnet [`TEFInsert.lsp`](#tefinsertlsp--tef-geradenstuecke-entlang-einer-linie) (`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"](#status-noch-offene-menueintraege-im-menue-ausgegraut)).
|
||
|
||
**Sensoren einfuegen** (real, ueber `ils-insert-sensor` → wiederholtes `_.INSERT`
|
||
mit interaktivem Einfuegepunkt/Rotation, Blockdatei via `ssg-ils-block-datei`):
|
||
|
||
| 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_langlsp--sprachumschaltung-deutschenglisch)) |
|
||
|
||
**SSG_BLOCKEDIT** – Doppelklick/Kontextmenue-Dispatcher:
|
||
|
||
Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearbeitungsbefehl auf (Reihenfolge wichtig: `GR_*` **vor** dem Omniflo-Zweig, da Geruest-Bloecke ebenfalls ein TEILEART-Attribut tragen):
|
||
|
||
| Blockmuster | Aktion |
|
||
| --- | --- |
|
||
| `KREISEL_*` | `KreiselEdit` |
|
||
| `ECKRAD_*` | `BEDIT` (Block-Editor) |
|
||
| `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`](../data/json/geruest.json) bzw.
|
||
[`data/json/geruest_traeger.json`](../data/json/geruest_traeger.json) konfigurieren
|
||
und einfuegen. Die Dialogdefinition wird **zur Laufzeit erzeugt**
|
||
(`geruest-dcl-schreiben`, temporaere DCL-Datei) – es gibt keine feste
|
||
`dcl/geruest.dcl`, weil je Anbauteil ein eigenes Mengenfeld gebraucht wird.
|
||
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`](../Lisp/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`.
|