Compare commits

..

259 Commits

Author SHA1 Message Date
m.stangl ab7fc92e23 Ausgabeverzeichnis nur über Lisp Variable festlegen. Anscheinend speichert Bricscad Umgebungen über die Sessions hinweg. Die Ausgaben der Tests landen woanders als der generelle Export 2026-07-10 21:26:41 +02:00
m.stangl bde2380490 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-10 21:22:53 +02:00
m.stangl 2767897158 Aufruf von explizitem Python Call rausgeworfen. War nur zu testzwecken 2026-07-10 20:16:46 +02:00
s.hensch 444d643dd3 [ADD] Attribute für ILS 2d/3d ergänzt und neu angeordnet 2026-07-10 14:16:30 +02:00
m.stangl 554e9bee99 Format der SivasNummer ohne + 2026-07-10 13:34:10 +02:00
m.stangl fe283a0bf3 ABP 60 und APB 100 als eigenes AUswahlkriterium in die Oberfläche der 90Grad Bögen hinzugefügt. Beide APB60 Bögen und die Sternweiche dazu 2026-07-10 13:32:52 +02:00
m.stangl 6bf6b00e13 neue APB 60 Bögen dazu 2026-07-10 13:31:18 +02:00
m.stangl f7933df5a4 Attribute mit SKript angeordnet. Test des Einfügens 2026-07-10 11:17:11 +02:00
m.stangl 0b89ed6c5e Dispogruppe-Header korrigiert, Container-Referenzen und --type 2D/3D fuer set_attributs.py
Sivasnr-Werte mit 0_BGxxxxxx-Mustern werden jetzt ueber die neue
[container]-Config-Sektion in kommaseparierte Listen aufgeloest.
set_attributs.py kann nun explizit zwischen data/omniflo/2D und /3D
als Quellverzeichnis waehlen.
2026-07-09 16:03:22 +02:00
m.stangl 335c6d7875 erste FAssung der reference Dateien dazu 2026-07-09 16:01:12 +02:00
s.hensch 8a7521572d Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-07-09 15:44:08 +02:00
s.hensch 1d3191b84b [ADD] Staustrecke Gerade mit Vario links/rechts 3D hinzugefügt 2026-07-09 15:43:58 +02:00
y.wang 6073eb1d78 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-09 10:59:00 +02:00
y.wang 96788e7244 TEST_LINIENZUG in eigene tests/test_linienzug.lsp auslagern + eigenen Menuepunkt Foerderer-Linienzug anlegen (Foerderer-Eintrag zurueckgesetzt), Menü neu laden nötig, damit Foerderer-Linienzug in Menü erscheint. 2026-07-09 10:58:56 +02:00
s.hensch 72a4637bd2 [CHANGE] Attribute für ARTINR und SIVASNR_TEF zu kommaseparierter liste geändert für vereinheitlichung; Unnötige dxf-Dateien entfernt oder umbenannt 2026-07-09 10:41:11 +02:00
y.wang 7a1444439c Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-08 13:45:15 +02:00
y.wang 3897581dc9 Die Funktion bei VF_Linienzug wurde optimiert. Und TEST_LINIENZUG wurde in test_foerdererer.lsp eingebaut. 2026-07-08 13:45:12 +02:00
m.stangl 8ae55d171e Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-07 09:05:19 +02:00
m.stangl 6a487433e2 Auflösung der 0_BG Nummern durch Sivas Nummern in den container Abschnitt der attradd.cfg eingepflegt. Für die programmgesteuerte Auflösung 2026-07-07 09:05:14 +02:00
y.wang 80ec7043b8 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-06 15:54:49 +02:00
y.wang 9ce739fb35 3D-Linienzug (gemischte Gefaellestrecke/VarioFoerderer-Kette, Modus 1: manuelle Eingabe) wurde bei Variofoerder gabaut. Die Block-Attribute für GF und VF wurde angepasst wie erfoerdert bei EXPORT. 2026-07-06 15:54:46 +02:00
s.hensch 5eb0acd446 Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-07-03 14:09:03 +02:00
s.hensch fd63e4c3ad Scanner für ILS hinzugefügt (2d-Block in beide Verzeichnisse 2d und 3d eingefügt); attribut und layer definitionen für Omniflo erweitert und korrigiert 2026-07-03 14:08:47 +02:00
y.wang acdf735e00 ATTREQ/ATTDIA vor GF-Block-Insert auf 0 setzen, um fehlende Attribute zu beheben; Horizontale Variofoerderer-Mittelsektion als zusaetzlichen Testfall in TEST_FOERDERER pruefen und bauen 2026-07-03 13:43:55 +02:00
y.wang 17d5bfc539 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-03 13:05:20 +02:00
y.wang 027b377b84 Testaufrufe an neue Signatur (L_GF-Halbierung + horizontale Fahrrichtung) anpassen 2026-07-03 13:05:08 +02:00
y.wang cc3cb9f160 horizontale Fahrrichtung (0°/90°/180°/270°) fuer Variofoederer manuelle Werteingabe ergänzen. die Möglichkeit des Horizontal-Varioföerderes wurde bei Ab-Förderrichtung geprüft. 2026-07-03 12:59:24 +02:00
s.hensch da1ffb27a4 Definitionen für Layerbelegung zur Information hinzugefügt; Nicht mehr notwendige Block Libraries entfernt 2026-07-03 09:06:03 +02:00
s.hensch d2d51e4415 _setenv auf die gitignore Liste gesetzt, damit diese nicht mehr verwaltet wird 2026-07-03 08:19:33 +02:00
m.stangl 2abcd0964c Test für alle Elemente ist jetzt interativ. Man kann jeden Test in einem Reiter offen lassen und ansehen (csv Export aller Files ist dann manuell zu machen), oder auch automatisch schliessen, dafür ist aber der csv Export anschliessend auch mit automatisch. 2026-07-02 16:35:16 +02:00
m.stangl 3c5d8be08d Doku angepasst 2026-07-02 14:06:44 +02:00
m.stangl f87260c605 .cfg Parser hinzu implementieren lassen. Spezifische Omniflo export routine die syncron in Lisp lief entfernt 2026-07-02 14:06:05 +02:00
m.stangl f73f0c123a omniflo csv Export lisp routine entfernt. 2026-07-02 14:04:32 +02:00
m.stangl 3869f8b624 omniflo unittest liest aktuell nur die json Exports von Bricscad 2026-07-02 14:03:55 +02:00
m.stangl 8a424d292e Dokumentation aktualisiert: omniflo csv Export raus. Alles nur noch über eine Funktion 2026-07-02 14:02:43 +02:00
m.stangl ca8543cca3 omniflo SumZeile jetzt nur über Python erzeugt. 2026-07-02 14:02:06 +02:00
m.stangl 05a7000d33 Gefällestrecke in Sivas und csv Exports eingebaut 2026-07-02 13:19:30 +02:00
m.stangl 3dd6e091e0 Gefällestrecke nach dem gleichen Muster bedaten wie die anderen Tests. Eingabedaten aus dem Test in json Datei gezogen. Ergänzung des Testsfalls durch Ergänzung des testsdata/*_tests.json möglich 2026-07-02 12:43:23 +02:00
y.wang 11555ace8e Attribut-Entities-Bug bei GF-Blockerstellung und VF-Blockerstellung in TEST-Funktionen beheben. 2026-07-02 10:12:30 +02:00
y.wang b915980540 die 3 Modus für Gefällestrecke wurden angepasst.Gemeinsamkeit aller Modi: Innere Elemente (Separator, Gefällebogen) werden immer per vollständiger KS_EIN→KS_AUS-3D-Rahmen-Kettung verkettet (insert-block-ks-to-ks) — nur bei AS/ES-Element (wegen des seitlichen Drehteller-Versatzes) wird die Position in X/Y und Z getrennt behandelt.Unterschied Modus 1/2 vs. Modus 3: In Modus 1/2 gibt es keinen vorgegebenen Endpunkt — die Endhöhe ist ein Ergebnis. In Modus 3 sind Start und Endpunkt (mit Höhen) vorgegeben, und die gesamte Geometrie (Winkel, Bogenauswahl, Segmentlängen) wird so berechnet, dass beide Punkte exakt erreicht werden. Test-Gefällestrecke wurde gebaut 2026-07-01 16:06:16 +02:00
y.wang 649857a9dd Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-30 12:29:38 +02:00
y.wang 0bee5ad8d0 die DWG sind bereinigt. Die bisherige positionsbasierte Block-Einfügung (Punkt + Winkel) wurde durch eine vollständige 3D-Frame-Kettung über KS_EIN/KS_AUS-Koordinatensysteme ersetzt, sodass beliebige räumliche Orientierungen korrekt durch die gesamte VarioFoerderer- und Gefaellestrecke-Anlage propagiert werden. 2026-06-30 12:29:33 +02:00
m.stangl 2e72f17806 Neue Testklassen für den Förderer gebaut: Status, Mathematik, ExportCSV und ExportSivas. Lisp/export.lsp wurde um VF_1, VF_2 Blöcke erweitert, um ein csv zu erhalten. Export_sivas und export_csv entsprechend um die nötigen Daten ergänzt 2026-06-30 11:21:06 +02:00
m.stangl b7025e5523 aktuelle OMniflo Export Liste als Referenz für den Test eingestellt 2026-06-30 11:19:01 +02:00
m.stangl 9b2bfed255 Debug Erzeugung aus dem Foerderer lisp Test entfernt 2026-06-30 11:05:16 +02:00
m.stangl 2009eb1a2c Readme der lisp Tests aktualisiert. Foerderer Tests korrigiert. Flaches .json benötigt. 2026-06-30 11:04:50 +02:00
m.stangl 8db7b2bfbf Veraltetes Menü Etagenförderer entfernt. Testdaten für den Förderertest wird jetzt aus .json Datei geladen. Testfunktionen des Förderers bauen jetzt auch Block um jeden Förderer, damit ein Export möglich ist . Fix einiger Funktionsaufrufe in den Varioförderer Funktionen. 2026-06-30 10:35:31 +02:00
m.stangl 68affdaa82 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-30 10:03:49 +02:00
y.wang 4a9d29f243 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-30 10:01:04 +02:00
y.wang d92b723e8c Blocknamen ohne Gradzeichen 2026-06-30 10:01:00 +02:00
m.stangl bf3996435a Weitere TOS Nummern für Zusatzmodul, Weichen Strecke und Automation in den Code für Export eingepflegt 2026-06-30 10:00:17 +02:00
m.stangl fe2e467888 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-29 17:08:42 +02:00
m.stangl 4863df7bac Sivas Export Format geändert 2026-06-29 17:08:37 +02:00
y.wang 8c7998c0cd Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-29 11:36:06 +02:00
y.wang 311d611f59 GF-Block-Erstellung und Attribute-Definition vollständig implementiert. 2026-06-29 11:34:57 +02:00
s.hensch 79f699432e Gradzeichen ° aus Dateinamen entfernt; Blöcke Separator und fehlende AS 30 Grad hinzugefügt 2026-06-29 10:25:11 +02:00
s.hensch 1328a6e933 Blöcke mit Koordinatensystemen versehen; Attribute mit Artikelnummern hinzugefügt; Weitere Blöcke hinzugefügt 2026-06-29 10:14:21 +02:00
s.hensch 9e79e21fb6 30 Grad ES und AS hinzugefügt 2026-06-26 14:16:11 +02:00
s.hensch 3a3d22d103 Aus- und Einschleuselemente für ILS in 2d und 3d hinzugefügt 2026-06-26 09:02:18 +02:00
m.stangl 20dd489468 omniflo Cleanup Routine rausgeworfen. Übernimmt jetzt das Zentralle all_tests.lsp. Ansonsten geht der omniflo csv Export nicht mehr. Kreisel Basisdatensatz entfernt. Nicht mehr in der Form zum test der Kreiselmodule nötig 2026-06-25 19:43:00 +02:00
m.stangl d961c81caf Koordinaten des Omniflo Tests berichtigt. Text der Sivasnummern noch in den Lisp Test dazu 2026-06-25 17:42:33 +02:00
m.stangl 5f4e73b3af bin/on_start.lsp geloescht + Dokumentation aktualisiert
on_start.lsp entfernt:
  Das Menue wird einmalig manuell per BricsCAD-Befehl _MENULOAD
  eingerichtet. BricsCAD speichert die Menuregistrierung dauerhaft.
  Ein externes Startup-Skript ist nicht mehr noetig.

Dokumentation aktualisiert:
  CLAUDE.md: Lademechanismus neu beschrieben mit _MENULOAD-Anleitung,
  Legacy-Liste bereinigt (on_start.lsp als entfernt eingetragen)
  Lisp/README.md: Ladereihenfolge durch Menueeinrichtungs-Anleitung
  ersetzt; ssg_load.lsp als Notfall-Alternative dokumentiert
  doc/LispTests.md: Verweis auf ssg_load.lsp und on_start bereinigt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:56:27 +02:00
m.stangl 376f2e1fc8 Revert: bin/on_start.lsp wiederhergestellt
Die Datei wurde faelschlicherweise als unreferenziert geloescht.
on_start.lsp wird von BricsCAD ueber die Startup-Suite (APPLOAD)
automatisch geladen und ruft (ssg-lib-startup) auf, welches per
MENULOAD die SSG_LIB.mnu laedt. Ohne diesen Ladevorgang steht das
SSG_LIB-Menue in BricsCAD nicht zur Verfuegung.

Grund fuer die Verwechslung: der Eintrag in der BricsCAD Startup-
Suite liegt in den lokalen BricsCAD-Einstellungen (ausserhalb Git)
und war daher per grep im Repository nicht auffindbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:49:28 +02:00
m.stangl 2c689cbcf1 Aufraeumaktion: bin/on_start.lsp geloescht, ssg_load.lsp Pfad-Fix
bin/on_start.lsp entfernt:
  Das Laden aller Module uebernimmt heute vollstaendig SSG_LIB.mnl,
  das automatisch beim MENULOAD geladen wird und ssg-ensure fuer
  Lazy-Loading sowie alle Kern- und Feature-Module direkt ausfuehrt.
  on_start.lsp war nirgendwo mehr referenziert (kein .bat, .mnu, .mnl
  oder .lsp rief die Datei oder ssg-lib-startup noch auf).

Lisp/ssg_load.lsp: Pfadermittlung robuster gemacht:
  base-path nutzt jetzt 1) DXFM_LISP, 2) findfile, 3) DWGPREFIX.
  Vorher schlug findfile "ssg_core.lsp" fehl wenn DXFM_LISP nicht im
  BricsCAD-Suchpfad war, load gab still den Fehlerstring zurueck und
  ssg-load-config crashte mit "no function definition".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:44:15 +02:00
m.stangl 84e91e557e Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-25 16:19:50 +02:00
m.stangl f417df4b54 Umgebungsvariablen nicht bei jedem Aufruf dauerhaft setzen. Ansonsten wird man bei jedem Startup damit belästigt. Nur einmal mit einem Schalter für das dauerhafte Setzen reicht 2026-06-25 16:18:56 +02:00
y.wang b9ca2820d4 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-25 15:40:14 +02:00
y.wang 0ea11fdac2 Block-Pfad-Ermittlung auf DXFMAKRO+DXFM_DIM umgestellt; Console bereinigt 2026-06-25 15:40:07 +02:00
m.stangl d408f3eea7 Testrunner geändert. Bei fehlgeschlagendem Test fehlt eine .json im test/Output Ordner 2026-06-25 15:36:14 +02:00
m.stangl 99eb5c9d86 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-25 15:33:11 +02:00
m.stangl 44762cce8f Funktion zur Prüfung der Vollständigkeit der benötigten DAteien hinzu. Test schlägt fehl, wenn diese nicht vorhanden sind 2026-06-25 15:33:03 +02:00
y.wang db0d9abb7a Startup-Alert bei VarioFoerderer entfernt. Alle verwendete Blöcke in VarioFoerderer.lsp und Gefaellestrecke.lsp sind aus data/ils/3D/ - DXFM_BLOCKS. 2026-06-25 14:30:03 +02:00
y.wang b0aeb04022 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-25 12:57:33 +02:00
y.wang b7499669af Die 2D/3D einzelnen Blockdateien für Gefaellestrecken und Varioförderer wurden eingepflegt. 2026-06-25 12:57:16 +02:00
s.hensch 2d4cb1cc36 [FIX] Menü zur Bearbeitung des Kreisels durch Doppelklick auf einen Kreisel wird nun wie erwartet aufgerufen, andere Blöcke und Textfelder und Objekte können nun trotzdem wie gewohnt durch einen Doppelklick mit den integrierten Bricscad Funktionen bearbeitet werden 2026-06-24 09:11:47 +02:00
m.stangl b60205013f xy Koordinaten waren falsch. Eingabe aus Beispiel neu definiert 2026-06-23 16:48:06 +02:00
m.stangl 64cd1612cb omniflo lisp funktionsaufrufe rausgeworfen und standardfunktionen verwendet. Ansonsten war Abhängigkeit zwischen Tests 2026-06-23 16:43:46 +02:00
m.stangl 10ed8b863b temp Dateien wieder weg 2026-06-23 16:42:03 +02:00
m.stangl 7aca5e2e0f Teile Vereinzeler links und rechts dazu 2026-06-23 16:41:25 +02:00
m.stangl f6c9b5ec00 Entladung in 3D von Tobie dazu 2026-06-23 15:43:54 +02:00
m.stangl 86d932fa23 Eigene Routine um flache json kv Files zu parsen. 2026-06-23 15:06:21 +02:00
m.stangl 676117fe22 alte Testdatei mit Varioförderern gelöscht 2026-06-23 15:04:27 +02:00
m.stangl 1f7aeb420d Ids werden jetzt in Bricscad von einer Lisp Funktion in Form einer aufsteigenden Nummer erzeugt 2026-06-23 10:11:47 +02:00
m.stangl abc7d5ab77 der Lisp Omniflo Test verwendet jetzt wirklich alle existierenden Omniflo Teile die da sind. 2026-06-22 11:19:27 +02:00
m.stangl fed941d7b1 Neuer Abschnitt 'alltests.json — Testregistry' erklaert Zweck, Format und save-Optionen. Workflow-Abschnitt aktualisiert: korrekte Beschreibung von SSG_RUN_ALL_TESTS, Vergleichstabelle vs. Einzeltest, und Namenskonventionen fuer LISP-Datei, Befehl und Export-Funktion. 2026-06-22 10:42:20 +02:00
y.wang 73528fa574 rm ils_library.dxf 2026-06-19 21:23:17 +02:00
y.wang 6be04e11ff DXF Reinigung 2026-06-19 21:09:29 +02:00
y.wang 250ee0d788 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-19 21:07:41 +02:00
m.stangl 2d6cb788cf Neue Positionen für die Kreisel im Test festgelegt. Weniger Überlappungen und leichter durch einen Blick von oben und der seite zu prüfen. 2026-06-19 21:06:02 +02:00
m.stangl 8d32102531 Testmodule aus alltests.json laden statt hartcodierter Liste
SSG_RUN_ALL_TESTS liest die Testliste jetzt aus tests/alltests.json.
Pro Test konfigurierbar: JSON-Export (immer), DXF, DWG oder kein
Speichern der Zeichnung ueber das Feld 'save'.
2026-06-19 21:01:47 +02:00
m.stangl c01dad28f3 Testroutinen auf kseinaus umbenannt und aktualisiert
test_ks.lsp in test_kseinaus.lsp umbenannt und alle Testroutinen
(foerderer, kreisel, omniflo) sowie run_tests.bat und README
entsprechend angepasst.
2026-06-19 21:00:45 +02:00
y.wang dea039f349 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-19 14:02:49 +02:00
y.wang cab9db526e die Variofoerderer.lsp umstruktiert. Gefaellstrecke kann nach einem Linienzug modeliert werden. Bei Kreiselinstert wurde die Blöck in 2D Pfad geladen. 2026-06-19 14:02:45 +02:00
m.stangl 21682576c4 Bugfixes in LISP-Testrunnern (Foerderer, KS, SAVEAS)
- test_foerderer.lsp: foerderanlage-einfuegen -> variofoerderer-einfuegen
  mit korrekten Parametern (seite, vf-nummer, n-scanner)
- test_foerderer.lsp, test_kreisel.lsp, test_ks.lsp: SAVEAS "DXF" durch
  SAVEAS "" ersetzt (BricsCAD erkennt Format an .dxf-Endung automatisch)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-18 16:05:50 +02:00
m.stangl bd053d76d3 Kreisel Script-Funktionen und flaches JSON-Testformat
- kreisel-insert-script und kreisel-connect-script in KreiselInsert.lsp
  fuer nicht-interaktives Einfuegen (Tests, Automatisierung)
- kreisel_tests.json von verschachteltem auf flaches JSON-Array umgestellt
  (kompatibel mit omni:load-json)
- test_kreisel.py an neues JSON-Format angepasst (direkte Felder statt
  nested expect/attributes)
- conftest.py: Leere kreisel_results.json wird jetzt korrekt uebersprungen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-18 16:05:40 +02:00
y.wang fc38d4740f Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-18 15:21:14 +02:00
y.wang 607ec3bd47 Merge 2026-06-18 15:21:10 +02:00
s.hensch d9962c96b1 2D ILS Dateien in neues 2D Verzeichnis verschoben 2026-06-18 15:16:06 +02:00
y.wang ee6ec9550f Die Logik für EtageVariofoerderer also zur Verbindung Zwei Kreisel übereinander wurde gebaut, mit AS- und Einelement 30° 2026-06-18 15:15:36 +02:00
m.stangl 8894cf9e4c Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-18 14:57:17 +02:00
m.stangl 669545761d neues Testsystem. Dazu Doku erstellt wie es funktioniert in dewr README.md Aufruf aller Tests im Bricscad durch eigenes Menü. 2026-06-18 14:57:03 +02:00
s.hensch 9ea5e1bbae Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-06-18 14:45:38 +02:00
s.hensch 3d0e4e6a80 3D und 2D bzw 2.5D mit identischen Koordinatensystemen hinzugefügt 2026-06-18 14:45:05 +02:00
m.stangl 91530e9d99 Menü für Lazy call umgebaut 2026-06-18 14:16:38 +02:00
y.wang 937d7b0e13 Der Aufruf-Befehl in Bricscad für Varioförderer.lsp wurde von FOERDERANLAGE auf VarioFoederer geändert. Die Block-Erstellung und die Attribut-Definition wurden integriet. 2026-06-18 12:31:38 +02:00
y.wang 714dc65f45 Alle Objekte sind Ende-an-Anfang miteinander verbunden. 2026-06-18 09:45:43 +02:00
y.wang 241cdccc26 Ordner Aufräumen 2026-06-18 08:46:42 +02:00
s.hensch ec55944721 Orderstruktur der Library in 2d und 3d unterteilt, Dateien entsprechend verschoben, Pfade in Variablen im gesamten Verzeichnis entsprechend korrigiert; Vario Vertikalbögen für 2d und 3d erzeugt; 2026-06-18 07:55:01 +02:00
m.stangl eef9a7ff25 Pfade mit Leerzeichen werden sonst nicht richtig aufgelöst 2026-06-17 15:02:18 +02:00
s.hensch 842e07ba76 Setenv.bat erweitert, dass auch V22 erkannt wird und die Möglichkeit zum Überladen von Umgebungsvariablen durch _setenv.bat, die nicht eingecheckt wird 2026-06-17 10:51:32 +02:00
m.stangl c650ea9b7c doc ergänzt 2026-06-16 17:42:14 +02:00
m.stangl a11d0807d2 Höhe, Drehung und Id in allen Omniflo Elementen auch setzen 2026-06-16 17:40:58 +02:00
m.stangl 1f00bb5c13 Startup Skripte entfernt. Werden jetzt über dynamische Menüs erledigt 2026-06-16 17:16:07 +02:00
m.stangl 0b501e5ea5 Anwendung der Erzeugung einer Id für jedes Element 2026-06-16 17:14:19 +02:00
m.stangl d1368dbb01 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-16 17:12:31 +02:00
m.stangl 13e4ebb5fc Lisp Routine erstellt, die jedem Element beim Export eine Id gibt. Menüs dynamisch gemacht, d.h. die Lisp Routinen werden erst geladen, wenn sie vom Nutzer per MEnü aufgerufen wurden 2026-06-16 17:12:21 +02:00
y.wang c196602e50 Merge 2026-06-16 12:53:50 +02:00
m.stangl f75a5ad0b1 Doppeltes Laden vom on_start.lsp entfernt 2026-06-15 16:09:02 +02:00
m.stangl 176b775050 Claude und Readme aktualisiert 2026-06-15 15:54:22 +02:00
m.stangl 43aa34674f Veraltete Angaben in Claude.md berichtigt. Dokumentation erneuert 2026-06-15 15:50:29 +02:00
m.stangl c915a4031f Contextmenü für die Rechte Maustaste eingeführt um Elemente zu bearbeiten 2026-06-15 14:30:55 +02:00
m.stangl b829b7e961 Attribut Winkel war noch nicht unsichtbar 2026-06-15 14:26:49 +02:00
m.stangl 59afa230c3 Alle Attribute entsprechend der Sivasnummer hinzugefügt. Alle als Unsichtbar und Konstant deklariert 2026-06-15 12:52:46 +02:00
m.stangl 2ceea62262 set_attributes.py baut jetzt einen Block der bei Klick alle seine Attribute anzeigt. 2026-06-12 17:57:48 +02:00
m.stangl b9a33def8b Doku der Tools aktualisiert 2026-06-12 17:57:07 +02:00
m.stangl 2f583a96cb Lisp/README.md als Doku der LispFunktionen erneuert. set_attr.py baut jetzt einen einzigen Block der alle Geometrie und die Attribute enthält. 2026-06-12 17:25:22 +02:00
m.stangl 7a13171714 logs/ und results/ zur .gitignore hinzugefuegt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 11:29:18 +02:00
m.stangl 041d292681 Omniflo-Testsuite hinzugefuegt (Python + AutoLISP)
tests/test_omniflo.py (350 Zeilen):
  Python-Tests fuer den Omniflo Bogen/Weiche Export. Testet:
  - Unit-Tests fuer build_bogen_merkmale / build_weiche_merkmale gegen
    Testdefinitionen aus omniflo_tests.json (kein BricsCAD erforderlich)
  - Merkmale-Werte gegen den JSON-Katalog (omniflo_boegen/weichen.json)
  - Korrekte Anzahl und Reihenfolge der Elemente in process_blocks()
  - CSV-Ausgabeformat (Header, Spaltenanzahl, Merkmale als JSON)
  - Integrationstest: liest eine tatsaechliche CSV aus einem BricsCAD-
    Lauf (falls DXFM_TESTOUT gesetzt und Datei vorhanden)
  Importiert direkt aus lib/export_csv.py (build_lookup, process_blocks,
  build_bogen_merkmale, build_weiche_merkmale, load_json).

tests/test_omniflo.lsp (173 Zeilen):
  AutoLISP-Tests fuer omni:insert-bogen und omni:insert-weiche.
  Prueft Block-Einfuegung, Attribut-Setzung (HOEHE, DREHUNG, ARTINR)
  und Fehlerverhalten bei ungueltigen Parametern. Laeuft direkt in
  BricsCAD via (load "tests/test_omniflo.lsp").

tests/testdata/omniflo_tests.json (114 Zeilen):
  Testdaten fuer test_omniflo.py: Definiert Testfaelle fuer Boegen
  (je Winkel: 22.5, 45, 67.5, 90, 180) und Weichen (90°, 45°, koerper,
  parallel) mit erwarteten Merkmale-Feldern und Beispiel-SivasNr.

tests/conftest.py:
  Pytest-Fixtures fuer den Testlauf: data_dir, testdata_dir,
  output_dir und omniflo_lookup (laedt Katalog-JSON falls vorhanden,
  sonst leeres Dict als Fallback).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 11:27:08 +02:00
m.stangl 1f2ebe5c86 export_csv.py und omniflo_utils.py bereinigt und korrigiert
lib/export_csv.py:
  - CSV-Header vereinfacht: NachbarIds, Planquadrat und rotation-Spalten
    entfernt (nicht im Sivas-Format benoetigt). Anzahl-Spalte auf festen
    Wert 1 gesetzt.
  - format_planquadrat() entfernt (war unused nach Header-Aenderung).
  - process_blocks(): elem_nr startet bei 0 statt -1 (erster Block war
    mit Nummer -1 ausgegeben worden).
  - build_bogen_merkmale(), build_weiche_merkmale(): KurvenWinkel und
    Radius werden jetzt explizit als float() gecastet, um sicherzustellen
    dass JSON-Werte aus dem Katalog als Zahl und nicht als String landen.
  - Felder nachbarids, planquadrat, rotation aus den item-Dicts entfernt.

lib/omniflo_utils.py:
  - import_element_as_block(): prueft jetzt zuerst ob eine Block-
    definition mit dem Zielnamen in der Quelldatei existiert (erzeugt
    durch set_attributs.py). Falls ja, wird diese direkt importiert
    statt des gesamten Modelspace. Das verhindert doppelte Entities wenn
    set_attributs.py die Geometrie bereits in einen Block gefasst hat.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 11:26:41 +02:00
m.stangl 9f78ff7f0a Alle LISP-Module auf ssg-cfg-or umgestellt (hardcodierte Konstanten entfernt)
Alle bisher hart codierten Geometrie-, Farb- und Default-Werte in den
LISP-Modulen werden jetzt ueber ssg-cfg-or aus component_defaults.json
gelesen (mit Fallback auf den bisherigen Wert als Sicherheitsnetz).

Lisp/KreiselInsert.lsp:
  - Geometrie-Konstanten: *kreisel-durchmesser*, *kreisel-pin-abstand*,
    *kreisel-default-laenge*, *kreisel-default-hoehe*, *eckrad-default-hoehe*
  - Beschriftungs-Einstellungen: Texthöhe, Farbe, Abstand
  - Linienfarben (color_linie_1/2, color_pin) fuer Layer/CECOLOR
  - Toleranzen: toleranz_kollinear, toleranz_winkel

Lisp/OmniModulInsert.lsp:
  - Default-Werte fuer HOEHE und DREHUNG beim Einfuegen und Bearbeiten
  - Textgroessen (textHeight, textGap) fuer Vorschau-Dialog
  - Max-Laengen fuer AP60, AP110, APG110

Lisp/VarioFoerderer.lsp:
  - staustrecke-basis, FESTE_HORIZONTAL
  - bogen-winkel Liste (zweifach, in Bibliotheks-Extraktion und Berechnung)
  - gefaelle_winkel (3°) an allen Stellen im Anlagen-Aufbau
  - skalierung_basis fuer Block-Skalierung
  - separator_block_dx/dz, station_block_dx/dz fuer Blockeinfuegung

Lisp/Gefaellestrecke.lsp:
  - Default-Wert fuer deltaL, default_winkel
  - separator_breite fuer Laengenberechnung

Lisp/export.lsp:
  - default_hoehe fuer HOEHE-Attribut-Fallback in Bogen/Weiche/Gerade
  - default_gerade_laenge fuer Laenge-Fallback
  - mm_pro_meter (1000.0) fuer Umrechnung mm->m bei Laengenangaben

Lisp/ssg_dialog.lsp:
  - dialog_preview_bg_color (-18) fuer fill_image Hintergrundfarbe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 11:26:22 +02:00
m.stangl cc301b318e JSON-Konfigurationssystem in ssg_core.lsp eingefuehrt
data/json/component_defaults.json: Neue zentrale Konfigurationsdatei
mit Standardwerten fuer alle Komponenten (kreisel, eckrad, omniflo,
vario, gefaelle, infrastruktur). Bisher waren Konstanten (Masse,
Farben, Toleranzen, Defaults) hart im LISP-Code eingebettet.

Lisp/ssg_core.lsp: JSON-Parser und Config-Zugriff hinzugefuegt:
  - ssg-read-file-lines: Datei zeilenweise einlesen
  - ssg-cfg-trim, ssg-cfg-split-comma: String-Hilfsfunktionen
  - ssg-cfg-parse-value, ssg-cfg-parse-array: JSON-Wert-Parser
    (unterstuetzt String, Zahl, Boolean, Array, null)
  - ssg-cfg-parse-section: JSON-Sektion zu Assoziationsliste parsen
  - ssg-load-config: Laedt component_defaults.json in *ssg-config*
  - ssg-cfg: Wert aus *ssg-config* lesen, nil wenn nicht vorhanden
  - ssg-cfg-or: Wert aus Config lesen mit Fallback-Default

Lisp/ssg_load.lsp: (ssg-load-config) wird direkt nach dem Laden von
ssg_core.lsp aufgerufen, sodass die Config beim Laden aller weiteren
Module bereits verfuegbar ist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 11:25:54 +02:00
m.stangl fd58ef612f attradd.py und add_attr.bat in set_attributs.py/.bat umbenannt
lib/attradd.py -> lib/set_attributs.py: Name besser passend zum
Skript-Zweck (setzt Attribute, analog set_einfuegepkt / set_koords).
bin/add_attr.bat -> bin/set_attributs.bat entsprechend angepasst.

cfg/attradd.cfg: Kommentar auf neuen Skriptnamen aktualisiert.
HOEHE/DREHUNG-Eintraege aus [bogen] und [weiche] entfernt, da diese
Attribute jetzt dynamisch via ssg-cfg-or aus component_defaults.json
bezogen werden (nicht mehr als statische ATTDEF-Defaults noetig).
Ebenso RADIUS aus [weiche] entfernt (war redundant zu KurvenWinkel).

doc/tools.md und CLAUDE.md: Alle Verweise auf attradd.py auf
set_attributs.py aktualisiert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 11:25:28 +02:00
m.stangl 9fe08411df Update der Attribute Höhe und Drehung vor Aufruf der Exports durchgeführt 2026-06-11 12:08:40 +02:00
m.stangl 0e8d264b6a eigene Export Routine aus den Tests extrahiert 2026-06-11 12:03:23 +02:00
m.stangl e4564be24c Omniflo Einträge von Verbindern und Bögen für Weichen Ergänzt 2026-06-11 11:15:13 +02:00
m.stangl a2d6571ab9 Omniflo csv Export erste Fassung. Höhe und Winkel in die Attribute ergänzt. Dcl Dialoge ermöglichen Eingabe von Höhe und Drehung. Neuer Menü-eintrag bearbeiten in Omniflo dazu. 2026-06-10 17:47:26 +02:00
m.stangl f05340ed59 Omniflo Export funktion geschrieben 2026-06-10 17:22:02 +02:00
m.stangl 22a358554d Pyrx Startup skripte und python Element entfernt, da Schwierigkeiten mit Kompabilitäten 2026-06-10 16:58:12 +02:00
m.stangl 1bda736606 Funktion hinzugefügt um die Quellen der Menüeinträge und Funktionen zu finden. menu-inventory.lsp 2026-06-10 16:57:06 +02:00
m.stangl fb64ea1b16 PYHTONHOME und PYTHONPATH aus Umgebung rausgeworfen. Wenn die .venv verwendet wird ist das ein problem. 2026-06-10 16:12:54 +02:00
m.stangl 40b430ee73 Startup Skript so modifiziert, dass Lisp files als Fallback geladen werden 2026-06-03 10:06:09 +02:00
m.stangl b8842957fc aktuellsten Stand eingepflegt. Probleme mit dem PYLOAD noch nicht bereinigt 2026-06-03 09:16:49 +02:00
y.wang 604cdaf81f Die Module für Gefaellestrecke wurde gebaut. 2026-06-02 15:16:24 +02:00
m.stangl f1c3e5f060 Startup-Sequenz geändert, um ein Debugfile möglichst früh zu haben 2026-06-02 13:14:00 +02:00
y.wang d2ab6ff4e2 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-02 10:00:42 +02:00
y.wang c014ef2f12 die Fehler in VarioFoerderer.lsp korrigiert. alle in ILS-LSP verwendete Block Dateien in data/ils/ konsolidiert. 2026-06-02 10:00:36 +02:00
m.stangl b2dbd8c1c3 vereinfachte Möglichkeit BRX Plugin zu laden über den .venv Pfad. 2026-06-01 19:24:15 +02:00
y.wang acf9f666cc Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-06-01 14:52:20 +02:00
y.wang b54f2e7b46 Die KS-EIN und KS-AUS für Ein- und Ausschleuselemente wurde in Library angepasst. 2026-06-01 14:52:14 +02:00
m.stangl d0373d09f3 Omniflo Boegen und Weichen auch durch .py erzeugen und ändern. 2026-06-01 11:08:19 +02:00
m.stangl 35e4e707aa Beschreibung von Claude für das PRojekt ergänzt, da in zukunft mit python gearbeitet wird 2026-06-01 11:07:13 +02:00
m.stangl 732daedadd lib/utils.py in lib/omniflo_utils.py umbenannt. elemente/kreisel.py verwendet jetzt auch die elemente/utils.py routinen 2026-06-01 10:27:38 +02:00
m.stangl 4bafc4443f eigenen Test geschrieben, der die Elemente im Varioförderer an den K_EIN und K_AUS Punkten aufreiht, so dass man eventuelle Fehler sehen kann. 2026-06-01 10:24:24 +02:00
m.stangl 676224b172 cache der aus den Koordinaten K_AUS und K_EIN geladenen Punkte eingeführt 2026-06-01 10:23:43 +02:00
m.stangl c30d2c51b9 Python Routinen mit PyRx als Ersatz für die .lsp Routinen verwendet. 2026-06-01 10:22:24 +02:00
m.stangl be69281af5 Varioförderer Test in tests.lsp wieder rein 2026-05-29 13:28:08 +02:00
m.stangl e41d6456d4 test runner dazu 2026-05-28 17:37:04 +02:00
m.stangl 3aed8fe176 debug beim Varioförderer dazu. dbgreturn routine gibt den Wert zurück. neues Test Konzept für unsere lisp Funktionen implementiert 2026-05-28 17:34:02 +02:00
m.stangl 909f780bf0 Testkonzept für unsere Lisp files überlegt 2026-05-28 17:31:11 +02:00
m.stangl dd90c3b97f Allgmeine PRojektbeschreibung für Claude dazu 2026-05-28 16:11:38 +02:00
m.stangl 5f179da36f Maße von AUS und EIN schleuselement festgestellt 2026-05-28 15:50:18 +02:00
m.stangl 765bf1f975 Gefällestrecken der Varioförderer werden jetzt auch aus den Blöcken der ILS Bibliothek gezogen, nicht mehr aus den EInzeldateien. 2026-05-28 15:23:20 +02:00
y.wang 96c00d20fa Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-28 14:47:41 +02:00
m.stangl 18c2aa0a60 Eckrad Befehle modifziert. Automatische Nummernvergabe in lisp impl. 2026-05-28 14:47:12 +02:00
y.wang 2400c20e37 :wqerge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-28 14:45:39 +02:00
y.wang 3b3cc2a005 Die horizontale Variobögen und Gefällebögen dazu, und die Varioförderer Lisp angepasst. 2026-05-28 14:45:34 +02:00
m.stangl 788593599a Entwicklungsplan nach Gespräch angepasst 2026-05-28 11:28:40 +02:00
m.stangl e85fefa7d3 Eckrad wird eingefügt. 2026-05-26 14:17:38 +02:00
m.stangl 590e197557 lisp dbg library um ein paar Einträge gefixt. dbg lib wird geladen und initalisiert. .dbg file erscheint im logs Ordner. Fix zu den verlorenden Attributen des Kreisels 2026-05-26 13:43:43 +02:00
m.stangl 552da72011 erste fassung einer .dbg library für lisp Programme erzeugt 2026-05-26 12:18:49 +02:00
m.stangl 7255d0b291 Fix der Höhen und verformentn 2026-05-20 18:54:34 +02:00
m.stangl 4544b7c56e Readme um aktuell vorhandenes Menü ergänzt 2026-05-20 17:57:11 +02:00
m.stangl 4eb5fc92fc Merge gemacht. Versuch eines Tests der lisp Routinen erstellt 2026-05-20 16:31:51 +02:00
s.hensch c2c31898e8 Neues ILS Library File angelegt für ALLE ILS DWG Komponenten in2d und 3d; Vario Bögen 3d vervollständigt; Ein- und Ausschleuselemente in 2d und 3d hinzugefügt(3d AS/ES: sehr große datenmenge in Modell sollte reduziert werden) 2026-05-20 15:33:52 +02:00
y.wang 4253158641 fehlende Variablen für draw - module wurde ergänzt 2026-05-20 09:09:49 +02:00
y.wang bfd55b2589 Merge 2026-05-20 08:59:28 +02:00
y.wang 9ce6748020 Kreisel wurde mit Beschriftung erstellt und Die Höhe des Basispunktes bestimmt die Höhe des neuen Kreisels. 2026-05-20 08:55:05 +02:00
m.stangl 156c2029a5 Undo Funktion mit ssg-start und ssg-end verwendet. Routinen standardisiert 2026-05-18 17:43:08 +02:00
m.stangl e801c84439 Erste FAssung für ein Makro für die Geraden erzeugt 2026-05-18 13:50:23 +02:00
m.stangl aeef67f2c3 Fix Pin Kreisel hatte nur eine Linie 2026-05-18 12:15:15 +02:00
m.stangl f18a038ff5 Eckrad Erzeugung dazu 2026-05-17 23:55:26 +02:00
m.stangl 92f20e7833 eigenes Menü zum Einfügen eines neuen Kreisels und zum Verbinden 2026-05-15 15:33:04 +02:00
m.stangl 86291d5479 Kreisel Block enthält jetzt alle Attribute die wir auch in die csv Datei schreiben wollen. Änderung des Blocks führt zum auslesen der Attribute und zum Neuerzeugung mit den bereits gesetzten Attributen nur mit neuer Länge. 2026-05-15 15:17:11 +02:00
m.stangl d8283437e8 erste allgemeine Fassung einer Kreiselroutine für horizontale und vertikale Kreisel. Allgemeine Deklaration aller Definitionen am Anfang des Blocks 2026-05-15 15:07:27 +02:00
m.stangl aa387dbcdd Walz Funktionen ssg-start und ssg-end für Undo und Error Handling eingebaut 2026-05-15 13:08:34 +02:00
m.stangl c1fa63f067 Fix c:KreiselConnect: abstandStr, typNum, newBasePoint als lokale Variablen ergänzt. Wären sonst global gewesen. dentify-connection-point: insertPoint, pickX, pickY, tolerance, type als lokale Variablen ergänzt ; calculate-new-basepoint: insertPoint als lokale Variable ergänzt; LAYER S_LP: Layername S_LP nach Farbwert eingefügt; [200 2026-05-15 12:52:17 +02:00
m.stangl b0a178829a Attribute setzten umbenannt 2026-05-15 12:25:01 +02:00
m.stangl c0dbae422a Sinn des Dokuments eingeschrieben 2026-05-15 12:05:27 +02:00
m.stangl 20bd278bea Überschriften ergänzt 2026-05-15 12:02:57 +02:00
m.stangl 5c92c98f7e Beispieldateien der Übersicht für alle Einfügepunkte und alle Koordinatensysteme in Doku dazu 2026-05-15 12:01:20 +02:00
m.stangl c4901aeff3 Doku um Screenshots der Ergebnisse ergänzt 2026-05-15 11:46:58 +02:00
m.stangl fa01e4cbc2 Sivas Export Routine als python file 2026-05-15 11:20:17 +02:00
m.stangl 75bd20a46b PYthon Programm für einfachen Stücklistenexport 2026-05-13 23:37:48 +02:00
m.stangl 6c0392da3c EXPORT für Sivas CSV und einfache Stückliste in je eigenem Menüpunkt aufrufbar 2026-05-13 23:35:41 +02:00
m.stangl 91773ac615 Routine um Attribute in jedem Omniflo .dxf File zu setzen. 2026-05-13 23:25:14 +02:00
m.stangl d454ad4149 Python Funktion um aus der durch die Lisproutine exportieren CSV eine Sivas TOS Datei mit enthaltenem json zu machen 2026-05-13 23:24:20 +02:00
m.stangl d381135995 Erste Fassung von ExportCSV in Lisp impl. 2026-05-13 23:22:58 +02:00
m.stangl 2e4b149896 Alle Koordinatensysteme K1,K2,K3 und K4 erzeugt und im .dxf der omniflo gesetzt 2026-05-13 15:16:40 +02:00
m.stangl 7573137ad1 kleinere Korrektur für Dreifach, Delta und Sternweiche zur Bestimmung von K2 und K3. NEuer Algorithmus 2026-05-13 15:12:59 +02:00
m.stangl bf8b7756ea K2 für die Bögen werden jetzt richtig gesetzt 2026-05-13 12:08:48 +02:00
y.wang 854b5e3bd5 Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-12 18:14:58 +02:00
y.wang d431dc507b getpoint Z-Wert Problem gelöst 2026-05-12 18:14:50 +02:00
m.stangl 438a18fd92 K1 bei allen Omniflo Bögen und Weichen eingefügt 2026-05-12 17:28:46 +02:00
m.stangl 89dccc139f K2 der Bögen wird erzeugt 2026-05-12 17:28:11 +02:00
m.stangl 69d71ff741 Erzeuge per Programm ein Koordinatensystem in einem Block und benennen ihn nach Wahl. Testfunktion zur Erzeugung und zum wiederauslesen impl. 2026-05-12 14:47:16 +02:00
m.stangl a61081168b Funktion zur Erzeugung von Koordinatensystemen gebaut um eindeutig den Ein und Auslauf von Bögen und weichen zu erhalten. 2026-05-12 13:56:16 +02:00
m.stangl 530aa0ca02 Doku zum Programm zum setzen des Einfügepunktes 2026-05-12 12:26:23 +02:00
m.stangl e8c6674c64 Programm zum setzen der Einfügepunkte berichtigt 2026-05-12 12:25:34 +02:00
m.stangl 482bad99d4 Einfügepunkt in den .dxf Dateien mit Skript geändert 2026-05-11 15:57:28 +02:00
m.stangl 32fac7a71e Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-11 15:56:26 +02:00
m.stangl c677f7482e neue Python Funktion zum setzen des Einfügepunktes an die korrekte Stelle für Oflo Bögen und Weichen 45/90 Grad 2026-05-11 15:56:20 +02:00
y.wang eb9edaca3c IF-Abfrage war falsch und wurde korrigiert. 2026-05-11 12:17:24 +02:00
y.wang 3d944f85dc fassung gemerged 2026-05-11 12:03:59 +02:00
y.wang 392f996f33 Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-11 11:40:47 +02:00
y.wang 16f0c6488a AN8 und SP8 für Kreisel als Einzelne DWG Datei gespeichert. 2026-05-11 11:40:12 +02:00
m.stangl 241d24c1d2 Oberfläche für Weichen dazu. Funktion dahintergehängt das eventuell vorhandene .dxf lädt 2026-05-08 15:25:04 +02:00
m.stangl a2cdc4e87b Omniflo Weichen Interface gebaut 2026-05-08 14:36:42 +02:00
m.stangl 1deaa2e361 Fix beim laden der json files 2026-05-08 13:35:33 +02:00
m.stangl cf17e92056 Saveload deaktiviert. Beim Laden möchte ich Fehler sehen, wenn welche da sind 2026-05-08 13:32:05 +02:00
m.stangl 34700d30ba If Verzweigung hatte Fehler 2026-05-08 13:27:39 +02:00
m.stangl 8aa0e4e6af Omniflo Modul wurde nohc nicht geladen 2026-05-08 13:23:07 +02:00
m.stangl 2c4b708233 Omniflo Dialoge mit dcl Datei erzeugt 2026-05-08 13:16:09 +02:00
m.stangl cc229617a5 Parser für die .json Datei in der aktuellen Form als key:value geschrieben um Omniflo Bögen und Weichen einzulesen. Schnittstellenfunktionen zum Filtern dazu 2026-05-08 12:55:07 +02:00
m.stangl bb7e3b1586 Grenzen und Ids von Omniflo und ILS als .json Files hinzugefügt. 2026-05-08 12:25:08 +02:00
y.wang f91e098555 zentrale Skripts SSG_LOAD zum Laden aller LSP Librarys 2026-05-08 12:02:41 +02:00
y.wang 1e93a94474 Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-08 11:42:38 +02:00
y.wang 57a33df110 Kreisel in eigenen Funktion durchführt. 2026-05-08 11:42:28 +02:00
m.stangl a3011e7c2a Aus den Lisp Daten unter M:\ACADSST\MENU eine neue Standardlibrary mit Codedoku extrahiert 2026-05-08 11:19:36 +02:00
m.stangl 9fee0e1eb4 call von Test Funktionen dazu in die Menüs. Aufruf einer externen Python Funktion . Rückgabe von Ergebnissen über eine Datei. 2026-05-07 17:53:51 +02:00
m.stangl 4f20325620 Menü soll ILS und Omniflo nebeneinander enthalten 2026-05-07 17:37:33 +02:00
m.stangl fd3d95fcc2 cui Files nicht mit verwalten 2026-05-07 17:36:43 +02:00
m.stangl 2cdf9434e5 Omniflo Dummy Routinen in eigene Datei getan 2026-05-07 17:36:26 +02:00
m.stangl d5856b5d9f Ladefehler der Menü werden abgefangen, ohne den gesamten Sratup abzubrechen. Null Check üfr SRCHPATH 2026-05-07 16:23:05 +02:00
m.stangl 93bfbbb77b identify-connection-point repariert: Fehlende < Vergleiche ergänzt: (< (abs ...) tolerance) statt (and (abs ...) tolerance). Extra-Klammer in Zeile 136 entfernt, die das defun vorzeitig beendet hat. Alle 8 cond-Klauseln korrigiert. 2026-05-07 16:21:30 +02:00
m.stangl b776f5a77a aus Lisp Folder on_start.lsp entfernt und in bin verschoben 2026-05-07 16:13:58 +02:00
m.stangl dc74ebc22e starupt.scr in bin dazu 2026-05-07 16:13:27 +02:00
m.stangl 0dfcad4e83 Hartcodierte Werte vorerst weiter verwenden 2026-05-07 15:55:03 +02:00
m.stangl efa79745fa Startup Skript in .lsp wird beim Starten des CAD mit aufgerufen, so dass die Menüs gebaut werden 2026-05-07 15:53:34 +02:00
m.stangl aac7d7c1bb Menüeintrag und Dummy Commandos unter SSG_LIB_Commands.lsp dazu 2026-05-07 15:45:26 +02:00
m.stangl f3bbd2f974 Datei wurde beim Foerdertest gleich 2 mal gespeichert. Einmal reicht. 2026-05-07 15:11:35 +02:00
m.stangl 94c52c33b6 startup Skript für Briscad dazu 2026-05-07 14:35:05 +02:00
y.wang dd3e871efe Die Fehler bei Förderertest korrigiert. 2026-05-07 12:18:51 +02:00
m.stangl 1d45573cc2 erge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-07 07:17:56 +02:00
m.stangl 56b8fd7ee6 korrigierte Fassung für z-Koordinaten rein 2026-05-07 07:17:42 +02:00
m.stangl ad72c45cf2 Korrektur der z-Koordinaten durch Claude 2026-05-06 19:47:14 +02:00
s.hensch df9d4033fc Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-06 16:46:15 +02:00
s.hensch 4ce066cf2f Motor und Umlenkstation mit Koordinatensystemen versehen 2026-05-06 16:46:04 +02:00
m.stangl 1d62b20b0a Funktionen zum Auslesen von KS_AUS und KS_EIN impl. Die Länge der Förderstrecke kann nun variabel eingestellt werden 2026-05-06 15:38:05 +02:00
s.hensch 1a4eae7044 Vario-Bögen für 39 und 51 grad auf/ab mit Koordinatensystemen hinzugefügt 2026-05-06 13:00:05 +02:00
s.hensch c05462a8d1 gitignore um nicht notwendige lock und temp Dateien von Bricscad bzw AutoCAD erweitert 2026-05-06 11:56:57 +02:00
s.hensch 22fc4c4d0d Sammlung für neue Vario-Blöcke mit Koordinatensystemen hinzugefügt für die weitere Verwendung in den LISP Skripten 2026-05-06 11:53:01 +02:00
s.hensch 61c2f78ed3 Merge branch 'master' of https://gitea.schoenenberger.de/m.stangl/dxfmakros 2026-05-06 11:46:56 +02:00
s.hensch 02f61540b2 Für das organisieren der Blöcke wird /data nun nicht mehr in .gitignore geführt 2026-05-06 11:46:53 +02:00
m.stangl 6719a3e9fa .gitignore dazu 2026-05-06 11:42:12 +02:00
m.stangl 2db73adb61 data Ordner aus plant2dxf eingecheckt zum Test des Einbaus von KOSs 2026-05-06 09:34:34 +02:00
m.stangl f07a759f9a Readme.md korrigiert 2026-05-06 07:12:42 +02:00
m.stangl d3b3cee939 Makroaufruf zum automatischen Testen des Varioförderers dazu: FOERDERTEST 2026-05-05 17:41:12 +02:00
m.stangl 812c6208e1 Arbeite vorerst weiter mit den vorher hartcodierten Werten 2026-05-05 17:12:53 +02:00
m.stangl b4724696a2 Flag ob man die Hartcodierten Werte der Bogenmaße oder die dynamische Berechnung haben möchte 2026-05-05 17:01:46 +02:00
366 changed files with 6324316 additions and 949 deletions
+128 -10
View File
@@ -1,8 +1,21 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# AutoCAD lock / tmp
*.dwl
*.dwl2
*.ac$
*.bak
*.sv$
*.tmp
# Distribution / packaging
.Python
build/
develop-eggs/
@@ -20,10 +33,18 @@ share/python-wheels/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
@@ -37,8 +58,76 @@ coverage.xml
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
@@ -46,25 +135,54 @@ venv/
ENV/
env.bak/
venv.bak/
.spyderDXFMAKRO
.spyDXFMAKRO
.ropeDXFMAKRO
_setenv.bat
# cui folder for briscad
aiassist_next_command/
aiassist_other_relevant_commands/
aiassist_personal_commands/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
.pdm.toml
__pypackages__/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
/site-packages
/site
.ipynb_checkpoints
profile_default/
ipython_config.py
# Benutzerdefiniert
/data
/work
/log
/logs
/results
/tests/output/
# BricsCAD kompilierte Menuedateien
*.cui
data/block_libraries/ils_library.dxf >> .gitignore
echo data/block_libraries/ils_library.dxf
+3 -2
View File
@@ -1,3 +1,4 @@
{
"iis.configDir": ""
}
"iis.configDir": "",
"specstory.cloudSync.enabled": "never"
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+162
View File
@@ -0,0 +1,162 @@
# dxfmakros - Projektanweisungen
## Projektbeschreibung
AutoLISP-Makros (SSG_LIB) fuer BricsCAD Pro zur automatisierten Erstellung von Foerderanlagen-Layouts (ILS Kreisel, Omniflo, Variofoerderer, Geruest). Ziel ist der Ersatz proprietaerer Tools (Bihler Omniflo, Bihler Geruest, Ruledesigner) durch eigene parametrische Makros.
## Technologie-Stack
- **CAD-System**: BricsCAD Pro (AutoCAD-kompatibel)
- **Hauptsprache**: AutoLISP (.lsp)
- **Hilfssprache**: Python (Export-Skripte in `lib/`)
- **Datenformate**: DXF/DWG (Bloecke), JSON (Komponentendaten), CSV (Export)
- **Dialoge**: DCL (Dialog Control Language, in `dcl/`)
- **Menu**: BricsCAD .mnu/.mnl Format (in `menu/`)
## Projektstruktur
| Verzeichnis | Inhalt |
|---|---|
| `Lisp/` | AutoLISP-Makros und Kernbibliotheken |
| `bin/` | Hilfs-Skripte (setenv.bat, start_briscad.bat) |
| `cfg/` | Konfigurationsdateien |
| `data/` | JSON-Daten, DXF-Quellen, Block-Libraries |
| `data/ils/` | DWG-Bloecke fuer ILS-Kreisel/Eckrad (AN8, SP8, AP-Typen) |
| `data/json/` | Komponentendaten (Masse, Sivas-IDs) |
| `data/block_libraries/` | DXF Block-Libraries (ils_library.dxf) |
| `dcl/` | DCL-Dialogdefinitionen |
| `doc/` | Dokumentation, Entwicklungsplan |
| `lib/` | Python-Skripte (DXF-Bearbeitung, Export) |
| `menu/` | BricsCAD-Menudefinition (SSG_LIB.mnu, SSG_LIB.mnl) |
| `tests/` | Testskripte und Referenzdaten |
## Lademechanismus (Lazy Loading via MNL)
Das Laden der LISP-Module erfolgt ueber das Menuesystem. Voraussetzung ist, dass das
Menue einmalig in BricsCAD geladen wurde (siehe unten: "Menue einrichten").
1. BricsCAD laedt beim Start automatisch `SSG_LIB.mnl` (gleichnamige MNL-Datei zum Menue)
2. Die MNL laedt alle Kern- und Feature-Module direkt per `ssg-ensure`
3. `ssg-ensure` ueberspringt bereits geladene Module (Flag `*ssg-<modul>-loaded*`)
### Menue einrichten (einmalig pro BricsCAD-Installation)
1. `bin/setenv.bat` ausfuehren (setzt `DXFM_LISP`, `DXFMAKRO` u.a.)
2. BricsCAD starten
3. In der BricsCAD-Kommandozeile: `_MENULOAD` eingeben
4. Im Dialog: `menu/SSG_LIB.mnu` auswaehlen und laden
5. BricsCAD laedt automatisch `SSG_LIB.mnl` mit alle Module werden initialisiert
Alternativ per LISP-Kommandozeile in BricsCAD:
```lisp
(command "_.MENULOAD" "C:/10-Develop/gitrepos/dxfmakros/menu/SSG_LIB.mnu")
```
Das Menue bleibt dauerhaft registriert. Nach einem Update der `.mnu`-Datei
genuegt es, BricsCAD neu zu starten oder `_MENULOAD` erneut aufzurufen.
### Voraussetzung
Umgebungsvariable `DXFM_LISP` muss gesetzt sein (via `bin/setenv.bat`).
Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD.
### Modulzuordnung im Menue
| Menue-Bereich | Modul | Befehle |
|---|---|---|
| Kreisel-Module | `KreiselInsert` | KreiselInsert, KreiselConnect, KreiselEdit, ILS_Eckrad |
| Zusatzmodul/Foerderer/Kurven | `SSG_LIB_Commands` | ILS_BTMT_*, ILS_ETF_*, ILS_K*_*, ILS_GK*_* |
| VarioFoerderer | `VarioFoerderer` | FOERDERANLAGE |
| Gefaellestrecke | `Gefaellestrecke` | GEFAELLESTRECKE |
| Omniflo (komplett) | `OmniModulInsert` | OMNI_APB_*, OMNI_W*_*, OMNI_AP*, OMNI_TEF_*, OMNI_TV_*, OMNI_EDIT |
| Export | `export` | EXPORTSIVAS, EXPORTCSV, CALLPYTHON |
| Doppelklick/Kontextmenue | `SSG_LIB_Commands` | SSG_BLOCKEDIT |
### Entfernte Legacy-Dateien
- `bin/startup.scr` - Entfernt (war fuer `/s` Parameter)
- `bin/acaddoc.lsp` - Entfernt (war fuer ACAD-Pfad-basiertes Laden)
- `bin/on_start.lsp` - Entfernt; Menue wird jetzt manuell per `_MENULOAD` eingerichtet
Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
## AutoLISP-Module
| Datei | Befehle | Beschreibung |
|---|---|---|
| `ssg_core.lsp` | - | Kernel: ssg-start/ssg-end, ssg-cfg-or, ssg-attrib-read/write, Layer/Block-Ops |
| `ssg_dbg.lsp` | - | Debug-Logging (dbgopen, dbgmsg, dbgflush, dbgclose) |
| `ssg_dialog.lsp` | - | DCL-Dialog-Vorlagen und Hilfsfunktionen |
| `ssg_layer.lsp` | - | Layer-Verwaltung |
| `KreiselInsert.lsp` | KreiselInsert, KreiselConnect, KreiselRedraw, KreiselQuick, KreiselEdit, KreiselParams, KreiselLabelSetup, KreiselLabelPos, KreiselLabelHoehe, ILS_Eckrad | ILS Kreisel und Eckrad komplett in AutoLISP |
| `VarioFoerderer.lsp` | FOERDERANLAGE | Vario-Foerderanlagen Generator |
| `Gefaellestrecke.lsp` | GEFAELLESTRECKE | Gefaelle-Foerderanlage (AUS -> Staustrecke skaliert -> Separator -> EIN) |
| `export.lsp` | EXPORTSIVAS, EXPORTCSV, OMNI_UPDATE_ATTRIBS | JSON-Sammlung und Python-Export (Omniflo-Merkmale/Sum-Zeile via lib/export_csv.py) |
| `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W*_*, OMNI_AP60/AP110, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen, Edit-Dialog |
| `SSG_LIB_Commands.lsp` | ILS_BTMT_*, ILS_ETF_*, ILS_K*_*, ILS_GK*_*, SSG_BLOCKEDIT | Dummy-Befehle fuer Menue + Doppelklick/Kontextmenue-Dispatcher |
| `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) |
## DCL-Dialoge
| Datei | Verwendet von |
|---|---|
| `kreisel_edit.dcl` | KreiselEdit (KreiselInsert.lsp) |
| `omniflo_boegen.dcl` | OMNI_APB_* (OmniModulInsert.lsp) |
| `omniflo_weichen.dcl` | OMNI_W*_* (OmniModulInsert.lsp) |
## Menue (SSG_LIB.mnu + SSG_LIB.mnl)
- `SSG_LIB.mnu` - Menuedefinition mit Lazy-Loading (`(ssg-ensure "Modul") Befehl`)
- `SSG_LIB.mnl` - Automatisch geladen mit dem Menue, definiert `ssg-ensure` Loader
- `***MENUGROUP=SSG_LIB` - Menuegruppenname
- `***POP1` - Hauptmenue (ILS, Omniflo, Export)
- `***DOUBLECLICK` - Doppelklick auf INSERT-Bloecke ruft SSG_BLOCKEDIT auf
- `***POP501` - Rechtsklick-Kontextmenue (KreiselEdit, OMNI_EDIT, SSG_BLOCKEDIT)
## Umgebungsvariablen
Werden via `bin/setenv.bat` gesetzt. Wichtigste:
- `DXFMAKRO` - Projektwurzel
- `DXFM_LISP` - Pfad zu Lisp-Dateien (benoetigt fuer ssg-ensure Lazy-Loader)
- `DXFM_BLOCKS` - Pfad zu DWG-Bloecken
- `DXFM_DATA` - Datenverzeichnis (JSON, DXF)
- `DXFM_LOG` - Log-Verzeichnis
- `DXFM_DCL` - Pfad zu DCL-Dialogdateien
- `DXFM_CFG` - Konfigurationsverzeichnis
## Konventionen
- AutoLISP-Funktionsnamen: `ssg-*` fuer Kernfunktionen, `C:BEFEHLSNAME` fuer User-Commands
- Alle Texte in Dateien ohne Umlaute (ae, oe, ue statt ae, oe, ue)
- Bloecke werden als DWG in `data/ils/` abgelegt, Block-Libraries als DXF in `data/block_libraries/`
- Komponentendaten (Masse, Sivas-IDs) liegen als JSON in `data/json/`
- Sprache im Code und Kommentaren: Deutsch
## Python-Bibliotheken
### Standalone-Skripte (`lib/`) - laufen extern mit ezdxf
Abhaengigkeiten: `ezdxf`, Standard-Library. Benoetigen Umgebungsvariablen (`DXFM_DATA`, `DXFM_RESULTS`, `DXFM_CFG`).
| Skript | Beschreibung |
|---|---|
| `omniflo_utils.py` | Gemeinsame Hilfsfunktionen fuer Omniflo-Skripte: `ROW_GROUPS` (Reihen-Gruppierung), `SWITCH_FILTERS` (Schalter-Filter), `build_row_layout`, `import_element_as_block`, `draw_cross`, `load_omniflo_data` |
| `set_einfuegepkt.py` | Setzt `$INSBASE` (Einfuegepunkt) in Omniflo-DXF-Dateien. Schalter je Typ: `--boegen`, `--weichen45`, `--weichen90`, `--weichenkoerper`, `--weichen-parallel`, `--delta`, `--dreifachweiche`, `--sternweiche`, `--show-omniflo` |
| `set_koords.py` | Setzt Koordinatensystem-Bloecke (K1-K4) in Omniflo-DXF-Dateien. Schalter: `--k1set` bis `--k4set`, `--set-all`, `--force`, `--show-omniflo`, `--test`, `--number` |
| `set_attributs.py` | Fuegt ATTDEF-Attribute zu Omniflo-DXF-Dateien hinzu. Liest Konfiguration aus `cfg/attradd.cfg`. Schalter: `--number`, `--dry-run` |
| `export_sivas.py` | Erzeugt Sivas-Export-CSV mit Summierungszeilen (ILS Automation, Omniflo Sum). Aufruf: `python export_sivas.py <export_raw.json> <data_dir> <output.csv>` |
| `export_csv.py` | Erzeugt einfache Item-Liste als CSV (ohne Summierung). Aufruf: `python export_csv.py <export_raw.json> <data_dir> <output.csv>` |
| `split_block_library.py` | Teilt `ils_library.dxf` in einzelne DXF-Dateien pro Block auf (mit Abhaengigkeiten). Export-Prefixe: Vario_, Staustrecke_, _3D_AS_, _3D_ES_ |
### Typische Verarbeitungskette (Omniflo-DXF)
1. `set_attributs.py` - Attribute zu Quell-DXFs hinzufuegen
2. `set_einfuegepkt.py` - Einfuegepunkte berechnen und setzen
3. `set_koords.py` - Koordinatensysteme (K1-K4) setzen
4. `export_sivas.py` / `export_csv.py` - Export aus Zeichnung
## Entwicklungsstand
Siehe `doc/Entwicklungsplan.md` fuer Meilensteinplanung und Aufwandsschaetzung.
Fertig (DONE): ILS Kreisel, ILS Eckrad, ILS Variofoerderer, Omniflo Boegen, Omniflo Weichen.
+22
View File
@@ -0,0 +1,22 @@
;; ============================================================
;; EtageVarioFoerderer.lsp — Kompatiblitaets-Wrapper
;; Laedt vf_core.lsp (Plugin-Dispatcher-Architektur)
;; c:ETAGEVARIOFOERDERER ist in vf_core.lsp als Alias definiert.
;; ============================================================
;; vf_core.lsp laden: 1) DXFM_LISP, 2) *ssg-lisp-pfad* (vom MNL gesetzt), 3) findfile
(setq *vf-core-datei*
(cond
((getenv "DXFM_LISP")
(strcat (vl-string-translate "\\" "/" (getenv "DXFM_LISP")) "/vf_core.lsp"))
((and (boundp '*ssg-lisp-pfad*) *ssg-lisp-pfad*
(findfile (strcat *ssg-lisp-pfad* "/vf_core.lsp")))
(strcat *ssg-lisp-pfad* "/vf_core.lsp"))
((findfile "vf_core.lsp")
(findfile "vf_core.lsp"))
(t nil)
)
)
(if *vf-core-datei*
(load *vf-core-datei*)
(princ "\n[EtageVarioFoerderer] WARNUNG: vf_core.lsp nicht gefunden - Befehle nicht verfuegbar.")
)
File diff suppressed because it is too large Load Diff
-307
View File
@@ -1,307 +0,0 @@
;; ============================================
;; ModulInsert.lsp
;; Kreisel Modul-Einfügesystem + Smart Connect
;; Version: 4.0
;;
;; Basispunkt: Linker Kreis, linkester Tangentenpunkt (links Mitte)
;; ============================================
;; Standardwerte initialisieren
(setq #Kreisel_Abstand 2300.0)
(setq #Kreisel_Typ "PIN")
;; ============================================
;; Haupt-Einfügebefehl (Position manuell angeben)
;; ============================================
(defun c:KreiselInsert ( / pt x y abstand typ oldLayer oldColor oldOsnap oldCmdEcho abstandStr typNum)
(princ "\n=== Kreisel Modul einfügen ===\n")
(princ "Basispunkt = linke Kreistangente (links Mitte)\n")
;; 1. Einfügepunkt abfragen
(setq pt (getpoint "\nBasispunkt (linke Kreistangente): "))
(if (null pt) (setq pt '(0 0 0)))
(setq x (car pt) y (cadr pt))
;; 2. Abstand abfragen
(princ (strcat "\nAbstand <" (rtos #Kreisel_Abstand 2 0) ">: "))
(setq abstandStr (getstring ""))
(if (= abstandStr "")
(setq abstand #Kreisel_Abstand)
(setq abstand (atof abstandStr))
)
(setq #Kreisel_Abstand abstand)
;; 3. Typ abfragen
(princ "\n[1] Kreisel mit PIN")
(princ "\n[2] Kreisel ohne PIN")
(princ (strcat "\nBitte wählen <" (if (= #Kreisel_Typ "PIN") "1" "2") ">: "))
(setq typNum (getstring ""))
(cond
((= typNum "2") (setq typ "OhnePIN"))
(t (setq typ "PIN"))
)
(setq #Kreisel_Typ typ)
(princ (strcat "\n→ Modus: " typ))
;; Modul zeichnen
(draw-module x y abstand typ)
(princ "\n✅ Kreisel Modul erfolgreich eingefügt")
(princ)
)
;; ============================================
;; Smart-Connect-Einfügebefehl
;; ============================================
(defun c:KreiselConnect ( / existingObj pickPoint connectionType newX newY abstand typ)
(princ "\n=== Kreisel Smart Connect ===\n")
;; 1. Bestehendes Modul auswählen
(setq existingObj (car (entsel "\nBestehendes Modul wählen: ")))
(if (null existingObj) (exit))
;; 2. Verbindungspunkt abfragen (Benutzer-Klickposition)
(setq pickPoint (getpoint "\nVerbindungspunkt wählen (auf Tangente klicken): "))
(if (null pickPoint) (exit))
;; 3. Verbindungspunkt-Typ erkennen
(setq connectionType (identify-connection-point existingObj pickPoint))
(princ (strcat "\n→ Verbindungspunkt: " connectionType))
;; 4. Parameter des neuen Moduls abfragen
(princ (strcat "\nAbstand <" (rtos #Kreisel_Abstand 2 0) ">: "))
(setq abstandStr (getstring ""))
(if (= abstandStr "")
(setq abstand #Kreisel_Abstand)
(setq abstand (atof abstandStr))
)
(princ "\n[1] Kreisel mit PIN")
(princ "\n[2] Kreisel ohne PIN")
(princ (strcat "\nBitte wählen <" (if (= #Kreisel_Typ "PIN") "1" "2") ">: "))
(setq typNum (getstring ""))
(cond
((= typNum "2") (setq typ "OhnePIN"))
(t (setq typ "PIN"))
)
;; 5. Basispunkt des neuen Moduls anhand der Verbindungsregeln berechnen
(setq newBasePoint (calculate-new-basepoint existingObj pickPoint connectionType abstand))
(if newBasePoint
(progn
(princ (strcat "\n→ Neue Basis: (" (rtos (car newBasePoint) 2 0) "," (rtos (cadr newBasePoint) 2 0) ")"))
(draw-module (car newBasePoint) (cadr newBasePoint) abstand typ)
(princ "\n✅ Smart Connect erfolgreich!")
)
(princ "\n❌ Verbindung nicht möglich!")
)
(princ)
)
;; ============================================
;; Verbindungspunkt-Typ erkennen
;; ============================================
(defun identify-connection-point (obj pickPoint / x y abstand)
;; Basispunkt des Moduls ermitteln (aus Einfügepunkt berechnen)
(setq insertPoint (cdr (assoc 10 (entget obj))))
(setq x (car insertPoint) y (cadr insertPoint))
;; Abstand ermitteln (sollte aus Modulattributen gelesen werden, vorerst globale Variable)
(setq abstand #Kreisel_Abstand)
(setq pickX (car pickPoint) pickY (cadr pickPoint))
(setq tolerance 50.0) ;; Toleranz 50mm
;; Verbindungspunkte prüfen
(cond
;; T_O (Mittelpunkt obere Tangente)
((and (abs (- pickX (+ x 400.0 (/ abstand 2.0)))) tolerance)
(abs (- pickY (+ y 400.0))) tolerance)
(setq type "T_O"))
;; T_U (Mittelpunkt untere Tangente)
((and (abs (- pickX (+ x 400.0 (/ abstand 2.0)))) tolerance)
(abs (- pickY (- y 400.0))) tolerance)
(setq type "T_U"))
;; M_O (Linker Kreis, oberer Rand)
((and (abs (- pickX (+ x 400.0))) tolerance)
(abs (- pickY (+ y 400.0)))) tolerance)
(setq type "M_O"))
;; M_U (Linker Kreis, unterer Rand)
((and (abs (- pickX (+ x 400.0))) tolerance)
(abs (- pickY (- y 400.0))) tolerance)
(setq type "M_U"))
;; M_L (Linker Kreis, linker Rand)
((and (abs (- pickX x)) tolerance)
(abs (- pickY y)) tolerance)
(setq type "M_L"))
;; S_O (Rechter Kreis, oberer Rand)
((and (abs (- pickX (+ x 400.0 abstand))) tolerance)
(abs (- pickY (+ y 400.0))) tolerance)
(setq type "S_O"))
;; S_U (Rechter Kreis, unterer Rand)
((and (abs (- pickX (+ x 400.0 abstand))) tolerance)
(abs (- pickY (- y 400.0))) tolerance)
(setq type "S_U"))
;; S_R (Rechter Kreis, rechter Rand)
((and (abs (- pickX (+ x 800.0 abstand))) tolerance)
(abs (- pickY y)) tolerance)
(setq type "S_R"))
(t (setq type "UNKNOWN"))
)
type
)
;; ============================================
;; Basispunkt des neuen Moduls berechnen
;; ============================================
(defun calculate-new-basepoint (obj pickPoint connectionType abstand / x y newX newY)
(setq insertPoint (cdr (assoc 10 (entget obj))))
(setq x (car insertPoint) y (cadr insertPoint))
(cond
;; T_O / T_U / M_O / S_O / M_U / S_U → Verbindung nach oben oder unten, neues Modul mit S_R
((member connectionType '("T_O" "T_U" "M_O" "S_O" "M_U" "S_U"))
(princ "\n→ Richtung: nach oben/unten")
;; Bestimmen ob nach oben oder unten
(if (> (cadr pickPoint) y)
(setq newX x newY (+ y 800.0 abstand)) ;; nach oben
(setq newX x newY (- y 800.0 abstand)) ;; nach unten
)
)
;; M_L → Verbindung nach links, neues Modul mit S_R
((= connectionType "M_L")
(princ "\n→ Richtung: nach links")
(setq newX (- x 800.0 abstand) newY y)
)
;; S_R → Verbindung nach rechts, neues Modul mit M_L
((= connectionType "S_R")
(princ "\n→ Richtung: nach rechts")
(setq newX (+ x 800.0 abstand) newY y)
)
(t (setq newX nil newY nil))
)
(if (and newX newY) (list newX newY) nil)
)
;; ============================================
;; Komplettes Modul zeichnen
;; ============================================
(defun draw-module (x y abstand typ / oldLayer oldColor oldOsnap oldCmdEcho)
;; Fang speichern und deaktivieren
(setq oldOsnap (getvar "OSMODE"))
(setq oldCmdEcho (getvar "CMDECHO"))
(setvar "OSMODE" 0)
(setvar "CMDECHO" 0)
(setq oldLayer (getvar "CLAYER"))
(setq oldColor (getvar "CECOLOR"))
;; Linken Kreisblock einfügen
(command "_.INSERT" "AN8" (list (+ x 400.0) y) 1 1 0)
;; Rechten Kreisblock einfügen
(command "_.INSERT" "SP8" (list (+ x 400.0 abstand) y) 1 1 0)
;; Tangenten zeichnen
(if (not (tblsearch "LAYER" "S_LP"))
(command "_.LAYER" "_NEW" "S_LP" "_C" "7" "" "")
)
(setvar "CLAYER" "S_LP")
(if (= typ "PIN")
(setvar "CECOLOR" "5")
(setvar "CECOLOR" "1")
)
;; Obere Tangente
(command "_.LINE"
(list (+ x 400.0) (+ y 400.0))
(list (+ x 400.0 abstand) (+ y 400.0))
"")
;; Untere Tangente
(command "_.LINE"
(list (+ x 400.0) (- y 400.0))
(list (+ x 400.0 abstand) (- y 400.0))
"")
;; PIN-Linien zeichnen
(if (= typ "PIN")
(progn
(if (not (tblsearch "LAYER" "pinbereich"))
(command "_.LAYER" "_NEW" "pinbereich" "_C" "3" "_LT" "2punkt" "")
)
(setvar "CLAYER" "pinbereich")
(setvar "CECOLOR" "3")
;; Obere PIN-Linie
(command "_.LINE"
(list (+ x 800.0) (+ y 300.0))
(list (+ x abstand) (+ y 300.0))
"")
;; Untere PIN-Linie
(command "_.LINE"
(list (+ x 800.0) (- y 300.0))
(list (+ x abstand) (- y 300.0))
"")
)
)
;; Einstellungen wiederherstellen
(setvar "CLAYER" oldLayer)
(setvar "CECOLOR" oldColor)
(setvar "OSMODE" oldOsnap)
(setvar "CMDECHO" oldCmdEcho)
)
;; ============================================
;; Hilfsbefehle
;; ============================================
(defun c:KreiselQuick ()
(setq pt (getpoint "\nBasispunkt (linke Kreistangente): "))
(if pt
(draw-module (car pt) (cadr pt) #Kreisel_Abstand #Kreisel_Typ)
)
(princ "\n✅ Schnell Einfügen fertig")
)
(defun c:KreiselParams ()
(princ "\n=== Aktuelle Kreisel Parameter ===")
(princ (strcat "\nAbstand: " (rtos #Kreisel_Abstand 2 0) " mm"))
(princ (strcat "\nTyp: " #Kreisel_Typ))
(princ "\nBasispunkt: linke Kreistangente (links Mitte)")
(princ "\n===================================\n")
(princ)
)
(princ "\nModulInsert.lsp geladen (Version 4.0 - Smart Connect)!")
(princ "\nBefehle: KreiselInsert, KreiselConnect, KreiselQuick, KreiselParams")
(princ)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+338
View File
@@ -0,0 +1,338 @@
# Lisp AutoLISP-Bibliotheken (SSG_LIB)
AutoLISP-Routinen für BricsCAD Pro zur automatisierten Erstellung von Förderanlagen-Layouts. Destilliert aus den historischen ACADSST-Makros (Schönenberger Systeme GmbH) und erweitert für die SSG_LIB-Befehle.
---
## Menue einrichten und Module laden
Module werden automatisch ueber `SSG_LIB.mnl` geladen, sobald das Menue
einmalig in BricsCAD registriert wurde:
**Einmalige Einrichtung (BricsCAD-Kommandozeile):**
```
_MENULOAD → menu/SSG_LIB.mnu auswaehlen
```
BricsCAD laedt daraufhin automatisch `SSG_LIB.mnl`, welches alle Module
per `ssg-ensure` initialisiert (Kern: ssg_core/dbg/dialog/layer, dann
alle Feature-Module). Details: siehe `../CLAUDE.md` Abschnitt "Lademechanismus".
**Manuell laden (Notfall / Entwicklung):**
```lisp
(load "C:/10-Develop/gitrepos/dxfmakros/Lisp/ssg_load.lsp")
```
`ssg_load.lsp` laedt alle Module in der richtigen Reihenfolge ohne Menueabhaengigkeit.
---
## Dateien
### `ssg_core.lsp` Kernbibliothek
Grundfunktionen für Umgebungssicherung, Benutzerinteraktion, Layer, Blöcke, Attribute und JSON-Konfiguration. Muss als erstes geladen werden.
**Umgebungssicherung:**
| Funktion | Beschreibung |
| --- | --- |
| `ssg-start titel vars` | Systemvariablen sichern, CMDECHO aus, Undo-Gruppe öffnen |
| `ssg-end` | Systemvariablen wiederherstellen, Undo-Gruppe schließen |
| `ssg-errhan em` | Fehlerhandler räumt auf und ruft `ssg-end` auf |
**Benutzer-Abfragen:**
| Funktion | Beschreibung |
| --- | --- |
| `ssg-ques text defa` | Ja/Nein-Abfrage; `defa=T` → Default Ja, `nil` → Default Nein |
| `ssg-emsg text` | Fehlermeldung mit optionalem Signalton (`ssg-bell`) |
**Layer-Hilfsfunktionen:**
| Funktion | Beschreibung |
| --- | --- |
| `ssg-get-layer text` | Layer eines angeklickten Objektes ermitteln |
| `ssg-layer-ss name typ` | Auswahlsatz aller Objekte eines Layers (optional nach Typ filtern) |
| `ssg-make-layer name farbe aktiv` | Layer anlegen (falls nicht vorhanden) und optional aktivieren |
| `ssg-ss-foreach ss func` | Iteration über Auswahlsatz `func` für jeden Entity-Name |
| `ssg-ss-redraw ss modus` | Auswahlsatz hervorheben (3), invertieren (4) oder normal (0) |
| `ssg-ss-add src dest` | Auswahlsatz `src` zu `dest` hinzufügen (in-place, mit Highlight) |
**Block-Operationen:**
| Funktion | Beschreibung |
| --- | --- |
| `ssg-timestamp` | Zeitstempel als `YYYYMMDDHHMMSS`-String erzeugen |
| `ssg-make-blockname pt` | Eindeutigen Blocknamen aus Einfügepunkt + Zeitstempel erzeugen |
| `ssg-insert-block layer farbe pfad pt xs ys rot` | Layer anlegen und Block einfügen |
| `ssg-make-block pt rotation ss` | Auswahlsatz als Block definieren und gleich einfügen |
**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_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)
```
---
### `ssg_dialog.lsp` Dialog-Pattern für Modul-Einfüge-Makros
Kapselt das wiederkehrende DCL-Muster: Dialog mit Vorschaubild, Radio-Auswahl, Block einfügen, Attribute setzen. Setzt `ssg_core.lsp` voraus.
| Funktion | Beschreibung |
| --- | --- |
| `ssg-dia-show-slide tile lib name` | Vorschau-Slide im image-Tile anzeigen (Hintergrundfarbe aus Config: `infrastruktur/dialog_preview_bg_color`) |
| `ssg-dia-update-preview tile idx lib liste` | Vorschau anhand Index-String aus Radio-/List-Tile aktualisieren |
| `ssg-modul-dialog dcl id sel-tile start-val prev-tile lib slides extra-init extra-read` | Vollständiger Modul-Dialog: lädt DCL, setzt Tiles, verknüpft Vorschau, liefert gewählten Index |
| `ssg-insert-modul layer farbe pfad attribs rotation` | Standardsequenz: Layer anlegen → Punkt abfragen → Block einfügen → Attribute setzen |
Die Datei enthält außerdem ein auskommentiertes **Template** für neue `c:BEFEHL`-Definitionen nach dem SSG-Muster.
---
### `ssg_layer.lsp` Interaktive Layer-Verwaltung
Benutzerfreundliche BricsCAD-Befehle für Layer-Operationen. Alle Befehle sichern die Umgebung über `ssg-start`/`ssg-end`. Setzt `ssg_core.lsp` voraus.
**Hilfsfunktionen:**
| Funktion | Beschreibung |
| --- | --- |
| `ssg-layer-list-all` | Alle Layernamen als Liste |
| `ssg-layer-info-all` | Alle Layer als Assoziationslisten (Name, Farbe, Linientyp, Flags) |
| `ssg-layer-visible-p name` | Sichtbarkeitsstatus prüfen (`T` = sichtbar) |
| `ssg-layer-safe-p name gruppe` | Prüfen ob Layer ausgeschaltet werden darf (nicht aktiver Layer) |
| `ssg-layer-group name` | Gruppen-Kennung aus Layernamen extrahieren (Position 23) |
| `ssg-layer-rename-group name neu` | Neuen Layernamen mit geänderter Gruppen-Kennung berechnen |
| `ssg-layer-group-move alt neu` | Alle Objekte einer Layergruppe auf neue Gruppen-Kennung verschieben |
**BricsCAD-Befehle:**
| Befehl | Beschreibung |
| --- | --- |
| `c:SSG-LayerSet` | Layer des angeklickten Objektes als aktiven Layer setzen |
| `c:SSG-LayerInfo` | Layer des angeklickten Objektes anzeigen |
| `c:SSG-LayerMove` | Auswahlsatz auf Layer eines anderen Objektes verschieben |
| `c:SSG-LayerCopy` | Auswahlsatz kopieren und Kopie auf Ziel-Layer legen |
| `c:SSG-LayerMoveType` | Alle Objekte des gleichen Typs auf dem gleichen Layer verschieben |
| `c:SSG-LayerOff` | Layer durch Anklicken ausschalten (Schleife bis Enter) |
| `c:SSG-LayerFreeze` | Layer durch Anklicken einfrieren (Schleife bis Enter) |
| `c:SSG-FreezeAll` | Alle Layer außer einem einfrieren |
| `c:SSG-ThawAll` | Alle Layer auftauen |
| `c:SSG-LayerOnAll` | Alle ausgeschalteten Layer einschalten |
| `c:SSG-LayerDelete` | Layer mit Sicherheitsabfrage löschen (Objekte + Layer) |
---
### `ssg_load.lsp` Laderoutine
Lädt alle Module in der richtigen Reihenfolge. Ermittelt den Pfad automatisch über `findfile`. Ruft direkt nach `ssg_core.lsp` die Funktion `ssg-load-config` auf, damit die JSON-Konfiguration für alle nachfolgenden Module verfügbar ist.
---
### `VarioFoerderer.lsp` Vario-Förderer
Parametrischer Generator für ILS Vario-Förderanlagen. Liest Block-Geometrie aus einer DWG-Bibliothek (`DXFM_BLOCKS`). Alle Konstanten (Abstände, Winkel, Skalierung) werden via `ssg-cfg-or` aus `component_defaults.json` (Sektion `vario`) gelesen.
**Befehl:** `c:FOERDERANLAGE`
**Wichtige interne Funktionen** (werden auch von `Gefaellestrecke.lsp` genutzt):
| Funktion | Beschreibung |
| --- | --- |
| `init-bibliothek` | Block-Bibliothek aus DWG laden und Geometriedaten extrahieren |
| `ensure-block-loaded name` | Block aus Bibliothek in aktives Dokument laden (einmalig) |
| `insert-block-by-ks name ks-nr pt` | Block anhand Koordinatensystem-Punkt einfügen |
| `insert-inclined-scaled-block name laenge winkel pt` | Geneigten, skalierten Block einfügen |
| `insert-rotated-block-with-ks name rot pt` | Rotierten Block mit KS-Offset einfügen |
| `get-line-start-end-points ename` | Start- und Endpunkt einer LINE-Entity ermitteln |
| `punkt-differenz p1 p2` | Differenzvektor zweier Punkte |
---
### `Gefaellestrecke.lsp` Gefällestrecken-Generator
Erzeugt eine einfache Förderanlage mit festem Gefällewinkel:
`AUS-Element → Staustrecke (skaliert) → Separator → EIN-Element`
Setzt `VarioFoerderer.lsp` voraus (nutzt dessen `init-bibliothek`, `insert-block-by-ks` und weitere Hilfsfunktionen). Alle Defaults (`default_delta_l`, `default_winkel`, `separator_breite`) kommen aus Config-Sektion `gefaelle`.
**Befehl:** `c:GEFAELLESTRECKE`
Zwei Modi:
- **Modus 1:** Startpunkt + ΔL (Horizontalabstand) interaktiv abfragen
- **Modus 2:** Bestehende 3D-Linie wählen (ΔL und Winkel werden daraus berechnet)
---
### `export.lsp` Export-Funktionen
Sammelt INSERT-Blöcke aus der Zeichnung und exportiert sie als JSON oder ruft Python-Skripte für den Sivas-Export auf.
| Befehl / Funktion | Beschreibung |
| --- | --- |
| `c:EXPORTSIVAS` | Alle Blöcke als JSON sammeln und `export_sivas.py` aufrufen (Sivas-CSV) |
| `c:EXPORTCSV` | Alle Blöcke als JSON sammeln und `export_csv.py` aufrufen (einfache Item-Liste, inkl. Omniflo Bogen/Weiche/Gerade und abschließender "Omniflo Sum"-Zeile) |
| `csv:collect-export-blocks` | Alle INSERT-Blöcke der Zeichnung als JSON-Array sammeln |
| `csv:run-export py-skript json-datei output-csv` | Python-Skript mit gesammelten Daten aufrufen |
| `csv:read-attribs ename` | Attribute eines INSERT als JSON-Objekt lesen |
| `c:OMNI_UPDATE_ATTRIBS` | HOEHE/DREHUNG aller Omniflo-Elemente aus der Zeichnung aktualisieren |
Der Omniflo-CSV-Export (Bogen/Weiche/Gerade, inkl. Merkmale-Aufbau und Sum-Zeile) läuft
seit Entfernung von `c:OMNI_EXPORT` ausschließlich über `c: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) |
---
### `KreiselInsert.lsp` ILS Kreisel und Eckrad
AutoLISP-Implementierung fuer ILS Kreisel und Eckrad. Enthaelt alle Befehle fuer Einfuegen, Verbinden, Neuzeichnen und Bearbeiten.
| Befehl | Beschreibung |
| --- | --- |
| `c:KreiselInsert` | Kreisel-Block an Punkt einfuegen (mit Dialog fuer Parameter) |
| `c:KreiselConnect` | Zwei Punkte waehlen, Kreisel dazwischen einfuegen |
| `c:KreiselRedraw` | Bestehenden Kreisel mit neuen Parametern neu zeichnen |
| `c:KreiselQuick` | Schnelleinfuegung mit Standardwerten |
| `c:KreiselEdit` | Kreisel-Attribute ueber DCL-Dialog bearbeiten |
| `c:KreiselParams` | Aktuelle Kreisel-Parameter anzeigen |
| `c:KreiselLabelSetup` | Schriftart, Hoehe und Farbe fuer Kreisel-Beschriftung konfigurieren |
| `c:KreiselLabelPos` | Label-Offset (dx/dy) setzen |
| `c:KreiselLabelHoehe` | Label-Hoehe aendern |
| `c:ILS_Eckrad` | Eckrad an Tangentenpunkt einfuegen |
---
### `OmniModulInsert.lsp` Omniflo-Komponenten
AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen. Liest JSON-Daten aus `omniflo_boegen.json` und `omniflo_weichen.json`. Alle Konstanten via `ssg-cfg-or` aus Config.
| Befehlsgruppe | Befehle | Beschreibung |
| --- | --- | --- |
| Daten | `OMNI_LOAD`, `OMNI_INFO_BOGEN`, `OMNI_INFO_WEICHE` | JSON-Daten laden und abfragen |
| Boegen | `OMNI_APB_630_90`, `OMNI_APB_550_675`, `OMNI_APB_630_45`, `OMNI_APB_550_225`, `OMNI_APB_650_180` | Omniflo-Boegen ueber DCL-Dialog einfuegen |
| Weichen | `OMNI_W90_*`, `OMNI_W45_*`, `OMNI_WP_*`, `OMNI_WK_*`, `OMNI_WKomb_*` | Omniflo-Weichen (Einfach/Doppel/Dreiwege, Delta, Stern) |
| Geraden | `OMNI_AP60`, `OMNI_AP110`, `OMNI_APG110` | Omniflo-Geradenstuecke |
| TEF | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade` | Omniflo-TEF-Elemente |
| Transferwagen | `OMNI_TV_*` | Transferwagen-Komponenten und Schaltwerke |
| Bogenweichen | `OMNI_APBW_*` | Omniflo-Bogenweichen (diverse Radien/Winkel) |
| Bearbeiten | `OMNI_EDIT` | Omniflo-Block selektieren und Attribute bearbeiten |
---
### `SSG_LIB_Commands.lsp` Dummy-Befehle und SSG_BLOCKEDIT
Platzhalter-Definitionen fuer noch nicht implementierte Menueintraege. Gibt beim Aufruf eine Meldung aus.
Registrierte Dummy-Befehle:
| Gruppe | Befehle |
| --- | --- |
| ILS Zusatzmodule | `ILS_BTMT_Beladung`, `ILS_BTMT_Entladung`, `ILS_ETF_Etagenfoerderer`, `ILS_TEF_Strecke` |
| ILS Kurven angetrieben Aussen | `ILS_K90LA`, `ILS_K90RA`, `ILS_K60LA`, `ILS_K60RA`, `ILS_K30LA`, `ILS_K30RA` |
| ILS Kurven angetrieben Innen | `ILS_K90LI`, `ILS_K90RI`, `ILS_K60LI`, `ILS_K60RI`, `ILS_K30LI`, `ILS_K30RI` |
| ILS Gefaellestrecken-Kurven | `ILS_Gefaellestrecke`, `ILS_GK90L`, `ILS_GK90R`, `ILS_GK60L`, `ILS_GK60R`, `ILS_GK30L`, `ILS_GK30R` |
> `FOERDERANLAGE` ist nicht hier definiert dieser Befehl ist in `VarioFoerderer.lsp` implementiert.
**SSG_BLOCKEDIT** Doppelklick/Kontextmenue-Dispatcher:
Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearbeitungsbefehl auf:
| Blockmuster | Aktion |
| --- | --- |
| `KREISEL_*` | `KreiselEdit` |
| `ECKRAD_*` | `BEDIT` (Block-Editor) |
| Omniflo (TEILEART-Attribut, AP110*, numerisch) | `OMNI_EDIT` |
| Sonstige | `BEDIT` (Block-Editor) |
+231
View File
@@ -0,0 +1,231 @@
;; ============================================================
;; SSG_LIB - Dummy-Befehlsdefinitionen fuer Menue SSG_LIB
;; Jeder Befehl gibt eine Meldung aus und kann spaeter
;; durch echte Funktionalitaet ersetzt werden.
;; ============================================================
;; --- ILS / Zusatzmodul ---
(defun c:ILS_BTMT_Beladung ()
(princ "\n[DUMMY] ILS_BTMT_Beladung aufgerufen")
(princ)
)
(defun c:ILS_BTMT_Entladung ()
(princ "\n[DUMMY] ILS_BTMT_Entladung aufgerufen")
(princ)
)
;; --- ILS / Foerderer ---
(defun c:ILS_TEF_Strecke ()
(princ "\n[DUMMY] ILS_TEF_Strecke aufgerufen")
(princ)
)
;; FOERDERANLAGE ist bereits in VarioFoerderer.lsp definiert
;; Kurven angetrieben Aussen
(defun c:ILS_K90LA ()
(princ "\n[DUMMY] 90 Kurve links angetrieben Aussen")
(princ)
)
(defun c:ILS_K90RA ()
(princ "\n[DUMMY] 90 Kurve rechts angetrieben Aussen")
(princ)
)
(defun c:ILS_K60LA ()
(princ "\n[DUMMY] 60 Kurve links angetrieben Aussen")
(princ)
)
(defun c:ILS_K60RA ()
(princ "\n[DUMMY] 60 Kurve rechts angetrieben Aussen")
(princ)
)
(defun c:ILS_K30LA ()
(princ "\n[DUMMY] 30 Kurve links angetrieben Aussen")
(princ)
)
(defun c:ILS_K30RA ()
(princ "\n[DUMMY] 30 Kurve rechts angetrieben Aussen")
(princ)
)
;; Kurven angetrieben Innen
(defun c:ILS_K90LI ()
(princ "\n[DUMMY] 90 Kurve links angetrieben Innen")
(princ)
)
(defun c:ILS_K90RI ()
(princ "\n[DUMMY] 90 Kurve rechts angetrieben Innen")
(princ)
)
(defun c:ILS_K60LI ()
(princ "\n[DUMMY] 60 Kurve links angetrieben Innen")
(princ)
)
(defun c:ILS_K60RI ()
(princ "\n[DUMMY] 60 Kurve rechts angetrieben Innen")
(princ)
)
(defun c:ILS_K30LI ()
(princ "\n[DUMMY] 30 Kurve links angetrieben Innen")
(princ)
)
(defun c:ILS_K30RI ()
(princ "\n[DUMMY] 30 Kurve rechts angetrieben Innen")
(princ)
)
;; --- ILS / Gefaellestrecke ---
(defun c:ILS_Gefaellestrecke ()
(princ "\n[DUMMY] ILS_Gefaellestrecke aufgerufen")
(princ)
)
(defun c:ILS_GK90L ()
(princ "\n[DUMMY] 90 Kurve links Gefaellestrecke")
(princ)
)
(defun c:ILS_GK90R ()
(princ "\n[DUMMY] 90 Kurve rechts Gefaellestrecke")
(princ)
)
(defun c:ILS_GK60L ()
(princ "\n[DUMMY] 60 Kurve links Gefaellestrecke")
(princ)
)
(defun c:ILS_GK60R ()
(princ "\n[DUMMY] 60 Kurve rechts Gefaellestrecke")
(princ)
)
(defun c:ILS_GK30L ()
(princ "\n[DUMMY] 30 Kurve links Gefaellestrecke")
(princ)
)
(defun c:ILS_GK30R ()
(princ "\n[DUMMY] 30 Kurve rechts Gefaellestrecke")
(princ)
)
;; ============================================================
;; SSG_DIM_SWITCH - Umschalten zwischen 2D und 3D Bloecken
;; Setzt DXFM_DIM, DXFM_BLOCKS und DXFM_OMNIFLO neu
;; ============================================================
(defun c:SSG_DIM_SWITCH ( / dim-neu basis)
(setq dim-neu (if (equal (strcase (getenv "DXFM_DIM")) "3D") "2D" "3D"))
(setq basis (getenv "DXFMAKRO"))
(setenv "DXFM_DIM" dim-neu)
(setenv "DXFM_BLOCKS" (strcat basis "\\data\\ils\\" dim-neu))
(setenv "DXFM_OMNIFLO" (strcat basis "\\data\\omniflo\\" dim-neu))
(princ (strcat "\nModus umgeschaltet auf: " dim-neu))
(princ (strcat "\n DXFM_BLOCKS = " (getenv "DXFM_BLOCKS")))
(princ (strcat "\n DXFM_OMNIFLO = " (getenv "DXFM_OMNIFLO")))
(princ)
)
;; ============================================================
;; SSG_BLOCKEDIT - Kontextmenue-Dispatcher
;; Erkennt den selektierten Blocktyp und ruft den passenden
;; Bearbeitungsbefehl auf (Rechtsklick-Kontextmenue).
;; ============================================================
(defun c:SSG_BLOCKEDIT ( / ss ent ed bname attribs teileart)
;; Block ermitteln: zuerst Implied Selection, dann Picking
(setq ss (ssget "I"))
(if (or (null ss) (/= (sslength ss) 1))
(progn
(princ "\nBlock auswaehlen: ")
(setq ss (ssget ":S" '((0 . "INSERT"))))
)
)
(if (null ss)
(progn
(princ "\nKein Block ausgewaehlt.")
(princ)
(exit)
)
)
(setq ent (ssname ss 0))
(setq ed (entget ent))
(if (/= (cdr (assoc 0 ed)) "INSERT")
(progn
(princ "\nKein Block ausgewaehlt.")
(princ)
(exit)
)
)
(setq bname (cdr (assoc 2 ed)))
(cond
;; Kreisel-Bloecke -> KreiselEdit
((wcmatch bname "KREISEL_*")
(princ (strcat "\nKreisel bearbeiten: " bname))
(c:KreiselEdit)
)
;; Eckrad-Bloecke -> BEDIT (kein eigener Edit-Dialog in LISP)
((wcmatch bname "ECKRAD_*")
(princ (strcat "\nEckrad bearbeiten: " bname))
(command "_.BEDIT" bname)
)
;; Omniflo-Bloecke -> OMNI_EDIT
;; Erkennung: TEILEART-Attribut vorhanden, AP110-Blockname oder rein numerisch
((progn
(setq attribs (ssg-attrib-read ent))
(setq teileart (cdr (assoc "TEILEART" attribs)))
(or
teileart
(wcmatch (strcase bname) "AP110*,AP_110*,APG110*")
(wcmatch bname "#*")
)
)
(princ (strcat "\nOmniflo Element bearbeiten: " bname))
(c:OMNI_EDIT)
)
;; Unbekannter Blocktyp -> natives EATTEDIT (Attribut-Editor)
(t
(princ (strcat "\nAttribute bearbeiten: " bname))
(command "_.EATTEDIT")
)
)
(princ)
)
;; ============================================================
;; C:EATTEDIT - Abfangen des eingebauten Doppelklick-Befehls
;; UNDEFINE zwingt BricsCAD, auch interne Aufrufe ueber LISP
;; zu leiten. Fallback auf _.EATTEDIT (Dot-Prefix = nativ,
;; kein Loop) fuer unbekannte Bloecke.
;; ============================================================
(defun c:EATTEDIT ()
(c:SSG_BLOCKEDIT)
)
(if (not *ssg-eattedit-undefined*)
(progn
(command "_.UNDEFINE" "EATTEDIT")
(setq *ssg-eattedit-undefined* t)
)
)
(princ "\nSSG_LIB_Commands.lsp geladen - Dummy-Befehle registriert.")
(princ)
+16 -541
View File
@@ -1,546 +1,21 @@
;; ============================================================
;; FÖRDERANLAGE GENERATOR für BricsCAD Pro
;; Version: 24.3 (Korrigierte Methodenzuordnung)
;; Befehl: FOERDERANLAGE
;; VarioFoerderer.lsp — Kompatiblitaets-Wrapper
;; Laedt vf_core.lsp (Plugin-Dispatcher-Architektur)
;; ============================================================
(vl-load-com)
;; ============================================================
;; TEIL 1: GLOBALE EINSTELLUNGEN
;; ============================================================
(setq modul-pfad (strcat (getenv "DXFM_BLOCKS") "/"))
(setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
(setq modelspace (vla-get-ModelSpace doc))
;; ============================================================
;; TEIL 2: FESTE MODUL-MASSE
;; ============================================================
(setq aus-dx 531.85)
(setq aus-dy -496.11)
(setq aus-dz -12.92)
(setq ein-dx 468.94)
(setq ein-dy -446.42)
(setq ein-dz -167.89)
(setq separator-laenge 300)
(setq spannstation-laenge 500)
(setq motorstation-laenge 500)
(setq staustrecke-basis 1000)
(setq FESTE_HORIZONTAL 1600)
;; ============================================================
;; TEIL 3: BOGEN-MASSE (für X-Werte aus Tabelle)
;; ============================================================
(setq bogen-auf-unten
'((3 399.73 0 0)(9 297.95 0 15.61)(12 296.52 0 23.34)
(15 593.04 0 62.33)(24 583.13 0 100.09)(36 847.53 0 234.76)
(48 1063.24 0 448.91))
)
(setq bogen-auf-oben
'((3 391.46 0 0)(9 281.45 0 14.75)(12 275.96 0 21.72)
(15 568.46 0 59.75)(24 546.87 0 93.37)(36 796.96 0 219.78)
(48 1000.4 0 422.88))
)
(setq bogen-ab-oben
'((9 389.31 0 -40.92)(12 284.23 0 -37.42)(15 389.31 0 -40.92)
(24 552.27 0 -124.51)(36 796.35 0 -265.43)(48 732.51 0 -349.39))
)
(setq bogen-ab-unten
'((9 397.54 0 -41.78)(12 296.52 0 -39.04)(15 493.38 0 -70.19)
(24 580.27 0 -131.23)(36 838.65 0 -280.41)(48 787.08 0 -375.42))
)
;; ============================================================
;; TEIL 4: HILFSFUNKTIONEN
;; ============================================================
(defun punkt-differenz (p1 p2)
(list (- (car p2) (car p1)) (- (cadr p2) (cadr p1)) (- (caddr p2) (caddr p1)))
)
(defun get-bogen-mass (tabelle winkel)
(setq result nil)
(foreach item tabelle (if (= (car item) winkel) (setq result (cdr item))))
(if (null result) (setq result '(800 0 0))) result
)
(defun get-bogen-mass-mit-abs (tabelle winkel)
(setq result nil)
(foreach item tabelle (if (= (car item) winkel) (setq result (list (cadr item) (caddr item) (abs (cadddr item))))))
(if (null result) (setq result '(800 0 0))) result
)
(defun fmt (x)
(if (and (numberp x) (not (equal x nil))) (rtos x 2 2) "---")
)
;; ============================================================
;; ActiveX Block einfügen (返回对象)
;; ============================================================
(defun InsertBlock (name punkt skala-x)
(setq insertionPoint (vlax-3D-point punkt))
(vla-InsertBlock modelspace insertionPoint name skala-x 1.0 1.0 0)
)
;; ============================================================
;; 🔥 METHODE 1: Für rotierte Blöcke (Staustrecken, Separator, Spannstation, Motorstation)
;; X = berechnet aus Länge * cos(Winkel)
;; Z = aus BoundingBox
;; ============================================================
(defun get-block-endpoint-rotated (obj startpunkt winkel laenge)
(setq rad (* winkel (/ pi 180.0)))
(setq berechnete_dx (* laenge (cos rad)))
(vla-GetBoundingBox obj 'minpt 'maxpt)
(setq minpt (vlax-safearray->list minpt))
(setq maxpt (vlax-safearray->list maxpt))
(setq reale_dz (- (caddr maxpt) (caddr minpt)))
(list (+ (car startpunkt) berechnete_dx)
(cadr startpunkt)
(+ (caddr startpunkt) reale_dz))
)
;; ============================================================
;; 🔥 METHODE 2: Für nicht-rotierte Blöcke (AUS_Element, EIN_Element)
;; X und Z aus BoundingBox (komplett aus Block-Geometrie)
;; ============================================================
(defun get-block-endpoint-nonrotated (obj startpunkt)
(vla-GetBoundingBox obj 'minpt 'maxpt)
(setq minpt (vlax-safearray->list minpt))
(setq maxpt (vlax-safearray->list maxpt))
(list (car maxpt) ;; X aus BBox
(cadr startpunkt) ;; Y gleich
(caddr maxpt)) ;; Z aus BBox
)
;; ============================================================
;; 🔥 METHODE 3: Für Vertikalbögen
;; X aus Tabelle (vordefinierte Werte)
;; Z aus BoundingBox
;; ============================================================
(defun get-block-endpoint-bogen (obj startpunkt bogen-x)
(vla-GetBoundingBox obj 'minpt 'maxpt)
(setq minpt (vlax-safearray->list minpt))
(setq maxpt (vlax-safearray->list maxpt))
(setq reale_dz (- (caddr maxpt) (caddr minpt)))
(list (+ (car startpunkt) bogen-x) ;; X aus Tabelle
(cadr startpunkt)
(+ (caddr startpunkt) reale_dz)) ;; Z aus BBox
)
;; ============================================================
;; Rotation eines Objekts um die Y-Achse (korrigiert)
;; ============================================================
(defun Rotate3D-Y (obj punkt winkel)
(setq rad (* winkel (/ pi 180.0)))
(setq tx (car punkt) ty (cadr punkt) tz (caddr punkt))
(setq matrix (list
(list (cos rad) 0 (sin rad) (- tx (* tx (cos rad)) (* tz (sin rad))))
(list 0 1 0 (- ty ty))
(list (- (sin rad)) 0 (cos rad) (- tz (* tx (sin rad)) (* tz (cos rad))))
(list 0 0 0 1)
))
(vla-TransformBy obj (vlax-tmatrix matrix))
)
;; ============================================================
;; TEIL 5: WINKELBERECHNUNG (unverändert)
;; ============================================================
(defun berechne-alle-winkel (deltaL deltaH richtung /
winkel-list ergebnis-liste A B cos3 sin3
bogen-x1 bogen-z1 bogen-x2 bogen-z2
abs-dz-AUS abs-dz-EIN L_GF L_VF cosα sinα nenner
winkel mass1 mass2 gueltig)
(setq abs-dz-AUS (abs aus-dz) abs-dz-EIN (abs ein-dz))
(setq winkel-list '(3 9 12 15 24 36 48) ergebnis-liste '())
(setq cos3 (cos (* 3 (/ pi 180.0))) sin3 (sin (* 3 (/ pi 180.0))))
(princ "\n\n=========================================\n BERECHNUNG FÜR ALLE WINKEL\n=========================================")
(princ (strcat "\nΔL = " (rtos deltaL 2 2) " mm\nΔH = " (rtos deltaH 2 2) " mm\nRichtung: " richtung))
(foreach winkel winkel-list
(if (= richtung "Auf")
(setq mass1 (get-bogen-mass bogen-auf-unten winkel) mass2 (get-bogen-mass bogen-auf-oben winkel)
bogen-z1 (caddr mass1) bogen-z2 (caddr mass2))
(setq mass1 (get-bogen-mass-mit-abs bogen-ab-oben winkel) mass2 (get-bogen-mass-mit-abs bogen-ab-unten winkel)
bogen-z1 (caddr mass1) bogen-z2 (caddr mass2))
)
(setq bogen-x1 (car mass1) bogen-x2 (car mass2))
(setq cosα (cos (* winkel (/ pi 180.0))) sinα (sin (* winkel (/ pi 180.0))))
(setq A (- deltaL aus-dx ein-dx bogen-x1 bogen-x2 (* FESTE_HORIZONTAL cos3)))
(setq B (- deltaH abs-dz-AUS abs-dz-EIN bogen-z1 bogen-z2 (* FESTE_HORIZONTAL sin3)))
(setq nenner (- (* cos3 sinα) (* sin3 cosα)))
(if (> (abs nenner) 0.0001)
(progn
(setq L_GF (/ (- (* A sinα) (* B cosα)) nenner))
(setq L_VF (/ (- (* B cos3) (* A sin3)) nenner))
(if (and (numberp L_GF) (numberp L_VF))
(progn
(setq gueltig (and (>= L_GF 0) (>= L_VF 0)))
(setq ergebnis-liste (cons (list winkel L_GF L_VF gueltig) ergebnis-liste))
)
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
)
)
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
)
)
(setq ergebnis-liste (reverse ergebnis-liste))
(princ "\n\n=================================================================================\n ERGEBNISTABELLE\n=================================================================================")
(princ "\n Winkel L_GF (mm) L_VF (mm) Status\n=================================================================================")
(setq best-winkel nil best-L_GF nil best-L_VF nil)
(foreach item ergebnis-liste
(setq winkel (car item) L_GF (cadr item) L_VF (caddr item) gueltig (cadddr item))
(if (and (numberp L_GF) (numberp L_VF))
(progn
(princ (strcat "\n " (itoa winkel) "° " (fmt L_GF) " mm " (fmt L_VF) " mm "))
(if gueltig
(progn
(princ "✓ GÜLTIG")
(if (and (null best-winkel) (>= L_GF 0) (>= L_VF 0))
(setq best-winkel winkel best-L_GF L_GF best-L_VF L_VF)
)
)
(princ "✗ UNGÜLTIG")
)
)
(princ (strcat "\n " (itoa winkel) "° --- --- ✗ FEHLER"))
)
)
(princ "\n=================================================================================")
(list best-winkel best-L_GF best-L_VF ergebnis-liste)
)
;; ============================================================
;; TEIL 6: MODULE EINFÜGEN (mit korrigierter Methodenzuordnung)
;; ============================================================
(defun foerderanlage-einfuegen (deltaL deltaH richtung
best-winkel L_GF L_VF startpunkt)
(setq aktueller-punkt startpunkt)
(setq L_GF1 (/ L_GF 2))
(setq L_GF2 (/ L_GF 2))
(princ "\n\n=========================================")
(princ "\nBeginne mit dem Einfügen der Module...")
(princ "\n=========================================")
(princ (strcat "\nStartpunkt (AUS_Element Eingang): X=" (rtos (car aktueller-punkt) 2 2)
", Y=" (rtos (cadr aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
;; ==========================================================
;; 1. AUS_Element_links - Verwenden Sie die manuellen Werte
;; ==========================================================
(princ "\n\n1/11: AUS_Element_links")
(setq blockname (strcat modul-pfad "AUS_Element_links.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt 1.0))
;; Verwenden Sie die manuellen Werte statt BoundingBox
(setq aktueller-punkt (list
(+ (car aktueller-punkt) aus-dx)
(+ (cadr aktueller-punkt) aus-dy)
(+ (caddr aktueller-punkt) aus-dz)))
(princ (strcat "\n → AUS_Element Ausgang (manuell): X=" (rtos (car aktueller-punkt) 2 2)
", Y=" (rtos (cadr aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ "\n FEHLER: AUS_Element_links.dwg nicht gefunden.")
)
;; ==========================================================
;; 2. 1. GEFÄLLESTRECKE (L_GF1) (METHODE 1: rotiert, X per cos, Z per BBox)
;; ==========================================================
(if (> L_GF1 0.1)
(progn
(princ (strcat "\n2/11: Staustrecke (3° nach unten, Länge=" (rtos L_GF1 2 2) " mm)"))
(setq blockname (strcat modul-pfad "Staustrecke_SP_1000_mm.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt (/ L_GF1 1000.0)))
(Rotate3D-Y block aktueller-punkt 3)
(setq aktueller-punkt (get-block-endpoint-rotated block aktueller-punkt 3 L_GF1))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ (strcat "\n FEHLER: Blockdatei nicht gefunden: " blockname))
)
)
(princ "\n2/11: (übersprungen, L_GF1 = 0)")
)
;; ==========================================================
;; 3. SEPARATOR 1 (METHODE 1: rotiert, X per cos, Z per BBox)
;; ==========================================================
(princ "\n3/11: Separator 300mm (3° nach unten)")
(setq blockname (strcat modul-pfad "Staustrecke_Separator_SP_300_mm.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt 1.0))
(Rotate3D-Y block aktueller-punkt 3)
(setq aktueller-punkt (get-block-endpoint-rotated block aktueller-punkt 3 separator-laenge))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ "\n FEHLER: Separator 1 Datei nicht gefunden.")
)
;; ==========================================================
;; 4. SPANNSTATION (METHODE 1: rotiert, X per cos, Z per BBox)
;; ==========================================================
(princ "\n4/11: Spannstation 500mm (3° nach unten)")
(setq blockname (strcat modul-pfad "Vario_Spannstation_SP_500mm.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt 1.0))
(Rotate3D-Y block aktueller-punkt 3)
(setq aktueller-punkt (get-block-endpoint-rotated block aktueller-punkt 3 spannstation-laenge))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ "\n FEHLER: Spannstation Datei nicht gefunden.")
)
;; ==========================================================
;; 5. 1. VERTIKALBOGEN (METHODE 3: X aus Tabelle, Z aus BoundingBox)
;; ==========================================================
(if (= richtung "Auf")
(progn
(princ (strcat "\n5/11: Vertikalbogen_Auf_" (itoa best-winkel) "_Unten"))
(setq blockname (strcat modul-pfad "Vertikalbogen_Auf_" (itoa best-winkel) "_Unten.dwg"))
(setq bogen-mass (get-bogen-mass bogen-auf-unten best-winkel))
)
(progn
(princ (strcat "\n5/11: Vertikalbogen_Ab_" (itoa best-winkel) "_Oben"))
(setq blockname (strcat modul-pfad "Vertikalbogen_Ab_" (itoa best-winkel) "_Oben.dwg"))
(setq bogen-mass (get-bogen-mass-mit-abs bogen-ab-oben best-winkel))
)
)
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt 1.0))
;; KEINE Rotation! Der Bogen ist bereits richtig ausgerichtet
(setq bogen-x (car bogen-mass))
(setq aktueller-punkt (get-block-endpoint-bogen block aktueller-punkt bogen-x))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ (strcat "\n FEHLER: Bogen-Datei nicht gefunden: " blockname))
)
;; ==========================================================
;; 6. VARIABLE STRECKE L_VF (METHODE 1: rotiert, X per cos, Z per BBox)
;; ==========================================================
(if (> L_VF 0.1)
(progn
(if (= richtung "Auf")
(progn
(princ (strcat "\n6/11: Steigungsstrecke (" (itoa best-winkel) "° nach oben, Länge=" (rtos L_VF 2 2) " mm)"))
(setq rot-winkel (- best-winkel))
)
(progn
(princ (strcat "\n6/11: Gefällestrecke (" (itoa best-winkel) "° nach unten, Länge=" (rtos L_VF 2 2) " mm)"))
(setq rot-winkel best-winkel)
)
)
(setq blockname (strcat modul-pfad "Staustrecke_SP_1000_mm.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt (/ L_VF 1000.0)))
(Rotate3D-Y block aktueller-punkt rot-winkel)
(setq aktueller-punkt (get-block-endpoint-rotated block aktueller-punkt rot-winkel L_VF))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ (strcat "\n FEHLER: Blockdatei nicht gefunden: " blockname))
)
)
(princ "\n6/11: (L_VF = 0, übersprungen)")
)
;; ==========================================================
;; 7. 2. VERTIKALBOGEN (METHODE 3: X aus Tabelle, Z aus BoundingBox)
;; ==========================================================
(if (= richtung "Auf")
(progn
(princ (strcat "\n7/11: Vertikalbogen_Auf_" (itoa best-winkel) "_Oben"))
(setq blockname (strcat modul-pfad "Vertikalbogen_Auf_" (itoa best-winkel) "_Oben.dwg"))
(setq bogen-mass (get-bogen-mass bogen-auf-oben best-winkel))
)
(progn
(princ (strcat "\n7/11: Vertikalbogen_Ab_" (itoa best-winkel) "_Unten"))
(setq blockname (strcat modul-pfad "Vertikalbogen_Ab_" (itoa best-winkel) "_Unten.dwg"))
(setq bogen-mass (get-bogen-mass-mit-abs bogen-ab-unten best-winkel))
)
)
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt 1.0))
;; KEINE Rotation!
(setq bogen-x (car bogen-mass))
(setq aktueller-punkt (get-block-endpoint-bogen block aktueller-punkt bogen-x))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ (strcat "\n FEHLER: Bogen-Datei nicht gefunden: " blockname))
)
;; ==========================================================
;; 8. MOTORSTATION (METHODE 1: rotiert, X per cos, Z per BBox)
;; ==========================================================
(princ "\n8/11: Motorstation 500mm (3° nach unten)")
(setq blockname (strcat modul-pfad "Vario_Motorstation_SP_500mm.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt 1.0))
(Rotate3D-Y block aktueller-punkt 3)
(setq aktueller-punkt (get-block-endpoint-rotated block aktueller-punkt 3 motorstation-laenge))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ "\n FEHLER: Motorstation Datei nicht gefunden.")
)
;; ==========================================================
;; 9. 2. GEFÄLLESTRECKE (L_GF2) (METHODE 1: rotiert, X per cos, Z per BBox)
;; ==========================================================
(if (> L_GF2 0.1)
(progn
(princ (strcat "\n9/11: Staustrecke (3° nach unten, Länge=" (rtos L_GF2 2 2) " mm)"))
(setq blockname (strcat modul-pfad "Staustrecke_SP_1000_mm.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt (/ L_GF2 1000.0)))
(Rotate3D-Y block aktueller-punkt 3)
(setq aktueller-punkt (get-block-endpoint-rotated block aktueller-punkt 3 L_GF2))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ (strcat "\n FEHLER: Blockdatei nicht gefunden: " blockname))
)
)
(princ "\n9/11: (übersprungen, L_GF2 = 0)")
)
;; ==========================================================
;; 10. SEPARATOR 2 (METHODE 1: rotiert, X per cos, Z per BBox)
;; ==========================================================
(princ "\n10/11: Separator 300mm (3° nach unten)")
(setq blockname (strcat modul-pfad "Staustrecke_Separator_SP_300_mm.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt 1.0))
(Rotate3D-Y block aktueller-punkt 3)
(setq aktueller-punkt (get-block-endpoint-rotated block aktueller-punkt 3 separator-laenge))
(princ (strcat "\n → Endpunkt: X=" (rtos (car aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ "\n FEHLER: Separator 2 Datei nicht gefunden.")
)
;; ==========================================================
;; 11. EIN_Element_links (METHODE 2: nicht rotiert, X und Z aus BoundingBox)
;; ==========================================================
(princ "\n11/11: EIN_Element_links")
(setq blockname (strcat modul-pfad "EIN_Element_links.dwg"))
(if (findfile blockname)
(progn
(setq block (InsertBlock blockname aktueller-punkt 1.0))
(setq aktueller-punkt (get-block-endpoint-nonrotated block aktueller-punkt))
(princ (strcat "\n → EIN_Element Ausgang: X=" (rtos (car aktueller-punkt) 2 2)
", Y=" (rtos (cadr aktueller-punkt) 2 2)
", Z=" (rtos (caddr aktueller-punkt) 2 2)))
)
(princ "\n FEHLER: EIN_Element_links Datei nicht gefunden.")
)
(princ "\n\n=========================================")
(princ "\n>>> FERTIG! Förderanlage erfolgreich erstellt! <<<")
(princ "\n=========================================")
)
;; ============================================================
;; TEIL 7: HAUPTFUNKTION
;; ============================================================
(defun c:FOERDERANLAGE ( / eingabe-modus startpunkt endpunkt differenz
deltaL deltaH deltaY richtung ergebnis
best-winkel L_GF L_VF ergebnis-liste antwort)
(princ "\n=========================================")
(princ "\n FÖRDERANLAGE GENERATOR v24.3")
(princ "\n=========================================")
(princ "\n\nEingabemodus wählen:")
(princ "\n 1 - Punkte auswählen (in der Zeichnung)")
(princ "\n 2 - Werte manuell eingeben")
(setq antwort (getstring "\nIhre Wahl (1/2): "))
;; vf_core.lsp laden: 1) DXFM_LISP, 2) *ssg-lisp-pfad* (vom MNL gesetzt), 3) findfile
(setq *vf-core-datei*
(cond
((= antwort "1") (setq eingabe-modus "Punkt"))
((= antwort "2") (setq eingabe-modus "Wert"))
(t (setq eingabe-modus "Punkt") (princ "\nUngültige Eingabe, Modus 'Punkte auswählen'"))
((getenv "DXFM_LISP")
(strcat (vl-string-translate "\\" "/" (getenv "DXFM_LISP")) "/vf_core.lsp"))
((and (boundp '*ssg-lisp-pfad*) *ssg-lisp-pfad*
(findfile (strcat *ssg-lisp-pfad* "/vf_core.lsp")))
(strcat *ssg-lisp-pfad* "/vf_core.lsp"))
((findfile "vf_core.lsp")
(findfile "vf_core.lsp"))
(t nil)
)
(if (= eingabe-modus "Punkt")
(progn
(princ "\n\n>>> MODUS: Punkte auswählen <<<")
(princ "\nWählen Sie die Einfügepunkte der Elemente.\n")
(setq startpunkt (getpoint "\n1. START-PUNKT (Eingang des AUS_Elements): "))
(if (null startpunkt) (progn (alert "Kein Startpunkt!") (exit)))
(setq endpunkt (getpoint "\n2. END-PUNKT (Ausgang des EIN_Elements): "))
(if (null endpunkt) (progn (alert "Kein Endpunkt!") (exit)))
(setq differenz (punkt-differenz startpunkt endpunkt))
(setq deltaL (abs (car differenz)) deltaY (cadr differenz) deltaH (caddr differenz))
(princ "\n\n=========================================")
(princ (strcat "\nGemessene Werte (Distanz zwischen den Punkten):\n ΔL = " (rtos deltaL 2 2) " mm\n ΔH = " (rtos deltaH 2 2) " mm"))
(if (> (abs deltaY) 50) (princ (strcat "\n ⚠ WARNUNG: Seitlicher Versatz ΔY = " (rtos deltaY 2 2) " mm!")))
(if (>= deltaH 0)
(progn (setq richtung "Auf") (princ "\n\nFörderrichtung: AUF (nach oben)"))
(progn (setq richtung "Ab") (setq deltaH (abs deltaH)) (princ "\n\nFörderrichtung: AB (nach unten)"))
)
(setq startpunkt-fuer-einfuegen startpunkt)
)
(progn
(princ "\n\n>>> MODUS: Manuelle Werteingabe <<<")
(setq deltaL (getreal "\nHorizontale Distanz ΔL (mm): "))
(if (null deltaL) (setq deltaL 15000))
(setq deltaH (getreal "\nHöhendifferenz |ΔH| (mm): "))
(if (null deltaH) (setq deltaH 3000))
(princ "\nFörderrichtung wählen:\n 1 - AUF (nach oben)\n 2 - AB (nach unten)")
(setq antwort (getstring "\nIhre Wahl (1/2): "))
(if (= antwort "2") (setq richtung "Ab") (setq richtung "Auf"))
(setq startpunkt-fuer-einfuegen (getpoint "\nStartpunkt für AUS_Element wählen: "))
(if (null startpunkt-fuer-einfuegen) (setq startpunkt-fuer-einfuegen '(0 0 0)))
)
)
(setq ergebnis (berechne-alle-winkel deltaL deltaH richtung))
(setq best-winkel (car ergebnis) L_GF (cadr ergebnis) L_VF (caddr ergebnis))
(if (or (null best-winkel) (null L_GF) (null L_VF) (<= L_GF 0) (<= L_VF 0))
(progn (alert "Kein passender Winkel gefunden!\n\nBitte andere Werte versuchen.") (exit))
)
(princ "\n\n=========================================")
(princ (strcat "\n>>> Empfohlener Winkel: " (itoa best-winkel) "°"))
(princ (strcat "\n>>> L_GF (gesamt): " (rtos L_GF 2 2) " mm"))
(princ (strcat "\n>>> L_GF1 = L_GF2 = " (rtos (/ L_GF 2) 2 2) " mm"))
(princ (strcat "\n>>> L_VF: " (rtos L_VF 2 2) " mm"))
(princ "\n=========================================")
(princ "\n\nMöchten Sie die Förderanlage einfügen?\n 1 - Ja, Module einfügen\n 2 - Nein, abbrechen")
(setq antwort (getstring "\nIhre Wahl (1/2): "))
(if (= antwort "1")
(foerderanlage-einfuegen deltaL deltaH richtung best-winkel L_GF L_VF startpunkt-fuer-einfuegen)
(princ "\nVorgang abgebrochen.")
)
(princ)
)
;; ============================================================
;; START
;; ============================================================
(princ "\n=========================================")
(princ "\n>>> FÖRDERANLAGE GENERATOR v24.3 geladen <<<")
(princ "\n>>> Befehl: FOERDERANLAGE <<<")
(princ "\n>>> Methodenzuordnung: <<<")
(princ "\n>>> - Rotierte Blöcke: X per Berechnung, Z per BoundingBox <<<")
(princ "\n>>> - Nicht-rotierte Blöcke: X und Z per BoundingBox <<<")
(princ "\n>>> - Vertikalbögen: X aus Tabelle, Z per BoundingBox <<<")
(princ "\n=========================================")
(princ)
(if *vf-core-datei*
(load *vf-core-datei*)
(princ "\n[VarioFoerderer] WARNUNG: vf_core.lsp nicht gefunden - Befehle nicht verfuegbar.")
)
+425
View File
@@ -0,0 +1,425 @@
;; ============================================================
;; export.lsp - Export-Funktionen fuer INSERT-Bloecke
;;
;; Enthaelt:
;; - JSON-Sammler (csv:collect-export-blocks, csv:run-export)
;; - Python-basierter Export: EXPORTSIVAS, EXPORTCSV
;;
;; Alle Blockname-Muster dieses Moduls sind zentral in cfg/export.cfg
;; (INI-Style, Abschnitt [blockpattern]) deklariert und werden beim
;; Laden des Moduls einmalig eingelesen (export:load-cfg).
;; Datei-/Skriptnamen sind fest im Code hinterlegt (*export-filenames*).
;; ============================================================
;; --- Export-Konfiguration aus cfg/export.cfg laden ---
;; Nutzt den zentralen INI-Parser aus ssg_core.lsp (ssg-load-ini / ssg-ini-get /
;; ssg-ini-list), damit fuer alle Module derselbe .cfg-Standard gilt.
(defun export:load-cfg ( / cfg-pfad)
(setq cfg-pfad (strcat (getenv "DXFM_CFG") "/export.cfg"))
(setq *export-cfg* (ssg-load-ini cfg-pfad))
(if (null *export-cfg*)
(princ (strcat "\n[export] WARNUNG: " cfg-pfad " nicht gefunden/leer, verwende Vorgaben."))
)
(princ)
)
;; --- Einzelwert aus *export-cfg* lesen, mit Fallback ---
;; section = "blockpattern"
(defun export:cfg (section key default)
(ssg-ini-get *export-cfg* section key default)
)
;; --- Muster aus [blockpattern] als normalisierter wcmatch-String ---
;; key = Config-Key, z.B. "pattern_kreisel"
;; default-str = Fallback-Wert als kommagetrennter String, falls Config fehlt
;; Rueckgabe: kommagetrennter String ohne Leerzeichen, z.B. "KR_*,KREISEL_*"
(defun export:pattern (key default-str)
(ssg-ini-list *export-cfg* "blockpattern" key default-str)
)
;; Beim Laden des Moduls einmalig einlesen (Lazy-Loading via ssg-ensure "export")
(export:load-cfg)
;; --- Test-Override fuer den Ausgabeordner (nur Lisp-Sitzungsspeicher) ---
;; Wird ausschliesslich von TEST_EXPORT_ALL (tests/test_export_all.lsp)
;; waehrend des Testlaufs auf DXFM_TESTOUT gesetzt und danach garantiert
;; wieder auf nil zurueckgesetzt. Bewusst KEIN (setenv "DXFM_RESULTS" ...):
;; (setenv ...) schreibt in BricsCAD dauerhaft in die Profil-Registry und
;; ueberlebt damit jeden Neustart.
(setq *export-test-override* nil)
;; --- Feste Datei-/Skriptnamen dieses Moduls (keine Config, direkt im Code) ---
(setq *export-filenames*
(list
(cons "raw_json_datei" "export_raw.json")
(cons "sivas_script" "export_sivas.py")
(cons "sivas_csv" "export_sivas.csv")
(cons "csv_script" "export_csv.py")
(cons "csv_csv" "export.csv")
)
)
;; --- Dateinamen aus *export-filenames* lesen ---
(defun export:filename (key)
(cdr (assoc key *export-filenames*))
)
;; --- String fuer JSON escapen (Anfuehrungszeichen/Backslash) ---
;; Konvertiert nicht-String-Werte (z.B. T, nil, Zahlen) defensiv in String.
(defun csv:json-escape (s)
(if (not (= (type s) 'STR))
(setq s (if s (vl-princ-to-string s) ""))
)
(setq s (vl-string-subst "\\\\" "\\" s))
(vl-string-subst "\\\"" "\"" s)
)
;; --- Attribute eines INSERT-Blocks als JSON-Objekt lesen ---
;; ename = Entity-Name des INSERT
;; Rueckgabe: String wie {"TAG1":"Wert1","TAG2":"Wert2"}
(defun csv:read-attribs (ename / obj ed typ tag wert parts)
(setq obj (entnext ename))
(setq parts nil)
(while obj
(setq ed (entget obj))
(setq typ (cdr (assoc 0 ed)))
(if (equal typ "SEQEND") (setq obj nil)
(progn
(if (equal typ "ATTRIB")
(setq parts (cons (strcat "\"" (csv:json-escape (cdr (assoc 2 ed)))
"\":\"" (csv:json-escape (cdr (assoc 1 ed))) "\"")
parts))
)
(setq obj (entnext obj))
)
)
)
(if parts
(progn
(setq parts (reverse parts))
(strcat "{" (car parts)
(apply 'strcat (mapcar '(lambda (p) (strcat "," p)) (cdr parts)))
"}")
)
"{}"
)
)
;; --- Einen INSERT-Block als JSON-Objekt schreiben ---
(defun csv:block-to-json (ename / ed blk-name layer pt rotation handle attribs)
(setq ed (entget ename))
(setq blk-name (cdr (assoc 2 ed)))
(setq layer (cdr (assoc 8 ed)))
(setq pt (cdr (assoc 10 ed)))
(setq rotation (cdr (assoc 50 ed)))
(setq handle (cdr (assoc 5 ed)))
(if (null rotation) (setq rotation 0.0))
(setq attribs (csv:read-attribs ename))
(strcat
" {\"block_name\":\"" (csv:json-escape blk-name) "\""
",\"layer\":\"" (csv:json-escape layer) "\""
",\"handle\":\"" (csv:json-escape handle) "\""
",\"x\":" (rtos (car pt) 2 4)
",\"y\":" (rtos (cadr pt) 2 4)
",\"z\":" (rtos (if (caddr pt) (caddr pt) 0.0) 2 4)
",\"rotation\":" (rtos (* (/ rotation pi) 180.0) 2 4)
",\"attribs\":" attribs
"}"
)
)
;; --- Relevante Bloecke sammeln ---
;; Filtert INSERT-Entities auf exportierbare Bloecke:
;; KR_* = Kreisel Compound-Bloecke
;; AP110* = Omniflo Geraden
;; Omniflo Boegen/Weichen = rein numerische Blocknamen (SivasNr)
;; Vario* = VarioFoerderer-Bloecke
;; GF_* = Gefaellestrecke Compound-Bloecke
;; Gibt Auswahlsatz zurueck oder nil.
(defun csv:collect-export-blocks ( / ss-all ss-out i ename ed bname)
(setq ss-all (ssget "X" (list (cons 0 "INSERT"))))
(if (null ss-all) (setq ss-out nil)
(progn
(setq ss-out (ssadd))
(setq i 0)
(while (setq ename (ssname ss-all i))
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
(if (or
(wcmatch bname (export:pattern "pattern_kreisel" "KR_*,KREISEL_*,ECKRAD_*"))
(wcmatch (strcase bname) (export:pattern "pattern_gerade" "AP110*,AP_110*"))
(wcmatch bname (export:pattern "pattern_strecke"
"Vario*,Staustrecke*,AUS_Element*,EIN_Element*,VF_*,GF_*"))
;; Rein numerische Namen = Omniflo SivasNr (Boegen/Weichen)
;; Rein LISP-intern (Python klassifiziert Omniflo stattdessen
;; ueber exakten Katalog-Match), daher fest im Code statt in
;; cfg/export.cfg.
(wcmatch bname "#*")
)
(ssadd ename ss-out)
)
(setq i (1+ i))
)
(if (= (sslength ss-out) 0) (setq ss-out nil))
)
)
ss-out
)
;; --- HOEHE/DREHUNG aller Omniflo-Elemente still aktualisieren ---
;; Wird automatisch vor jedem Export aufgerufen.
(defun omni:update-all-attribs ( / ss i ename ed bname teileart)
(setq ss (ssget "X" (list (cons 0 "INSERT"))))
(if ss
(progn
(setq i 0)
(while (setq ename (ssname ss i))
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
(setq teileart (csv:get-attrib ename "TEILEART"))
(if (or teileart
(wcmatch (strcase bname) (export:pattern "pattern_gerade" "AP110*,AP_110*")))
(progn
(omni:set-hoehe-attrib ename)
(omni:set-drehung-attrib ename)
)
)
(setq i (1+ i))
)
)
)
)
;; --- Gemeinsame Export-Funktion ---
;; Sammelt relevante Bloecke, schreibt JSON, ruft Python auf.
;; label = Anzeigename (z.B. "EXPORTCSV")
;; py-name = Python-Skript-Name (z.B. "export_csv.py")
;; csv-name = Ergebnis-CSV-Name (z.B. "export.csv")
(defun csv:run-export (label py-name csv-name / ss i ename fh out-pfad
py-skript ergebnis-pfad cmd first-block count out-dir)
;; Vor dem Export: IDs aller Bloecke sicherstellen und Duplikate korrigieren
(princ (strcat "\n[" label "] Pruefe und vergebe IDs..."))
(ssg-id-check-all)
;; Vor dem Export HOEHE/DREHUNG aller Omniflo-Elemente aktualisieren
(princ (strcat "\n[" label "] Aktualisiere Hoehe/Drehung..."))
(omni:update-all-attribs)
(princ (strcat "\n[" label "] Sammle relevante Bloecke..."))
(setq ss (csv:collect-export-blocks))
(if (null ss)
(progn
(princ (strcat "\n[" label "] Keine relevanten Bloecke gefunden."))
(princ)
)
(progn
(setq count (sslength ss))
(princ (strcat "\n[" label "] " (itoa count) " Bloecke gefunden."))
;; Ausgabeordner: DXFM_RESULTS, ausser *export-test-override* ist gesetzt
;; (nur waehrend TEST_EXPORT_ALL, siehe tests/test_export_all.lsp).
;; WICHTIG: Hier bewusst KEIN (setenv "DXFM_RESULTS" ...) verwenden!
;; (setenv ...) schreibt in BricsCAD dauerhaft in die Profil-Registry
;; und ueberlebt damit jeden Neustart - ein einziger Testlauf wuerde
;; DXFM_RESULTS fuer alle zukuenftigen Sitzungen unwiderruflich auf den
;; Testordner umbiegen. *export-test-override* ist eine reine
;; Lisp-Variable (nur Prozess-/Sitzungsspeicher) und daher sicher.
(setq out-dir (if *export-test-override*
*export-test-override*
(getenv "DXFM_RESULTS")))
(if (not (vl-file-directory-p out-dir)) (vl-mkdir out-dir))
(princ (strcat "\n[" label "] Ausgabeordner: " out-dir))
;; JSON-Datei zusammenbauen
(setq out-pfad (strcat out-dir "/"
(export:filename "raw_json_datei")))
(setq fh (open out-pfad "w"))
(if (null fh)
(progn
(princ (strcat "\n[" label "] FEHLER: Kann Datei nicht oeffnen: " out-pfad))
(princ)
)
(progn
(write-line "[" fh)
(setq i 0)
(setq first-block T)
(while (setq ename (ssname ss i))
(if (not first-block)
(write-line "," fh)
)
(write-line (csv:block-to-json ename) fh)
(setq first-block nil)
(setq i (1+ i))
)
(write-line "]" fh)
(close fh)
(princ (strcat "\n[" label "] JSON geschrieben: " out-pfad))
;; Python-Skript aufrufen
(setq py-skript (strcat (getenv "DXFM_LIB") "/" py-name))
(if (findfile py-skript)
(progn
(setq ergebnis-pfad (strcat out-dir "/" csv-name))
(setq cmd (strcat "python \"" py-skript "\""
" \"" out-pfad "\""
" \"" (getenv "DXFM_DATA") "\""
" \"" ergebnis-pfad "\""))
(princ (strcat "\n[" label "] Rufe Python auf..."))
(startapp "cmd" (strcat "/c " cmd))
(princ (strcat "\n[" label "] Export gestartet: " ergebnis-pfad))
)
(princ (strcat "\n[" label "] FEHLER: Python-Skript nicht gefunden: " py-skript))
)
)
)
)
)
(princ)
)
;; --- EXPORTSIVAS: Sivas-spezifischer CSV-Export mit Summierungszeilen ---
(defun c:EXPORTSIVAS ()
(csv:run-export "EXPORTSIVAS"
(export:filename "sivas_script")
(export:filename "sivas_csv"))
)
;; --- EXPORTCSV: Einfache Item-Liste aller Bloecke (ohne Summierung) ---
(defun c:EXPORTCSV ()
(csv:run-export "EXPORTCSV"
(export:filename "csv_script")
(export:filename "csv_csv"))
)
;; ============================================================
;; OMNIFLO HOEHE/DREHUNG AKTUALISIEREN
;; ============================================================
;; --- Attribut-Wert eines INSERT-Blocks nach Tag lesen ---
(defun csv:get-attrib (ename tag / obj ed typ atag)
(setq obj (entnext ename))
(while obj
(setq ed (entget obj))
(setq typ (cdr (assoc 0 ed)))
(if (equal typ "SEQEND")
(setq obj nil)
(progn
(if (and (equal typ "ATTRIB")
(= (strcase (cdr (assoc 2 ed))) (strcase tag)))
(progn (setq obj nil) (setq atag (cdr (assoc 1 ed))))
(setq obj (entnext obj))
)
)
)
)
atag
)
;; --- Hoehe eines Omniflo-Blocks aus der Zeichnung ermitteln ---
;; Liest z-Koordinate des Einfuegepunkts.
;; Falls der Block KS_EIN, KS_AUS oder K1-K4 enthaelt,
;; wird die minimale Z-Koordinate dieser Unterelemente + Block-Z verwendet.
(defun omni:get-block-hoehe (ename / ed bname pt z-insert blk-tbl sub-ent sub-ed sub-bname sub-pt z-list z-min)
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
(setq pt (cdr (assoc 10 ed)))
(setq z-insert (if (caddr pt) (caddr pt) 0.0))
(setq blk-tbl (tblsearch "BLOCK" bname))
(if (null blk-tbl)
z-insert
(progn
(setq sub-ent (entnext (cdr (assoc -2 blk-tbl))))
(setq z-list nil)
(while sub-ent
(setq sub-ed (entget sub-ent))
(if (= (cdr (assoc 0 sub-ed)) "INSERT")
(progn
(setq sub-bname (strcase (cdr (assoc 2 sub-ed))))
(if (wcmatch sub-bname
(export:pattern "pattern_ks_subblocks" "KS_EIN,KS_AUS,K1,K2,K3,K4"))
(progn
(setq sub-pt (cdr (assoc 10 sub-ed)))
(setq z-list (cons (if (caddr sub-pt) (caddr sub-pt) 0.0) z-list))
)
)
)
)
(setq sub-ent (entnext sub-ent))
)
(if z-list
(progn
(setq z-min (car z-list))
(foreach z (cdr z-list)
(if (< z z-min) (setq z-min z))
)
(+ z-insert z-min)
)
z-insert
)
)
)
)
;; --- HOEHE-Attribut eines Omniflo-Blocks setzen ---
;; Liest Z-Koordinate (ggf. aus KS-Unterblock) und schreibt als HOEHE-Attribut.
(defun omni:set-hoehe-attrib (ename / hoehe)
(setq hoehe (omni:get-block-hoehe ename))
(ssg-attrib-set-on ename (list (cons "HOEHE" (rtos hoehe 2 1))))
hoehe
)
;; --- DREHUNG-Attribut eines Omniflo-Blocks setzen ---
;; Liest CAD-Rotationswinkel (Gruppe 50, Bogenmass) und schreibt als DREHUNG-Attribut.
(defun omni:set-drehung-attrib (ename / ed rotation deg)
(setq ed (entget ename))
(setq rotation (cdr (assoc 50 ed)))
(if (null rotation) (setq rotation 0.0))
(setq deg (* (/ rotation pi) 180.0))
(ssg-attrib-set-on ename (list (cons "DREHUNG" (rtos deg 2 1))))
deg
)
;; ============================================================
;; C:OMNI_UPDATE_ATTRIBS - HOEHE und DREHUNG aller Omniflo-Elemente aktualisieren
;; Setzt HOEHE aus Z-Koordinate (bzw. min. KS-Sub-Block) und
;; DREHUNG aus CAD-Rotationswinkel fuer alle Bloecke mit TEILEART-Attribut.
;; ============================================================
(defun c:OMNI_UPDATE_ATTRIBS ( / ss i ename ed bname teileart count)
(setq ss (ssget "X" (list (cons 0 "INSERT"))))
(if (null ss)
(princ "\n[OMNI_UPDATE] Keine INSERT-Bloecke in der Zeichnung.")
(progn
(setq count 0)
(setq i 0)
(while (setq ename (ssname ss i))
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
;; Nur Omniflo-Elemente (erkennbar an TEILEART-Attribut oder AP110-Blockname)
(setq teileart (csv:get-attrib ename "TEILEART"))
(if (or teileart
(wcmatch (strcase bname) (export:pattern "pattern_gerade" "AP110*,AP_110*")))
(progn
(omni:set-hoehe-attrib ename)
(omni:set-drehung-attrib ename)
(setq count (1+ count))
)
)
(setq i (1+ i))
)
(princ (strcat "\n[OMNI_UPDATE] " (itoa count) " Elemente aktualisiert (HOEHE, DREHUNG)."))
)
)
(princ)
)
+29
View File
@@ -0,0 +1,29 @@
;; ============================================================
;; tests.lsp - Test- und Hilfsfunktionen
;;
;; Export-Funktionen wurden nach export.lsp ausgelagert.
;; ============================================================
(defun c:CALLPYTHON ( / log-pfad py-skript return-datei cmd fh zeile)
(setq log-pfad (getenv "DXFM_LOG"))
(setq py-skript (strcat (getenv "DXFM_LIB") "\\testpycall.py"))
(setq return-datei (strcat log-pfad "\\testpycall_return.txt"))
(if (findfile py-skript)
(progn
(setq cmd (strcat "python \"" py-skript "\" \"" log-pfad "\""))
(command "_.SHELL" cmd)
(if (findfile return-datei)
(progn
(setq fh (open return-datei "r"))
(setq zeile (read-line fh))
(close fh)
(princ (strcat "\n[SSG_LIB] Python Rueckgabe: " zeile))
)
(princ "\n[SSG_LIB] WARNUNG: Keine Rueckgabe von Python erhalten.")
)
)
(princ (strcat "\n[SSG_LIB] FEHLER: " py-skript " nicht gefunden!"))
)
(princ)
)
+184
View File
@@ -0,0 +1,184 @@
;;; ============================================================
;;; menu-inventory.lsp BricsCAD V25
;;; Inventar: Menuegruppen / BRX-Plugins / LISP-Startdateien
;;; Aufruf: MenuInventory
;;; ============================================================
(defun c:MenuInventory ( / sep phdr prow
acad-obj app-obj groups-coll grp
app-list app-name app found f entry
i srch pth lisp-name)
;; ---- Hilfsfunktionen ----
(defun sep () (princ "\n------------------------------------------------------------"))
(defun phdr (ttl) (sep) (princ (strcat "\n " ttl)) (sep))
(defun prow (lbl val)
(princ (strcat "\n " lbl))
(princ (strcat "\n -> " (if (and val (> (strlen val) 0)) val "<unbekannt>"))))
;; ---- String-Split (Semikolon-getrennte Pfade) ----
(defun split-semi (s / result start pos ch)
(setq result '() start 0 pos 0)
(while (<= pos (strlen s))
(setq ch (if (< pos (strlen s)) (substr s (1+ pos) 1) ";"))
(if (= ch ";")
(progn
(if (> pos start)
(setq result (append result (list (substr s (1+ start) (- pos start))))))
(setq start (1+ pos))))
(setq pos (1+ pos)))
result)
;; ============================================================
(princ "\n")
(princ "\n============================================================")
(princ "\n BricsCAD V25 -- Inventar: Menues / Plugins / LISP-Apps")
(princ "\n============================================================")
;; ==============================================================
;; BLOCK 1: Menuegruppen via COM/ActiveX
;; ==============================================================
(phdr "1. GELADENE MENUEGRUPPEN (CUI)")
(setq i 0)
(vl-load-com)
(if (not (setq acad-obj (vlax-get-acad-object)))
(princ "\n [COM nicht verfuegbar]")
(progn
(setq app-obj (vla-get-application acad-obj))
(setq groups-coll (vla-get-menugroups app-obj))
(if (null groups-coll)
(princ "\n [Keine Menuegruppen per COM abrufbar]")
(progn
(princ (strcat "\n Anzahl Gruppen: "
(itoa (vla-get-count groups-coll))))
(vlax-for grp groups-coll
(setq i (1+ i))
(prow
(strcat "[" (itoa i) "] "
(vlax-get-property grp 'Name))
;; MenuFileName gibt den vollen CUI-Pfad
(if (vlax-property-available-p grp 'MenuFileName)
(vlax-get-property grp 'MenuFileName)
"<MenuFileName nicht verfuegbar>")
)
)
)
)
)
)
;; ==============================================================
;; BLOCK 2: Geladene Applikationen (BRX/TX-Module)
;; ==============================================================
(phdr "2. GELADENE APPLIKATIONEN (BRX/TX)")
(setq i 0)
;; Versuch 1: COM LoadedApplications (falls verfuegbar)
(setq app-list nil)
(if (and acad-obj
(not (vl-catch-all-error-p
(setq app-list
(vl-catch-all-apply
'vlax-get-property
(list app-obj 'LoadedApplications))))))
(progn
(princ "\n [Quelle: COM LoadedApplications]")
(princ (strcat "\n Anzahl: " (itoa (vla-get-count app-list))))
(vlax-for app app-list
(setq i (1+ i))
(prow (strcat "[" (itoa i) "] "
(if (vlax-property-available-p app 'Name)
(vlax-get-property app 'Name) "?"))
(if (vlax-property-available-p app 'FullName)
(vlax-get-property app 'FullName) "<Pfad n/a>"))))
;; Versuch 2: ads_arxlist (einige BricsCAD-Builds)
(if (not (vl-catch-all-error-p
(setq app-list
(vl-catch-all-apply 'ads_arxlist nil))))
(progn
(princ "\n [Quelle: ads_arxlist]")
(princ (strcat "\n Anzahl: " (itoa (length app-list))))
(foreach app-name app-list
(setq i (1+ i))
(prow (strcat "[" (itoa i) "] " app-name)
(cond ((findfile app-name) (findfile app-name))
(T app-name)))))
;; Versuch 3: Bekannte BRX-Dateien in Support-Pfaden suchen
(progn
(princ "\n [COM/ads_arxlist nicht verfuegbar]")
(princ "\n Suche nach .brx/.tx Dateien in Support-Pfaden:")
(setq srch (getvar "SRCHPATH"))
(if (and srch (> (strlen srch) 0))
(foreach pth (split-semi srch)
(if (and (> (strlen pth) 0) (findfile pth))
(foreach ext (list "*.brx" "*.tx")
(setq found (vl-directory-files pth ext 1))
(foreach f found
(setq i (1+ i))
(prow (strcat "[" (itoa i) "] " f)
(strcat pth "\\" f)))))))
(if (= i 0)
(princ "\n [Keine BRX/TX-Module in Support-Pfaden gefunden]"))
)
)
)
;; ==============================================================
;; BLOCK 3: LISP-Startdateien
;; ==============================================================
(phdr "3. LISP-STARTDATEIEN")
(setq i 0)
;; Systemvariablen fuer globale / dok-lokale LISP-Dateien
(foreach entry (list
(list "ACADLSPASAPP" (getvar "ACADLSPASAPP"))
(list "ACADLSPASDOC" (getvar "ACADLSPASDOC")))
(setq lisp-name (cadr entry))
(if (and lisp-name (= (type lisp-name) 'STR) (> (strlen lisp-name) 0))
(progn
(setq i (1+ i))
(prow (strcat "[" (itoa i) "] " (car entry) ": " lisp-name)
(findfile lisp-name)))))
;; Bekannte BricsCAD-Startup-Hooks in den Support-Pfaden
(foreach f (list "on_start.lsp" "on_doc_load.lsp" "on_doc_save.lsp"
"on_quit.lsp" "acad.lsp" "acaddoc.lsp")
(setq lisp-name (findfile f))
(if lisp-name
(progn
(setq i (1+ i))
(prow (strcat "[" (itoa i) "] Startup-Hook: " f) lisp-name))))
(if (= i 0)
(princ "\n [Keine LISP-Startdateien gefunden]"))
;; ==============================================================
;; BLOCK 4: Systeminformationen
;; ==============================================================
(phdr "4. SYSTEMINFORMATIONEN")
(princ (strcat "\n Haupt-CUI (MENUNAME): "
(if (= (type (getvar "MENUNAME")) 'STR) (getvar "MENUNAME") "<n/a>")))
(princ (strcat "\n Profil (CPROFILE): "
(if (= (type (getvar "CPROFILE")) 'STR) (getvar "CPROFILE") "<n/a>")))
(princ "\n Support-Pfade (SRCHPATH):")
(setq srch (getvar "SRCHPATH"))
(if (and srch (= (type srch) 'STR) (> (strlen srch) 0))
(foreach pth (split-semi srch)
(if (> (strlen pth) 0)
(princ (strcat "\n " pth))))
(princ "\n <leer>"))
;; ==============================================================
(sep)
(princ "\n Ende des Inventars.")
(princ "\n============================================================\n")
(princ)
)
(princ "\n[menu-inventory.lsp geladen] Befehl: MenuInventory")
(princ)
+894
View File
@@ -0,0 +1,894 @@
;; ============================================================
;; SSG_CORE.LSP - Kernbibliothek: Umgebung, Fehler, Dialog
;; Allgemeingueltige Hilfsfunktionen fuer AutoCAD-LISP Makros
;; Ursprung: ACADSST/MENU/ssg.lsp, pu1pu2.lsp (Schoenenberger)
;; Bereinigt und verallgemeinert: 2025
;; ============================================================
;; ------------------------------------------------------------
;; UMGEBUNGSSICHERUNG
;; Sichert Systemvariablen vor Makroausfuehrung und stellt
;; sie danach wieder her. Wird immer als Paar verwendet:
;; (ssg-start "Titel" '(("OSMODE") ("ORTHOMODE")))
;; ... Makrocode ...
;; (ssg-end)
;; ------------------------------------------------------------
(defun ssg-start (titel zusatz-vars / xlen xpos xvar)
;; titel - Anzeigename des Makros
;; zusatz-vars - Liste zusaetzlicher Variablen z.B. '(("OSMODE")("ORTHOMODE"))
;; Immer CLAYER und CMDECHO werden automatisch gesichert.
(setq _ssg-olderr *error*
*error* (function ssg-errhan)
_ssg-cavar (append '(("CLAYER") ("CMDECHO")) zusatz-vars)
xlen (length _ssg-cavar)
xpos 0
)
(repeat xlen
(setq xvar (car (nth xpos _ssg-cavar))
_ssg-cavar (subst (cons xvar (getvar xvar))
(nth xpos _ssg-cavar) _ssg-cavar)
xpos (1+ xpos)
)
)
(setvar "CMDECHO" 0)
(command "_undo" "_G")
(graphscr)
(if titel (prompt (strcat "\n***** " titel " *****\n")))
(princ)
)
(defun ssg-end (/ xpos xlen xvar)
(if _ssg-cavar
(progn
(command)
(command "_undo" "_E")
(setq xpos 1
xlen (length _ssg-cavar)
)
(if (/= (getvar "CLAYER") (caar _ssg-cavar))
(command "_LAYER" "_SE" (cdar _ssg-cavar) "")
)
(repeat (1- xlen)
(setq xvar (nth xpos _ssg-cavar)
xpos (1+ xpos)
)
(setvar (car xvar) (cdr xvar))
)
)
)
(if _ssg-olderr (setq *error* _ssg-olderr))
(princ)
)
(defun ssg-errhan (em)
(if (= em "Function cancelled")
(princ)
(progn (princ "\nFehler: ") (princ em))
)
(command)
(command)
(ssg-end)
)
;; ------------------------------------------------------------
;; BENUTZER-ABFRAGEN
;; ------------------------------------------------------------
;; Ja/Nein-Abfrage mit konfigurierbarem Default
;; defa = T -> Default ist "Yes" (Eingabe noetig um "No" zu waehlen)
;; defa = nil -> Default ist "No"
;; Rueckgabe: T wenn "No" gewaehlt (also Ablehnung), nil wenn "Yes"
(defun ssg-ques (prompt-text defa)
(if defa
(progn
(initget 1 "Yes No Yes")
(= (getkword (strcat "\n" prompt-text " Y/N <Y>: ")) "No")
)
(progn
(initget 1 "Yes No No")
(= (getkword (strcat "\n" prompt-text " Y/N <N>: ")) "Yes")
)
)
)
;; Fehlermeldung mit optionalem Signalton
;; ssg-bell = T -> kein Ton; nil -> Ton ausgeben
(defun ssg-emsg (text)
(if (not ssg-bell) (prompt "\007"))
(terpri)
(prompt text)
(terpri)
)
;; ------------------------------------------------------------
;; LAYER-HILFSFUNKTIONEN
;; ------------------------------------------------------------
;; Layer eines angeklickten Objektes ermitteln
;; txt = Prompt-Text fuer Objektauswahl
;; Rueckgabe: Layername als String, nil wenn Abbruch
(defun ssg-get-layer (txt / sel)
(if (setq sel (entsel txt))
(cdr (assoc 8 (entget (car sel))))
)
)
;; Alle Objekte eines bestimmten Layers als Auswahlsatz liefern
;; lay-name = Layername; ent-typ = Entitaetstyp z.B. "LINE" (nil = alle)
(defun ssg-layer-ss (lay-name ent-typ)
(if ent-typ
(ssget "X" (list (cons 0 ent-typ) (cons 8 lay-name)))
(ssget "X" (list (cons 8 lay-name)))
)
)
;; Layer anlegen (falls nicht vorhanden) und optional setzen
;; lay-name = Name; color = Farbnummer als String z.B. "2"; set-aktiv = T/nil
(defun ssg-make-layer (lay-name color set-aktiv)
(if set-aktiv
(command "_LAYER" "_M" lay-name "_CO" color lay-name "")
(command "_LAYER" "_N" lay-name "_CO" color lay-name "")
)
)
;; Auswahlsatz-Iteration: Funktion fuer jedes Element aufrufen
;; ss = Auswahlsatz; func = Funktion mit einem Parameter (entity-name)
(defun ssg-ss-foreach (ss func / i ename)
(if ss
(progn
(setq i 0)
(while (setq ename (ssname ss i))
(func ename)
(setq i (1+ i))
)
)
)
)
;; Alle Elemente eines Auswahlsatzes hervorheben/zuruecksetzen
;; ss = Auswahlsatz; modus = 3 (hervorheben) / 4 (invertiert) / 0 (normal)
(defun ssg-ss-redraw (ss modus / i ename)
(if ss
(progn
(setq i 0)
(while (setq ename (ssname ss i))
(redraw ename modus)
(setq i (1+ i))
)
)
)
)
;; Auswahlsatz zu einem anderen Auswahlsatz hinzufuegen (in-place)
;; src-ss = Quell-Auswahlsatz; dest-ss = Ziel-Auswahlsatz (wird modifiziert)
(defun ssg-ss-add (src-ss dest-ss / i ename)
(if (null dest-ss) (setq dest-ss (ssadd)))
(setq i 0)
(while (setq ename (ssname src-ss i))
(ssadd ename dest-ss)
(redraw ename 3)
(setq i (1+ i))
)
dest-ss
)
;; ------------------------------------------------------------
;; BLOCK-OPERATIONEN
;; ------------------------------------------------------------
;; Zeitstempel als YYYYMMDDHHMMSS erzeugen (fuer eindeutige Blocknamen)
(defun ssg-timestamp ( / cd ds ts)
(setq cd (rtos (getvar "CDATE") 2 6))
;; cd = "20260518.143052" -> Punkt entfernen
(setq ds (substr cd 1 8))
(setq ts (substr cd 10 6))
(strcat ds ts)
)
;; Eindeutigen Blocknamen aus Einfuegepunkt + Zeitstempel erzeugen
;; pt = Einfuegepunkt (Liste); Rueckgabe: Blockname als String
(defun ssg-make-blockname (pt / k1 k2)
(setq k1 (strcat (itoa (abs (fix (car pt))))
(itoa (abs (fix (cadr pt))))
(itoa (abs (fix (caddr pt)))))
k2 (substr (rtos (getvar "cdate") 2 9) 10 9)
)
(strcat k1 k2)
)
;; Einzel-Block einfuegen mit Layer anlegen
;; lay-name = Ziel-Layer; color = Layerfarbe
;; blk-pfad = vollstaendiger Blockpfad (ohne Erweiterung)
;; pt = Einfuegepunkt; xscale yscale = Skalierung ("" = 1)
;; rotation = Drehwinkel als String oder pause fuer interaktiv
(defun ssg-insert-block (lay-name color blk-pfad pt xscale yscale rotation)
(ssg-make-layer lay-name color T)
(command "_insert" blk-pfad pt xscale yscale rotation)
)
;; Block aus Auswahlsatz erstellen und gleich wieder einfuegen
;; pt = Origin; rotation = Drehwinkel als String
;; ss = Auswahlsatz der Elemente
;; Rueckgabe: Blockname (String)
(defun ssg-make-block (pt rotation ss / bname gefunden)
(setq bname (ssg-make-blockname pt)
gefunden (tblsearch "block" bname)
)
(if (not gefunden)
(progn
(command "_block" bname pt ss "")
(command "_insert" bname pt "" "" rotation)
)
(progn
(alert (strcat "Blockname '" bname "' existiert bereits - wird uebersprungen."))
(setq bname (strcat "x" bname))
(command "_block" bname pt ss "")
(command "_insert" bname pt "" "" rotation)
)
)
bname
)
;; ------------------------------------------------------------
;; ATTRIBUT-OPERATIONEN
;; ------------------------------------------------------------
;; Attribut eines Blocks (letzte Einfuegung) aendern
;; tag = Attributbezeichner (z.B. "ARTINR")
;; wert = neuer Wert
;; ersetzen = T -> vollstaendiger Ersatz; nil -> Anfuegen
(defun ssg-attrib-set (tag wert ersetzen / obj typ attr-tag attr-wert)
(setq obj (entlast))
(while (not (equal (cdr (assoc 0 (entget obj))) "SEQEND"))
(setq typ (cdr (assoc 0 (entget obj))))
(if (equal typ "ATTRIB")
(progn
(setq attr-tag (cdr (assoc 2 (entget obj)))
attr-wert (cdr (assoc 1 (entget obj)))
)
(if (equal attr-tag tag)
(if ersetzen
(entmod (subst (cons 1 wert)
(assoc 1 (entget obj)) (entget obj)))
(entmod (subst (cons 1 (strcat attr-wert wert))
(assoc 1 (entget obj)) (entget obj)))
)
)
)
)
(setq obj (entnext obj))
)
)
;; Mehrere Attribute eines Blocks auf einmal setzen
;; attrib-alist = Assoziationsliste '(("TAG1" . "Wert1") ("TAG2" . "Wert2") ...)
(defun ssg-attrib-set-many (attrib-alist / obj typ tag wert)
(setq obj (entlast))
(while (not (equal (cdr (assoc 0 (entget obj))) "SEQEND"))
(setq typ (cdr (assoc 0 (entget obj))))
(if (equal typ "ATTRIB")
(progn
(setq tag (cdr (assoc 2 (entget obj))))
(setq wert (cdr (assoc tag attrib-alist)))
(if (and wert (> (strlen wert) 0))
(entmod (subst (cons 1 wert)
(assoc 1 (entget obj)) (entget obj)))
)
)
)
(setq obj (entnext obj))
)
)
;; Alle Attribute eines INSERT-Entity als Assoziationsliste lesen.
;; ent = Entity-Name eines INSERT mit Attributen.
;; Rueckgabe: (("TAG1" . "Wert1") ("TAG2" . "Wert2") ...) oder nil
(defun ssg-attrib-read (ent / e ed result)
(setq e (entnext ent))
(while e
(setq ed (entget e))
(if (equal (cdr (assoc 0 ed)) "SEQEND")
(setq e nil)
(progn
(if (equal (cdr (assoc 0 ed)) "ATTRIB")
(setq result (cons (cons (cdr (assoc 2 ed)) (cdr (assoc 1 ed))) result))
)
(setq e (entnext e))
)
)
)
(reverse result)
)
;; Default-Attribute aus einer Definitionsliste erzeugen.
;; attrib-defs = Liste von (TAG DEFAULT) Paaren, z.B. '(("TYP" "A") ("NR" "0"))
;; Rueckgabe: Assoziationsliste (("TYP" . "A") ("NR" . "0") ...)
(defun ssg-attrib-defaults (attrib-defs / result)
(foreach def attrib-defs
(setq result (cons (cons (car def) (cadr def)) result))
)
(reverse result)
)
;; Gegebene Attribute mit Defaults zusammenfuehren.
;; given = alist mit Ueberschreibungen (darf nil sein)
;; attrib-defs = Definitionsliste ((TAG DEFAULT) ...)
;; Rueckgabe: vollstaendige alist mit allen Tags
(defun ssg-attrib-merge (given attrib-defs / defaults pair existing)
(setq defaults (ssg-attrib-defaults attrib-defs))
(if given
(foreach pair given
(setq existing (assoc (car pair) defaults))
(if existing
(setq defaults (subst pair existing defaults))
(setq defaults (append defaults (list pair)))
)
)
)
defaults
)
;; Unsichtbare ATTDEF-Entities bei (0,0) erzeugen.
;; Muss VOR dem _BLOCK-Befehl aufgerufen werden, damit die ATTDEFs
;; Teil der Blockdefinition werden.
;; attrib-defs = Definitionsliste ((TAG DEFAULT) ...)
;; text-height = Texthoehe der ATTDEFs (z.B. 50.0)
(defun ssg-attrib-make-defs (attrib-defs text-height / ypos)
(setq ypos 0.0)
(foreach def attrib-defs
(entmake (list
'(0 . "ATTDEF")
'(8 . "0")
(cons 10 (list 0.0 ypos 0.0))
(cons 40 text-height)
(cons 1 (cadr def))
(cons 3 (car def))
(cons 2 (car def))
'(70 . 1)
))
(setq ypos (- ypos (* text-height (ssg-cfg-or "infrastruktur" "attdef_y_spacing_factor" 2.0))))
)
)
;; Attribute eines bestimmten INSERT-Entity setzen (nicht entlast).
;; ent = Entity-Name des INSERT-Blocks
;; attrib-alist = (("TAG" . "Wert") ...)
(defun ssg-attrib-set-on (ent attrib-alist / obj ed typ tag wert)
(setq obj (entnext ent))
(while obj
(setq ed (entget obj))
(setq typ (cdr (assoc 0 ed)))
(if (equal typ "SEQEND") (setq obj nil)
(progn
(if (equal typ "ATTRIB")
(progn
(setq tag (cdr (assoc 2 ed)))
(setq wert (cdr (assoc tag attrib-alist)))
(if (and wert (= (type wert) 'STR) (> (strlen wert) 0))
(progn
(entmod (subst (cons 1 wert) (assoc 1 ed) ed))
(entupd obj)
)
)
)
)
(setq obj (entnext obj))
)
)
)
)
;; ============================================================
;; GEMEINSAMES ATTRIBUT-SCHEMA FUER STRECKEN-BLOECKE
;; (Gefaellestrecke + VarioFoerderer, feste Reihenfolge)
;; ============================================================
;; Vorderteil (immer vorhanden). Bezeichnung = Blockname (GF_n/VF_n),
;; Artinr. fest 6220 (alle GF/VF). TYP-Wert wird zur Laufzeit gesetzt.
;; ID zuerst (global, jeder eingefuegte Baustein - Kreisel/GF/VF - erhaelt eine
;; neue ID), danach Bezeichnung (= Blockname). Hoehen/Delta mit Einheit _mm.
(setq *strecke-attr-front*
'(("ID" "")
("Bezeichnung" "")
("Artinr." "6220")
("MONTAGEHOEHE_m" "0.000")
("HOEHE_VON_mm" "0")
("HOEHE_BIS_mm" "0")
("DELTA_H_mm" "0")
("DELTA_L_mm" "0")
("TYP" "Streckengruppe")
("SEITE_AS" "rechts")
("SEITE_ES" "rechts")
("ANZAHL_GF" "0")
("L_GF_m" "0.000")
("GF_WINKEL" "0.0")))
;; Mittelteil - nur fuer TYP "Streckengruppe" (mehrsegmentig/mit Bogen bzw. VF).
;; Eine einsegmentige Gefaellestrecke ohne Bogen ("Gefaellestrecke") bekommt
;; diese Attribute NICHT.
(setq *strecke-attr-gruppe*
'(("GF_Bogen_L_90" "0")
("GF_Bogen_L_60" "0")
("GF_Bogen_L_30" "0")
("GF_Bogen_R_90" "0")
("GF_Bogen_R_60" "0")
("GF_Bogen_R_30" "0")
("ANZAHL_VF" "0")
("MOTORSEITE" "")
("L_VF_m" "0.000")
("ANTRIEBFAHRTRICHTUNG" "Auf")
("VF_WINKEL" "0")
("VF_Bogen_A_90" "0")
("VF_Bogen_A_60" "0")
("VF_Bogen_A_30" "0")
("VF_Bogen_I_90" "0")
("VF_Bogen_I_60" "0")
("VF_Bogen_I_30" "0")))
;; Hinterteil (immer vorhanden). ANZAHL_SEPARATOR-Wert wird zur Laufzeit gesetzt
;; (einsegmentige Gefaellestrecke: 1; Streckengruppe: gezaehlt).
(setq *strecke-attr-hinten*
'(("ANZAHL_SEPARATOR" "1")
("ANZAHL_SCANNER" "0")))
;; Geordnete ATTDEF-Definitionsliste fuer einen Strecken-Block-Typ.
;; typ "Gefaellestrecke" -> Vorderteil + Hinterteil (reduziert)
;; sonst ("Streckengruppe") -> Vorderteil + Mittelteil + Hinterteil (voll)
(defun ssg-strecke-attrib-defs (typ)
(if (= typ "Gefaellestrecke")
(append *strecke-attr-front* *strecke-attr-hinten*)
(append *strecke-attr-front* *strecke-attr-gruppe* *strecke-attr-hinten*)))
;; Assoziationsliste in ATTDEF-Definitionsliste konvertieren.
;; alist = (("TAG" . "Wert") ...) -> ((TAG Wert) ...)
;; Passend fuer ssg-attrib-make-defs.
(defun ssg-attrib-alist-to-defs (alist / result)
(foreach pair alist
(setq result (cons (list (car pair) (cdr pair)) result))
)
(reverse result)
)
;; Block (.dwg) temporaer einfuegen, Attribute lesen, Block loeschen.
;; dwg-pfad = vollstaendiger Pfad zur .dwg Datei
;; Rueckgabe: Assoziationsliste (("TAG" . "Wert") ...) oder nil
(defun ssg-attrib-read-dwg (dwg-pfad / tmpEnt srcAttribs oldAttreq oldAttdia)
(if (not (findfile dwg-pfad))
(progn
(princ (strcat "\nFEHLER: Block nicht gefunden: " dwg-pfad))
nil
)
(progn
(setq oldAttreq (getvar "ATTREQ"))
(setq oldAttdia (getvar "ATTDIA"))
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
(command "_.INSERT" dwg-pfad (list 0.0 0.0 0.0) 1 1 0)
(setvar "ATTREQ" oldAttreq)
(setvar "ATTDIA" oldAttdia)
(setq tmpEnt (entlast))
(setq srcAttribs (ssg-attrib-read tmpEnt))
(command "_.ERASE" tmpEnt "")
srcAttribs
)
)
)
;; Attribut eines Blocks anhand seines Handle suchen und aendern
;; handle = Entity-Handle (String) des INSERT
;; tag = Attributbezeichner
;; wert = neuer Wert
;; ersetzen = T -> ersetzen; nil -> anhaengen
(defun ssg-attrib-by-handle (handle tag wert ersetzen / e typ blk-tag blk-wert fertig)
(setq e (entnext)
fertig nil
)
(while (and e (not fertig))
(setq typ (cdr (assoc 0 (entget e))))
(if (and (equal (cdr (assoc 5 (entget e))) handle)
(equal typ "INSERT")
(equal (cdr (assoc 66 (entget e))) 1)
)
(progn
(while (not (= (cdr (assoc 0 (entget e))) "SEQEND"))
(if (equal (cdr (assoc 0 (entget e))) "ATTRIB")
(progn
(setq blk-tag (cdr (assoc 2 (entget e)))
blk-wert (cdr (assoc 1 (entget e)))
)
(if (equal blk-tag tag)
(if ersetzen
(entmod (subst (cons 1 wert)
(assoc 1 (entget e)) (entget e)))
(entmod (subst (cons 1 (strcat blk-wert wert))
(assoc 1 (entget e)) (entget e)))
)
)
)
)
(setq e (entnext e))
)
(setq fertig T)
)
)
(setq e (entnext e))
)
)
;; ------------------------------------------------------------
;; DIALOG-STANDARD-PATTERN
;; Vorlage fuer DCL-Dialoge: laden, initialisieren, starten
;; Verwendung:
;; (ssg-dialog-run "pfad/dialog.dcl" "dialog-name" init-fn accept-fn)
;;
;; init-fn = Funktion ohne Parameter, setzt Tiles und Actions
;; accept-fn = Funktion ohne Parameter, liest Tiles aus
;; ------------------------------------------------------------
(defun ssg-dialog-run (dcl-pfad dialog-name init-fn accept-fn / dat)
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog dialog-name dat))
(progn (alert "Dialog konnte nicht geladen werden.") (exit))
)
(if init-fn (init-fn))
(action_tile "accept" "(if accept-fn (accept-fn)) (done_dialog 1)")
(action_tile "cancel" "(done_dialog 0)")
(start_dialog)
(unload_dialog dat)
)
;; ------------------------------------------------------------
;; ZOOM-HILFSFUNKTIONEN
;; ------------------------------------------------------------
;; Aktuelle View-Groesse merken
(defun ssg-zoom-save ()
(setq _ssg-view-size (getvar "VIEWSIZE"))
)
;; Auf gespeicherte View-Groesse zurueckschalten (wenn veraendert)
(defun ssg-zoom-restore ()
(if (and _ssg-view-size (/= (getvar "VIEWSIZE") _ssg-view-size))
(command "_ZOOM" "_P")
)
)
;; ------------------------------------------------------------
;; KONFIGURATION AUS JSON LADEN
;; Liest data/json/component_defaults.json und stellt Werte
;; ueber (ssg-cfg "section" "key") bereit.
;; Struktur: {"section": {"key": wert, ...}, ...}
;; Ergebnis: *ssg-config* = (("section" ("key" . wert) ...) ...)
;; ------------------------------------------------------------
(setq *ssg-config* nil)
;; Datei zeilenweise einlesen (wie omni:read-file-lines)
(defun ssg-read-file-lines (datei / f zeile ergebnis)
(setq f (open datei "r"))
(if (null f)
nil
(progn
(setq ergebnis nil)
(while (setq zeile (read-line f))
(setq ergebnis (cons zeile ergebnis))
)
(close f)
(reverse ergebnis)
)
)
)
;; Whitespace und Komma trimmen
(defun ssg-cfg-trim (s / len)
(setq s (vl-string-trim " \t\r\n" s))
(setq len (strlen s))
(if (and (> len 0) (= (substr s len 1) ","))
(setq s (substr s 1 (1- len)))
)
(vl-string-trim " \t\r\n" s)
)
;; JSON-Wert parsen (String, Zahl, null, true, false, Array)
(defun ssg-cfg-parse-value (val-str / len)
(setq val-str (ssg-cfg-trim val-str))
(cond
((= val-str "null") nil)
((= val-str "true") T)
((= val-str "false") nil)
;; String
((= (substr val-str 1 1) "\"")
(setq len (strlen val-str))
(if (and (> len 1) (= (substr val-str len 1) "\""))
(substr val-str 2 (- len 2))
val-str
)
)
;; Array [...] -> Liste von Werten parsen
((= (substr val-str 1 1) "[")
(ssg-cfg-parse-array val-str)
)
;; Zahl
(T
(if (vl-string-search "." val-str)
(atof val-str)
(atoi val-str)
)
)
)
)
;; Einfaches JSON-Array parsen: [1, 2, 3.5, "text"]
(defun ssg-cfg-parse-array (arr-str / inhalt teile ergebnis item)
(setq inhalt (ssg-cfg-trim arr-str))
;; Klammern entfernen
(setq inhalt (substr inhalt 2 (- (strlen inhalt) 2)))
;; An Kommas aufteilen (einfach: kein verschachteltes Array)
(setq teile (ssg-cfg-split-comma inhalt))
(setq ergebnis nil)
(foreach item teile
(setq ergebnis (cons (ssg-cfg-parse-value item) ergebnis))
)
(reverse ergebnis)
)
;; String an Kommas aufteilen -> Liste von Strings
(defun ssg-cfg-split-comma (s / result current i ch)
(setq result nil current "" i 1)
(repeat (strlen s)
(setq ch (substr s i 1))
(if (= ch ",")
(progn
(setq result (cons current result))
(setq current "")
)
(setq current (strcat current ch))
)
(setq i (1+ i))
)
(if (> (strlen (vl-string-trim " " current)) 0)
(setq result (cons current result))
)
(reverse result)
)
;; Key-Value-Zeile parsen: "key": wert -> ("key" . wert)
(defun ssg-cfg-parse-kv (zeile / pos key rest pos2 val)
(setq zeile (ssg-cfg-trim zeile))
(if (and (> (strlen zeile) 0) (= (substr zeile 1 1) "\""))
(progn
(setq pos (vl-string-search "\"" zeile 1))
(if pos
(progn
(setq key (substr zeile 2 (1- pos)))
(setq rest (substr zeile (+ pos 2)))
(setq pos2 (vl-string-search ":" rest))
(if pos2
(cons key (ssg-cfg-parse-value (substr rest (+ pos2 2))))
)
)
)
)
)
)
;; --- JSON-Array von flachen Objekten parsen ---
;; Verwendet ssg-cfg-trim und ssg-cfg-parse-kv aus ssg_core.
;; Rueckgabe: Liste von Alists (("key" . wert) ...)
(defun ssg-parse-json-array (zeilen / in-obj obj ergebnis zeile kv trimmed)
(setq in-obj nil obj nil ergebnis nil)
(foreach zeile zeilen
(setq trimmed (ssg-cfg-trim zeile))
(cond
((= trimmed "{")
(setq in-obj T obj nil))
((or (= trimmed "}") (= trimmed "},"))
(if (and in-obj obj)
(setq ergebnis (cons (reverse obj) ergebnis)))
(setq in-obj nil))
(in-obj
(setq kv (ssg-cfg-parse-kv trimmed))
(if kv (setq obj (cons kv obj))))
)
)
(reverse ergebnis)
)
;; JSON-Datei als flaches Array laden
;; Rueckgabe: Liste von Alists oder nil bei Fehler
(defun ssg-load-json (datei / zeilen)
(setq zeilen (ssg-read-file-lines datei))
(if zeilen (ssg-parse-json-array zeilen))
)
;; Wert aus Alist lesen: (ssg-val alist "key")
(defun ssg-val (alist key)
(cdr (assoc key alist))
)
;; Verschachteltes JSON-Objekt parsen (1 Ebene tief)
;; {"section": {"key": val, ...}, ...}
;; -> (("section" ("key" . val) ...) ...)
(defun ssg-cfg-parse-nested (zeilen / ergebnis section section-data
trimmed kv in-section in-inner)
(setq ergebnis nil
section nil
section-data nil
in-section nil
in-inner nil
)
(foreach zeile zeilen
(setq trimmed (ssg-cfg-trim zeile))
(cond
;; Aeusseres { oder } ignorieren (Wurzel-Objekt)
((and (not in-section) (= trimmed "{")) nil)
((and (not in-section) (= trimmed "}")) nil)
;; Section-Start: "name": {
((and (not in-inner) (vl-string-search ": {" trimmed))
(setq kv (ssg-cfg-parse-kv
(substr trimmed 1 (vl-string-search ": {" trimmed))))
;; kv ist hier nur der Key-Teil, der Rest ist ": {"
;; Einfacher: Key direkt extrahieren
(setq section (substr trimmed 2
(1- (vl-string-search "\"" trimmed 1))))
(setq section-data nil)
(setq in-section T in-inner T)
)
;; Section-Ende: }
((and in-inner (or (= trimmed "}") (= trimmed "},")))
(if section
(setq ergebnis (cons (cons section (reverse section-data)) ergebnis))
)
(setq in-section nil in-inner nil section nil section-data nil)
)
;; Key-Value innerhalb einer Section
(in-inner
(setq kv (ssg-cfg-parse-kv trimmed))
(if kv (setq section-data (cons kv section-data)))
)
)
)
(reverse ergebnis)
)
;; Konfiguration laden
;; Sucht data/json/component_defaults.json ueber DXFM_DATA
(defun ssg-load-config ( / data-pfad cfg-datei zeilen)
(setq data-pfad (getenv "DXFM_DATA"))
(if (null data-pfad)
(princ "\n[CFG] WARNUNG: DXFM_DATA nicht gesetzt, Config nicht geladen.")
(progn
(setq cfg-datei (strcat data-pfad "/json/component_defaults.json"))
(if (not (findfile cfg-datei))
(princ (strcat "\n[CFG] WARNUNG: " cfg-datei " nicht gefunden."))
(progn
(setq zeilen (ssg-read-file-lines cfg-datei))
(if zeilen
(progn
(setq *ssg-config* (ssg-cfg-parse-nested zeilen))
(princ (strcat "\n[CFG] Config geladen: "
(itoa (length *ssg-config*)) " Sektionen."))
)
(princ (strcat "\n[CFG] WARNUNG: Leere Config-Datei: " cfg-datei))
)
)
)
)
)
(princ)
)
;; Wert aus Config lesen: (ssg-cfg "section" "key")
;; Gibt den Wert oder nil zurueck.
(defun ssg-cfg (section key / sec-data)
(if *ssg-config*
(progn
(setq sec-data (cdr (assoc section *ssg-config*)))
(if sec-data
(cdr (assoc key sec-data))
)
)
)
)
;; Wert mit Fallback: (ssg-cfg-or "section" "key" default)
(defun ssg-cfg-or (section key default / val)
(setq val (ssg-cfg section key))
(if val val default)
)
;; ============================================================
;; INI-STYLE CONFIG-PARSER (Standard fuer alle cfg/*.cfg-Dateien)
;;
;; Format:
;; [Abschnitt]
;; Key = Wert (einzelner Wert)
;; Key = Wert1, Wert2, Wert3 (kommagetrennte Liste, z.B. fuer wcmatch)
;; # Kommentar / Leerzeile werden ignoriert
;;
;; Verwendung:
;; (setq cfg (ssg-load-ini pfad))
;; (ssg-ini-get cfg "sektion" "key" "default")
;; (ssg-ini-list cfg "sektion" "key" "a,b,c") ; normalisiert zu "a,b,c" (wcmatch-tauglich)
;; ============================================================
;; Zeilen einer .cfg-Datei in verschachtelte Alist parsen.
;; Rueckgabe: (("sektion" ("key" . "wert") ...) ...)
(defun ssg-ini-parse-lines (zeilen / ergebnis section sec-data trimmed pos key val)
(setq ergebnis nil section nil sec-data nil)
(foreach zeile zeilen
(setq trimmed (vl-string-trim " \t\r\n" zeile))
(cond
;; Leerzeile oder Kommentar
((or (= trimmed "") (= (substr trimmed 1 1) "#")) nil)
;; Abschnitt: [name]
((and (= (substr trimmed 1 1) "[")
(= (substr trimmed (strlen trimmed) 1) "]"))
(if section
(setq ergebnis (cons (cons section (reverse sec-data)) ergebnis)))
(setq section (substr trimmed 2 (- (strlen trimmed) 2)))
(setq sec-data nil)
)
;; Key=Wert
((and section (setq pos (vl-string-search "=" trimmed)))
(setq key (vl-string-trim " \t" (substr trimmed 1 pos)))
(setq val (vl-string-trim " \t" (substr trimmed (+ pos 2))))
(setq sec-data (cons (cons key val) sec-data))
)
)
)
(if section
(setq ergebnis (cons (cons section (reverse sec-data)) ergebnis)))
(reverse ergebnis)
)
;; .cfg-Datei laden und als verschachtelte Alist zurueckgeben, oder nil.
(defun ssg-load-ini (cfg-datei / zeilen)
(setq zeilen (ssg-read-file-lines cfg-datei))
(if zeilen (ssg-ini-parse-lines zeilen))
)
;; Einzelwert aus geladener INI-Alist lesen, mit Fallback.
;; ini-data = Rueckgabe von ssg-load-ini
(defun ssg-ini-get (ini-data section key default / sec-data val)
(setq sec-data (cdr (assoc section ini-data)))
(setq val (if sec-data (cdr (assoc key sec-data))))
(if (and val (> (strlen val) 0)) val default)
)
;; Kommagetrennten Wert aus geladener INI-Alist lesen und normalisieren
;; (Leerzeichen um Kommas entfernen, leere Teile verwerfen).
;; default-str = Fallback als kommagetrennter String, falls Config/Key fehlt.
;; Rueckgabe: kommagetrennter String, z.B. "KR_*,KREISEL_*" (wcmatch-tauglich)
(defun ssg-ini-list (ini-data section key default-str / raw teile ergebnis item first)
(setq raw (ssg-ini-get ini-data section key default-str))
(setq teile (ssg-cfg-split-comma raw))
(setq ergebnis "" first T)
(foreach item teile
(setq item (vl-string-trim " \t" item))
(if (> (strlen item) 0)
(progn
(setq ergebnis (if first item (strcat ergebnis "," item)))
(setq first nil)
)
)
)
ergebnis
)
(prompt "\nssg_core.lsp geladen.")
(princ)
+276
View File
@@ -0,0 +1,276 @@
;; ============================================================
;; SSG_DBG.LSP - Debug-Routinensammlung
;;
;; Funktionen:
;; (dbgopen "dateiname.dbg") - Oeffnet Debug-Datei
;; (dbgclose) - Schliesst Debug-Datei
;; (dbgon) - Aktiviert Debug-Ausgabe
;; (dbgoff) - Deaktiviert Debug-Ausgabe
;; (dbgf "funktionsname") - Schreibt Funktionseintritt mit {
;; (dbgreturn wert) - Schreibt Funktionsaustritt mit } = wert
;; (dbg wert) - Schreibt Variable mit aktuellem Wert
;; (dbgp "text") - Debug-Print (Alias fuer dbgmsg)
;; (dbgmsg "text") - Freitext-Nachricht loggen
;;
;; Strategie: dbgf/dbg/dbgmsg puffern im Speicher.
;; dbgreturn flusht den Puffer auf die Platte (open/append/close).
;; So hat jede Funktion mindestens einen Schreibvorgang,
;; ohne dass jeder einzelne dbg-Aufruf die Datei oeffnet.
;;
;; dbgon/dbgoff steuert, ob Ausgaben geschrieben werden.
;; Ein (dbgoff) VOR (dbgopen) verhindert das Anlegen der Datei.
;;
;; Beispiel:
;; (dbgopen "test.dbg" "DXFM_LOG")
;; (dbgf "meine-funktion")
;; (dbg 'x)
;; (dbgreturn ergebnis) ; <-- hier wird alles geschrieben
;; (dbgclose)
;; ============================================================
;; Globale Variablen
(setq *dbg-path* nil) ; Voller Dateipfad (String)
(setq *dbg-indent* 0) ; Aktuelle Einruecktiefe
(setq *dbg-active* T) ; Debug-Ausgabe aktiv (Standard: ein)
(setq *dbg-buffer* nil) ; Zeilenpuffer (Liste von Strings)
;; ------------------------------------------------------------
;; DBGON - Debug-Ausgabe aktivieren
;; ------------------------------------------------------------
(defun dbgon ()
(setq *dbg-active* T)
(princ)
)
;; ------------------------------------------------------------
;; DBGOFF - Debug-Ausgabe deaktivieren
;; ------------------------------------------------------------
(defun dbgoff ()
(setq *dbg-active* nil)
(princ)
)
;; ------------------------------------------------------------
;; DBG-FLUSH - Puffer auf Platte schreiben (open/append/close)
;; ------------------------------------------------------------
(defun dbg-flush (/ fh)
(if (and *dbg-path* *dbg-buffer*)
(progn
(setq fh (open *dbg-path* "a"))
(if fh
(progn
(foreach line (reverse *dbg-buffer*)
(write-line line fh)
)
(close fh)
)
)
(setq *dbg-buffer* nil)
)
)
)
;; ------------------------------------------------------------
;; DBG-BUFWRITE - Zeile in den Puffer schreiben
;; ------------------------------------------------------------
(defun dbg-bufwrite (line)
(setq *dbg-buffer* (cons line *dbg-buffer*))
)
;; ------------------------------------------------------------
;; DBGOPEN - Debug-Datei oeffnen
;; Wenn *dbg-active* nil ist, wird keine Datei angelegt.
;; Parameter:
;; filename - Dateiname (z.B. "test.dbg")
;; envvar - Optional: Name einer Umgebungsvariable fuer das
;; Zielverzeichnis (z.B. "DXFM_LOG").
;; Wenn nil oder nicht gesetzt, wird "." verwendet.
;; ------------------------------------------------------------
(defun dbgopen (filename envvar / dir fullpath fh ts)
(if (not *dbg-active*)
(progn
(prompt "\n[DBG] Debug deaktiviert - keine Datei angelegt.")
(princ)
)
(progn
;; Verzeichnis bestimmen
(setq dir nil)
(if (and envvar (/= envvar ""))
(progn
(setq dir (getenv envvar))
;;(prompt (strcat "\n[DBG] getenv " envvar " = " (if dir dir "nil")))
)
)
(if (or (not dir) (= dir ""))
(setq dir ".")
)
;; Backslash am Ende sicherstellen
(if (and (/= (substr dir (strlen dir) 1) "\\")
(/= (substr dir (strlen dir) 1) "/"))
(setq dir (strcat dir "\\"))
)
;; Verzeichnis anlegen falls es nicht existiert
(if (not (vl-file-directory-p (vl-string-right-trim "\\/" dir)))
(progn
(vl-mkdir (vl-string-right-trim "\\/" dir))
(prompt (strcat "\n[DBG] Verzeichnis angelegt: " dir))
)
)
(setq fullpath (strcat dir filename))
;; Datei mit "w" erstellen/leeren, Header schreiben, sofort schliessen
(setq fh (open fullpath "w"))
(if fh
(progn
(setq *dbg-path* fullpath)
(setq *dbg-indent* 0)
(setq *dbg-buffer* nil)
(setq ts (menucmd "M=$(edtime,$(getvar,date),YYYY-MO-DD HH:MM:SS)"))
(if (not ts) (setq ts "(kein Zeitstempel)"))
(write-line (strcat "=== DEBUG START " ts " ===") fh)
(close fh)
(prompt (strcat "\n[DBG] Debug-Datei geoeffnet: " fullpath))
)
(prompt (strcat "\n[DBG] FEHLER: Konnte Debug-Datei nicht oeffnen: " fullpath))
)
(princ)
)
)
)
;; ------------------------------------------------------------
;; DBGCLOSE - Debug-Datei schliessen (Puffer + Abschluss schreiben)
;; ------------------------------------------------------------
(defun dbgclose ( / ts)
(if *dbg-path*
(progn
(setq ts (menucmd "M=$(edtime,$(getvar,date),YYYY-MO-DD HH:MM:SS)"))
(if (not ts) (setq ts "(kein Zeitstempel)"))
(dbg-bufwrite (strcat "=== DEBUG ENDE " ts " ==="))
(dbg-flush)
(setq *dbg-path* nil)
(setq *dbg-indent* 0)
(prompt "\n[DBG] Debug-Datei geschlossen.")
)
(prompt "\n[DBG] Keine Debug-Datei geoeffnet.")
)
(princ)
)
;; ------------------------------------------------------------
;; DBG-TABS - Hilfsfunktion: Erzeugt Einrueckung
;; ------------------------------------------------------------
(defun dbg-tabs (/ result)
(setq result "")
(repeat *dbg-indent*
(setq result (strcat result "\t"))
)
result
)
;; ------------------------------------------------------------
;; DBG-TOSTRING - Hilfsfunktion: Wert in String umwandeln
;; ------------------------------------------------------------
(defun dbg-tostring (val)
(cond
((= val nil) "nil")
((= (type val) 'STR) (strcat "\"" val "\""))
((= (type val) 'INT) (itoa val))
((= (type val) 'REAL) (rtos val 2 6))
((= (type val) 'LIST)
(strcat "(" (dbg-list-tostring val) ")")
)
((= (type val) 'ENAME) (strcat "<Entity: " (vl-princ-to-string val) ">"))
(T (vl-princ-to-string val))
)
)
;; ------------------------------------------------------------
;; DBG-LIST-TOSTRING - Hilfsfunktion: Liste in String
;; ------------------------------------------------------------
(defun dbg-list-tostring (lst / result first)
(setq result "" first T)
(foreach item lst
(if first
(setq first nil)
(setq result (strcat result " "))
)
(setq result (strcat result (dbg-tostring item)))
)
result
)
;; ------------------------------------------------------------
;; DBGF - Funktionseintritt loggen (puffert nur)
;; Schreibt "funktionsname(){" und erhoeht Einrueckung
;; ------------------------------------------------------------
(defun dbgf (funcname)
(if (and *dbg-path* *dbg-active*)
(progn
(dbg-bufwrite (strcat (dbg-tabs) funcname "(){"))
(setq *dbg-indent* (1+ *dbg-indent*))
)
)
(princ)
)
;; ------------------------------------------------------------
;; DBGRETURN - Funktionsaustritt loggen + FLUSH auf Platte
;; Verringert Einrueckung und schreibt "} = wert"
;; ------------------------------------------------------------
(defun dbgreturn (retval)
(if (and *dbg-path* *dbg-active*)
(progn
(setq *dbg-indent* (max 0 (1- *dbg-indent*)))
(if retval
(dbg-bufwrite (strcat (dbg-tabs) "} = " (dbg-tostring retval)))
(dbg-bufwrite (strcat (dbg-tabs) "}"))
)
(dbg-flush)
)
)
retval
)
;; ------------------------------------------------------------
;; DBG - Variable/Wert loggen (puffert nur)
;; Aufruf: (dbg 'varname) oder (dbg wert)
;; ------------------------------------------------------------
(defun dbg (varname / val)
(if (and *dbg-path* *dbg-active*)
(if (= (type varname) 'SYM)
(progn
(setq val (eval varname))
(dbg-bufwrite (strcat (dbg-tabs) (vl-symbol-name varname) "=" (dbg-tostring val)))
)
(dbg-bufwrite (strcat (dbg-tabs) "value=" (dbg-tostring varname)))
)
)
(princ)
)
;; ------------------------------------------------------------
;; DBGMSG - Freitext-Nachricht loggen (puffert nur)
;; ------------------------------------------------------------
(defun dbgmsg (msg)
(if (and *dbg-path* *dbg-active*)
(dbg-bufwrite (strcat (dbg-tabs) ">> " msg))
)
(princ)
)
;; ------------------------------------------------------------
;; DBGP - Alias fuer DBGMSG (debug print)
;; ------------------------------------------------------------
(defun dbgp (msg) (dbgmsg msg))
;; ------------------------------------------------------------
;; DBGFLUSH - Puffer sofort auf Platte schreiben (oeffentlich)
;; Nuetzlich wenn kein dbgreturn folgt (z.B. Startup-Code)
;; ------------------------------------------------------------
(defun dbgflush ()
(dbg-flush)
(princ)
)
(prompt "\nssg_dbg geladen.")
(princ)
+165
View File
@@ -0,0 +1,165 @@
;; ============================================================
;; SSG_DIALOG.LSP - Standard-Pattern fuer Modul-Einfuege-Dialoge
;; Kapselt das wiederkehrende Muster aus den ACADSST-Makros:
;; - DCL-Dialog mit Vorschaubild
;; - Radio-/List-Auswahl -> Blockname + Parameter setzen
;; - Block einfuegen + Attribute befuellen
;;
;; Setzt ssg_core.lsp voraus.
;; Ursprung: ILS2100/*.lsp, HFS/hfs_mod.lsp (Schoenenberger)
;; Bereinigt und verallgemeinert: 2025
;; ============================================================
;; ------------------------------------------------------------
;; VORSCHAU-BILD im Dialog aktualisieren
;; tile-name = Name des image-Tiles im DCL (z.B. "anzeige")
;; slide-lib = Pfad zur .slb-Datei ohne Erweiterung (z.B. "m:/acadsst/ils2100")
;; slide-name = Name des Slides in der Bibliothek
;; Hintergrundfarbe -18 = AutoCAD-Grafik-Hintergrund
;; ------------------------------------------------------------
(defun ssg-dia-show-slide (tile-name slide-lib slide-name / breite hoehe)
(setq breite (dimx_tile tile-name)
hoehe (dimy_tile tile-name)
)
(start_image tile-name)
(fill_image 0 0 breite hoehe (ssg-cfg-or "infrastruktur" "dialog_preview_bg_color" -18))
(slide_image 0 0 breite hoehe (strcat slide-lib "(" slide-name ")"))
(end_image)
)
;; Vorschau mit Index-basierter Auswahl aktualisieren
;; tile-name = image-Tile-Name
;; idx-str = aktueller Auswahlindex als String (wie get_tile liefert)
;; slide-lib = Pfad zur Slide-Bibliothek
;; slide-list = Liste der Slide-Namen, Index entspricht dem Radio-Index
(defun ssg-dia-update-preview (tile-name idx-str slide-lib slide-list / idx)
(setq idx (atoi idx-str))
(if (and (>= idx 0) (< idx (length slide-list)))
(ssg-dia-show-slide tile-name slide-lib (nth idx slide-list))
)
)
;; ------------------------------------------------------------
;; GENERISCHER MODUL-DIALOG
;; Vereinfacht das haeufige Muster:
;; 1. DCL laden, Tiles initialisieren
;; 2. ACTION_TILE fuer Auswahl-Tile (aktualisiert Vorschau)
;; 3. accept/cancel
;; 4. Rueckgabe: ausgewaehlter Index oder nil bei Abbruch
;;
;; dcl-pfad = vollstaendiger Pfad zur .dcl-Datei
;; dialog-id = Name des Dialogs in der .dcl
;; select-tile= Name des List/Radio-Tiles fuer die Auswahl
;; start-val = Start-Auswahl als String (z.B. "0")
;; preview-tile= Name des image-Tiles (nil = kein Vorschaubild)
;; slide-lib = Pfad der Slide-Bibliothek (nil = kein Vorschaubild)
;; slide-list = Liste der Slide-Namen entsprechend Auswahl-Index
;; extra-init = Funktion fuer weitere Tile-Initialisierungen (nil = keine)
;; extra-read = Funktion zum Auslesen weiterer Tiles bei accept (nil = keine)
;; ------------------------------------------------------------
(defun ssg-modul-dialog (dcl-pfad dialog-id select-tile start-val
preview-tile slide-lib slide-list
extra-init extra-read
/ dat ergebnis aktuell)
(setq dat (load_dialog dcl-pfad)
aktuell start-val
)
(if (not (new_dialog dialog-id dat))
(progn (alert "Dialog nicht verfuegbar.") (exit))
)
(set_tile select-tile start-val)
(if (and preview-tile slide-lib slide-list)
(ssg-dia-update-preview preview-tile start-val slide-lib slide-list)
)
(if extra-init (extra-init))
(action_tile select-tile
(strcat
"(setq aktuell (get_tile \"" select-tile "\"))"
(if (and preview-tile slide-lib slide-list)
(strcat "(ssg-dia-update-preview \"" preview-tile "\" aktuell \""
slide-lib "\" slide-list)")
""
)
)
)
(action_tile "accept"
(strcat
"(setq ergebnis aktuell)"
(if extra-read "(extra-read)" "")
"(done_dialog 1)"
)
)
(action_tile "cancel" "(done_dialog 0)")
(start_dialog)
(unload_dialog dat)
ergebnis
)
;; ------------------------------------------------------------
;; BLOCK-MODUL EINFUEGEN - Standardsequenz
;; Kapselt das immer gleiche Muster:
;; 1. Layer anlegen
;; 2. Einfuegepunkt abfragen
;; 3. Block-Kennung (eindeutiger Name) erstellen
;; 4. Block einfuegen (mit Winkel-Abfrage oder fest)
;; 5. Attribute setzen
;;
;; lay-name = Ziel-Layer
;; lay-color = Layerfarbe als String
;; blk-pfad = vollstaendiger Blockpfad (Laufwerk + Verzeichnis + Dateiname)
;; attrib-alist= Assoziationsliste der Attribute '(("TAG" . "Wert") ...)
;; rotation = Drehwinkel als String oder pause fuer Benutzerabfrage
;; Rueckgabe = Einfuegepunkt
;; ------------------------------------------------------------
(defun ssg-insert-modul (lay-name lay-color blk-pfad attrib-alist rotation / pt)
(ssg-make-layer lay-name lay-color T)
(setq pt (getpoint "\nEinfuegepunkt waehlen: "))
(command "_insert" blk-pfad pt "" "" rotation)
(if attrib-alist
(ssg-attrib-set-many attrib-alist)
)
pt
)
;; ------------------------------------------------------------
;; HAUPT-MAKRO TEMPLATE
;; Vorlage fuer c:BEFEHL-Definitionen nach dem SSG-Muster.
;; Kopieren und anpassen.
;;
;; Beispiel-Aufruf eines konkreten Moduls (nicht ausfuehren):
;;
;; (defun c:MEIN_MODUL ( / pt ergebnis)
;; (ssg-start "MEIN MODUL" '(("OSMODE")))
;; (setq ergebnis
;; (ssg-modul-dialog
;; (strcat lw "/acadsst/pfad/mein_dialog.dcl")
;; "DIALOG_NAME"
;; "DWG_NAME" ; Radio/List-Tile
;; (if (null m_DWG_NAME) "0" m_DWG_NAME)
;; "anzeige" ; Vorschau-Tile
;; (strcat lw "/acadsst/pfad/slb_bibliothek")
;; '("slide0" "slide1" "slide2")
;; nil ; extra-init
;; nil ; extra-read
;; )
;; )
;; (if ergebnis
;; (progn
;; (setq m_DWG_NAME ergebnis)
;; (setq pt (ssg-insert-modul "LAYER-NAME" "3"
;; (strcat lw "/acadsst/pfad/block_" ergebnis)
;; (list (cons "GRUPPE" "G1") (cons "ARTINR" "123456"))
;; pause))
;; )
;; )
;; (ssg-end)
;; )
;; ------------------------------------------------------------
(prompt "\nssg_dialog.lsp geladen.")
(princ)
+201
View File
@@ -0,0 +1,201 @@
;; ============================================================
;; SSG_ID - Eindeutige ID-Verwaltung fuer SSG_LIB Bloecke
;;
;; Jedes eingefuegte Element erhaelt ein Attribut "ID" mit
;; einer eindeutigen, vierstelligen Nummer (z.B. "0001").
;;
;; Befehle:
;; IDGENERATE - Weist dem zuletzt eingefuegten Block eine neue ID zu
;; IDSCHECK - Prueft alle Bloecke auf doppelte IDs und korrigiert sie
;;
;; Funktionen:
;; (ssg-id-max) - Hoechste ID in der Zeichnung ermitteln
;; (ssg-id-generate ent) - Neue ID erzeugen und auf Block setzen
;; (ssg-id-check-all) - Doubletten pruefen und korrigieren
;; (ssg-id-format n) - Zahl als 4-stelligen String formatieren
;; ============================================================
;; --- ID als 4-stelligen String formatieren ---
;; n = Integer (z.B. 1 -> "0001", 42 -> "0042")
(defun ssg-id-format (n / s)
(setq s (itoa n))
(while (< (strlen s) 4)
(setq s (strcat "0" s))
)
s
)
;; --- Alle exportierbaren INSERT-Entities sammeln ---
;; Gleiche Filterlogik wie csv:collect-export-blocks
(defun ssg-id-collect-blocks ( / ss-all ss-out i ename ed bname)
(setq ss-all (ssget "X" (list (cons 0 "INSERT"))))
(if (null ss-all)
nil
(progn
(setq ss-out (ssadd))
(setq i 0)
(while (setq ename (ssname ss-all i))
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
(if (or
(wcmatch bname "KR_*,KREISEL_*,ECKRAD_*")
(wcmatch (strcase bname) "AP110*,AP_110*,AP60*,AP_60*,APG110*")
(wcmatch bname "Vario*,Staustrecke*,AUS_Element*,EIN_Element*,VF_*,GF_*")
(wcmatch bname "#*")
)
(ssadd ename ss-out)
)
(setq i (1+ i))
)
(if (= (sslength ss-out) 0) nil ss-out)
)
)
)
;; --- Hoechste ID in der Zeichnung ermitteln ---
;; Durchsucht alle exportierbaren Bloecke nach dem Attribut "ID".
;; Rueckgabe: Integer (hoechste ID) oder 0 wenn keine gefunden.
(defun ssg-id-max ( / ss i ename attribs id-val id-num max-id)
(setq max-id 0)
(setq ss (ssg-id-collect-blocks))
(if ss
(progn
(setq i 0)
(while (setq ename (ssname ss i))
(setq attribs (ssg-attrib-read ename))
(setq id-val (cdr (assoc "ID" attribs)))
(if (and id-val (> (strlen id-val) 0))
(progn
(setq id-num (atoi id-val))
(if (> id-num max-id)
(setq max-id id-num)
)
)
)
(setq i (1+ i))
)
)
)
max-id
)
;; --- Neue ID erzeugen und auf einen Block setzen ---
;; ent = Entity-Name eines INSERT-Blocks mit ID-Attribut
;; Rueckgabe: Die zugewiesene ID als String oder nil bei Fehler
(defun ssg-id-generate (ent / max-id new-id new-id-str)
(if (and ent (= (cdr (assoc 0 (entget ent))) "INSERT"))
(progn
(setq max-id (ssg-id-max))
(setq new-id (1+ max-id))
(setq new-id-str (ssg-id-format new-id))
(ssg-attrib-set-on ent (list (cons "ID" new-id-str)))
(princ (strcat "\n[ID] Neue ID zugewiesen: " new-id-str))
new-id-str
)
(progn
(princ "\n[ID] FEHLER: Kein gueltiger INSERT-Block!")
nil
)
)
)
;; --- Alle Bloecke auf doppelte IDs pruefen und korrigieren ---
;; Findet Bloecke mit gleicher ID. Behaelt die erste Instanz,
;; weist Duplikaten neue IDs zu.
;; Rueckgabe: Anzahl korrigierter IDs
(defun ssg-id-check-all ( / ss i ename attribs id-val id-num
id-map entry max-id fixed-count new-id-str)
(setq ss (ssg-id-collect-blocks))
(if (null ss)
(progn
(princ "\n[IDSCHECK] Keine relevanten Bloecke gefunden.")
0
)
(progn
;; Phase 1: Alle IDs sammeln und hoechste ID ermitteln
(setq id-map nil)
(setq max-id 0)
(setq i 0)
(while (setq ename (ssname ss i))
(setq attribs (ssg-attrib-read ename))
(setq id-val (cdr (assoc "ID" attribs)))
(if (and id-val (> (strlen id-val) 0))
(progn
(setq id-num (atoi id-val))
(if (> id-num max-id) (setq max-id id-num))
;; In Map eintragen: (id-num . (ename1 ename2 ...))
(setq entry (assoc id-num id-map))
(if entry
(setq id-map (subst (cons id-num (append (cdr entry) (list ename)))
entry id-map))
(setq id-map (cons (cons id-num (list ename)) id-map))
)
)
;; Block ohne ID -> neue ID zuweisen
(progn
(setq max-id (1+ max-id))
(setq new-id-str (ssg-id-format max-id))
(ssg-attrib-set-on ename (list (cons "ID" new-id-str)))
(princ (strcat "\n[IDSCHECK] Fehlende ID gesetzt: " new-id-str
" (Block " (cdr (assoc 2 (entget ename))) ")"))
)
)
(setq i (1+ i))
)
;; Phase 2: Duplikate korrigieren
(setq fixed-count 0)
(foreach entry id-map
(if (> (length (cdr entry)) 1)
(progn
;; Erste Instanz behalten, Duplikate neu nummerieren
(foreach ename (cdr (cdr entry))
(setq max-id (1+ max-id))
(setq new-id-str (ssg-id-format max-id))
(ssg-attrib-set-on ename (list (cons "ID" new-id-str)))
(princ (strcat "\n[IDSCHECK] Duplikat ID " (ssg-id-format (car entry))
" -> neue ID " new-id-str
" (Block " (cdr (assoc 2 (entget ename))) ")"))
(setq fixed-count (1+ fixed-count))
)
)
)
)
(princ (strcat "\n[IDSCHECK] Fertig. " (itoa fixed-count) " Duplikate korrigiert."))
fixed-count
)
)
)
;; --- Befehl: IDSCHECK ---
;; Prueft alle Bloecke auf doppelte IDs und korrigiert sie.
(defun c:IDSCHECK ( / count)
(ssg-start "IDSCHECK" nil)
(setq count (ssg-id-check-all))
(princ (strcat "\n[IDSCHECK] " (itoa count) " IDs korrigiert."))
(ssg-end)
(princ)
)
;; --- Befehl: IDGENERATE ---
;; Fordert den Benutzer auf, einen Block zu waehlen und weist eine neue ID zu.
(defun c:IDGENERATE ( / ent ed)
(ssg-start "IDGENERATE" nil)
(setq ent (car (entsel "\nBlock waehlen: ")))
(if (and ent (= (cdr (assoc 0 (entget ent))) "INSERT"))
(ssg-id-generate ent)
(princ "\n[IDGENERATE] Kein gueltiger Block gewaehlt.")
)
(ssg-end)
(princ)
)
(princ "\n[SSG_ID] Geladen.")
(princ)
+315
View File
@@ -0,0 +1,315 @@
;; ============================================================
;; SSG_LAYER.LSP - Layer-Verwaltungsroutinen
;; Interaktive Layer-Operationen: verschieben, ein/ausschalten,
;; einfrieren, Gruppen-Management.
;; Ursprung: ACADSST/MENU/laymr14.lsp (Schoenenberger)
;; Bereinigt und verallgemeinert: 2025
;; Setzt ssg_core.lsp voraus.
;; ============================================================
;; ------------------------------------------------------------
;; LAYER-INFORMATION
;; ------------------------------------------------------------
;; Alle Layer als Liste von Layernamen liefern
;; Rueckgabe: Liste von Strings
(defun ssg-layer-list-all (/ result entry first)
(setq result nil
first T
)
(while (setq entry (tblnext "LAYER" first))
(setq result (cons (cdr (assoc 2 entry)) result)
first nil
)
)
(reverse result)
)
;; Layer-Infos als Assoziationsliste liefern
;; Rueckgabe: Liste von (name . layer-alist) Paaren
(defun ssg-layer-info-all (/ result entry first)
(setq result nil
first T
)
(while (setq entry (tblnext "LAYER" first))
(setq result (cons (cons (cdr (assoc 2 entry)) (cdr entry)) result)
first nil
)
)
(reverse result)
)
;; Layer-Sichtbarkeitsstatus pruefen
;; lay-name = Layername; Rueckgabe: T wenn sichtbar, nil wenn aus/gefroren
(defun ssg-layer-visible-p (lay-name / entry flags color)
(setq entry (tblsearch "LAYER" lay-name))
(if entry
(progn
(setq flags (cdr (assoc 70 entry))
color (cdr (assoc 62 entry))
)
(and (not (minusp color)) ; nicht ausgeschaltet (negativ = aus)
(= (logand flags 1) 0) ; nicht gefroren (bit 0)
)
)
)
)
;; Pruefen ob Objekt-Layer der aktive Layer ist (Schutz vor Ausschalten)
;; lay-name = zu pruefender Layer; ist-gruppe = T wenn Gruppen-Layer
;; Rueckgabe: T wenn sicher (nicht aktiver Layer), nil wenn Problem
(defun ssg-layer-safe-p (lay-name ist-gruppe)
(if ist-gruppe
(/= (substr (getvar "CLAYER") 2 2) lay-name)
(/= (getvar "CLAYER") lay-name)
)
)
;; ------------------------------------------------------------
;; EINFACHE LAYER-OPERATIONEN
;; ------------------------------------------------------------
;; Layer eines angeklickten Objektes ermitteln und setzen (aktiv machen)
;; Rueckgabe: neuer Layername oder nil bei Abbruch
(defun c:SSG-LayerSet (/ sel lay)
(ssg-start "Layer setzen" nil)
(if (setq lay (ssg-get-layer "\nObjekt auf dem Ziel-Layer waehlen: "))
(progn
(command "_LAYER" "_SET" lay "")
(prompt (strcat "\nAktiver Layer: " lay))
)
(ssg-emsg "Kein Objekt gewaehlt.")
)
(ssg-end)
lay
)
;; Layer eines Objektes anzeigen
(defun c:SSG-LayerInfo (/ sel lay)
(ssg-start "Layer-Info" nil)
(if (setq lay (ssg-get-layer "\nObjekt waehlen: "))
(prompt (strcat "\nObjekt liegt auf Layer: " lay))
(ssg-emsg "Kein Objekt gewaehlt.")
)
(ssg-end)
lay
)
;; Objekte auf einen anderen Layer verschieben (interaktiv)
(defun c:SSG-LayerMove (/ elem ziel-lay)
(ssg-start "Layer wechseln" nil)
(if (setq elem (ssget))
(if (setq ziel-lay (ssg-get-layer "\nObjekt auf dem Ziel-Layer waehlen: "))
(command "_CHANGE" elem "" "_PROP" "_LA" ziel-lay "")
(ssg-emsg "Kein Ziel-Layer gewaehlt.")
)
(ssg-emsg "Kein Objekt gewaehlt.")
)
(ssg-end)
)
;; Objekte auf einen anderen Layer kopieren und dort ablegen
(defun c:SSG-LayerCopy (/ elem ziel-lay)
(ssg-start "Layer-Kopie" nil)
(if (setq elem (ssget))
(if (setq ziel-lay (ssg-get-layer "\nObjekt auf dem Ziel-Layer waehlen: "))
(command "_COPY" elem "" "@" "@" "_CHANGE" elem "" "_PROP" "_LA" ziel-lay "")
(ssg-emsg "Kein Ziel-Layer gewaehlt.")
)
(ssg-emsg "Kein Objekt gewaehlt.")
)
(ssg-end)
)
;; Alle Objekte eines Typs auf dem gleichen Layer auf neuen Layer verschieben
;; (nach Auswahl eines Referenz-Objektes dieses Typs)
(defun c:SSG-LayerMoveType (/ ref-lay ref-typ elem ziel-lay ss ref-sel)
(ssg-start "Layer-Typ verschieben" nil)
(if (setq ref-lay (ssg-get-layer "\nReferenz-Objekt waehlen (bestimmt Typ und Layer): "))
(progn
(setq ref-sel (entsel "\nNochmals fuer Typ-Ermittlung anklicken: "))
(if ref-sel
(progn
(setq ref-typ (cdr (assoc 0 (entget (car ref-sel))))
ss (ssg-layer-ss ref-lay ref-typ)
)
(if ss
(if (setq ziel-lay (ssg-get-layer "\nObjekt auf dem Ziel-Layer waehlen: "))
(progn
(ssg-zoom-save)
(ssg-ss-redraw ss 3)
(if (not (ssg-ques (strcat "Layer dieser " ref-typ "-Objekte wechseln?") nil))
(command "_CHANGE" ss "" "_PROP" "_LA" ziel-lay "")
(ssg-ss-redraw ss 4)
)
(ssg-zoom-restore)
)
(ssg-emsg "Kein Ziel-Layer.")
)
(ssg-emsg "Keine passenden Objekte gefunden.")
)
)
(ssg-emsg "Abgebrochen.")
)
)
(ssg-emsg "Kein Referenz-Objekt gewaehlt.")
)
(ssg-end)
)
;; ------------------------------------------------------------
;; LAYER EIN-/AUSSCHALTEN UND EINFRIEREN
;; ------------------------------------------------------------
;; Layer durch Anklicken ausschalten
(defun c:SSG-LayerOff (/ lay)
(ssg-start "Layer ausschalten" nil)
(while (setq lay (ssg-get-layer "\nLayer zum Ausblenden anklicken (Enter=Ende): "))
(if (ssg-layer-safe-p lay nil)
(command "_LAYER" "_OFF" lay "")
(ssg-emsg "Aktiven Layer nicht ausschalten!")
)
)
(ssg-end)
)
;; Layer durch Anklicken einfrieren
(defun c:SSG-LayerFreeze (/ lay)
(ssg-start "Layer einfrieren" nil)
(while (setq lay (ssg-get-layer "\nLayer zum Einfrieren anklicken (Enter=Ende): "))
(if (ssg-layer-safe-p lay nil)
(command "_LAYER" "_FR" lay "")
(ssg-emsg "Aktiven Layer nicht einfrieren!")
)
)
(ssg-end)
)
;; Alle Layer ausser dem aktiven einfrieren
(defun c:SSG-FreezeAll (/ aktiv)
(ssg-start "Alle anderen Layer einfrieren" nil)
(setq aktiv (ssg-get-layer "\nObjekt auf dem Layer waehlen, der AKTIV bleibt: "))
(if aktiv
(progn
(command "_LAYER" "_SET" aktiv "_FR" "*" "")
(prompt (strcat "\nNur Layer '" aktiv "' ist sichtbar."))
)
(ssg-emsg "Abgebrochen.")
)
(ssg-end)
)
;; Alle ausgefrorenen Layer wieder auftauen
(defun c:SSG-ThawAll ()
(ssg-start "Alle Layer auftauen" nil)
(command "_LAYER" "_T" "*" "")
(ssg-end)
)
;; Alle ausgeschalteten Layer einschalten
(defun c:SSG-LayerOnAll ()
(ssg-start "Alle Layer einschalten" nil)
(command "_LAYER" "_ON" "*" "")
(ssg-end)
)
;; ------------------------------------------------------------
;; LAYER UMBENENNEN / VERSCHIEBEN (Gruppenkonzept)
;; Im Schoenenberger-System haben Layer die Form "X-XX-Name"
;; wobei Position 2-3 die Gruppe identifiziert.
;; Diese Funktionen erlauben das Umbenennen der Gruppen-Kennung.
;; ------------------------------------------------------------
;; Gruppen-Buchstaben aus Layernamen extrahieren (Position 2-3)
(defun ssg-layer-group (lay-name)
(substr lay-name 2 2)
)
;; Neuen Layernamen mit geaenderter Gruppen-Kennung erzeugen
;; lay-name = original; new-grp = neue Gruppen-Kennung (2 Zeichen)
(defun ssg-layer-rename-group (lay-name new-grp)
(strcat (substr lay-name 1 1) new-grp (substr lay-name 4))
)
;; Alle Objekte eines Gruppen-Layers auf neuen Gruppen-Layer verschieben
;; old-grp = alte Gruppen-Kennung; new-grp = neue Gruppen-Kennung
(defun ssg-layer-group-move (old-grp new-grp / all-layers entry lay-info new-name
lay-color lay-ltyp c ss i e ed)
(setq all-layers (ssg-layer-info-all))
(foreach entry all-layers
(if (= (ssg-layer-group (car entry)) old-grp)
(progn
(setq lay-info (cdr entry)
new-name (ssg-layer-rename-group (car entry) new-grp)
c (cdr (assoc 62 lay-info))
lay-color (if (minusp c) (abs c) c)
lay-ltyp (cdr (assoc 6 lay-info))
)
(if (not (tblsearch "LAYER" new-name))
(command "_LAYER" "_N" new-name "_CO" (itoa lay-color) new-name
"LT" lay-ltyp new-name "")
)
(setq ss (ssg-layer-ss (car entry) nil))
(if ss
(progn
(setq i 0)
(while (setq e (ssname ss i))
(setq ed (entget e))
(entmod (subst (cons 8 new-name) (assoc 8 ed) ed))
(setq i (1+ i))
)
)
)
)
)
)
)
;; ------------------------------------------------------------
;; LAYER LOESCHEN (mit Sicherheitsabfrage)
;; Loescht alle Objekte auf einem Layer und danach den Layer selbst.
;; Nur interaktiv verwenden!
;; ------------------------------------------------------------
(defun c:SSG-LayerDelete (/ lay ss)
(ssg-start "Layer loeschen" nil)
(initget 1)
(setq lay (getstring "\nLayername zum Loeschen: "))
(if (tblsearch "LAYER" lay)
(progn
(setq ss (ssg-layer-ss lay nil))
(if ss
(progn
(ssg-ss-redraw ss 4)
(if (not (ssg-ques (strcat "Alle Objekte auf Layer '" lay "' loeschen?") nil))
(progn
(command "_ERASE" ss "")
(command "_LAYER" "_OFF" lay "")
(command "_PURGE" "_LA" lay "N")
(prompt (strcat "\nLayer '" lay "' geloescht."))
)
(progn
(ssg-ss-redraw ss 0)
(prompt "\nAbgebrochen.")
)
)
)
(progn
(command "_LAYER" "_OFF" lay "")
(command "_PURGE" "_LA" lay "N")
(prompt (strcat "\nLeerer Layer '" lay "' geloescht."))
)
)
)
(ssg-emsg (strcat "Layer '" lay "' existiert nicht."))
)
(ssg-end)
)
(prompt "\nssg_layer.lsp geladen.")
(princ)
+41
View File
@@ -0,0 +1,41 @@
;; ============================================================
;; SSG_LOAD.LSP - Laderoutine fuer die SSG-Standardbibliotheken
;;
;; Laedt alle SSG-Kernbibliotheken in der richtigen Reihenfolge.
;; In acad.lsp oder manuell aufrufen:
;; (load "pfad/ssg_load.lsp")
;;
;; Alternativ nur einzelne Bibliotheken laden:
;; (load "pfad/ssg_core.lsp")
;; (load "pfad/ssg_layer.lsp")
;; (load "pfad/ssg_dialog.lsp")
;; ============================================================
(defun ssg-load-libs (/ base-path found)
;; Pfad ermitteln: 1) DXFM_LISP, 2) findfile, 3) DWGPREFIX
(setq base-path
(cond
((getenv "DXFM_LISP")
(strcat (vl-string-translate "\\" "/" (getenv "DXFM_LISP")) "/"))
((setq found (findfile "ssg_core.lsp"))
(substr found 1 (- (strlen found) (strlen "ssg_core.lsp"))))
(t (getvar "DWGPREFIX"))
)
)
(load (strcat base-path "ssg_core.lsp") "ssg_core.lsp nicht gefunden")
(ssg-load-config)
(load (strcat base-path "ssg_dbg.lsp") "ssg_dbg.lsp nicht gefunden")
(load (strcat base-path "ssg_dialog.lsp") "ssg_dialog.lsp nicht gefunden")
(load (strcat base-path "ssg_layer.lsp") "ssg_layer.lsp nicht gefunden")
(load (strcat base-path "KreiselInsert.lsp") "KreiselInsert.lsp nicht gefunden")
(load (strcat base-path "VarioFoerderer.lsp") "VarioFoerderer.lsp nicht gefunden")
(load (strcat base-path "Gefaellestrecke.lsp") "Gefaellestrecke.lsp nicht gefunden")
(load (strcat base-path "export.lsp") "export.lsp nicht gefunden")
(load (strcat base-path "tests.lsp") "tests.lsp nicht gefunden")
(load (strcat base-path "OmniModulInsert.lsp") "OmniModulInsert.lsp nicht gefunden")
(load (strcat base-path "SSG_LIB_Commands.lsp") "SSG_LIB_Commands.lsp nicht gefunden")
(prompt "\nSSG-Bibliotheken geladen: ssg_core, ssg_dbg, ssg_dialog, ssg_layer, KreiselInsert, VarioFoerderer, Gefaellestrecke, export, tests, OmniModulInsert, SSG_LIB_Commands")
(princ)
)
(ssg-load-libs)
+1384
View File
File diff suppressed because it is too large Load Diff
+798
View File
@@ -0,0 +1,798 @@
;; ============================================================
;; VF_ETAGE - Etage VarioFoerderer (Typ: "etage")
;; Version: 26.0
;; Abhaengigkeit: vf_core.lsp muss zuerst geladen sein
;; Geometrie: AS/ES 30 Grad, direkt uebereinander (60 Grad Hz-Winkel)
;; 15-Schritt-Einfuegung
;; ============================================================
;; Sicherstellen, dass vf_core.lsp geladen ist
(if (not (car (atoms-family 1 '("VF-TYP-REGISTRIEREN"))))
(progn
(setq *vf-etage-core-pfad*
(cond
((getenv "DXFM_LISP")
(vl-string-translate "\\" "/" (getenv "DXFM_LISP")))
((and (boundp '*ssg-lisp-pfad*) *ssg-lisp-pfad*)
*ssg-lisp-pfad*)
(t nil)
)
)
(if *vf-etage-core-pfad*
(load (strcat *vf-etage-core-pfad* "/vf_core.lsp"))
(progn
(princ "\n[vf_etage] WARNUNG: Lisp-Pfad nicht ermittelbar - vf_core.lsp nicht ladbar!")
(exit)
)
)
)
)
;; ============================================================
;; TEIL 1: ETAGE-SPEZIFISCHE GLOBALE VARIABLEN
;; ============================================================
(setq etage-aus-dx nil etage-aus-dz nil)
(setq etage-ein-dx nil etage-ein-dz nil)
(setq etage-gef-dx nil etage-gef-dy nil etage-gef-dz nil)
(setq etage-gef-dx-rechts nil etage-gef-dz-rechts nil)
(setq etage-gef-dx-links nil etage-gef-dz-links nil)
(setq *etage-lib-initialized* nil)
(setq FESTE_ETAGE_MITTE 1000)
(setq ETAGE_SCHRAEG_LAENGE 700)
(setq ETAGE_HZ_WINKEL 60)
;; ============================================================
;; TEIL 2: BIBLIOTHEK INITIALISIEREN (ETAGE-SPEZIFISCH)
;; ============================================================
(defun init-bibliothek-etage ( / temp-obj ks-data ks-ein-pos ks-aus-pos
gefaelle-blockname)
(if (and *etage-lib-initialized* (not (tblsearch "BLOCK" "AS_Element_30_rechts")))
(setq *etage-lib-initialized* nil))
(if *etage-lib-initialized*
(progn (princ "\n Etage-Bibliothek bereits initialisiert.") t)
(progn
(princ "\n Initialisiere Etage-Bibliothek...")
;; Standard-Bogen-Daten laden (bogen-auf/bogen-ab benoetigt)
(if (not *lib-initialized*)
(init-bibliothek)
)
;; AS_30_rechts Masse extrahieren
(princ "\n Extrahiere AS_30_rechts Masse...")
(ensure-block-loaded "AS_Element_30_rechts")
(ensure-block-loaded "AS_Element_30_links")
(if (tblsearch "BLOCK" "AS_Element_30_rechts")
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0))
"AS_Element_30_rechts" 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(vla-Delete temp-obj)
(setq ks-ein-pos nil ks-aus-pos nil)
(foreach item ks-data
(if (= (car item) "KS_EIN") (setq ks-ein-pos (cadr item)))
(if (= (car item) "KS_AUS") (setq ks-aus-pos (cadr item)))
)
(if (and ks-ein-pos ks-aus-pos)
(progn
(setq etage-aus-dx (- (caar ks-aus-pos) (caar ks-ein-pos)))
(setq etage-aus-dz (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
(princ (strcat "\n AS_30_rechts: dx=" (rtos etage-aus-dx 2 1)
" mm, dz=" (rtos etage-aus-dz 2 1) " mm"))
)
(progn
(princ "\n WARNUNG: KS fehlt - Standardwerte")
(setq etage-aus-dx 525.8 etage-aus-dz -72.9)
)
)
)
(progn
(princ "\n WARNUNG: Block AS_Element_30_rechts fehlt - Standardwerte")
(setq etage-aus-dx 525.8 etage-aus-dz -72.9)
)
)
;; ES_30_rechts Masse extrahieren
(princ "\n Extrahiere ES_30_rechts Masse...")
(ensure-block-loaded "ES_Element_30_rechts")
(ensure-block-loaded "ES_Element_30_links")
(if (tblsearch "BLOCK" "ES_Element_30_rechts")
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0))
"ES_Element_30_rechts" 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(vla-Delete temp-obj)
(setq ks-ein-pos nil ks-aus-pos nil)
(foreach item ks-data
(if (= (car item) "KS_EIN") (setq ks-ein-pos (cadr item)))
(if (= (car item) "KS_AUS") (setq ks-aus-pos (cadr item)))
)
(if (and ks-ein-pos ks-aus-pos)
(progn
(setq etage-ein-dx (- (caar ks-aus-pos) (caar ks-ein-pos)))
(setq etage-ein-dz (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
(princ (strcat "\n ES_30_rechts: dx=" (rtos etage-ein-dx 2 1)
" mm, dz=" (rtos etage-ein-dz 2 1) " mm"))
)
(progn
(princ "\n WARNUNG: KS fehlt - Standardwerte")
(setq etage-ein-dx 576.2 etage-ein-dz -54.6)
)
)
)
(progn
(princ "\n WARNUNG: Block ES_Element_30_rechts fehlt - Standardwerte")
(setq etage-ein-dx 576.2 etage-ein-dz -54.6)
)
)
;; Gefaellebogen_links_60 Masse extrahieren
(setq gefaelle-blockname "Gefaellebogen_links_60_R500")
(princ (strcat "\n Extrahiere " gefaelle-blockname " Masse..."))
(ensure-block-loaded gefaelle-blockname)
(if (tblsearch "BLOCK" gefaelle-blockname)
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0)) gefaelle-blockname 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(vla-Delete temp-obj)
(setq ks-ein-pos nil ks-aus-pos nil)
(foreach item ks-data
(if (= (car item) "KS_EIN") (setq ks-ein-pos (cadr item)))
(if (= (car item) "KS_AUS") (setq ks-aus-pos (cadr item)))
)
(if (and ks-ein-pos ks-aus-pos)
(progn
(setq etage-gef-dx-links (- (caar ks-aus-pos) (caar ks-ein-pos)))
(setq etage-gef-dz-links (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
)
(progn
(princ "\n WARNUNG: kein KS - Standardwerte (links)")
(setq etage-gef-dx-links 0.0 etage-gef-dz-links -10.0)
)
)
)
(progn
(princ "\n WARNUNG: Block fehlt - Standardwerte (links)")
(setq etage-gef-dx-links 0.0 etage-gef-dz-links -10.0)
)
)
(princ (strcat "\n Gefaellebogen links: dx=" (rtos etage-gef-dx-links 2 2)
" dz=" (rtos etage-gef-dz-links 2 2) " mm"))
;; Gefaellebogen_rechts_60 Masse extrahieren
(setq gefaelle-blockname "Gefaellebogen_rechts_60_R500")
(princ (strcat "\n Extrahiere " gefaelle-blockname " Masse..."))
(ensure-block-loaded gefaelle-blockname)
(if (tblsearch "BLOCK" gefaelle-blockname)
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0)) gefaelle-blockname 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(vla-Delete temp-obj)
(setq ks-ein-pos nil ks-aus-pos nil)
(foreach item ks-data
(if (= (car item) "KS_EIN") (setq ks-ein-pos (cadr item)))
(if (= (car item) "KS_AUS") (setq ks-aus-pos (cadr item)))
)
(if (and ks-ein-pos ks-aus-pos)
(progn
(setq etage-gef-dx-rechts (- (caar ks-aus-pos) (caar ks-ein-pos)))
(setq etage-gef-dz-rechts (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
)
(progn
(princ "\n WARNUNG: kein KS - Standardwerte (rechts)")
(setq etage-gef-dx-rechts 0.0 etage-gef-dz-rechts -10.0)
)
)
)
(progn
(princ "\n WARNUNG: Block fehlt - Standardwerte (rechts)")
(setq etage-gef-dx-rechts 0.0 etage-gef-dz-rechts -10.0)
)
)
(princ (strcat "\n Gefaellebogen rechts: dx=" (rtos etage-gef-dx-rechts 2 2)
" dz=" (rtos etage-gef-dz-rechts 2 2) " mm"))
(setq *etage-lib-initialized* t)
(princ "\n Etage-Bibliothek erfolgreich initialisiert.")
t
)
)
)
;; ============================================================
;; TEIL 3: EINFUEGEFUNKTIONEN MIT KOMBINIERTER HZ+VERT ROTATION
;; ============================================================
;; Transformationsmatrix: Rz(hz) * Ry(vert)
;; [ cos(hz)*cos(vert) -sin(hz) cos(hz)*sin(vert) ]
;; [ sin(hz)*cos(vert) cos(hz) sin(hz)*sin(vert) ]
;; [ -sin(vert) 0 cos(vert) ]
(defun insert-hz-incl-scaled-block (blockname startpunkt laenge hz-winkel vert-winkel /
rad-hz rad-vert chz shz cv sv scale
matrix block-obj endpunkt)
(setq scale (/ (float laenge) 1000.0))
(setq rad-hz (* (float hz-winkel) (/ pi 180.0)))
(setq rad-vert (* (float vert-winkel) (/ pi 180.0)))
(setq chz (cos rad-hz) shz (sin rad-hz))
(setq cv (cos rad-vert) sv (sin rad-vert))
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(exit)
)
)
(setq block-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0)) blockname scale 1.0 1.0 0))
(setq matrix (list
(list (* chz cv) (- shz) (* chz sv) 0)
(list (* shz cv) chz (* shz sv) 0)
(list (- sv) 0 cv 0)
(list 0 0 0 1)
))
(vla-TransformBy block-obj (vlax-tmatrix matrix))
(vla-Move block-obj (vlax-3D-point '(0 0 0)) (vlax-3D-point startpunkt))
(setq endpunkt (list
(+ (car startpunkt) (* laenge chz cv))
(+ (cadr startpunkt) (* laenge shz cv))
(+ (caddr startpunkt) (* (- sv) laenge))))
(princ (strcat "\n HzIncl " blockname " L=" (rtos laenge 2 0)
" hz=" (rtos hz-winkel 2 0) (chr 176)
" v=" (rtos vert-winkel 2 0) (chr 176)
" -> Z=" (rtos (caddr endpunkt) 2 1)))
endpunkt
)
(defun insert-hz-rotated-block-with-ks (blockname startpunkt hz-winkel vert-winkel block-dx block-dz /
rad-hz rad-vert chz shz cv sv
matrix block-obj endpunkt)
(setq rad-hz (* (float hz-winkel) (/ pi 180.0)))
(setq rad-vert (* (float vert-winkel) (/ pi 180.0)))
(setq chz (cos rad-hz) shz (sin rad-hz))
(setq cv (cos rad-vert) sv (sin rad-vert))
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(exit)
)
)
(setq block-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0)) blockname 1.0 1.0 1.0 0))
(setq matrix (list
(list (* chz cv) (- shz) (* chz sv) 0)
(list (* shz cv) chz (* shz sv) 0)
(list (- sv) 0 cv 0)
(list 0 0 0 1)
))
(vla-TransformBy block-obj (vlax-tmatrix matrix))
(vla-Move block-obj (vlax-3D-point '(0 0 0)) (vlax-3D-point startpunkt))
(setq endpunkt (list
(+ (car startpunkt) (+ (* block-dx chz cv) (* block-dz chz sv)))
(+ (cadr startpunkt) (+ (* block-dx shz cv) (* block-dz shz sv)))
(+ (caddr startpunkt) (+ (* (- sv) block-dx) (* cv block-dz)))))
(princ (strcat "\n HzRot " blockname
" hz=" (rtos hz-winkel 2 0) (chr 176)
" v=" (rtos vert-winkel 2 0) (chr 176)
" -> Z=" (rtos (caddr endpunkt) 2 1)))
endpunkt
)
(defun insert-hz-rotated-block-by-ks (blockname startpunkt hz-winkel vert-winkel /
rad-hz rad-vert chz shz cv sv
temp-obj block-obj ks-data ks-ein ks-aus
p-ein p-aus p-ein-rot p-aus-rot
offset ausgang)
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(exit)
)
)
(setq rad-hz (* (float hz-winkel) (/ pi 180.0)))
(setq rad-vert (* (float vert-winkel) (/ pi 180.0)))
(setq chz (cos rad-hz) shz (sin rad-hz))
(setq cv (cos rad-vert) sv (sin rad-vert))
;; KS-Positionen aus Cache (Block bei 0 Grad am Ursprung)
(setq temp-obj (vla-InsertBlock modelspace (vlax-3D-point '(0 0 0)) blockname 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(if (not (vlax-erased-p temp-obj)) (vla-Delete temp-obj))
(setq ks-ein (cadr (assoc "KS_EIN" ks-data)))
(setq ks-aus (cadr (assoc "KS_AUS" ks-data)))
;; Block einfuegen und rotieren
(setq block-obj (vla-InsertBlock modelspace (vlax-3D-point '(0 0 0)) blockname 1.0 1.0 1.0 0))
(vla-TransformBy block-obj (vlax-tmatrix
(list (list (* chz cv) (- shz) (* chz sv) 0)
(list (* shz cv) chz (* shz sv) 0)
(list (- sv) 0 cv 0)
(list 0 0 0 1))))
(if (and ks-ein ks-aus)
(progn
(setq p-ein (car ks-ein))
(setq p-aus (car ks-aus))
;; Rotation auf KS-Punkte anwenden: p' = Rz(hz)*Ry(vert) * p
(setq p-ein-rot
(list (+ (* chz cv (car p-ein)) (- (* shz (cadr p-ein))) (* chz sv (caddr p-ein)))
(+ (* shz cv (car p-ein)) (* chz (cadr p-ein)) (* shz sv (caddr p-ein)))
(+ (* (- sv) (car p-ein)) (* cv (caddr p-ein)))))
(setq p-aus-rot
(list (+ (* chz cv (car p-aus)) (- (* shz (cadr p-aus))) (* chz sv (caddr p-aus)))
(+ (* shz cv (car p-aus)) (* chz (cadr p-aus)) (* shz sv (caddr p-aus)))
(+ (* (- sv) (car p-aus)) (* cv (caddr p-aus)))))
;; Block verschieben: rotiertes KS_EIN auf startpunkt
(vla-Move block-obj
(vlax-3D-point p-ein-rot)
(vlax-3D-point startpunkt))
(setq offset (list (- (car startpunkt) (car p-ein-rot))
(- (cadr startpunkt) (cadr p-ein-rot))
(- (caddr startpunkt) (caddr p-ein-rot))))
(setq ausgang (list (+ (car p-aus-rot) (car offset))
(+ (cadr p-aus-rot) (cadr offset))
(+ (caddr p-aus-rot) (caddr offset))))
(princ (strcat "\n HzRotKS " blockname
" hz=" (rtos hz-winkel 2 0) (chr 176)
" -> Z=" (rtos (caddr ausgang) 2 1)))
ausgang
)
(progn
(princ (strcat "\n WARNUNG: KS fehlt in '" blockname "' - verwende Startpunkt"))
startpunkt
)
)
)
(defun insert-hz-scaled-block-by-ks (blockname startpunkt laenge hz-winkel vert-winkel /
rad-hz rad-vert chz shz cv sv scale
temp-obj block-obj ks-data ks-ein ks-aus
p-ein p-aus p-ein-s p-aus-s
p-ein-rot p-aus-rot offset ausgang)
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(exit)
)
)
(setq scale (/ (float laenge) 1000.0))
(setq rad-hz (* (float hz-winkel) (/ pi 180.0)))
(setq rad-vert (* (float vert-winkel) (/ pi 180.0)))
(setq chz (cos rad-hz) shz (sin rad-hz))
(setq cv (cos rad-vert) sv (sin rad-vert))
;; KS bei Massstab 1
(setq temp-obj (vla-InsertBlock modelspace (vlax-3D-point '(0 0 0)) blockname 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(if (not (vlax-erased-p temp-obj)) (vla-Delete temp-obj))
(setq ks-ein (cadr (assoc "KS_EIN" ks-data)))
(setq ks-aus (cadr (assoc "KS_AUS" ks-data)))
;; Block mit XScale einfuegen und rotieren
(setq block-obj (vla-InsertBlock modelspace (vlax-3D-point '(0 0 0)) blockname scale 1.0 1.0 0))
(vla-TransformBy block-obj (vlax-tmatrix
(list (list (* chz cv) (- shz) (* chz sv) 0)
(list (* shz cv) chz (* shz sv) 0)
(list (- sv) 0 cv 0)
(list 0 0 0 1))))
(if (and ks-ein ks-aus)
(progn
(setq p-ein (car ks-ein))
(setq p-aus (car ks-aus))
;; X-Skalierung anwenden
(setq p-ein-s (list (* scale (car p-ein)) (cadr p-ein) (caddr p-ein)))
(setq p-aus-s (list (* scale (car p-aus)) (cadr p-aus) (caddr p-aus)))
;; Rotation: p' = Rz(hz)*Ry(vert) * p
(setq p-ein-rot
(list (+ (* chz cv (car p-ein-s)) (- (* shz (cadr p-ein-s))) (* chz sv (caddr p-ein-s)))
(+ (* shz cv (car p-ein-s)) (* chz (cadr p-ein-s)) (* shz sv (caddr p-ein-s)))
(+ (* (- sv) (car p-ein-s)) (* cv (caddr p-ein-s)))))
(setq p-aus-rot
(list (+ (* chz cv (car p-aus-s)) (- (* shz (cadr p-aus-s))) (* chz sv (caddr p-aus-s)))
(+ (* shz cv (car p-aus-s)) (* chz (cadr p-aus-s)) (* shz sv (caddr p-aus-s)))
(+ (* (- sv) (car p-aus-s)) (* cv (caddr p-aus-s)))))
;; Block verschieben
(vla-Move block-obj
(vlax-3D-point p-ein-rot)
(vlax-3D-point startpunkt))
(setq offset (list (- (car startpunkt) (car p-ein-rot))
(- (cadr startpunkt) (cadr p-ein-rot))
(- (caddr startpunkt) (caddr p-ein-rot))))
(setq ausgang (list (+ (car p-aus-rot) (car offset))
(+ (cadr p-aus-rot) (cadr offset))
(+ (caddr p-aus-rot) (caddr offset))))
(princ (strcat "\n HzScaleKS " blockname
" " (rtos laenge 2 0) "mm"
" hz=" (rtos hz-winkel 2 0) (chr 176)
" -> Z=" (rtos (caddr ausgang) 2 1)))
ausgang
)
(progn
(princ (strcat "\n WARNUNG: KS fehlt in '" blockname "' - verwende Startpunkt"))
startpunkt
)
)
)
;; ============================================================
;; TEIL 4: WINKELBERECHNUNG (ETAGE)
;; ============================================================
(defun berechne-winkel-etage (deltaL deltaH richtung /
winkel-list ergebnis-liste A B cos3 sin3
bogen-x1 bogen-z1 bogen-x2 bogen-z2
abs-dz-AUS abs-dz-EIN abs-dz-GEF
L_GF L_VF cosα sinα
winkel-eff cosEff sinEff rad5 rad7
winkel mass1 mass2 gueltig
best-winkel best-L_GF best-L_VF
feste-gesamt-cos feste-gesamt-sin
schraeg-hz-rad schraeg-cos schraeg-z)
(if (not *etage-lib-initialized*)
(progn
(alert "Etage-Bibliothek nicht initialisiert!")
(exit)
)
)
(setq abs-dz-AUS (abs etage-aus-dz)
abs-dz-EIN (abs etage-ein-dz)
abs-dz-GEF (abs etage-gef-dz))
(setq winkel-list '(3 6 9 12 15 18 21 27 33 39 45 51))
(setq ergebnis-liste '())
(setq cos3 (cos (* 3.0 (/ pi 180.0)))
sin3 (sin (* 3.0 (/ pi 180.0))))
(setq feste-gesamt-cos (* FESTE_ETAGE_MITTE cos3))
(setq feste-gesamt-sin (* FESTE_ETAGE_MITTE sin3))
(setq schraeg-hz-rad (* (float ETAGE_HZ_WINKEL) (/ pi 180.0)))
(setq schraeg-cos (* (cos schraeg-hz-rad) cos3))
(princ "\n\n=========================================")
(princ "\n ETAGE-BERECHNUNG FUER ALLE WINKEL")
(princ "\n=========================================")
(princ (strcat "\n△L=" (rtos deltaL 2 2) " mm"
" △H=" (rtos deltaH 2 2) " mm"
" Richtung=" richtung))
(foreach winkel winkel-list
(if (= richtung "Auf")
(progn
(setq mass1 (get-bogen-mass bogen-auf winkel))
(setq mass2 (get-bogen-mass bogen-ab winkel))
)
(progn
(setq mass1 (get-bogen-mass bogen-ab winkel))
(setq mass2 (get-bogen-mass bogen-auf winkel))
)
)
(if (or (null mass1) (null mass2))
(progn
(princ (strcat "\n " (itoa winkel) (chr 176) " -> Bogen nicht vorhanden"))
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
)
(progn
(setq rad5 (* 3.0 (/ pi 180.0)))
(setq rad7 (* (float (if (= richtung "Auf") (- 3 winkel) (+ winkel 3)))
(/ pi 180.0)))
(setq bogen-x1 (+ (* (car mass1) (cos rad5)) (* (caddr mass1) (sin rad5))))
(setq bogen-z1 (+ (* (- (car mass1)) (sin rad5)) (* (caddr mass1) (cos rad5))))
(setq bogen-x2 (+ (* (car mass2) (cos rad7)) (* (caddr mass2) (sin rad7))))
(setq bogen-z2 (+ (* (- (car mass2)) (sin rad7)) (* (caddr mass2) (cos rad7))))
(setq cosα (cos (* winkel (/ pi 180.0)))
sinα (sin (* winkel (/ pi 180.0))))
(setq winkel-eff (if (= richtung "Auf") (- winkel 3) (+ winkel 3)))
(setq cosEff (cos (* winkel-eff (/ pi 180.0)))
sinEff (sin (* winkel-eff (/ pi 180.0))))
;; A: horizontaler Rest nach Abzug aller festen Teile
(setq A (- deltaL
etage-aus-dx
etage-ein-dx
(* 2.0 ETAGE_SCHRAEG_LAENGE schraeg-cos)
(* 2.0 etage-gef-dx)
bogen-x1
bogen-x2
(* 2.0 feste-gesamt-cos)))
;; B: vertikaler Rest (Vorzeichen analog Standard)
(setq schraeg-z (* ETAGE_SCHRAEG_LAENGE sin3))
(if (= richtung "Auf")
(setq B (+ deltaH
abs-dz-AUS
abs-dz-EIN
(* 2.0 schraeg-z)
(* 2.0 abs-dz-GEF)
(- bogen-z1)
(- bogen-z2)
(* 2.0 feste-gesamt-sin)))
(setq B (+ (- deltaH
abs-dz-AUS
abs-dz-EIN
(* 2.0 schraeg-z)
(* 2.0 abs-dz-GEF)
(* 2.0 feste-gesamt-sin))
bogen-z1
bogen-z2))
)
(if (> (abs sinα) 0.0001)
(progn
(setq L_GF (/ (- (* A sinEff) (* B cosEff)) sinα))
(if (= richtung "Auf")
(setq L_VF (/ (+ (* A sin3) (* B cos3)) sinα))
(setq L_VF (/ (- (* B cos3) (* A sin3)) sinα))
)
(if (and (numberp L_GF) (numberp L_VF))
(progn
(setq gueltig (and (>= L_GF 0) (>= L_VF 0)))
(setq ergebnis-liste
(cons (list winkel L_GF L_VF gueltig) ergebnis-liste))
)
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
)
)
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
)
)
)
)
(setq ergebnis-liste (reverse ergebnis-liste))
(princ "\n\n=================================================================================")
(princ "\n ERGEBNISTABELLE (L_GF = gesamt beider GF-Strecken)")
(princ "\n=================================================================================")
(princ "\n Winkel L_GF (mm) L_VF (mm) Status")
(princ "\n=================================================================================")
(setq best-winkel nil best-L_GF nil best-L_VF nil)
(foreach item ergebnis-liste
(setq winkel (car item)
L_GF (cadr item)
L_VF (caddr item)
gueltig (cadddr item))
(if (and (numberp L_GF) (numberp L_VF))
(progn
(princ (strcat "\n " (itoa winkel) (chr 176)
" " (fmt L_GF) " mm " (fmt L_VF) " mm "))
(if gueltig
(progn
(princ "GUELTIG")
(if (or (null best-winkel) (< winkel best-winkel))
(setq best-winkel winkel best-L_GF L_GF best-L_VF L_VF)
)
)
(princ "UNGUELTIG (negative Laenge)")
)
)
(princ (strcat "\n " (itoa winkel) (chr 176)
" --- --- FEHLER"))
)
)
(princ "\n=================================================================================")
(if best-winkel
(princ (strcat "\n>>> Empfohlener Winkel: " (itoa best-winkel) (chr 176)))
(princ "\n>>> KEIN passender Winkel gefunden!")
)
(list best-winkel best-L_GF best-L_VF ergebnis-liste)
)
;; ============================================================
;; TEIL 5: BERECHNE-WRAPPER (Schnittstelle fuer Registry)
;; ============================================================
;; Initialisiert Etage-Bibliothek, aktiviert Gefaellebogen-Masse
;; passend zur gewaehlten Seite (benoetigt fuer Geometrieberechnung).
(defun berechne-etage (deltaL deltaH richtung seite)
(init-bibliothek-etage)
(if (= seite "rechts")
(progn
(setq etage-gef-dx etage-gef-dx-rechts)
(setq etage-gef-dz etage-gef-dz-rechts))
(progn
(setq etage-gef-dx etage-gef-dx-links)
(setq etage-gef-dz etage-gef-dz-links))
)
(princ (strcat "\n Gefaellebogen " seite
": dx=" (rtos etage-gef-dx 2 2) " mm"))
(berechne-winkel-etage deltaL deltaH richtung)
)
;; ============================================================
;; TEIL 6: EINFUEGEN (15 Schritte, ohne VF_*-Block-Erstellung)
;; ============================================================
;; Gibt endpunkt zurueck.
;; VF_*-Block-Erstellung erfolgt zentral im Dispatcher (vf_core.lsp).
;; hz: Parameter fuer Registry-Kompatibilitaet mit variofoerderer-einfuegen
;; (siehe c:VarioFoerderer) - wird hier NICHT verwendet: die Etage-Anlage hat
;; bereits eine eigene, fest verdrahtete horizontale Geometrie (hz-anfang/
;; hz-ende fuer den 60-Grad-Uebereinander-Versatz) und unterstuetzt aktuell
;; keine zusaetzliche globale Fahrtrichtung.
(defun etage-foerderanlage-einfuegen (deltaL deltaH richtung
best-winkel L_GF1 L_GF2 L_VF
startpunkt seite hz
/ aktueller-punkt bogen-name endpunkt
bogen-mass bogen-dx bogen-dz
as-block es-block gefaelle-blockname
hz-vorzeichen hz-anfang hz-ende)
(setq aktueller-punkt startpunkt)
;; Horizontalwinkel-Vorzeichen je nach Seite:
;; rechts: Anfang +60 Grad (links), Ende -60 Grad (rechts)
;; links: Anfang -60 Grad, Ende +60 Grad
(setq hz-vorzeichen (if (= seite "rechts") 1 -1))
(setq hz-anfang (* hz-vorzeichen ETAGE_HZ_WINKEL))
(setq hz-ende (* (- hz-vorzeichen) ETAGE_HZ_WINKEL))
(setq as-block (strcat "AS_Element_30_" seite))
(setq es-block (strcat "ES_Element_30_" seite))
(setq gefaelle-blockname
(if (= seite "rechts")
"Gefaellebogen_rechts_60_R500"
"Gefaellebogen_links_60_R500"
))
;; Sentinel: Bibliothek neu initialisieren wenn Bloecke fehlen
(if (and *etage-lib-initialized* (not (tblsearch "BLOCK" "AS_Element_30_rechts")))
(setq *etage-lib-initialized* nil))
(if (not *etage-lib-initialized*) (init-bibliothek-etage))
;; 1. AS_30
(princ (strcat "\n\n1/15: " as-block " (0 Grad)"))
(setq aktueller-punkt (insert-block-by-ks as-block aktueller-punkt 0.0))
;; 2. Staustrecke 400mm (hz-anfang, 3 Grad vert, KS_EIN)
(princ (strcat "\n\n2/15: Staustrecke 400mm ("
(itoa hz-anfang) " Grad hz, 3 Grad vert, KS_EIN)"))
(setq aktueller-punkt
(insert-hz-scaled-block-by-ks "Staustrecke_SP_1000_mm" aktueller-punkt
400 hz-anfang 3))
;; 3. Separator (hz-anfang, 3 Grad vert)
(princ (strcat "\n\n3/15: Separator (300mm, "
(itoa hz-anfang) " Grad hz, 3 Grad vert)"))
(setq aktueller-punkt
(insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
hz-anfang 3 300 0))
;; 4. Gefaellebogen Anfang (hz-anfang, 0 Grad vert, KS_EIN)
(princ (strcat "\n\n4/15: " gefaelle-blockname
" (Anfang, " (itoa hz-anfang) " Grad hz, 0 Grad vert, KS_EIN)"))
(setq aktueller-punkt
(insert-hz-rotated-block-by-ks gefaelle-blockname aktueller-punkt hz-anfang 0))
;; 5. L_GF1 (3 Grad geneigt)
(if (> L_GF1 0.1)
(progn
(princ (strcat "\n\n5/15: Gefaellestrecke (3 Grad, L=" (rtos L_GF1 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF1 3 0.0))
)
(princ "\n\n5/15: L_GF1 (uebersprungen)")
)
;; 6. Umlenkstation (3 Grad geneigt)
(princ "\n\n6/15: Umlenkstation (500mm, 3 Grad geneigt)")
(setq aktueller-punkt
(insert-rotated-block-with-ks "Vario_Umlenkstation_500mm" aktueller-punkt 3 500 0 0.0))
;; 7. 1. Vertikalbogen (3 Grad geneigt)
(if (= richtung "Auf")
(progn
(setq bogen-name (strcat "Vario_Bogen_auf_" (itoa best-winkel)))
(setq bogen-mass (get-bogen-mass bogen-auf best-winkel))
)
(progn
(setq bogen-name (strcat "Vario_Bogen_ab_" (itoa best-winkel)))
(setq bogen-mass (get-bogen-mass bogen-ab best-winkel))
)
)
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
(princ (strcat "\n\n7/15: " bogen-name " (3 Grad geneigt)"))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt 3 bogen-dx bogen-dz 0.0))
;; 8. Variable Strecke L_VF
(if (> L_VF 0.1)
(progn
(if (= richtung "Auf")
(progn
(princ (strcat "\n\n8/15: Steigungsstrecke ("
(itoa (- (- best-winkel 3))) " Grad, L=" (rtos L_VF 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_VF (- (- best-winkel 3)) 0.0))
)
(progn
(princ (strcat "\n\n8/15: Gefaellestrecke ("
(itoa (+ best-winkel 3)) " Grad, L=" (rtos L_VF 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_VF (+ best-winkel 3) 0.0))
)
)
)
(princ "\n\n8/15: L_VF (uebersprungen)")
)
;; 9. 2. Vertikalbogen
(if (= richtung "Auf")
(progn
(setq bogen-name (strcat "Vario_Bogen_ab_" (itoa best-winkel)))
(setq bogen-mass (get-bogen-mass bogen-ab best-winkel))
)
(progn
(setq bogen-name (strcat "Vario_Bogen_auf_" (itoa best-winkel)))
(setq bogen-mass (get-bogen-mass bogen-auf best-winkel))
)
)
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
(if (= richtung "Auf")
(progn
(princ (strcat "\n\n9/15: " bogen-name
" (" (itoa (- 3 best-winkel)) " Grad geneigt)"))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt
(- 3 best-winkel) bogen-dx bogen-dz 0.0))
)
(progn
(princ (strcat "\n\n9/15: " bogen-name
" (" (itoa (+ best-winkel 3)) " Grad geneigt)"))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt
(+ best-winkel 3) bogen-dx bogen-dz 0.0))
)
)
;; 10. Motorstation (3 Grad geneigt)
(princ "\n\n10/15: Motorstation (500mm, 3 Grad geneigt)")
(setq aktueller-punkt
(insert-rotated-block-with-ks "Vario_Motorstation_500mm" aktueller-punkt 3 500 0 0.0))
;; 11. L_GF2 (3 Grad geneigt)
(if (> L_GF2 0.1)
(progn
(princ (strcat "\n\n11/15: Gefaellestrecke (3 Grad, L=" (rtos L_GF2 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF2 3 0.0))
)
(princ "\n\n11/15: L_GF2 (uebersprungen)")
)
;; 12. Gefaellebogen Ende (via KS_EIN, 0 Grad vert)
(princ (strcat "\n\n12/15: " gefaelle-blockname " (Ende, KS_EIN)"))
(setq aktueller-punkt (insert-block-by-ks gefaelle-blockname aktueller-punkt 0.0))
;; 13. Separator Ende (hz-ende, 3 Grad vert)
(princ (strcat "\n\n13/15: Separator (300mm, "
(itoa hz-ende) " Grad hz, 3 Grad vert)"))
(setq aktueller-punkt
(insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
hz-ende 3 300 0))
;; 14. Staustrecke 400mm Ende (hz-ende, 3 Grad vert, KS_EIN)
(princ (strcat "\n\n14/15: Staustrecke 400mm ("
(itoa hz-ende) " Grad hz, 3 Grad vert, KS_EIN)"))
(setq aktueller-punkt
(insert-hz-scaled-block-by-ks "Staustrecke_SP_1000_mm" aktueller-punkt
400 hz-ende 3))
;; 15. ES_30 (hz-ende, 0 Grad vert)
(princ (strcat "\n\n15/15: " es-block
" (Ende, " (itoa hz-ende) " Grad hz, 0 Grad vert)"))
(setq endpunkt
(insert-hz-rotated-block-with-ks es-block aktueller-punkt
hz-ende 0 etage-ein-dx etage-ein-dz))
(princ "\n\n=========================================")
(princ "\n>>> Etage-VarioFoerderer eingefuegt! <<<")
endpunkt
)
;; ============================================================
;; REGISTRIERUNG
;; ============================================================
(vf-typ-registrieren
"etage"
'berechne-etage
'etage-foerderanlage-einfuegen
"Etage VarioFoerderer (AS/ES 30 Grad, direkt uebereinander)")
(princ "\n>>> vf_etage.lsp geladen - Typ 'etage' registriert")
(princ)
File diff suppressed because it is too large Load Diff
+719
View File
@@ -0,0 +1,719 @@
;; ============================================================
;; VF_STANDARD - Standard VarioFoerderer (Typ: "standard")
;; Version: 26.0
;; Abhaengigkeit: vf_core.lsp muss zuerst geladen sein
;; Geometrie: AS/ES 90 Grad, horizontal versetzt
;; 11-Schritt-Einfuegung
;; ============================================================
;; Sicherstellen, dass vf_core.lsp geladen ist
(if (not (car (atoms-family 1 '("VF-TYP-REGISTRIEREN"))))
(progn
(setq *vf-std-core-pfad*
(cond
((getenv "DXFM_LISP")
(vl-string-translate "\\" "/" (getenv "DXFM_LISP")))
((and (boundp '*ssg-lisp-pfad*) *ssg-lisp-pfad*)
*ssg-lisp-pfad*)
(t nil)
)
)
(if *vf-std-core-pfad*
(load (strcat *vf-std-core-pfad* "/vf_core.lsp"))
(progn
(princ "\n[vf_standard] WARNUNG: Lisp-Pfad nicht ermittelbar - vf_core.lsp nicht ladbar!")
(exit)
)
)
)
)
;; ============================================================
;; TEIL 1: STANDARD-SPEZIFISCHE GLOBALE VARIABLEN
;; ============================================================
(setq aus-dx nil aus-dy nil aus-dz nil)
(setq ein-dx nil ein-dy nil ein-dz nil)
(setq separator-laenge nil umlenk-laenge nil motorstation-laenge nil)
(setq staustrecke-basis 1000)
(setq FESTE_HORIZONTAL 1600)
(setq bogen-auf '())
(setq bogen-ab '())
(setq *lib-initialized* nil)
(setq *bogen-cache-loaded* nil)
(setq *modul-cache* nil)
;; ============================================================
;; TEIL 2: BLOCK-DATEI-PRUEFUNG
;; ============================================================
;; Prueft ob alle benoetigten Block-Dateien vorhanden sind.
;; Gibt t zurueck wenn OK (oder Library-DXF vorhanden), nil wenn Einzeldateien fehlen.
(defun vf-check-required-blocks ( / lib-datei bogen-winkel required-blocks missing bname datei)
(setq lib-datei
(strcat (vl-string-translate "\\" "/" (getenv "DXFM_DATA"))
"/block_libraries/ils_library.dxf"))
(if (findfile lib-datei)
t ;; Library-Datei vorhanden: alle Bloecke darin verfuegbar
(progn
(setq bogen-winkel (ssg-cfg-or "vario" "bogen_winkel"
'(3 6 9 12 15 18 21 27 33 39 45 51)))
(setq required-blocks
(append
(list "AS_Element_90_links" "AS_Element_90_rechts"
"ES_Element_90_links" "ES_Element_90_rechts"
"Staustrecke_SP_1000_mm" "Staustrecke_Separator_SP_300_mm"
"Vario_Umlenkstation_500mm" "Vario_Motorstation_500mm")
(mapcar (function (lambda (w) (strcat "Vario_Bogen_auf_" (itoa w)))) bogen-winkel)
(mapcar (function (lambda (w) (strcat "Vario_Bogen_ab_" (itoa w)))) bogen-winkel)
)
)
(setq missing '())
(foreach bname required-blocks
(setq datei (strcat block-pfad bname ".dwg"))
(if (not (findfile datei))
(setq missing (cons datei missing))
)
)
(if missing
(progn
(princ (strcat "\n FEHLER: DXFM_BLOCKS = " block-pfad))
(princ "\n Folgende Block-Dateien fehlen:")
(foreach f (reverse missing)
(princ (strcat "\n - " f))
)
nil
)
t
)
)
)
)
;; ============================================================
;; TEIL 3: BIBLIOTHEK INITIALISIEREN
;; ============================================================
(defun init-bibliothek ( / temp-obj bogen-winkel ks-data ks-ein-pos ks-aus-pos
dx dy dz bogen-name)
;; "bereits initialisiert" nur, wenn das Flag gesetzt UND die Bogen-Tabelle
;; tatsaechlich befuellt ist. Sonst (Stuck-State: Flag gesetzt, aber bogen-auf
;; leer - z.B. nach einer fehlgeschlagenen Extraktion) neu initialisieren.
(if (and *lib-initialized* bogen-auf bogen-ab
(tblsearch "BLOCK" "AS_Element_90_links"))
(progn
(princ "\n Standard-Bibliothek bereits initialisiert.")
t
)
(if (not (vf-check-required-blocks))
nil
(progn
(setq *lib-initialized* nil)
(setq *ks-cache* nil)
(princ "\n Initialisiere Standard-Bibliothek...")
;; AS_90 Masse extrahieren
(princ "\n Extrahiere AUS_Element Masse...")
(ensure-block-loaded "AS_Element_90_links")
(ensure-block-loaded "AS_Element_90_rechts")
(if (tblsearch "BLOCK" "AS_Element_90_links")
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0))
"AS_Element_90_links" 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(vla-Delete temp-obj)
(setq ks-ein-pos nil ks-aus-pos nil)
(foreach item ks-data
(if (= (car item) "KS_EIN") (setq ks-ein-pos (cadr item)))
(if (= (car item) "KS_AUS") (setq ks-aus-pos (cadr item)))
)
(if (and ks-ein-pos ks-aus-pos)
(progn
(setq aus-dx (- (caar ks-aus-pos) (caar ks-ein-pos)))
(setq aus-dy (- (cadr (car ks-aus-pos)) (cadr (car ks-ein-pos))))
(setq aus-dz (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
(princ (strcat "\n AS_90: dx=" (rtos aus-dx 2 0)
" dz=" (rtos aus-dz 2 0)))
)
(princ "\n FEHLER: KS_EIN/KS_AUS fehlt im AS_90!")
)
)
(princ "\n FEHLER: Block AS_Element_90_links nicht geladen!")
)
;; ES_90 Masse extrahieren
(princ "\n Extrahiere EIN_Element Masse...")
(ensure-block-loaded "ES_Element_90_links")
(ensure-block-loaded "ES_Element_90_rechts")
(if (tblsearch "BLOCK" "ES_Element_90_links")
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0))
"ES_Element_90_links" 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(vla-Delete temp-obj)
(setq ks-ein-pos nil ks-aus-pos nil)
(foreach item ks-data
(if (= (car item) "KS_EIN") (setq ks-ein-pos (cadr item)))
(if (= (car item) "KS_AUS") (setq ks-aus-pos (cadr item)))
)
(if (and ks-ein-pos ks-aus-pos)
(progn
(setq ein-dx (- (caar ks-aus-pos) (caar ks-ein-pos)))
(setq ein-dy (- (cadr (car ks-aus-pos)) (cadr (car ks-ein-pos))))
(setq ein-dz (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
(princ (strcat "\n ES_90: dx=" (rtos ein-dx 2 0)
" dz=" (rtos ein-dz 2 0)))
)
(princ "\n FEHLER: KS_EIN/KS_AUS fehlt im ES_90!")
)
)
(princ "\n FEHLER: Block ES_Element_90_links nicht geladen!")
)
;; Bogen-Masse extrahieren
(princ "\n Extrahiere Bogen-Masse...")
(setq bogen-auf '())
(setq bogen-ab '())
(setq bogen-winkel (ssg-cfg-or "vario" "bogen_winkel"
'(3 6 9 12 15 18 21 27 33 39 45 51)))
(foreach w bogen-winkel
;; Aufwaertsbogen
(setq bogen-name (strcat "Vario_Bogen_auf_" (itoa w)))
(ensure-block-loaded bogen-name)
(if (tblsearch "BLOCK" bogen-name)
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0)) bogen-name 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(vla-Delete temp-obj)
(setq ks-ein-pos nil ks-aus-pos nil)
(foreach item ks-data
(if (= (car item) "KS_EIN") (setq ks-ein-pos (cadr item)))
(if (= (car item) "KS_AUS") (setq ks-aus-pos (cadr item)))
)
(if (and ks-ein-pos ks-aus-pos)
(progn
(setq dx (- (caar ks-aus-pos) (caar ks-ein-pos)))
(setq dy (- (cadr (car ks-aus-pos)) (cadr (car ks-ein-pos))))
(setq dz (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
(setq bogen-auf (cons (list w dx dy dz) bogen-auf))
(princ (strcat "\n OK auf_" (itoa w)
": dx=" (rtos dx 2 0) " dz=" (rtos dz 2 0)))
)
(princ (strcat "\n FEHLER auf_" (itoa w) ": KS fehlt!"))
)
)
(princ (strcat "\n FEHLER auf_" (itoa w) ": Block nicht geladen!"))
)
;; Abwaertsbogen
(setq bogen-name (strcat "Vario_Bogen_ab_" (itoa w)))
(ensure-block-loaded bogen-name)
(if (tblsearch "BLOCK" bogen-name)
(progn
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0)) bogen-name 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block temp-obj))
(vla-Delete temp-obj)
(setq ks-ein-pos nil ks-aus-pos nil)
(foreach item ks-data
(if (= (car item) "KS_EIN") (setq ks-ein-pos (cadr item)))
(if (= (car item) "KS_AUS") (setq ks-aus-pos (cadr item)))
)
(if (and ks-ein-pos ks-aus-pos)
(progn
(setq dx (- (caar ks-aus-pos) (caar ks-ein-pos)))
(setq dy (- (cadr (car ks-aus-pos)) (cadr (car ks-ein-pos))))
(setq dz (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
(setq bogen-ab (cons (list w dx dy dz) bogen-ab))
(princ (strcat "\n OK ab_" (itoa w)
": dx=" (rtos dx 2 0) " dz=" (rtos dz 2 0)))
)
(princ (strcat "\n FEHLER ab_" (itoa w) ": KS fehlt!"))
)
)
(princ (strcat "\n FEHLER ab_" (itoa w) ": Block nicht geladen!"))
)
)
(setq bogen-auf (reverse bogen-auf))
(setq bogen-ab (reverse bogen-ab))
(setq *lib-initialized* t)
(princ "\n Standard-Bibliothek erfolgreich initialisiert.")
t
) ;; end progn (Initialisierung)
) ;; end (if not vf-check-required-blocks)
) ;; end outer (if and *lib-initialized*)
)
;; ============================================================
;; TEIL 3: BOGEN-MASSE
;; ============================================================
(defun get-bogen-mass (tabelle winkel)
(setq result nil)
(foreach item tabelle
(if (= (car item) winkel) (setq result (cdr item)))
)
(if (null result)
(princ (strcat "\n FEHLER: Winkel " (itoa winkel)
" nicht in Bogen-Tabelle!"))
)
result
)
;; ============================================================
;; TEIL 4: WINKELBERECHNUNG
;; ============================================================
;; feste-hz: horizontales Budget der festen Elemente (Umlenk+Motor+Separatoren).
;; nil => Standardwert FESTE_HORIZONTAL (1600, Standard-VF mit 2 Separatoren).
;; Der Linienzug uebergibt 1300 (nur 1 Separator am Einlauf, siehe vf_linienzug).
(defun berechne-alle-winkel (deltaL deltaH richtung feste-hz /
winkel-list ergebnis-liste A B cos3 sin3
bogen-x1 bogen-z1 bogen-x2 bogen-z2
abs-dz-AUS abs-dz-EIN L_GF L_VF cosα sinα
winkel-eff cosEff sinEff rad5 rad7
winkel mass1 mass2 gueltig
best-winkel best-L_GF best-L_VF)
(if (or (not *lib-initialized*) (null aus-dz) (null ein-dz))
(progn
(princ "\n FEHLER: Bibliothek nicht korrekt initialisiert (AUS/EIN-Masse fehlen)!")
(exit)
)
)
(if (null feste-hz) (setq feste-hz FESTE_HORIZONTAL))
(setq abs-dz-AUS (abs aus-dz) abs-dz-EIN (abs ein-dz))
(setq winkel-list (ssg-cfg-or "vario" "bogen_winkel"
'(3 6 9 12 15 18 21 27 33 39 45 51)))
(setq ergebnis-liste '())
(setq cos3 (cos (* (ssg-cfg-or "vario" "gefaelle_winkel" 3) (/ pi 180.0)))
sin3 (sin (* (ssg-cfg-or "vario" "gefaelle_winkel" 3) (/ pi 180.0))))
(princ "\n\n=========================================")
(princ "\n BERECHNUNG FUER ALLE WINKEL (Standard)")
(princ "\n=========================================")
(princ (strcat "\n△L=" (rtos deltaL 2 2) " mm"
" △H=" (rtos deltaH 2 2) " mm"
" Richtung=" richtung))
(foreach winkel winkel-list
(if (= richtung "Auf")
(progn
(setq mass1 (get-bogen-mass bogen-auf winkel))
(setq mass2 (get-bogen-mass bogen-ab winkel))
)
(progn
(setq mass1 (get-bogen-mass bogen-ab winkel))
(setq mass2 (get-bogen-mass bogen-auf winkel))
)
)
(if (or (null mass1) (null mass2))
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
(progn
(setq rad5 (* 3.0 (/ pi 180.0)))
(setq rad7 (* (float (if (= richtung "Auf") (- 3 winkel) (+ winkel 3)))
(/ pi 180.0)))
(setq bogen-x1 (+ (* (car mass1) (cos rad5)) (* (caddr mass1) (sin rad5))))
(setq bogen-z1 (+ (* (- (car mass1)) (sin rad5)) (* (caddr mass1) (cos rad5))))
(setq bogen-x2 (+ (* (car mass2) (cos rad7)) (* (caddr mass2) (sin rad7))))
(setq bogen-z2 (+ (* (- (car mass2)) (sin rad7)) (* (caddr mass2) (cos rad7))))
(setq cosα (cos (* winkel (/ pi 180.0)))
sinα (sin (* winkel (/ pi 180.0))))
(setq A (- deltaL aus-dx ein-dx bogen-x1 bogen-x2
(* feste-hz cos3)))
(setq winkel-eff (if (= richtung "Auf") (- winkel 3) (+ winkel 3)))
(setq cosEff (cos (* winkel-eff (/ pi 180.0)))
sinEff (sin (* winkel-eff (/ pi 180.0))))
(if (= richtung "Auf")
(setq B (+ deltaH abs-dz-AUS abs-dz-EIN
(- bogen-z1) (- bogen-z2)
(* feste-hz sin3)))
(setq B (+ (- deltaH abs-dz-AUS abs-dz-EIN
(* feste-hz sin3))
bogen-z1 bogen-z2))
)
(if (> (abs sinα) 0.0001)
(progn
(setq L_GF (/ (- (* A sinEff) (* B cosEff)) sinα))
(if (= richtung "Auf")
(setq L_VF (/ (+ (* A sin3) (* B cos3)) sinα))
(setq L_VF (/ (- (* B cos3) (* A sin3)) sinα))
)
(if (and (numberp L_GF) (numberp L_VF))
(progn
(setq gueltig (and (>= L_GF 0) (>= L_VF 0)))
(setq ergebnis-liste
(cons (list winkel L_GF L_VF gueltig) ergebnis-liste))
)
(setq ergebnis-liste
(cons (list winkel nil nil nil) ergebnis-liste))
)
)
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
)
)
)
)
(setq ergebnis-liste (reverse ergebnis-liste))
(princ "\n\n=================================================================================")
(princ "\n ERGEBNISTABELLE")
(princ "\n=================================================================================")
(princ "\n Winkel L_GF (mm) L_VF (mm) Status")
(princ "\n=================================================================================")
(setq best-winkel nil best-L_GF nil best-L_VF nil)
(foreach item ergebnis-liste
(setq winkel (car item) L_GF (cadr item) L_VF (caddr item) gueltig (cadddr item))
(if (and (numberp L_GF) (numberp L_VF))
(progn
(princ (strcat "\n " (itoa winkel) (chr 176)
" " (fmt L_GF) " mm " (fmt L_VF) " mm "))
(if gueltig
(progn
(princ "GUELTIG")
(if (or (null best-winkel) (< winkel best-winkel))
(setq best-winkel winkel best-L_GF L_GF best-L_VF L_VF)
)
)
(princ "UNGUELTIG (negative Laenge)")
)
)
(princ (strcat "\n " (itoa winkel) (chr 176)
" --- --- FEHLER"))
)
)
(princ "\n=================================================================================")
(if best-winkel
(princ (strcat "\n>>> Empfohlener Winkel: " (itoa best-winkel) (chr 176)))
(princ "\n>>> KEIN passender Winkel gefunden!")
)
(list best-winkel best-L_GF best-L_VF ergebnis-liste)
)
;; Prueft/berechnet die Variante mit HORIZONTALER Zwischenstrecke (Schritt
;; 6/11 bei 0 Grad statt geneigt). Die beiden Vertikalboegen sind dabei
;; IMMER auf 3 Grad fixiert (Vario_Bogen_auf_3 / Vario_Bogen_ab_3), weil sie
;; nur zwischen der festen 3-Grad-Neigung von Umlenk-/Motorstation und der
;; horizontalen Mitte vermitteln muessen - unabhaengig von Auf/Ab.
;; WICHTIG (geometrische Konsequenz): GF1+GF2 (an AS/ES-Seite, ebenfalls
;; fest bei 3 Grad geneigt) sind die einzige nennenswerte Quelle fuer
;; Hoehenaenderung, da sich die beiden Boegen gegenseitig fast vollstaendig
;; kompensieren. Die feste 3-Grad-Neigung wirkt IMMER absenkend:
;; - "Ab": passt zur gewuenschten Absenkung -> deltaH praktisch beliebig
;; erreichbar (im Rahmen von deltaL), GF1+GF2 werden einfach laenger.
;; - "Auf": wirkt der gewuenschten Steigung entgegen -> nur fuer SEHR
;; KLEINE deltaH ueberhaupt gueltig (wenige cm).
;; Rueckgabe: (GF_total L_VF gueltig) oder nil falls Boegen nicht messbar.
(defun berechne-horizontale-mitte (deltaL deltaH richtung /
mass1 mass2 rad3 bogen-x1 bogen-z1
bogen-x2 bogen-z2 deltaH-signiert
A-hz B-hz GF_total L_VF-hz gueltig)
(setq mass1 (get-bogen-mass bogen-auf 3))
(setq mass2 (get-bogen-mass bogen-ab 3))
(if (or (null mass1) (null mass2))
nil
(progn
(setq rad3 (* 3.0 (/ pi 180.0)))
;; Bogen1 (immer auf_3): Eintritt bei 3 Grad (von Umlenkstation), biegt auf 0 Grad
(setq bogen-x1 (+ (* (car mass1) (cos rad3)) (* (caddr mass1) (sin rad3))))
(setq bogen-z1 (+ (* (- (car mass1)) (sin rad3)) (* (caddr mass1) (cos rad3))))
;; Bogen2 (immer ab_3): Eintritt bei 0 Grad (von der horizontalen Mitte), biegt auf 3 Grad
(setq bogen-x2 (car mass2))
(setq bogen-z2 (caddr mass2))
;; Signierte Ziel-Hoehenaenderung: Auf=+deltaH, Ab=-deltaH
(setq deltaH-signiert (if (= richtung "Auf") deltaH (- deltaH)))
;; Horizontal-Budget: deltaL minus AS/ES minus beide Boegen minus feste Stationen (bei 3 Grad)
(setq A-hz (- deltaL aus-dx ein-dx bogen-x1 bogen-x2
(* FESTE_HORIZONTAL (cos rad3))))
;; Hoehen-Budget: was GF1+GF2 (bei 3 Grad) noch beitragen muessen
(setq B-hz (- (+ aus-dz ein-dz (- (* FESTE_HORIZONTAL (sin rad3)))
bogen-z1 bogen-z2)
deltaH-signiert))
(setq GF_total (/ B-hz (sin rad3)))
(setq L_VF-hz (- A-hz (* GF_total (cos rad3))))
(setq gueltig (and (>= GF_total 0) (>= L_VF-hz 0)))
(list GF_total L_VF-hz gueltig)
)
)
)
;; ============================================================
;; TEIL 5: BERECHNE-WRAPPER (Schnittstelle fuer Registry)
;; ============================================================
;; Initialisiert Standard-Bibliothek und berechnet Winkel.
;; seite-Parameter wird fuer Standard-Typ nicht benoetigt (keine Vorab-Geometrie).
;; Die Machbarkeitspruefung fuer die horizontale Zwischenstrecke passiert
;; separat und VORAB in c:VarioFoerderer (vor der Foerderrichtung-Abfrage),
;; deshalb liefert diese Funktion nur noch die normale Winkelsuche zurueck.
(defun berechne-standard (deltaL deltaH richtung seite)
(setq FESTE_HORIZONTAL (ssg-cfg-or "vario" "feste_horizontal" 1600))
(setq staustrecke-basis (ssg-cfg-or "vario" "staustrecke_basis" 1000))
(init-bibliothek)
(berechne-alle-winkel deltaL deltaH richtung nil)
)
;; ============================================================
;; TEIL 6: EINFUEGEN (11 Schritte, ohne VF_*-Block-Erstellung)
;; ============================================================
;; Gibt endpunkt zurueck (letzter KS_AUS nach ES_90).
;; VF_*-Block-Erstellung erfolgt zentral im Dispatcher (vf_core.lsp).
;; hz: horizontale Fahrtrichtung in Grad (0=Ost/+X, 90=Nord/+Y, 180=West/-X,
;; 270=Sued/-Y). Default 0, falls vom Aufrufer nicht mitgegeben (Etage-
;; Registry-Kompatibilitaet - siehe c:VarioFoerderer).
;; --- Teil 1/3: AS-Element (Kettenanfang) ---
;; Eigenstaendig, damit vf-linienzug (Gemischte GF/VF-Kette) ein VF-Segment
;; auch OHNE eigenes AS/ES mitten in der Kette einfuegen kann (vfs-mitte-teil
;; alleine), waehrend ein normaler Standard-VarioFoerderer weiterhin alle 3
;; Teile nacheinander durchlaeuft (siehe variofoerderer-einfuegen unten).
(defun vfs-as-teil (startpunkt seite hz / as-block)
(if (null hz) (setq hz 0.0))
(setq hz (float hz))
(setq as-block (strcat "AS_Element_90_" seite))
(if (not *lib-initialized*) (init-bibliothek))
(princ (strcat "\n\n1/11: " as-block " (hz=" (rtos hz 2 1) grad-zeichen ")"))
(insert-block-by-ks as-block startpunkt hz)
)
;; --- Teil 2a: VF-Eingang (GF1 + Separator + Umlenkstation) ---
;; Beginnt eine reine VF-Einheit: bringt die Kette von der (3-Grad-geneigten)
;; AS-Seite ueber GF1 + Separator bis zur Umlenkstation. Wird pro VF-Einheit
;; GENAU EINMAL aufgerufen (auch wenn danach mehrere Sub-Segmente folgen).
(defun vfs-vf-entry (aktueller-punkt L_GF1 hz)
(if (null hz) (setq hz 0.0))
(setq hz (float hz))
;; 1. Gefaellestrecke GF1 (verbindet AS-Neigung mit Umlenkstation)
(if (> L_GF1 0.1)
(progn
(princ (strcat "\n\n[VF-Eingang] Gefaellestrecke GF1 (3 Grad, L=" (rtos L_GF1 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_GF1 (ssg-cfg-or "vario" "gefaelle_winkel" 3) hz))
)
(princ "\n\n[VF-Eingang] Gefaellestrecke GF1 (uebersprungen)")
)
;; 2. Separator (am GF1-Ende / vor Umlenkstation)
(princ "\n[VF-Eingang] Separator (300 mm, 3 Grad geneigt)")
(setq aktueller-punkt
(insert-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
(ssg-cfg-or "vario" "gefaelle_winkel" 3)
(ssg-cfg-or "vario" "separator_block_dx" 300)
(ssg-cfg-or "vario" "separator_block_dz" 0) hz))
;; 3. Umlenkstation
(princ "\n[VF-Eingang] Umlenkstation (500 mm, 3 Grad geneigt)")
(setq aktueller-punkt
(insert-rotated-block-with-ks "Vario_Umlenkstation_500mm" aktueller-punkt
(ssg-cfg-or "vario" "gefaelle_winkel" 3)
(ssg-cfg-or "vario" "station_block_dx" 500)
(ssg-cfg-or "vario" "station_block_dz" 0) hz))
aktueller-punkt
)
;; --- Teil 2b: VF-Koerper (Vertikalbogen + L_VF + Vertikalbogen) ---
;; EIN reines VF-Sub-Segment. Wichtig: es BEGINNT und ENDET auf der
;; 3-Grad-Basisneigung, weil Ein- und Ausgangsbogen denselben Winkel haben.
;; Dadurch lassen sich mehrere Sub-Segmente (und Vario-Kurven dazwischen)
;; beliebig aneinanderreihen (siehe doc/VarioFoerderer_Linienzug_Prinzipien.md).
;; best-winkel=0 => horizontales Sub-Segment (Boegen fest auf_3/ab_3).
(defun vfs-vf-koerper (aktueller-punkt richtung best-winkel L_VF hz /
bogen-name bogen-mass bogen-dx bogen-dz)
(if (null hz) (setq hz 0.0))
(setq hz (float hz))
;; 5. 1. Vertikalbogen
;; Sonderfall best-winkel=0 (horizontale Zwischenstrecke, siehe
;; berechne-horizontale-mitte): Boegen IMMER auf_3/ab_3, unabhaengig von
;; Auf/Ab, da sie nur zwischen der festen 3-Grad-Neigung und der
;; horizontalen Mitte vermitteln muessen.
(if (= best-winkel 0)
(progn
(setq bogen-name "Vario_Bogen_auf_3")
(setq bogen-mass (get-bogen-mass bogen-auf 3))
)
(if (= richtung "Auf")
(progn
(setq bogen-name (strcat "Vario_Bogen_auf_" (itoa best-winkel)))
(setq bogen-mass (get-bogen-mass bogen-auf best-winkel))
)
(progn
(setq bogen-name (strcat "Vario_Bogen_ab_" (itoa best-winkel)))
(setq bogen-mass (get-bogen-mass bogen-ab best-winkel))
)
)
)
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
(princ (strcat "\n\n5/11: " bogen-name " (3 Grad geneigt)"))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt
(ssg-cfg-or "vario" "gefaelle_winkel" 3) bogen-dx bogen-dz hz))
;; 6. Variable Strecke L_VF
(if (> L_VF 0.1)
(progn
(if (= best-winkel 0)
(progn
(princ (strcat "\n\n6/11: Horizontale Zwischenstrecke (0 Grad, L="
(rtos L_VF 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_VF 0 hz))
)
(if (= richtung "Auf")
(progn
(princ (strcat "\n\n6/11: Steigungsstrecke ("
(itoa (- (- best-winkel 3))) " Grad, L=" (rtos L_VF 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_VF (- (- best-winkel 3)) hz))
)
(progn
(princ (strcat "\n\n6/11: Gefaellestrecke ("
(itoa (+ best-winkel 3)) " Grad, L=" (rtos L_VF 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_VF (+ best-winkel 3) hz))
)
)
)
)
(princ "\n\n6/11: (uebersprungen)")
)
;; 7. 2. Vertikalbogen
(if (= best-winkel 0)
(progn
(setq bogen-name "Vario_Bogen_ab_3")
(setq bogen-mass (get-bogen-mass bogen-ab 3))
)
(if (= richtung "Auf")
(progn
(setq bogen-name (strcat "Vario_Bogen_ab_" (itoa best-winkel)))
(setq bogen-mass (get-bogen-mass bogen-ab best-winkel))
)
(progn
(setq bogen-name (strcat "Vario_Bogen_auf_" (itoa best-winkel)))
(setq bogen-mass (get-bogen-mass bogen-auf best-winkel))
)
)
)
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
(if (= best-winkel 0)
(progn
(princ (strcat "\n\n7/11: " bogen-name " (3 Grad geneigt)"))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt
0 bogen-dx bogen-dz hz))
)
(if (= richtung "Auf")
(progn
(princ (strcat "\n\n7/11: " bogen-name
" (" (itoa (- 3 best-winkel)) " Grad geneigt)"))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt
(- 3 best-winkel) bogen-dx bogen-dz hz))
)
(progn
(princ (strcat "\n\n7/11: " bogen-name
" (" (itoa (+ best-winkel 3)) " Grad geneigt)"))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt
(+ best-winkel 3) bogen-dx bogen-dz hz))
)
)
)
aktueller-punkt
)
;; --- Teil 2c: VF-Ausgang (Motorstation [+ GF2] [+ Separator]) ---
;; Schliesst eine reine VF-Einheit mit der Motorstation.
;; L_GF2 > 0.1 => GF2 (3 Grad) wird angehaengt (verbindet Motorstation
;; mit der Auslauf-Neigung).
;; mit-separator T => Separator (300 mm) am Ende (Standard-VF: vor ES).
;; Standard-VF: L_GF2 = L_GF/2, mit-separator = t.
;; Linienzug: Separator wird NICHT hier gebaut (er sitzt erst vor dem ES bzw.
;; optional zwischen Foerderern) -> mit-separator = nil; GF2 je nach Wahl.
(defun vfs-vf-exit (aktueller-punkt L_GF2 hz mit-separator)
(if (null hz) (setq hz 0.0))
(setq hz (float hz))
;; Motorstation
(princ "\n\n[VF-Ausgang] Motorstation (500 mm, 3 Grad geneigt)")
(setq aktueller-punkt
(insert-rotated-block-with-ks "Vario_Motorstation_500mm" aktueller-punkt
(ssg-cfg-or "vario" "gefaelle_winkel" 3)
(ssg-cfg-or "vario" "station_block_dx" 500)
(ssg-cfg-or "vario" "station_block_dz" 0) hz))
;; GF2 (optional, verbindet Motorstation mit der Auslauf-Neigung)
(if (> L_GF2 0.1)
(progn
(princ (strcat "\n[VF-Ausgang] Gefaellestrecke GF2 (3 Grad, L=" (rtos L_GF2 2 2) " mm)"))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_GF2 (ssg-cfg-or "vario" "gefaelle_winkel" 3) hz))
)
(princ "\n[VF-Ausgang] GF2 (kein / uebersprungen)")
)
;; Separator (optional, nur Standard-VF)
(if mit-separator
(progn
(princ "\n[VF-Ausgang] Separator (300 mm, 3 Grad geneigt)")
(setq aktueller-punkt
(insert-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
(ssg-cfg-or "vario" "gefaelle_winkel" 3)
(ssg-cfg-or "vario" "separator_block_dx" 300)
(ssg-cfg-or "vario" "separator_block_dz" 0) hz))
)
)
aktueller-punkt
)
;; --- Teil 2 (Zusammensetzung): Kettenmitte fuer den Standard-VF ---
;; Entry + EIN Koerper + Exit. Verhalten identisch zur bisherigen Fassung.
(defun vfs-mitte-teil (aktueller-punkt richtung best-winkel L_GF1 L_GF2 L_VF hz)
(if (null hz) (setq hz 0.0))
(setq hz (float hz))
(setq aktueller-punkt (vfs-vf-entry aktueller-punkt L_GF1 hz))
(setq aktueller-punkt (vfs-vf-koerper aktueller-punkt richtung best-winkel L_VF hz))
(setq aktueller-punkt (vfs-vf-exit aktueller-punkt L_GF2 hz t))
aktueller-punkt
)
;; --- Teil 3/3: ES-Element (Kettenende) ---
(defun vfs-es-teil (aktueller-punkt seite hz / es-block)
(if (null hz) (setq hz 0.0))
(setq hz (float hz))
(setq es-block (strcat "ES_Element_90_" seite))
(princ (strcat "\n\n11/11: " es-block " (hz=" (rtos hz 2 1) grad-zeichen ")"))
(insert-block-by-ks es-block aktueller-punkt hz)
)
;; --- Zusammensetzung: kompletter Standard-VarioFoerderer ---
;; Reine Verkettung von Teil 1+2+3, Verhalten identisch zur bisherigen
;; monolithischen Fassung. deltaL/deltaH werden hier nicht gebraucht (Teil
;; der einfuege-fn-Schnittstelle der Typ-Registry, siehe vf-typ-registrieren).
(defun variofoerderer-einfuegen (deltaL deltaH richtung best-winkel
L_GF1 L_GF2 L_VF startpunkt seite hz
/ aktueller-punkt endpunkt)
(if (null hz) (setq hz 0.0))
(setq hz (float hz))
(setq aktueller-punkt (vfs-as-teil startpunkt seite hz))
(setq aktueller-punkt
(vfs-mitte-teil aktueller-punkt richtung best-winkel L_GF1 L_GF2 L_VF hz))
(setq endpunkt (vfs-es-teil aktueller-punkt seite hz))
(princ "\n\n=========================================")
(princ "\n>>> Standard VarioFoerderer eingefuegt!")
endpunkt
)
;; ============================================================
;; REGISTRIERUNG
;; ============================================================
(vf-typ-registrieren
"standard"
'berechne-standard
'variofoerderer-einfuegen
"Standard VarioFoerderer (AS/ES 90 Grad, horizontal versetzt)")
(princ "\n>>> vf_standard.lsp geladen - Typ 'standard' registriert")
(princ)
+179 -69
View File
@@ -1,25 +1,167 @@
# test
# dxfmakros
> Kurze Projektbeschreibung hier eintragen.
AutoLISP-Makros fuer BricsCAD Pro zur automatisierten Erstellung von Foerderanlagen- und Kreisel-Layouts.
## Menustruktur (SSG_LIB)
```
SSG_LIB
├── ILS
│ ├── Kreisel-Module
│ │ ├── Einfuegen → KreiselInsert
│ │ ├── Verbinden → KreiselConnect
│ │ ├── Bearbeiten → KreiselEdit
│ │ └── Eckrad → ILS_Eckrad
│ ├── Zusatzmodul
│ │ ├── BTMT-Beladung → ILS_BTMT_Beladung
│ │ └── BTMT-Entladung → ILS_BTMT_Entladung
│ ├── Foerderer
│ │ ├── TEF Strecke → ILS_TEF_Strecke
│ │ ├── VarioFoerderer → FOERDERANLAGE
│ │ ├── Kurven angetr. Aussen → ILS_K{90,60,30}{LA,RA}
│ │ ├── Kurven angetr. Innen → ILS_K{90,60,30}{LI,RI}
│ │ └── Gefaellestrecke → ILS_G{K90,K60,K30}{L,R}
│ └── ILS Schliessen
├── Omniflo
│ ├── Boegen
│ │ ├── 90 → OMNI_APB_630_90
│ │ ├── 67.5 → OMNI_APB_550_675
│ │ ├── 45 → OMNI_APB_630_45
│ │ ├── 22.5 → OMNI_APB_550_225
│ │ └── 180 → OMNI_APB_650_180
│ ├── Aluprofil Gerade
│ │ ├── AP 60 → OMNI_AP60
│ │ ├── AP 110 → OMNI_AP110
│ │ └── APG 110 → OMNI_APG110
│ ├── Weiche 90 Grad
│ │ ├── Einfach → OMNI_W90_Einfach
│ │ ├── Doppel → OMNI_W90_Doppel
│ │ └── Dreiwege → OMNI_W90_Dreiwege
│ ├── Weiche 45 Grad
│ │ ├── Einfach → OMNI_W45_Einfach
│ │ ├── Doppel → OMNI_W45_Doppel
│ │ └── Dreiwege → OMNI_W45_Dreiwege
│ ├── Weichen Parallel
│ │ ├── Einfach → OMNI_WP_Einfach
│ │ ├── Doppel → OMNI_WP_Doppel
│ │ └── Dreiwege → OMNI_WP_Dreiwege
│ ├── Weichenkoerper
│ │ ├── Einfach → OMNI_WK_Einfach
│ │ ├── Doppel → OMNI_WK_Doppel
│ │ └── Dreiwege → OMNI_WK_Dreiwege
│ ├── Weichenkombinationen
│ │ ├── Delta → OMNI_WKomb_Delta
│ │ └── Star → OMNI_WKomb_Star
│ ├── TEF Elemente
│ │ ├── Umlenkspannst. rechts → OMNI_TEF_UmlenkR
│ │ ├── Umlenkspannst. links → OMNI_TEF_UmlenkL
│ │ ├── Antriebst. links → OMNI_TEF_AntriebL
│ │ ├── Antriebst. rechts → OMNI_TEF_AntriebR
│ │ └── TEF Gerade → OMNI_TEF_Gerade
│ └── KettenFoerderer → OMNI_KettenFoerderer
└── External
├── Call Python → CALLPYTHON
├── Export Sivas → EXPORTSIVAS
└── Export CSV → EXPORTCSV
```
## Befehle nach Modul
### KreiselInsert.lsp - Kreisel Modul-Einfuegesystem
Zeichnet ILS-Kreiselmodule als Compound-Bloecke mit konfigurierbarem Abstand, Typ und Attributen.
| Befehl | Beschreibung |
| --- | --- |
| `KreiselInsert` | Modul an manuell gewaehltem Punkt einfuegen (Abstand, Drehung, Hoehe, Typ interaktiv) |
| `KreiselConnect` | Smart Connect: Kreisel zwischen zwei parallelen Linien einfuegen, berechnet Position/Abstand/Rotation automatisch |
| `KreiselEdit` | Bestehenden Kreisel per DCL-Dialog bearbeiten (Name, Abstand, Hoehe, Ausrichtung, Drehrichtung, Typ) |
| `KreiselRedraw` | Kreisel mit optionalem neuem Abstand/Hoehe neu zeichnen, Attribute bleiben erhalten |
| `KreiselQuick` | Schnelleinfuegen mit Standardparametern (horizontal) |
| `KreiselParams` | Aktuelle Kreisel-Parameterkonfiguration anzeigen |
| `ILS_Eckrad` | Einzelnen AN8-Block (Antriebs-/Eckrad) an gewaehltem Punkt einfuegen |
| `KreiselLabelPos` | Label-Position (X/Y-Offset) konfigurieren |
| `KreiselLabelHoehe` | Label-Texthoehe konfigurieren |
| `KreiselLabelSetup` | Label-Darstellung konfigurieren (Hoehe, Farbe, Abstand, Schriftart) |
### OmniModulInsert.lsp - Omniflo Komponenten
Einfuegen von Omniflo-Standardkomponenten (Boegen, Geraden, Weichen, TEF-Elemente).
| Befehl | Beschreibung |
| --- | --- |
| `OMNI_LOAD` | Omniflo-Komponentendaten aus JSON-Dateien laden |
| `OMNI_INFO_BOGEN` | Info zu einem Omniflo-Bogen nach Sivas-ID anzeigen |
| `OMNI_INFO_WEICHE` | Info zu einer Omniflo-Weiche nach Sivas-ID anzeigen |
| `OMNI_APB_*` | Boegen einfuegen (90, 67.5, 45, 22.5, 180 Grad) |
| `OMNI_AP60/AP110/APG110` | Aluprofil-Geraden einfuegen |
| `OMNI_W90/W45/WP/WK_*` | Weichen einfuegen (Einfach, Doppel, Dreiwege) |
| `OMNI_WKomb_Delta/Star` | Weichenkombinationen einfuegen |
| `OMNI_TEF_*` | TEF-Elemente einfuegen (Umlenk-/Antriebsstationen, Gerade) |
| `OMNI_KettenFoerderer` | Kettenfoerderer einfuegen |
### VarioFoerderer.lsp - Foerderanlage Generator (v24.4)
Generiert komplette Vario-Foerderanlagen mit Vertikalboegen, Motor-/Spannstationen, Staustrecken und Ein-/Ausschleus-Elementen.
| Befehl | Beschreibung |
| --- | --- |
| `FOERDERANLAGE` | Interaktiver Generator: Zwei Punkte oder manuelle Distanz/Hoehe, berechnet optimalen Bogenwinkel |
| `FOERDERTEST` | Automatischer Testlauf (Distanz=6000, Hoehe=2000, Richtung=Auf), speichert als DXF |
Unterstuetzte Bogenwinkel: 3, 9, 12, 15, 24, 36, 48 Grad
### ssg_layer.lsp - Layerverwaltung
| Befehl | Beschreibung |
| --- | --- |
| `SSG-LayerSet` | Objekt anklicken, dessen Layer wird aktiv |
| `SSG-LayerInfo` | Layer eines angeklickten Objekts anzeigen |
| `SSG-LayerMove` | Selektierte Objekte auf Ziel-Layer verschieben |
| `SSG-LayerCopy` | Selektierte Objekte auf Ziel-Layer kopieren |
| `SSG-LayerMoveType` | Alle Objekte gleichen Typs von Referenz- auf Ziel-Layer verschieben |
| `SSG-LayerOff` | Layer per Klick ausschalten (mehrfach moeglich) |
| `SSG-LayerFreeze` | Layer per Klick einfrieren (mehrfach moeglich) |
| `SSG-FreezeAll` | Alle Layer ausser dem angeklickten einfrieren |
| `SSG-ThawAll` | Alle eingefrorenen Layer auftauen |
| `SSG-LayerOnAll` | Alle ausgeschalteten Layer einschalten |
| `SSG-LayerDelete` | Layer und alle Objekte darauf loeschen (mit Bestaetigung) |
### tests.lsp - Export und Python-Integration
| Befehl | Beschreibung |
| --- | --- |
| `CALLPYTHON` | Python-Skripte via CLI aufrufen, Ausgabe loggen |
| `EXPORTSIVAS` | Daten im Sivas-Format exportieren |
| `EXPORTCSV` | Zeichnungsdaten als CSV exportieren |
## Kernbibliotheken (Lisp/)
| Datei | Beschreibung |
| --- | --- |
| `ssg_core.lsp` | Kernel: Umgebung, Layer-Ops, Block-Ops, Attribut-Ops, Fehlerbehandlung |
| `ssg_dialog.lsp` | Dialog-Vorlagen: Slide-Preview, Modul-Dialog, Block-Einfuegesequenz |
| `ssg_layer.lsp` | Layer-Verwaltungsbefehle |
| `ssg_load.lsp` | Loader: Laedt alle SSG-Bibliotheken in korrekter Reihenfolge |
| `on_start.lsp` | Startup-Skript: Setzt Umgebung und laedt Libraries |
## Projektstruktur
```
test/
├── bin/ # Skripte zur Umgebungsverwaltung
│ ├── setenv.bat/.sh # Umgebungsvariablen setzen
├── install_py.bat/.sh # venv erstellen + pip install
│ ├── activate_venv.bat/.sh # venv aktivieren
│ └── get_cmd.bat/.sh # Shell mit Umgebung oeffnen
├── cfg/ # Konfigurationsdateien (INI/JSON)
├── data/ # Eingabedaten (nicht im Git)
├── doc/ # Dokumentation
├── examples/ # Beispieldateien
├── lib/ # Python-Quellcode / Bibliothek
├── log/ # Log-Dateien (nicht im Git)
├── results/ # Ergebnisse / Ausgaben (nicht im Git)
├── tests/ # Unit Tests
├── .gitignore
```text
dxfmakros/
├── Blocks/ # DWG-Bloecke (AN8, SP8, Vertikalboegen, etc.)
├── Lisp/ # AutoLISP-Makros und Kernbibliotheken
├── bin/ # Hilfs-Skripte (setenv, create_tests, etc.)
├── cfg/ # Konfigurationsdateien (attradd.cfg)
├── data/ # Quelldaten (JSON, DXF) - nicht im Git
├── dcl/ # DCL-Dialogdefinitionen (kreisel_edit.dcl)
├── doc/ # Dokumentation und Referenz-DXFs
├── examples/ # Beispieldateien
├── lib/ # Python-Skripte (export_csv.py, etc.)
├── logs/ # Logdateien - nicht im Git
├── menu/ # BricsCAD-Menudefinition (SSG_LIB.mnu)
├── results/ # Ergebnisse / Exporte - nicht im Git
├── tests/ # Testskripte und Referenzdaten
├── LICENSE
├── README.md
└── requirements.txt
@@ -27,64 +169,32 @@ test/
## Umgebungsvariablen
| Variable | Beschreibung |
|----------------|---------------------------|
| `DXFMAKRO` | Wurzelverzeichnis |
| `DXFM_BIN` | Skriptverzeichnis |
| `DXFM_LIB` | Python-Quellcode |
| `DXFM_CFG` | Konfigurationsdateien |
| `DXFM_DATA` | Eingabedaten |
| `DXFM_LOG` | Log-Dateien |
| `DXFM_RESULTS` | Ergebnisse |
| `DXFM_EXAMPLES` | Beispieldateien |
| `PYTHONPATH` | Erweitert um `DXFM_LIB` |
| Variable | Beschreibung |
| --- | --- |
| `DXFMAKRO` | Wurzelverzeichnis des Projekts |
| `DXFM_BLOCKS` | Pfad zum Blocks-Verzeichnis |
| `DXFM_LISP` | Pfad zu den LISP-Dateien |
| `DXFM_RESULTS` | Pfad fuer DXF-Exporte |
| `DXFM_BIN` | Skriptverzeichnis |
| `DXFM_LIB` | Python-Quellcode |
| `DXFM_CFG` | Konfigurationsdateien |
| `DXFM_TESTS` | Testverzeichnis |
| `DXFM_DATA` | Datenverzeichnis |
| `BRICSCAD` | Pfad zur BricsCAD-Executable |
## Installation
## Einrichtung
### Voraussetzungen
1. `bin\setenv.bat` ausfuehren (setzt alle Umgebungsvariablen)
2. BricsCAD starten - `on_start.lsp` laedt alle Libraries automatisch via `startup.scr`
3. Menu `SSG_LIB` nutzen oder Befehle in der Kommandozeile ausfuehren
- Python 3.10 oder hoeher
### Setup (Windows)
## Tests
```bat
bin\install_py.bat
bin\create_tests.bat
```
### Setup (Linux / macOS)
```bash
bash bin/install_py.sh
```
## Nutzung
### Umgebung setzen
```bat
bin\setenv.bat # Windows
```
```bash
source bin/setenv.sh # Linux / macOS
```
### Shell mit gesetzten Variablen oeffnen
```bat
bin\get_cmd.bat # Windows
```
```bash
source bin/get_cmd.sh # Linux / macOS
```
### venv aktivieren
```bat
bin\activate_venv.bat # Windows
```
```bash
source bin/activate_venv.sh # Linux / macOS
```
Erzeugt eine Test-DXF, fuehrt Kreisel-Einfuege- und Exportbefehle aus, und validiert die Ergebnisse gegen Referenzdateien in `tests/references/`.
## Lizenz
+41
View File
@@ -0,0 +1,41 @@
@echo off
REM ================================================================
REM create_tests.bat - ILS Testlauf
REM
REM Ablauf:
REM 1. Umgebung setzen
REM 2. Python: ILStest.dxf mit Linien erzeugen
REM 3. BricsCAD: Kreisel einfuegen, exportieren, speichern
REM 4. Python: Ergebnisse gegen Referenzen validieren
REM ================================================================
call "%~dp0setenv.bat"
echo.
echo ================================================================
echo ILS TEST - Schritt 1: Basis-DXF erzeugen
echo ================================================================
python "%DXFM_TESTS%\create_ILStest_dxf.py" "%DXFM_TESTS%\ILStest.dxf"
if errorlevel 1 (
echo FEHLER: DXF-Erzeugung fehlgeschlagen!
pause
exit /b 1
)
echo.
echo ================================================================
echo ILS TEST - Schritt 2: BricsCAD starten und Kreisel erzeugen
echo ================================================================
echo BricsCAD wird gestartet mit dem Testskript...
echo Nach Abschluss des Tests BricsCAD schliessen.
echo.
start /wait "" %BRICSCAD% /s "%DXFM_TESTS%\ILS_test.scr"
echo.
echo ================================================================
echo ILS TEST - Schritt 3: Ergebnisse validieren
echo ================================================================
python "%DXFM_TESTS%\validate_tests.py" "%DXFM_RESULTS%" "%DXFM_TESTS%\references"
echo.
pause
+96
View File
@@ -0,0 +1,96 @@
@echo off
REM ================================================================
REM run_tests.bat - Testausfuehrung fuer SSG_LIB
REM
REM Schalter:
REM --check Fuehrt pytest-Validierung aus
REM (ohne) Zeigt Hilfe an
REM
REM Beispiele:
REM bin\run_tests.bat --check
REM bin\run_tests.bat --check test_kreisel.py
REM ================================================================
REM Umgebung setzen
call "%~dp0setenv.bat"
REM Virtuelle Umgebung aktivieren
if exist "%DXFMAKRO%\.venv\Scripts\activate.bat" (
call "%DXFMAKRO%\.venv\Scripts\activate.bat"
) else (
echo WARNUNG: .venv nicht gefunden - pytest muss im PATH sein!
)
set DO_CHECK=0
set CHECK_ARG=
REM Argumente parsen
:parse_args
if "%~1"=="" goto :after_args
if "%~1"=="--check" (
set DO_CHECK=1
if not "%~2"=="" (
set "CHECK_ARG=%~2"
shift
)
shift
goto :parse_args
)
echo Unbekannter Schalter: %~1
goto :show_help
:after_args
if %DO_CHECK%==0 goto :show_help
REM ================================================================
REM --check: pytest-Validierung
REM ================================================================
if %DO_CHECK%==1 (
echo.
echo ================================================================
echo PYTEST VALIDIERUNG
echo ================================================================
REM Pruefen ob output-Verzeichnis Ergebnisse enthaelt
if not exist "%DXFM_TESTOUT%\*.json" (
echo.
echo WARNUNG: Keine Ergebnisse in %DXFM_TESTOUT%
echo Zuerst TESTRUN in BricsCAD ausfuehren!
echo.
)
if not "%CHECK_ARG%"=="" (
echo Teste: %CHECK_ARG%
pytest "%DXFM_TESTS%\%CHECK_ARG%" -v
) else (
echo Teste: alle Module
pytest "%DXFM_TESTS%" -v
)
if errorlevel 1 (
echo.
echo ================================================================
echo ERGEBNIS: TESTS FEHLGESCHLAGEN
echo ================================================================
exit /b 1
)
echo.
echo ================================================================
echo ERGEBNIS: ALLE TESTS BESTANDEN
echo ================================================================
)
exit /b 0
:show_help
echo.
echo Aufruf: bin\run_tests.bat --check [testdatei]
echo.
echo Schalter:
echo --check Fuehrt pytest-Validierung fuer alle Module aus
echo --check test_kreisel.py Validiert nur Kreisel-Tests
echo.
echo Workflow:
echo 1. In BricsCAD: SSG_RUN_ALL_TESTS ausfuehren
echo 2. bin\run_tests.bat --check
echo.
exit /b 1
+8
View File
@@ -0,0 +1,8 @@
@echo off
REM ================================================================
REM Fuegt Attribute (ATTDEF) zu Omniflo DXF-Dateien hinzu
REM ================================================================
call "%~dp0setenv.bat"
python "%DXFM_LIB%\set_attributs.py" %*
+8
View File
@@ -0,0 +1,8 @@
@echo off
REM ================================================================
REM Setzt Einfuegepunkte fuer Omniflo DXF-Dateien
REM ================================================================
call "%~dp0setenv.bat"
python "%DXFM_LIB%\set_koords.py" %*
+8
View File
@@ -0,0 +1,8 @@
@echo off
REM ================================================================
REM Setzt Einfuegepunkte fuer Omniflo DXF-Dateien
REM ================================================================
call "%~dp0setenv.bat"
python "%DXFM_LIB%\set_einfuegepkt.py" %*
+59 -17
View File
@@ -4,7 +4,7 @@ REM ================================================================
REM TEST - Umgebungsvariablen Setup
REM ================================================================
echo Setting up environment variables for TEST ...
echo Setting up environment variables for DXFMAKROS ...
REM Basis-Projektpfad (aktueller Ordner)
set "DXFMAKRO=%~dp0.."
@@ -15,41 +15,83 @@ REM Pfade fuer verschiedene Komponenten
set "DXFM_BIN=%DXFMAKRO%\bin"
set "DXFM_LIB=%DXFMAKRO%\lib"
set "DXFM_DATA=%DXFMAKRO%\data"
set "DXFM_TESTS=%DXFMAKRO%\tests"
set "DXFM_TESTDATA=%DXFM_TESTS%\testdata"
set "DXFM_TESTOUT=%DXFM_TESTS%\output"
set "DXFM_TESTREF=%DXFM_TESTS%\reference"
set "DXFM_CFG=%DXFMAKRO%\cfg"
set "DXFM_BLOCKS=%DXFMAKRO%\Blocks"
set "DXFM_LOG=%DXFMAKRO%\logs"
set "DXFM_LISP=%DXFMAKRO%\Lisp"
set "DXFM_DCL=%DXFMAKRO%\dcl"
set "DXFM_RESULTS=%DXFMAKRO%\results"
REM 2D/3D-Modus: Standard ist 3D (alle Module nutzen data\ils\3D\)
set "DXFM_DIM=3D"
set BRICSCAD="C:\Program Files\Bricsys\BricsCAD V25 de_DE\bricscad.exe"
REM Python-Pfad erweitern (nur wenn noch nicht vorhanden)
echo %PYTHONPATH% | find /i "%DXFM_LIB%" >nul
if errorlevel 1 (
set "PYTHONPATH=%DXFM_LIB%;%PYTHONPATH%"
if exist "C:\Program Files\Bricsys\BricsCAD V25 de_DE\bricscad.exe" (
set "BRICSCAD=C:\Program Files\Bricsys\BricsCAD V25 de_DE\bricscad.exe"
) else if exist "C:\Program Files\Bricsys\BricsCAD V22 de_DE\bricscad.exe" (
set "BRICSCAD=C:\Program Files\Bricsys\BricsCAD V22 de_DE\bricscad.exe"
) else if exist "D:\Programme\BricsCAD\bricscad.exe" (
set "BRICSCAD=D:\Programme\BricsCAD\bricscad.exe"
) else (
echo Keine BricsCAD-Installation gefunden.
)
REM Ueberladen von Umgebungsvariablen durch _setenv.bat (z.B. DXFM_DIM=3D)
if exist "%~dp0_setenv.bat" (
echo Lade lokale Umgebungseinstellungen aus _setenv.bat...
call "%~dp0_setenv.bat"
)
REM Kommandozeilenparameter hat hoechste Prioritaet
if /i "%1"=="3D" set "DXFM_DIM=3D"
if /i "%1"=="2D" set "DXFM_DIM=2D"
REM Abhaengige Pfade nach Override berechnen
set "DXFM_BLOCKS=%DXFMAKRO%\data\ils\%DXFM_DIM%"
set "DXFM_OMNIFLO=%DXFMAKRO%\data\omniflo\%DXFM_DIM%"
REM Ordner erstellen falls sie nicht existieren
if not exist "%DXFM_BIN%" mkdir "%DXFM_BIN%"
if not exist "%DXFM_CFG%" mkdir "%DXFM_CFG%"
if not exist "%DXFM_LIB%" mkdir "%DXFM_LIB%"
if not exist "%DXFM_DATA%" mkdir "%DXFM_DATA%"
if not exist "%DXFM_BLOCKS%" mkdir "%DXFM_BLOCKS%"
if not exist "%DXFM_OMNIFLO%" mkdir "%DXFM_OMNIFLO%"
if not exist "%DXFM_LISP%" mkdir "%DXFM_LISP%"
if not exist "%DXFM_LOG%" mkdir "%DXFM_LOG%"
if not exist "%DXFM_RESULTS%" mkdir "%DXFM_RESULTS%"
if not exist "%DXFM_TESTDATA%" mkdir "%DXFM_TESTDATA%"
if not exist "%DXFM_TESTOUT%" mkdir "%DXFM_TESTOUT%"
if not exist "%DXFM_TESTREF%" mkdir "%DXFM_TESTREF%"
REM Hinweis: setx (dauerhaft) wird hier nicht verwendet.
REM Variablen gelten nur fuer diesen Prozess und Kindprozesse (z.B. BricsCAD).
REM Falls dauerhafte Registry-Eintraege benoetigt werden: setenv.bat --persist aufrufen.
if /i "%1"=="--persist" (
echo Setze Umgebungsvariablen dauerhaft in der Registry ^(setx^)...
setx DXFMAKRO "%DXFMAKRO%" >nul
setx DXFM_LISP "%DXFM_LISP%" >nul
setx DXFM_DATA "%DXFM_DATA%" >nul
setx DXFM_DCL "%DXFM_DCL%" >nul
setx DXFM_CFG "%DXFM_CFG%" >nul
setx DXFM_LOG "%DXFM_LOG%" >nul
setx DXFM_DIM "%DXFM_DIM%" >nul
setx DXFM_BLOCKS "%DXFM_BLOCKS%" >nul
echo Dauerhaft gesetzt. Gilt fuer alle neuen Prozesse.
)
REM Umgebungsvariablen anzeigen
echo.
echo ================================================================
echo TEST ENVIRONMENT SETUP COMPLETE
echo ================================================================
echo DXFMAKRO = %DXFMAKRO%
echo DXFM_BIN = %DXFM_BIN%
echo DXFM_CFG = %DXFM_CFG%
echo DXFM_LIB = %DXFM_LIB%
echo DXFM_DATA = %DXFM_DATA%
echo DXFM_BLOCKS = %DXFM_BLOCKS%
echo DXFM_LISP = %DXFM_LISP%
echo PYTHONPATH = %PYTHONPATH%
echo DXFM_DIM = %DXFM_DIM%
echo DXFM_BLOCKS = %DXFM_BLOCKS%
echo DXFM_OMNIFLO = %DXFM_OMNIFLO%
echo ================================================================
echo.
+3
View File
@@ -0,0 +1,3 @@
call "%~dp0setenv.bat"
echo DXFMAKRO=%DXFMAKRO%
start "" "%BRICSCAD%"
+105
View File
@@ -0,0 +1,105 @@
# ============================================================
# attradd.cfg - Attribut-Konfiguration fuer Omniflo DXF-Elemente
#
# Format:
# [ABSCHNITT] Elementtyp (bogen / weiche / layer)
# TAG = QUELLE QUELLE ist entweder:
# - ein JSON-Feldname (wird aus omniflo_*.json gelesen)
# - ein fester Wert in Anfuehrungszeichen: "fester Text"
# - ein Platzhalter: {layer}, {sivasnr}
#
# Verfuegbare Platzhalter:
# {sivasnr} SivasNr des Elements (= DXF-Dateiname)
# {layer} Ziel-Layer (aus [layer] Abschnitt)
# {profiltyp} ProfilTyp aus JSON
#
# Hinweis:
# Zeilen mit # sind Kommentare. Leerzeilen werden ignoriert.
# ============================================================
# ------------------------------------------------------------
# Layer-Zuordnung nach Elementkategorie
# set_attributs.py bestimmt die Kategorie anhand KurvenWinkel und
# WeichenTyp aus den JSON-Daten und setzt LAYER entsprechend.
# ------------------------------------------------------------
[layer]
# Boegen (alle Winkel)
bogen = "A-2"
# Weichen 90 Grad (Einzelweiche/Doppelweiche/Dreiwegeweiche, KurvenWinkel=90)
weiche_90 = "A-2"
# Weichen 45 Grad (Einzelweiche/Doppelweiche/Dreiwegeweiche, KurvenWinkel=45)
weiche_45 = "A-2"
# Weichenbatterien / Parallel (KurvenWinkel=0)
weichenbatterie = "A-2"
# Weichenkombinationen (Deltaweiche, Sternweiche, Dreifachweiche)
weichenkombination = "A-2"
# Weichenkoerper (KurvenWinkel=22.5)
weichenkoerper = "A-2"
# Kreuzungsweichen (800, 300) - Layer L für Stahlstrecke (alt)
kreuzungsweiche = "L-2"
# PNEUMATISCH GESCHALTET
# Weichen pneumatisch 90 Grad (Einzelweiche/Doppelweiche/Dreiwegeweiche, KurvenWinkel=90)
weiche_pn_90 = "A-3"
# Weichen 45 Grad (Einzelweiche/Doppelweiche/Dreiwegeweiche, KurvenWinkel=45)
weiche_pn_45 = "A-3"
# Weichenbatterien / Parallel (KurvenWinkel=0)
weichenbatterie_pn = "A-3"
# Weichenkombinationen (Deltaweiche, Sternweiche, Dreifachweiche)
weichenkombination_pn = "A-3"
# Weichenkoerper (KurvenWinkel=22.5)
weichenkoerper_pn = "A-3"
# Kreuzungsweichen (300) - Layer L für Stahlstrecke (alt)
kreuzungsweiche_pn = "L-3"
# TEF Förderer
TEF_gerade = "F-1"
TEF_bogen = "F-1"
TEF_antriebstation = "F-1"
TEF_umlenkspannstation = "F-1"
[bogen]
BESCHR = ProfilTyp
ARTINR = Sivasnr
TEILEART = "Omniflo Kurve"
ID = ""
# LAYER wird aus [layer] bestimmt (Kategorie: bogen)
# LAYER = "A-OF-Bogen"
RADIUS = Radius
WINKEL = KurvenWinkel
SIVASNR_TEF = SivasnrTEF
HOEHE = ""
DREHUNG = ""
[weiche]
BESCHR = ProfilTyp
ARTINR = Sivasnr
TEILEART = "Omniflo Weiche"
ID = ""
# LAYER wird aus [layer] bestimmt (Kategorie abhaengig von KurvenWinkel/WeichenTyp)
# LAYER = "A-OF-Weiche"
WEICHENTYP = WeichenTyp
WINKEL = KurvenWinkel
RICHTUNG = KurvenRichtung
SIVASNR_TEF = SivasnrTEF
HOEHE = ""
DREHUNG = ""
[gerade]
ARTINR = Sivasnr
TEILEART = "Omniflo Gerade"
ID = ""
LAENGE = Laenge
LAYER = "A-2"
HOEHE = ""
DREHUNG = ""
[container]
0_BG071090 = 0_B10071, 0_B10090, 0_B10090
0_BG080090 = 0_B10080, 0_B10090,
0_BG081090 = 0_B10081, 0_B10090,
0_BG090090 = 0_B10090, 0_B10090,
0_BG190090 = 0_B10090, 0_B10090
+29
View File
@@ -0,0 +1,29 @@
# ============================================================
# export.cfg - Konfiguration fuer Lisp/export.lsp UND lib/export_csv.py,
# lib/export_sivas.py (gemeinsame Blockname-Muster, siehe
# lib/export_blockpatterns.py)
#
# Format: INI-Style
# [ABSCHNITT]
# Key = Wert (einzelner Wert)
# Key = Wert1, Wert2, Wert3 (Musterliste fuer wcmatch/fnmatch, kommagetrennt)
#
# Zeilen mit # sind Kommentare. Leerzeilen werden ignoriert.
#
# pattern_kreisel/pattern_strecke sind fuer Lisp's Block-SAMMLUNG grob
# gehalten (nur "gehoert das ueberhaupt zum Export"). Die uebrigen
# pattern_eckrad/pattern_variofoerderer/pattern_gefaellestrecke/
# pattern_strecke_module-Keys sind Teilmengen davon fuer die feinere
# TeileArt-KLASSIFIKATION in Python (eigene Zeile je Teileart) -
# Aenderungen an Blocknamen bitte in beiden Stellen nachziehen.
# ============================================================
[blockpattern]
pattern_kreisel= KR_*, KREISEL_*, ECKRAD_*
pattern_eckrad= ECKRAD_*
pattern_gerade= AP110*, AP_110*
pattern_strecke= Vario*, Staustrecke*, AUS_Element*, EIN_Element*, VF_*, GF_*
pattern_variofoerderer= VF_*
pattern_gefaellestrecke= GF_*
pattern_strecke_module= Vario*, Staustrecke*, AUS_Element*, EIN_Element*
pattern_ks_subblocks= KS_EIN, KS_AUS, K1, K2, K3, K4
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More