Compare commits

..

103 Commits

Author SHA1 Message Date
m.stangl 60f2b72e39 Omniflo-Streckenzug-Test + skriptfaehige Aluprofil-Geraden
Neuer Test: 4 Geraden -> 180-Grad-Kurve (4x 45-Grad-Bogen) -> 4 Geraden
als lueckenlos verketteter Streckenzug (U-Form).

- testdata/omniflo_strecke_tests.json: 12 Elemente mit berechneter,
  verketteter Platzierung (x, y, drehung, x_ende, y_ende, Bogen-Mittelpunkt)
- test_omniflo_strecke.py: Geometrie-Validierung ohne BricsCAD (Struktur,
  Katalog-Abgleich, Verkettung, Kurvensumme 180 Grad, gemeinsamer Mittelpunkt)
- test_omniflo_strecke.lsp: C:TEST_OMNIFLO_STRECKE baut die Strecke auf
- alltests.json/README.md: Test registriert und dokumentiert

OmniModulInsert.lsp: omni:insert-block in skriptfaehigen Kern omni:make-gerade
+ omni:read-src-attribs aufgeteilt. Der Kern erzeugt eine Aluprofil-Gerade
non-interaktiv aus zwei Punkten (kein getpoint/ssg-start), sodass der Test
echte Gerade-Bloecke statt nackter Linien baut. Interaktives Verhalten von
omni:insert-block bleibt unveraendert (Vorschau-Text, Laengenpruefung).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 17:51:05 +02:00
m.stangl 258608b77f Export: Gefällestrecke-Höhe, Gerüst-Defaults, Omniflo-Komponenten-Split
- Entfernt "Hoehe oben"/"Hoehe unten" aus Gefällestrecke JSON-Export
- "Hoehe in m" kommt jetzt konsistent aus MONTAGEHOEHE_m bei Kreisel/Variofoerderer/Gefällestrecke
- Setzt "Geruest fuer Einzelmodul" auf Default True (statt False) bei Kreisel, Eckrad, Variofoerderer, Gefällestrecke
  - Eckrad-Abfrage: Default = Yes, Logik korrigiert (war invertiert)
- JSON-Key-Reihenfolge optimiert:
  - Variofoerderer/ILS 2.0 Strecke: "Hoehe in m" zuerst
  - Gefällestrecke/ILS 2.0 Gefällestrecke: "Hoehe in m" und "Typ" zuerst
  - Kreisel: "Hoehe in m" zuerst
- Omniflo-Komponenten-Split: Teile mit "0_B"-Präfix werden als separate CSV-Zeilen ausgegeben
  - Multi-Komponenten-Sivasnr (z.B. "834372002+0_BG090090") splitten
  - IDs werden mit .t1, .t2, etc. ergänzt
  - 0_B-Komponenten als "TEF Bogen"/"TEF Weiche" klassifiziert

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-23 15:26:51 +02:00
m.stangl 6b7f6e925d Lisp Tests im Readme dokumentiert 2026-07-23 14:52:52 +02:00
m.stangl be12533af1 Daten: Omniflo 3D-Block BTMT-Beladung; .gitignore repariert
Kaputte .gitignore-Zeile (verungluecktes echo >> .gitignore) auf den
gemeinten Eintrag data/block_libraries/ils_library.dxf zurueckgesetzt und
Tool-Cache .skylos/ ergaenzt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:50:48 +02:00
m.stangl 5f4a0c7af2 Tests: BricsCAD-Skriptstart /s -> /b (Batch-Modus) korrigiert
/s ist der Support-Ordner-Schalter, nicht der Skript-Schalter - BricsCAD
ignorierte die .scr und startete mit voller GUI. /b fuehrt das Skript
tatsaechlich aus (test_unit.scr endet mit _.QUIT, BricsCAD schliesst sich
selbst). run_tests.bat zusaetzlich mit /nologo; create_tests.bat mit
Anfuehrungszeichen um %BRICSCAD% (Pfad enthaelt Leerzeichen).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:50:38 +02:00
m.stangl 3f7074f06b Lisp-Unit-Tests fuer reine Standardfunktionen + run_tests.bat --lisp
- tests/test_unit.lsp: Mini-Test-Framework (tu-eq/tu-eqf/tu-true/tu-nil)
  und Testfaelle fuer reine Funktionen aus ssg_core, ssg_lang, ssg_id,
  vf_core, export, Gefaellestrecke, OmniModulInsert, KreiselInsert.
  Befehl TEST_UNIT schreibt tests/output/unit_results.txt.
- tests/test_unit.scr: Headless-Startskript (laedt SSG_LIB, ruft
  TEST_UNIT, beendet BricsCAD), pfadunabhaengig ueber DXFMAKRO.
- bin/run_tests.bat: Schalter --lisp startet BricsCAD headless, wertet
  den Report aus (RESULT: OK/FAIL) und setzt den Exit-Code.
- tests/README.md: Abschnitt zu den LISP-Unit-Tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:44:35 +02:00
m.stangl 52264f1531 Export: Insertpoint (24-Zeichen KOS) und K1-K4 (12-Zeichen Position) je Block
csv:block-to-json ergaenzt fuer jeden Block einen Insertpoint-String
(Position+Rotation als Z-Quaternion, csv:kos-encode) sowie K1-K4 als
reine Positions-Strings (csv:trans-encode, 0.1 mm). KS_EIN/KS_AUS werden
auf K1/K2 gemappt, falls keine echten K1/K2 vorhanden sind. Neue CSV-
Spalten Insertpoint;K1;K2;K3;K4 in export_csv.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:38:08 +02:00
m.stangl f51b421e23 Export der BB enthält mindesthöhe 2026-07-23 14:06:06 +02:00
m.stangl 5ffe81b370 Sivas-Export: Geruestoption fuer Einzelmodul in allen ILS-Elementen ergaenzt
Kreisel, Eckrad, Gefaellestrecke und VarioFoerderer schreiben jetzt neben
"Geruest fuer Einzelmodul" auch die gewaehlte Geruestoption (GERUEST_TYP)
in die Merkmale. Eckrad bekommt dafuer erstmals eine eigene Gruppierung
nach Geruest-Signatur (bisher immer eine gemeinsame Zeile ohne Details);
Kreisel/Gefaellestrecke gruppieren nun ebenfalls nach Geruestoption, damit
unterschiedliche Optionen nicht mehr in einer Zeile verschwinden.
2026-07-23 13:05:01 +02:00
m.stangl 1c5f29a250 test_foerderer.py: Spaltenindizes an neue Fehler-/IDs-Spalten angepasst
CSV-Header hat inzwischen eine "Fehler"-Spalte (export_csv.py, zwischen
Nachbarn und Merkmale) und der Sivas-Export eine "IDs"-Spalte (export_sivas.py,
vor details) bekommen - der Test war darauf noch nicht nachgezogen und
erwartete die alten Spaltenpositionen/Header, wodurch Header- und
Merkmale/details-JSON-Pruefungen fehlschlugen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 12:55:50 +02:00
m.stangl 9516fd63af set_koords.py: manuelle Abstandsformeln durch math.dist ersetzt
Die wiederholten (dx**2 + dy**2 [+ dz**2]) ** 0.5-Formeln fuer den
euklidischen Abstand zweier Punkte (K1-K4-Positionsbestimmung fuer
Boegen/Weichen/Weichenkoerper) sind jetzt math.dist(p1, p2) - gleiches
Ergebnis, aber weniger Code und keine Gefahr, beim manuellen Quadrieren
ein Vorzeichen/Exponenten zu vertippen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 12:55:50 +02:00
m.stangl b6b71c5997 safe_float/safe_int Hilfsfunktionen: doppelten try/except-Code konsolidiert
export_csv.py und export_sivas.py enthielten je ca. 10 nahezu identische
try/except (ValueError, TypeError)-Bloecke fuer "String zu float/int mit
Fallback". Neue gemeinsame Helfer safe_float()/safe_int()
(export_blockpatterns.py) ersetzen diese Bloecke; dabei auch zwei bislang
ungeschuetzte int()/float()-Aufrufe in export_sivas.py (Kreisel-Zaehler)
abgesichert, die bei fehlerhaften Attributwerten sonst abgestuerzt waeren.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 12:55:50 +02:00
m.stangl 2842e1f1c9 CSV-Escaping-Bug behoben, export.cfg-Mehrfachparsing beseitigt
format_csv_line() in export_csv.py/export_sivas.py hat Feldwerte per
f-String direkt in doppelte Anfuehrungszeichen gesetzt, ohne ein
eingebettetes '"' zu escapen (z.B. eine Bezeichnung mit Anfuehrungszeichen
haette die Spaltengrenze der Zeile kaputt gemacht). Neuer gemeinsamer
Helper csv_quote() (export_blockpatterns.py) verdoppelt eingebettete
Anfuehrungszeichen nach RFC 4180.

Ausserdem: export.cfg wurde bisher von vier unabhaengigen load_*-Funktionen
(load_patterns, load_neighbor_tolerance_mm, load_omniflo_cell_size_mm,
load_planquadrat_config) separat von der Platte gelesen und geparst. Neuer
gemeinsamer, gecachter load_export_cfg() in export_blockpatterns.py sorgt
dafuer, dass export.cfg pro Exportlauf nur noch einmal gelesen wird.

Dabei auch die in export_csv.py bereits genutzte, aber in export_planquadrat.py
fehlende resolve_origins()-Funktion (automatische Planquadrat-Ursprungs-
Ermittlung) ergaenzt - ohne sie war der Import von export_csv.py gebrochen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 12:55:50 +02:00
s.hensch 2ccfe005d9 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-23 11:03:39 +02:00
s.hensch 79b7e9af4f [ADD] 2D Elemente für Vario Motor und Umlenkstation hinzugefügt 2026-07-23 11:03:29 +02:00
m.stangl 6396111777 Geruest fuer Einzelmodul + Geruestoption bei Foerderer, Gefaellestrecke und Eckrad ergaenzt
Kreisel hatte GERUEST_EINZELMODUL bereits; ergaenzt um die neue Combobox
GERUEST_TYP (IPE-Geruest abgestuft / Obergeruest oben / Schoenenberger
Geruest / nur Doppelrohrtraeger, Default Schoenenberger Geruest) im
KreiselEdit-Dialog. VarioFoerderer (Standard-Dialog) und Gefaellestrecke
(Modus 1) erhalten beide Attribute neu in ihren DCL-Dialogen inkl.
Edit-Vorbelegung. ILS_Eckrad (kein Dialog vorhanden) fragt beide Werte
per Kommandozeilen-Menue ab. Konsolen-only-Pfade ohne Dialog (VF
Etage/Linienzug, GF Linienzug/3D-Objekte) bleiben auf Schema-Default,
analog zum bisherigen Kreisel-Verhalten.

Gemeinsame Optionsliste/Helper (*ssg-geruest-optionen*,
ssg-geruest-typ-to-idx/idx-to-typ, ssg-ask-geruest-typ) in ssg_core.lsp
war bereits durch einen parallelen Commit (120e26a) mit eingeflossen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 10:37:22 +02:00
m.stangl ad287b683d CSV-Export: Nachbarschaftserkennung neu aufgebaut (ohne shapely), Fehlerspalte ergaenzt
Nachbarschaft wird jetzt in drei getrennten Gruppen geprueft statt global
ueber alle Elemente: Kreisel/Eckrad gegeneinander, Kreisel/Eckrad gegen
Gefaellestrecke/Foerderer/Strecke-Modul (diese drei nicht gegeneinander),
und Omniflo-Elemente gegeneinander (rasterbasiert vorgefiltert nach x/y-
Koordinate). Ersetzt die bisherige shapely-STRtree-Loesung durch reines
Python, da die shapely-Abhaengigkeit den regulaeren CSV-Export in der von
BricsCAD genutzten Python-Umgebung brechen konnte.

Neue Spalte "Fehler" markiert Elemente mit zu wenigen Partnern
("unverbunden"/"nur ein Partner") je nach TeileArt-Mindestanzahl.

Ausserdem: SSG_RUN_ALL_TESTS-Absturz nach TEST_KREISEL behoben (ssg-start/
ssg-end nutzten flache globale Variablen statt eines Stacks, wodurch
verschachtelte Aufrufe den *error*-Handler dauerhaft korrumpierten) und
FILEDIA=0 um den DXFOUT-Kommandozeilenaufruf ergaenzt.
2026-07-23 10:35:42 +02:00
y.wang 6d81b30628 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-23 09:08:19 +02:00
y.wang eef20cafe8 AS-Platzierungen gefixiert. AS-dz jetzt konsistent flach, Debug-Zeile entfernt 2026-07-23 09:08:07 +02:00
y.wang fe2ad9cb32 vf-next-number ueberspringt bestehende Block-Definitionen (verhindert sporadischen VF-Bau-Fehlschlag)
Parallel-VF selbstkorrigierend auf GF-AS-KS_EIN ausrichten + vf-next-number gegen Namenskollision haertenm, Debug-Ausgaben entfernt.
2026-07-23 09:07:27 +02:00
m.stangl 6ab698286f CSV-Export: Nachbarschaftserkennung ueber Bounding-Box-Ueberschneidung (STRtree/shapely)
Neue Spalte "Nachbarn" (kommaseparierte TeileId-Liste) in export_csv.py:
zwei Elemente gelten als benachbart, wenn ihre Bounding-Boxes (x/y-Ebene)
sich ueberschneiden. Toleranz konfigurierbar in mm ueber cfg/export.cfg
[Nachbarschaft] -> toleranz_mm, siehe lib/export_neighbors.py.
Nur EXPORTCSV betroffen, EXPORTSIVAS bleibt unveraendert.

shapely als neue Abhaengigkeit in requirements.txt ergaenzt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 15:26:30 +02:00
m.stangl 57badf0556 Sivas-Export: Spalte Hoehe[m] entfernt
Die Hoehe-Angabe steht bereits pro Element in der details-JSON-Spalte
(z.B. "Hoehe in m" aus dem MONTAGEHOEHE_m-Attribut bei VarioFoerderer/
Linienzug), die separate Top-Level-Spalte war redundant.
2026-07-22 13:01:24 +02:00
m.stangl 193b0dea04 CSV-Export: Bounding-Box (Position/Boundingbox) und Planquadrat-Spalte ergaenzt
Nur EXPORTCSV betroffen, EXPORTSIVAS bleibt unveraendert:
- Position/Boundingbox: Bounding-Box je Block per vla-getboundingbox
  (Lisp/export.lsp, csv:get-bbox), Mittelpunkt und Ausdehnung x/y/z.
- Planquadrat: aus x/y-Koordinate berechnet nach cfg/export.cfg
  [Planquadrate] (Schrittweite, numerisch/alphabetisch je Achse,
  alphabetische Zaehlung mit Excel-Spalten-Umlauf Z->AA), siehe
  lib/export_planquadrat.py.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 12:52:33 +02:00
s.hensch a0fd5d83bd Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-22 12:48:12 +02:00
s.hensch 6ab835c425 [FIX] Dropdown Menü für Weichenauswahl Omniflo verbreitert, um den gesamten Text sichtbar zu machen; [FIX] Grad Zeichen in Beschreibungen der Dropdowns bzw in den entsprechenden JSON Dateien entfernt 2026-07-22 12:48:07 +02:00
y.wang 8daf6548c8 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-22 12:44:29 +02:00
y.wang c6d5a4e8eb Doppelklick-GF-Edit repariert 2026-07-22 12:43:29 +02:00
y.wang c0f06b68cd Fehler für Etage-VF korrigiert. 2026-07-22 12:42:18 +02:00
m.stangl 4159132ce1 Bezeichner war im json Export noch drin, obwohl es eigene Spalte ist 2026-07-22 12:09:42 +02:00
m.stangl efdf6224ff Noch einen Eintrag vergessen gehabt 2026-07-22 11:46:59 +02:00
m.stangl bb92b8ef69 Artinr. mit Punkt ist keine gute Idee für eine Attributbezeichnung. Geändert 2026-07-22 11:44:33 +02:00
m.stangl 048bf61ac4 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros
# Conflicts:
#	Lisp/KreiselInsert.lsp
#	lib/export_sivas.py
2026-07-22 11:28:30 +02:00
m.stangl 3f916a6fed Kreisel: Attribut Geruest_Einzelmodul hinzugefuegt (Erzeugung, Edit-Dialog, Export)
Jeder Kreisel bekommt bei der Erzeugung das neue Attribut GERUEST_EINZELMODUL
(Default false), im KreiselEdit-Dialog per Checkbox "Geruest fuer Einzelmodul"
umschaltbar. Fliesst als echter JSON-Bool ins details-Feld von EXPORTSIVAS/
EXPORTCSV und wird bei der Sivas-Gruppierung gleichartiger Kreisel beruecksichtigt.
2026-07-22 11:25:09 +02:00
s.hensch 187f0acf31 [FIX] nach dem Editieren bzw. Austauschen eines Objekts über Doppelklick und Menü wird das Layer nun korrekt entsprechend des Layer-Attributs gesetzt 2026-07-22 08:54:04 +02:00
s.hensch 63e4e9ef32 [FIX] Weichentyp im json für die dynamische Erzeugung der Oberfläche für Deltaweichen korrigiert; [CHANGE] Drehung der Omniflo Objekte wird nun interaktiv durch den Benutzer angegeben wie zuvor in Bihler 2026-07-22 08:07:24 +02:00
s.hensch 67acbd8f38 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-21 15:46:12 +02:00
s.hensch a7037d975c [FIX] Omniflo Blöcke nicht mehr benötigte Boundingbox Rudimente vom Ruledesigner entfernt; [CHANGE] Omniflo Blöcke in Blockdatei in den Ursprung positioniert, damit bessere Kontrolle möglich; [DELETE] Block libraries aus dem Repo entfernt, da nicht mehr benötigt 2026-07-21 15:45:44 +02:00
s.ayadi 042d3b72e8 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-21 14:51:00 +02:00
s.ayadi e63694a4af fix for changing 2026-07-21 14:42:51 +02:00
s.hensch 36cd89cc84 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-21 14:32:44 +02:00
s.hensch 25c8a21fdb [CHANGE] Attribute in den Omniflo Blöcken bereinigt und Vereinheitlicht; [ADD] Scanner, Stopper, Bremse für Omniflo 2D als Block hinzugefügt 2026-07-21 14:32:32 +02:00
y.wang 9a92bede21 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-21 14:11:56 +02:00
y.wang b962872071 HOEHEN_CHECK - misst/schreibt Hoehen-Attribute (Kreisel/VF/GF), markiert ungueltige Hoehen auf Layer S_HOEHE_PRUEFEN, Buehnenabzug ab 2m 2026-07-21 14:11:29 +02:00
y.wang b5ae0a1da0 i18n: Keys gf-vf-modul-fehlt/gf-vf-gebaut fuer 'VF daneben bauen' nachgereicht (de/en) 2026-07-21 14:05:59 +02:00
y.wang 5bb6bb8241 fix: Z-Versatz bei GF/VF behoben (OSMODE=0 im Wrap ssg-block-wrap-welt); gepickte Hoehe als Einfuegehoehe im GF-Dialog 2026-07-21 14:05:13 +02:00
m.stangl 12fc783eb7 Strings Beladung und Entladung geändet 2026-07-21 14:04:43 +02:00
y.wang d99bdb10d5 Kreisel-Attributreihenfolge neu (ID/Bezeichnung/Artinr. zuerst), Artinr.=6200 ergaenzt, N_RAMPEN->ANZAHL_RAMPEN (inkl. Export-Fallback) 2026-07-21 13:55:51 +02:00
y.wang 59835c1d2f fix: OSMODE=0 in Omniflo-Inserts (Aluprofil/DXF) gegen Hoehen-Umfang-Bug 2026-07-21 13:51:16 +02:00
m.stangl dfc17a8f39 Linienzug hat jetzt eine Frage mehr wegen 90 oder 30 Grad. 2026-07-21 12:56:34 +02:00
s.hensch 82470ae708 [ADD] CUI wird nun verwaltet, da sowieso aktuelle version notwendig und einfacher zu integrieren 2026-07-21 12:05:43 +02:00
s.hensch fe8e78d56c Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-21 09:11:21 +02:00
s.hensch a0e86571b1 [ADD] Menüeintrag für Omniflo Anbaugruppen Scanner, Stopper, Bremse hinzugefügt und Einfügen implementiert 2026-07-21 09:11:08 +02:00
y.wang 1ca3241a83 Button -VF daneben bauen- im GF-Edit-Dialog - baut gegenläufigen, steigenden Standard-VF 2000mm parallel,Doppel-Bestaetigung in Modus 1 (DCL-Dialog) entfernt - OK-Klick fuegt direkt ein 2026-07-20 21:40:41 +02:00
y.wang 41311f5fd3 ZAEHLE_SEP_SCAN schreibt ILS-Bezeichnung in Sensor-Attribut zuordnung und markiert nicht zugeordnete Sensoren mit Gelb Kreis 2026-07-20 18:14:06 +02:00
y.wang 21daab974d Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-20 16:50:14 +02:00
y.wang 8efdbc0c5f keys de/en für VF-linienzug wurde eingefügt, Export Sivas ruft vorab ZAEHLE_SEP_SCAN auf(Attribute aktualisieren), Menü neu laden notwendig 2026-07-20 16:49:59 +02:00
m.stangl 903e086e7f Bezeichnung statt Name bei ILS KReisel und Eckrad verwendet. Eigene Spalte für Bezeichnung im Sivas Export dazu gebaut 2026-07-20 16:46:16 +02:00
m.stangl d4ea049918 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-20 15:39:22 +02:00
m.stangl 5c28db9e91 Oberfläche für Standard von Varioförder und Gefällestrecke bauen lassen 2026-07-20 15:39:17 +02:00
m.stangl 27ab8b4875 altes Symbol rausgeworfen 2026-07-20 15:12:52 +02:00
y.wang 297bb8b905 Menueeintraege Scanner/Separator einfuegen + Zaehlbefehl im Zusatzmodul; Einfuege-Befehle ILS_SCANNER_INSERT/ILS_SEPARATOR_INSTERT 2026-07-20 14:43:59 +02:00
y.wang 4971af8617 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-20 14:15:49 +02:00
y.wang 2acbd1e989 die KS_AUS von 30° AS_Element wurde korrigiert. 2026-07-20 14:15:42 +02:00
s.hensch 15f57e7c32 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-20 14:14:41 +02:00
s.hensch 4bec8d92bd [ADD] Funktionen und Menü zum Hinzufügen von Omniflo TEF Bauteilen integriert 2026-07-20 14:14:35 +02:00
y.wang 6e8f4c75fe Merge origin/master: i18n-System (de/en) + 30-Grad-AS/ES-Elemente zusammenfuehren
Lokaler Stand (Modus-3 Randwert-Solver, 30/90-AS/ES, Kreisel-Attribute)
mit dem Remote-Stand (Internationalisierung ssg-text, neue Bloecke,
Sivas-Export) vereint.

Konfliktaufloesung:
- vf_linienzug.lsp: Nicht-interaktive -block-Kerne (fuer Pfad-Modi) behalten,
  interaktive Abfragen (GF-Bogen, Vario-Kurve, ES-Seite) auf ssg-text
  umgestellt. Kein doppelter defun mehr.
- Gefaellestrecke.lsp: 30/90-Winkelabfrage mit den i18n-Seiten-Prompts
  kombiniert; gefaellestrecke-einfuegen-Aufruf mit as-/es-winkel.
- vf_core.lsp: vf-frage-element-winkel nimmt jetzt einen i18n-Header-Key
  (vf-winkel-aus-header / vf-winkel-ein-header) statt festem Text.
- lang/de_DE.json + en_GB.json: neue Keys vf-winkel-aus/ein-header,
  vf-winkel-90/30; gf-seite-Header ohne irrefuehrendes "_90_".
- export_sivas.py: ANZAHL_SEPARATOR/ANZAHL_SCANNER mit N_*-Fallback plus
  Remote-Umsortierung; doppelte "Kreiselart"-Zeile entfernt.
- AS_Element_30_links/rechts.dwg + Separator_SP.dwg (3D): Remote-Version
  (Attribut-Stand) uebernommen. Die KS_AUS-Geometrie-Korrektur der 30-Grad-
  AS-Elemente wird danach in BricsCAD nachgezogen.

Offen (Folge-Commit): die Modus-Treiber in vf_linienzug.lsp
(vf-linienzug-modus / -modus2 / -modus3) sind noch nicht i18n
(ca. 110 Strings).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 14:08:13 +02:00
y.wang bc09b23c23 Überprfüng Funktion für Anzahl der Separatoren und Scanner wurde gebaut 2026-07-20 13:06:50 +02:00
y.wang 57a9f09898 Attribut-Tags umbenannt: N_SEPARATOREN → ANZAHL_SEPARATOR, N_SCANNER → ANZAHL_SCANNER 2026-07-20 13:04:47 +02:00
y.wang f38b06ddf5 VF-Linienzug Modus 2 (Ziel-Hoehe) fertig , AS/ES 30/90 Grad bei GF und VF waehlbar. 2026-07-20 12:59:09 +02:00
y.wang c20c35411a Die KS-AUS von 30° AS_ELemente wurde korrigiert. 2026-07-20 12:49:32 +02:00
m.stangl a56ddb5e6c Attribute des Kreisels werden beim Sivas Export in anderer Reihenfolge rausgeschrieben 2026-07-20 09:49:20 +02:00
m.stangl 7941a792e0 Reihenfolge des Sivas CSV Exports geändert 2026-07-20 09:45:11 +02:00
s.hensch adfde744e2 [FIX] Beim Einfügen eines Blocks wird die Farbe des Layers nur noch neu gesetzt, wenn der Layer noch nicht existiert 2026-07-20 08:43:08 +02:00
s.hensch 2d6fd86d37 [ADD] LISP Skript zum Erstellen einer JSON-Datei mit allen DWG-Blöcken und deren Attributen eines Verzeichnisses und Skript zum Schreiben von Attributen aus einer JSON auf die Blöcke in einem Verzeichnis entsprechend des Dateinamens 2026-07-20 07:47:18 +02:00
m.stangl e2aee8c413 neue Omniflo Referenz 2026-07-18 20:17:36 +02:00
m.stangl 6d5cecd6a1 test_foerderer: TeileArt-Erwartung an aktuelles export_csv.py angleichen
test_vario_teileart erwartete noch "VarioFoerderer", obwohl export_csv.py
seit Commit bf51747 (14 Commits zuvor) bewusst "ILS 2.0 Strecke" liefert -
ein VarioFoerderer ist ein Streckentyp. Test war seither stale, unabhaengig
von den foerderer_tests.json-Aenderungen dieser Session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 22:27:32 +02:00
m.stangl f6635ef217 Neue Referenzdaten für den Förderer eingepflegt, da jetzt auch verschiedene Varianten im Test laufen können. 2026-07-17 18:44:13 +02:00
m.stangl 1c43a5301b TEST_FOERDERER: Seite, Winkel und GF-Verteilung ueber foerderer_tests.json steuerbar
Bisher waren Seite (links/rechts), ein erzwungener Rampenwinkel und die
Aufteilung der Gefaelle-Laenge auf Ein-/Auslauf im Testtreiber hart codiert
(immer "links", automatischer Winkel, 50/50-Split). Alle drei Werte sind
bereits als Parameter/Rueckgabewerte in vf_standard.lsp/vf_core.lsp
vorhanden - keine Aenderung an produktivem LISP-Code noetig, nur am
Testtreiber und der Testdatei.

Neue optionale JSON-Felder: seite, winkel, gf_verteilung (gleichmaessig/
vorne/hinten). Bestehende 12 Testfaelle bleiben unveraendert und
verhalten sich dank Default-Fallbacks identisch zu vorher.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 17:33:18 +02:00
m.stangl db75a25ae1 Sivas-Export: Gefaellestrecke und VarioFoerderer mit Detail-Zeilen statt Sammelzeile
Gefaellestrecke (GF_N): je Zeile eine Gruppe gleichartiger Bloecke (gleiche
Hoehe/Laenge/Winkel/Separatoren/Scanner/Typ), IDs und Bezeichnung als Array
statt einer einzigen Sammelzeile mit reiner Anzahl.

VarioFoerderer (VF_N): je Compound-Block eine eigene Zeile mit vollstaendigen
Gefaelle-/Angetrieben-Teilgruppen (Laengen, Winkel, Kurven, Foerderrichtung),
da VF_N immer TYP "Streckengruppe" ist. Lose Strecke-Elemente ausserhalb
eines VF_N-Blocks bleiben weiterhin in einer gruppierten IDs-Zeile.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 14:09:26 +02:00
s.hensch 18a2172d4f [FIX] Attribute der DWG Blöcke mit UTF-8 formatiert und Umlaute und Sonderzeichen (°) entfernt bzw ersetzt, zB ä->ae 2026-07-17 12:41:34 +02:00
s.hensch 659aa8e8c1 [FIX] JSON Parser in Lisp konnte keine leeren JSON Attribut-Objekte behandeln (Kurve:{}) und hat einen Fehler geworfen. Dieses Verhalten wurde nun korrigiert 2026-07-17 12:39:22 +02:00
s.hensch d3ad4f8c5e [ADD] Modulweichen-Blöcke hinzugefügt für die spätere dynamische Erzeugung anhand der Weichensituationen - Diese Blöcke sind keine Dummy-Weichenelemente für die TOS Kalkulation 2026-07-17 10:42:21 +02:00
m.stangl bd1366bc8a Uebersetzung der Benutzermeldungen in vf_core.lsp und Gefaellestrecke.lsp auf ssg-text/ssg-textf umgestellt
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 09:39:18 +02:00
m.stangl 9199ea705f Werkzeug zur Extraktion der Begriffe aus den Lisp Files mit eingecheckt 2026-07-15 23:48:33 +02:00
m.stangl cfdcd31b30 Sprachen als .json Datei in lang Ordner gelegt 2026-07-15 23:47:20 +02:00
m.stangl 78f19c750c Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-15 21:25:49 +02:00
m.stangl 2eca169326 Uebersetzung aller Benutzermeldungen auf ssg-text/ssg-textf umgestellt
Vollstaendiger i18n-Rollout ueber alle Feature- und Kernmodule: alle benutzersichtbaren princ/prompt/getXXX/alert-Texte laufen jetzt ueber die zentrale Sprachtabelle in ssg_lang.lsp (Deutsch/Englisch, umschaltbar via SSG_SPRACHE). 403 Tabelleneintraege, 497 Aufrufstellen in 17 Dateien.

Ausgeschlossen wie geplant: Debug-Ausgaben (dbg*), Lademeldungen, [DUMMY]-Platzhalter, [CFG]/[OMNI]-Diagnosemarker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 21:24:18 +02:00
s.hensch 1ddd9449c6 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-07-15 16:02:04 +02:00
s.hensch 3ab7d29476 [FIX] Korrektur und Ergänzung der Attribute und deren Werte in den Blockdateien für ILS und Omniflo 2026-07-15 16:01:49 +02:00
m.stangl 15ba546a17 Übersetzungsdatei dazu 2026-07-15 15:18:08 +02:00
m.stangl 9458382965 Sprachumschaltung von DE nach EN über Menü möglich gemacht 2026-07-15 15:11:02 +02:00
m.stangl 0fe14c5454 Was bei Übersetzung zu tun wäre 2026-07-14 16:36:25 +02:00
m.stangl bf517475bb ILS Elementtypen für den Export hinzugefügt. 2026-07-14 16:25:21 +02:00
m.stangl ae9ce69d5f Doku der ausgegrauten Menüs 2026-07-14 14:45:24 +02:00
m.stangl 2ae64cb4a8 Menüs ausgegraut die nur Dummyroutinen aufrufen 2026-07-14 14:44:24 +02:00
y.wang 8e5db27730 3D-Blöcke für Motorstation und Umlenkstation links/rechts wurden eingepflegt. 2026-07-14 14:03:20 +02:00
y.wang 73603ea55b Linienzug-Testeingaben nach linienzug_tests.json auslagern + in alltests.json und run-all integrieren 2026-07-14 14:00:53 +02:00
m.stangl a9c03b0b9a BT MT Beladung als .dwg eingecheckt 2026-07-13 11:56:33 +02:00
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
361 changed files with 761698 additions and 592665 deletions
+6 -3
View File
@@ -183,6 +183,9 @@ cython_debug/
/tests/output/
# BricsCAD kompilierte Menuedateien
*.cui
data/block_libraries/ils_library.dxf >> .gitignore
echo data/block_libraries/ils_library.dxf
#CUI soll nun auch verwaltet werden
#*.cui
data/block_libraries/ils_library.dxf
# Tool-Caches
.skylos/
+13 -7
View File
@@ -67,11 +67,12 @@ Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD.
|---|---|---|
| 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 |
| VarioFoerderer | `VarioFoerderer` | FOERDERANLAGE, VARIOFOERDERER_EDIT |
| Gefaellestrecke | `Gefaellestrecke` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT |
| 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 |
| Konfiguration | `SSG_LIB_Commands` | SSG_DIM_SWITCH, SSG_SPRACHE |
| Doppelklick/Kontextmenue | `SSG_LIB_Commands` | SSG_BLOCKEDIT (dispatcht Kreisel->KreiselEdit, Omniflo->OMNI_EDIT, GF_*->GEFAELLESTRECKE_EDIT, VF_*->VARIOFOERDERER_EDIT) |
### Entfernte Legacy-Dateien
@@ -86,15 +87,16 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
| Datei | Befehle | Beschreibung |
|---|---|---|
| `ssg_core.lsp` | - | Kernel: ssg-start/ssg-end, ssg-cfg-or, ssg-attrib-read/write, Layer/Block-Ops |
| `ssg_lang.lsp` | - | Sprachumschaltung Deutsch/Englisch (ssg-text, ssg-textf, *ssg-lang*) |
| `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) |
| `VarioFoerderer.lsp` (Wrapper fuer `vf_core.lsp`/`vf_standard.lsp`/`vf_etage.lsp`/`vf_linienzug.lsp`) | FOERDERANLAGE, VARIOFOERDERER_EDIT | Vario-Foerderanlagen Generator (Typen Standard/Etage/Linienzug); Standardfall + Werteingabe per DCL-Dialog (`vfs-standard-dialog-ablauf` in vf_standard.lsp); Doppelklick auf VF_n-Block ruft VARIOFOERDERER_EDIT (nur fuer per Dialog erstellte Standard-Bloecke, erkannt an XDATA) |
| `Gefaellestrecke.lsp` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT | Gefaelle-Foerderanlage (AUS -> Staustrecke skaliert -> Separator -> EIN); Modus 1 per DCL-Dialog (Einfuegehoehe, Element-Winkel 30/90); Doppelklick auf GF_n-Block ruft GEFAELLESTRECKE_EDIT (Dialog vorbelegt, Neuaufbau) |
| `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 |
| `SSG_LIB_Commands.lsp` | ILS_BTMT_*, ILS_ETF_*, ILS_K*_*, ILS_GK*_*, SSG_BLOCKEDIT, SSG_DIM_SWITCH, SSG_SPRACHE | Dummy-Befehle fuer Menue + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) |
| `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) |
## DCL-Dialoge
@@ -102,15 +104,18 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
| Datei | Verwendet von |
|---|---|
| `kreisel_edit.dcl` | KreiselEdit (KreiselInsert.lsp) |
| `gefaellestrecke.dcl` | GEFAELLESTRECKE Modus 1 (Gefaellestrecke.lsp, `gf-dialog-eingabe`) |
| `variofoerderer.dcl` | FOERDERANLAGE Standardfall + Werteingabe (vf_standard.lsp, `vfs-dialog-eingabe-basis`/`vfs-dialog-winkel-verteilung`) |
| `omniflo_boegen.dcl` | OMNI_APB_* (OmniModulInsert.lsp) |
| `omniflo_weichen.dcl` | OMNI_W*_* (OmniModulInsert.lsp) |
| `sprache.dcl` | SSG_SPRACHE (SSG_LIB_Commands.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)
- `***POP1` - Hauptmenue (ILS, Omniflo, Export, Konfiguration)
- `***DOUBLECLICK` - Doppelklick auf INSERT-Bloecke ruft SSG_BLOCKEDIT auf
- `***POP501` - Rechtsklick-Kontextmenue (KreiselEdit, OMNI_EDIT, SSG_BLOCKEDIT)
@@ -124,6 +129,7 @@ Werden via `bin/setenv.bat` gesetzt. Wichtigste:
- `DXFM_LOG` - Log-Verzeichnis
- `DXFM_DCL` - Pfad zu DCL-Dialogdateien
- `DXFM_CFG` - Konfigurationsverzeichnis
- `DXFM_LANG` - Aktive Sprache (`de_DE`/`en_GB`), persistiert von `SSG_SPRACHE`; Default `de_DE`
## Konventionen
+1 -1
View File
@@ -18,5 +18,5 @@
)
(if *vf-core-datei*
(load *vf-core-datei*)
(princ "\n[EtageVarioFoerderer] WARNUNG: vf_core.lsp nicht gefunden - Befehle nicht verfuegbar.")
(princ (ssg-text "vfstart-etage-core-nicht-gefunden"))
)
+745 -277
View File
File diff suppressed because it is too large Load Diff
+154 -126
View File
@@ -31,7 +31,7 @@
(strcat (substr *ssg-lisp-pfad* 1 (vl-string-search "/Lisp" *ssg-lisp-pfad*))
"/data/ils/" *ki-dxfm-dim* "/"))
(t
(princ "\n[KreiselInsert] WARNUNG: Block-Pfad nicht ermittelbar!")
(princ (ssg-text "kreisel-warn-blockpfad"))
nil)
)
)
@@ -58,7 +58,7 @@
(defun ssg-cfg-or (sektion schluessel standard) standard)
(defun ssg-cfg (sektion schluessel) nil)
(defun ssg-load-config () nil)
(princ "\n[KreiselInsert] WARNUNG: ssg_core.lsp nicht gefunden - Standardwerte.")
(princ (ssg-text "kreisel-warn-core-fehlt"))
)
)
)
@@ -71,18 +71,26 @@
(setq *kreisel-default-hoehe* (ssg-cfg-or "kreisel" "default_hoehe" 2000.0))
;; Attribut-Definitionen: ((TAG DEFAULT) ...)
;; Anzeige-/Attributreihenfolge im Block (ID zuerst, dann Bezeichnung,
;; ARTINR fest 6200, Montage-/Hoehendaten, dann Ausstattung).
;; NUMMER steht am Ende (wird intern fuer Nummerierung/Blockname
;; benoetigt; Entfernen erfordert Refactor der Nummernvergabe).
(setq *kreisel-attrib-defs*
'(("NAME" "")
("DREHRICHTUNG" "UZS")
("N_SEPARATOREN" "2")
("KREISELART" "STANDARD")
("N_SCANNER" "0")
("N_RAMPEN" "0")
("DREHUNG" "0")
("ABSTAND" "2300")
("NUMMER" "0")
'(("ID" "")
("Bezeichnung" "")
("ARTINR" "6200")
("MONTAGEHOEHE_m" "0.000")
("HOEHE" "0")
("ID" ""))
("KREISELART" "STANDARD")
("ABSTAND" "2300")
("ANZAHL_SEPARATOR" "2")
("ANZAHL_SCANNER" "0")
("ANZAHL_RAMPEN" "0")
("GERUEST_EINZELMODUL" "1")
("GERUEST_TYP" "Schoenenberger Geruest")
("DREHRICHTUNG" "UZS")
("DREHUNG" "0")
("NUMMER" "0"))
)
;; Eckrad-Einstellungen
@@ -90,11 +98,13 @@
;; Eckrad Attribut-Definitionen: ((TAG DEFAULT) ...)
(setq *eckrad-attrib-defs*
'(("NAME" "")
'(("Bezeichnung" "")
("DREHRICHTUNG" "UZS")
("DREHUNG" "0")
("NUMMER" "0")
("HOEHE" "0")
("GERUEST_EINZELMODUL" "1")
("GERUEST_TYP" "Schoenenberger Geruest")
("ID" ""))
)
@@ -122,7 +132,7 @@
(progn
;; Neuen Textstil mit Arial erstellen
(command "_.STYLE" style-name "Arial" 0 1 0 "N" "N" "N")
(princ (strcat "\n-> Textstil '" style-name "' mit Arial erstellt"))
(princ (ssg-textf "kreisel-textstil-erstellt" (list style-name)))
)
)
@@ -222,7 +232,7 @@
(cons 11 insertPoint) ;; Ausrichtungspunkt
))
(princ (strcat "\n-> Beschriftung: " textStr " (Höhe=" (rtos textHoehe 2 0) "mm, Arial, zentriert)"))
(princ (ssg-textf "kreisel-beschriftung-erzeugt" (list textStr (rtos textHoehe 2 0))))
textStr
)
@@ -230,9 +240,9 @@
;; Kreiselart abfragen. Rueckgabe: "PIN" oder "STANDARD"
(defun kreisel-ask-typ ( / typNum typ)
(princ "\n[1] STANDARD (ohne PIN)")
(princ "\n[2] PIN")
(princ (strcat "\nBitte waehlen <" (if (= #Kreisel_Typ "PIN") "2" "1") ">: "))
(princ (ssg-text "kreisel-typ-opt-standard"))
(princ (ssg-text "kreisel-typ-opt-pin"))
(princ (ssg-textf "kreisel-typ-prompt" (list (if (= #Kreisel_Typ "PIN") "2" "1"))))
(setq typNum (getstring ""))
(cond
((= typNum "2") (setq typ "PIN"))
@@ -325,9 +335,9 @@
)
)
;; NAME automatisch setzen: "KreiselN"
(setq attribs (subst (cons "NAME" (strcat "Kreisel" (itoa kreisel-nummer)))
(assoc "NAME" attribs) attribs))
;; Bezeichnung automatisch setzen: "KreiselN"
(setq attribs (subst (cons "Bezeichnung" (strcat "Kreisel" (itoa kreisel-nummer)))
(assoc "Bezeichnung" attribs) attribs))
;; --- HÖHE BESTIMMEN ---
;; Priorität 1: Aus basePoint (wenn 3D Punkt mit Z > 0)
@@ -337,7 +347,7 @@
(progn
(setq z-hoehe (caddr basePoint))
(setq block-hoehe (rtos z-hoehe 2 0))
(princ (strcat "\n-> Höhe aus Basispunkt übernommen: " block-hoehe))
(princ (ssg-textf "kreisel-hoehe-aus-basispunkt" (list block-hoehe)))
)
(progn
;; Höhe aus Attributen lesen
@@ -353,6 +363,11 @@
(setq attribs (subst (cons "HOEHE" block-hoehe)
(assoc "HOEHE" attribs) attribs))
;; Montagehoehe in Metern ableiten (Default = HOEHE / 1000, mm->m).
;; Bleibt ein normales Attribut und kann vom Benutzer geaendert werden.
(setq attribs (subst (cons "MONTAGEHOEHE_m" (rtos (/ z-hoehe 1000.0) 2 3))
(assoc "MONTAGEHOEHE_m" attribs) attribs))
;; Abgeleitete Masse
(setq radius (/ *kreisel-durchmesser* 2.0))
(setq pin-y (- radius *kreisel-pin-abstand*))
@@ -454,12 +469,12 @@
;; --- Block erzeugen (Entities werden aus Zeichnung entfernt) ---
(if (> (sslength ss) 0)
(command "_.-BLOCK" bname (list 0.0 0.0 0.0) ss "")
(princ "\nFehler: Keine Entities zum Block erstellen!")
(princ (ssg-text "kreisel-fehler-keine-entities"))
)
(princ (strcat "\n-> Neue Blockdefinition: " bname))
(princ (ssg-textf "kreisel-neue-blockdef" (list bname)))
)
(princ (strcat "\n-> Verwende bestehende Blockdefinition: " bname))
(princ (ssg-textf "kreisel-bestehende-blockdef" (list bname)))
)
;; --- Block am Zielpunkt einfuegen (ohne Attribut-Dialog) ---
@@ -495,8 +510,7 @@
(if (atoms-family 1 '("ssg-id-generate"))
(ssg-id-generate block-ent)
)
(princ (strcat "\n-> Kreisel #" (itoa kreisel-nummer) " eingefügt: " bname
" (Höhe=" block-hoehe ")"))
(princ (ssg-textf "kreisel-eingefuegt" (list (itoa kreisel-nummer) bname block-hoehe)))
(entlast)
)
@@ -514,19 +528,19 @@
;; --------------------------------------------
(defun c:KreiselInsert ( / pt abstand typ rotation rotStr hoehe
selectedEnt blockAttribs oldOsmode)
(ssg-start "Kreisel Modul einfuegen" '(("OSMODE") ("CECOLOR")))
(ssg-start (ssg-text "kreisel-start-insert") '(("OSMODE") ("CECOLOR")))
;; Temporär Osnap für Blockerkennung setzen
(setq oldOsmode (getvar "OSMODE"))
(setvar "OSMODE" (logior oldOsmode 512)) ;; 512 = INS (Block-Einfügepunkt)
;; 1. Einfuegepunkt
(setq pt (getpoint "\nBasispunkt (AN-Seite): "))
(setq pt (getpoint (ssg-text "kreisel-prompt-basispunkt")))
(if (null pt)
(progn
(setvar "OSMODE" oldOsmode)
(ssg-end)
(princ "\nBefehl abgebrochen.")
(princ (ssg-text "kreisel-abbruch-befehl"))
(princ)
(return)
)
@@ -546,16 +560,16 @@
(setq blockAttribs (ssg-attrib-read selectedEnt))
(assoc "HOEHE" blockAttribs))
(setq hoehe (atof (cdr (assoc "HOEHE" blockAttribs))))
(princ (strcat "\n-> Höhe von bestehendem Kreisel übernommen: " (rtos hoehe 2 0)))
(princ (ssg-textf "kreisel-hoehe-von-bestehendem" (list (rtos hoehe 2 0))))
)
;; Fall 2: Punkt hat Z-Koordinate > 0
((and (> (length pt) 2) (> (caddr pt) 0))
(setq hoehe (caddr pt))
(princ (strcat "\n-> Höhe aus 3D-Punkt übernommen: " (rtos hoehe 2 0)))
(princ (ssg-textf "kreisel-hoehe-aus-3dpunkt" (list (rtos hoehe 2 0))))
)
;; Fall 3: Sonst separat abfragen
(t
(setq hoehe (getreal (strcat "\nHöhe (Z-Koordinate) <" (rtos *kreisel-default-hoehe* 2 0) ">: ")))
(setq hoehe (getreal (ssg-textf "kreisel-prompt-hoehe-z" (list (rtos *kreisel-default-hoehe* 2 0)))))
(if (null hoehe) (setq hoehe *kreisel-default-hoehe*))
)
)
@@ -563,13 +577,12 @@
;; 3. Abstand
(initget 6)
(setq abstand (getdist (list (car pt) (cadr pt))
(strcat "\nAbstand (Tangentenlaenge) <"
(rtos *kreisel-default-laenge* 2 0) ">: ")))
(ssg-textf "kreisel-prompt-abstand" (list (rtos *kreisel-default-laenge* 2 0)))))
(if (null abstand) (setq abstand *kreisel-default-laenge*))
(princ (strcat "\n-> Abstand: " (rtos abstand 2 0) " mm"))
(princ (ssg-textf "kreisel-abstand-ausgabe" (list (rtos abstand 2 0))))
;; 4. Rotation
(setq rotStr (getstring "\nRotation in Grad <0>: "))
(setq rotStr (getstring (ssg-text "kreisel-prompt-rotation")))
(if (= rotStr "")
(setq rotation 0.0)
(setq rotation (atof rotStr))
@@ -578,9 +591,8 @@
;; 5. Kreiselart
(setq typ (kreisel-ask-typ))
(princ (strcat "\n-> Rotation: " (rtos rotation 2 1)
" Höhe: " (rtos hoehe 2 0)
" Kreiselart: " typ))
(princ (ssg-textf "kreisel-insert-zusammenfassung"
(list (rtos rotation 2 1) (rtos hoehe 2 0) typ)))
;; 6. Modul einfuegen
(draw-module (list (car pt) (cadr pt) hoehe) abstand rotation
@@ -590,7 +602,7 @@
;; KEIN weiteres (setvar "OSMODE" ...) mehr nötig!
;; ssg-end stellt nur CLAYER und CMDECHO wieder her, nicht OSMODE
(princ "\nKreisel Modul eingefuegt.")
(princ (ssg-text "kreisel-insert-fertig"))
(ssg-end)
)
@@ -607,20 +619,20 @@
;; -----------------------------------------------
(defun c:KreiselConnect ( / ptStart ptEnd dx dy dist abstand rotation typ hoehe)
(ssg-start "Kreisel Smart Connect" '(("OSMODE") ("CECOLOR")))
(ssg-start (ssg-text "kreisel-start-connect") '(("OSMODE") ("CECOLOR")))
(princ "\n--- Kreisel durch Linie definieren (AN -> SP) ---")
(princ (ssg-text "kreisel-connect-header"))
;; 1. Startpunkt (aeusserster Punkt AN-Seite)
(setq ptStart (getpoint "\nStartpunkt (AN-Seite aussen): "))
(setq ptStart (getpoint (ssg-text "kreisel-prompt-startpunkt")))
(if (null ptStart)
(progn (ssg-end) (princ "\nAbgebrochen.") (princ) (exit))
(progn (ssg-end) (princ (ssg-text "kreisel-abgebrochen")) (princ) (exit))
)
;; 2. Endpunkt (aeusserster Punkt SP-Seite) mit Gummiband
(setq ptEnd (getpoint ptStart "\nEndpunkt (SP-Seite aussen): "))
(setq ptEnd (getpoint ptStart (ssg-text "kreisel-prompt-endpunkt")))
(if (null ptEnd)
(progn (ssg-end) (princ "\nAbgebrochen.") (princ) (exit))
(progn (ssg-end) (princ (ssg-text "kreisel-abgebrochen")) (princ) (exit))
)
;; 3. Geometrie berechnen
@@ -631,8 +643,8 @@
(if (<= abstand 0.0)
(progn
(ssg-emsg (strcat "Distanz zu klein! ("
(rtos dist 2 0) " < " (rtos *kreisel-durchmesser* 2 0) ")"))
(ssg-emsg (ssg-textf "kreisel-emsg-distanz-klein"
(list (rtos dist 2 0) (rtos *kreisel-durchmesser* 2 0))))
(ssg-end)
(exit)
)
@@ -648,26 +660,24 @@
)
(if (<= hoehe 0.0)
(progn
(setq hoehe (getreal (strcat "\nHoehe (Z-Koordinate) <" (rtos *kreisel-default-hoehe* 2 0) ">: ")))
(setq hoehe (getreal (ssg-textf "kreisel-prompt-hoehe-z" (list (rtos *kreisel-default-hoehe* 2 0)))))
(if (null hoehe) (setq hoehe *kreisel-default-hoehe*))
)
(princ (strcat "\n-> Hoehe aus Startpunkt uebernommen: " (rtos hoehe 2 0)))
(princ (ssg-textf "kreisel-hoehe-aus-startpunkt" (list (rtos hoehe 2 0))))
)
;; 6. Kreiselart abfragen
(setq typ (kreisel-ask-typ))
(princ (strcat "\n-> Abstand: " (rtos abstand 2 0) " mm"
" Rotation: " (rtos rotation 2 1) " Grad"
" Hoehe: " (rtos hoehe 2 0)
" Kreiselart: " typ))
(princ (ssg-textf "kreisel-connect-zusammenfassung"
(list (rtos abstand 2 0) (rtos rotation 2 1) (rtos hoehe 2 0) typ)))
;; 7. Modul einfuegen
(draw-module (list (car ptStart) (cadr ptStart) hoehe) abstand rotation
(list (cons "KREISELART" typ)
(cons "HOEHE" (rtos hoehe 2 0))))
(princ "\nKreisel Connect erfolgreich!")
(princ (ssg-text "kreisel-connect-erfolgreich"))
(ssg-end)
)
@@ -684,7 +694,7 @@
;; hoehe : Hoehe in mm (oder nil fuer Z aus pt)
;; Rueckgabe: Entity-Name des erzeugten Blocks oder nil
(defun kreisel-insert-script (pt abstand rotation typ hoehe / z blockEnt)
(ssg-start "Kreisel Script Insert" '(("OSMODE") ("CECOLOR")))
(ssg-start (ssg-text "kreisel-start-script-insert") '(("OSMODE") ("CECOLOR")))
(if (null typ) (setq typ "STANDARD"))
(setq z (if hoehe hoehe
(if (and pt (caddr pt)) (caddr pt) *kreisel-default-hoehe*)))
@@ -703,14 +713,14 @@
;; hoehe : Hoehe in mm (oder nil fuer Z aus ptStart)
;; Rueckgabe: Entity-Name des erzeugten Blocks oder nil
(defun kreisel-connect-script (ptStart ptEnd typ hoehe / dx dy dist abstand rotation z blockEnt)
(ssg-start "Kreisel Script Connect" '(("OSMODE") ("CECOLOR")))
(ssg-start (ssg-text "kreisel-start-script-connect") '(("OSMODE") ("CECOLOR")))
(if (null typ) (setq typ "STANDARD"))
(setq dx (- (car ptEnd) (car ptStart))
dy (- (cadr ptEnd) (cadr ptStart)))
(setq dist (sqrt (+ (* dx dx) (* dy dy))))
(setq abstand (- dist *kreisel-durchmesser*))
(if (<= abstand 0.0)
(progn (princ (strcat "\n[Connect] Distanz zu klein: " (rtos dist 2 0)))
(progn (princ (ssg-textf "kreisel-script-distanz-klein" (list (rtos dist 2 0))))
(ssg-end) nil)
(progn
(setq rotation (* (/ 180.0 pi) (atan dy dx)))
@@ -727,19 +737,19 @@
;; Neue Befehle für Beschriftungs-Einstellungen
(defun c:KreiselLabelPos ( / dx dy)
(setq dx (getreal (strcat "\nX-Abstand von AN8-Mitte <" (rtos *kreisel-beschriftung-abstand-x* 2 0) ">: ")))
(setq dx (getreal (ssg-textf "kreisel-prompt-x-abstand" (list (rtos *kreisel-beschriftung-abstand-x* 2 0)))))
(if dx (setq *kreisel-beschriftung-abstand-x* dx))
(setq dy (getreal (strcat "\nY-Abstand von AN8-Mitte <" (rtos *kreisel-beschriftung-abstand-y* 2 0) ">: ")))
(setq dy (getreal (ssg-textf "kreisel-prompt-y-abstand" (list (rtos *kreisel-beschriftung-abstand-y* 2 0)))))
(if dy (setq *kreisel-beschriftung-abstand-y* dy))
(princ (strcat "\nNeue Beschriftungsposition: X=" (rtos *kreisel-beschriftung-abstand-x* 2 0)
" Y=" (rtos *kreisel-beschriftung-abstand-y* 2 0)))
(princ (ssg-textf "kreisel-neue-beschriftungsposition"
(list (rtos *kreisel-beschriftung-abstand-x* 2 0) (rtos *kreisel-beschriftung-abstand-y* 2 0))))
(princ)
)
(defun c:KreiselLabelHoehe ( / h)
(setq h (getreal (strcat "\nTexthöhe <" (rtos *kreisel-beschriftung-hoehe* 2 0) ">: ")))
(setq h (getreal (ssg-textf "kreisel-prompt-texthoehe" (list (rtos *kreisel-beschriftung-hoehe* 2 0)))))
(if h (setq *kreisel-beschriftung-hoehe* h))
(princ (strcat "\nNeue Texthöhe: " (rtos *kreisel-beschriftung-hoehe* 2 0)))
(princ (ssg-textf "kreisel-neue-texthoehe" (list (rtos *kreisel-beschriftung-hoehe* 2 0))))
(princ)
)
@@ -753,17 +763,17 @@
;; -----------------------------------------------
(defun c:KreiselRedraw ( / sel ent ed attribs basePoint rotation newAbstand)
(ssg-start "Kreisel Neu Zeichnen" '(("CECOLOR")))
(ssg-start (ssg-text "kreisel-start-redraw") '(("CECOLOR")))
;; 1. Bestehenden Kreisel-Block auswaehlen
(setq sel (entsel "\nKreisel-Block auswaehlen: "))
(setq sel (entsel (ssg-text "kreisel-prompt-block-auswaehlen")))
(if (null sel) (exit))
(setq ent (car sel))
(setq ed (entget ent))
;; Pruefen ob INSERT
(if (/= (cdr (assoc 0 ed)) "INSERT")
(progn (ssg-emsg "Kein Block ausgewaehlt!") (exit))
(progn (ssg-emsg (ssg-text "kreisel-emsg-kein-block")) (exit))
)
;; 2. Bestehende Werte auslesen
@@ -772,19 +782,20 @@
(setq rotation (* (/ 180.0 pi) (cdr (assoc 50 ed))))
;; NEU - Höhe aus Attributen lesen und anzeigen:
(princ (strcat "\n-> Bestehend: Abstand=" (cdr (assoc "ABSTAND" attribs))
" Drehung=" (cdr (assoc "DREHUNG" attribs))
" Höhe=" (cdr (assoc "HOEHE" attribs)) ;; <-- NEU
" Art=" (cdr (assoc "KREISELART" attribs))))
(princ (ssg-textf "kreisel-redraw-bestehend"
(list (cdr (assoc "ABSTAND" attribs))
(cdr (assoc "DREHUNG" attribs))
(cdr (assoc "HOEHE" attribs))
(cdr (assoc "KREISELART" attribs)))))
;; 3. Neuen Abstand abfragen (Enter = beibehalten)
(initget 6)
(setq newAbstand (getdist (strcat "\nNeuer Abstand <" (cdr (assoc "ABSTAND" attribs)) ">: ")))
(setq newAbstand (getdist (ssg-textf "kreisel-prompt-neuer-abstand" (list (cdr (assoc "ABSTAND" attribs))))))
(if (null newAbstand)
(setq newAbstand (atof (cdr (assoc "ABSTAND" attribs))))
)
;; NEU - Neue Höhe abfragen:
(setq newHoehe (getreal (strcat "\nNeue Höhe <" (cdr (assoc "HOEHE" attribs)) ">: ")))
(setq newHoehe (getreal (ssg-textf "kreisel-prompt-neue-hoehe" (list (cdr (assoc "HOEHE" attribs))))))
(if (null newHoehe)
(setq newHoehe (atof (cdr (assoc "HOEHE" attribs))))
)
@@ -795,7 +806,7 @@
(draw-module (list (car basePoint) (cadr basePoint) newHoehe)
newAbstand rotation attribs)
(princ (strcat "\nKreisel neu gezeichnet. Abstand=" (rtos newAbstand 2 0)))
(princ (ssg-textf "kreisel-redraw-fertig" (list (rtos newAbstand 2 0))))
(ssg-end)
)
@@ -804,17 +815,17 @@
;; KreiselQuick: Schnell mit Defaults (horizontal)
;; --------------------------------------------
(defun c:KreiselQuick ( / pt)
(ssg-start "Kreisel Schnell Einfuegen" '(("CECOLOR")))
(setq pt (getpoint "\nBasispunkt (AN-Seite): "))
(ssg-start (ssg-text "kreisel-start-quick") '(("CECOLOR")))
(setq pt (getpoint (ssg-text "kreisel-prompt-basispunkt")))
;; NEU - Höhe abfragen:
(setq hoehe (getreal (strcat "\nHöhe (Z-Koordinate) <0>: ")))
(setq hoehe (getreal (ssg-textf "kreisel-prompt-hoehe-z" (list "0"))))
(if (null hoehe) (setq hoehe 0.0))
(if pt
;; NEU - Höhe im Aufruf übergeben:
(draw-module (list (car pt) (cadr pt) hoehe) *kreisel-default-laenge* 0.0
(list (cons "HOEHE" (rtos hoehe 2 0))))
)
(princ "\nSchnell Einfuegen fertig.")
(princ (ssg-text "kreisel-quick-fertig"))
(ssg-end)
)
@@ -860,7 +871,8 @@
(defun c:KreiselEdit ( / sel ss ent ed attribs basePoint rotation
dcl-pfad dat ergebnis
dlg-name dlg-abstand dlg-hoehe dlg-ausrichtung
dlg-drehrichtung dlg-kreiselart
dlg-drehrichtung dlg-kreiselart dlg-geruest-einzelmodul
dlg-geruest-typ
newAbstand newRotation ausrichtLabels)
;; Implied Selection VOR ssg-start pruefen (ssg-start hebt Selektion auf)
@@ -870,13 +882,13 @@
(setq ent (ssname ss 0))
)
(ssg-start "Kreisel bearbeiten" '(("OSMODE") ("CECOLOR") ("ATTREQ") ("ATTDIA")))
(ssg-start (ssg-text "kreisel-start-edit") '(("OSMODE") ("CECOLOR") ("ATTREQ") ("ATTDIA")))
(setvar "OSMODE" 0)
;; 1. Block auswaehlen (falls nicht vorselektiert)
(if (null ent)
(progn
(setq sel (entsel "\nKreisel-Block auswaehlen: "))
(setq sel (entsel (ssg-text "kreisel-prompt-block-auswaehlen")))
(if sel (setq ent (car sel)))
)
)
@@ -884,7 +896,7 @@
(setq ed (entget ent))
(if (/= (cdr (assoc 0 ed)) "INSERT")
(progn (ssg-emsg "Kein Block ausgewaehlt!") (ssg-end) (exit))
(progn (ssg-emsg (ssg-text "kreisel-emsg-kein-block")) (ssg-end) (exit))
)
;; 2. Bestehende Werte auslesen
@@ -895,7 +907,7 @@
;; Pruefen ob Block Kreisel-Attribute hat (mindestens ABSTAND)
(if (null (assoc "ABSTAND" attribs))
(progn
(ssg-emsg "Kein Kreisel-Block! (Attribut ABSTAND fehlt)")
(ssg-emsg (ssg-text "kreisel-emsg-kein-kreisel-block"))
(ssg-end)
(exit)
)
@@ -912,15 +924,14 @@
(setq attribs (subst (cons "HOEHE" (rtos (if (caddr basePoint) (caddr basePoint) 0.0) 2 1))
(assoc "HOEHE" attribs) attribs))
(princ (strcat "\n-> Bestehend: Abstand=" (cdr (assoc "ABSTAND" attribs))
" Drehung=" (rtos rotation 2 1)
" Art=" (cdr (assoc "KREISELART" attribs))))
(princ (ssg-textf "kreisel-edit-bestehend"
(list (cdr (assoc "ABSTAND" attribs)) (rtos rotation 2 1) (cdr (assoc "KREISELART" attribs)))))
;; 3. DCL-Dialog laden
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/kreisel_edit.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "kreisel_edit" dat))
(progn (alert (strcat "Dialog nicht verfuegbar: " dcl-pfad)) (ssg-end) (exit))
(progn (alert (ssg-textf "kreisel-edit-dialog-fehlt" (list dcl-pfad))) (ssg-end) (exit))
)
;; Ausrichtungs-Labels fuer popup_list aufbauen
@@ -933,7 +944,7 @@
)
;; Tiles initialisieren
(set_tile "name" (cdr (assoc "NAME" attribs)))
(set_tile "name" (cdr (assoc "Bezeichnung" attribs)))
(set_tile "abstand" (cdr (assoc "ABSTAND" attribs)))
(set_tile "hoehe" (cdr (assoc "HOEHE" attribs)))
@@ -956,6 +967,14 @@
(end_list)
(set_tile "kreiselart" (if (equal (cdr (assoc "KREISELART" attribs)) "PIN") "1" "0"))
(set_tile "geruest_einzelmodul"
(if (equal (cdr (assoc "GERUEST_EINZELMODUL" attribs)) "1") "1" "0"))
(start_list "geruest_typ")
(foreach opt *ssg-geruest-optionen* (add_list opt))
(end_list)
(set_tile "geruest_typ" (itoa (ssg-geruest-typ-to-idx (cdr (assoc "GERUEST_TYP" attribs)))))
;; Actions
(action_tile "accept"
(strcat
@@ -965,6 +984,8 @@
"(setq dlg-ausrichtung (get_tile \"ausrichtung\"))"
"(setq dlg-drehrichtung (get_tile \"drehrichtung\"))"
"(setq dlg-kreiselart (get_tile \"kreiselart\"))"
"(setq dlg-geruest-einzelmodul (get_tile \"geruest_einzelmodul\"))"
"(setq dlg-geruest-typ (get_tile \"geruest_typ\"))"
"(done_dialog 1)"
)
)
@@ -981,8 +1002,8 @@
(setq newRotation (kreisel-idx-to-rotation (atoi dlg-ausrichtung)))
;; Attribute aktualisieren
(setq attribs (subst (cons "NAME" dlg-name)
(assoc "NAME" attribs) attribs))
(setq attribs (subst (cons "Bezeichnung" dlg-name)
(assoc "Bezeichnung" attribs) attribs))
(setq attribs (subst (cons "HOEHE" dlg-hoehe)
(assoc "HOEHE" attribs) attribs))
(setq attribs (subst (cons "KREISELART"
@@ -991,6 +1012,10 @@
(setq attribs (subst (cons "DREHRICHTUNG"
(if (= dlg-drehrichtung "1") "GUZ" "UZS"))
(assoc "DREHRICHTUNG" attribs) attribs))
(setq attribs (subst (cons "GERUEST_EINZELMODUL" dlg-geruest-einzelmodul)
(assoc "GERUEST_EINZELMODUL" attribs) attribs))
(setq attribs (subst (cons "GERUEST_TYP" (ssg-geruest-idx-to-typ (atoi dlg-geruest-typ)))
(assoc "GERUEST_TYP" attribs) attribs))
;; Alten Block loeschen
(command "_.ERASE" ent "")
@@ -999,13 +1024,10 @@
(draw-module (list (car basePoint) (cadr basePoint) (atof dlg-hoehe))
newAbstand newRotation attribs)
(princ (strcat "\nKreisel aktualisiert: "
"Name=" dlg-name
" Abstand=" (rtos newAbstand 2 0)
" Hoehe=" dlg-hoehe
" Rotation=" (rtos newRotation 2 1)))
(princ (ssg-textf "kreisel-edit-aktualisiert"
(list dlg-name (rtos newAbstand 2 0) dlg-hoehe (rtos newRotation 2 1))))
)
(princ "\nAbgebrochen.")
(princ (ssg-text "kreisel-abgebrochen"))
)
(ssg-end)
@@ -1016,13 +1038,13 @@
;; KreiselParams: Aktuelle Parameter anzeigen
;; --------------------------------------------
(defun c:KreiselParams ()
(princ "\n=== Kreisel Parameter ===")
(princ (strcat "\nKreiselart: " #Kreisel_Typ))
(princ (strcat "\nDurchmesser: " (rtos *kreisel-durchmesser* 2 0)))
(princ (strcat "\nDefault-Laenge: " (rtos *kreisel-default-laenge* 2 0)))
(princ (ssg-text "kreisel-params-header"))
(princ (ssg-textf "kreisel-params-typ" (list #Kreisel_Typ)))
(princ (ssg-textf "kreisel-params-durchmesser" (list (rtos *kreisel-durchmesser* 2 0))))
(princ (ssg-textf "kreisel-params-default-laenge" (list (rtos *kreisel-default-laenge* 2 0))))
;; NEU - Default-Höhe anzeigen:
(princ (strcat "\nDefault-Höhe: " (rtos *kreisel-default-hoehe* 2 0)))
(princ "\nAttribute im Block:")
(princ (ssg-textf "kreisel-params-default-hoehe" (list (rtos *kreisel-default-hoehe* 2 0))))
(princ (ssg-text "kreisel-params-attribute-header"))
(foreach def *kreisel-attrib-defs*
(princ (strcat "\n " (car def) " = " (cadr def)))
)
@@ -1041,16 +1063,17 @@
;; 4. Hoehe aus Z-Koordinate oder manuell
;; --------------------------------------------
(defun c:ILS_Eckrad ( / ptTangent ptDir dx dy dist ux uy radius
centerPt rotation hoehe)
centerPt rotation hoehe
geruest-einzelmodul geruest-typ)
(dbgf "c:ILS_Eckrad")
;; 1. Beruehrpunkt (Tangentenpunkt)
(setq ptTangent (getpoint "\nBeruehrpunkt Eckrad (Tangente): "))
(setq ptTangent (getpoint (ssg-text "kreisel-eckrad-beruehrpunkt")))
(if (null ptTangent) (progn (dbgreturn nil) (exit)))
(dbg 'ptTangent)
;; 2. Richtungspunkt (Gummiband vom Beruehrpunkt)
(setq ptDir (getpoint ptTangent "\nRichtung zum Kreismittelpunkt: "))
(setq ptDir (getpoint ptTangent (ssg-text "kreisel-eckrad-richtung")))
(if (null ptDir) (progn (dbgreturn nil) (exit)))
(dbg 'ptDir)
@@ -1061,7 +1084,7 @@
(if (<= dist (ssg-cfg-or "kreisel" "toleranz_min_distanz" 0.001))
(progn
(princ "\nFehler: Beruehr- und Richtungspunkt sind identisch!")
(princ (ssg-text "kreisel-eckrad-fehler-identisch"))
(dbgreturn nil)
(exit)
)
@@ -1087,17 +1110,23 @@
(if (and (> (length ptTangent) 2) (caddr ptTangent) (> (caddr ptTangent) 0))
(progn
(setq hoehe (caddr ptTangent))
(princ (strcat "\n-> Hoehe aus 3D-Punkt uebernommen: " (rtos hoehe 2 0)))
(princ (ssg-textf "kreisel-hoehe-aus-3dpunkt" (list (rtos hoehe 2 0))))
)
(progn
(setq hoehe (getreal (strcat "\nHoehe (Z-Koordinate) <" (rtos *eckrad-default-hoehe* 2 0) ">: ")))
(setq hoehe (getreal (ssg-textf "kreisel-prompt-hoehe-z" (list (rtos *eckrad-default-hoehe* 2 0)))))
(if (null hoehe) (setq hoehe *eckrad-default-hoehe*))
)
)
(dbg 'hoehe)
;; 5. Einfuegen (centerPt ist der Kreismittelpunkt)
(ils-eckrad-insert (list (car centerPt) (cadr centerPt) hoehe) rotation nil)
;; 5. Geruest fuer Einzelmodul + Geruestoption abfragen
(setq geruest-einzelmodul (if (ssg-ques (ssg-text "kreisel-eckrad-geruest-frage") T) "1" "0"))
(setq geruest-typ (ssg-ask-geruest-typ))
;; 6. Einfuegen (centerPt ist der Kreismittelpunkt)
(ils-eckrad-insert (list (car centerPt) (cadr centerPt) hoehe) rotation
(list (cons "GERUEST_EINZELMODUL" geruest-einzelmodul)
(cons "GERUEST_TYP" geruest-typ)))
(dbgreturn nil)
)
@@ -1118,7 +1147,7 @@
(dbg 'pt)
(dbg 'rotation)
(ssg-start "Eckrad einfuegen" '(("ATTREQ") ("ATTDIA") ("OSMODE") ("CECOLOR")))
(ssg-start (ssg-text "kreisel-start-eckrad") '(("ATTREQ") ("ATTDIA") ("OSMODE") ("CECOLOR")))
;; Attribute vorbereiten
(setq attribs (ssg-attrib-merge attribs *eckrad-attrib-defs*))
@@ -1215,14 +1244,14 @@
(dbgp (strcat "Blockdefinition erzeugt: " bname))
)
(progn
(princ "\nFehler: Keine Entities zum Block erstellen!")
(princ (ssg-text "kreisel-fehler-keine-entities"))
(dbgp "FEHLER: Keine Entities fuer Block!")
)
)
(princ (strcat "\n-> Neue Blockdefinition: " bname))
(princ (ssg-textf "kreisel-neue-blockdef" (list bname)))
)
(progn
(princ (strcat "\n-> Verwende bestehende Blockdefinition: " bname))
(princ (ssg-textf "kreisel-bestehende-blockdef" (list bname)))
(dbgp (strcat "Verwende bestehende Blockdefinition: " bname))
)
)
@@ -1259,29 +1288,28 @@
)
(entupd block-ent)
(princ (strcat "\n-> Eckrad #" (itoa eckrad-nummer) " eingefuegt: " bname
" bei " (rtos (car pt) 2 1) "," (rtos (cadr pt) 2 1)
" Rotation=" (rtos rotation 2 1)
" Hoehe=" block-hoehe))
(princ (ssg-textf "kreisel-eckrad-eingefuegt"
(list (itoa eckrad-nummer) bname (rtos (car pt) 2 1) (rtos (cadr pt) 2 1)
(rtos rotation 2 1) block-hoehe)))
(ssg-end)
(dbgreturn (entlast))
)
;; NEU: KreiselLabelSetup - Hier einfügen!
(defun c:KreiselLabelSetup ( / hoehe farbe abstand schriftart)
(setq hoehe (getreal (strcat "\nSchrifthöhe <" (rtos *kreisel-beschriftung-hoehe* 2 0) ">: ")))
(setq hoehe (getreal (ssg-textf "kreisel-prompt-schrifthoehe" (list (rtos *kreisel-beschriftung-hoehe* 2 0)))))
(if hoehe (setq *kreisel-beschriftung-hoehe* hoehe))
(setq farbe (getint (strcat "\nSchriftfarbe (1=Rot,2=Gelb,3=Grün,4=Cyan,5=Blau,6=Magenta,7=Weiß) <" (itoa *kreisel-beschriftung-farbe*) ">: ")))
(setq farbe (getint (ssg-textf "kreisel-prompt-schriftfarbe" (list (itoa *kreisel-beschriftung-farbe*)))))
(if farbe (setq *kreisel-beschriftung-farbe* farbe))
(setq abstand (getreal (strcat "\nAbstand über Kreisel-Mitte <" (rtos *kreisel-beschriftung-abstand-oben* 2 0) ">: ")))
(setq abstand (getreal (ssg-textf "kreisel-prompt-abstand-oben" (list (rtos *kreisel-beschriftung-abstand-oben* 2 0)))))
(if abstand (setq *kreisel-beschriftung-abstand-oben* abstand))
(princ (strcat "\nNeue Einstellungen: Höhe=" (rtos *kreisel-beschriftung-hoehe* 2 0)
", Farbe=" (itoa *kreisel-beschriftung-farbe*)
", Y-Versatz=" (rtos *kreisel-beschriftung-abstand-oben* 2 0)
", Schriftart=Arial"))
(princ (ssg-textf "kreisel-labelsetup-fertig"
(list (rtos *kreisel-beschriftung-hoehe* 2 0)
(itoa *kreisel-beschriftung-farbe*)
(rtos *kreisel-beschriftung-abstand-oben* 2 0))))
(princ)
)
+332 -193
View File
@@ -28,7 +28,7 @@
(setq data-pfad (getenv "DXFM_DATA"))
(if (null data-pfad)
(progn
(princ "\n[OMNI] FEHLER: DXFM_DATA nicht gesetzt!")
(princ (ssg-text "omni-fehler-dxfm-data"))
nil
)
(progn
@@ -242,21 +242,21 @@
;; --- BricsCAD-Befehl: Bogen-Info anzeigen ---
(defun c:OMNI_INFO_BOGEN ( / id eintrag)
(if (null *OMNI-BOEGEN*) (omni:load-data))
(setq id (getstring T "\nSivasId des Bogens eingeben: "))
(if (= id "") (princ "\nAbgebrochen.")
(setq id (getstring T (ssg-text "omni-info-bogen-prompt")))
(if (= id "") (princ (ssg-text "omni-abbruch"))
(progn
;; Versuch als Zahl, dann als String
(setq eintrag (omni:get-bogen (if (/= (atoi id) 0) (atoi id) id)))
(if eintrag
(progn
(princ (strcat "\n ProfilTyp: " (omni:sivasid-to-str (omni:val eintrag "ProfilTyp"))))
(princ (strcat "\n Radius: " (itoa (fix (omni:val eintrag "Radius")))))
(princ (strcat "\n KurvenWinkel: " (rtos (omni:val eintrag "KurvenWinkel") 2 1)))
(princ (strcat "\n Breite: " (itoa (fix (omni:val eintrag "Breite")))))
(princ (strcat "\n Laenge: " (itoa (fix (omni:val eintrag "Länge")))))
(princ (strcat "\n Antriebsart: " (itoa (fix (omni:val eintrag "Antriebsart")))))
(princ (ssg-textf "omni-bogen-info-profiltyp" (list (omni:sivasid-to-str (omni:val eintrag "ProfilTyp")))))
(princ (ssg-textf "omni-bogen-info-radius" (list (itoa (fix (omni:val eintrag "Radius"))))))
(princ (ssg-textf "omni-bogen-info-kurvenwinkel" (list (rtos (omni:val eintrag "KurvenWinkel") 2 1))))
(princ (ssg-textf "omni-bogen-info-breite" (list (itoa (fix (omni:val eintrag "Breite"))))))
(princ (ssg-textf "omni-bogen-info-laenge" (list (itoa (fix (omni:val eintrag "Länge"))))))
(princ (ssg-textf "omni-bogen-info-antriebsart" (list (itoa (fix (omni:val eintrag "Antriebsart"))))))
)
(princ (strcat "\nKein Bogen mit SivasId '" id "' gefunden."))
(princ (ssg-textf "omni-bogen-nicht-gefunden" (list id)))
)
)
)
@@ -267,25 +267,25 @@
;; --- BricsCAD-Befehl: Weichen-Info anzeigen ---
(defun c:OMNI_INFO_WEICHE ( / id eintrag wkl)
(if (null *OMNI-WEICHEN*) (omni:load-data))
(setq id (getstring T "\nSivasId der Weiche eingeben: "))
(if (= id "") (princ "\nAbgebrochen.")
(setq id (getstring T (ssg-text "omni-info-weiche-prompt")))
(if (= id "") (princ (ssg-text "omni-abbruch"))
(progn
(setq eintrag (omni:get-weiche (if (/= (atoi id) 0) (atoi id) id)))
(if eintrag
(progn
(princ (strcat "\n ProfilTyp: " (omni:sivasid-to-str (omni:val eintrag "ProfilTyp"))))
(princ (strcat "\n WeichenTyp: " (omni:sivasid-to-str (omni:val eintrag "WeichenTyp"))))
(princ (ssg-textf "omni-weiche-info-profiltyp" (list (omni:sivasid-to-str (omni:val eintrag "ProfilTyp")))))
(princ (ssg-textf "omni-weiche-info-weichentyp" (list (omni:sivasid-to-str (omni:val eintrag "WeichenTyp")))))
(setq wkl (omni:val eintrag "KurvenWinkel"))
(princ (strcat "\n KurvenWinkel: " (if (= (type wkl) 'INT) (itoa wkl) (rtos wkl 2 1))))
(princ (strcat "\n Schaltungstyp: " (omni:sivasid-to-str (omni:val eintrag "Schaltungstyp"))))
(princ (strcat "\n Breite: " (itoa (fix (omni:val eintrag "Breite")))))
(princ (strcat "\n Laenge: " (itoa (fix (omni:val eintrag "Länge")))))
(princ (strcat "\n KurvenRichtung: " (itoa (fix (omni:val eintrag "KurvenRichtung")))))
(princ (ssg-textf "omni-weiche-info-kurvenwinkel" (list (if (= (type wkl) 'INT) (itoa wkl) (rtos wkl 2 1)))))
(princ (ssg-textf "omni-weiche-info-schaltungstyp" (list (omni:sivasid-to-str (omni:val eintrag "Schaltungstyp")))))
(princ (ssg-textf "omni-weiche-info-breite" (list (itoa (fix (omni:val eintrag "Breite"))))))
(princ (ssg-textf "omni-weiche-info-laenge" (list (itoa (fix (omni:val eintrag "Länge"))))))
(princ (ssg-textf "omni-weiche-info-kurvenrichtung" (list (itoa (fix (omni:val eintrag "KurvenRichtung"))))))
(if (omni:val eintrag "WeichenkörperLänge")
(princ (strcat "\n WK-Laenge: " (rtos (omni:val eintrag "WeichenkörperLänge") 2 1)))
(princ (ssg-textf "omni-weiche-info-wklaenge" (list (rtos (omni:val eintrag "WeichenkörperLänge") 2 1))))
)
)
(princ (strcat "\nKeine Weiche mit SivasId '" id "' gefunden."))
(princ (ssg-textf "omni-weiche-nicht-gefunden" (list id)))
)
)
)
@@ -332,12 +332,13 @@
;; z.B. "APB 60" oder "APB 110" (nil = keine Einschraenkung)
;; Rueckgabe: (eintrag hoehe drehung) oder nil bei Abbruch
(defun omni:bogen-dialog (winkel init-hoehe init-drehung profiltyp / dcl-pfad dat boegen-liste
profil-liste ergebnis dlg-hoehe dlg-drehung profil)
profil-liste ergebnis dlg-hoehe profil)
(if (null *OMNI-BOEGEN*) (omni:load-data))
;; Defaults
;; Hinweis: init-drehung wird nicht mehr verwendet - die Drehung wird nach
;; dem Einfuegen interaktiv abgefragt (omni:insert-dxf mit drehung=nil).
(if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
(if (null init-drehung) (setq init-drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))
;; Boegen nach Winkel filtern
(setq boegen-liste (omni:filter *OMNI-BOEGEN* "KurvenWinkel" winkel))
@@ -357,11 +358,15 @@
(if (null boegen-liste)
(progn
(alert (strcat "Keine Boegen fuer "
(alert (ssg-textf "omni-bogen-keine-gefunden"
(list
(strcat
(if (= (type winkel) 'INT) (itoa winkel) (rtos winkel 2 1))
" Grad"
(ssg-text "omni-grad")
)
(if profiltyp (strcat " (" profiltyp ")") "")
" gefunden."))
)
))
nil
)
(progn
@@ -376,7 +381,7 @@
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/omniflo_boegen.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "omniflo_boegen" dat))
(progn (alert "Bogen-Dialog konnte nicht geladen werden.") nil)
(progn (alert (ssg-text "omni-bogen-dialog-ladefehler")) nil)
(progn
;; Dropdown befuellen
(start_list "bogenart")
@@ -384,9 +389,8 @@
(end_list)
(set_tile "bogenart" "0")
;; Hoehe und Drehung initialisieren
;; Hoehe initialisieren (Drehung erfolgt interaktiv nach dem Einfuegen)
(set_tile "val_hoehe" init-hoehe)
(set_tile "val_drehung" init-drehung)
;; Startwerte anzeigen
(omni:bogen-dlg-update "0")
@@ -399,16 +403,15 @@
(strcat
"(setq ergebnis (atoi (get_tile \"bogenart\")))"
"(setq dlg-hoehe (get_tile \"val_hoehe\"))"
"(setq dlg-drehung (get_tile \"val_drehung\"))"
"(done_dialog 1)"))
(action_tile "cancel" "(done_dialog 0)")
(start_dialog)
(unload_dialog dat)
;; Gewaehlten Eintrag mit Hoehe/Drehung zurueckgeben
;; Gewaehlten Eintrag mit Hoehe zurueckgeben (drehung=nil -> interaktiv)
(if ergebnis
(list (nth ergebnis *OMNI-DLG-BOEGEN*) dlg-hoehe dlg-drehung)
(list (nth ergebnis *OMNI-DLG-BOEGEN*) dlg-hoehe nil)
nil
)
)
@@ -427,7 +430,7 @@
(setq dlg-result (omni:bogen-dialog 90 nil nil "APB 60"))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[BOGEN] Abgebrochen.")
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
@@ -437,7 +440,7 @@
(setq dlg-result (omni:bogen-dialog 90 nil nil "APB 110"))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[BOGEN] Abgebrochen.")
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
@@ -446,7 +449,7 @@
(setq dlg-result (omni:bogen-dialog 67.5 nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[BOGEN] Abgebrochen.")
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
@@ -455,7 +458,7 @@
(setq dlg-result (omni:bogen-dialog 45 nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[BOGEN] Abgebrochen.")
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
@@ -464,7 +467,7 @@
(setq dlg-result (omni:bogen-dialog 22.5 nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[BOGEN] Abgebrochen.")
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
@@ -473,7 +476,7 @@
(setq dlg-result (omni:bogen-dialog 180 nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[BOGEN] Abgebrochen.")
(princ (ssg-text "omni-abbruch-bogen"))
)
(princ)
)
@@ -494,43 +497,52 @@
;;
;; blockname = Profiltyp (z.B. "AP60", "AP110", "APG110")
;; laengemax = Maximale Fahrstreckenlaenge in mm
(defun omni:insert-block (blockname laengemax /
pt pt2 laenge laengeStr
dx dy angle angleDeg
textEnt textHeight textGap
perpX perpY textPt ed
lastEnt ss e bname blockEnt
srcAttribs attribDefs attribs
ok)
(setq textHeight (ssg-cfg-or "omniflo" "text_height" 100.0))
(setq textGap (ssg-cfg-or "omniflo" "text_gap" 20.0))
;; 0. Attribute aus der Quell-.dwg lesen (vor ssg-start, da eigene INSERT/ERASE)
;; --- Quell-Attribute einer Aluprofil-.dwg lesen (mit ID-Feld) ---
;; blockname = Profiltyp (z.B. "AP60", "AP110", "APG110")
;; Rueckgabe: Attribut-Alist (mit angehaengtem leeren "ID"-Feld) oder nil,
;; wenn *block-path* fehlt oder die Quell-.dwg keine Attribute hat.
(defun omni:read-src-attribs (blockname / srcAttribs)
(if (and (boundp '*block-path*) *block-path*)
(progn
(setq srcAttribs (ssg-attrib-read-dwg (strcat *block-path* blockname ".dwg")))
;; ID-Attribut hinzufuegen falls noch nicht vorhanden
(if (and srcAttribs (not (assoc "ID" srcAttribs)))
(setq srcAttribs (append srcAttribs (list (cons "ID" ""))))
)
(if (null srcAttribs)
(progn (princ "\n[OMNI] Keine Attribute im Quell-Block gefunden.") nil)
(progn
;; LAENGEMAX aus Quell-Attribut lesen (falls vorhanden), sonst Parameter
(if (and (assoc "LAENGEMAX" srcAttribs)
(> (strlen (cdr (assoc "LAENGEMAX" srcAttribs))) 0))
(setq laengemax (atof (cdr (assoc "LAENGEMAX" srcAttribs))))
)
)
srcAttribs
)
(setq pt (getpoint "\nEinfuegepunkt waehlen: "))
(if (null pt)
(progn (princ "\n[OMNI] Abgebrochen.") nil)
(progn
(ssg-start "OMNI Aluprofil" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
;; ATTREQ/ATTDIA auf 0 setzen (werden durch ssg-end wiederhergestellt)
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
;; 1. Text horizontal am Einfuegepunkt erzeugen
;; --- Aluprofil-Gerade non-interaktiv aus zwei Punkten erzeugen ---
;;
;; Skriptfaehiger Kern von omni:insert-block: baut aus zwei bekannten
;; Punkten (Anfang pt, Ende pt2) den Compound-Block (Linie + ATTDEFs) und
;; fuegt ihn ein. Fuehrt KEINE Nutzerabfrage und KEIN ssg-start/ssg-end aus -
;; der Aufrufer sichert die Umgebung und setzt OSMODE/ATTREQ/ATTDIA=0.
;;
;; blockname = Profiltyp (z.B. "AP110")
;; pt / pt2 = Anfangs-/Endpunkt (Liste x y [z])
;; srcAttribs = Quell-Attribute (Alist) oder nil (dann Block ohne ATTDEFs)
;; textHeight / textGap = Textparameter
;; textEnt = optionaler, bereits erzeugter Vorschau-Text (Tag 1 = blockname);
;; nil -> wird hier erzeugt
;; Rueckgabe: Entity-Name des eingefuegten INSERT-Blocks oder nil.
(defun omni:make-gerade (blockname pt pt2 srcAttribs textHeight textGap textEnt /
laenge laengeStr dx dy angle angleDeg
perpX perpY textPt ed lastEnt ss e bname blockEnt
attribs attribDefs)
(setq laenge (distance (list (car pt) (cadr pt))
(list (car pt2) (cadr pt2))))
(setq laengeStr (rtos laenge 2 0))
(setq dx (- (car pt2) (car pt))
dy (- (cadr pt2) (cadr pt)))
(setq angle (atan dy dx))
(setq angleDeg (* (/ 180.0 pi) angle))
;; 1. Vorschau-Text erzeugen, falls nicht vom Aufrufer uebergeben
(if (null textEnt)
(progn
(entmake (list '(0 . "TEXT")
(cons 8 (getvar "CLAYER"))
(cons 10 (list (car pt) (cadr pt)
@@ -539,40 +551,12 @@
(cons 1 blockname)
'(50 . 0.0)))
(setq textEnt (entlast))
;; 2. Endpunkt fuer Fahrstrecke abfragen (Schleife bei Ueberschreitung)
(setq ok nil)
(while (not ok)
(setq pt2 (getpoint pt "\nEndpunkt der Fahrstrecke waehlen: "))
(if (null pt2)
(progn
;; Abbruch: Text loeschen
(command "_.ERASE" textEnt "")
(princ "\n[OMNI] Abgebrochen.")
(setq ok T pt nil)
)
(progn
(setq laenge (distance (list (car pt) (cadr pt))
(list (car pt2) (cadr pt2))))
(if (> laenge laengemax)
(alert (strcat "Die gewuenschte Fahrstreckenlaenge von "
(rtos laenge 2 0) " mm ueberschreitet die Maximallaenge von "
(rtos laengemax 2 0) " mm des Fahrstreckenprofils.\n"
"Bitte neu definieren!"))
(progn
(setq laengeStr (rtos laenge 2 0))
(setq dx (- (car pt2) (car pt))
dy (- (cadr pt2) (cadr pt)))
(setq angle (atan dy dx))
(setq angleDeg (* (/ 180.0 pi) angle))
;; 3. Compound-Block: Linie bei (0,0) + ATTDEFs aus Quell-Attributen
)
(setq lastEnt textEnt)
;; Linie von Ursprung bis (laenge, 0)
;; 2. Compound-Block: Linie bei (0,0)..(laenge,0) + ATTDEFs aus Quell-Attributen
(command "_.LINE" (list 0.0 0.0) (list laenge 0.0) "")
;; ATTDEFs aus Quell-Attributen erzeugen
(setq attribDefs (ssg-attrib-alist-to-defs srcAttribs))
(ssg-attrib-make-defs attribDefs 50.0)
@@ -587,14 +571,16 @@
(if (tblsearch "BLOCK" bname)
(setq bname (strcat bname "_" (itoa (fix (* (getvar "CDATE") 1000000)))))
)
;; Objektfang aus: sonst kann _.INSERT den Einfuegepunkt pt auf ein Objekt
;; umfangen (z.B. den Text bei pt) und die Hoehe verfaelschen.
(setvar "OSMODE" 0)
(command "_.-BLOCK" bname (list 0.0 0.0 0.0) ss "")
;; Block einfuegen (ATTREQ/ATTDIA bereits auf 0)
(command "_.INSERT" bname pt 1 1 angleDeg)
(setq blockEnt (entlast))
;; 4. Attribute setzen: Quell-Werte + LAENGE/A aktualisieren
;; 3. Attribute setzen: Quell-Werte + LAENGE/A aktualisieren
(setq attribs srcAttribs)
(if (assoc "LAENGE" attribs)
(setq attribs (subst (cons "LAENGE" laengeStr)
@@ -608,14 +594,13 @@
)
(ssg-attrib-set-on blockEnt attribs)
;; 5. Text aktualisieren: oberhalb der Linie positionieren,
;; um Linienwinkel drehen, Inhalt mit Laenge ergaenzen
;; 4. Text oberhalb der Linie positionieren, um Linienwinkel drehen,
;; Inhalt mit Laenge ergaenzen
(setq perpX (* (- (sin angle)) textGap)
perpY (* (cos angle) textGap))
(setq textPt (list (+ (car pt) perpX)
(+ (cadr pt) perpY)
(if (caddr pt) (caddr pt) 0.0)))
(setq ed (entget textEnt))
(setq ed (subst (cons 10 textPt) (assoc 10 ed) ed))
(if (assoc 50 ed)
@@ -627,12 +612,75 @@
(entmod ed)
(entupd textEnt)
;; Eindeutige ID zuweisen
;; 5. Eindeutige ID zuweisen
(if (and blockEnt (atoms-family 1 '("ssg-id-generate")))
(ssg-id-generate blockEnt)
)
(princ (strcat "\n[OMNI] " bname " eingefuegt. Laenge=" laengeStr " mm"))
(princ (ssg-textf "omni-insert-block-eingefuegt" (list bname laengeStr)))
blockEnt
)
;; Aluprofil-Fahrstrecke interaktiv einfuegen (siehe Ablaufbeschreibung oben).
;; Fragt Einfuege- und Endpunkt ab und delegiert die Blockerzeugung an
;; omni:make-gerade.
(defun omni:insert-block (blockname laengemax /
pt pt2 laenge textEnt textHeight textGap srcAttribs ok)
(setq textHeight (ssg-cfg-or "omniflo" "text_height" 100.0))
(setq textGap (ssg-cfg-or "omniflo" "text_gap" 20.0))
;; 0. Attribute aus der Quell-.dwg lesen (vor ssg-start, da eigene INSERT/ERASE)
(setq srcAttribs (omni:read-src-attribs blockname))
(if (null srcAttribs)
(progn (princ (ssg-text "omni-insert-keine-attribute")) nil)
(progn
;; LAENGEMAX aus Quell-Attribut lesen (falls vorhanden), sonst Parameter
(if (and (assoc "LAENGEMAX" srcAttribs)
(> (strlen (cdr (assoc "LAENGEMAX" srcAttribs))) 0))
(setq laengemax (atof (cdr (assoc "LAENGEMAX" srcAttribs))))
)
(setq pt (getpoint (ssg-text "omni-prompt-einfuegepunkt")))
(if (null pt)
(progn (princ (ssg-text "omni-abbruch-omni")) nil)
(progn
(ssg-start "OMNI Aluprofil" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
;; ATTREQ/ATTDIA auf 0 setzen (werden durch ssg-end wiederhergestellt)
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
;; Vorschau-Text horizontal am Einfuegepunkt (waehrend Endpunktwahl)
(entmake (list '(0 . "TEXT")
(cons 8 (getvar "CLAYER"))
(cons 10 (list (car pt) (cadr pt)
(if (caddr pt) (caddr pt) 0.0)))
(cons 40 textHeight)
(cons 1 blockname)
'(50 . 0.0)))
(setq textEnt (entlast))
;; Endpunkt fuer Fahrstrecke abfragen (Schleife bei Ueberschreitung)
(setq ok nil)
(while (not ok)
(setq pt2 (getpoint pt (ssg-text "omni-prompt-endpunkt-fahrstrecke")))
(if (null pt2)
(progn
;; Abbruch: Vorschau-Text loeschen
(command "_.ERASE" textEnt "")
(princ (ssg-text "omni-abbruch-omni"))
(setq ok T pt nil)
)
(progn
(setq laenge (distance (list (car pt) (cadr pt))
(list (car pt2) (cadr pt2))))
(if (> laenge laengemax)
(alert (ssg-textf "omni-laenge-ueberschritten"
(list (rtos laenge 2 0) (rtos laengemax 2 0))))
(progn
(omni:make-gerade blockname pt pt2 srcAttribs
textHeight textGap textEnt)
(setq ok T)
)
)
@@ -760,13 +808,14 @@
;; weichentyp = "Einzelweiche", "Doppelweiche", "Dreiwegeweiche" oder nil fuer alle
;; init-hoehe / init-drehung = Vorbelegung (optional, fuer Edit-Modus)
;; Rueckgabe: (eintrag hoehe drehung) oder nil bei Abbruch
(defun omni:weichen-dialog (winkel weichentyp init-hoehe init-drehung / dcl-pfad dat basis-liste
profil-liste ergebnis dlg-hoehe dlg-drehung)
(defun omni:weichen-dialog (winkel weichentyp init-hoehe init-drehung breite / dcl-pfad dat basis-liste
profil-liste ergebnis dlg-hoehe)
(if (null *OMNI-WEICHEN*) (omni:load-data))
;; Defaults
;; Hinweis: init-drehung wird nicht mehr verwendet - die Drehung wird nach
;; dem Einfuegen interaktiv abgefragt (omni:insert-dxf mit drehung=nil).
(if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
(if (null init-drehung) (setq init-drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))
;; Weichen nach Winkel filtern (nil = alle Winkel)
(if winkel
@@ -782,16 +831,26 @@
basis-liste))
)
;; Optional nach Breite filtern (z.B. Weichenkombinationen Delta 1400/700 vs. 1600/800)
(if breite
(setq basis-liste
(vl-remove-if-not
'(lambda (e) (= (cdr (assoc "Breite" e)) breite))
basis-liste))
)
(if (null basis-liste)
(progn
(alert (strcat "Keine Weichen fuer "
(alert (ssg-textf "omni-weiche-keine-gefunden"
(list
(cond
((null winkel) "alle Winkel")
((= (type winkel) 'INT) (strcat (itoa winkel) " Grad"))
(T (strcat (rtos winkel 2 1) " Grad"))
((null winkel) (ssg-text "omni-alle-winkel"))
((= (type winkel) 'INT) (strcat (itoa winkel) (ssg-text "omni-grad")))
(T (strcat (rtos winkel 2 1) (ssg-text "omni-grad")))
)
(if weichentyp (strcat " / " weichentyp) "")
" gefunden."))
)
))
nil
)
(progn
@@ -807,7 +866,7 @@
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/omniflo_weichen.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "omniflo_weichen" dat))
(progn (alert "Weichen-Dialog konnte nicht geladen werden.") nil)
(progn (alert (ssg-text "omni-weiche-dialog-ladefehler")) nil)
(progn
;; Dropdown befuellen
(start_list "profiltyp")
@@ -815,9 +874,8 @@
(end_list)
(set_tile "profiltyp" "0")
;; Hoehe und Drehung initialisieren
;; Hoehe initialisieren (Drehung erfolgt interaktiv nach dem Einfuegen)
(set_tile "val_hoehe" init-hoehe)
(set_tile "val_drehung" init-drehung)
;; Startwerte anzeigen
(omni:weichen-dlg-update "0")
@@ -838,16 +896,15 @@
(strcat
"(setq ergebnis (atoi (get_tile \"profiltyp\")))"
"(setq dlg-hoehe (get_tile \"val_hoehe\"))"
"(setq dlg-drehung (get_tile \"val_drehung\"))"
"(done_dialog 1)"))
(action_tile "cancel" "(done_dialog 0)")
(start_dialog)
(unload_dialog dat)
;; Gewaehlten Eintrag mit Hoehe/Drehung zurueckgeben
;; Gewaehlten Eintrag mit Hoehe zurueckgeben (drehung=nil -> interaktiv)
(if ergebnis
(list (nth ergebnis *OMNI-DLG-WEICHEN*) dlg-hoehe dlg-drehung)
(list (nth ergebnis *OMNI-DLG-WEICHEN*) dlg-hoehe nil)
nil
)
)
@@ -868,51 +925,76 @@
;; hoehe = Hoehe in mm als String (wird als HOEHE-Attribut gesetzt)
;; drehung = Drehwinkel in Grad als String (Block-Rotation)
;; Rueckgabe: Einfuegepunkt oder nil bei Abbruch
(defun omni:insert-dxf (sivasnr-str hoehe drehung / dxf-pfad omniflo-pfad pt angleDeg blockEnt attribs layer-name)
(defun omni:insert-dxf (sivasnr-str hoehe drehung / dxf-pfad omniflo-pfad angleDeg
drehung-anzeige blockEnt attribs layer-name ed pt10 zval zdelta)
(setq omniflo-pfad (getenv "DXFM_OMNIFLO"))
(if (null omniflo-pfad)
(progn
(princ "\n[OMNI] FEHLER: DXFM_OMNIFLO nicht gesetzt!")
(princ (ssg-text "omni-fehler-dxfm-omniflo"))
nil
)
(progn
(setq dxf-pfad (strcat omniflo-pfad "/" sivasnr-str ".dxf"))
(if (not (findfile dxf-pfad))
(progn
(princ (strcat "\n[OMNI] FEHLER: DXF nicht gefunden: " dxf-pfad))
(princ (ssg-textf "omni-fehler-dxf-nicht-gefunden" (list dxf-pfad)))
nil
)
(progn
(setq pt (getpoint "\nEinfuegepunkt waehlen: "))
(if (null pt)
(progn (princ "\n[OMNI] Abgebrochen.") nil)
(progn
(ssg-start "OMNI DXF Insert" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
(ssg-start "OMNI DXF Insert" '(("ATTREQ") ("ATTDIA")))
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
;; Drehwinkel aus Dialog verwenden
(setq angleDeg (if drehung (atof drehung) 0.0))
;; Absolute Z-Hoehe fuer den Einfuegepunkt bestimmen
(setq zval (if (and hoehe (/= hoehe "")) (atof hoehe) 0.0))
;; Hoehe als Z-Koordinate auf den Einfuegepunkt anwenden
(if (and hoehe (/= hoehe ""))
(setq pt (list (car pt) (cadr pt) (atof hoehe)))
(setq pt (list (car pt) (cadr pt) (if (caddr pt) (caddr pt) 0.0)))
;; Interaktives Einfuegen mit Live-Vorschau am Mauszeiger:
;; dxf-pfad -> Block aus Datei definieren/waehlen
;; 1. 'pause -> Einfuegepunkt; Objekt haengt sichtbar am Cursor und
;; verschiebt sich mit der Maus (erster Klick positioniert)
;; "" "" -> X-/Y-Massstab = 1
;; Drehung -> aus Dialog fest, sonst 2. 'pause: Objekt dreht sich
;; beim Ziehen sichtbar mit, zweiter Klick beendet
(if drehung
(progn
(setq angleDeg (atof drehung))
(setq drehung-anzeige drehung)
(command "_.INSERT" dxf-pfad pause "" "" angleDeg)
)
;; Block einfuegen mit Drehwinkel aus Dialog
(command "_.INSERT" dxf-pfad pt "" "" angleDeg)
;; INSERT vollstaendig abschliessen (Attribut-Prompts beenden)
(while (> (getvar "CMDACTIVE") 0) (command ""))
(command "_.INSERT" dxf-pfad pause "" "" pause)
)
;; INSERT vollstaendig abschliessen (bei Bedarf weitere Eingabe zulassen)
(while (> (getvar "CMDACTIVE") 0) (command pause))
(setq blockEnt (entlast))
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
(progn
(setq ed (entget blockEnt))
;; Tatsaechlich per Maus gesetzte Drehung ermitteln (interaktiv)
(if (null drehung)
(progn
(setq angleDeg (* (cdr (assoc 50 ed)) (/ 180.0 pi)))
(setq drehung-anzeige (rtos angleDeg 2 1))
)
)
;; Z-Hoehe absolut anwenden: Block (inkl. Attribute) per MOVE um
;; die Differenz zum aktuellen Einfuegepunkt-Z verschieben. Osnap
;; beim interaktiven Einfuegen kann eine abweichende Z-Lage liefern,
;; daher Differenz statt fixem Wert (vgl. GF-Z-Versatz-Bug).
;; Explizite Koordinaten unterliegen keinem Objektfang.
(setq pt10 (cdr (assoc 10 ed)))
(setq zdelta (- zval (caddr pt10)))
(if (/= zdelta 0.0)
(command "_.MOVE" blockEnt "" (list 0.0 0.0 0.0) (list 0.0 0.0 zdelta))
)
;; HOEHE und DREHUNG Attribute setzen
(ssg-attrib-set-on blockEnt
(list (cons "HOEHE" (if hoehe hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
(cons "DREHUNG" (if drehung drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))))
(cons "DREHUNG" drehung-anzeige)))
;; Layer aus LAYER-Attribut lesen und Block verschieben
(setq attribs (ssg-attrib-read blockEnt))
@@ -927,19 +1009,26 @@
)
)
;; Fallback fuer Anzeige, falls keine Drehung ermittelt wurde
(if (null drehung-anzeige)
(setq drehung-anzeige (rtos (if angleDeg angleDeg 0.0) 2 1))
)
;; Eindeutige ID zuweisen
(if (and blockEnt (atoms-family 1 '("ssg-id-generate")))
(ssg-id-generate blockEnt)
)
(princ (strcat "\n[OMNI] " sivasnr-str " eingefuegt."
" Hoehe=" (if hoehe hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))
" Drehung=" (if drehung drehung (ssg-cfg-or "omniflo" "default_drehung" "0"))
(if layer-name (strcat " Layer=" layer-name) "")))
(princ (ssg-textf "omni-dxf-eingefuegt"
(list
sivasnr-str
(if hoehe hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))
drehung-anzeige
(if layer-name (strcat " Layer=" layer-name) "")
)))
(ssg-end)
pt
)
)
;; Rueckgabe: tatsaechlicher Einfuegepunkt
(if blockEnt (cdr (assoc 10 (entget blockEnt))))
)
)
)
@@ -956,8 +1045,8 @@
(setq hoehe (cadr dlg-result))
(setq drehung (caddr dlg-result))
(setq sivasnr-str (omni:sivasid-to-str (omni:val eintrag "Sivasnr")))
(princ (strcat "\n[OMNI] Einfuegen: "
(omni:val eintrag "ProfilTyp") " (" sivasnr-str ")"))
(princ (ssg-textf "omni-einfuegen-info"
(list (omni:val eintrag "ProfilTyp") sivasnr-str)))
(omni:insert-dxf sivasnr-str hoehe drehung)
)
)
@@ -970,131 +1059,140 @@
;; --- Omniflo / Weiche 90 Grad ---
(defun c:OMNI_W90_Einfach ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 90 "Einzelweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 90 "Einzelweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_W90_Doppel ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 90 "Doppelweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 90 "Doppelweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_W90_Dreiwege ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 90 "Dreiwegeweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 90 "Dreiwegeweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
;; --- Omniflo / Weiche 45 Grad ---
(defun c:OMNI_W45_Einfach ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 45 "Einzelweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 45 "Einzelweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_W45_Doppel ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 45 "Doppelweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 45 "Doppelweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_W45_Dreiwege ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 45 "Dreiwegeweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 45 "Dreiwegeweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
;; --- Omniflo / Weichen Parallel ---
(defun c:OMNI_WP_Einfach ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 0 "Einzelweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 0 "Einzelweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_WP_Doppel ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 0 "Doppelweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 0 "Doppelweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_WP_Dreiwege ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 0 "Dreiwegeweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 0 "Dreiwegeweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
;; --- Omniflo / Weichenkoerper ---
(defun c:OMNI_WK_Einfach ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 22.5 "Einzelweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 22.5 "Einzelweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_WK_Doppel ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 22.5 "Doppelweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 22.5 "Doppelweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_WK_Dreiwege ( / dlg-result)
(setq dlg-result (omni:weichen-dialog 22.5 "Dreiwegeweiche" nil nil))
(setq dlg-result (omni:weichen-dialog 22.5 "Dreiwegeweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
;; --- Omniflo / Weichenkombinationen ---
(defun c:OMNI_WKomb_Delta ( / dlg-result)
(setq dlg-result (omni:weichen-dialog nil "Deltaweiche" nil nil))
(defun c:OMNI_WKomb_Delta_1400 ( / dlg-result)
(setq dlg-result (omni:weichen-dialog nil "Deltaweiche" nil nil 1400))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_WKomb_Delta_1600 ( / dlg-result)
(setq dlg-result (omni:weichen-dialog nil "Deltaweiche" nil nil 1600))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
(defun c:OMNI_WKomb_Star ( / dlg-result)
(setq dlg-result (omni:weichen-dialog nil "Sternweiche" nil nil))
(setq dlg-result (omni:weichen-dialog nil "Sternweiche" nil nil nil))
(if dlg-result
(omni:insert-from-entry dlg-result)
(princ "\n[WEICHE] Abgebrochen.")
(princ (ssg-text "omni-abbruch-weiche"))
)
(princ)
)
@@ -1109,7 +1207,8 @@
artinr hoehe drehung rotation
typ eintrag winkel weichentyp
dlg-result new-eintrag new-hoehe new-drehung
basePoint sivasnr-str dxf-pfad data-pfad angleDeg blockEnt)
basePoint sivasnr-str dxf-pfad data-pfad angleDeg blockEnt
layer-name)
;; Implied Selection pruefen
(setq ss (ssget "I"))
@@ -1124,7 +1223,7 @@
;; 1. Block auswaehlen (falls nicht vorselektiert)
(if (null ent)
(progn
(setq sel (entsel "\nOmniflo-Element auswaehlen: "))
(setq sel (entsel (ssg-text "omni-edit-prompt-auswahl")))
(if sel (setq ent (car sel)))
)
)
@@ -1132,7 +1231,7 @@
(setq ed (entget ent))
(if (/= (cdr (assoc 0 ed)) "INSERT")
(progn (ssg-emsg "Kein Block ausgewaehlt!") (ssg-end) (exit))
(progn (ssg-emsg (ssg-text "omni-edit-kein-block")) (ssg-end) (exit))
)
;; 2. Bestehende Attribute lesen
@@ -1188,7 +1287,7 @@
(if (null eintrag)
(progn
(ssg-emsg "Kein Omniflo-Element erkannt! (ARTINR/Blockname nicht im Katalog)")
(ssg-emsg (ssg-text "omni-edit-kein-element"))
(ssg-end)
(exit)
)
@@ -1204,25 +1303,29 @@
(progn
(setq winkel (cdr (assoc "KurvenWinkel" eintrag)))
(setq weichentyp (cdr (assoc "WeichenTyp" eintrag)))
(setq dlg-result (omni:weichen-dialog winkel weichentyp hoehe drehung))
(setq dlg-result (omni:weichen-dialog winkel weichentyp hoehe drehung nil))
)
)
(if (null dlg-result)
(progn (princ "\nAbgebrochen.") (ssg-end) (exit))
(progn (princ (ssg-text "omni-abbruch")) (ssg-end) (exit))
)
;; 5. Neuen Eintrag und Werte extrahieren
;; Drehung: Dialog liefert keine Drehung mehr (interaktiv beim Neu-Einfuegen);
;; beim Edit wird die bestehende Blockdrehung beibehalten. Quelle ist die
;; tatsaechliche Geometrie (rotation = Gruppe 50 in Grad, immer numerisch),
;; nicht das DREHUNG-Attribut (kann fehlen/kein Zahl-String sein -> (atof T)).
(setq new-eintrag (car dlg-result))
(setq new-hoehe (cadr dlg-result))
(setq new-drehung (caddr dlg-result))
(setq new-drehung (rtos rotation 2 1))
(setq sivasnr-str (omni:sivasid-to-str (omni:val new-eintrag "Sivasnr")))
;; 6. DXF-Datei pruefen
(setq dxf-pfad (strcat (getenv "DXFM_OMNIFLO") "/" sivasnr-str ".dxf"))
(if (not (findfile dxf-pfad))
(progn
(ssg-emsg (strcat "DXF nicht gefunden: " dxf-pfad))
(ssg-emsg (ssg-textf "omni-edit-dxf-nicht-gefunden" (list dxf-pfad)))
(ssg-end)
(exit)
)
@@ -1246,43 +1349,79 @@
;; Attribute setzen
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
(progn
(ssg-attrib-set-on blockEnt
(list (cons "HOEHE" (if new-hoehe new-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
(cons "DREHUNG" (if new-drehung new-drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))))
;; Layer aus LAYER-Attribut lesen und Block verschieben (wie omni:insert-dxf)
(setq attribs (ssg-attrib-read blockEnt))
(setq layer-name (cdr (assoc "LAYER" attribs)))
(if (and layer-name (> (strlen layer-name) 0))
(progn
(ssg-make-layer layer-name 7 nil)
(entmod (subst (cons 8 layer-name) (assoc 8 (entget blockEnt)) (entget blockEnt)))
(entupd blockEnt)
)
)
)
)
(princ (strcat "\n[OMNI] Element aktualisiert: " sivasnr-str
" Hoehe=" (if new-hoehe new-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))
" Drehung=" (if new-drehung new-drehung (ssg-cfg-or "omniflo" "default_drehung" "0"))))
(princ (ssg-textf "omni-edit-aktualisiert"
(list
sivasnr-str
(if new-hoehe new-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))
(if new-drehung new-drehung (ssg-cfg-or "omniflo" "default_drehung" "0"))
)))
(ssg-end)
(princ)
)
;; --- Omniflo / Anbaugruppen, Scanner, Stopper ---
;; Feste TEF-Bauteile ohne Sivas-Auswahl: Datei liegt direkt unter DXFM_OMNIFLO,
;; wird per omni:insert-dxf am gewaehlten Einfuegepunkt ohne Drehung eingefuegt.
(defun c:OMNI_STOPPER ()
(omni:insert-dxf "827062022" nil nil)
(princ)
)
(defun c:OMNI_SCANNER ()
(omni:insert-dxf "Scanner" nil nil)
(princ)
)
(defun c:OMNI_BUERSTENBREMSE ()
(omni:insert-dxf "827064041" nil nil)
(princ)
)
;; --- Omniflo / TEF Elemente ---
;; Feste TEF-Bauteile ohne Sivas-Auswahl: Datei liegt direkt unter DXFM_OMNIFLO,
;; wird per omni:insert-dxf am gewaehlten Einfuegepunkt ohne Drehung eingefuegt.
(defun c:OMNI_TEF_UmlenkR ()
(princ "\n[DUMMY] Umlenkspannst. rechts fuer TEF links")
(omni:insert-dxf "Umlenkspannst_TEF_rechts" nil nil)
(princ)
)
(defun c:OMNI_TEF_UmlenkL ()
(princ "\n[DUMMY] Umlenkspannst. links fuer TEF rechts")
(omni:insert-dxf "Umlenkspannst_TEF_links" nil nil)
(princ)
)
(defun c:OMNI_TEF_AntriebL ()
(princ "\n[DUMMY] Antriebst. links fuer TEF links")
(omni:insert-dxf "0_B10010" nil nil)
(princ)
)
(defun c:OMNI_TEF_AntriebR ()
(princ "\n[DUMMY] Antriebst. rechts fuer TEF rechts")
(omni:insert-dxf "0_B10020" nil nil)
(princ)
)
(defun c:OMNI_TEF_Gerade ()
(princ "\n[DUMMY] TEF Gerade")
(omni:insert-dxf "0_B10030" nil nil)
(princ)
)
+187 -9
View File
@@ -15,7 +15,7 @@ _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
per `ssg-ensure` initialisiert (Kern: ssg_core/lang/dbg/dialog/layer, dann
alle Feature-Module). Details: siehe `../CLAUDE.md` Abschnitt "Lademechanismus".
**Manuell laden (Notfall / Entwicklung):**
@@ -26,6 +26,28 @@ alle Feature-Module). Details: siehe `../CLAUDE.md` Abschnitt "Lademechanismus".
---
## Status: noch offene Menueintraege (im Menue ausgegraut)
Die folgenden Menueintraege rufen aktuell nur eine Dummy-Funktion auf (Meldung
`[DUMMY]`, keine Geometrie). Sie sind in `menu/SSG_LIB.mnu` mit `~` **ausgegraut**
und werden erst bei echter Implementierung wieder aktiviert. Der `~`-Marker steht
am Label-Anfang, bei Submenue-Schliessern hinter dem `<-` (`[<-~Label]`).
| Menuebereich | Eintraege | Definiert in |
| --- | --- | --- |
| ILS ▸ Zusatzmodul | BTMT-Beladung, BTMT-Entladung | `SSG_LIB_Commands.lsp` |
| ILS ▸ Foerderer | Durch TEF angetriebene Strecke; Kurven 90/60/30 links/rechts angetrieben Aussen + Innen (12) | `SSG_LIB_Commands.lsp` |
| ILS ▸ Gefaellestrecke | Kurven 90/60/30 links/rechts Gefaellestrecke (6) | `SSG_LIB_Commands.lsp` |
| Omniflo ▸ TEF Elemente | UmlenkR/L, AntriebL/R, TEF Gerade, KettenFoerderer (6) | `OmniModulInsert.lsp` |
| Omniflo ▸ Verbinder | alle `OMNI_TV_*` (18) | `OmniModulInsert.lsp` |
| Omniflo ▸ Boegen fuer Weichen | alle `OMNI_APBW_*` (14) | `OmniModulInsert.lsp` |
Aktiv (implementiert) sind u.a.: Kreisel, Eckrad, VarioFoerderer, EtageVarioFoerderer,
Gefaellestrecke, Omniflo Boegen (APB), Aluprofil-Geraden (AP), alle Weichen
(W90/W45/WP/WK/WKomb), Export (Sivas/CSV) und die Tests.
---
## Dateien
### `ssg_core.lsp` Kernbibliothek
@@ -111,6 +133,20 @@ Interne Parser-Funktionen (nicht direkt aufrufen):
---
### `ssg_lang.lsp` Sprachumschaltung (Deutsch/Englisch)
Zentrale Textverwaltung fuer benutzersichtbare Meldungen. Kern-Modul, wird direkt nach `ssg_core` geladen. Wird schrittweise auf weitere Module ausgerollt (siehe `doc/translate.md`).
| Funktion | Beschreibung |
| --- | --- |
| `ssg-text key` | Liefert Text zu `key` in `*ssg-lang*`, Fallback `de_DE`, dann Key selbst |
| `ssg-textf key werte` | Wie `ssg-text`, ersetzt Platzhalter `%1 %2 ...` durch `werte` (Liste) |
Sprache umschalten: Befehl `SSG_SPRACHE` (Menue → Konfiguration → Sprache) setzt `*ssg-lang*`
live und persistiert via `(setenv "DXFM_LANG" ...)`. Default ohne `DXFM_LANG` ist `"de_DE"`.
---
### `ssg_dbg.lsp` Debug-Logging
Dateibasiertes Debug-Log mit gepuffertem Schreiben. `dbgf`/`dbg`/`dbgmsg` puffern im Speicher, `dbgreturn` flusht auf die Platte (open/append/close).
@@ -197,9 +233,30 @@ Lädt alle Module in der richtigen Reihenfolge. Ermittelt den Pfad automatisch
### `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.
Kompatibilitäts-Wrapper, der `vf_core.lsp` lädt (Plugin-Dispatcher-Architektur; lädt seinerseits `vf_standard.lsp`, `vf_etage.lsp`, `vf_linienzug.lsp`). Parametrischer Generator für ILS Vario-Förderanlagen. Liest Block-Geometrie aus einer DWG-Bibliothek (`DXFM_BLOCKS`). Alle Konstanten (Abstände, Winkel, Skalierung) werden via `ssg-cfg-or` aus `component_defaults.json` (Sektion `vario`) gelesen.
**Befehl:** `c:FOERDERANLAGE`
**Befehl:** `c:FOERDERANLAGE` / `c:VarioFoerderer` wählt zuerst den Anlagen-Typ (Standard/Etage/Linienzug):
- **Typ „standard“ + Werteingabe:** läuft über den DCL-Dialog
[`dcl/variofoerderer.dcl`](../dcl/variofoerderer.dcl) (zwei Dialoge, `vfs-standard-dialog-ablauf`
in `vf_standard.lsp`): Dialog 1 (`vfs-dialog-eingabe-basis`) erfasst deltaL, deltaH,
Förderrichtung (Auf/Ab), Einfügehöhe, Fahrtrichtung und Seite; anschließend berechnet
`berechne-standard` die gültigen Winkel-Varianten, und Dialog 2
(`vfs-dialog-winkel-verteilung`) lässt Winkel und L_GF-Verteilung (vorne/hinten) wählen.
Startpunkt (X/Y) wird wie bei der Gefällestrecke vorher in der Zeichnung gepickt.
- **Typ „standard“ + 3D-Linie**, sowie **Typ „etage“** und **„linienzug“** bleiben
vollständig interaktiv (Kommandozeile), unverändert gegenüber dem bisherigen Ablauf.
**Bearbeiten (`c:VARIOFOERDERER_EDIT`):** Doppelklick auf einen `VF_n`-Block bzw.
Rechtsklick-Kontextmenü/`SSG_BLOCKEDIT` öffnet dieselben Dialoge, vorbelegt mit den
aktuellen Parametern, und baut die Strecke bei OK am selben Startpunkt neu auf (neue
`VF_n`-Nummer). Da `VF_n`-Blöcke auch von Etage- und Linienzug-Anlagen erzeugt werden
(deren komplexere Geometrie ein einfacher Neuaufbau zerstören würde), markiert
`vfs-xdata-schreiben` nur per Standard-Dialog erstellte Blöcke mit XDATA (App
`SSG_VF_EDIT`, Fahrtrichtung `hz`); Blöcke ohne diese Markierung weist
`c:VARIOFOERDERER_EDIT` mit einer Meldung ab, statt sie zu verändern. Winkel und L_GF1
werden aus den Sivas-Attributen (`VF_WINKEL`, `L_GF_m`) vorbelegt (Verteilung stets als
„Eigene Werte“ mit dem exakten aktuellen L_GF1).
**Wichtige interne Funktionen** (werden auch von `Gefaellestrecke.lsp` genutzt):
@@ -224,10 +281,36 @@ Setzt `VarioFoerderer.lsp` voraus (nutzt dessen `init-bibliothek`, `insert-block
**Befehl:** `c:GEFAELLESTRECKE`
Zwei Modi:
Drei Modi:
- **Modus 1:** Startpunkt + ΔL (Horizontalabstand) interaktiv abfragen
- **Modus 2:** Bestehende 3D-Linie wählen (ΔL und Winkel werden daraus berechnet)
- **Modus 1:** Startpunkt (X/Y) picken, restliche Parameter über den DCL-Dialog
[`dcl/gefaellestrecke.dcl`](../dcl/gefaellestrecke.dcl) eingeben (ΔL, Einfügehöhe Z,
Gefällewinkel, Fahrtrichtung, AUS-/EIN-Element je Winkel 30/90 und Seite links/rechts).
Die Einfügehöhe aus dem Dialog setzt die Z-Koordinate des Startpunkts.
- **Modus 2:** Bestehende 3D-Linie wählen (ΔL und Fahrtrichtung werden daraus berechnet),
restliche Parameter interaktiv über die Kommandozeile.
- **Modus 3:** Linienzug aus LINE-/ARC-Objekten; ARC-Segmente werden durch
Gefällebogen-Blöcke ersetzt, Winkel aus ΔH und Geometrie berechnet.
**Dialog-Hilfsfunktionen:** `gf-dialog-eingabe` (lädt/liest den DCL-Dialog, liefert
`(deltaL winkel hz-winkel as-seite es-seite einfuegehoehe as-winkel es-winkel)` oder `nil`
bei Abbruch) und `gf-modus12-abschluss` (gemeinsamer Abschluss für Modus 1+2: setzt die
Element-Masse per `vf-set-as-masse`/`vf-set-es-masse`, berechnet die Staustreckenlänge,
zeigt die Zusammenfassung und ruft `gefaellestrecke-einfuegen`).
Die AUS-/EIN-Element-Varianten (30/90 Grad, links/rechts) liegen als DWG-Blöcke
`AS_Element_<30|90>_<links|rechts>` bzw. `ES_Element_…` in `data/ils/2D|3D/`; ihre Maße
werden direkt aus dem Block gemessen (`vf-element-masse`), es gibt dafür keine JSON-Tabelle.
**Bearbeiten (`c:GEFAELLESTRECKE_EDIT`):** Doppelklick auf einen Gefällestrecken-Block
(`GF_n`) bzw. Rechtsklick-Kontextmenü/`SSG_BLOCKEDIT` öffnet denselben DCL-Dialog,
vorbelegt mit den aktuellen Parametern, und baut die Strecke bei OK am selben Startpunkt
neu auf. Damit Fahrtrichtung und Element-Winkel (30/90) verlustfrei rekonstruiert werden,
schreibt `gefaellestrecke-einfuegen` diese beim Erstellen als XDATA (App `SSG_GF_EDIT`,
Helfer `gf-xdata-schreiben`/`gf-xdata-lesen`) auf das `GF_n`-INSERT bewusst **nicht** in
den Sivas-Attributsatz, damit der Export unverändert bleibt. Ältere Blöcke ohne XDATA
werden aus den Attributen vorbelegt (Fahrtrichtung 0°, Element-Winkel 90° als Vorgabe).
Der Neuaufbau läuft über `gf-rebuild` (nicht-interaktiv, ohne Konsolen-Rückfrage).
---
@@ -248,6 +331,21 @@ Der Omniflo-CSV-Export (Bogen/Weiche/Gerade, inkl. Merkmale-Aufbau und Sum-Zeile
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
@@ -260,6 +358,77 @@ Testbefehle für die Python-Integration. Export-Funktionen wurden in `export.lsp
---
## Tests
Zwei Test-Ebenen, beide gesteuert über `bin\run_tests.bat` (Details und
Verzeichnisstruktur: [`../tests/README.md`](../tests/README.md)):
1. **LISP-Unit-Tests** (`tests/test_unit.lsp`) prüfen reine
Standardfunktionen direkt in AutoLISP, ohne Zeichnung.
2. **Zeichnungsbasierte Integrationstests** (`tests/test_*.lsp` +
`tests/test_*.py`) erzeugen Blöcke in BricsCAD und validieren das
Ergebnis anschließend mit pytest/ezdxf.
### LISP-Unit-Tests (`test_unit.lsp`)
Testen **reine Hilfsfunktionen** solche, die nur aus ihren Argumenten ein
Ergebnis berechnen und keine Zeichnungsdatenbank, Auswahlsätze, Dialoge oder
Blockdateien brauchen (String-, Zahl-, Vektor-, Listen- und Alist-Helfer).
Abgedeckt werden Funktionen aus `ssg_core`, `ssg_lang`, `ssg_id`, `vf_core`,
`export`, `Gefaellestrecke`, `OmniModulInsert` und `KreiselInsert`.
**Aufruf über die Kommandozeile** (startet BricsCAD headless):
```cmd
bin\run_tests.bat --lisp
```
`run_tests.bat --lisp` löscht das alte Ergebnis, startet BricsCAD mit
`tests/test_unit.scr` (lädt `ssg_load.lsp` + `test_unit.lsp`, ruft `TEST_UNIT`
auf und beendet BricsCAD), gibt danach `tests/output/unit_results.txt` aus und
liefert Exit-Code 1, wenn ein Test fehlschlägt oder kein Report entsteht.
**Aufruf direkt in BricsCAD** (SSG_LIB geladen):
```lisp
(load (strcat (getenv "DXFMAKRO") "/tests/test_unit.lsp"))
TEST_UNIT
```
**Aufbau eines Testfalls.** `test_unit.lsp` enthält ein Mini-Framework: jeder
Testfall ruft eine Funktion auf und vergleicht das Ergebnis gegen einen
erwarteten Wert. Die Assertion-Helfer zählen Treffer/Fehler mit und schreiben
je eine `PASS`/`FAIL`-Zeile:
| Helfer | Vergleich |
| --- | --- |
| `tu-eq name erwartet ist` | exakt (`equal`) Strings, Ganzzahlen, Listen davon |
| `tu-eqf name erwartet ist` | numerisch mit Toleranz `1e-6` Fliesskomma, auch verschachtelte Listen |
| `tu-true name ist` | Ergebnis ist nicht `nil` |
| `tu-nil name ist` | Ergebnis ist `nil` |
Beispiel Formatierung einer ID und ein Vektor-Kreuzprodukt:
```lisp
(tu-eq "ssg-id-format/1" "0001" (ssg-id-format 1))
(tu-eqf "vec3-cross/x-cross-y" '(0.0 0.0 1.0) (vec3-cross '(1.0 0.0 0.0) '(0.0 1.0 0.0)))
```
Die Testfälle sind in `tu-tests-<modul>`-Funktionen gruppiert; `c:TEST_UNIT`
ruft alle nacheinander auf, gibt eine Zusammenfassung
(`Gesamt / PASS / FAIL`) aus und schreibt den Report `unit_results.txt` mit
einer abschließenden Zeile `RESULT: OK` bzw. `RESULT: FAIL` (die
`run_tests.bat` auswertet).
**Neuen Testfall ergänzen:** in der passenden `tu-tests-<modul>`-Funktion eine
`tu-eq`/`tu-eqf`/`tu-true`/`tu-nil`-Zeile hinzufügen. Für ein neues Modul eine
eigene `tu-tests-<modul>`-Funktion anlegen und in `c:TEST_UNIT` aufrufen.
Getestet werden sollten nur Funktionen ohne Zeichnungs-/Dialog-Umfeld alles
mit `ssget`/`entget`/`entmake`/`command`/`vla-*`/`entsel`/DCL gehört in die
zeichnungsbasierten Integrationstests.
---
### `KreiselInsert.lsp` ILS Kreisel und Eckrad
AutoLISP-Implementierung fuer ILS Kreisel und Eckrad. Enthaelt alle Befehle fuer Einfuegen, Verbinden, Neuzeichnen und Bearbeiten.
@@ -289,9 +458,9 @@ AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbind
| 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) |
| TEF ⚠️ | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade`, `OMNI_KettenFoerderer` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) |
| Transferwagen ⚠️ | `OMNI_TV_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) |
| Bogenweichen ⚠️ | `OMNI_APBW_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) |
| Bearbeiten | `OMNI_EDIT` | Omniflo-Block selektieren und Attribute bearbeiten |
---
@@ -299,6 +468,8 @@ AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbind
### `SSG_LIB_Commands.lsp` Dummy-Befehle und SSG_BLOCKEDIT
Platzhalter-Definitionen fuer noch nicht implementierte Menueintraege. Gibt beim Aufruf eine Meldung aus.
Alle zugehoerigen Menueintraege sind in `menu/SSG_LIB.mnu` mit `~` ausgegraut (siehe
Abschnitt ["Status: noch offene Menueintraege"](#status-noch-offene-menueintraege-im-menue-ausgegraut)).
Registrierte Dummy-Befehle:
@@ -311,6 +482,13 @@ Registrierte Dummy-Befehle:
> `FOERDERANLAGE` ist nicht hier definiert dieser Befehl ist in `VarioFoerderer.lsp` implementiert.
**Konfigurationsbefehle** (Menue → Konfiguration):
| Befehl | Beschreibung |
| --- | --- |
| `SSG_DIM_SWITCH` | Schaltet zwischen 2D/3D-Bloecken um (setzt `DXFM_DIM`, `DXFM_BLOCKS`, `DXFM_OMNIFLO`) |
| `SSG_SPRACHE` | Oeffnet Dialog `sprache.dcl`, setzt `*ssg-lang*` und persistiert via `DXFM_LANG` (siehe [`ssg_lang.lsp`](#ssg_langlsp--sprachumschaltung-deutschenglisch)) |
**SSG_BLOCKEDIT** Doppelklick/Kontextmenue-Dispatcher:
Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearbeitungsbefehl auf:
+105 -10
View File
@@ -15,6 +15,55 @@
(princ)
)
;; --- ILS / Zusatzmodul: Sensoren (Scanner / Separator) einfuegen ---
;; Ermittelt den Pfad zu einer Sensor-Blockdatei. Die Sensor-Bloecke
;; werden fest aus data/ils/3D geladen (unabhaengig von der
;; 2D/3D-Umschaltung).
(defun ils-sensor-pfad (fname / p)
(setq p (strcat (getenv "DXFMAKRO") "\\data\\ils\\3D\\" fname ".dwg"))
(if (findfile p) p nil)
)
;; Fuegt einen Sensor-Block wiederholt ein, bis der Benutzer mit
;; ENTER oder ESC abbricht. Rotation je Einfuegung interaktiv.
(defun ils-insert-sensor (fname / pfad pt oldattreq n res)
(setq pfad (ils-sensor-pfad fname))
(if (null pfad)
(princ (strcat "\n>>> FEHLER: Blockdatei '" fname ".dwg' nicht gefunden."
" (in data/ils/3D pruefen)"))
(progn
(setq oldattreq (getvar "ATTREQ"))
(setvar "ATTREQ" 0)
(setq n 0)
;; Punkt abfragen; ENTER liefert nil, ESC einen abgefangenen Fehler -
;; beides beendet die Schleife sauber (ATTREQ wird wiederhergestellt).
(while
(progn
(setq res (vl-catch-all-apply
'getpoint
(list (strcat "\nEinfuegepunkt fuer " fname " [ENTER=Ende]: "))))
(and (not (vl-catch-all-error-p res)) res)
)
(setq pt res)
(command "_.INSERT" pfad pt "" "" pause)
(setq n (1+ n))
)
(setvar "ATTREQ" oldattreq)
(princ (strcat "\n>>> " (itoa n) " x " fname " eingefuegt."))
)
)
(princ)
)
(defun c:ILS_SCANNER_INSERT ()
(ils-insert-sensor "Scanner")
)
(defun c:ILS_SEPARATOR_INSERT ()
(ils-insert-sensor "Separator_SP")
)
;; --- ILS / Foerderer ---
(defun c:ILS_TEF_Strecke ()
(princ "\n[DUMMY] ILS_TEF_Strecke aufgerufen")
@@ -132,9 +181,41 @@
(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-textf "dim-switch-modus" (list dim-neu)))
(princ (ssg-textf "dim-switch-blocks" (list (getenv "DXFM_BLOCKS"))))
(princ (ssg-textf "dim-switch-omniflo" (list (getenv "DXFM_OMNIFLO"))))
(princ)
)
;; ============================================================
;; SSG_SPRACHE - Sprache umschalten (Deutsch/Englisch)
;; Setzt *ssg-lang* live und persistiert ueber DXFM_LANG
;; ============================================================
(defun ssg-sprache-init ( / idx)
(start_list "sprache")
(add_list "Deutsch")
(add_list "Englisch")
(end_list)
(setq idx (if (= *ssg-lang* "en_GB") "1" "0"))
(set_tile "sprache" idx)
)
(defun ssg-sprache-accept ( / idx neu)
(setq idx (get_tile "sprache"))
(setq neu (if (= idx "1") "en_GB" "de_DE"))
(setq *ssg-lang* neu)
(setenv "DXFM_LANG" neu)
)
(defun c:SSG_SPRACHE ()
(ssg-dialog-run
(strcat (getenv "DXFM_DCL") "/sprache.dcl")
"sprache"
'ssg-sprache-init
'ssg-sprache-accept
)
(princ (ssg-textf "sprache-gewechselt" (list *ssg-lang*)))
(princ)
)
@@ -149,13 +230,13 @@
(setq ss (ssget "I"))
(if (or (null ss) (/= (sslength ss) 1))
(progn
(princ "\nBlock auswaehlen: ")
(princ (ssg-text "cmd-block-auswaehlen"))
(setq ss (ssget ":S" '((0 . "INSERT"))))
)
)
(if (null ss)
(progn
(princ "\nKein Block ausgewaehlt.")
(princ (ssg-text "cmd-kein-block-ausgewaehlt"))
(princ)
(exit)
)
@@ -166,7 +247,7 @@
(if (/= (cdr (assoc 0 ed)) "INSERT")
(progn
(princ "\nKein Block ausgewaehlt.")
(princ (ssg-text "cmd-kein-block-ausgewaehlt"))
(princ)
(exit)
)
@@ -177,16 +258,30 @@
(cond
;; Kreisel-Bloecke -> KreiselEdit
((wcmatch bname "KREISEL_*")
(princ (strcat "\nKreisel bearbeiten: " bname))
(princ (ssg-textf "cmd-kreisel-bearbeiten" (list bname)))
(c:KreiselEdit)
)
;; Eckrad-Bloecke -> BEDIT (kein eigener Edit-Dialog in LISP)
((wcmatch bname "ECKRAD_*")
(princ (strcat "\nEckrad bearbeiten: " bname))
(princ (ssg-textf "cmd-eckrad-bearbeiten" (list bname)))
(command "_.BEDIT" bname)
)
;; Gefaellestrecke-Bloecke (GF_n) -> GEFAELLESTRECKE_EDIT (DCL-Dialog)
((wcmatch bname "GF_*")
(princ (ssg-textf "cmd-gefaelle-bearbeiten" (list bname)))
(c:GEFAELLESTRECKE_EDIT)
)
;; VarioFoerderer-Bloecke (VF_n) -> VARIOFOERDERER_EDIT (DCL-Dialog);
;; weist Bloecke ohne SSG_VF_EDIT-XDATA (Etage/Linienzug/Altbestand)
;; intern selbst ab, siehe c:VARIOFOERDERER_EDIT in vf_standard.lsp.
((wcmatch bname "VF_*")
(princ (ssg-textf "cmd-variofoerderer-bearbeiten" (list bname)))
(c:VARIOFOERDERER_EDIT)
)
;; Omniflo-Bloecke -> OMNI_EDIT
;; Erkennung: TEILEART-Attribut vorhanden, AP110-Blockname oder rein numerisch
((progn
@@ -198,13 +293,13 @@
(wcmatch bname "#*")
)
)
(princ (strcat "\nOmniflo Element bearbeiten: " bname))
(princ (ssg-textf "cmd-omniflo-bearbeiten" (list bname)))
(c:OMNI_EDIT)
)
;; Unbekannter Blocktyp -> natives EATTEDIT (Attribut-Editor)
(t
(princ (strcat "\nAttribute bearbeiten: " bname))
(princ (ssg-textf "cmd-attribute-bearbeiten" (list bname)))
(command "_.EATTEDIT")
)
)
+210
View File
@@ -0,0 +1,210 @@
;; ============================================================
;; TEFInsert.lsp - TEF-Geradenstuecke entlang einer Linie
;;
;; Zeichnet eine Linie zwischen zwei vom Benutzer gewaehlten Punkten
;; und reiht darauf 1000 mm lange TEF-Geradenelemente
;; (data/omniflo/<DIM>/0_B10030.dxf, $INSBASE=Ursprung=Anfang des
;; Elements, Ende bei lokal X=1000) aneinander.
;;
;; Ist die Linienlaenge kein exaktes Vielfaches von 1000 mm, wird fuer
;; das letzte Stueck ein zusaetzliches Element eingefuegt, das auf der
;; Linie zurueckverschoben platziert wird (ueberlappt das vorletzte
;; Element), sodass der Foerderer exakt am Linienende endet - statt
;; einer Luecke oder eines abgeschnittenen Elements.
;;
;; Die Linie darf geneigt sein (3D): Start-/Endpunkt koennen
;; unterschiedliche Z-Werte haben, die Elemente werden dann analog zu
;; vf_core.lsp (Rz(hz)*Ry(winkel)-Rotation, winkel positiv=abwaerts)
;; gekippt eingefuegt.
;;
;; Befehl: TEF_FOERDERER_LINIE
;; ============================================================
(vl-load-com)
(if (null doc) (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))))
(if (null modelspace) (setq modelspace (vla-get-ModelSpace doc)))
;; Elementlaenge (mm) von 0_B10030.dxf (siehe Header-Kommentar oben)
(if (null *tefl-elementlaenge*) (setq *tefl-elementlaenge* 1000.0))
;; Toleranz (mm): Restlaenge unterhalb dieses Werts gilt als "exaktes
;; Vielfaches der Elementlaenge" -> kein Zusatzelement noetig.
(if (null *tefl-toleranz*) (setq *tefl-toleranz* 0.5))
;; Dateiname (ohne .dxf) des TEF-Geradenelements in DXFM_OMNIFLO
(if (null *tefl-blockname*) (setq *tefl-blockname* "0_B10030"))
;; ------------------------------------------------------------
;; Pfad zur Element-DXF ermitteln (DXFM_OMNIFLO, wie omni:insert-dxf
;; in OmniModulInsert.lsp).
;; ------------------------------------------------------------
(defun tefl-dxf-pfad ( / omniflo-pfad)
(setq omniflo-pfad (getenv "DXFM_OMNIFLO"))
(if omniflo-pfad
(strcat (vl-string-translate "\\" "/" omniflo-pfad) "/" *tefl-blockname* ".dxf")
)
)
;; ------------------------------------------------------------
;; Element-DXF einmalig als Block registrieren (Analog zu
;; ensure-block-loaded in vf_core.lsp, aber fuer eine externe .dxf statt
;; .dwg): einmal am Ursprung einfuegen und wieder loeschen, damit die
;; Datei als Block-Tabelleneintrag *tefl-blockname* existiert. Danach
;; kann jede weitere Einfuegung ueber vla-InsertBlock + vla-TransformBy
;; mit voller 3D-Rotation erfolgen (das kann die reine command-Zeilen-
;; INSERT nicht leisten - die dreht nur um die Z-Achse).
;; ------------------------------------------------------------
(defun tefl-ensure-block-loaded (dxf-pfad / tmpEnt)
(if (not (tblsearch "BLOCK" *tefl-blockname*))
(progn
(command "_.INSERT" dxf-pfad (list 0.0 0.0 0.0) 1 1 0)
(while (> (getvar "CMDACTIVE") 0) (command ""))
(setq tmpEnt (entlast))
(if (and tmpEnt (= (cdr (assoc 0 (entget tmpEnt))) "INSERT"))
(command "_.ERASE" tmpEnt "")
)
)
)
(tblsearch "BLOCK" *tefl-blockname*)
)
;; ------------------------------------------------------------
;; Ein Element an Position 's' (mm ab Startpunkt) entlang der
;; Fahrtrichtung einfuegen.
;; start : Startpunkt der Linie (3D)
;; richtung-einheit : Einheitsvektor der Fahrtrichtung (3D)
;; hz / winkel : Fahrtrichtung in Grad (Rz(hz)*Ry(winkel)-Konvention
;; wie hz-winkel->xu/frame->hz-winkel in vf_core.lsp)
;;
;; Attribute: vla-InsertBlock legt fuer ein Block mit ATTDEFs automatisch
;; ATTRIB-Entities mit den Vorgabewerten aus der Quell-DXF an (wie beim
;; command-Zeilen-INSERT mit ATTREQ=0). Analog zu omni:insert-dxf in
;; OmniModulInsert.lsp wird danach nur das LAYER-Attribut ausgelesen und
;; der Block auf diesen Layer verschoben - alle anderen Attribute
;; (ARTINR, BESCHR, MENGE, POSITION, DETAILS, ...) behalten den aus der
;; Quell-DXF uebernommenen Vorgabewert.
;; ------------------------------------------------------------
(defun tefl-insert-element (start richtung-einheit s hz winkel /
rad-h rad-v chv shv cvv svv matrix block-obj blockEnt
pt attribs layer-name)
(setq pt (list (+ (car start) (* s (car richtung-einheit)))
(+ (cadr start) (* s (cadr richtung-einheit)))
(+ (caddr start) (* s (caddr richtung-einheit)))))
(setq rad-h (* (float hz) (/ pi 180.0)))
(setq rad-v (* (float winkel) (/ pi 180.0)))
(setq chv (cos rad-h) shv (sin rad-h) cvv (cos rad-v) svv (sin rad-v))
(setq block-obj (vla-InsertBlock modelspace (vlax-3D-point '(0.0 0.0 0.0))
*tefl-blockname* 1.0 1.0 1.0 0))
(setq matrix (list
(list (* chv cvv) (- shv) (* chv svv) 0)
(list (* shv cvv) chv (* shv svv) 0)
(list (- svv) 0 cvv 0)
(list 0 0 0 1)))
(vla-TransformBy block-obj (vlax-tmatrix matrix))
(vla-Move block-obj (vlax-3D-point '(0.0 0.0 0.0)) (vlax-3D-point pt))
;; LAYER-Attribut auslesen und Block auf diesen Layer verschieben
(setq blockEnt (vlax-vla-object->ename block-obj))
(setq attribs (ssg-attrib-read blockEnt))
(setq layer-name (cdr (assoc "LAYER" attribs)))
(if (and layer-name (> (strlen layer-name) 0))
(progn
(ssg-make-layer layer-name 7 nil)
(entmod (subst (cons 8 layer-name) (assoc 8 (entget blockEnt)) (entget blockEnt)))
(entupd blockEnt)
)
)
;; Eindeutige ID zuweisen, falls das Block-Schema ein ID-Attribut fuehrt
;; (bei 0_B10030 aktuell nicht der Fall - dann folgenlos, wie in
;; omni:insert-dxf).
(if (atoms-family 1 '("ssg-id-generate"))
(ssg-id-generate blockEnt)
)
block-obj
)
;; ------------------------------------------------------------
;; Hauptbefehl: Start-/Endpunkt abfragen, Linie zeichnen, TEF-Geraden-
;; elemente entlang der Linie aneinanderreihen.
;; ------------------------------------------------------------
(defun c:TEF_FOERDERER_LINIE ( / dxf-pfad p1 p2 dx dy dz laenge horiz hz winkel
richtung-einheit anzahl-voll rest i s)
(setq dxf-pfad (tefl-dxf-pfad))
(cond
((null dxf-pfad)
(princ (ssg-text "tefl-fehler-dxfm-omniflo")))
((not (findfile dxf-pfad))
(princ (ssg-textf "tefl-fehler-dxf-nicht-gefunden" (list dxf-pfad))))
(t
(setq p1 (getpoint (ssg-text "tefl-prompt-startpunkt")))
(if (null p1)
(princ (ssg-text "tefl-abgebrochen"))
(progn
(setq p2 (getpoint p1 (ssg-text "tefl-prompt-endpunkt")))
(if (null p2)
(princ (ssg-text "tefl-abgebrochen"))
(progn
(setq dx (- (car p2) (car p1))
dy (- (cadr p2) (cadr p1))
dz (- (caddr p2) (caddr p1)))
(setq laenge (sqrt (+ (* dx dx) (* dy dy) (* dz dz))))
(if (< laenge *tefl-toleranz*)
(princ (ssg-text "tefl-fehler-laenge-null"))
(progn
(ssg-start "TEF Foerderer Linie" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
(if (not (tefl-ensure-block-loaded dxf-pfad))
(progn
(princ (ssg-textf "tefl-fehler-dxf-nicht-gefunden" (list dxf-pfad)))
(ssg-end)
)
(progn
;; Fahrtrichtung als Einheitsvektor + hz/winkel
(setq richtung-einheit
(list (/ dx laenge) (/ dy laenge) (/ dz laenge)))
(setq horiz (sqrt (+ (* dx dx) (* dy dy))))
(setq hz (* (atan dy dx) (/ 180.0 pi)))
(setq winkel (* (atan (- dz) horiz) (/ 180.0 pi)))
;; Volle Elemente ab dem Startpunkt aneinanderreihen
(setq anzahl-voll
(fix (/ (+ laenge *tefl-toleranz*) *tefl-elementlaenge*)))
(setq i 0)
(repeat anzahl-voll
(tefl-insert-element p1 richtung-einheit
(* i *tefl-elementlaenge*) hz winkel)
(setq i (1+ i))
)
;; Restlaenge: Zusatzelement zurueckverschoben einfuegen,
;; damit der Foerderer exakt am Linienende (p2) endet.
(setq rest (- laenge (* anzahl-voll *tefl-elementlaenge*)))
(if (> rest *tefl-toleranz*)
(progn
(setq s (- laenge *tefl-elementlaenge*))
(tefl-insert-element p1 richtung-einheit s hz winkel)
(setq anzahl-voll (1+ anzahl-voll))
)
)
(princ (ssg-textf "tefl-fertig"
(list (itoa anzahl-voll) (rtos laenge 2 0))))
(ssg-end)
)
)
)
)
)
)
)
)
)
)
(princ)
)
(princ "\nTEFInsert.lsp geladen. Befehl: TEF_FOERDERER_LINIE")
(princ)
+1 -1
View File
@@ -17,5 +17,5 @@
)
(if *vf-core-datei*
(load *vf-core-datei*)
(princ "\n[VarioFoerderer] WARNUNG: vf_core.lsp nicht gefunden - Befehle nicht verfuegbar.")
(princ (ssg-text "vfstart-core-nicht-gefunden"))
)
+272
View File
@@ -0,0 +1,272 @@
;; ============================================================
;; addattribute.lisp
;; Synchronisiert ATTDEF-Attribute in den ILS-Block-DWGs mit den
;; Werten aus allocations.json.
;;
;; Es wird zwischen data/ils/2D und data/ils/3D unterschieden: nach
;; Auswahl des Verzeichnisses wird die dortige allocations.json
;; gelesen (data/ils/<2D|3D>/allocations.json) und anschliessend
;; werden ausschliesslich die DWGs in genau diesem Verzeichnis
;; bearbeitet.
;;
;; Ablauf je JSON-Eintrag "Blockname": {"TAG": "Wert", ...}:
;; - <Blockname>.dwg im selben Verzeichnis wie die JSON oeffnen
;; - je Attribut (TAG/Wert):
;; - ATTDEF mit diesem Tag existiert nicht -> neu anlegen,
;; Vorgabewert = JSON-Wert (auch wenn dieser leer ist)
;; - ATTDEF existiert, ist aber leer -> mit JSON-Wert befuellen
;; - ATTDEF existiert und ist bereits befuellt
;; -> NUR ueberschreiben,
;; wenn der JSON-Wert NICHT leer ("") ist. Ein leerer JSON-Wert
;; loescht also nie einen bereits vorhandenen Wert.
;; - DWG nur dann speichern, wenn sich mindestens ein Attributwert
;; geaendert hat oder neu angelegt wurde (bessere Nachverfolgbarkeit
;; im Versionsvergleich). Falls durch dieses Skript geoeffnet, wird
;; die DWG anschliessend wieder geschlossen. War die DWG schon vorher
;; offen, bleibt sie offen.
;;
;; Voraussetzung: DXFM_DATA ist gesetzt (siehe bin/setenv.bat).
;;
;; Aufruf in BricsCAD:
;; (load "C:/.../data/ils/2D/addattribute.lisp")
;; ILS_ATTR_SYNC
;; ============================================================
(vl-load-com)
;; ssg_core.lsp (JSON-Parser ssg-cfg-parse-nested) sicherstellen,
;; falls das Menue/die Kern-Module noch nicht geladen wurden.
(if (not (car (atoms-family 1 '("SSG-CFG-PARSE-NESTED"))))
(if (getenv "DXFM_LISP")
(load (strcat (vl-string-translate "\\" "/" (getenv "DXFM_LISP")) "/ssg_core.lsp"))
)
)
;; ------------------------------------------------------------
;; Bereits offenes Dokument mit gegebenem Pfad suchen (oder nil)
;; ------------------------------------------------------------
(defun iad-find-open-doc (dwg-pfad / docs anzahl i doc full treffer)
(setq docs (vla-get-Documents (vlax-get-acad-object))
anzahl (vla-get-Count docs)
i 0
treffer nil
dwg-pfad (strcase (vl-string-translate "\\" "/" dwg-pfad))
)
(while (and (< i anzahl) (not treffer))
(setq doc (vla-item docs i))
(setq full (strcase (vl-string-translate "\\" "/" (vla-get-FullName doc))))
(if (= full dwg-pfad) (setq treffer doc))
(setq i (1+ i))
)
treffer
)
;; ------------------------------------------------------------
;; Ein einzelnes ATTDEF aktualisieren (Ueberschreib-Regel)
;; Rueckgabe: t, wenn der Wert tatsaechlich geaendert wurde
;; ------------------------------------------------------------
(defun iad-update-attdef (ent jsonwert / ed altwert)
(setq ed (entget ent)
altwert (cdr (assoc 1 ed))
)
(if (null altwert) (setq altwert ""))
(cond
((equal altwert jsonwert)
(princ (strcat "\n = " (cdr (assoc 2 ed)) " = '" altwert "' (unveraendert)"))
nil
)
((or (= (strlen altwert) 0) (> (strlen jsonwert) 0))
(entmod (subst (cons 1 jsonwert) (assoc 1 ed) ed))
(princ (strcat "\n - " (cdr (assoc 2 ed)) " = '" jsonwert "'"))
t
)
(t
(princ (strcat "\n = " (cdr (assoc 2 ed)) " = '" altwert "' (unveraendert, JSON-Wert leer)"))
nil
)
)
)
;; ------------------------------------------------------------
;; Neues (unsichtbares) ATTDEF anlegen
;; ------------------------------------------------------------
(defun iad-create-attdef (tag wert ypos texthoehe layer)
(entmake (list
'(0 . "ATTDEF")
(cons 8 layer)
(cons 10 (list 0.0 ypos 0.0))
(cons 40 texthoehe)
(cons 1 wert)
(cons 3 tag)
(cons 2 tag)
'(70 . 1)
))
(princ (strcat "\n + " tag " = '" wert "' (neu angelegt)"))
)
;; ------------------------------------------------------------
;; Alle Attribute eines JSON-Eintrags im aktiven Dokument abgleichen
;; attribs = (("TAG" . "Wert") ...)
;; Rueckgabe: t, wenn mindestens ein Attribut geaendert/neu angelegt wurde
;; ------------------------------------------------------------
(defun iad-sync-attribs-in-current-doc (attribs / texthoehe layer ss anzahl i ent ed
tag wert pt vorhandene ypos gefunden paar geaendert)
(setq texthoehe (ssg-cfg-or "ils_attribut" "texthoehe" 50.0)
layer (ssg-cfg-or "ils_attribut" "layer" "0")
vorhandene nil
ypos 0.0
geaendert nil
)
;; Vorhandene ATTDEFs einsammeln (Tag -> Entity) und tiefsten Y-Wert merken
(setq ss (ssget "X" '((0 . "ATTDEF"))))
(if ss
(progn
(setq i 0 anzahl (sslength ss))
(while (< i anzahl)
(setq ent (ssname ss i)
ed (entget ent)
tag (cdr (assoc 2 ed))
pt (cdr (assoc 10 ed))
)
(setq vorhandene (cons (cons tag ent) vorhandene))
(if (and pt (< (cadr pt) ypos)) (setq ypos (cadr pt)))
(setq i (1+ i))
)
)
)
(setq ypos (- ypos (* texthoehe 2.0)))
(foreach paar attribs
(setq tag (car paar)
wert (cdr paar)
)
(if (null wert) (setq wert ""))
(setq gefunden (cdr (assoc tag vorhandene)))
(if gefunden
(if (iad-update-attdef gefunden wert) (setq geaendert t))
(progn
(iad-create-attdef tag wert ypos texthoehe layer)
(setq ypos (- ypos (* texthoehe 2.0)))
(setq geaendert t)
)
)
)
geaendert
)
;; ------------------------------------------------------------
;; Hauptbefehl
;; ------------------------------------------------------------
(defun c:ILS_ATTR_SYNC ( / data-dir json-pfad dwg-dir dwg-unterverz daten orig-doc anzahl-aktualisiert
anzahl-unveraendert anzahl-fehler anzahl-fehlt eintrag blockname attribs
dwg-pfad bereits-offen fehler fehlende-liste name)
(setq data-dir (getenv "DXFM_DATA"))
(if (not data-dir)
(progn
(alert "DXFM_DATA ist nicht gesetzt.\nBitte zuerst bin/setenv.bat ausfuehren.")
(exit)
)
)
(setq data-dir (vl-string-translate "\\" "/" data-dir))
(initget "2D 3D")
(setq dwg-unterverz (getkword "\nDWG-Verzeichnis waehlen [2D/3D] <2D>: "))
(if (not dwg-unterverz) (setq dwg-unterverz "2D"))
(setq dwg-dir (strcat data-dir "/ils/" dwg-unterverz)
json-pfad (strcat dwg-dir "/allocations.json")
)
(if (not (findfile json-pfad))
(progn
(alert (strcat "JSON nicht gefunden:\n" json-pfad))
(exit)
)
)
(setq daten (ssg-cfg-parse-nested (ssg-read-file-lines json-pfad)))
(if (not daten)
(progn
(alert "JSON konnte nicht gelesen werden oder ist leer.")
(exit)
)
)
(setq orig-doc (vla-get-ActiveDocument (vlax-get-acad-object))
anzahl-aktualisiert 0
anzahl-unveraendert 0
anzahl-fehler 0
anzahl-fehlt 0
fehlende-liste nil
)
(foreach eintrag daten
(setq blockname (car eintrag)
attribs (cdr eintrag)
dwg-pfad (strcat dwg-dir "/" blockname ".dwg")
)
(if (findfile dwg-pfad)
(progn
(princ (strcat "\n[ATTR-SYNC] Bearbeite " blockname ".dwg ..."))
(setq bereits-offen (iad-find-open-doc dwg-pfad))
(setq fehler
(vl-catch-all-apply
(function
(lambda ( / geaendert)
(if bereits-offen
(progn
(vlax-put-property (vlax-get-acad-object) 'ActiveDocument bereits-offen)
(setq geaendert (iad-sync-attribs-in-current-doc attribs))
)
(progn
(command "_.OPEN" dwg-pfad)
(setq geaendert (iad-sync-attribs-in-current-doc attribs))
)
)
(if geaendert
(command "_.QSAVE")
(princ "\n (keine Aenderungen, DWG nicht gespeichert)")
)
(if (not bereits-offen) (command "_.CLOSE"))
geaendert
)
)
nil
)
)
(if (vl-catch-all-error-p fehler)
(progn
(princ (strcat "\n[ATTR-SYNC] FEHLER bei " blockname ".dwg: "
(vl-catch-all-error-message fehler)))
(setq anzahl-fehler (1+ anzahl-fehler))
)
(if fehler
(setq anzahl-aktualisiert (1+ anzahl-aktualisiert))
(setq anzahl-unveraendert (1+ anzahl-unveraendert))
)
)
)
(progn
(setq anzahl-fehlt (1+ anzahl-fehlt))
(setq fehlende-liste (cons (strcat blockname ".dwg") fehlende-liste))
)
)
)
(vlax-put-property (vlax-get-acad-object) 'ActiveDocument orig-doc)
(princ (strcat "\n[ATTR-SYNC] Fertig: " (itoa anzahl-aktualisiert) " DWG(s) aktualisiert, "
(itoa anzahl-unveraendert) " ueberprueft (keine Aenderungen), "
(itoa anzahl-fehler) " Fehler, "
(itoa anzahl-fehlt) " nicht gefunden."))
(if fehlende-liste
(progn
(princ "\n[ATTR-SYNC] WARNUNG: DWG nicht gefunden fuer:")
(foreach name (reverse fehlende-liste)
(princ (strcat "\n - " name))
)
)
)
(princ)
)
(princ "\naddattribute.lisp geladen. Befehl: ILS_ATTR_SYNC")
(princ)
+452
View File
@@ -0,0 +1,452 @@
;;; ============================================================
;;; check_hoehen.lsp - Hoehen-Check (PHASE 1-3)
;;; ------------------------------------------------------------
;;; Phase 1 - messen & schreiben:
;;; Kreisel : Z des Einfuegepunkts -> HOEHE
;;; VF/GF : KS_EIN.Z (aus AS_Element) -> HOEHE_VON_mm
;;; KS_AUS.Z (aus ES_Element) -> HOEHE_BIS_mm
;;; MONTAGEHOEHE_m:
;;; Kreisel = HOEHE / 1000
;;; Gefaellestrecke = HOEHE_VON_mm / 1000
;;; VarioFoerderer = (HOEHE_VON_mm + HOEHE_BIS_mm) / 2 / 1000
;;;
;;; Phase 2 - 0-/Negativ-Pruefung (ungueltig = Wert <= 0 oder nicht
;;; messbar):
;;; - Hoehe eingeben -> Block in Z verschieben, Attribute neu.
;;; - ENTER -> Markierungskreis (Layer *ch-mark-layer*),
;;; Block spaeter manuell anpassen.
;;;
;;; Phase 3 - Buehne: liegt die rohe Montagehoehe ueber
;;; *ch-buehne-schwelle-m* (Default 2,0 m), wird pro Block gefragt,
;;; ob eine Buehne vorhanden ist; deren Hoehe wird abgezogen
;;; (MONTAGEHOEHE_m = roh - Buehne).
;;;
;;; PHASE 1-3 bewusst OHNE: QSAVE (Testmodus, UNDO moeglich).
;;;
;;; Aufruf: HOEHEN_CHECK
;;; Nutzt die KS-Extraktion aus vf_core (extract-ks-from-block-raw).
;;; ============================================================
(vl-load-com)
;; Blockname-Muster (Grossschreibung) der KS-tragenden Teilbloecke.
(setq *ch-as-pattern* "AS_ELEMENT*") ;; enthaelt KS_EIN (Hoehe von)
(setq *ch-es-pattern* "ES_ELEMENT*") ;; enthaelt KS_AUS (Hoehe bis)
;; Markierung ungueltiger Hoehen: Kreis auf eigenem Layer.
(setq *ch-mark-layer* "S_HOEHE_PRUEFEN")
(setq *ch-mark-color* 1) ;; 1 = Rot
(if (null *ch-mark-radius-factor*) (setq *ch-mark-radius-factor* 1.1))
(if (null *ch-mark-radius-min*) (setq *ch-mark-radius-min* 1000.0))
;; Schwelle (m): ab dieser Montagehoehe wird pro Block nach einer
;; Buehne gefragt (typische Anlagenhoehe ~2 m; darueber liegt die
;; Anlage vermutlich auf einer Buehne).
(if (null *ch-buehne-schwelle-m*) (setq *ch-buehne-schwelle-m* 2.0))
;;; ------------------------------------------------------------
;;; vf_core-KS-Helfer sicherstellen (extract-ks-from-block-raw).
;;; ------------------------------------------------------------
(defun ch-ensure-vfcore ( / p)
(if (null (car (atoms-family 1 '("EXTRACT-KS-FROM-BLOCK-RAW"))))
(cond
((car (atoms-family 1 '("SSG-ENSURE")))
(vl-catch-all-apply '(lambda () (ssg-ensure "VarioFoerderer"))))
((getenv "DXFM_LISP")
(setq p (strcat (vl-string-translate "\\" "/" (getenv "DXFM_LISP")) "/vf_core.lsp"))
(if (findfile p) (vl-catch-all-apply 'load (list p))))
)
)
(if (car (atoms-family 1 '("EXTRACT-KS-FROM-BLOCK-RAW"))) t nil)
)
;;; ------------------------------------------------------------
;;; Attributwert an einem INSERT setzen (Tag ohne Gross/Klein).
;;; Nur wenn der Block Attribute fuehrt (66=1). Rueckgabe: T/nil.
;;; ------------------------------------------------------------
(defun ch-set-att (ins tag val / e ed done ok)
(setq done nil ok nil)
(if (= (cdr (assoc 66 (entget ins))) 1)
(progn
(setq e (entnext ins))
(while (and e (not done))
(setq ed (entget e))
(cond
((= (cdr (assoc 0 ed)) "ATTRIB")
(if (= (strcase (cdr (assoc 2 ed))) (strcase tag))
(progn
(entmod (subst (cons 1 val) (assoc 1 ed) ed))
(entupd e)
(setq ok t))))
((= (cdr (assoc 0 ed)) "SEQEND") (setq done t))
)
(setq e (entnext e))
)
)
)
ok
)
;;; ------------------------------------------------------------
;;; Attributwert (String) an einem INSERT lesen. "" wenn fehlend.
;;; ------------------------------------------------------------
(defun ch-get-att-str (ins tag / e ed done val)
(setq done nil val "")
(if (= (cdr (assoc 66 (entget ins))) 1)
(progn
(setq e (entnext ins))
(while (and e (not done))
(setq ed (entget e))
(cond
((= (cdr (assoc 0 ed)) "ATTRIB")
(if (= (strcase (cdr (assoc 2 ed))) (strcase tag))
(progn (setq val (cdr (assoc 1 ed))) (setq done t))))
((= (cdr (assoc 0 ed)) "SEQEND") (setq done t))
)
(setq e (entnext e))
)
)
)
val
)
;;; ------------------------------------------------------------
;;; Sortier-Vergleich fuer Kandidaten (idnum ename idx).
;;; Primaer nach ID-Nummer, sekundaer nach Fund-Index (verhindert,
;;; dass vl-sort Eintraege mit gleicher ID verwirft).
;;; ------------------------------------------------------------
(defun ch-id< (a b)
(if (= (car a) (car b)) (< (caddr a) (caddr b)) (< (car a) (car b)))
)
;;; ------------------------------------------------------------
;;; Z-Koordinate des KS-Ursprungs aus einem ks-data-Satz holen.
;;; ------------------------------------------------------------
(defun ch-ks-z (ksdata ksname / entry)
(setq entry (cadr (assoc ksname ksdata)))
(if entry (caddr (car entry)) nil)
)
;;; ------------------------------------------------------------
;;; KS_EIN.Z / KS_AUS.Z eines Composite-Blocks (VF_n/GF_n) messen.
;;; Rueckgabe: (kez kaz) - fehlende Werte = nil.
;;; ------------------------------------------------------------
(defun ch-measure-vfgf (ename / obj subs nm ksdata kez kaz)
(setq kez nil kaz nil)
(setq obj (vlax-ename->vla-object ename))
(setq subs (vl-catch-all-apply 'vlax-invoke (list obj 'Explode)))
(if (and (not (vl-catch-all-error-p subs)) subs)
(progn
(foreach sub subs
(if (and (not (vlax-erased-p sub))
(= (vla-get-ObjectName sub) "AcDbBlockReference"))
(progn
(setq nm (strcase (vla-get-Name sub)))
(cond
((and (null kez) (wcmatch nm *ch-as-pattern*))
(setq ksdata (extract-ks-from-block-raw sub))
(setq kez (ch-ks-z ksdata "KS_EIN")))
((and (null kaz) (wcmatch nm *ch-es-pattern*))
(setq ksdata (extract-ks-from-block-raw sub))
(setq kaz (ch-ks-z ksdata "KS_AUS")))
)
)
)
)
(foreach sub subs
(if (not (vlax-erased-p sub))
(vl-catch-all-apply 'vla-Delete (list sub))))
)
)
(list kez kaz)
)
;;; ------------------------------------------------------------
;;; getboundingbox-Punkt (Safearray/Variant) in Liste wandeln.
;;; ------------------------------------------------------------
(defun ch-pt->list (v)
(cond
((= (type v) 'variant) (vlax-safearray->list (vlax-variant-value v)))
((= (type v) 'safearray) (vlax-safearray->list v))
((listp v) v)
(t nil)
)
)
;;; ------------------------------------------------------------
;;; Bounding-Box (WCS, XY) eines INSERT: (minx miny maxx maxy) oder nil.
;;; ------------------------------------------------------------
(defun ch-bbox (ent / obj res)
(setq obj (vlax-ename->vla-object ent))
(vl-catch-all-apply 'vla-update (list obj))
(setq res
(vl-catch-all-apply
'(lambda ( / ll ur)
(vla-getboundingbox obj 'll 'ur)
(list (ch-pt->list ll) (ch-pt->list ur)))))
(if (vl-catch-all-error-p res)
nil
(list (car (car res)) (cadr (car res)) (car (cadr res)) (cadr (cadr res)))
)
)
;;; ------------------------------------------------------------
;;; Layer anlegen / Farbe angleichen (ohne aktuellen Layer zu aendern).
;;; ------------------------------------------------------------
(defun ch-ensure-layer (name color / lay ed)
(if (tblsearch "LAYER" name)
(progn
(setq lay (tblobjname "LAYER" name) ed (entget lay))
(if (assoc 62 ed)
(entmod (subst (cons 62 color) (assoc 62 ed) ed))))
(entmake (list '(0 . "LAYER")
'(100 . "AcDbSymbolTableRecord")
'(100 . "AcDbLayerTableRecord")
(cons 2 name) (cons 70 0) (cons 62 color) (cons 6 "Continuous")))
)
)
;;; ------------------------------------------------------------
;;; Block mit einem Kreis markieren (zentriert, Radius aus XY-Box).
;;; ------------------------------------------------------------
(defun ch-mark (ent / bb ipt cx cy cz r)
(setq bb (ch-bbox ent))
(setq ipt (cdr (assoc 10 (entget ent))))
(setq cz (if (and ipt (caddr ipt)) (caddr ipt) 0.0))
(if bb
(progn
(setq cx (/ (+ (nth 0 bb) (nth 2 bb)) 2.0)
cy (/ (+ (nth 1 bb) (nth 3 bb)) 2.0))
(setq r (* *ch-mark-radius-factor*
(/ (distance (list (nth 0 bb) (nth 1 bb))
(list (nth 2 bb) (nth 3 bb))) 2.0)))
(if (< r *ch-mark-radius-min*) (setq r *ch-mark-radius-min*)))
(progn (setq cx (car ipt) cy (cadr ipt) r *ch-mark-radius-min*))
)
(ch-ensure-layer *ch-mark-layer* *ch-mark-color*)
(entmake (list '(0 . "CIRCLE") (cons 8 *ch-mark-layer*)
(cons 10 (list cx cy cz)) (cons 40 r)))
)
;;; ------------------------------------------------------------
;;; Ungueltig = nil oder <= 0.
;;; ------------------------------------------------------------
(defun ch-invalid-p (v) (or (null v) (<= v 0)))
;;; ------------------------------------------------------------
;;; Block um dz in Z verschieben (WCS).
;;; ------------------------------------------------------------
(defun ch-move-z (ent dz)
(vla-Move (vlax-ename->vla-object ent)
(vlax-3d-point 0 0 0) (vlax-3d-point 0 0 dz))
)
;;; ------------------------------------------------------------
;;; MONTAGEHOEHE_m schreiben (roher Wert in m). Liegt der rohe Wert
;;; ueber *ch-buehne-schwelle-m*, wird pro Block nach einer Buehne
;;; gefragt und deren Hoehe abgezogen (real = roh - buehne).
;;; Rueckgabe: der geschriebene (evtl. reduzierte) Wert.
;;; ------------------------------------------------------------
(defun ch-write-montage (ent raw lbl / real ans buehne)
(setq real raw)
(if (> raw *ch-buehne-schwelle-m*)
(progn
(initget "Ja Nein")
(setq ans (getkword (strcat "\n " lbl ": Montagehoehe " (rtos raw 2 3)
" m (> " (rtos *ch-buehne-schwelle-m* 2 1)
" m). Buehne vorhanden? [Ja/Nein] <Nein>: ")))
(if (= ans "Ja")
(progn
(setq buehne (getreal "\n Buehnenhoehe in m: "))
(if (and buehne (> buehne 0))
(if (>= buehne raw)
(princ (strcat "\n ! Buehne (" (rtos buehne 2 3)
" m) >= Montagehoehe (" (rtos raw 2 3)
" m) - kein Abzug, roher Wert bleibt."))
(progn
(setq real (- raw buehne))
(princ (strcat "\n Buehne " (rtos buehne 2 3)
" m abgezogen -> " (rtos real 2 3) " m")))
)
)
)
)
)
)
(ch-set-att ent "MONTAGEHOEHE_m" (rtos real 2 3))
real
)
;;; ============================================================
;;; HAUPTBEFEHL (Phase 1 + 2)
;;; ============================================================
(defun c:HOEHEN_CHECK ( / ss i idx id items it ent ed nm lbl zc meas kez kaz
montage inp delta mss
n-kreisel n-vf n-gf n-fixed n-marked n-fehler)
(if (not (ch-ensure-vfcore))
(progn
(princ "\n>>> FEHLER: vf_core (extract-ks-from-block-raw) nicht geladen.")
(princ "\n Bitte das SSG_LIB-Menue laden oder DXFM_LISP setzen.")
(princ)
(exit)
)
)
(setq n-kreisel 0 n-vf 0 n-gf 0 n-fixed 0 n-marked 0 n-fehler 0)
;; Alte Markierungskreise entfernen (Idempotenz)
(setq mss (ssget "_X" (list (cons 0 "CIRCLE") (cons 8 *ch-mark-layer*))))
(if mss (command "_.ERASE" mss ""))
(vl-catch-all-apply '(lambda () (command "_.REGEN")))
(princ "\n============================================")
(princ "\n Hoehen-Check (Phase 1-3)")
(princ "\n============================================")
(setq ss (ssget "_X" '((0 . "INSERT"))))
(if (null ss)
(princ "\n Keine Bloecke gefunden.")
(progn
;; Kandidaten (KREISEL/VF/GF) sammeln und nach ID-Attribut sortieren
(setq items nil i 0 idx 0)
(while (< i (sslength ss))
(setq ent (ssname ss i)
nm (strcase (cdr (assoc 2 (entget ent)))))
(if (or (wcmatch nm "KREISEL_*") (wcmatch nm "VF_*") (wcmatch nm "GF_*"))
(progn
(setq id (ch-get-att-str ent "ID"))
(setq items (cons (list (if (and id (/= id "")) (atoi id) 999999)
ent idx)
items))
(setq idx (1+ idx))))
(setq i (1+ i))
)
(setq items (vl-sort items 'ch-id<))
(if (> (length items) 0)
(princ (strcat "\n (" (itoa (length items))
" Bloecke, Verarbeitung in ID-Reihenfolge)")))
;; in ID-Reihenfolge verarbeiten
(foreach it items
(setq ent (cadr it)
ed (entget ent)
nm (strcase (cdr (assoc 2 ed)))
lbl (cdr (assoc 2 ed)))
(cond
;; ===================== KREISEL =====================
((wcmatch nm "KREISEL_*")
(setq n-kreisel (1+ n-kreisel))
(setq zc (caddr (cdr (assoc 10 ed))))
(if (null zc) (setq zc 0.0))
(if (ch-invalid-p zc)
;; --- ungueltig: eingeben/verschieben oder markieren ---
(progn
(setq inp (getreal (strcat "\n " lbl " ungueltige Hoehe ("
(rtos zc 2 0)
" mm). Neue Hoehe in mm [ENTER=markieren]: ")))
(if (and inp (> inp 0))
(progn
(ch-move-z ent (- inp zc))
(setq zc inp)
(ch-set-att ent "HOEHE" (rtos zc 2 0))
(setq montage (ch-write-montage ent (/ zc 1000.0) lbl))
(setq n-fixed (1+ n-fixed))
(princ (strcat "\n -> verschoben & gesetzt: HOEHE=" (rtos zc 2 0)
" -> MONTAGEHOEHE_m=" (rtos montage 2 3))))
(progn
(ch-mark ent)
(setq n-marked (1+ n-marked))
(princ (strcat "\n -> markiert (Layer " *ch-mark-layer*
"), spaeter anpassen")))
)
)
;; --- gueltig ---
(progn
(ch-set-att ent "HOEHE" (rtos zc 2 0))
(setq montage (ch-write-montage ent (/ zc 1000.0) lbl))
(princ (strcat "\n " lbl ": HOEHE=" (rtos zc 2 0)
" -> MONTAGEHOEHE_m=" (rtos montage 2 3))))
)
)
;; ===================== VF / GF =====================
((or (wcmatch nm "VF_*") (wcmatch nm "GF_*"))
(if (wcmatch nm "GF_*") (setq n-gf (1+ n-gf)) (setq n-vf (1+ n-vf)))
(setq meas (ch-measure-vfgf ent) kez (car meas) kaz (cadr meas))
(cond
;; --- nicht messbar -> markieren ---
((or (null kez) (null kaz))
(setq n-fehler (1+ n-fehler))
(ch-mark ent)
(setq n-marked (1+ n-marked))
(princ (strcat "\n " lbl ": ! KS nicht messbar (VON="
(if kez (rtos kez 2 0) "?") ", BIS="
(if kaz (rtos kaz 2 0) "?") ") -> markiert")))
;; --- ungueltig (<=0) -> eingeben/verschieben oder markieren ---
((or (ch-invalid-p kez) (ch-invalid-p kaz))
(setq inp (getreal (strcat "\n " lbl " ungueltig (VON=" (rtos kez 2 0)
", BIS=" (rtos kaz 2 0)
"). KS_EIN-Hoehe in mm [ENTER=markieren]: ")))
(if (and inp (> inp 0))
(progn
(setq delta (- inp kez))
(ch-move-z ent delta)
(setq kez inp kaz (+ kaz delta))
(if (or (ch-invalid-p kez) (ch-invalid-p kaz))
(progn
(ch-mark ent)
(setq n-marked (1+ n-marked))
(princ (strcat "\n -> verschoben, aber BIS weiter ungueltig ("
(rtos kaz 2 0) " mm) -> markiert")))
(progn
(ch-set-att ent "HOEHE_VON_mm" (rtos kez 2 0))
(ch-set-att ent "HOEHE_BIS_mm" (rtos kaz 2 0))
(setq montage (ch-write-montage ent
(if (wcmatch nm "GF_*")
(/ kez 1000.0)
(/ (+ kez kaz) 2000.0)) lbl))
(setq n-fixed (1+ n-fixed))
(princ (strcat "\n -> verschoben & gesetzt: VON=" (rtos kez 2 0)
", BIS=" (rtos kaz 2 0)
" -> MONTAGEHOEHE_m=" (rtos montage 2 3))))
)
)
(progn
(ch-mark ent)
(setq n-marked (1+ n-marked))
(princ (strcat "\n -> markiert (Layer " *ch-mark-layer*
"), spaeter anpassen")))
)
)
;; --- gueltig ---
(t
(ch-set-att ent "HOEHE_VON_mm" (rtos kez 2 0))
(ch-set-att ent "HOEHE_BIS_mm" (rtos kaz 2 0))
(setq montage (ch-write-montage ent
(if (wcmatch nm "GF_*")
(/ kez 1000.0)
(/ (+ kez kaz) 2000.0)) lbl))
(princ (strcat "\n " lbl ": HOEHE_VON_mm=" (rtos kez 2 0)
", HOEHE_BIS_mm=" (rtos kaz 2 0)
" -> MONTAGEHOEHE_m=" (rtos montage 2 3))))
)
)
)
)
(princ (strcat "\n--------------------------------------------"
"\n Kreisel: " (itoa n-kreisel)
" VF: " (itoa n-vf)
" GF: " (itoa n-gf)
"\n korrigiert (verschoben): " (itoa n-fixed)
" markiert: " (itoa n-marked)
" nicht messbar: " (itoa n-fehler)))
(if (> n-marked 0)
(princ (strcat "\n Markierte Bloecke: Layer '" *ch-mark-layer*
"' - spaeter Hoehe anpassen und erneut ausfuehren.")))
(princ "\n Hinweis: Phase 1-3 - kein QSAVE (UNDO moeglich).")
)
)
(princ "\n>>> Fertig.")
(princ)
)
(princ "\n>>> check_hoehen.lsp geladen (Phase 1-3). Befehl: HOEHEN_CHECK")
(princ)
+243
View File
@@ -0,0 +1,243 @@
;; ============================================================
;; collect_attributes.lsp
;; Sammelt die aktuellen ATTDEF-Werte aller Bloecke (DWG-Dateien)
;; eines Verzeichnisses und schreibt sie als JSON-Datei
;; "allocations_collected.json" - im selben Format wie
;; allocations.json (siehe addattribute.lsp):
;; {"Blockname": {"TAG1": "Wert1", "TAG2": "Wert2", ...}, ...}
;;
;; Wird zunaechst fuer data/ils/2D und data/ils/3D ausgefuehrt -
;; je Verzeichnis entsteht eine eigene allocations_collected.json,
;; direkt im jeweiligen Verzeichnis abgelegt.
;;
;; Voraussetzung: DXFM_DATA ist gesetzt (siehe bin/setenv.bat).
;;
;; Aufruf in BricsCAD:
;; (load "C:/.../Lisp/collect_attributes.lsp")
;; ILS_ATTR_COLLECT
;; ============================================================
(vl-load-com)
;; ------------------------------------------------------------
;; Bereits offenes Dokument mit gegebenem Pfad suchen (oder nil)
;; ------------------------------------------------------------
(defun cac-find-open-doc (dwg-pfad / docs anzahl i doc full treffer)
(setq docs (vla-get-Documents (vlax-get-acad-object))
anzahl (vla-get-Count docs)
i 0
treffer nil
dwg-pfad (strcase (vl-string-translate "\\" "/" dwg-pfad))
)
(while (and (< i anzahl) (not treffer))
(setq doc (vla-item docs i))
(setq full (strcase (vl-string-translate "\\" "/" (vla-get-FullName doc))))
(if (= full dwg-pfad) (setq treffer doc))
(setq i (1+ i))
)
treffer
)
;; ------------------------------------------------------------
;; String fuer JSON escapen (Anfuehrungszeichen/Backslash)
;; ------------------------------------------------------------
(defun cac-json-escape (s)
(if (null s) (setq s ""))
(setq s (vl-string-subst "\\\\" "\\" s))
(vl-string-subst "\\\"" "\"" s)
)
;; ------------------------------------------------------------
;; Alle ATTDEFs im aktiven Dokument einsammeln (alphabetisch nach
;; Tag sortiert, fuer reproduzierbare Ausgabe) -> (("TAG" . "Wert") ...)
;; ------------------------------------------------------------
(defun cac-collect-attdefs-in-current-doc ( / ss anzahl i ent ed tag wert ergebnis)
(setq ss (ssget "X" '((0 . "ATTDEF"))))
(setq ergebnis nil)
(if ss
(progn
(setq i 0 anzahl (sslength ss))
(while (< i anzahl)
(setq ent (ssname ss i)
ed (entget ent)
tag (cdr (assoc 2 ed))
wert (cdr (assoc 1 ed))
)
(if (null wert) (setq wert ""))
(setq ergebnis (cons (cons tag wert) ergebnis))
(setq i (1+ i))
)
)
)
(vl-sort ergebnis (function (lambda (a b) (< (strcase (car a)) (strcase (car b))))))
)
;; ------------------------------------------------------------
;; Attribut-Alist ((TAG . Wert) ...) als eingerueckten JSON-Objekt-
;; Text formatieren, z.B.:
;; {
;; "TAG1": "Wert1",
;; "TAG2": "Wert2"
;; }
;; einruecken = Einrueckung der schliessenden Klammer
;; ------------------------------------------------------------
(defun cac-attribs-to-json (attribs einruecken / innen zeilen)
(if (null attribs)
"{}"
(progn
(setq innen (strcat einruecken " "))
(setq zeilen
(mapcar
(function (lambda (paar)
(strcat innen "\"" (cac-json-escape (car paar)) "\": \""
(cac-json-escape (cdr paar)) "\"")
))
attribs
)
)
(strcat "{\n"
(car zeilen)
(apply 'strcat (mapcar (function (lambda (z) (strcat ",\n" z))) (cdr zeilen)))
"\n" einruecken "}"
)
)
)
)
;; ------------------------------------------------------------
;; Eine DWG-Datei oeffnen (falls noetig), ATTDEFs einsammeln und
;; die Datei wieder schliessen (falls durch diese Funktion geoeffnet).
;; Rueckgabe: ('ok . (("TAG" . "Wert") ...)) oder ('fehler . meldung)
;; ------------------------------------------------------------
(defun cac-collect-dwg (dwg-pfad / bereits-offen ergebnis fehler)
(setq bereits-offen (cac-find-open-doc dwg-pfad))
(setq ergebnis nil)
(setq fehler
(vl-catch-all-apply
(function
(lambda ()
(if bereits-offen
(vlax-put-property (vlax-get-acad-object) 'ActiveDocument bereits-offen)
(command "_.OPEN" dwg-pfad)
)
(setq ergebnis (cac-collect-attdefs-in-current-doc))
(if (not bereits-offen) (command "_.CLOSE"))
)
)
nil
)
)
(if (vl-catch-all-error-p fehler)
(cons 'fehler (vl-catch-all-error-message fehler))
(cons 'ok ergebnis)
)
)
;; ------------------------------------------------------------
;; Alle *.dwg eines Verzeichnisses einlesen und als
;; allocations_collected.json (json-pfad) schreiben.
;; ------------------------------------------------------------
(defun cac-collect-directory (dwg-dir json-pfad / dateien datei dwg-pfad orig-doc
blockname ergebnis anzahl-ok anzahl-fehler
fehler-liste eintraege fh erste paar)
(setq dwg-dir (vl-string-right-trim "/" (vl-string-translate "\\" "/" dwg-dir)))
(if (not (findfile dwg-dir))
(princ (strcat "\n[ATTR-COLLECT] Verzeichnis nicht gefunden, uebersprungen: " dwg-dir))
(progn
(setq dateien (vl-directory-files dwg-dir "*.dwg" 1))
(if (not dateien)
(princ (strcat "\n[ATTR-COLLECT] Keine DWG-Dateien in: " dwg-dir))
(progn
(setq orig-doc (vla-get-ActiveDocument (vlax-get-acad-object))
anzahl-ok 0
anzahl-fehler 0
fehler-liste nil
eintraege nil
)
(foreach datei dateien
(setq blockname (vl-filename-base datei)
dwg-pfad (strcat dwg-dir "/" datei)
)
(princ (strcat "\n[ATTR-COLLECT] Lese " datei " ..."))
(setq ergebnis (cac-collect-dwg dwg-pfad))
(if (equal (car ergebnis) 'fehler)
(progn
(princ (strcat "\n[ATTR-COLLECT] FEHLER bei " datei ": " (cdr ergebnis)))
(setq anzahl-fehler (1+ anzahl-fehler))
(setq fehler-liste (cons datei fehler-liste))
)
(progn
(setq eintraege (cons (cons blockname (cdr ergebnis)) eintraege))
(setq anzahl-ok (1+ anzahl-ok))
)
)
)
(vlax-put-property (vlax-get-acad-object) 'ActiveDocument orig-doc)
(setq eintraege (reverse eintraege))
;; JSON schreiben
(setq fh (open json-pfad "w"))
(if (null fh)
(princ (strcat "\n[ATTR-COLLECT] FEHLER: Datei kann nicht geschrieben werden: " json-pfad))
(progn
(write-line "{" fh)
(setq erste T)
(foreach paar eintraege
(if (not erste) (write-line "," fh))
(write-line (strcat " \"" (cac-json-escape (car paar)) "\": "
(cac-attribs-to-json (cdr paar) " "))
fh)
(setq erste nil)
)
(write-line "}" fh)
(close fh)
(princ (strcat "\n[ATTR-COLLECT] " json-pfad " geschrieben ("
(itoa anzahl-ok) " Bloecke)."))
)
)
(princ (strcat "\n[ATTR-COLLECT] " dwg-dir " fertig: "
(itoa anzahl-ok) " gelesen, "
(itoa anzahl-fehler) " Fehler."))
(if fehler-liste
(progn
(princ "\n[ATTR-COLLECT] WARNUNG: Fehler bei:")
(foreach datei (reverse fehler-liste)
(princ (strcat "\n - " datei))
)
)
)
)
)
)
)
(princ)
)
;; ------------------------------------------------------------
;; Hauptbefehl - verarbeitet DXFM_DATA/ils/2D und DXFM_DATA/ils/3D
;; ------------------------------------------------------------
(defun c:ILS_ATTR_COLLECT ( / data-dir basis-dir subverz dwg-dir json-pfad)
(setq data-dir (getenv "DXFM_DATA"))
(if (not data-dir)
(progn
(alert "DXFM_DATA ist nicht gesetzt.\nBitte zuerst bin/setenv.bat ausfuehren.")
(exit)
)
)
(setq data-dir (vl-string-translate "\\" "/" data-dir)
basis-dir (strcat data-dir "/ils")
)
(foreach subverz '("2D" "3D")
(setq dwg-dir (strcat basis-dir "/" subverz)
json-pfad (strcat dwg-dir "/allocations_collected.json")
)
(princ (strcat "\n[ATTR-COLLECT] === " subverz " ==="))
(cac-collect-directory dwg-dir json-pfad)
)
(princ)
)
(princ "\ncollect_attributes.lsp geladen. Befehl: ILS_ATTR_COLLECT")
(princ)
+501
View File
@@ -0,0 +1,501 @@
;;; ============================================================
;;; count_sep_scan.lsp - Eigenstaendiges Zaehl-Werkzeug
;;; ------------------------------------------------------------
;;; Zaehlt die manuell platzierten Bloecke "Scanner" und
;;; "Separator_SP" je ILS-Block (Kreisel / VarioFoerderer /
;;; Gefaellestrecke) und schreibt die Anzahlen in die Attribute
;;; des jeweiligen ILS-Blocks. Anschliessend QSAVE.
;;;
;;; Zuordnung eines Sensors zu einem ILS-Block (Z wird ignoriert):
;;; - Scanner: der Einfuegepunkt (X/Y) muss in der Bounding-Box
;;; des ILS-Blocks liegen. Die 3D-Geometrie des Scanners kann
;;; weit vom Einfuegepunkt entfernt sein, daher zaehlt hier der
;;; Einfuegepunkt (dort klickt der Benutzer auf den Block).
;;; - Separator: der geometrische Mittelpunkt (Zentrum der eigenen
;;; Bounding-Box, unabhaengig vom $INSBASE) muss in der
;;; Bounding-Box des ILS-Blocks liegen.
;;; - Liegt der Punkt in mehreren Boxen (Ueberlappung), wird
;;; der ILS-Block mit dem naechstgelegenen Box-Zentrum gewaehlt.
;;; - Ein optionaler Toleranzrand (*senstol*) vergroessert die
;;; Box, damit Sensoren knapp am Rand noch erfasst werden.
;;;
;;; Zusaetzlich:
;;; - Bei zugeordneten Sensoren wird die Bezeichnung des ILS-Blocks
;;; (Attribut "Bezeichnung", Fallback Blockname) in das Sensor-
;;; Attribut *zuordnung-tag* geschrieben.
;;; - Nicht zugeordnete Sensoren werden mit einem Kreis auf dem
;;; Layer *mark-layer* markiert (zentriert auf den Sensor).
;;; - Der Befehl ist wiederholbar: alte Markierungskreise werden
;;; zu Beginn entfernt.
;;;
;;; Aufruf: ZAEHLE_SEP_SCAN
;;; Laden: per APPLOAD oder (load "count_sep_scan")
;;; ============================================================
(vl-load-com)
;;; ------------------------------------------------------------
;;; KONFIGURATION (bei Bedarf anpassen)
;;; ------------------------------------------------------------
;; Toleranzrand um die ILS-Block-Box in Zeichnungseinheiten (mm).
;; 0.0 = exakte Box. Groesserer Wert = Sensoren knapp ausserhalb
;; werden noch dem ILS-Block zugerechnet.
(if (null *senstol*) (setq *senstol* 0.0))
;; Blockname-Muster (wcmatch, Grossschreibung) fuer die manuell
;; platzierten Sensoren.
(setq *scanner-pattern* "SCANNER,SCANNER_*")
(setq *separator-pattern* "SEPARATOR_SP,SEPARATOR_SP_*")
;; Blockname-Muster fuer die INTERN im ILS-Block (in der Kette)
;; gezeichneten Separatoren. Diese bilden die Basis fuer
;; ANZAHL_SEPARATOR und werden bei jedem Lauf frisch gezaehlt.
(setq *intern-separator-pattern* "STAUSTRECKE_SEPARATOR_SP*")
;; Attribut-Tag im Scanner-/Separator-Block, in das die Bezeichnung
;; des zugeordneten ILS-Blocks geschrieben wird (Gross/Klein egal).
(setq *zuordnung-tag* "zuordnung")
;; Markierung nicht zugeordneter Sensoren: Kreis auf eigenem Layer.
(setq *mark-layer* "S_SENSOR_UNZUGEORDNET")
(setq *mark-color* 2) ;; 2 = Gelb
;; Kreisradius = Faktor * halbe XY-Diagonale der Sensor-Box,
;; mindestens *mark-radius-min* (mm).
(if (null *mark-radius-factor*) (setq *mark-radius-factor* 1.5))
(if (null *mark-radius-min*) (setq *mark-radius-min* 500.0))
;;; ------------------------------------------------------------
;;; ILS-Block-Erkennung und zugehoerige Attribut-Tags
;;; Alle ILS-Bloecke (Kreisel / VF / GF) verwenden einheitlich
;;; ANZAHL_SCANNER und ANZAHL_SEPARATOR.
;;; Rueckgabe: (scanner-tag separator-tag) oder nil
;;; ------------------------------------------------------------
(defun cs-carrier-tags (nm / up)
(setq up (strcase nm))
(if (or (wcmatch up "KREISEL_*")
(wcmatch up "VF_*")
(wcmatch up "GF_*"))
(list "ANZAHL_SCANNER" "ANZAHL_SEPARATOR")
nil
)
)
;;; ------------------------------------------------------------
;;; Sensor-Erkennung
;;; Rueckgabe: 'scanner | 'separator | nil
;;; ------------------------------------------------------------
(defun cs-sensor-kind (nm / up)
(setq up (strcase nm))
(cond
((wcmatch up *scanner-pattern*) 'scanner)
((wcmatch up *separator-pattern*) 'separator)
(t nil)
)
)
;;; ------------------------------------------------------------
;;; Punkt-Rueckgabe von vla-getboundingbox in eine Liste wandeln.
;;; BricsCAD liefert ein Safearray, AutoCAD ein Variant mit
;;; Safearray - beide Faelle werden hier abgedeckt.
;;; ------------------------------------------------------------
(defun cs-pt->list (v)
(cond
((= (type v) 'variant) (vlax-safearray->list (vlax-variant-value v)))
((= (type v) 'safearray) (vlax-safearray->list v))
((listp v) v)
(t nil)
)
)
;;; ------------------------------------------------------------
;;; Bounding-Box eines INSERT holen (WCS, achsparallel).
;;; Erzwingt vorher ein vla-update (Regen des Objekts), da
;;; vla-getboundingbox sonst auf nicht-regenerierten oder auf
;;; eingefrorenen Layern liegenden Bloecken scheitert.
;;; Rueckgabe: (minx miny maxx maxy) oder nil bei Fehler.
;;; *cs-last-error* enthaelt bei Fehler den echten COM-Fehlertext.
;;; ------------------------------------------------------------
(defun cs-bbox (ent / obj res)
(setq *cs-last-error* nil)
(setq obj (vlax-ename->vla-object ent))
;; Objekt regenerieren (Fehler ignorieren)
(vl-catch-all-apply 'vla-update (list obj))
(setq res
(vl-catch-all-apply
'(lambda ( / ll ur)
(vla-getboundingbox obj 'll 'ur)
(list (cs-pt->list ll) (cs-pt->list ur)))))
(if (vl-catch-all-error-p res)
(progn
(setq *cs-last-error* (vl-catch-all-error-message res))
nil)
(list (car (car res)) (cadr (car res)) ;; minx miny
(car (cadr res)) (cadr (cadr res))) ;; maxx maxy
)
)
;;; ------------------------------------------------------------
;;; Referenzpunkt eines Sensors (X/Y), je nach Typ:
;;; - Scanner : Einfuegepunkt (DXF-Gruppe 10).
;;; - Separator : geometrischer Mittelpunkt seiner eigenen
;;; Bounding-Box (unabhaengig vom $INSBASE),
;;; Fallback auf den Einfuegepunkt.
;;; ------------------------------------------------------------
(defun cs-sensor-point (ent ed kind / bb)
(if (eq kind 'scanner)
(cdr (assoc 10 ed))
(progn
(setq bb (cs-bbox ent))
(if bb
(list (/ (+ (nth 0 bb) (nth 2 bb)) 2.0)
(/ (+ (nth 1 bb) (nth 3 bb)) 2.0))
(cdr (assoc 10 ed))
)
)
)
)
;;; ------------------------------------------------------------
;;; Liegt Punkt pt (X/Y) in ILS-Block-Record rec (mit Toleranz)?
;;; rec = (ename tagScan tagSep minx miny maxx maxy cx cy)
;;; ------------------------------------------------------------
(defun cs-in-box (pt rec / x y)
(setq x (car pt) y (cadr pt))
(and (>= x (- (nth 3 rec) *senstol*))
(<= x (+ (nth 5 rec) *senstol*))
(>= y (- (nth 4 rec) *senstol*))
(<= y (+ (nth 6 rec) *senstol*)))
)
;;; ------------------------------------------------------------
;;; Sensor-Punkt einem ILS-Block zuordnen.
;;; Rueckgabe: ILS-Block-Record oder nil (keine Zuordnung).
;;; Bei mehreren Treffern: naechstes Box-Zentrum (X/Y).
;;; ------------------------------------------------------------
(defun cs-assign (pt carriers / matches best bestd d)
(setq matches nil)
(foreach rec carriers
(if (cs-in-box pt rec) (setq matches (cons rec matches))))
(cond
((null matches) nil)
((= (length matches) 1) (car matches))
(t
(setq best nil bestd nil)
(foreach rec matches
(setq d (distance (list (car pt) (cadr pt))
(list (nth 7 rec) (nth 8 rec))))
(if (or (null bestd) (< d bestd))
(setq bestd d best rec)))
best)
)
)
;;; ------------------------------------------------------------
;;; Zaehler in einer Assoc-Liste (Schluessel = ename) erhoehen.
;;; ------------------------------------------------------------
(defun cs-bump (alist key / pair)
(setq pair (assoc key alist))
(if pair
(subst (cons key (1+ (cdr pair))) pair alist)
(cons (cons key 1) alist))
)
;;; ------------------------------------------------------------
;;; Attributwert an einem INSERT setzen (Tag ohne Gross/Klein).
;;; Rueckgabe: T wenn Tag gefunden und gesetzt, sonst nil.
;;; ------------------------------------------------------------
(defun cs-set-att (ins tag val / e ed done ok)
(setq done nil ok nil)
;; Nur iterieren, wenn der INSERT ueberhaupt Attribute fuehrt (66=1),
;; sonst wuerde entnext in fremde Objekte weiterlaufen.
(if (= (cdr (assoc 66 (entget ins))) 1)
(progn
(setq e (entnext ins))
(while (and e (not done))
(setq ed (entget e))
(cond
((= (cdr (assoc 0 ed)) "ATTRIB")
(if (= (strcase (cdr (assoc 2 ed))) (strcase tag))
(progn
(entmod (subst (cons 1 val) (assoc 1 ed) ed))
(entupd e)
(setq ok t))))
((= (cdr (assoc 0 ed)) "SEQEND") (setq done t))
)
(setq e (entnext e))
)
)
)
ok
)
;;; ------------------------------------------------------------
;;; Zaehlt rekursiv, wie oft ein Block (Muster pat) in der
;;; Definition des Blocks bname verwendet wird - inklusive
;;; verschachtelter Unterbloecke. Damit wird die interne Anzahl
;;; der Kette-Separatoren aus der Geometrie ermittelt.
;;; ------------------------------------------------------------
(defun cs-count-nested (bname pat / e ed nm n stop)
(setq n 0 stop nil)
(setq e (tblobjname "BLOCK" bname))
(if e
(progn
(setq e (entnext e))
(while (and e (not stop))
(setq ed (entget e))
(cond
((= (cdr (assoc 0 ed)) "ENDBLK") (setq stop t))
((= (cdr (assoc 0 ed)) "INSERT")
(setq nm (cdr (assoc 2 ed)))
(if (wcmatch (strcase nm) pat)
(setq n (1+ n))
(setq n (+ n (cs-count-nested nm pat)))))
)
(if (not stop) (setq e (entnext e)))
)
)
)
n
)
;;; ------------------------------------------------------------
;;; Attributwert (String) an einem INSERT lesen. "" wenn nicht
;;; vorhanden. Tag ohne Gross/Klein-Unterscheidung.
;;; ------------------------------------------------------------
(defun cs-get-att-str (ins tag / e ed done val)
(setq done nil val "")
(if (= (cdr (assoc 66 (entget ins))) 1)
(progn
(setq e (entnext ins))
(while (and e (not done))
(setq ed (entget e))
(cond
((= (cdr (assoc 0 ed)) "ATTRIB")
(if (= (strcase (cdr (assoc 2 ed))) (strcase tag))
(progn (setq val (cdr (assoc 1 ed))) (setq done t))))
((= (cdr (assoc 0 ed)) "SEQEND") (setq done t))
)
(setq e (entnext e))
)
)
)
val
)
;;; ------------------------------------------------------------
;;; Bezeichnung eines ILS-Blocks ermitteln: Attribut "Bezeichnung",
;;; Fallback auf den Blocknamen.
;;; ------------------------------------------------------------
(defun cs-carrier-label (ent nm / bez)
(setq bez (cs-get-att-str ent "Bezeichnung"))
(if (and bez (/= bez "")) bez nm)
)
;;; ------------------------------------------------------------
;;; Layer anlegen (falls fehlend), ohne den aktuellen Layer zu aendern.
;;; ------------------------------------------------------------
(defun cs-ensure-layer (name color / lay ed)
(if (tblsearch "LAYER" name)
;; Layer existiert bereits: Standardfarbe angleichen
(progn
(setq lay (tblobjname "LAYER" name))
(setq ed (entget lay))
(if (assoc 62 ed)
(entmod (subst (cons 62 color) (assoc 62 ed) ed)))
)
;; Layer neu anlegen
(entmake (list '(0 . "LAYER")
'(100 . "AcDbSymbolTableRecord")
'(100 . "AcDbLayerTableRecord")
(cons 2 name)
(cons 70 0)
(cons 62 color)
(cons 6 "Continuous")))
)
)
;;; ------------------------------------------------------------
;;; Nicht zugeordneten Sensor mit einem Kreis markieren, zentriert
;;; auf die Sensor-Geometrie. Radius aus der XY-Box des Sensors
;;; (Faktor), mindestens *mark-radius-min*.
;;; ------------------------------------------------------------
(defun cs-mark-unassigned (ent / bb ipt cx cy cz r)
(setq bb (cs-bbox ent))
(setq ipt (cdr (assoc 10 (entget ent))))
(setq cz (if (and ipt (caddr ipt)) (caddr ipt) 0.0))
(if bb
(progn
(setq cx (/ (+ (nth 0 bb) (nth 2 bb)) 2.0)
cy (/ (+ (nth 1 bb) (nth 3 bb)) 2.0))
(setq r (* *mark-radius-factor*
(/ (distance (list (nth 0 bb) (nth 1 bb))
(list (nth 2 bb) (nth 3 bb))) 2.0)))
(if (< r *mark-radius-min*) (setq r *mark-radius-min*)))
(progn
(setq cx (car ipt) cy (cadr ipt) r *mark-radius-min*))
)
(cs-ensure-layer *mark-layer* *mark-color*)
(entmake (list '(0 . "CIRCLE")
(cons 8 *mark-layer*)
(cons 10 (list cx cy cz))
(cons 40 r)))
)
;;; ============================================================
;;; HAUPTBEFEHL
;;; ============================================================
(defun c:ZAEHLE_SEP_SCAN ( / ss i ent ed nm tags bb cx cy label
carriers scanlist seplist kind pt
scanCounts sepCounts
rec en nm2 ns nsep internSep newS newP
s sent spt
n-scan-unassigned n-sep-unassigned
n-zuordnung-fehlt mss
okS okP)
(setq carriers nil scanlist nil seplist nil n-zuordnung-fehlt 0)
;; Alte Markierungskreise entfernen (Idempotenz)
(setq mss (ssget "_X" (list (cons 0 "CIRCLE") (cons 8 *mark-layer*))))
(if mss (command "_.ERASE" mss ""))
;; Vor der Extents-Berechnung einmal regenerieren, damit
;; vla-getboundingbox verlaessliche Werte liefert.
(vl-catch-all-apply '(lambda () (command "_.REGEN")))
;; --- 1. Alle INSERTs sammeln und klassifizieren ---
(setq ss (ssget "_X" '((0 . "INSERT"))))
(if (null ss)
(progn (princ "\n>>> Keine Bloecke in der Zeichnung gefunden.") (princ))
(progn
(setq i 0)
(while (< i (sslength ss))
(setq ent (ssname ss i))
(setq ed (entget ent))
(setq nm (cdr (assoc 2 ed)))
(setq tags (cs-carrier-tags nm))
(cond
;; --- ILS-Block ---
(tags
(setq bb (cs-bbox ent))
(if bb
(progn
(setq cx (/ (+ (nth 0 bb) (nth 2 bb)) 2.0))
(setq cy (/ (+ (nth 1 bb) (nth 3 bb)) 2.0))
(setq label (cs-carrier-label ent nm))
(setq carriers
(cons (list ent (car tags) (cadr tags)
(nth 0 bb) (nth 1 bb) (nth 2 bb) (nth 3 bb)
cx cy label)
carriers)))
(princ (strcat "\n! Bounding-Box fehlgeschlagen fuer ILS-Block '" nm "'"
(if *cs-last-error*
(strcat " (" *cs-last-error* ")") "")))
)
)
;; --- Sensor (Entity + Referenzpunkt merken) ---
(t
(setq kind (cs-sensor-kind nm))
(if kind
(progn
(setq pt (cs-sensor-point ent ed kind))
(if (eq kind 'scanner)
(setq scanlist (cons (list ent pt) scanlist))
(setq seplist (cons (list ent pt) seplist)))))
)
)
(setq i (1+ i))
)
;; --- 2. Sensoren zuordnen: zuordnung schreiben bzw. markieren ---
(setq scanCounts nil sepCounts nil
n-scan-unassigned 0 n-sep-unassigned 0)
(foreach s scanlist
(setq sent (car s) spt (cadr s))
(setq rec (cs-assign spt carriers))
(if rec
(progn
(setq scanCounts (cs-bump scanCounts (car rec)))
(if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec)))
(setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt))))
(progn
(setq n-scan-unassigned (1+ n-scan-unassigned))
(cs-set-att sent *zuordnung-tag* "")
(cs-mark-unassigned sent))))
(foreach s seplist
(setq sent (car s) spt (cadr s))
(setq rec (cs-assign spt carriers))
(if rec
(progn
(setq sepCounts (cs-bump sepCounts (car rec)))
(if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec)))
(setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt))))
(progn
(setq n-sep-unassigned (1+ n-sep-unassigned))
(cs-set-att sent *zuordnung-tag* "")
(cs-mark-unassigned sent))))
;; --- 3. ANZAHL-Attribute setzen und Bericht ausgeben ---
(princ "\n============================================")
(princ "\n Sensor-Zaehlung je ILS-Block")
(princ "\n============================================")
(if (null carriers)
(princ "\n (Keine ILS-Bloecke KREISEL_/VF_/GF_ gefunden)")
(foreach rec carriers
(setq en (car rec))
(setq nm2 (cdr (assoc 2 (entget en))))
(setq ns (cond ((assoc en scanCounts) (cdr (assoc en scanCounts))) (t 0)))
(setq nsep (cond ((assoc en sepCounts) (cdr (assoc en sepCounts))) (t 0)))
;; interne Kette-Separatoren frisch aus der Blockdefinition zaehlen
(setq internSep (cs-count-nested nm2 *intern-separator-pattern*))
;; Scanner = nur neu zugeordnete
;; Separator = interne Kette-Separatoren + neu zugeordnete
(setq newS ns)
(setq newP (+ internSep nsep))
;; gefundene Anzahlen melden (mit Bezeichnung/Label)
(princ (strcat "\n " nm2 " [" (nth 9 rec) "]"
": Scanner(neu)=" (itoa ns)
", Separator intern=" (itoa internSep)
" + manuell=" (itoa nsep)))
;; Werte schreiben und Ergebnis bestaetigen
(setq okS (cs-set-att en (nth 1 rec) (itoa newS)))
(setq okP (cs-set-att en (nth 2 rec) (itoa newP)))
(if (and okS okP)
(princ (strcat "\n -> geschrieben: "
"ANZAHL_SCANNER=" (itoa newS)
", ANZAHL_SEPARATOR=" (itoa newP)))
(princ (strcat "\n -> FEHLER beim Schreiben: "
(if okS "" "ANZAHL_SCANNER fehlt ")
(if okP "" "ANZAHL_SEPARATOR fehlt"))))
)
)
(princ (strcat "\n--------------------------------------------"
"\n ILS-Bloecke gesamt: " (itoa (length carriers))
"\n Scanner gesamt: " (itoa (length scanlist))
" (nicht zugeordnet: " (itoa n-scan-unassigned) ")"
"\n Separator gesamt: " (itoa (length seplist))
" (nicht zugeordnet: " (itoa n-sep-unassigned) ")"))
(if (> (+ n-scan-unassigned n-sep-unassigned) 0)
(princ (strcat "\n " (itoa (+ n-scan-unassigned n-sep-unassigned))
" nicht zugeordnete(r) Sensor(en) mit Kreis markiert"
" (Layer '" *mark-layer* "').")))
(if (> n-zuordnung-fehlt 0)
(princ (strcat "\n WARNUNG: " (itoa n-zuordnung-fehlt)
" zugeordnete(r) Sensor(en) ohne Attribut '"
*zuordnung-tag* "' - Bezeichnung nicht schreibbar.")))
;; --- 4. Zeichnung speichern ---
(princ "\n--------------------------------------------")
(princ "\n Speichere Zeichnung (QSAVE) ...")
(command "_.QSAVE")
(princ "\n>>> Fertig.")
(princ)
)
)
(princ)
)
(princ "\n>>> count_sep_scan.lsp geladen. Befehl: ZAEHLE_SEP_SCAN")
(princ)
+292 -21
View File
@@ -11,6 +11,7 @@
;; Datei-/Skriptnamen sind fest im Code hinterlegt (*export-filenames*).
;; ============================================================
(vl-load-com)
;; --- Export-Konfiguration aus cfg/export.cfg laden ---
;; Nutzt den zentralen INI-Parser aus ssg_core.lsp (ssg-load-ini / ssg-ini-get /
@@ -19,7 +20,7 @@
(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 (ssg-textf "exp-cfg-not-found" (list cfg-pfad)))
)
(princ)
)
@@ -41,6 +42,14 @@
;; 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*
@@ -70,6 +79,210 @@
)
;; --- Safearray/Variant-Rueckgabe von vla-getboundingbox in Liste wandeln ---
;; BricsCAD liefert ein Safearray, AutoCAD ein Variant mit Safearray.
(defun csv:pt->list (v)
(cond
((= (type v) 'variant) (vlax-safearray->list (vlax-variant-value v)))
((= (type v) 'safearray) (vlax-safearray->list v))
((listp v) v)
(t nil)
)
)
;; ============================================================
;; KOS-KOMPRIMIERUNG (Position + Rotation als 24-Zeichen Base64-String)
;; ============================================================
;; Kodiert Position (x,y,z in mm) und Rotation (als Quaternion qx,qy,qz,qw)
;; verlustarm (24 Bit Fixed-Point je Wert) in einen 24-Zeichen Base64-String.
;; Ported aus einer interaktiven Referenz-Routine (c:ExportKOS), hier als
;; reine Funktion fuer den automatischen Export nutzbar. Alle Elemente in
;; diesem Projekt werden ausschliesslich um die Z-Achse gedreht (siehe
;; DREHUNG-Konvention weiter unten), daher genuegt eine Halbwinkel-Quaternion
;; fuer eine reine Z-Rotation (csv:z-angle-to-quat) -- keine vollstaendige
;; Rotationsmatrix/Quaternion-Extraktion noetig.
(setq *csv-b64-chars* "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
;; --- Wert auf [min-val, max-val] begrenzen ---
(defun csv:clamp (val min-val max-val)
(max min-val (min val max-val))
)
;; --- Rotationswinkel (Grad, reine Z-Drehung) -> Quaternion (qx qy qz qw) ---
(defun csv:z-angle-to-quat (deg / rad)
(setq rad (/ (* deg pi) 180.0))
(list 0.0 0.0 (sin (/ rad 2.0)) (cos (/ rad 2.0)))
)
;; --- Liste vorzeichenbehafteter 24-Bit-Integer -> Base64 (je 4 Zeichen) ---
;; Gemeinsamer Kodierer fuer csv:kos-encode und csv:trans-encode.
(defun csv:b64-encode-ints (int-list / b64-str val)
(setq b64-str "")
(foreach val int-list
(if (< val 0) (setq val (+ val 16777216))) ; Zweierkomplement (24 Bit)
(setq b64-str (strcat b64-str
(substr *csv-b64-chars* (1+ (lsh val -18)) 1)
(substr *csv-b64-chars* (1+ (logand (lsh val -12) 63)) 1)
(substr *csv-b64-chars* (1+ (logand (lsh val -6) 63)) 1)
(substr *csv-b64-chars* (1+ (logand val 63)) 1)
))
)
b64-str
)
;; --- Position (mm) + Quaternion -> 24-Zeichen Base64-String ---
;; Fixed-Point: x,y,z (Faktor 1000 = mm) und qx,qy,qz werden je auf 24 Bit
;; gerundet (6 Werte * 4 Zeichen = 24 Zeichen). qw wird nicht mitkodiert,
;; sondern nur zur Vorzeichen-Normierung verwendet (q und -q sind dieselbe
;; Rotation). Fuer den Insertpoint (volle Lage), siehe csv:trans-encode fuer
;; reine Positionen (K1-K4).
(defun csv:kos-encode (x y z qx qy qz qw)
(if (< qw 0.0)
(setq qx (- qx) qy (- qy) qz (- qz))
)
(csv:b64-encode-ints (list
(fix (csv:clamp (* x 1000.0) -8388607 8388607))
(fix (csv:clamp (* y 1000.0) -8388607 8388607))
(fix (csv:clamp (* z 1000.0) -8388607 8388607))
(fix (csv:clamp (* qx 8388607.0) -8388607 8388607))
(fix (csv:clamp (* qy 8388607.0) -8388607 8388607))
(fix (csv:clamp (* qz 8388607.0) -8388607 8388607))
))
)
;; --- Position (nur x,y,z) -> 12-Zeichen Base64-String ---
;; Fixed-Point Faktor 10.0 (0.1 mm Genauigkeit, Bereich +-838 m), 3 Werte *
;; 4 Zeichen = 12 Zeichen. Fuer die Koordinatensysteme K1-K4 (nur Position,
;; keine Rotation). Ported aus der Referenz-Routine c:ExportTrans.
(defun csv:trans-encode (x y z)
(csv:b64-encode-ints (list
(fix (csv:clamp (* x 10.0) -8388607 8388607))
(fix (csv:clamp (* y 10.0) -8388607 8388607))
(fix (csv:clamp (* z 10.0) -8388607 8388607))
))
)
;; --- Lokalen Punkt (relativ zum Block-Ursprung) unter Beruecksichtigung der
;; Eltern-Rotation (reine Z-Drehung um den Einfuegepunkt) in Weltkoordinaten
;; umrechnen. Rueckgabe: (x y z) ---
(defun csv:local-to-world (parent-pt parent-rot-rad local-pt / c s lx ly lz pz)
(setq c (cos parent-rot-rad) s (sin parent-rot-rad))
(setq lx (car local-pt) ly (cadr local-pt))
(setq lz (if (caddr local-pt) (caddr local-pt) 0.0))
(setq pz (if (caddr parent-pt) (caddr parent-pt) 0.0))
(list
(+ (car parent-pt) (- (* lx c) (* ly s)))
(+ (cadr parent-pt) (+ (* lx s) (* ly c)))
(+ pz lz)
)
)
;; --- K1-K4-Koordinatensysteme eines Blocks als Positions-Strings lesen ---
;; ename = Entity-Name des platzierten INSERT (Omniflo Bogen/Weiche/Gerade).
;; pt/rot-rad = bereits ermittelte Welt-Position/-Rotation (radiant) des
;; Eltern-INSERT (siehe csv:block-to-json), keine erneute Abfrage.
;; Sucht in der Block-DEFINITION (wie omni:get-block-hoehe) nach direkten
;; Sub-INSERTs "K1".."K4" und rechnet deren lokale Position ueber die
;; Eltern-Rotation (reine Z-Drehung) in Weltkoordinaten um. Es wird nur die
;; POSITION kodiert (12-Zeichen-String, csv:trans-encode) - keine Rotation.
;; Zusaetzlich werden Strecken-Koordinatensysteme KS_EIN->K1 und KS_AUS->K2
;; (inkl. der KSYS_-Varianten, siehe ks-normalize-name in vf_core.lsp) gemappt,
;; sofern kein echter K1/K2 am Block vorhanden ist (echte K-Bloecke haben
;; Vorrang: sie werden vorne angehaengt, csv:k-kos liest per assoc den ersten).
;; Rueckgabe: Assoc-Liste (("K1" . "<pos-string>") ("K2" . ...) ...), nur
;; fuer tatsaechlich vorhandene K-Bloecke (nicht jedes Element hat alle 4).
(defun csv:get-k-kos-strings (ename pt rot-rad / ed bname blk-tbl sub-ent sub-ed
sub-bname sub-pt world-pt target is-real result)
(setq ed (entget ename))
(setq bname (cdr (assoc 2 ed)))
(setq blk-tbl (tblsearch "BLOCK" bname))
(setq result nil)
(if blk-tbl
(progn
(setq sub-ent (entnext (cdr (assoc -2 blk-tbl))))
(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))))
;; Ziel-Slot bestimmen: echte K1-K4 direkt, KS_EIN/KS_AUS gemappt.
(setq is-real (wcmatch sub-bname "K1,K2,K3,K4"))
(setq target
(cond
(is-real sub-bname)
((or (= sub-bname "KS_EIN") (= sub-bname "KSYS_EIN")) "K1")
((or (= sub-bname "KS_AUS") (= sub-bname "KSYS_AUS")) "K2")
(t nil)))
;; Echte K-Bloecke immer aufnehmen (vorne = Vorrang bei assoc);
;; KS-abgeleitete nur, wenn der Slot noch nicht belegt ist.
(if (and target (or is-real (not (assoc target result))))
(progn
(setq sub-pt (cdr (assoc 10 sub-ed)))
(setq world-pt (csv:local-to-world pt rot-rad sub-pt))
(setq result (cons
(cons target
(csv:trans-encode
(car world-pt) (cadr world-pt) (caddr world-pt)))
result))
)
)
)
)
(setq sub-ent (entnext sub-ent))
)
)
)
result
)
;; --- Wert aus csv:get-k-kos-strings nach Name lesen, "" falls nicht vorhanden ---
(defun csv:k-kos (k-list name / found)
(setq found (assoc name k-list))
(if found (cdr found) "")
)
;; --- Mindesthoehe der Bounding-Box (Z-Ausdehnung), aus cfg/export.cfg ---
;; [Boundingbox] bb_minimum_height_mm, Default 1 (mm) falls nicht gesetzt.
;; Verhindert dz=0 bei flachen 2D-Bloecken (Draufsicht ohne Z-Ausdehnung).
(defun csv:bb-minimum-height-mm ()
(atof (export:cfg "Boundingbox" "bb_minimum_height_mm" "1"))
)
;; --- Bounding-Box (WCS, achsparallel) eines INSERT-Blocks ermitteln ---
;; Erzwingt vorher ein vla-update (Regen), da vla-getboundingbox sonst auf
;; nicht-regenerierten oder auf eingefrorenen Layern liegenden Bloecken scheitert.
;; Rueckgabe: Liste (cx cy cz dx dy dz) -- Mittelpunkt + Ausdehnung, oder nil bei Fehler.
;; dz wird auf csv:bb-minimum-height-mm angehoben, falls kleiner (siehe dort).
(defun csv:get-bbox (ename / obj res minpt maxpt dz min-hoehe)
(setq obj (vlax-ename->vla-object ename))
(vl-catch-all-apply 'vla-update (list obj))
(setq res
(vl-catch-all-apply
'(lambda ( / ll ur)
(vla-getboundingbox obj 'll 'ur)
(list (csv:pt->list ll) (csv:pt->list ur)))))
(if (vl-catch-all-error-p res)
nil
(progn
(setq minpt (car res))
(setq maxpt (cadr res))
(setq dz (- (caddr maxpt) (caddr minpt)))
(setq min-hoehe (csv:bb-minimum-height-mm))
(if (< dz min-hoehe) (setq dz min-hoehe))
(list
(/ (+ (car minpt) (car maxpt)) 2.0)
(/ (+ (cadr minpt) (cadr maxpt)) 2.0)
(/ (+ (caddr minpt) (caddr maxpt)) 2.0)
(- (car maxpt) (car minpt))
(- (cadr maxpt) (cadr minpt))
dz
)
)
)
)
;; --- Attribute eines INSERT-Blocks als JSON-Objekt lesen ---
;; ename = Entity-Name des INSERT
;; Rueckgabe: String wie {"TAG1":"Wert1","TAG2":"Wert2"}
@@ -103,7 +316,14 @@
;; --- Einen INSERT-Block als JSON-Objekt schreiben ---
(defun csv:block-to-json (ename / ed blk-name layer pt rotation handle attribs)
;; include-bbox = T -> zusaetzlich Bounding-Box (Mitte + Ausdehnung) ermitteln
;; und als "bbox"-Objekt anhaengen (nur fuer EXPORTCSV, nicht fuer EXPORTSIVAS).
;; "insertpoint" (KOS-String von Position+Rotation des Blocks selbst) und
;; "k1".."k4" (KOS-Strings der Koordinatensysteme im Block, siehe
;; csv:get-k-kos-strings) werden immer geschrieben, unabhaengig von
;; include-bbox -- Kodierung ueber csv:kos-encode (siehe dort).
(defun csv:block-to-json (ename include-bbox / ed blk-name layer pt rotation handle attribs bbox bbox-json
insert-quat insert-kos k-list)
(setq ed (entget ename))
(setq blk-name (cdr (assoc 2 ed)))
(setq layer (cdr (assoc 8 ed)))
@@ -112,6 +332,31 @@
(setq handle (cdr (assoc 5 ed)))
(if (null rotation) (setq rotation 0.0))
(setq attribs (csv:read-attribs ename))
(setq insert-quat (csv:z-angle-to-quat (* (/ rotation pi) 180.0)))
(setq insert-kos (csv:kos-encode
(car pt) (cadr pt) (if (caddr pt) (caddr pt) 0.0)
(nth 0 insert-quat) (nth 1 insert-quat) (nth 2 insert-quat) (nth 3 insert-quat)))
(setq k-list (csv:get-k-kos-strings ename pt rotation))
(setq bbox-json "")
(if include-bbox
(progn
(setq bbox (csv:get-bbox ename))
(if bbox
(setq bbox-json
(strcat
",\"bbox\":{"
"\"cx\":" (rtos (nth 0 bbox) 2 4)
",\"cy\":" (rtos (nth 1 bbox) 2 4)
",\"cz\":" (rtos (nth 2 bbox) 2 4)
",\"dx\":" (rtos (nth 3 bbox) 2 4)
",\"dy\":" (rtos (nth 4 bbox) 2 4)
",\"dz\":" (rtos (nth 5 bbox) 2 4)
"}"
)
)
)
)
)
(strcat
" {\"block_name\":\"" (csv:json-escape blk-name) "\""
",\"layer\":\"" (csv:json-escape layer) "\""
@@ -121,6 +366,12 @@
",\"z\":" (rtos (if (caddr pt) (caddr pt) 0.0) 2 4)
",\"rotation\":" (rtos (* (/ rotation pi) 180.0) 2 4)
",\"attribs\":" attribs
",\"insertpoint\":\"" insert-kos "\""
",\"k1\":\"" (csv:k-kos k-list "K1") "\""
",\"k2\":\"" (csv:k-kos k-list "K2") "\""
",\"k3\":\"" (csv:k-kos k-list "K3") "\""
",\"k4\":\"" (csv:k-kos k-list "K4") "\""
bbox-json
"}"
)
)
@@ -195,33 +446,49 @@
;; 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)
;; include-bbox = T -> Bounding-Box je Block ermitteln und mit exportieren
;; (siehe csv:block-to-json); fuer EXPORTSIVAS nil.
(defun csv:run-export (label py-name csv-name include-bbox / 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..."))
(princ (ssg-textf "exp-check-ids" (list label)))
(ssg-id-check-all)
;; Vor dem Export HOEHE/DREHUNG aller Omniflo-Elemente aktualisieren
(princ (strcat "\n[" label "] Aktualisiere Hoehe/Drehung..."))
(princ (ssg-textf "exp-update-hoehe-drehung" (list label)))
(omni:update-all-attribs)
(princ (strcat "\n[" label "] Sammle relevante Bloecke..."))
(princ (ssg-textf "exp-collect-blocks" (list label)))
(setq ss (csv:collect-export-blocks))
(if (null ss)
(progn
(princ (strcat "\n[" label "] Keine relevanten Bloecke gefunden."))
(princ (ssg-textf "exp-no-blocks-found" (list label)))
(princ)
)
(progn
(setq count (sslength ss))
(princ (strcat "\n[" label "] " (itoa count) " Bloecke gefunden."))
(princ (ssg-textf "exp-blocks-found" (list label count)))
;; 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 (ssg-textf "exp-output-dir" (list label out-dir)))
;; JSON-Datei zusammenbauen
(setq out-pfad (strcat (getenv "DXFM_RESULTS") "/"
(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 (ssg-textf "exp-file-open-error" (list label out-pfad)))
(princ)
)
(progn
@@ -232,28 +499,28 @@
(if (not first-block)
(write-line "," fh)
)
(write-line (csv:block-to-json ename) fh)
(write-line (csv:block-to-json ename include-bbox) fh)
(setq first-block nil)
(setq i (1+ i))
)
(write-line "]" fh)
(close fh)
(princ (strcat "\n[" label "] JSON geschrieben: " out-pfad))
(princ (ssg-textf "exp-json-written" (list label out-pfad)))
;; Python-Skript aufrufen
(setq py-skript (strcat (getenv "DXFM_LIB") "/" py-name))
(if (findfile py-skript)
(progn
(setq ergebnis-pfad (strcat (getenv "DXFM_RESULTS") "/" csv-name))
(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..."))
(princ (ssg-textf "exp-calling-python" (list label)))
(startapp "cmd" (strcat "/c " cmd))
(princ (strcat "\n[" label "] Export gestartet: " ergebnis-pfad))
(princ (ssg-textf "exp-export-started" (list label ergebnis-pfad)))
)
(princ (strcat "\n[" label "] FEHLER: Python-Skript nicht gefunden: " py-skript))
(princ (ssg-textf "exp-python-not-found" (list label py-skript)))
)
)
)
@@ -267,14 +534,18 @@
(defun c:EXPORTSIVAS ()
(csv:run-export "EXPORTSIVAS"
(export:filename "sivas_script")
(export:filename "sivas_csv"))
(export:filename "sivas_csv")
nil)
)
;; --- EXPORTCSV: Einfache Item-Liste aller Bloecke (ohne Summierung) ---
;; Ermittelt zusaetzlich je Block eine Bounding-Box (siehe csv:get-bbox),
;; die im Python-Skript als Position/Boundingbox-Spalten ausgegeben wird.
(defun c:EXPORTCSV ()
(csv:run-export "EXPORTCSV"
(export:filename "csv_script")
(export:filename "csv_csv"))
(export:filename "csv_csv")
T)
)
@@ -377,7 +648,7 @@
(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.")
(princ (ssg-text "exp-omni-no-inserts"))
(progn
(setq count 0)
(setq i 0)
@@ -396,7 +667,7 @@
)
(setq i (1+ i))
)
(princ (strcat "\n[OMNI_UPDATE] " (itoa count) " Elemente aktualisiert (HOEHE, DREHUNG)."))
(princ (ssg-textf "exp-omni-updated" (list count)))
)
)
(princ)
+3 -3
View File
@@ -17,12 +17,12 @@
(setq fh (open return-datei "r"))
(setq zeile (read-line fh))
(close fh)
(princ (strcat "\n[SSG_LIB] Python Rueckgabe: " zeile))
(princ (ssg-textf "extcall-python-rueckgabe" (list zeile)))
)
(princ "\n[SSG_LIB] WARNUNG: Keine Rueckgabe von Python erhalten.")
(princ (ssg-text "extcall-keine-rueckgabe"))
)
)
(princ (strcat "\n[SSG_LIB] FEHLER: " py-skript " nicht gefunden!"))
(princ (ssg-textf "extcall-skript-nicht-gefunden" (list py-skript)))
)
(princ)
)
+159 -30
View File
@@ -13,59 +13,77 @@
;; (ssg-start "Titel" '(("OSMODE") ("ORTHOMODE")))
;; ... Makrocode ...
;; (ssg-end)
;;
;; Nestbar ueber *ssg-start-stack*: jedes ssg-start legt einen eigenen
;; Frame (vorheriger *error*-Handler + Variablenwerte) oben auf den
;; Stack, ssg-end nimmt genau diesen Frame wieder herunter. Noetig, weil
;; z.B. ein Test-Wrapper (ssg-start "TEST_KREISEL" ...) selbst wieder
;; Makros aufruft, die ihrerseits ssg-start/ssg-end nutzen - mit einer
;; einzelnen globalen Variable statt eines Stacks wuerde der innere
;; Aufruf den *error*-Handler und die CLAYER/CMDECHO/...-Werte des
;; aeusseren Aufrufs ueberschreiben. Ergebnis waere ein *error* wird
;; nach dem aeusseren ssg-end dauerhaft an ssg-errhan haengen bleiben
;; (statt zum urspruenglichen Default-Handler zurueckzukehren) und bei
;; jedem folgenden Fehler faelschlich veraltete CLAYER/CECOLOR-Werte
;; ueber "_LAYER"/"_undo" auf die Kommandozeile schreiben.
;; ------------------------------------------------------------
(defun ssg-start (titel zusatz-vars / xlen xpos xvar)
(if (not (boundp '*ssg-start-stack*)) (setq *ssg-start-stack* nil))
(defun ssg-start (titel zusatz-vars / cavar 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)
(setq cavar (append '(("CLAYER") ("CMDECHO")) zusatz-vars)
xlen (length 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)
(setq xvar (car (nth xpos cavar))
cavar (subst (cons xvar (getvar xvar)) (nth xpos cavar) cavar)
xpos (1+ xpos)
)
)
(setq *ssg-start-stack* (cons (cons *error* cavar) *ssg-start-stack*))
(setq *error* (function ssg-errhan))
(setvar "CMDECHO" 0)
(command "_undo" "_G")
(graphscr)
(if titel (prompt (strcat "\n***** " titel " *****\n")))
(if titel (prompt (ssg-textf "core-start-titel" (list titel))))
(princ)
)
(defun ssg-end (/ xpos xlen xvar)
(if _ssg-cavar
(defun ssg-end (/ frame cavar xpos xlen xvar)
(if *ssg-start-stack*
(progn
(setq frame (car *ssg-start-stack*)
*ssg-start-stack* (cdr *ssg-start-stack*)
cavar (cdr frame)
)
(command)
(command "_undo" "_E")
(setq xpos 1
xlen (length _ssg-cavar)
xlen (length cavar)
)
(if (/= (getvar "CLAYER") (caar _ssg-cavar))
(command "_LAYER" "_SE" (cdar _ssg-cavar) "")
(if (/= (getvar "CLAYER") (caar cavar))
(command "_LAYER" "_SE" (cdar cavar) "")
)
(repeat (1- xlen)
(setq xvar (nth xpos _ssg-cavar)
(setq xvar (nth xpos cavar)
xpos (1+ xpos)
)
(setvar (car xvar) (cdr xvar))
)
(setq *error* (car frame))
)
)
(if _ssg-olderr (setq *error* _ssg-olderr))
(princ)
)
(defun ssg-errhan (em)
(if (= em "Function cancelled")
(princ)
(progn (princ "\nFehler: ") (princ em))
(progn (princ (ssg-text "core-errhan-fehler")) (princ em))
)
(command)
(command)
@@ -73,6 +91,52 @@
)
;; ------------------------------------------------------------
;; BLOCK-WRAP MIT GARANTIERT WELTPARALLELEM BKS
;; ------------------------------------------------------------
;; Fasst die Entities in ss zu einem Block bname zusammen und fuegt ihn am
;; Welt-Punkt basispkt-welt wieder ein. Setzt das BKS dazu temporaer hart
;; auf Welt und stellt es danach wieder her.
;;
;; Hintergrund (31.95mm-Z-Versatz-Bug): (command "_.-BLOCK"/"_.INSERT" ...)
;; rechnet Punktargumente im AKTUELLEN BKS. Bei einem vom Welt-KS
;; abweichenden BKS ging der korrekt via (trans ...) umgerechnete Z-Wert
;; beim _.-BLOCK -> _.INSERT-Rundlauf verloren, sodass der fertige Block
;; um die BKS-Hoehe (z.B. 31.95mm) in Z verschoben wurde - obwohl die
;; ELEVATION-Systemvariable 0 war. Bei BKS=Welt liegen Objekte, Basispunkt
;; und Einfuegepunkt alle bei WCS-Z ohne jede Umrechnungs-Mehrdeutigkeit;
;; ein bei WCS-Z=0 platziertes Element bleibt garantiert bei Z=0.
;;
;; Rueckgabe: das eingefuegte INSERT-Objekt (entlast).
(defun ssg-block-wrap-welt (bname basispkt-welt ss / alt-attreq alt-attdia alt-elev alt-osmode)
(setq alt-attreq (getvar "ATTREQ")
alt-attdia (getvar "ATTDIA")
alt-elev (getvar "ELEVATION")
alt-osmode (getvar "OSMODE"))
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
;; OSMODE=0: laufenden Objektfang abschalten. Sonst kann _.INSERT den
;; explizit uebergebenen Einfuegepunkt (X,Y,0) auf ein an derselben X/Y-Stelle
;; liegendes Objekt umfangen - z.B. den gefangenen Basispunkt bei Z=12000 ->
;; der Block landet auf 12000 statt 0 (12000er-Bug).
(setvar "OSMODE" 0)
;; ELEVATION=0: sonst kann _.INSERT die Z-Hoehe aus der aktuellen Elevation
;; statt aus dem uebergebenen Punkt ziehen.
(setvar "ELEVATION" 0.0)
;; BKS temporaer auf Welt; _Previous stellt danach das vorige BKS wieder her.
(command "_.UCS" "_World")
;; basispkt-welt ist ein Welt-Punkt; bei BKS=Welt ist er zugleich BKS-Punkt.
(command "_.-BLOCK" bname basispkt-welt ss "")
(command "_.INSERT" bname basispkt-welt 1.0 1.0 0.0)
(command "_.UCS" "_Previous")
(setvar "OSMODE" alt-osmode)
(setvar "ELEVATION" alt-elev)
(setvar "ATTREQ" alt-attreq)
(setvar "ATTDIA" alt-attdia)
(entlast)
)
;; ------------------------------------------------------------
;; BENUTZER-ABFRAGEN
;; ------------------------------------------------------------
@@ -85,11 +149,11 @@
(if defa
(progn
(initget 1 "Yes No Yes")
(= (getkword (strcat "\n" prompt-text " Y/N <Y>: ")) "No")
(= (getkword (strcat "\n" prompt-text (ssg-text "ques-yn-default-yes"))) "No")
)
(progn
(initget 1 "Yes No No")
(= (getkword (strcat "\n" prompt-text " Y/N <N>: ")) "Yes")
(= (getkword (strcat "\n" prompt-text (ssg-text "ques-yn-default-no"))) "Yes")
)
)
)
@@ -126,12 +190,17 @@
)
)
;; Layer anlegen (falls nicht vorhanden) und optional setzen
;; Layer anlegen (falls nicht vorhanden) und optional aktivieren
;; lay-name = Name; color = Farbnummer als String z.B. "2"; set-aktiv = T/nil
(defun ssg-make-layer (lay-name color set-aktiv)
;; Farbe wird nur bei Neuanlage gesetzt, bestehende Layer bleiben unveraendert
(defun ssg-make-layer (lay-name color set-aktiv / neu)
(setq neu (not (tblsearch "LAYER" lay-name)))
(if set-aktiv
(command "_LAYER" "_M" lay-name "_CO" color lay-name "")
(command "_LAYER" "_N" lay-name "_CO" color lay-name "")
(command "_LAYER" "_M" lay-name "")
(command "_LAYER" "_N" lay-name "")
)
(if neu
(command "_LAYER" "_CO" color lay-name "")
)
)
@@ -225,7 +294,7 @@
(command "_insert" bname pt "" "" rotation)
)
(progn
(alert (strcat "Blockname '" bname "' existiert bereits - wird uebersprungen."))
(alert (ssg-textf "core-blockname-exists" (list bname)))
(setq bname (strcat "x" bname))
(command "_block" bname pt ss "")
(command "_insert" bname pt "" "" rotation)
@@ -389,13 +458,13 @@
;; (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.
;; 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")
("ARTINR" "6220")
("MONTAGEHOEHE_m" "0.000")
("HOEHE_VON_mm" "0")
("HOEHE_BIS_mm" "0")
@@ -434,7 +503,56 @@
;; (einsegmentige Gefaellestrecke: 1; Streckengruppe: gezaehlt).
(setq *strecke-attr-hinten*
'(("ANZAHL_SEPARATOR" "1")
("ANZAHL_SCANNER" "0")))
("ANZAHL_SCANNER" "0")
("GERUEST_EINZELMODUL" "1")
("GERUEST_TYP" "Schoenenberger Geruest")))
;; ============================================================
;; GERUESTOPTION - gemeinsame Combobox-Werte fuer Kreisel, Eckrad,
;; VarioFoerderer und Gefaellestrecke (Attribut GERUEST_TYP).
;; Reihenfolge = Reihenfolge in der Dialog-Combobox. Index 2
;; ("Schoenenberger Geruest") ist der Default.
;; ============================================================
(setq *ssg-geruest-optionen*
'("IPE-Geruest abgestuft"
"Obergeruest oben"
"Schoenenberger Geruest"
"nur Doppelrohrtraeger")
)
;; Geruest-Typ (String) -> Combobox-Index. Unbekannter/leerer Wert -> Default (2).
(defun ssg-geruest-typ-to-idx (typ / idx i gefunden)
(setq idx 2 i 0 gefunden nil)
(foreach opt *ssg-geruest-optionen*
(if (and (not gefunden) (equal typ opt))
(progn (setq idx i) (setq gefunden T))
)
(setq i (1+ i))
)
idx
)
;; Combobox-Index -> Geruest-Typ (String).
(defun ssg-geruest-idx-to-typ (idx)
(nth idx *ssg-geruest-optionen*)
)
;; Geruestoption per Kommandozeilen-Menue abfragen (fuer Module ohne DCL-Dialog,
;; z.B. ILS_Eckrad). Rueckgabe: Geruest-Typ-String aus *ssg-geruest-optionen*.
(defun ssg-ask-geruest-typ ( / i opt antwort idx)
(princ (ssg-text "geruest-typ-header"))
(setq i 1)
(foreach opt *ssg-geruest-optionen*
(princ (ssg-textf "geruest-typ-opt" (list i opt)))
(setq i (1+ i))
)
(setq antwort (getint (ssg-textf "geruest-typ-prompt" (list (itoa (1+ (ssg-geruest-typ-to-idx nil)))))))
(if (or (null antwort) (< antwort 1) (> antwort (length *ssg-geruest-optionen*)))
(setq idx (ssg-geruest-typ-to-idx nil))
(setq idx (1- antwort))
)
(ssg-geruest-idx-to-typ idx)
)
;; Geordnete ATTDEF-Definitionsliste fuer einen Strecken-Block-Typ.
;; typ "Gefaellestrecke" -> Vorderteil + Hinterteil (reduziert)
@@ -460,7 +578,7 @@
(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))
(princ (ssg-textf "core-dwg-not-found" (list dwg-pfad)))
nil
)
(progn
@@ -536,8 +654,8 @@
(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)")
(if init-fn (apply init-fn nil))
(action_tile "accept" "(if accept-fn (apply accept-fn nil)) (done_dialog 1)")
(action_tile "cancel" "(done_dialog 0)")
(start_dialog)
(unload_dialog dat)
@@ -733,6 +851,17 @@
((and (not in-section) (= trimmed "{")) nil)
((and (not in-section) (= trimmed "}")) nil)
;; Leere Section auf einer Zeile: "name": {}
;; (Section-Start und -Ende zugleich - json.dump schreibt leere
;; Objekte immer inline, unabhaengig von der Einrueckung.)
((and (not in-inner)
(>= (strlen trimmed) 2)
(= (substr trimmed (1- (strlen trimmed)) 2) "{}"))
(setq section (substr trimmed 2
(1- (vl-string-search "\"" trimmed 1))))
(setq ergebnis (cons (cons section nil) ergebnis))
)
;; Section-Start: "name": {
((and (not in-inner) (vl-string-search ": {" trimmed))
(setq kv (ssg-cfg-parse-kv
+2 -2
View File
@@ -67,7 +67,7 @@
aktuell start-val
)
(if (not (new_dialog dialog-id dat))
(progn (alert "Dialog nicht verfuegbar.") (exit))
(progn (alert (ssg-text "dialog-nicht-verfuegbar")) (exit))
)
(set_tile select-tile start-val)
(if (and preview-tile slide-lib slide-list)
@@ -116,7 +116,7 @@
;; ------------------------------------------------------------
(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: "))
(setq pt (getpoint (ssg-text "dialog-einfuegepunkt-waehlen")))
(command "_insert" blk-pfad pt "" "" rotation)
(if attrib-alist
(ssg-attrib-set-many attrib-alist)
+12 -12
View File
@@ -93,11 +93,11 @@
(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))
(princ (ssg-textf "id-new-assigned" (list new-id-str)))
new-id-str
)
(progn
(princ "\n[ID] FEHLER: Kein gueltiger INSERT-Block!")
(princ (ssg-text "id-invalid-block"))
nil
)
)
@@ -113,7 +113,7 @@
(setq ss (ssg-id-collect-blocks))
(if (null ss)
(progn
(princ "\n[IDSCHECK] Keine relevanten Bloecke gefunden.")
(princ (ssg-text "id-check-no-blocks"))
0
)
(progn
@@ -141,8 +141,8 @@
(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))) ")"))
(princ (ssg-textf "id-check-missing-set"
(list new-id-str (cdr (assoc 2 (entget ename))))))
)
)
(setq i (1+ i))
@@ -158,16 +158,16 @@
(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))) ")"))
(princ (ssg-textf "id-check-duplicate"
(list (ssg-id-format (car entry)) new-id-str
(cdr (assoc 2 (entget ename))))))
(setq fixed-count (1+ fixed-count))
)
)
)
)
(princ (strcat "\n[IDSCHECK] Fertig. " (itoa fixed-count) " Duplikate korrigiert."))
(princ (ssg-textf "id-check-done" (list fixed-count)))
fixed-count
)
)
@@ -179,7 +179,7 @@
(defun c:IDSCHECK ( / count)
(ssg-start "IDSCHECK" nil)
(setq count (ssg-id-check-all))
(princ (strcat "\n[IDSCHECK] " (itoa count) " IDs korrigiert."))
(princ (ssg-textf "id-check-corrected" (list count)))
(ssg-end)
(princ)
)
@@ -188,10 +188,10 @@
;; 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: ")))
(setq ent (car (entsel (ssg-text "id-select-block-prompt"))))
(if (and ent (= (cdr (assoc 0 (entget ent))) "INSERT"))
(ssg-id-generate ent)
(princ "\n[IDGENERATE] Kein gueltiger Block gewaehlt.")
(princ (ssg-text "id-generate-invalid"))
)
(ssg-end)
(princ)
+148
View File
@@ -0,0 +1,148 @@
;; ============================================================
;; SSG_LANG.LSP - Sprachumschaltung (Deutsch/Englisch)
;; Zentrale Textverwaltung fuer benutzersichtbare Meldungen.
;; Kern-Modul, wird direkt nach ssg_core geladen.
;;
;; Die Texte liegen extern in lang/de_DE.json und lang/en_GB.json.
;; Diese Datei ist reiner Lade-/Zugriffscode. Beim Laden wird
;; *ssg-texts* aus den JSON-Dateien befuellt - Format wie bisher:
;; (key (cons "de_DE" wert) (cons "en_GB" wert))
;; Die JSON-Dateien werden aus Lisp/ssg_lang.lsp einmalig per
;; tools/migrate_lang_to_json.py erzeugt und danach direkt gepflegt.
;; ============================================================
;; ------------------------------------------------------------
;; Alle Vorkommen von alt in str durch neu ersetzen.
;; Frueh definiert, da ssg-lang-unescape es beim Laden braucht.
;; ------------------------------------------------------------
(defun ssg-str-replace-all (neu alt str / pos ergebnis)
(setq ergebnis "")
(while (setq pos (vl-string-search alt str))
(setq ergebnis (strcat ergebnis (substr str 1 pos) neu))
(setq str (substr str (+ pos 1 (strlen alt))))
)
(strcat ergebnis str)
)
;; ------------------------------------------------------------
;; Sprachordner ermitteln: 1) DXFMAKRO env, 2) *ssg-lisp-pfad*, 3) nil.
;; Gleiches Fallback-Muster wie in Gefaellestrecke.lsp/KreiselInsert.lsp.
;; DXFM_LANG bleibt der Sprachcode und wird hier NICHT als Pfad genutzt.
;; ------------------------------------------------------------
(defun ssg-lang-dir ( / )
(cond
((and (getenv "DXFMAKRO") (= (type (getenv "DXFMAKRO")) 'STR)
(> (strlen (getenv "DXFMAKRO")) 0))
(strcat (vl-string-right-trim "/" (vl-string-translate "\\" "/" (getenv "DXFMAKRO")))
"/lang"))
((and (boundp '*ssg-lisp-pfad*) (= (type *ssg-lisp-pfad*) 'STR)
(vl-string-search "/Lisp" *ssg-lisp-pfad*))
(strcat (substr *ssg-lisp-pfad* 1 (vl-string-search "/Lisp" *ssg-lisp-pfad*))
"/lang"))
(t nil)
)
)
;; ------------------------------------------------------------
;; Escapes aus einem JSON-Rohwert aufloesen: \n -> Zeilenumbruch.
;; Der JSON-Parser (ssg-cfg-parse-nested) liefert \n als literale
;; 2-Zeichen-Folge (Backslash + n) zurueck; hier wird sie in einen
;; echten Zeilenumbruch gewandelt. Suchmuster ist "\\n" (= die zwei
;; Zeichen Backslash+n); "\n" waere bereits ein Zeilenumbruch.
;; Andere Escapes kommen in den Sprachdateien nicht vor.
;; ------------------------------------------------------------
(defun ssg-lang-unescape (wert)
(if wert
(ssg-str-replace-all (chr 10) "\\n" wert)
)
)
;; ------------------------------------------------------------
;; Beide Sprachdateien laden und *ssg-texts* im bisherigen Format
;; befuellen: (key (cons "de_DE" ...) (cons "en_GB" ...)).
;; Fehlt eine Datei oder ein Key, bleibt der jeweilige Wert nil -
;; die Fallback-Kette in ssg-text greift dann automatisch
;; (en_GB -> de_DE -> Key). BricsCAD startet in jedem Fall.
;; ------------------------------------------------------------
(defun ssg-lang-load ( / dir de-datei en-datei de-sec en-sec
key wert-de wert-en ergebnis)
(setq *ssg-texts* nil)
(setq dir (ssg-lang-dir))
(if (null dir)
(princ "\n[LANG] WARNUNG: Sprachordner nicht ermittelbar (DXFMAKRO nicht gesetzt).")
(progn
(setq de-datei (strcat dir "/de_DE.json")
en-datei (strcat dir "/en_GB.json"))
(if (findfile de-datei)
(setq de-sec (cdr (assoc "texts"
(ssg-cfg-parse-nested (ssg-read-file-lines de-datei)))))
(princ (strcat "\n[LANG] WARNUNG: " de-datei " nicht gefunden."))
)
(if (findfile en-datei)
(setq en-sec (cdr (assoc "texts"
(ssg-cfg-parse-nested (ssg-read-file-lines en-datei)))))
(princ (strcat "\n[LANG] WARNUNG: " en-datei " nicht gefunden."))
)
(foreach paar de-sec
(setq key (car paar)
wert-de (ssg-lang-unescape (cdr paar))
wert-en (ssg-lang-unescape (cdr (assoc key en-sec))))
(setq ergebnis
(cons (list key (cons "de_DE" wert-de) (cons "en_GB" wert-en)) ergebnis))
)
(setq *ssg-texts* (reverse ergebnis))
(princ (strcat "\n[LANG] " (itoa (length *ssg-texts*)) " Texte geladen."))
)
)
(princ)
)
;; ------------------------------------------------------------
;; AKTUELLE SPRACHE
;; Default de_DE, Init aus DXFM_LANG. Ein erneutes Laden dieses
;; Moduls ueberschreibt eine zur Laufzeit gesetzte Sprache nicht.
;; ------------------------------------------------------------
(if (null *ssg-lang*)
(setq *ssg-lang* (getenv "DXFM_LANG"))
)
(if (or (null *ssg-lang*) (= *ssg-lang* ""))
(setq *ssg-lang* "de_DE")
)
;; Texttabelle aus den JSON-Sprachdateien befuellen
(ssg-lang-load)
;; ------------------------------------------------------------
;; ssg-text - Text zu einem Key in der aktuellen Sprache liefern
;; Fallback-Kette: *ssg-lang* -> de_DE -> Key selbst
;; ------------------------------------------------------------
(defun ssg-text (key / eintrag wert)
(setq eintrag (assoc key *ssg-texts*))
(if eintrag
(progn
(setq wert (cdr (assoc *ssg-lang* (cdr eintrag))))
(if (null wert)
(setq wert (cdr (assoc "de_DE" (cdr eintrag))))
)
(if (null wert) key wert)
)
key
)
)
;; ssg-textf - Text mit Platzhaltern %1 %2 ... aus einer Werteliste fuellen
(defun ssg-textf (key werte / txt i platzhalter)
(setq txt (ssg-text key))
(setq i 1)
(foreach w werte
(setq platzhalter (strcat "%" (itoa i)))
(setq txt (ssg-str-replace-all (vl-princ-to-string w) platzhalter txt))
(setq i (1+ i))
)
txt
)
(princ)
+33 -33
View File
@@ -75,12 +75,12 @@
;; 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: "))
(if (setq lay (ssg-get-layer (ssg-text "layer-prompt-ziel-layer")))
(progn
(command "_LAYER" "_SET" lay "")
(prompt (strcat "\nAktiver Layer: " lay))
(prompt (ssg-textf "layer-aktiver-layer" (list lay)))
)
(ssg-emsg "Kein Objekt gewaehlt.")
(ssg-emsg (ssg-text "layer-err-kein-objekt"))
)
(ssg-end)
lay
@@ -89,9 +89,9 @@
;; 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.")
(if (setq lay (ssg-get-layer (ssg-text "layer-prompt-objekt")))
(prompt (ssg-textf "layer-objekt-auf-layer" (list lay)))
(ssg-emsg (ssg-text "layer-err-kein-objekt"))
)
(ssg-end)
lay
@@ -101,11 +101,11 @@
(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: "))
(if (setq ziel-lay (ssg-get-layer (ssg-text "layer-prompt-ziel-layer")))
(command "_CHANGE" elem "" "_PROP" "_LA" ziel-lay "")
(ssg-emsg "Kein Ziel-Layer gewaehlt.")
(ssg-emsg (ssg-text "layer-err-kein-ziel-layer"))
)
(ssg-emsg "Kein Objekt gewaehlt.")
(ssg-emsg (ssg-text "layer-err-kein-objekt"))
)
(ssg-end)
)
@@ -114,11 +114,11 @@
(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: "))
(if (setq ziel-lay (ssg-get-layer (ssg-text "layer-prompt-ziel-layer")))
(command "_COPY" elem "" "@" "@" "_CHANGE" elem "" "_PROP" "_LA" ziel-lay "")
(ssg-emsg "Kein Ziel-Layer gewaehlt.")
(ssg-emsg (ssg-text "layer-err-kein-ziel-layer"))
)
(ssg-emsg "Kein Objekt gewaehlt.")
(ssg-emsg (ssg-text "layer-err-kein-objekt"))
)
(ssg-end)
)
@@ -127,34 +127,34 @@
;; (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): "))
(if (setq ref-lay (ssg-get-layer (ssg-text "layer-prompt-referenz-objekt")))
(progn
(setq ref-sel (entsel "\nNochmals fuer Typ-Ermittlung anklicken: "))
(setq ref-sel (entsel (ssg-text "layer-prompt-typ-ermittlung")))
(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: "))
(if (setq ziel-lay (ssg-get-layer (ssg-text "layer-prompt-ziel-layer")))
(progn
(ssg-zoom-save)
(ssg-ss-redraw ss 3)
(if (not (ssg-ques (strcat "Layer dieser " ref-typ "-Objekte wechseln?") nil))
(if (not (ssg-ques (ssg-textf "layer-ques-typ-wechseln" (list ref-typ)) nil))
(command "_CHANGE" ss "" "_PROP" "_LA" ziel-lay "")
(ssg-ss-redraw ss 4)
)
(ssg-zoom-restore)
)
(ssg-emsg "Kein Ziel-Layer.")
(ssg-emsg (ssg-text "layer-err-kein-ziel-layer-kurz"))
)
(ssg-emsg "Keine passenden Objekte gefunden.")
(ssg-emsg (ssg-text "layer-err-keine-passenden-objekte"))
)
)
(ssg-emsg "Abgebrochen.")
(ssg-emsg (ssg-text "layer-abgebrochen"))
)
)
(ssg-emsg "Kein Referenz-Objekt gewaehlt.")
(ssg-emsg (ssg-text "layer-err-kein-referenz-objekt"))
)
(ssg-end)
)
@@ -167,10 +167,10 @@
;; 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): "))
(while (setq lay (ssg-get-layer (ssg-text "layer-prompt-ausblenden")))
(if (ssg-layer-safe-p lay nil)
(command "_LAYER" "_OFF" lay "")
(ssg-emsg "Aktiven Layer nicht ausschalten!")
(ssg-emsg (ssg-text "layer-err-aktiv-nicht-ausschalten"))
)
)
(ssg-end)
@@ -179,10 +179,10 @@
;; 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): "))
(while (setq lay (ssg-get-layer (ssg-text "layer-prompt-einfrieren")))
(if (ssg-layer-safe-p lay nil)
(command "_LAYER" "_FR" lay "")
(ssg-emsg "Aktiven Layer nicht einfrieren!")
(ssg-emsg (ssg-text "layer-err-aktiv-nicht-einfrieren"))
)
)
(ssg-end)
@@ -191,13 +191,13 @@
;; 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: "))
(setq aktiv (ssg-get-layer (ssg-text "layer-prompt-aktiv-bleibt")))
(if aktiv
(progn
(command "_LAYER" "_SET" aktiv "_FR" "*" "")
(prompt (strcat "\nNur Layer '" aktiv "' ist sichtbar."))
(prompt (ssg-textf "layer-nur-layer-sichtbar" (list aktiv)))
)
(ssg-emsg "Abgebrochen.")
(ssg-emsg (ssg-text "layer-abgebrochen"))
)
(ssg-end)
)
@@ -278,34 +278,34 @@
(defun c:SSG-LayerDelete (/ lay ss)
(ssg-start "Layer loeschen" nil)
(initget 1)
(setq lay (getstring "\nLayername zum Loeschen: "))
(setq lay (getstring (ssg-text "layer-prompt-name-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))
(if (not (ssg-ques (ssg-textf "layer-ques-alle-loeschen" (list lay)) nil))
(progn
(command "_ERASE" ss "")
(command "_LAYER" "_OFF" lay "")
(command "_PURGE" "_LA" lay "N")
(prompt (strcat "\nLayer '" lay "' geloescht."))
(prompt (ssg-textf "layer-geloescht" (list lay)))
)
(progn
(ssg-ss-redraw ss 0)
(prompt "\nAbgebrochen.")
(prompt (strcat "\n" (ssg-text "layer-abgebrochen")))
)
)
)
(progn
(command "_LAYER" "_OFF" lay "")
(command "_PURGE" "_LA" lay "N")
(prompt (strcat "\nLeerer Layer '" lay "' geloescht."))
(prompt (ssg-textf "layer-leerer-geloescht" (list lay)))
)
)
)
(ssg-emsg (strcat "Layer '" lay "' existiert nicht."))
(ssg-emsg (ssg-textf "layer-existiert-nicht" (list lay)))
)
(ssg-end)
)
+2 -1
View File
@@ -24,6 +24,7 @@
)
(load (strcat base-path "ssg_core.lsp") "ssg_core.lsp nicht gefunden")
(ssg-load-config)
(load (strcat base-path "ssg_lang.lsp") "ssg_lang.lsp nicht gefunden")
(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")
@@ -34,7 +35,7 @@
(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")
(prompt "\nSSG-Bibliotheken geladen: ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, KreiselInsert, VarioFoerderer, Gefaellestrecke, export, tests, OmniModulInsert, SSG_LIB_Commands")
(princ)
)
+268 -150
View File
@@ -253,14 +253,14 @@
(setq block-datei (strcat block-pfad blockname ".dwg"))
(if (findfile block-datei)
(progn
(princ (strcat "\n Lade Block: " blockname " ..."))
(princ (ssg-textf "vfc-lade-block" (list blockname)))
(setq temp-obj (vla-InsertBlock modelspace
(vlax-3D-point '(0 0 0))
block-datei 1.0 1.0 1.0 0))
(vla-Delete temp-obj)
(princ " OK")
(princ (ssg-text "vfc-status-ok"))
)
(princ (strcat "\n FEHLER: Block-Datei nicht gefunden: " block-datei))
(princ (ssg-textf "vfc-fehler-block-datei-fehlt" (list block-datei)))
)
)
)
@@ -341,7 +341,7 @@
;; ============================================================
(defun get-3d-point-from-object (msg / ent obj pt variant)
(princ msg)
(princ "\n >> Objekt (Block) waehlen: ")
(princ (ssg-text "vfc-objekt-block-waehlen"))
(setq ent (entsel))
(if ent
(progn
@@ -350,17 +350,17 @@
(progn
(setq variant (vla-get-InsertionPoint obj))
(setq pt (vlax-safearray->list (vlax-variant-value variant)))
(princ (strcat "\n Block-Einfuegepunkt: X=" (rtos (car pt) 2 3)
" Y=" (rtos (cadr pt) 2 3) " Z=" (rtos (caddr pt) 2 3)))
(princ (ssg-textf "vfc-block-einfuegepunkt"
(list (rtos (car pt) 2 3) (rtos (cadr pt) 2 3) (rtos (caddr pt) 2 3))))
)
(progn
(setq pt (cadr ent))
(princ (strcat "\n Punkt auf Objekt: Z=" (rtos (caddr pt) 2 2) " mm"))
(princ (ssg-textf "vfc-punkt-auf-objekt" (list (rtos (caddr pt) 2 2))))
)
)
)
(progn
(princ "\n Kein Objekt gewaehlt.")
(princ (ssg-text "vfc-kein-objekt-gewaehlt"))
(setq pt nil)
)
)
@@ -369,7 +369,7 @@
(defun get-line-start-end-points (msg / ent obj obj-name start-pt end-pt)
(princ msg)
(princ "\n >> 3D-Linie oder Polylinie waehlen: ")
(princ (ssg-text "vfc-linie-polylinie-waehlen"))
(setq ent (entsel))
(if ent
(progn
@@ -381,29 +381,24 @@
(vlax-variant-value (vla-get-StartPoint obj))))
(setq end-pt (vlax-safearray->list
(vlax-variant-value (vla-get-EndPoint obj))))
(princ (strcat "\n 3D-Linie:"
"\n Start: X=" (rtos (car start-pt) 2 2)
" Y=" (rtos (cadr start-pt) 2 2)
" Z=" (rtos (caddr start-pt) 2 2)
"\n Ende: X=" (rtos (car end-pt) 2 2)
" Y=" (rtos (cadr end-pt) 2 2)
" Z=" (rtos (caddr end-pt) 2 2)))
(princ (ssg-textf "vfc-3dlinie-start-ende"
(list (rtos (car start-pt) 2 2) (rtos (cadr start-pt) 2 2) (rtos (caddr start-pt) 2 2)
(rtos (car end-pt) 2 2) (rtos (cadr end-pt) 2 2) (rtos (caddr end-pt) 2 2))))
)
((= obj-name "AcDbPolyline")
(setq start-pt (vlax-curve-getStartPoint obj))
(setq end-pt (vlax-curve-getEndPoint obj))
(princ (strcat "\n 3D-Polylinie:"
"\n Start Z=" (rtos (caddr start-pt) 2 2)
" Ende Z=" (rtos (caddr end-pt) 2 2)))
(princ (ssg-textf "vfc-3dpolylinie-start-ende"
(list (rtos (caddr start-pt) 2 2) (rtos (caddr end-pt) 2 2))))
)
(t
(princ "\n FEHLER: Keine Linie oder Polylinie ausgewaehlt!")
(princ (ssg-text "vfc-fehler-keine-linie"))
(setq start-pt nil end-pt nil)
)
)
)
(progn
(princ "\n Kein Objekt gewaehlt.")
(princ (ssg-text "vfc-kein-objekt-gewaehlt"))
(setq start-pt nil end-pt nil)
)
)
@@ -431,6 +426,14 @@
)
(setq #VF_LetzteNr (max #VF_LetzteNr maxnr))
(setq #VF_LetzteNr (1+ #VF_LetzteNr))
;; Nummern ueberspringen, deren Block-DEFINITION bereits existiert (z.B. Rest
;; eines frueher fehlgeschlagenen Baus, der eine VF_n-Definition ohne INSERT
;; hinterliess). Sonst trifft das spaetere _.-BLOCK auf einen vorhandenen
;; Namen -> "Neu definieren?"-Abfrage verschluckt die Folge-Eingaben ->
;; Block wird nicht korrekt erzeugt ("Eintrag kann nicht erkannt werden").
(while (tblsearch "BLOCK" (strcat "VF_" (itoa #VF_LetzteNr)))
(princ (strcat "\n [VF-Nr] VF_" (itoa #VF_LetzteNr) " existiert bereits, naechste..."))
(setq #VF_LetzteNr (1+ #VF_LetzteNr)))
#VF_LetzteNr
)
@@ -443,18 +446,18 @@
rad-h chv shv ein-x ein-y ein-z dx-loc dy-loc dz-loc offset ausgang)
(if (or (null einfuegepunkt) (not (listp einfuegepunkt)))
(progn
(princ (strcat "\n FEHLER: Ungueltiger Einfuegepunkt fuer '" blockname "'"))
(princ (ssg-textf "vfc-fehler-ungueltiger-einfuegepunkt" (list blockname)))
(exit)
)
)
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(princ (ssg-textf "vfc-fehler-block-nicht-in-bibliothek-abgebrochen" (list blockname)))
(exit)
)
)
(princ (strcat "\n Fuege Block '" blockname "' ein... (hz=" (rtos (float hz) 2 1) (chr 176) ")"))
(princ (ssg-textf "vfc-fuege-block-ein-hz" (list blockname (rtos (float hz) 2 1) (chr 176))))
(setq rad-h (* (float hz) (/ pi 180.0)))
(setq chv (cos rad-h) shv (sin rad-h))
;; KS_EIN/KS_AUS ueber eigenes Temp-Objekt am Ursprung ermitteln (nicht am
@@ -499,13 +502,12 @@
(+ (car einfuegepunkt) (- (* chv dx-loc) (* shv dy-loc)))
(+ (cadr einfuegepunkt) (+ (* shv dx-loc) (* chv dy-loc)))
(+ (caddr einfuegepunkt) dz-loc)))
(princ (strcat "\n KS_AUS: X=" (rtos (car ausgang) 2 2)
" Y=" (rtos (cadr ausgang) 2 2)
" Z=" (rtos (caddr ausgang) 2 2)))
(princ (ssg-textf "vfc-ks-aus-xyz"
(list (rtos (car ausgang) 2 2) (rtos (cadr ausgang) 2 2) (rtos (caddr ausgang) 2 2))))
ausgang
)
(progn
(princ "\n WARNUNG: KS_EIN/KS_AUS nicht gefunden!")
(princ (ssg-text "vfc-warnung-ks-nicht-gefunden"))
einfuegepunkt
)
)
@@ -523,7 +525,7 @@
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek"))
(princ (ssg-textf "vfc-fehler-block-nicht-in-bibliothek" (list blockname)))
(exit)))
;; Ziel-Rahmen auspacken
(setq P-t (car target-frame)
@@ -543,7 +545,7 @@
(setq ks-aus-raw (cadr (assoc "KS_AUS" ks-data)))
(if (not (and ks-ein-raw ks-aus-raw))
(progn
(princ (strcat "\n FEHLER: KS_EIN/KS_AUS fehlen in '" blockname "'"))
(princ (ssg-textf "vfc-fehler-ks-fehlen" (list blockname)))
(exit)))
;; Block am Ursprung einfuegen (Rotation=0, Massstab=1) - dieses Objekt
;; bleibt tatsaechlich in der Zeichnung.
@@ -583,10 +585,8 @@
(setq xu-out (mat3-mul-vec3 R xu-aus)
yu-out (mat3-mul-vec3 R yu-aus)
zu-out (mat3-mul-vec3 R zu-aus))
(princ (strcat "\n '" blockname "' eingefuegt"
"\n KS_AUS: X=" (rtos (car P-out) 2 2)
" Y=" (rtos (cadr P-out) 2 2)
" Z=" (rtos (caddr P-out) 2 2)))
(princ (ssg-textf "vfc-block-eingefuegt-ksaus"
(list blockname (rtos (car P-out) 2 2) (rtos (cadr P-out) 2 2) (rtos (caddr P-out) 2 2))))
(list P-out xu-out yu-out zu-out))
;; Fuegt Block ein: Orientierung wie insert-block-ks-to-ks (KS_EIN-Achsen werden
@@ -613,7 +613,7 @@
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek"))
(princ (ssg-textf "vfc-fehler-block-nicht-in-bibliothek" (list blockname)))
(exit)))
;; Ziel-Rahmen auspacken
(setq P-t (car target-frame)
@@ -633,7 +633,7 @@
(setq ks-aus-raw (cadr (assoc "KS_AUS" ks-data)))
(if (not (and ks-ein-raw ks-aus-raw))
(progn
(princ (strcat "\n FEHLER: KS_EIN/KS_AUS fehlen in '" blockname "'"))
(princ (ssg-textf "vfc-fehler-ks-fehlen" (list blockname)))
(exit)))
;; Block am Ursprung einfuegen (Rotation=0, Massstab=1) - dieses Objekt
;; bleibt tatsaechlich in der Zeichnung.
@@ -681,33 +681,114 @@
(setq xu-out (mat3-mul-vec3 R xu-aus)
yu-out (mat3-mul-vec3 R yu-aus)
zu-out (mat3-mul-vec3 R zu-aus))
(princ (strcat "\n '" blockname "' eingefuegt (XY:" (if xy-ref xy-ref "Ursprung")
" Z:" (if z-ref z-ref "Ursprung") ")"
"\n KS_AUS: X=" (rtos (car P-out) 2 2)
" Y=" (rtos (cadr P-out) 2 2)
" Z=" (rtos (caddr P-out) 2 2)))
(princ (ssg-textf "vfc-block-eingefuegt-xyzref-ksaus"
(list blockname
(if xy-ref xy-ref (ssg-text "vfc-ursprung"))
(if z-ref z-ref (ssg-text "vfc-ursprung"))
(rtos (car P-out) 2 2) (rtos (cadr P-out) 2 2) (rtos (caddr P-out) 2 2))))
(list P-out xu-out yu-out zu-out))
;; ============================================================
;; AS-/ES-Element: Winkel-Variante (30 / 90 Grad)
;; ============================================================
;; Masse (KS_EIN->KS_AUS als (dx dy dz)) eines Elements aus dem Block ziehen.
(defun vf-element-masse (blockname / temp-obj ks-data ke ka)
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
nil
(progn
(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 ke (cadr (assoc "KS_EIN" ks-data)) ka (cadr (assoc "KS_AUS" ks-data)))
(if (and ke ka)
(list (- (caar ka) (caar ke))
(- (cadr (car ka)) (cadr (car ke)))
(- (caddr (car ka)) (caddr (car ke))))
nil))))
;; Ebenen-Schwenk (Grad) eines Elements: Winkel von KS_EIN.xu nach KS_AUS.xu in
;; der XY-Ebene, direkt aus dem Block gemessen (unabhaengig davon, ob 30/90-Turn
;; oder gerade). Wird genutzt, um KS_EIN so zu drehen, dass KS_AUS entlang hz
;; zeigt: ein-hz = hz - plan-turn. Fallback 90 (Vorgabe fuer 90-Grad-Element).
(defun vf-element-plan-turn (blockname / temp-obj ks-data fe fa)
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
90.0
(progn
(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 fe (ks-frame-extract (cadr (assoc "KS_EIN" ks-data))))
(setq fa (ks-frame-extract (cadr (assoc "KS_AUS" ks-data))))
(if (and fe fa)
(- (* (atan (cadr (cadr fa)) (car (cadr fa))) (/ 180.0 pi))
(* (atan (cadr (cadr fe)) (car (cadr fe))) (/ 180.0 pi)))
90.0))))
;; KS-Info eines Elements (im Block, Einbau-Rotation 0):
;; Rueckgabe (ein-ang aus-ang vx vy)
;; ein-ang / aus-ang : Ebenen-Winkel (Grad) von KS_EIN.xu bzw. KS_AUS.xu
;; vx / vy : KS_AUS.origin - KS_EIN.origin (Block-XY)
;; Damit laesst sich die KS_AUS-Lage + Achsrichtung analytisch vorausberechnen.
(defun vf-element-ks-info (blockname / temp-obj ks-data fe fa)
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
nil
(progn
(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 fe (ks-frame-extract (cadr (assoc "KS_EIN" ks-data))))
(setq fa (ks-frame-extract (cadr (assoc "KS_AUS" ks-data))))
(if (and fe fa)
(list (* (atan (cadr (cadr fe)) (car (cadr fe))) (/ 180.0 pi))
(* (atan (cadr (cadr fa)) (car (cadr fa))) (/ 180.0 pi))
(- (car (car fa)) (car (car fe)))
(- (cadr (car fa)) (cadr (car fe))))
nil))))
;; 30/90-Wahl fuer ein AS/ES-Element. Rueckgabe: "30" oder "90" (Vorgabe 90).
;; headerkey: i18n-Key fuer die Kopfzeile ("vf-winkel-aus-header" oder
;; "vf-winkel-ein-header"). Rueckgabe: "30" oder "90" (Default 90).
(defun vf-frage-element-winkel (headerkey)
(princ (ssg-text headerkey))
(princ (ssg-text "vf-winkel-90"))
(princ (ssg-text "vf-winkel-30"))
(if (= (getstring (ssg-text "prompt-wahl-1-2")) "2") "30" "90"))
;; AS-/ES-Masse-Globals (aus-dx/dy/dz bzw. ein-dx/dy/dz) fuer die gewaehlte
;; Winkel-/Seiten-Variante neu setzen (fuer berechne-alle-winkel, GF-Winkel,
;; Trimmungen). Ohne gueltigen Block bleiben die Werte unveraendert.
(defun vf-set-as-masse (winkel seite / m)
(setq m (vf-element-masse (strcat "AS_Element_" winkel "_" seite)))
(if m (setq aus-dx (car m) aus-dy (cadr m) aus-dz (caddr m))))
(defun vf-set-es-masse (winkel seite / m)
(setq m (vf-element-masse (strcat "ES_Element_" winkel "_" seite)))
(if m (setq ein-dx (car m) ein-dy (cadr m) ein-dz (caddr m))))
;; hz: horizontale Fahrtrichtung in Grad (0=Ost/+X, 90=Nord/+Y, ...),
;; winkel: vertikale Neigung in Grad. Rotation = Rz(hz)*Ry(winkel).
(defun insert-inclined-scaled-block (blockname startpunkt laenge winkel hz /
rad-v rad-h chv shv cvv svv matrix block-obj endpunkt scale)
(if (<= laenge 0.1)
(progn
(princ (strcat "\n Laenge=" (rtos laenge 2 2) " mm -> uebersprungen"))
(princ (ssg-textf "vfc-laenge-uebersprungen" (list (rtos laenge 2 2))))
startpunkt
)
(progn
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(princ (ssg-textf "vfc-fehler-block-nicht-in-bibliothek-abgebrochen" (list blockname)))
(exit)
)
)
(princ (strcat "\n Fuege '" blockname "' ein"
" (L=" (rtos laenge 2 2) " mm, W=" (itoa winkel) (chr 176)
" hz=" (rtos (float hz) 2 1) (chr 176) ")"))
(princ (ssg-textf "vfc-fuege-ein-lwhz"
(list blockname (rtos laenge 2 2) (itoa winkel) (chr 176) (rtos (float hz) 2 1) (chr 176))))
(setq scale (/ laenge (ssg-cfg-or "vario" "skalierung_basis" 1000.0)))
(setq rad-v (* (float winkel) (/ pi 180.0)))
(setq rad-h (* (float hz) (/ pi 180.0)))
@@ -729,9 +810,8 @@
(+ (car startpunkt) (* laenge chv cvv))
(+ (cadr startpunkt) (* laenge shv cvv))
(+ (caddr startpunkt) (* laenge (- svv)))))
(princ (strcat "\n Endpunkt: X=" (rtos (car endpunkt) 2 2)
" Y=" (rtos (cadr endpunkt) 2 2)
" Z=" (rtos (caddr endpunkt) 2 2)))
(princ (ssg-textf "vfc-endpunkt-xyz"
(list (rtos (car endpunkt) 2 2) (rtos (cadr endpunkt) 2 2) (rtos (caddr endpunkt) 2 2))))
endpunkt
)
)
@@ -759,20 +839,19 @@
dx dz ins-pt endpunkt)
(if (or (null startpunkt) (not (listp startpunkt)))
(progn
(princ (strcat "\n FEHLER: Ungueltiger Einfuegepunkt fuer '" blockname "'"))
(princ (ssg-textf "vfc-fehler-ungueltiger-einfuegepunkt" (list blockname)))
startpunkt
)
(progn
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(princ (ssg-textf "vfc-fehler-block-nicht-in-bibliothek-abgebrochen" (list blockname)))
(exit)
)
)
(princ (strcat "\n Fuege Block '" blockname "' ein"
" (Rotation " (itoa winkel) (chr 176)
" hz=" (rtos (float hz) 2 1) (chr 176) ")"))
(princ (ssg-textf "vfc-fuege-block-ein-rotation-hz"
(list blockname (itoa winkel) (chr 176) (rtos (float hz) 2 1) (chr 176))))
(setq rad-v (* winkel (/ pi 180.0)))
(setq rad-h (* (float hz) (/ pi 180.0)))
(setq chv (cos rad-h) shv (sin rad-h) cvv (cos rad-v) svv (sin rad-v))
@@ -828,10 +907,9 @@
(+ (car startpunkt) (+ (* dx chv cvv) (* dz chv svv)))
(+ (cadr startpunkt) (+ (* dx shv cvv) (* dz shv svv)))
(+ (caddr startpunkt) (+ (* dx (- svv)) (* dz cvv)))))
(princ (strcat "\n Endpunkt: X=" (rtos (car endpunkt) 2 2)
" Y=" (rtos (cadr endpunkt) 2 2)
" Z=" (rtos (caddr endpunkt) 2 2)
" (dx=" (rtos dx 2 1) " dz=" (rtos dz 2 1) ")"))
(princ (ssg-textf "vfc-endpunkt-xyz-dxdz"
(list (rtos (car endpunkt) 2 2) (rtos (cadr endpunkt) 2 2) (rtos (caddr endpunkt) 2 2)
(rtos dx 2 1) (rtos dz 2 1))))
endpunkt
)
)
@@ -842,24 +920,24 @@
;; ============================================================
(defun vf-eingabe-abfragen ( / eingabe-modus line-points startpunkt endpunkt differenz
deltaL deltaH deltaX deltaY richtung antwort hz-winkel)
(princ "\n\nEingabemodus waehlen:")
(princ "\n 1 - 3D-Linie auswaehlen (Start- und Endpunkt mit Hoehe)")
(princ "\n 2 - Werte manuell eingeben")
(setq antwort (getstring "\nIhre Wahl (1/2): "))
(princ (ssg-text "vfc-eingabemodus-header"))
(princ (ssg-text "vfc-eingabemodus-3dlinie"))
(princ (ssg-text "vfc-eingabemodus-werte"))
(setq antwort (getstring (ssg-text "vfc-prompt-wahl-1-2-ohne-default")))
(cond
((= antwort "1") (setq eingabe-modus "Linie"))
((= antwort "2") (setq eingabe-modus "Wert"))
(t (setq eingabe-modus "Linie") (princ "\nModus: 3D-Linie"))
(t (setq eingabe-modus "Linie") (princ (ssg-text "vfc-modus-3dlinie-fallback")))
)
(if (= eingabe-modus "Linie")
(progn
(princ "\n\n>>> MODUS: 3D-Linie auswaehlen <<<")
(princ (ssg-text "vfc-modus-3dlinie-header"))
(command "BKS" "W")
(princ "\n BKS auf Weltkoordinaten gesetzt.")
(princ (ssg-text "vfc-bks-weltkoordinaten"))
(setq line-points
(get-line-start-end-points "\nBitte 3D-Linie fuer die Foerderstrecke auswaehlen:"))
(get-line-start-end-points (ssg-text "vfc-bitte-3dlinie-foerderstrecke")))
(if (null line-points)
(progn (alert "Keine gueltige Linie ausgewaehlt!") (exit))
(progn (alert (ssg-text "vfc-alert-keine-gueltige-linie")) (exit))
)
(setq startpunkt (car line-points)
endpunkt (cadr line-points))
@@ -871,20 +949,19 @@
;; Fahrtrichtung aus der Linie ableiten (0=Ost, 90=Nord, ...)
(setq hz-winkel
(* (angle '(0.0 0.0) (list (car differenz) (cadr differenz))) (/ 180.0 pi)))
(princ (strcat "\n △L=" (rtos deltaL 2 2) " mm"
" △H=" (rtos deltaH 2 2) " mm"
" Fahrtrichtung=" (rtos hz-winkel 2 1) grad-zeichen))
(princ (ssg-textf "vfc-delta-l-h-richtung"
(list (chr 916) (rtos deltaL 2 2) (rtos deltaH 2 2) (rtos hz-winkel 2 1) grad-zeichen)))
(if (>= deltaH 0)
(progn (setq richtung "Auf") (princ "\n Foerderrichtung: AUF"))
(progn (setq richtung "Auf") (princ (ssg-text "vfc-foerderrichtung-auf")))
(progn (setq richtung "Ab") (setq deltaH (abs deltaH))
(princ "\n Foerderrichtung: AB"))
(princ (ssg-text "vfc-foerderrichtung-ab")))
)
)
(progn
(princ "\n\n>>> MODUS: Manuelle Werteingabe <<<")
(setq deltaL (getreal "\n△L - Horizontale Distanz (mm): "))
(princ (ssg-text "vfc-modus-werteingabe-header"))
(setq deltaL (getreal (ssg-textf "vfc-prompt-delta-l" (list (chr 916)))))
(if (null deltaL) (setq deltaL 15000))
(setq deltaH (getreal "\n△H - Hoehenunterschied (mm): "))
(setq deltaH (getreal (ssg-textf "vfc-prompt-delta-h" (list (chr 916)))))
(if (null deltaH) (setq deltaH 3000))
;; Foerderrichtung bleibt eine einfache Auf/Ab-Frage - die horizontale
;; Zwischenstrecke ist geometrisch NUR bei "Ab" ueberhaupt erreichbar
@@ -892,25 +969,25 @@
;; erst SPAETER, nach Bibliotheks-Init, als Zusatzoption in der
;; Winkel-Auswahl angeboten (siehe c:VarioFoerderer) - einheitlich fuer
;; Werteingabe UND 3D-Linie.
(princ "\nFoerderrichtung:\n 1 - AUF\n 2 - AB")
(setq antwort (getstring "\nIhre Wahl (1/2): "))
(princ (ssg-text "vfc-foerderrichtung-menu"))
(setq antwort (getstring (ssg-text "vfc-prompt-wahl-1-2-ohne-default")))
(if (= antwort "2") (setq richtung "Ab") (setq richtung "Auf"))
(setq startpunkt (getpoint "\nStartpunkt fuer AUS_Element waehlen: "))
(setq startpunkt (getpoint (ssg-text "vfc-prompt-startpunkt-aus")))
(if (null startpunkt) (setq startpunkt '(0 0 0)))
;; Horizontale Fahrtrichtung waehlen (analog Gefaellestrecke Modus 1)
(princ "\n\nFahrtrichtung waehlen:")
(princ "\n 1 - 0° (X-Achse +, Ost)")
(princ "\n 2 - 90° (Y-Achse +, Nord)")
(princ "\n 3 - 180° (X-Achse -, West)")
(princ "\n 4 - 270° (Y-Achse -, Sued)")
(setq antwort (getstring "\nIhre Wahl (1/2/3/4) [1]: "))
(princ (ssg-text "vfc-fahrtrichtung-header"))
(princ (ssg-textf "vfc-fahrtrichtung-0" (list grad-zeichen)))
(princ (ssg-textf "vfc-fahrtrichtung-90" (list grad-zeichen)))
(princ (ssg-textf "vfc-fahrtrichtung-180" (list grad-zeichen)))
(princ (ssg-textf "vfc-fahrtrichtung-270" (list grad-zeichen)))
(setq antwort (getstring (ssg-text "prompt-wahl-1-2-3-4")))
(cond
((= antwort "2") (setq hz-winkel 90.0))
((= antwort "3") (setq hz-winkel 180.0))
((= antwort "4") (setq hz-winkel 270.0))
(t (setq hz-winkel 0.0))
)
(princ (strcat "\n>>> Fahrtrichtung: " (rtos hz-winkel 2 1) grad-zeichen))
(princ (ssg-textf "vfc-fahrtrichtung-ergebnis" (list (rtos hz-winkel 2 1) grad-zeichen)))
)
)
(list deltaL deltaH richtung startpunkt hz-winkel eingabe-modus)
@@ -938,7 +1015,7 @@
(setq L_GF_str (strcat (rtos (/ L_GF1 1000.0) 2 3) "," (rtos (/ L_GF2 1000.0) 2 3)))
(setq label-txt
(strcat "VF" (itoa vf-nummer)
": von " (itoa (fix hoehe-von)) "mm bis " (itoa (fix hoehe-bis)) "mm, "
(ssg-textf "vfc-label-von-bis" (list (itoa (fix hoehe-von)) (itoa (fix hoehe-bis))))
delta-sym "H=" (itoa (fix deltaH)) "mm; "
delta-sym "L=" (itoa (fix deltaL)) "mm; "
"VF:" L_VF_str "m; GF:" L_GF_str "m; "
@@ -996,8 +1073,11 @@
(defun vf-block-erstellen (anlage-typ seite vf-nummer n-scanner
hoehe-von hoehe-bis deltaH deltaL L_VF L_GF1 L_GF2
richtung best-winkel startpunkt lastEnt hz
geruest-einzelmodul geruest-typ
/ vf-bname vf-ss vf-e vf-insert montagehoehe-m attdef-ypos L_GF_m-str)
(if (null hz) (setq hz 0.0))
(if (null geruest-einzelmodul) (setq geruest-einzelmodul "1"))
(if (null geruest-typ) (setq geruest-typ (ssg-geruest-idx-to-typ (ssg-geruest-typ-to-idx nil))))
;; Beschriftungstext erzeugen
(vf-make-label vf-nummer hoehe-von hoehe-bis deltaH deltaL L_VF L_GF1 L_GF2
richtung best-winkel 2 n-scanner startpunkt hz)
@@ -1035,12 +1115,11 @@
(setq vf-bname (strcat "VF_" (itoa vf-nummer)))
(if (> (sslength vf-ss) 0)
(progn
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
(command "_.-BLOCK" vf-bname startpunkt vf-ss "")
(command "_.INSERT" vf-bname startpunkt 1.0 1.0 0.0)
(setvar "ATTREQ" 1)
(setq vf-insert (entlast))
;; Block definieren und einfuegen mit garantiert weltparallelem BKS.
;; startpunkt ist ein Welt-Punkt; ssg-block-wrap-welt setzt das BKS
;; temporaer auf Welt (verhindert den 31.95mm-Z-Versatz bei
;; abweichendem BKS) und stellt es danach wieder her.
(setq vf-insert (ssg-block-wrap-welt vf-bname startpunkt vf-ss))
(setq montagehoehe-m (/ (+ hoehe-von hoehe-bis) 2000.0))
;; L_GF_m: kommagetrennte Segmentlaengen in Metern (vorne,hinten),
;; analog L_GF_m in Gefaellestrecke.lsp.
@@ -1048,7 +1127,7 @@
(ssg-attrib-set-on vf-insert
(list
(cons "Bezeichnung" vf-bname)
;; Artinr. bleibt auf Schema-Vorgabe "6220"
;; ARTINR bleibt auf Schema-Vorgabe "6220"
(cons "MONTAGEHOEHE_m" (rtos montagehoehe-m 2 3))
(cons "HOEHE_VON_mm" (itoa (fix hoehe-von)))
(cons "HOEHE_BIS_mm" (itoa (fix hoehe-bis)))
@@ -1069,6 +1148,8 @@
(cons "VF_WINKEL" (itoa best-winkel))
(cons "ANZAHL_SEPARATOR" "2")
(cons "ANZAHL_SCANNER" (itoa n-scanner))
(cons "GERUEST_EINZELMODUL" geruest-einzelmodul)
(cons "GERUEST_TYP" geruest-typ)
)
)
;; Typ-spezifische Bogen-Zaehler (Etage: 2x Gefaellebogen je Seite)
@@ -1081,9 +1162,10 @@
;; Aufsteigende, eindeutige ID vergeben (wie beim Kreisel), falls verfuegbar.
(if (car (atoms-family 1 '("SSG-ID-GENERATE")))
(ssg-id-generate vf-insert))
(princ (strcat "\n>>> Block '" vf-bname "' erstellt und eingefuegt."))
(princ (ssg-textf "vfc-block-erstellt-eingefuegt" (list vf-bname)))
vf-insert
)
(princ "\n>>> FEHLER: Keine Entities fuer Block gefunden!")
(progn (princ (ssg-text "vfc-fehler-keine-entities")) nil)
)
)
@@ -1126,16 +1208,16 @@
best-winkel L_GF L_GF1 L_GF2 L_VF
idx eintrag wahl antwort verteilung-modus
n-scanner vf-nummer hoehe-von hoehe-bis lastEnt
staustrecke-basis)
staustrecke-basis vf-insert)
(princ "\n=========================================")
(princ "\n VARIOFOERDERER GENERATOR v26.0")
(princ (ssg-text "vfc-banner-titel"))
(princ "\n=========================================")
;; 1. Typ aus Registry waehlen
(if (null *vf-typ-registry*)
(progn
(alert "Keine Typen registriert!\nvf_standard.lsp und vf_etage.lsp pruefen.")
(alert (ssg-text "vfc-alert-keine-typen"))
(exit)
)
)
@@ -1143,19 +1225,19 @@
(if (and *vf-vorauswahl-typ* (assoc *vf-vorauswahl-typ* *vf-typ-registry*))
(progn
(setq typ-eintr (assoc *vf-vorauswahl-typ* *vf-typ-registry*))
(princ (strcat "\n>>> Typ vorgewaehlt: " *vf-vorauswahl-typ*))
(princ (ssg-textf "vfc-typ-vorgewaehlt" (list *vf-vorauswahl-typ*)))
(setq *vf-vorauswahl-typ* nil)
)
(progn
(setq *vf-vorauswahl-typ* nil)
(princ "\n\nAnlagen-Typ waehlen:")
(princ (ssg-text "vfc-anlagen-typ-header"))
(setq idx 1)
(foreach eintr *vf-typ-registry*
(princ (strcat "\n " (itoa idx) " - " (nth 3 eintr)))
(princ (ssg-textf "vfc-typ-option" (list idx (nth 3 eintr))))
(setq idx (1+ idx))
)
(setq wahl (getint (strcat "\nIhre Wahl (1-"
(itoa (length *vf-typ-registry*)) ") [1]: ")))
(setq wahl (getint (ssg-textf "vfc-prompt-wahl-1-n"
(list (length *vf-typ-registry*)))))
(if (or (null wahl) (< wahl 1) (> wahl (length *vf-typ-registry*)))
(setq wahl 1))
(setq typ-eintr (nth (1- wahl) *vf-typ-registry*))
@@ -1164,7 +1246,7 @@
(setq anlage-typ (nth 0 typ-eintr))
(setq berechne-fn (nth 1 typ-eintr))
(setq einfuege-fn (nth 2 typ-eintr))
(princ (strcat "\n>>> Typ: " anlage-typ))
(princ (ssg-textf "vfc-typ-gewaehlt" (list anlage-typ)))
;; Sonderfall "linienzug": eigener Befehlsablauf (interaktive Mehrsegment-
;; Kette mit gemischten GF/VF-Segmenten), passt nicht in das berechne-fn/
@@ -1172,14 +1254,44 @@
;; vf_linienzug.lsp. Dispatcht hier direkt und beendet den Standard-Ablauf.
(if (= anlage-typ "linienzug")
(progn
(vf-linienzug-modus)
(princ "\n\nLinienzug-Modus waehlen:")
(princ "\n 1 - Manuelle Eingabe (Punkte klicken)")
(princ "\n 2 - 3D-Objekte + Ziel-Hoehe (Randwert-Solver, fertig)")
(princ "\n 3 - 3D-Objekte stueckweise (Vorwaerts-Nachbau, in Arbeit)")
(setq wahl (getint "\nIhre Wahl (1/2/3) [1]: "))
;; Konsolen-Nummer -> interne Funktion:
;; 2 = fertiger Ziel-Hoehe-Modus (intern vf-linienzug-modus2)
;; 3 = alter Vorwaerts-Nachbau (intern vf-linienzug-modus3, wird umgebaut)
(cond ((= wahl 2) (vf-linienzug-modus2))
((= wahl 3) (vf-linienzug-modus3))
(t (vf-linienzug-modus)))
(exit)
)
)
;; 2. VF-Nummer automatisch ermitteln
(setq vf-nummer (vf-next-number))
(princ (strcat "\n>>> Naechste VF-Nummer: VF" (itoa vf-nummer)))
(princ (ssg-textf "vfc-naechste-vf-nummer" (list (itoa vf-nummer))))
;; 2b. Standardfall (anlage-typ "standard") + Werteingabe -> DCL-Dialog
;; (dcl/variofoerderer.dcl, siehe vf_standard.lsp: vfs-standard-dialog-ablauf).
;; 3D-Linie-Eingabe und alle anderen Anlagen-Typen (Etage, Linienzug) bleiben
;; unveraendert interaktiv (fallen unten in den bestehenden Konsolen-Ablauf,
;; der die Eingabemodus-Frage dabei erneut stellt - siehe vf-eingabe-abfragen).
(if (= anlage-typ "standard")
(progn
(princ (ssg-text "vfc-eingabemodus-header"))
(princ (ssg-text "vfc-eingabemodus-3dlinie"))
(princ (ssg-text "vfc-eingabemodus-werte"))
(setq antwort (getstring (ssg-text "vfc-prompt-wahl-1-2-ohne-default")))
(if (= antwort "2")
(progn
(vfs-standard-dialog-ablauf vf-nummer)
(exit)
)
)
)
)
;; 3. Gemeinsame Eingabe (deltaL, deltaH, richtung, startpunkt) - richtung
;; steht bei beiden Eingabemodi (Werteingabe UND 3D-Linie) bereits fest.
@@ -1192,12 +1304,12 @@
eingabe-modus (nth 5 eingabe))
;; 4. Seite-Auswahl (vor Berechnung, weil Etage-Typ sie fuer Geometrie braucht)
(princ "\n\nSeite waehlen:")
(princ "\n 1 - Rechts")
(princ "\n 2 - Links")
(setq antwort (getstring "\nIhre Wahl (1/2) [1]: "))
(princ (ssg-text "vfc-seite-header"))
(princ (ssg-text "vfc-seite-rechts"))
(princ (ssg-text "vfc-seite-links"))
(setq antwort (getstring (ssg-text "prompt-wahl-1-2")))
(if (= antwort "2") (setq seite "links") (setq seite "rechts"))
(princ (strcat "\n>>> Seite: " seite))
(princ (ssg-textf "vfc-seite-gewaehlt" (list seite)))
;; 5. Typ-spezifische Berechnung (init + Winkelsuche)
(setq ergebnis (apply berechne-fn (list deltaL deltaH richtung seite)))
@@ -1216,7 +1328,7 @@
(setq ergebnis-liste
(append ergebnis-liste
(list (list 0 (car horizontal-info) (cadr horizontal-info) T))))
(princ "\n\n>>> Hinweis: Ein horizontale Variofoerderer ( 0°) ist bei diesem △L/△H zusaetzlich moeglich!")
(princ (ssg-textf "vfc-hinweis-horizontal-moeglich" (list (chr 176) (chr 916))))
)
(setq horizontal-info nil)
)
@@ -1236,9 +1348,8 @@
ergebnis-liste)))
(if (null gueltige-winkel)
(progn
(alert (strcat "Kein passender Winkel gefunden!\n"
"△L=" (rtos deltaL 2 0) " mm, △H="
(rtos deltaH 2 0) " mm, Richtung=" richtung))
(alert (ssg-textf "vfc-alert-kein-winkel"
(list (chr 916) (rtos deltaL 2 0) (rtos deltaH 2 0) richtung)))
(exit)
)
)
@@ -1252,29 +1363,27 @@
(setq eintrag (assoc best-winkel ergebnis-liste))
(setq L_GF (nth 1 eintrag) L_VF (nth 2 eintrag))
(if (= best-winkel 0)
(princ "\n\n>>> Einzige gueltige Variante: Horizontale Variofoerderer")
(princ (strcat "\n\n>>> Einziger gueltiger Winkel: "
(itoa best-winkel) (chr 176)))
(princ (ssg-text "vfc-einzige-variante-horizontal"))
(princ (ssg-textf "vfc-einziger-winkel" (list (itoa best-winkel) (chr 176))))
)
)
(progn
(princ "\n\nMehrere gueltige Winkel verfuegbar. Bitte waehlen:")
(princ (ssg-text "vfc-mehrere-winkel-header"))
(setq idx 1)
(foreach w gueltige-winkel
(setq eintrag (assoc w ergebnis-liste))
(if (= w 0)
(princ (strcat "\n " (itoa idx) " - Horizontale Variofoerderer (0"
(chr 176) ")"
" (L_GF=" (rtos (nth 1 eintrag) 2 1)
" mm, L_VF=" (rtos (nth 2 eintrag) 2 1) " mm)"))
(princ (strcat "\n " (itoa idx) " - " (itoa w) (chr 176)
" (L_GF=" (rtos (nth 1 eintrag) 2 1)
" mm, L_VF=" (rtos (nth 2 eintrag) 2 1) " mm)"))
(princ (ssg-textf "vfc-winkel-option-horizontal"
(list idx (chr 176)
(rtos (nth 1 eintrag) 2 1) (rtos (nth 2 eintrag) 2 1))))
(princ (ssg-textf "vfc-winkel-option"
(list idx (itoa w) (chr 176)
(rtos (nth 1 eintrag) 2 1) (rtos (nth 2 eintrag) 2 1))))
)
(setq idx (1+ idx))
)
(setq wahl (getint (strcat "Winkel waehlen (1-"
(itoa (length gueltige-winkel)) ") [1]: ")))
(setq wahl (getint (ssg-textf "vfc-prompt-winkel-waehlen"
(list (length gueltige-winkel)))))
(if (or (null wahl) (< wahl 1) (> wahl (length gueltige-winkel)))
(setq wahl 1))
(setq best-winkel (nth (1- wahl) gueltige-winkel))
@@ -1284,22 +1393,20 @@
)
(princ "\n\n=========================================")
(if (= best-winkel 0)
(princ (strcat "\n>>> Horizontale Variofoerderer"
" L_GF: " (rtos L_GF 2 2) " mm"
" L_VF: " (rtos L_VF 2 2) " mm"))
(princ (strcat "\n>>> Winkel: " (itoa best-winkel) (chr 176)
" L_GF: " (rtos L_GF 2 2) " mm"
" L_VF: " (rtos L_VF 2 2) " mm"))
(princ (ssg-textf "vfc-zus-horizontal"
(list (rtos L_GF 2 2) (rtos L_VF 2 2))))
(princ (ssg-textf "vfc-zus-winkel"
(list (itoa best-winkel) (chr 176) (rtos L_GF 2 2) (rtos L_VF 2 2))))
)
(princ "\n=========================================")
;; 9. L_GF Verteilung
(princ "\n\nVerteilung der Gefaellestrecken (vorne/hinten):")
(princ "\n 1 - Gleichmaessig (L_GF1 = L_GF2 = L_GF/2)")
(princ "\n 2 - Vorne Minimum, hinten Rest")
(princ "\n 3 - Hinten Minimum, vorne Rest")
(princ "\n 4 - Eigene Werte eingeben")
(setq verteilung-modus (getstring "\nIhre Wahl (1/2/3/4) [1]: "))
(princ (ssg-text "vfc-gf-verteilung-header"))
(princ (ssg-text "vfc-gf-verteilung-1"))
(princ (ssg-text "vfc-gf-verteilung-2"))
(princ (ssg-text "vfc-gf-verteilung-3"))
(princ (ssg-text "vfc-gf-verteilung-4"))
(setq verteilung-modus (getstring (ssg-text "prompt-wahl-1-2-3-4")))
(if (= verteilung-modus "") (setq verteilung-modus "1"))
(cond
((= verteilung-modus "1")
@@ -1311,23 +1418,22 @@
(setq L_GF2 (float staustrecke-basis))
(setq L_GF1 (max 0.0 (- L_GF (float staustrecke-basis)))))
((= verteilung-modus "4")
(setq L_GF1 (getreal (strcat "\nL_GF1 vorne (mm) ["
(rtos (/ L_GF 2.0) 2 2) "]: ")))
(setq L_GF1 (getreal (ssg-textf "vfc-prompt-lgf1-vorne"
(list (rtos (/ L_GF 2.0) 2 2)))))
(if (null L_GF1) (setq L_GF1 (/ L_GF 2.0)))
(setq L_GF2 (max 0.0 (- L_GF L_GF1)))
(princ (strcat "\n L_GF2 hinten: " (rtos L_GF2 2 2) " mm")))
(princ (ssg-textf "vfc-lgf2-hinten" (list (rtos L_GF2 2 2)))))
(t (setq L_GF1 (/ L_GF 2.0) L_GF2 (/ L_GF 2.0)))
)
(princ (strcat "\n>>> L_GF1=" (rtos L_GF1 2 2)
" mm L_GF2=" (rtos L_GF2 2 2) " mm"))
(princ (ssg-textf "vfc-zus-lgf" (list (rtos L_GF1 2 2) (rtos L_GF2 2 2))))
;; Scanner-Anzahl wird nicht mehr abgefragt (Attribut ANZAHL_SCANNER bleibt 0).
(setq n-scanner 0)
;; 11. Bestaetigung
(princ "\n\nMoechten Sie die Foerderanlage einfuegen?")
(princ "\n 1 - Ja, Module einfuegen\n 2 - Nein, abbrechen")
(setq antwort (getstring "\nIhre Wahl (1/2): "))
(princ (ssg-text "vfc-einfuegen-frage"))
(princ (ssg-text "vfc-einfuegen-optionen"))
(setq antwort (getstring (ssg-text "vfc-prompt-wahl-1-2-ohne-default")))
(if (= antwort "1")
(progn
@@ -1346,13 +1452,25 @@
(list deltaL deltaH richtung best-winkel L_GF1 L_GF2 L_VF startpunkt seite hz))
;; Gemeinsame VF_*-Block-Erstellung
;; Geruest fuer Einzelmodul/Geruestoption sind in diesem interaktiven
;; Konsolen-Ablauf (Etage/Linienzug) nicht abfragbar - bleiben auf
;; Schema-Default (analog Kreisel: nur ueber Dialog editierbar).
(setq vf-insert
(vf-block-erstellen anlage-typ seite vf-nummer n-scanner
hoehe-von hoehe-bis deltaH deltaL L_VF L_GF1 L_GF2
richtung best-winkel startpunkt lastEnt hz)
richtung best-winkel startpunkt lastEnt hz
"0" "Schoenenberger Geruest"))
;; Standard-Bloecke aus dem interaktiven Konsolen-Ablauf ebenfalls mit der
;; SSG_VF_EDIT-XDATA markieren - sie sind (wie die Dialog-Variante) aus
;; Attributen + hz verlustfrei rekonstruierbar, also per Doppelklick
;; (c:VARIOFOERDERER_EDIT) editierbar. Etage/Linienzug bleiben unmarkiert.
(if (and vf-insert (= anlage-typ "standard"))
(vfs-xdata-schreiben vf-insert hz))
(princ "\n=========================================")
)
(princ "\nVorgang abgebrochen.")
(princ (ssg-text "vfc-vorgang-abgebrochen"))
)
nil
)
+173 -133
View File
@@ -21,7 +21,7 @@
(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!")
(princ (ssg-text "vfe-warn-lisp-pfad"))
(exit)
)
)
@@ -40,7 +40,11 @@
(setq FESTE_ETAGE_MITTE 1000)
(setq ETAGE_SCHRAEG_LAENGE 700)
(setq ETAGE_HZ_WINKEL 60)
;; Schwenkwinkel der Ein-/Auslauf-Schraegsektionen: 30 Grad (AS_30/ES_30 +
;; 30-Grad-Gefaellebogen). War frueher 60. Nur noch im Laengen-/Hoehen-Budget
;; berechne-winkel-etage (schraeg-cos) verwendet; die fruehere absolute
;; hz-Platzierung wurde durch Frame-Verkettung (cur-hz) ersetzt.
(setq ETAGE_HZ_WINKEL 30)
;; ============================================================
;; TEIL 2: BIBLIOTHEK INITIALISIEREN (ETAGE-SPEZIFISCH)
@@ -50,9 +54,9 @@
(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 (ssg-text "vfe-bib-bereits-init")) t)
(progn
(princ "\n Initialisiere Etage-Bibliothek...")
(princ (ssg-text "vfe-bib-initialisiere"))
;; Standard-Bogen-Daten laden (bogen-auf/bogen-ab benoetigt)
(if (not *lib-initialized*)
@@ -60,7 +64,7 @@
)
;; AS_30_rechts Masse extrahieren
(princ "\n Extrahiere AS_30_rechts Masse...")
(princ (ssg-text "vfe-extrahiere-as30"))
(ensure-block-loaded "AS_Element_30_rechts")
(ensure-block-loaded "AS_Element_30_links")
(if (tblsearch "BLOCK" "AS_Element_30_rechts")
@@ -79,23 +83,22 @@
(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"))
(princ (ssg-textf "vfe-as30-mass" (list (rtos etage-aus-dx 2 1) (rtos etage-aus-dz 2 1))))
)
(progn
(princ "\n WARNUNG: KS fehlt - Standardwerte")
(princ (ssg-text "vfe-warn-ks-fehlt-standard"))
(setq etage-aus-dx 525.8 etage-aus-dz -72.9)
)
)
)
(progn
(princ "\n WARNUNG: Block AS_Element_30_rechts fehlt - Standardwerte")
(princ (ssg-text "vfe-warn-block-as30-fehlt"))
(setq etage-aus-dx 525.8 etage-aus-dz -72.9)
)
)
;; ES_30_rechts Masse extrahieren
(princ "\n Extrahiere ES_30_rechts Masse...")
(princ (ssg-text "vfe-extrahiere-es30"))
(ensure-block-loaded "ES_Element_30_rechts")
(ensure-block-loaded "ES_Element_30_links")
(if (tblsearch "BLOCK" "ES_Element_30_rechts")
@@ -114,24 +117,23 @@
(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"))
(princ (ssg-textf "vfe-es30-mass" (list (rtos etage-ein-dx 2 1) (rtos etage-ein-dz 2 1))))
)
(progn
(princ "\n WARNUNG: KS fehlt - Standardwerte")
(princ (ssg-text "vfe-warn-ks-fehlt-standard"))
(setq etage-ein-dx 576.2 etage-ein-dz -54.6)
)
)
)
(progn
(princ "\n WARNUNG: Block ES_Element_30_rechts fehlt - Standardwerte")
(princ (ssg-text "vfe-warn-block-es30-fehlt"))
(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..."))
;; Gefaellebogen_links_30 Masse extrahieren
(setq gefaelle-blockname "Gefaellebogen_links_30_R500")
(princ (ssg-textf "vfe-extrahiere-block-mass" (list gefaelle-blockname)))
(ensure-block-loaded gefaelle-blockname)
(if (tblsearch "BLOCK" gefaelle-blockname)
(progn
@@ -150,22 +152,21 @@
(setq etage-gef-dz-links (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
)
(progn
(princ "\n WARNUNG: kein KS - Standardwerte (links)")
(princ (ssg-text "vfe-warn-kein-ks-links"))
(setq etage-gef-dx-links 0.0 etage-gef-dz-links -10.0)
)
)
)
(progn
(princ "\n WARNUNG: Block fehlt - Standardwerte (links)")
(princ (ssg-text "vfe-warn-block-fehlt-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"))
(princ (ssg-textf "vfe-gefaellebogen-links-mass" (list (rtos etage-gef-dx-links 2 2) (rtos etage-gef-dz-links 2 2))))
;; Gefaellebogen_rechts_60 Masse extrahieren
(setq gefaelle-blockname "Gefaellebogen_rechts_60_R500")
(princ (strcat "\n Extrahiere " gefaelle-blockname " Masse..."))
;; Gefaellebogen_rechts_30 Masse extrahieren
(setq gefaelle-blockname "Gefaellebogen_rechts_30_R500")
(princ (ssg-textf "vfe-extrahiere-block-mass" (list gefaelle-blockname)))
(ensure-block-loaded gefaelle-blockname)
(if (tblsearch "BLOCK" gefaelle-blockname)
(progn
@@ -184,21 +185,20 @@
(setq etage-gef-dz-rechts (- (caddr (car ks-aus-pos)) (caddr (car ks-ein-pos))))
)
(progn
(princ "\n WARNUNG: kein KS - Standardwerte (rechts)")
(princ (ssg-text "vfe-warn-kein-ks-rechts"))
(setq etage-gef-dx-rechts 0.0 etage-gef-dz-rechts -10.0)
)
)
)
(progn
(princ "\n WARNUNG: Block fehlt - Standardwerte (rechts)")
(princ (ssg-text "vfe-warn-block-fehlt-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"))
(princ (ssg-textf "vfe-gefaellebogen-rechts-mass" (list (rtos etage-gef-dx-rechts 2 2) (rtos etage-gef-dz-rechts 2 2))))
(setq *etage-lib-initialized* t)
(princ "\n Etage-Bibliothek erfolgreich initialisiert.")
(princ (ssg-text "vfe-bib-init-erfolg"))
t
)
)
@@ -223,7 +223,7 @@
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(princ (ssg-textf "vfe-block-fehlt-abbruch" (list blockname)))
(exit)
)
)
@@ -241,10 +241,11 @@
(+ (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)))
(princ (ssg-textf "vfe-hz-incl-status"
(list blockname (rtos laenge 2 0)
(strcat (rtos hz-winkel 2 0) (chr 176))
(strcat (rtos vert-winkel 2 0) (chr 176))
(rtos (caddr endpunkt) 2 1))))
endpunkt
)
@@ -258,7 +259,7 @@
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(princ (ssg-textf "vfe-block-fehlt-abbruch" (list blockname)))
(exit)
)
)
@@ -276,10 +277,11 @@
(+ (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)))
(princ (ssg-textf "vfe-hz-rot-status"
(list blockname
(strcat (rtos hz-winkel 2 0) (chr 176))
(strcat (rtos vert-winkel 2 0) (chr 176))
(rtos (caddr endpunkt) 2 1))))
endpunkt
)
@@ -291,7 +293,7 @@
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(princ (ssg-textf "vfe-block-fehlt-abbruch" (list blockname)))
(exit)
)
)
@@ -335,13 +337,14 @@
(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)))
(princ (ssg-textf "vfe-hz-rotks-status"
(list blockname
(strcat (rtos hz-winkel 2 0) (chr 176))
(rtos (caddr ausgang) 2 1))))
ausgang
)
(progn
(princ (strcat "\n WARNUNG: KS fehlt in '" blockname "' - verwende Startpunkt"))
(princ (ssg-textf "vfe-ks-fehlt-startpunkt" (list blockname)))
startpunkt
)
)
@@ -355,7 +358,7 @@
(ensure-block-loaded blockname)
(if (not (tblsearch "BLOCK" blockname))
(progn
(princ (strcat "\n FEHLER: Block '" blockname "' nicht in Bibliothek - abgebrochen"))
(princ (ssg-textf "vfe-block-fehlt-abbruch" (list blockname)))
(exit)
)
)
@@ -403,14 +406,14 @@
(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)))
(princ (ssg-textf "vfe-hz-scaleks-status"
(list blockname (rtos laenge 2 0)
(strcat (rtos hz-winkel 2 0) (chr 176))
(rtos (caddr ausgang) 2 1))))
ausgang
)
(progn
(princ (strcat "\n WARNUNG: KS fehlt in '" blockname "' - verwende Startpunkt"))
(princ (ssg-textf "vfe-ks-fehlt-startpunkt" (list blockname)))
startpunkt
)
)
@@ -432,7 +435,7 @@
(if (not *etage-lib-initialized*)
(progn
(alert "Etage-Bibliothek nicht initialisiert!")
(alert (ssg-text "vfe-alert-bib-nicht-init"))
(exit)
)
)
@@ -452,11 +455,9 @@
(setq schraeg-cos (* (cos schraeg-hz-rad) cos3))
(princ "\n\n=========================================")
(princ "\n ETAGE-BERECHNUNG FUER ALLE WINKEL")
(princ (ssg-text "vfe-berechnung-header"))
(princ "\n=========================================")
(princ (strcat "\n△L=" (rtos deltaL 2 2) " mm"
" △H=" (rtos deltaH 2 2) " mm"
" Richtung=" richtung))
(princ (ssg-textf "vfe-delta-info" (list (rtos deltaL 2 2) (rtos deltaH 2 2) richtung)))
(foreach winkel winkel-list
(if (= richtung "Auf")
@@ -471,7 +472,7 @@
)
(if (or (null mass1) (null mass2))
(progn
(princ (strcat "\n " (itoa winkel) (chr 176) " -> Bogen nicht vorhanden"))
(princ (ssg-textf "vfe-bogen-nicht-vorhanden" (list (strcat (itoa winkel) (chr 176)))))
(setq ergebnis-liste (cons (list winkel nil nil nil) ergebnis-liste))
)
(progn
@@ -540,9 +541,9 @@
(setq ergebnis-liste (reverse ergebnis-liste))
(princ "\n\n=================================================================================")
(princ "\n ERGEBNISTABELLE (L_GF = gesamt beider GF-Strecken)")
(princ (ssg-text "vfe-ergebnistabelle-header"))
(princ "\n=================================================================================")
(princ "\n Winkel L_GF (mm) L_VF (mm) Status")
(princ (ssg-text "vfe-tabelle-spalten"))
(princ "\n=================================================================================")
(setq best-winkel nil best-L_GF nil best-L_VF nil)
@@ -553,26 +554,25 @@
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 "))
(princ (ssg-textf "vfe-tabelle-zeile"
(list (strcat (itoa winkel) (chr 176)) (fmt L_GF) (fmt L_VF))))
(if gueltig
(progn
(princ "GUELTIG")
(princ (ssg-text "vfe-status-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 (ssg-text "vfe-status-ungueltig"))
)
)
(princ (strcat "\n " (itoa winkel) (chr 176)
" --- --- FEHLER"))
(princ (ssg-textf "vfe-tabelle-zeile-fehler" (list (strcat (itoa winkel) (chr 176)))))
)
)
(princ "\n=================================================================================")
(if best-winkel
(princ (strcat "\n>>> Empfohlener Winkel: " (itoa best-winkel) (chr 176)))
(princ "\n>>> KEIN passender Winkel gefunden!")
(princ (ssg-textf "vfe-empfohlener-winkel" (list (strcat (itoa best-winkel) (chr 176)))))
(princ (ssg-text "vfe-kein-winkel-gefunden"))
)
(list best-winkel best-L_GF best-L_VF ergebnis-liste)
)
@@ -592,8 +592,7 @@
(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"))
(princ (ssg-textf "vfe-gefaellebogen-seite-dx" (list seite (rtos etage-gef-dx 2 2))))
(berechne-winkel-etage deltaL deltaH richtung)
)
@@ -602,75 +601,91 @@
;; ============================================================
;; 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.
;; hz: Richtung der Hauptlinie (Default 0 = horizontal/X). AS-KS_EIN und
;; ES-KS_AUS liegen koaxial auf dieser Linie; die Kette wird frame-verkettet
;; aufgebaut (cur-hz laeuft durch, Boegen drehen um ihren gemessenen Schwenk).
(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)
as-hz as-ksinfo
cur-hz bogen-info es-info
perp-sin perp-cos p2b-perp es-place-rad
es-wx es-wy es-perp perp-rate L-exit)
(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))
;; hz = Richtung der Hauptlinie (AS-KS_EIN / ES-KS_AUS liegen darauf).
;; Default 0 (horizontal), falls der Aufrufer nichts uebergibt.
(if (null hz) (setq hz 0.0))
(setq hz (float hz))
(setq as-block (strcat "AS_Element_30_" seite))
(setq es-block (strcat "ES_Element_30_" seite))
;; Gefaellebogen auf der GEGENSEITE des AS-Elements (Nutzer-Vorgabe
;; 2026-07-21): AS links -> Boegen rechts, AS rechts -> Boegen links.
;; Beide Etage-Boegen nutzen dieselbe (Gegen-)Seite.
(setq gefaelle-blockname
(if (= seite "rechts")
"Gefaellebogen_rechts_60_R500"
"Gefaellebogen_links_60_R500"
"Gefaellebogen_links_30_R500"
"Gefaellebogen_rechts_30_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))
;; 1. AS_30 - KS_EIN koaxial zur Hauptlinie (hz) ausrichten.
;; vf-element-ks-info liefert (ein-ang aus-ang vx vy): ein-ang/aus-ang sind die
;; Ebenen-Winkel der KS_EIN- bzw. KS_AUS-Achse IM BLOCK (bei Einbau-Rotation 0).
;; Platzierungs-hz = (hz - ein-ang) dreht die KS_EIN-Achse von ein-ang auf hz
;; -> KS_EIN liegt koaxial auf der Hauptlinie (Abnahmekriterium).
(princ (ssg-textf "vfe-step1-as30" (list as-block)))
(setq as-ksinfo (vf-element-ks-info as-block))
(setq aktueller-punkt
(insert-block-by-ks as-block aktueller-punkt (- hz (car as-ksinfo))))
;; KS_AUS-Richtung (absolut) = hz + Schwenk (aus-ang - ein-ang); die folgende
;; GF laeuft in dieser Richtung weiter (Frame-Verkettung wie im Linienzug).
(setq as-hz (+ hz (- (cadr as-ksinfo) (car as-ksinfo))))
;; 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)"))
;; 2. Staustrecke 400mm (folgt der AS-Richtung as-hz, 3 Grad vert, KS_EIN)
(princ (ssg-textf "vfe-step2" (list (rtos as-hz 2 1))))
(setq aktueller-punkt
(insert-hz-scaled-block-by-ks "Staustrecke_SP_1000_mm" aktueller-punkt
400 hz-anfang 3))
400 as-hz 3))
;; 3. Separator (hz-anfang, 3 Grad vert)
(princ (strcat "\n\n3/15: Separator (300mm, "
(itoa hz-anfang) " Grad hz, 3 Grad vert)"))
;; 3. Separator (folgt der AS-Richtung as-hz, 3 Grad vert)
(princ (ssg-textf "vfe-step3" (list (rtos as-hz 2 1))))
(setq aktueller-punkt
(insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
hz-anfang 3 300 0))
as-hz 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)"))
;; Ab hier laufende Richtung cur-hz mitfuehren (frame-verkettet). Start =
;; KS_AUS-Richtung des AS (as-hz). Jeder Gefaellebogen dreht cur-hz um seinen
;; gemessenen Schwenk (Vorzeichen/Seite kommen aus dem Block).
(setq cur-hz as-hz)
;; 4. Gefaellebogen Anfang (verkettet: KS_EIN auf cur-hz, dann cur-hz drehen)
(setq bogen-info (vf-element-ks-info gefaelle-blockname))
(princ (ssg-textf "vfe-step4" (list gefaelle-blockname (rtos cur-hz 2 1))))
(setq aktueller-punkt
(insert-hz-rotated-block-by-ks gefaelle-blockname aktueller-punkt hz-anfang 0))
(insert-hz-rotated-block-by-ks gefaelle-blockname aktueller-punkt
(- cur-hz (car bogen-info)) 0))
(setq cur-hz (+ cur-hz (- (cadr bogen-info) (car bogen-info))))
;; 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)"))
(princ (ssg-textf "vfe-step5-strecke" (list (rtos L_GF1 2 2))))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF1 3 0.0))
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF1 3 cur-hz))
)
(princ "\n\n5/15: L_GF1 (uebersprungen)")
(princ (ssg-text "vfe-step5-skip"))
)
;; 6. Umlenkstation (3 Grad geneigt)
(princ "\n\n6/15: Umlenkstation (500mm, 3 Grad geneigt)")
(princ (ssg-text "vfe-step6"))
(setq aktueller-punkt
(insert-rotated-block-with-ks "Vario_Umlenkstation_500mm" aktueller-punkt 3 500 0 0.0))
(insert-rotated-block-with-ks "Vario_Umlenkstation_500mm" aktueller-punkt 3 500 0 cur-hz))
;; 7. 1. Vertikalbogen (3 Grad geneigt)
(if (= richtung "Auf")
@@ -684,31 +699,29 @@
)
)
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
(princ (strcat "\n\n7/15: " bogen-name " (3 Grad geneigt)"))
(princ (ssg-textf "vfe-step7" (list bogen-name)))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt 3 bogen-dx bogen-dz 0.0))
(insert-rotated-block-with-ks bogen-name aktueller-punkt 3 bogen-dx bogen-dz cur-hz))
;; 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)"))
(princ (ssg-textf "vfe-step8-auf" (list (itoa (- (- best-winkel 3))) (rtos L_VF 2 2))))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_VF (- (- best-winkel 3)) 0.0))
L_VF (- (- best-winkel 3)) cur-hz))
)
(progn
(princ (strcat "\n\n8/15: Gefaellestrecke ("
(itoa (+ best-winkel 3)) " Grad, L=" (rtos L_VF 2 2) " mm)"))
(princ (ssg-textf "vfe-step8-ab" (list (itoa (+ best-winkel 3)) (rtos L_VF 2 2))))
(setq aktueller-punkt
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt
L_VF (+ best-winkel 3) 0.0))
L_VF (+ best-winkel 3) cur-hz))
)
)
)
(princ "\n\n8/15: L_VF (uebersprungen)")
(princ (ssg-text "vfe-step8-skip"))
)
;; 9. 2. Vertikalbogen
@@ -729,56 +742,83 @@
" (" (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))
(- 3 best-winkel) bogen-dx bogen-dz cur-hz))
)
(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))
(+ best-winkel 3) bogen-dx bogen-dz cur-hz))
)
)
;; 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))
(insert-rotated-block-with-ks "Vario_Motorstation_500mm" aktueller-punkt 3 500 0 cur-hz))
;; 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))
(insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF2 3 cur-hz))
)
(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)"))
;; 12. Gefaellebogen Ende (verkettet: KS_EIN auf cur-hz, dann cur-hz drehen)
(setq bogen-info (vf-element-ks-info gefaelle-blockname))
(princ (strcat "\n\n12/15: " gefaelle-blockname
" (Ende, verkettet cur-hz=" (rtos cur-hz 2 1) ")"))
(setq aktueller-punkt
(insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
hz-ende 3 300 0))
(insert-block-by-ks gefaelle-blockname aktueller-punkt (- cur-hz (car bogen-info))))
(setq cur-hz (+ cur-hz (- (cadr bogen-info) (car bogen-info))))
;; 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)"))
;; --- Auslauf RUECKWAERTS vom ES gerechnet (analog Linienzug Modus 2):
;; die Auslauf-Staustrecke wird variabel, sodass das ES-KS_AUS OHNE
;; seitlichen Versatz auf der Hauptachse landet. Reihenfolge (Nutzer-Vorgabe):
;; Staustrecke -> Separator -> ES.
(setq es-info (vf-element-ks-info es-block))
;; perp = Einheitsvektor senkrecht zur Hauptlinie hz: (-sin hz, cos hz)
(setq perp-sin (sin (* hz (/ pi 180.0)))
perp-cos (cos (* hz (/ pi 180.0))))
;; seitliche Lage nach Bogen2 (perp-Abstand des aktuellen Punkts zu startpunkt)
(setq p2b-perp (+ (* (- (car aktueller-punkt) (car startpunkt)) (- perp-sin))
(* (- (cadr aktueller-punkt) (cadr startpunkt)) perp-cos)))
;; ES-Eigenversatz KS_EIN->KS_AUS (Block vx/vy) in Auslaufrichtung gedreht -> perp
(setq es-place-rad (* (- cur-hz (car es-info)) (/ pi 180.0)))
(setq es-wx (- (* (caddr es-info) (cos es-place-rad)) (* (cadddr es-info) (sin es-place-rad))))
(setq es-wy (+ (* (caddr es-info) (sin es-place-rad)) (* (cadddr es-info) (cos es-place-rad))))
(setq es-perp (+ (* es-wx (- perp-sin)) (* es-wy perp-cos)))
;; perp-Auslenkung pro Laengeneinheit bei cur-hz (Neigung 3 Grad)
(setq perp-rate (* (cos (* 3.0 (/ pi 180.0)))
(sin (* (- cur-hz hz) (/ pi 180.0)))))
;; Loesen: p2b-perp + (L_exit + 300)*perp-rate + es-perp = 0
(setq L-exit
(if (> (abs perp-rate) 1e-6)
(- (/ (- (+ p2b-perp es-perp)) perp-rate) 300.0)
400.0))
(if (< L-exit 50.0) (setq L-exit 50.0)) ; Schutz gegen negative/zu kurze GF
;; 13. Auslauf-Staustrecke (variabel, folgt cur-hz, 3 Grad vert, KS_EIN)
(princ (strcat "\n\n13/15: Staustrecke (variabel L=" (rtos L-exit 2 1)
", cur-hz=" (rtos cur-hz 2 1) ")"))
(setq aktueller-punkt
(insert-hz-scaled-block-by-ks "Staustrecke_SP_1000_mm" aktueller-punkt
400 hz-ende 3))
L-exit cur-hz 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)"))
;; 14. Separator (verkettet, folgt cur-hz, 3 Grad vert)
(princ (strcat "\n\n14/15: Separator (300mm, cur-hz=" (rtos cur-hz 2 1) ")"))
(setq aktueller-punkt
(insert-hz-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
cur-hz 3 300 0))
;; 15. ES_30 (verkettet: KS_EIN auf cur-hz; KS_AUS auf der Hauptlinie)
(princ (strcat "\n\n15/15: " es-block " (Ende, verkettet cur-hz=" (rtos cur-hz 2 1) ")"))
(setq endpunkt
(insert-hz-rotated-block-with-ks es-block aktueller-punkt
hz-ende 0 etage-ein-dx etage-ein-dz))
(insert-block-by-ks es-block aktueller-punkt (- cur-hz (car es-info))))
(princ "\n\n=========================================")
(princ "\n>>> Etage-VarioFoerderer eingefuegt! <<<")
+1124 -116
View File
File diff suppressed because it is too large Load Diff
+494 -49
View File
@@ -21,7 +21,7 @@
(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!")
(princ (ssg-text "vfs-warn-lisppfad"))
(exit)
)
)
@@ -77,10 +77,10 @@
)
(if missing
(progn
(princ (strcat "\n FEHLER: DXFM_BLOCKS = " block-pfad))
(princ "\n Folgende Block-Dateien fehlen:")
(princ (ssg-textf "vfs-block-fehler-pfad" (list block-pfad)))
(princ (ssg-text "vfs-block-fehlende-header"))
(foreach f (reverse missing)
(princ (strcat "\n - " f))
(princ (ssg-textf "vfs-block-fehlende-item" (list f)))
)
nil
)
@@ -101,7 +101,7 @@
(if (and *lib-initialized* bogen-auf bogen-ab
(tblsearch "BLOCK" "AS_Element_90_links"))
(progn
(princ "\n Standard-Bibliothek bereits initialisiert.")
(princ (ssg-text "vfs-lib-bereits-init"))
t
)
(if (not (vf-check-required-blocks))
@@ -109,10 +109,10 @@
(progn
(setq *lib-initialized* nil)
(setq *ks-cache* nil)
(princ "\n Initialisiere Standard-Bibliothek...")
(princ (ssg-text "vfs-lib-init-start"))
;; AS_90 Masse extrahieren
(princ "\n Extrahiere AUS_Element Masse...")
(princ (ssg-text "vfs-extrahiere-aus"))
(ensure-block-loaded "AS_Element_90_links")
(ensure-block-loaded "AS_Element_90_rechts")
(if (tblsearch "BLOCK" "AS_Element_90_links")
@@ -132,17 +132,16 @@
(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 (ssg-textf "vfs-as90-mass" (list (rtos aus-dx 2 0) (rtos aus-dz 2 0))))
)
(princ "\n FEHLER: KS_EIN/KS_AUS fehlt im AS_90!")
(princ (ssg-text "vfs-fehler-ks-as90"))
)
)
(princ "\n FEHLER: Block AS_Element_90_links nicht geladen!")
(princ (ssg-text "vfs-fehler-block-as90"))
)
;; ES_90 Masse extrahieren
(princ "\n Extrahiere EIN_Element Masse...")
(princ (ssg-text "vfs-extrahiere-ein"))
(ensure-block-loaded "ES_Element_90_links")
(ensure-block-loaded "ES_Element_90_rechts")
(if (tblsearch "BLOCK" "ES_Element_90_links")
@@ -162,17 +161,16 @@
(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 (ssg-textf "vfs-es90-mass" (list (rtos ein-dx 2 0) (rtos ein-dz 2 0))))
)
(princ "\n FEHLER: KS_EIN/KS_AUS fehlt im ES_90!")
(princ (ssg-text "vfs-fehler-ks-es90"))
)
)
(princ "\n FEHLER: Block ES_Element_90_links nicht geladen!")
(princ (ssg-text "vfs-fehler-block-es90"))
)
;; Bogen-Masse extrahieren
(princ "\n Extrahiere Bogen-Masse...")
(princ (ssg-text "vfs-extrahiere-bogen"))
(setq bogen-auf '())
(setq bogen-ab '())
(setq bogen-winkel (ssg-cfg-or "vario" "bogen_winkel"
@@ -198,13 +196,12 @@
(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 (ssg-textf "vfs-bogen-auf-ok" (list (itoa w) (rtos dx 2 0) (rtos dz 2 0))))
)
(princ (strcat "\n FEHLER auf_" (itoa w) ": KS fehlt!"))
(princ (ssg-textf "vfs-bogen-auf-ks-fehlt" (list (itoa w))))
)
)
(princ (strcat "\n FEHLER auf_" (itoa w) ": Block nicht geladen!"))
(princ (ssg-textf "vfs-bogen-auf-block-fehlt" (list (itoa w))))
)
;; Abwaertsbogen
(setq bogen-name (strcat "Vario_Bogen_ab_" (itoa w)))
@@ -226,19 +223,18 @@
(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 (ssg-textf "vfs-bogen-ab-ok" (list (itoa w) (rtos dx 2 0) (rtos dz 2 0))))
)
(princ (strcat "\n FEHLER ab_" (itoa w) ": KS fehlt!"))
(princ (ssg-textf "vfs-bogen-ab-ks-fehlt" (list (itoa w))))
)
)
(princ (strcat "\n FEHLER ab_" (itoa w) ": Block nicht geladen!"))
(princ (ssg-textf "vfs-bogen-ab-block-fehlt" (list (itoa w))))
)
)
(setq bogen-auf (reverse bogen-auf))
(setq bogen-ab (reverse bogen-ab))
(setq *lib-initialized* t)
(princ "\n Standard-Bibliothek erfolgreich initialisiert.")
(princ (ssg-text "vfs-lib-init-erfolg"))
t
) ;; end progn (Initialisierung)
) ;; end (if not vf-check-required-blocks)
@@ -254,8 +250,7 @@
(if (= (car item) winkel) (setq result (cdr item)))
)
(if (null result)
(princ (strcat "\n FEHLER: Winkel " (itoa winkel)
" nicht in Bogen-Tabelle!"))
(princ (ssg-textf "vfs-fehler-winkel-tabelle" (list (itoa winkel))))
)
result
)
@@ -276,7 +271,7 @@
(if (or (not *lib-initialized*) (null aus-dz) (null ein-dz))
(progn
(princ "\n FEHLER: Bibliothek nicht korrekt initialisiert (AUS/EIN-Masse fehlen)!")
(princ (ssg-text "vfs-fehler-lib-nicht-init"))
(exit)
)
)
@@ -290,11 +285,10 @@
sin3 (sin (* (ssg-cfg-or "vario" "gefaelle_winkel" 3) (/ pi 180.0))))
(princ "\n\n=========================================")
(princ "\n BERECHNUNG FUER ALLE WINKEL (Standard)")
(princ (ssg-text "vfs-berechnung-header"))
(princ "\n=========================================")
(princ (strcat "\n△L=" (rtos deltaL 2 2) " mm"
" △H=" (rtos deltaH 2 2) " mm"
" Richtung=" richtung))
(princ (ssg-textf "vfs-berechnung-parameter"
(list (rtos deltaL 2 2) (rtos deltaH 2 2) richtung)))
(foreach winkel winkel-list
(if (= richtung "Auf")
@@ -357,9 +351,9 @@
(setq ergebnis-liste (reverse ergebnis-liste))
(princ "\n\n=================================================================================")
(princ "\n ERGEBNISTABELLE")
(princ (ssg-text "vfs-ergebnistabelle-header"))
(princ "\n=================================================================================")
(princ "\n Winkel L_GF (mm) L_VF (mm) Status")
(princ (ssg-text "vfs-tabelle-spalten"))
(princ "\n=================================================================================")
(setq best-winkel nil best-L_GF nil best-L_VF nil)
@@ -367,26 +361,25 @@
(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 "))
(princ (ssg-textf "vfs-tabelle-zeile"
(list (itoa winkel) (chr 176) (fmt L_GF) (fmt L_VF))))
(if gueltig
(progn
(princ "GUELTIG")
(princ (ssg-text "vfs-status-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 (ssg-text "vfs-status-ungueltig"))
)
)
(princ (strcat "\n " (itoa winkel) (chr 176)
" --- --- FEHLER"))
(princ (ssg-textf "vfs-tabelle-zeile-fehler" (list (itoa winkel) (chr 176))))
)
)
(princ "\n=================================================================================")
(if best-winkel
(princ (strcat "\n>>> Empfohlener Winkel: " (itoa best-winkel) (chr 176)))
(princ "\n>>> KEIN passender Winkel gefunden!")
(princ (ssg-textf "vfs-empfohlener-winkel" (list (itoa best-winkel) (chr 176))))
(princ (ssg-text "vfs-kein-winkel-gefunden"))
)
(list best-winkel best-L_GF best-L_VF ergebnis-liste)
)
@@ -471,7 +464,7 @@
(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 ")"))
(princ (ssg-textf "vfs-schritt-as" (list as-block (rtos hz 2 1) grad-zeichen)))
(insert-block-by-ks as-block startpunkt hz)
)
@@ -485,22 +478,22 @@
;; 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)"))
(princ (ssg-textf "vfs-vf-eingang-gf1" (list (rtos L_GF1 2 2))))
(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)")
(princ (ssg-text "vfs-vf-eingang-gf1-skip"))
)
;; 2. Separator (am GF1-Ende / vor Umlenkstation)
(princ "\n[VF-Eingang] Separator (300 mm, 3 Grad geneigt)")
(princ (ssg-text "vfs-vf-eingang-separator"))
(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)")
(princ (ssg-text "vfs-vf-eingang-umlenk"))
(setq aktueller-punkt
(insert-rotated-block-with-ks "Vario_Umlenkstation_500mm" aktueller-punkt
(ssg-cfg-or "vario" "gefaelle_winkel" 3)
@@ -542,7 +535,7 @@
)
)
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
(princ (strcat "\n\n5/11: " bogen-name " (3 Grad geneigt)"))
(princ (ssg-textf "vfs-schritt5-bogen1" (list bogen-name)))
(setq aktueller-punkt
(insert-rotated-block-with-ks bogen-name aktueller-punkt
(ssg-cfg-or "vario" "gefaelle_winkel" 3) bogen-dx bogen-dz hz))
@@ -706,6 +699,458 @@
endpunkt
)
;; ============================================================
;; DCL-DIALOG (Standardfall) - dcl/variofoerderer.dcl
;; Ersetzt die interaktive Werteingabe aus vf-eingabe-abfragen
;; (Konsolen-Modus "Werteingabe") fuer anlage-typ "standard" durch
;; zwei DCL-Dialoge: Basis-Eingabe und Winkel/Verteilung. Die
;; 3D-Linie-Eingabe sowie die Typen "etage"/"linienzug" bleiben
;; unveraendert interaktiv (siehe Verzweigung in c:VarioFoerderer).
;; ============================================================
;; Basis-Eingabe (Dialog 1): deltaL, deltaH, Richtung, Einfuegehoehe,
;; Fahrtrichtung, Seite, Geruest fuer Einzelmodul, Geruestoption.
;; prefill: Assoziationsliste zur Vorbelegung (fuer VARIOFOERDERER_EDIT) mit
;; Schluesseln "deltaL" "deltaH" "richtung" "einfuegehoehe" "hz" "seite"
;; "geruest-einzelmodul" "geruest-typ" - oder nil fuer Neuanlage mit Defaults.
;; Rueckgabe: (deltaL deltaH richtung einfuegehoehe hz seite
;; geruest-einzelmodul geruest-typ) oder nil bei Abbruch.
(defun vfs-dialog-eingabe-basis (prefill / dcl-pfad dat ergebnis
dlg-deltal dlg-deltah dlg-richtung dlg-hoehe
dlg-fahrtrichtung dlg-seite
dlg-geruest-einzelmodul dlg-geruest-typ
deltaL deltaH richtung hz seite z-start
geruest-einzelmodul geruest-typ)
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/variofoerderer.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "variofoerderer_basis" dat))
(progn
(if (>= dat 0) (unload_dialog dat))
(alert (ssg-textf "gf-alert-dialog-fehlt" (list dcl-pfad)))
nil
)
(progn
;; Vorbelegung: aus prefill (Edit) oder Defaults (Neuanlage)
(set_tile "deltal"
(if prefill (rtos (cdr (assoc "deltaL" prefill)) 2 0) "15000"))
(set_tile "deltah"
(if prefill (rtos (cdr (assoc "deltaH" prefill)) 2 0) "3000"))
(set_tile "einfuegehoehe"
(if prefill (rtos (cdr (assoc "einfuegehoehe" prefill)) 2 1) "0"))
(start_list "richtung")
(add_list (ssg-text "vfs-dlg-richtung-auf"))
(add_list (ssg-text "vfs-dlg-richtung-ab"))
(end_list)
(set_tile "richtung"
(if (and prefill (equal (cdr (assoc "richtung" prefill)) "Ab")) "1" "0"))
(start_list "fahrtrichtung")
(add_list (ssg-textf "gf-dlg-richtung-0" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-90" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-180" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-270" (list grad-zeichen)))
(end_list)
(set_tile "fahrtrichtung"
(if prefill
(cond ((equal (cdr (assoc "hz" prefill)) 90.0 0.1) "1")
((equal (cdr (assoc "hz" prefill)) 180.0 0.1) "2")
((equal (cdr (assoc "hz" prefill)) 270.0 0.1) "3")
(t "0"))
"0"))
(start_list "seite")
(add_list (ssg-text "gf-dlg-rechts"))
(add_list (ssg-text "gf-dlg-links"))
(end_list)
(set_tile "seite"
(if (and prefill (equal (cdr (assoc "seite" prefill)) "links")) "1" "0"))
(set_tile "geruest_einzelmodul"
(if (or (null prefill) (equal (cdr (assoc "geruest-einzelmodul" prefill)) "1")) "1" "0"))
(start_list "geruest_typ")
(foreach opt *ssg-geruest-optionen* (add_list opt))
(end_list)
(set_tile "geruest_typ"
(itoa (ssg-geruest-typ-to-idx (if prefill (cdr (assoc "geruest-typ" prefill)) nil))))
;; Actions
(action_tile "accept"
(strcat
"(setq dlg-deltal (get_tile \"deltal\"))"
"(setq dlg-deltah (get_tile \"deltah\"))"
"(setq dlg-richtung (get_tile \"richtung\"))"
"(setq dlg-hoehe (get_tile \"einfuegehoehe\"))"
"(setq dlg-fahrtrichtung (get_tile \"fahrtrichtung\"))"
"(setq dlg-seite (get_tile \"seite\"))"
"(setq dlg-geruest-einzelmodul (get_tile \"geruest_einzelmodul\"))"
"(setq dlg-geruest-typ (get_tile \"geruest_typ\"))"
"(done_dialog 1)"
)
)
(action_tile "cancel" "(done_dialog 0)")
(setq ergebnis (start_dialog))
(unload_dialog dat)
(if (= ergebnis 1)
(progn
(setq deltaL (atof dlg-deltal))
(setq deltaH (atof dlg-deltah))
(setq richtung (if (= dlg-richtung "1") "Ab" "Auf"))
(setq z-start (atof dlg-hoehe))
(setq hz
(cond ((= dlg-fahrtrichtung "1") 90.0)
((= dlg-fahrtrichtung "2") 180.0)
((= dlg-fahrtrichtung "3") 270.0)
(t 0.0)))
(setq seite (if (= dlg-seite "1") "links" "rechts"))
(setq geruest-einzelmodul dlg-geruest-einzelmodul)
(setq geruest-typ (ssg-geruest-idx-to-typ (atoi dlg-geruest-typ)))
(list deltaL deltaH richtung z-start hz seite geruest-einzelmodul geruest-typ)
)
nil
)
)
)
)
;; Winkel/Verteilung-Eingabe (Dialog 2): Winkel-Popup aus den vorher
;; berechneten gueltigen Varianten (gueltige-winkel/ergebnis-liste, siehe
;; berechne-alle-winkel), plus L_GF-Verteilung vorne/hinten (analog Schritt
;; 8+9 in c:VarioFoerderer).
;; prefill: Assoziationsliste ("winkel" . best-winkel) ("verteilung-idx" . "0".."3")
;; ("lgf1" . mm) - oder nil fuer Vorbelegung mit dem kleinsten gueltigen Winkel.
;; Rueckgabe: (best-winkel L_GF L_VF L_GF1 L_GF2 verteilung-modus) oder nil bei Abbruch.
(defun vfs-dialog-winkel-verteilung (gueltige-winkel ergebnis-liste staustrecke-basis prefill /
dcl-pfad dat ergebnis w eintrag idx sel-idx init-verteilung
dlg-winkel dlg-verteilung dlg-lgf1
best-winkel L_GF L_VF verteilung-modus L_GF1 L_GF2)
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/variofoerderer.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "variofoerderer_winkel" dat))
(progn
(if (>= dat 0) (unload_dialog dat))
(alert (ssg-textf "gf-alert-dialog-fehlt" (list dcl-pfad)))
nil
)
(progn
;; Winkel-Popup aus den gueltigen Varianten aufbauen
(start_list "winkel")
(foreach w gueltige-winkel
(setq eintrag (assoc w ergebnis-liste))
(if (= w 0)
(add_list (ssg-textf "vfs-dlg-winkel-horizontal"
(list (rtos (nth 1 eintrag) 2 1) (rtos (nth 2 eintrag) 2 1))))
(add_list (ssg-textf "vfs-dlg-winkel-option"
(list (itoa w) grad-zeichen (rtos (nth 1 eintrag) 2 1) (rtos (nth 2 eintrag) 2 1))))
)
)
(end_list)
;; Vorbelegung: Winkel aus prefill (falls noch gueltig), sonst erster
;; (kleinster) gueltiger Winkel - analog der automatischen Konsolen-Wahl.
(setq sel-idx 0 idx 0)
(if prefill
(foreach w gueltige-winkel
(if (equal w (cdr (assoc "winkel" prefill))) (setq sel-idx idx))
(setq idx (1+ idx))
)
)
(set_tile "winkel" (itoa sel-idx))
;; Verteilung: Popup + manuelles L_GF1-Feld (nur bei "Eigene Werte" aktiv)
(start_list "verteilung")
(add_list (ssg-text "vfs-dlg-verteilung-1"))
(add_list (ssg-text "vfs-dlg-verteilung-2"))
(add_list (ssg-text "vfs-dlg-verteilung-3"))
(add_list (ssg-text "vfs-dlg-verteilung-4"))
(end_list)
(setq init-verteilung (if prefill (cdr (assoc "verteilung-idx" prefill)) "0"))
(set_tile "verteilung" init-verteilung)
(set_tile "lgf1_manuell"
(if (and prefill (cdr (assoc "lgf1" prefill)))
(rtos (cdr (assoc "lgf1" prefill)) 2 1) "0"))
(mode_tile "lgf1_manuell" (if (= init-verteilung "3") 0 1))
(action_tile "verteilung"
"(mode_tile \"lgf1_manuell\" (if (= (get_tile \"verteilung\") \"3\") 0 1))")
(action_tile "accept"
(strcat
"(setq dlg-winkel (get_tile \"winkel\"))"
"(setq dlg-verteilung (get_tile \"verteilung\"))"
"(setq dlg-lgf1 (get_tile \"lgf1_manuell\"))"
"(done_dialog 1)"
)
)
(action_tile "cancel" "(done_dialog 0)")
(setq ergebnis (start_dialog))
(unload_dialog dat)
(if (= ergebnis 1)
(progn
(setq best-winkel (nth (atoi dlg-winkel) gueltige-winkel))
(setq eintrag (assoc best-winkel ergebnis-liste))
(setq L_GF (nth 1 eintrag) L_VF (nth 2 eintrag))
(setq verteilung-modus dlg-verteilung)
(cond
((= verteilung-modus "0")
(setq L_GF1 (/ L_GF 2.0) L_GF2 (/ L_GF 2.0)))
((= verteilung-modus "1")
(setq L_GF1 (float staustrecke-basis))
(setq L_GF2 (max 0.0 (- L_GF (float staustrecke-basis)))))
((= verteilung-modus "2")
(setq L_GF2 (float staustrecke-basis))
(setq L_GF1 (max 0.0 (- L_GF (float staustrecke-basis)))))
((= verteilung-modus "3")
(setq L_GF1 (atof dlg-lgf1))
(if (or (null L_GF1) (< L_GF1 0)) (setq L_GF1 (/ L_GF 2.0)))
(if (> L_GF1 L_GF) (setq L_GF1 L_GF))
(setq L_GF2 (max 0.0 (- L_GF L_GF1))))
(t (setq L_GF1 (/ L_GF 2.0) L_GF2 (/ L_GF 2.0)))
)
(list best-winkel L_GF L_VF L_GF1 L_GF2 verteilung-modus)
)
nil
)
)
)
)
;; ============================================================
;; XDATA-Metadaten fuer den Edit-Nachbau (App "SSG_VF_EDIT").
;; Markiert ein VF_n-INSERT als "mit dem Standard-Dialog erstellt" und
;; speichert die Fahrtrichtung (hz) - der einzige Wert, der sich nicht aus
;; den Sivas-Attributen rekonstruieren laesst (ANTRIEBFAHRTRICHTUNG, SEITE_AS,
;; VF_WINKEL, L_GF_m stehen dort bereits). Bewusst NICHT im Sivas-Attributsatz.
;; Ohne diese Markierung (z.B. Etage-, Linienzug- oder Altbestand-Bloecke)
;; verweigert c:VARIOFOERDERER_EDIT die Bearbeitung, um deren komplexere
;; Geometrie nicht versehentlich durch einen einfachen Neuaufbau zu ersetzen.
;; ============================================================
(if (null *vf-xdata-app*) (setq *vf-xdata-app* "SSG_VF_EDIT"))
(defun vfs-xdata-schreiben (ent hz /)
(regapp *vf-xdata-app*)
(entmod
(append (entget ent)
(list
(list -3
(list *vf-xdata-app*
(cons 1000 "standard")
(cons 1000 (rtos (float hz) 2 4)))))))
ent
)
;; XDATA lesen -> (typ-marker hz-str) oder nil.
(defun vfs-xdata-lesen (ent / xd app-data)
(setq xd (entget ent (list *vf-xdata-app*)))
(setq app-data (cdr (assoc -3 xd)))
(if app-data
(mapcar 'cdr (cdr (car app-data)))
nil
)
)
;; ============================================================
;; Gemeinsame Berechnung + Winkel/Verteilung-Dialog + Einfuegung.
;; Wird sowohl von der Neuanlage (vfs-standard-dialog-ablauf) als auch vom
;; Edit-Befehl (c:VARIOFOERDERER_EDIT) verwendet.
;; winkel-prefill: Vorbelegung fuer vfs-dialog-winkel-verteilung oder nil.
;; ============================================================
(defun vfs-standard-dialog-berechnen-einfuegen (vf-nummer deltaL deltaH richtung startpunkt hz seite
winkel-prefill geruest-einzelmodul geruest-typ /
ergebnis ergebnis-liste gueltige-winkel horizontal-info
winkelwahl best-winkel L_GF L_VF L_GF1 L_GF2 verteilung-modus
n-scanner hoehe-von hoehe-bis lastEnt vf-insert vf-endpunkt staustrecke-basis)
(setq ergebnis (berechne-standard deltaL deltaH richtung seite))
(setq ergebnis-liste (cadddr ergebnis))
(setq staustrecke-basis (ssg-cfg-or "vario" "staustrecke_basis" 1000))
;; Horizontale Zwischenstrecke als Zusatzoption (nur bei "Ab" erreichbar,
;; siehe Kommentar in c:VarioFoerderer Schritt 5b).
(setq horizontal-info nil)
(if (= richtung "Ab")
(progn
(setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab"))
(if (and horizontal-info (caddr horizontal-info))
(setq ergebnis-liste
(append ergebnis-liste (list (list 0 (car horizontal-info) (cadr horizontal-info) T))))
(setq horizontal-info nil)
)
)
)
(setq gueltige-winkel
(mapcar 'car
(vl-remove-if-not
(function (lambda (e) (and (nth 3 e) (numberp (nth 1 e)) (numberp (nth 2 e))
(>= (nth 1 e) 0) (>= (nth 2 e) 0))))
ergebnis-liste)))
(if (null gueltige-winkel)
(alert (ssg-textf "vfc-alert-kein-winkel"
(list (chr 916) (rtos deltaL 2 0) (rtos deltaH 2 0) richtung)))
(progn
(setq winkelwahl (vfs-dialog-winkel-verteilung gueltige-winkel ergebnis-liste staustrecke-basis winkel-prefill))
(if (null winkelwahl)
(princ (ssg-text "vfc-vorgang-abgebrochen"))
(progn
(setq best-winkel (nth 0 winkelwahl)
L_GF (nth 1 winkelwahl)
L_VF (nth 2 winkelwahl)
L_GF1 (nth 3 winkelwahl)
L_GF2 (nth 4 winkelwahl)
verteilung-modus (nth 5 winkelwahl))
(setq n-scanner 0)
(setq hoehe-von (caddr startpunkt))
(setq hoehe-bis
(cond ((= richtung "Auf") (+ hoehe-von deltaH))
((= richtung "Ab") (- hoehe-von deltaH))
(t hoehe-von)))
(setq lastEnt (vf-lastent-ohne-attribute))
;; endpunkt = tatsaechliches ES-KS_AUS (Weltpunkt) - wird fuer die
;; Ausrichtung des Parallel-VF (gf-baue-parallel-vf) zurueckgegeben.
(setq vf-endpunkt
(variofoerderer-einfuegen deltaL deltaH richtung best-winkel L_GF1 L_GF2 L_VF startpunkt seite hz))
(setq vf-insert
(vf-block-erstellen "standard" seite vf-nummer n-scanner
hoehe-von hoehe-bis deltaH deltaL L_VF L_GF1 L_GF2
richtung best-winkel startpunkt lastEnt hz
geruest-einzelmodul geruest-typ))
(if vf-insert (vfs-xdata-schreiben vf-insert hz))
(princ "\n=========================================")
)
)
)
)
;; Rueckgabe: (vf-insert vf-endpunkt) fuer aufrufende Ausrichtungslogik;
;; bei Abbruch/Fehler (nil nil). Menue-Aufrufer ignorieren die Rueckgabe.
(list vf-insert vf-endpunkt)
)
;; Neuanlage (Menue/Konsole -> Dialog): Startpunkt (X/Y) picken, Basis-Dialog,
;; dann gemeinsame Berechnung/Winkel-Dialog/Einfuegung.
(defun vfs-standard-dialog-ablauf (vf-nummer / eingabe deltaL deltaH richtung
z-start hz seite startpunkt startpunkt-xy
geruest-einzelmodul geruest-typ)
(setq startpunkt-xy (getpoint (ssg-text "vfc-prompt-startpunkt-aus")))
(if (null startpunkt-xy) (setq startpunkt-xy '(0 0 0)))
(setq eingabe (vfs-dialog-eingabe-basis nil))
(if (null eingabe)
(princ (ssg-text "vfc-vorgang-abgebrochen"))
(progn
(setq deltaL (nth 0 eingabe)
deltaH (nth 1 eingabe)
richtung (nth 2 eingabe)
z-start (nth 3 eingabe)
hz (nth 4 eingabe)
seite (nth 5 eingabe)
geruest-einzelmodul (nth 6 eingabe)
geruest-typ (nth 7 eingabe))
(setq startpunkt (list (car startpunkt-xy) (cadr startpunkt-xy) z-start))
(vfs-standard-dialog-berechnen-einfuegen vf-nummer deltaL deltaH richtung startpunkt hz seite nil
geruest-einzelmodul geruest-typ)
)
)
)
;; ============================================================
;; VARIOFOERDERER_EDIT - Doppelklick/Kontextmenue-Bearbeitung
;; ============================================================
;; Bearbeitet einen bestehenden Standard-VarioFoerderer (VF_n-Block, mit
;; SSG_VF_EDIT-XDATA) ueber die DCL-Dialoge: liest die aktuellen Parameter,
;; zeigt sie vorbelegt und baut die Strecke bei OK am selben Startpunkt neu
;; auf. Wird vom Doppelklick-Dispatcher SSG_BLOCKEDIT fuer Blocknamen "VF_*"
;; aufgerufen. Bloecke ohne SSG_VF_EDIT-XDATA (Etage, Linienzug, Altbestand)
;; werden abgewiesen, da ihre Geometrie sich nicht verlustfrei aus dem
;; einfachen Standard-Schema rekonstruieren laesst.
(defun c:VARIOFOERDERER_EDIT ( / ss ent ed bname startpunkt attribs xd
deltaL deltaH richtung z-start hz seite
eingabe vf-nummer best-winkel-attr L_GF_m-teile
prefill-basis prefill-winkel
geruest-einzelmodul geruest-typ)
;; Implied Selection VOR ssg-start pruefen (ssg-start hebt Selektion auf)
(setq ss (ssget "I"))
(if (and ss (= (sslength ss) 1)
(= (cdr (assoc 0 (entget (ssname ss 0)))) "INSERT"))
(setq ent (ssname ss 0))
)
(ssg-start "VARIOFOERDERER_EDIT" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
(setvar "OSMODE" 0)
(if (null ent)
(progn
(setq ss (ssget ":S" '((0 . "INSERT"))))
(if ss (setq ent (ssname ss 0)))
)
)
(if (null ent) (progn (ssg-end) (exit)))
(setq ed (entget ent))
(setq bname (cdr (assoc 2 ed)))
(if (not (wcmatch bname "VF_*"))
(progn (alert (ssg-textf "vfs-edit-kein-vf" (list bname))) (ssg-end) (exit)))
(setq xd (vfs-xdata-lesen ent))
(if (or (null xd) (/= (car xd) "standard"))
(progn (alert (ssg-textf "vfs-edit-keine-xdata" (list bname))) (ssg-end) (exit)))
(setq startpunkt (cdr (assoc 10 ed)))
(setq attribs (ssg-attrib-read ent))
(setq hz (atof (nth 1 xd)))
(setq deltaL (atof (cond ((cdr (assoc "DELTA_L_mm" attribs))) ("15000"))))
(setq deltaH (atof (cond ((cdr (assoc "DELTA_H_mm" attribs))) ("3000"))))
(setq richtung (cond ((cdr (assoc "ANTRIEBFAHRTRICHTUNG" attribs))) ("Auf")))
(setq seite (cond ((cdr (assoc "SEITE_AS" attribs))) ("rechts")))
(setq z-start (caddr startpunkt))
(setq prefill-basis
(list (cons "deltaL" deltaL) (cons "deltaH" deltaH) (cons "richtung" richtung)
(cons "einfuegehoehe" z-start) (cons "hz" hz) (cons "seite" seite)
(cons "geruest-einzelmodul" (cond ((cdr (assoc "GERUEST_EINZELMODUL" attribs))) ("1")))
(cons "geruest-typ" (cdr (assoc "GERUEST_TYP" attribs)))))
(setq eingabe (vfs-dialog-eingabe-basis prefill-basis))
(if (null eingabe)
(princ (ssg-text "vfc-vorgang-abgebrochen"))
(progn
(setq deltaL (nth 0 eingabe)
deltaH (nth 1 eingabe)
richtung (nth 2 eingabe)
z-start (nth 3 eingabe)
hz (nth 4 eingabe)
seite (nth 5 eingabe)
geruest-einzelmodul (nth 6 eingabe)
geruest-typ (nth 7 eingabe))
(setq startpunkt (list (car startpunkt) (cadr startpunkt) z-start))
;; Vorbelegung Winkel/Verteilung: bestehenden Winkel vorschlagen, L_GF-
;; Verteilung als "Eigene Werte" mit dem aktuellen L_GF1 (aus L_GF_m) -
;; das ist unabhaengig vom urspruenglichen Verteilungsmodus immer exakt.
(setq best-winkel-attr (atoi (cond ((cdr (assoc "VF_WINKEL" attribs))) ("0"))))
(setq L_GF_m-teile (ssg-cfg-split-comma (cond ((cdr (assoc "L_GF_m" attribs))) ("0.0,0.0"))))
(setq prefill-winkel
(list (cons "winkel" best-winkel-attr)
(cons "verteilung-idx" "3")
(cons "lgf1" (* 1000.0 (atof (car L_GF_m-teile))))))
(entdel ent)
(setq vf-nummer (vf-next-number))
(vfs-standard-dialog-berechnen-einfuegen vf-nummer deltaL deltaH richtung
startpunkt hz seite prefill-winkel geruest-einzelmodul geruest-typ)
(princ (ssg-textf "vfs-edit-neu-aufgebaut" (list bname)))
)
)
(ssg-end)
(princ)
)
;; ============================================================
;; REGISTRIERUNG
;; ============================================================
+15 -2
View File
@@ -50,7 +50,8 @@ SSG_LIB
│ │ ├── Doppel → OMNI_WK_Doppel
│ │ └── Dreiwege → OMNI_WK_Dreiwege
│ ├── Weichenkombinationen
│ │ ├── Delta → OMNI_WKomb_Delta
│ │ ├── Delta 1400/700 → OMNI_WKomb_Delta_1400
│ │ ├── Delta 1600/800 → OMNI_WKomb_Delta_1600
│ │ └── Star → OMNI_WKomb_Star
│ ├── TEF Elemente
│ │ ├── Umlenkspannst. rechts → OMNI_TEF_UmlenkR
@@ -59,6 +60,9 @@ SSG_LIB
│ │ ├── Antriebst. rechts → OMNI_TEF_AntriebR
│ │ └── TEF Gerade → OMNI_TEF_Gerade
│ └── KettenFoerderer → OMNI_KettenFoerderer
├── Konfiguration
│ ├── Umschalten 2D und 3D → SSG_DIM_SWITCH
│ └── Sprache → SSG_SPRACHE
└── External
├── Call Python → CALLPYTHON
├── Export Sivas → EXPORTSIVAS
@@ -96,7 +100,7 @@ Einfuegen von Omniflo-Standardkomponenten (Boegen, Geraden, Weichen, TEF-Element
| `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_WKomb_Delta_1400/1600, OMNI_WKomb_Star` | Weichenkombinationen einfuegen |
| `OMNI_TEF_*` | TEF-Elemente einfuegen (Umlenk-/Antriebsstationen, Gerade) |
| `OMNI_KettenFoerderer` | Kettenfoerderer einfuegen |
@@ -127,6 +131,13 @@ Unterstuetzte Bogenwinkel: 3, 9, 12, 15, 24, 36, 48 Grad
| `SSG-LayerOnAll` | Alle ausgeschalteten Layer einschalten |
| `SSG-LayerDelete` | Layer und alle Objekte darauf loeschen (mit Bestaetigung) |
### SSG_LIB_Commands.lsp - Konfiguration
| Befehl | Beschreibung |
| --- | --- |
| `SSG_DIM_SWITCH` | Schaltet zwischen 2D- und 3D-Bloecken um |
| `SSG_SPRACHE` | Sprache umschalten (Deutsch/Englisch), persistiert ueber `DXFM_LANG` |
### tests.lsp - Export und Python-Integration
| Befehl | Beschreibung |
@@ -140,6 +151,7 @@ Unterstuetzte Bogenwinkel: 3, 9, 12, 15, 24, 36, 48 Grad
| Datei | Beschreibung |
| --- | --- |
| `ssg_core.lsp` | Kernel: Umgebung, Layer-Ops, Block-Ops, Attribut-Ops, Fehlerbehandlung |
| `ssg_lang.lsp` | Sprachumschaltung Deutsch/Englisch (`ssg-text`, `ssg-textf`, `*ssg-lang*`) |
| `ssg_dialog.lsp` | Dialog-Vorlagen: Slide-Preview, Modul-Dialog, Block-Einfuegesequenz |
| `ssg_layer.lsp` | Layer-Verwaltungsbefehle |
| `ssg_load.lsp` | Loader: Laedt alle SSG-Bibliotheken in korrekter Reihenfolge |
@@ -180,6 +192,7 @@ dxfmakros/
| `DXFM_CFG` | Konfigurationsdateien |
| `DXFM_TESTS` | Testverzeichnis |
| `DXFM_DATA` | Datenverzeichnis |
| `DXFM_LANG` | Aktive Sprache (`de_DE`/`en_GB`), persistiert von `SSG_SPRACHE`; Default `de_DE` |
| `BRICSCAD` | Pfad zur BricsCAD-Executable |
## Einrichtung
+2 -1
View File
@@ -29,7 +29,8 @@ 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"
REM /b = Skript ausfuehren (NICHT /s - das ist der Support-Ordner-Schalter).
start /wait "" "%BRICSCAD%" /b "%DXFM_TESTS%\ILS_test.scr"
echo.
echo ================================================================
+149 -2
View File
@@ -1,14 +1,22 @@
@echo off
setlocal EnableDelayedExpansion
REM ================================================================
REM run_tests.bat - Testausfuehrung fuer SSG_LIB
REM
REM Schalter:
REM --lisp Startet BricsCAD headless, fuehrt die LISP-Unit-Tests
REM (TEST_UNIT) aus und wertet tests\output\unit_results.txt aus
REM --check Fuehrt pytest-Validierung aus
REM --diff_references Vergleicht CSVs in tests\reference und tests\output,
REM ruft bei Unterschieden das Diff-Tool (meld) auf
REM (ohne) Zeigt Hilfe an
REM
REM Beispiele:
REM bin\run_tests.bat --lisp
REM bin\run_tests.bat --check
REM bin\run_tests.bat --check test_kreisel.py
REM bin\run_tests.bat --diff_references
REM bin\run_tests.bat --diff_references kreisel_tests_export.csv
REM ================================================================
REM Umgebung setzen
@@ -23,10 +31,18 @@ if exist "%DXFMAKRO%\.venv\Scripts\activate.bat" (
set DO_CHECK=0
set CHECK_ARG=
set DO_DIFF=0
set DIFF_ARG=
set DO_LISP=0
REM Argumente parsen
:parse_args
if "%~1"=="" goto :after_args
if "%~1"=="--lisp" (
set DO_LISP=1
shift
goto :parse_args
)
if "%~1"=="--check" (
set DO_CHECK=1
if not "%~2"=="" (
@@ -36,11 +52,73 @@ if "%~1"=="--check" (
shift
goto :parse_args
)
if "%~1"=="--diff_references" (
set DO_DIFF=1
if not "%~2"=="" (
set "DIFF_ARG=%~2"
shift
)
shift
goto :parse_args
)
echo Unbekannter Schalter: %~1
goto :show_help
:after_args
if %DO_CHECK%==0 goto :show_help
if %DO_LISP%==0 if %DO_CHECK%==0 if %DO_DIFF%==0 goto :show_help
REM ================================================================
REM --lisp: LISP-Unit-Tests in BricsCAD ausfuehren
REM ================================================================
if %DO_LISP%==1 (
echo.
echo ================================================================
echo LISP UNIT-TESTS ^(TEST_UNIT^)
echo ================================================================
if not defined BRICSCAD (
echo FEHLER: BricsCAD nicht gefunden - siehe setenv.bat.
exit /b 1
)
if not exist "%DXFM_TESTS%\test_unit.scr" (
echo FEHLER: %DXFM_TESTS%\test_unit.scr nicht gefunden.
exit /b 1
)
REM Altes Ergebnis loeschen - fehlender Report = fehlgeschlagener Lauf
if exist "%DXFM_TESTOUT%\unit_results.txt" del "%DXFM_TESTOUT%\unit_results.txt"
echo BricsCAD wird im Batch-Modus gestartet ^(Skript: test_unit.scr^)...
REM /b = Skript im Batch-Modus ausfuehren (NICHT /s - das ist der
REM Support-Ordner-Schalter und ignoriert die .scr komplett).
REM /nologo unterdrueckt den Startbildschirm. Das Skript endet mit
REM _.QUIT, daher schliesst sich BricsCAD nach dem Lauf selbst.
start /wait "" "%BRICSCAD%" /nologo /b "%DXFM_TESTS%\test_unit.scr"
if not exist "%DXFM_TESTOUT%\unit_results.txt" (
echo.
echo FEHLER: Kein Report erzeugt ^(%DXFM_TESTOUT%\unit_results.txt^).
echo Lief TEST_UNIT in BricsCAD durch?
exit /b 1
)
echo.
type "%DXFM_TESTOUT%\unit_results.txt"
findstr /b /c:"RESULT: OK" "%DXFM_TESTOUT%\unit_results.txt" >nul
if errorlevel 1 (
echo.
echo ================================================================
echo ERGEBNIS: LISP-TESTS FEHLGESCHLAGEN
echo ================================================================
exit /b 1
)
echo.
echo ================================================================
echo ERGEBNIS: ALLE LISP-TESTS BESTANDEN
echo ================================================================
)
REM ================================================================
REM --check: pytest-Validierung
@@ -79,18 +157,87 @@ if %DO_CHECK%==1 (
echo ================================================================
)
REM ================================================================
REM --diff_references: CSV-Referenzvergleich
REM ================================================================
if %DO_DIFF%==1 (
echo.
echo ================================================================
echo REFERENZVERGLEICH ^(--diff_references^)
echo ================================================================
if not defined DXFM_DIFFTOOL (
echo.
echo FEHLER: Kein Diff-Tool ^(meld^) gefunden - siehe setenv.bat.
echo meld installieren: https://meldmerge.org
exit /b 1
)
set DIFF_COUNT=0
if not "%DIFF_ARG%"=="" (
if not exist "%DXFM_TESTREF%\%DIFF_ARG%" (
echo FEHLER: Referenzdatei nicht gefunden: %DXFM_TESTREF%\%DIFF_ARG%
exit /b 1
)
call :diff_one "%DXFM_TESTREF%\%DIFF_ARG%"
) else (
for %%F in ("%DXFM_TESTREF%\*.csv") do call :diff_one "%%F"
)
echo.
if !DIFF_COUNT!==0 (
echo ================================================================
echo ERGEBNIS: KEINE UNTERSCHIEDE GEFUNDEN
echo ================================================================
) else (
echo ================================================================
echo ERGEBNIS: !DIFF_COUNT! DATEI^(EN^) MIT UNTERSCHIEDEN
echo ================================================================
)
)
exit /b 0
REM ----------------------------------------------------------------
REM :diff_one <referenzdatei>
REM Vergleicht eine Referenzdatei mit der gleichnamigen Output-Datei
REM und ruft bei Unterschieden das Diff-Tool auf.
REM ----------------------------------------------------------------
:diff_one
set "REF_FILE=%~1"
set "OUT_FILE=%DXFM_TESTOUT%\%~nx1"
if not exist "%OUT_FILE%" (
echo WARNUNG: Keine Output-Datei fuer %~nx1 gefunden - uebersprungen.
goto :eof
)
fc "%REF_FILE%" "%OUT_FILE%" >nul 2>nul
if errorlevel 1 (
set /a DIFF_COUNT+=1
echo Unterschied: %~nx1
"%DXFM_DIFFTOOL%" "%REF_FILE%" "%OUT_FILE%"
)
goto :eof
:show_help
echo.
echo Aufruf: bin\run_tests.bat --check [testdatei]
echo Aufruf: bin\run_tests.bat --lisp
echo bin\run_tests.bat --check [testdatei]
echo bin\run_tests.bat --diff_references [csv-datei]
echo.
echo Schalter:
echo --lisp Startet BricsCAD headless, fuehrt TEST_UNIT aus
echo und wertet tests\output\unit_results.txt aus
echo --check Fuehrt pytest-Validierung fuer alle Module aus
echo --check test_kreisel.py Validiert nur Kreisel-Tests
echo --diff_references Vergleicht alle CSVs in tests\reference/output,
echo ruft bei Unterschieden meld auf
echo --diff_references datei.csv Vergleicht nur die angegebene CSV-Datei
echo.
echo Workflow:
echo 0. bin\run_tests.bat --lisp ^(reine LISP-Funktionen, ohne Zeichnung^)
echo 1. In BricsCAD: SSG_RUN_ALL_TESTS ausfuehren
echo 2. bin\run_tests.bat --check
echo 3. bin\run_tests.bat --diff_references
echo.
exit /b 1
+16
View File
@@ -15,6 +15,7 @@ REM Pfade fuer verschiedene Komponenten
set "DXFM_BIN=%DXFMAKRO%\bin"
set "DXFM_LIB=%DXFMAKRO%\lib"
set "DXFM_DATA=%DXFMAKRO%\data"
set "DXFM_LANG=%DXFMAKRO%\lang"
set "DXFM_TESTS=%DXFMAKRO%\tests"
set "DXFM_TESTDATA=%DXFM_TESTS%\testdata"
set "DXFM_TESTOUT=%DXFM_TESTS%\output"
@@ -40,6 +41,18 @@ if exist "C:\Program Files\Bricsys\BricsCAD V25 de_DE\bricscad.exe" (
echo Keine BricsCAD-Installation gefunden.
)
REM Diff-Tool fuer Referenzvergleich (run_tests.bat --diff_references) ermitteln
set "DXFM_DIFFTOOL="
for /f "delims=" %%D in ('where meld 2^>nul') do (
if not defined DXFM_DIFFTOOL set "DXFM_DIFFTOOL=%%D"
)
if not defined DXFM_DIFFTOOL (
if exist "C:\Program Files\Meld\Meld.exe" set "DXFM_DIFFTOOL=C:\Program Files\Meld\Meld.exe"
)
if not defined DXFM_DIFFTOOL (
echo HINWEIS: Kein Diff-Tool ^(meld^) gefunden - run_tests.bat --diff_references steht nicht zur Verfuegung.
)
REM Ueberladen von Umgebungsvariablen durch _setenv.bat (z.B. DXFM_DIM=3D)
if exist "%~dp0_setenv.bat" (
echo Lade lokale Umgebungseinstellungen aus _setenv.bat...
@@ -60,6 +73,7 @@ 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_LANG%" mkdir "%DXFM_LANG%"
if not exist "%DXFM_BLOCKS%" mkdir "%DXFM_BLOCKS%"
if not exist "%DXFM_OMNIFLO%" mkdir "%DXFM_OMNIFLO%"
if not exist "%DXFM_LISP%" mkdir "%DXFM_LISP%"
@@ -77,6 +91,7 @@ if /i "%1"=="--persist" (
setx DXFMAKRO "%DXFMAKRO%" >nul
setx DXFM_LISP "%DXFM_LISP%" >nul
setx DXFM_DATA "%DXFM_DATA%" >nul
setx DXFM_LANG "%DXFM_LANG%" >nul
setx DXFM_DCL "%DXFM_DCL%" >nul
setx DXFM_CFG "%DXFM_CFG%" >nul
setx DXFM_LOG "%DXFM_LOG%" >nul
@@ -92,6 +107,7 @@ echo DXFMAKRO = %DXFMAKRO%
echo DXFM_DIM = %DXFM_DIM%
echo DXFM_BLOCKS = %DXFM_BLOCKS%
echo DXFM_OMNIFLO = %DXFM_OMNIFLO%
echo DXFM_DIFFTOOL = %DXFM_DIFFTOOL%
echo ================================================================
echo.
+66
View File
@@ -27,3 +27,69 @@ 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
[Planquadrate]
section=Planquadrate_AN
# x_origin/y_origin (in m, DXF-Koordinate der Planquadrat-Ecke A/1 bzw. 1/1):
# Der Zeichnungsnullpunkt (0,0) liegt in der Regel NICHT in der Gebaeudeecke -
# Bauteile mit negativer x/y-Koordinate wuerden ohne Offset einen Planquadrat-
# Index <= 0 ergeben und damit ein leeres Label (z.B. "/" oder "A/") liefern.
# Leer lassen/weglassen = automatisch: der Ursprung wird bei jedem Export neu
# auf das jeweils am weitesten links (x_origin) bzw. am weitesten unten
# (y_origin) liegende Element der aktuellen Zeichnung gesetzt, damit gilt
# immer Index 1 = dieses Element. Nur explizit setzen, wenn ein fester
# Bezug zur realen Gebaeudeecke gebraucht wird (z.B. Vergleich ueber
# mehrere Exportlaeufe/Zeichnungen hinweg).
x_origin=
y_origin=
# hier kann man im csv Export aus den Koordinaten der Bauteile die Planquadrate berechnen lassen, in denen sie liegen
# Zählung ist numerisch oder Alphabetisch möglich, Schrittweite in m (z.B. 2m pro Spalte, 4m pro Zeile)
# liegt man im ersten Quadrat, ist diese A/1, oder 1/1 oder 1/A, je nach Formatierung. Die Zählung beginnt immer bei 1
[Planquadrate_NA]
# z.B. 1/A
x_step=2
x_description=numerisch # zahlen, von links nach rechts, 2m pro Spalte
y_step=4
y_description=alphabetisch # Buchstaben von unten nach oben, 4m pro Zeile
format= {x}/{y} # Formatierung der Planquadrate, {y} und {x} werden durch die berechneten gerundeten Werte der Objektkoordinaten ersetzt
[Planquadrate_AN]
# z.B. A/1
x_step=2
x_description=alphabetisch # Buchstaben, von links nach rechts, 2m pro Spalte
y_step=2
y_description=alphabetisch # Zahlen von unten nach oben, 2m pro Zeile
format= {x}/{y}
[Planquadrate_NN]
# z.B. 2/5
x_step=2
x_description=numerisch # Zahlen, von links nach rechts, 2m pro Spalte
y_step=4
y_description=numerisch # Zahlen von unten nach oben, 4m pro Zeile
format= {x}/{y}
[Nachbarschaft]
# Toleranz fuer die Nachbarschaftserkennung beim CSV-Export (Spalte "Nachbarn").
# Die Bounding-Box jedes Elements wird um die Haelfte dieses Werts nach allen
# Seiten erweitert, bevor auf Ueberschneidung mit anderen Elementen geprueft
# wird - zwei Elemente mit einem Abstand <= toleranz_mm (z.B. zwei Kreisel)
# gelten dann ebenfalls als benachbart. Wert in mm. Siehe lib/export_neighbors.py.
toleranz_mm=200
# Rastergroesse (mm) fuer die Omniflo-Nachbarschaftspruefung (Bogen/Weiche/
# Gerade gegen Bogen/Weiche/Gerade). Omniflo-Elemente werden vor dem
# Ueberschneidungstest nach x/y-Koordinate in Quadranten dieser Groesse
# eingeteilt, geprueft wird dann nur innerhalb derselben und der 8
# angrenzenden Zellen (statt jedes Element gegen jedes). Sollte groesser
# als die ueblichen Omniflo-Bauteile sein (AP110-Geraden ca. 2000mm).
omniflo_zellgroesse_mm=3000
[Boundingbox]
# Mindesthoehe (Z-Ausdehnung) der von export.lsp (csv:get-bbox, per
# vla-getboundingbox) ermittelten Bounding-Box. Flache 2D-Bloecke (Draufsicht)
# haben oft dz=0 - wird auf diesen Wert angehoben. Wert in mm. Default 1, falls
# nicht gesetzt.
bb_minimum_height_mm=1
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.
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