diff --git a/CLAUDE.md b/CLAUDE.md index ab00d03..2cb453f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -75,7 +75,7 @@ Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD. | VarioFoerderer | `VarioFoerderer` | FOERDERANLAGE, VARIOFOERDERER_EDIT, Vario_Kette_Merge | | Gefaellestrecke | `Gefaellestrecke` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT | | Omniflo (komplett) | `OmniModulInsert` | OMNI_APB_*, OMNI_W*_*, OMNI_AP*, OMNI_TEF_*, OMNI_TV_*, OMNI_LADESCHLEIFE_*, OMNI_EDIT | -| Geruest | `GeruestInsert` | GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG (derselbe Dialog, im jeweiligen Bereich geoeffnet; Rohr-Geruest-Traeger/Gattertraeger noch Platzhalter auf GERUEST) | +| Geruest | `GeruestInsert` | GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG (derselbe Dialog, im jeweiligen Bereich geoeffnet), GERUEST_TRAEGER (eigener Dialog), GERUEST_TRAEGER_BESCHRIFTEN (Untermenue Geruest -> Funktionen -> Traeger beschriften; alle Traeger der Zeichnung neu beschriften); Gattertraeger noch Platzhalter auf GERUEST | | Connections | `Connection_Edit` + `SSG_LIB_Commands` | CONNECTION_INSERT, CONNECTION_EDIT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT | | Export | `export` | EXPORTSIVAS, EXPORTCSV, CALLPYTHON | | Konfiguration | `SSG_LIB_Commands` + `DrawPlanquadrate` | SSG_DIM_SWITCH, SSG_SPRACHE, PLANQUADRATE_TOGGLE (DRAW_PLANQUADRATE/DELETE_PLANQUADRATE) | @@ -107,7 +107,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W*_*, OMNI_AP60/AP110, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_LADESCHLEIFE_AP110, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen, Ladeschleifen (`data/json/omniflo_ladeschleifen.json`, per `ssg-json-laden`, da die Beschreibungen Kommas enthalten; Blockdatei darf `.dwg` statt `.dxf` sein), Edit-Dialog | | `SSG_LIB_Commands.lsp` | ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_SCANNER_INSERT, ILS_SEPARATOR_INSERT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT, ILS_ETF_*, ILS_GK*_*, SSG_BLOCKEDIT, SSG_DIM_SWITCH, SSG_SPRACHE | BTMT Be-/Entladung (`ils-insert-station`: wiederholtes Einfuegen von `BTMT-Beladung` bzw. `SC_Entladung`, Drehung interaktiv, Layer aus `LAYER`-Attribut, Dimension via `ssg-ils-block-laden`) + Sensoren (`ils-insert-sensor`) + Eingang-/Ausgang-Symbol (frei platzierbar wie BTMT Be-/Entladung, ueber `ils-insert-station` mit den Rohnamen `Eingang`/`Ausgang`, Bloecke `Eingang_.dwg`/`Ausgang_.dwg` in data/ils) + Dummy-Befehle fuer Menue + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) | | `Tro_Edit.lsp` | TRO_INSERT, TRO_EDIT | TRO-Marker (Block `TRO_SYM_`) fuer sps_skel (lib/tro_annotate.py): TRO_INSERT fuegt eine bestehende Blockdefinition an einem gewaehlten Punkt ein und setzt ID/TYPE (bricht ab, wenn der Typ noch keine Blockdefinition in der Zeichnung hat - die entsteht nur ueber tro_annotate.py); TRO_EDIT aendert ID/TYPE eines bestehenden Markers per Dialog. Typliste aus `tro_types.lsp` (von `tro_annotate.py --emit-lisp` nach DXFM_LISP geschrieben). Der Dispatcher SSG_BLOCKEDIT leitet Blocknamen `TRO_*` zu TRO_EDIT. | -| `GeruestInsert.lsp` | GERUEST, GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG | Geruest-Baugruppen aus `data/json/geruest.json` konfigurieren und einfuegen. **Ein Dialog fuer alle Bereiche**: oben ein Dropdown `bereich` (Rohrabhaenger / Saeulen / Wandbefestigung, Reihenfolge = Dateireihenfolge, Anzeigename aus dem ASCII-Feld `titel`). DCL hat **kein Reiter-Tile**, und da sich die Teilezeilen je Bereich unterscheiden, schliesst ein Bereichswechsel den Dialog (`done_dialog 4`) und die Schleife in `c:GERUEST` baut ihn neu auf; der Stand jedes Bereichs bleibt in `*geruest-zustand*` erhalten, ein versehentlicher Wechsel verwirft also nichts. 1"- und 2"-Saeulen liegen in EINER Baugruppe `Saeulen` mit gemeinsamer Anbauteil-Liste; **`teileart` und `dummy` duerfen je Geometrie-Variante ueberschrieben werden** (`geruest-variante-wert`, Variante gewinnt vor Baugruppe) - so liefert `R 1"` weiterhin TEILEART `Geruest Saeule 1 Zoll` und die `R 2"`-Varianten `Geruest Saeule 2 Zoll`, die Groessen bleiben im Export also unterscheidbar. **Die Dialogdefinition wird zur Laufzeit erzeugt** (`geruest-dcl-schreiben` -> temporaere Datei per `vl-filename-mktemp`, nach `unload_dialog` wieder geloescht) - es gibt KEINE `dcl/geruest.dcl`. Grund: je Anbauteil wird ein eigenes Mengenfeld gebraucht, und eine DCL-Liste (`list_box`) kann keine Eingabefelder enthalten; DCL kann weder Dateien einbinden noch Tiles zur Laufzeit erzeugen. Inhalt: Basis-Variante aus `geometrie_varianten` (Dropdown), Laenge (gegen `attribute.Laenge` min/max geprueft, Retry-Schleife), Farbe (`attribute.Teilefarbe`, Freitext bei `frei_option`) und **zwei Befestigungslisten** ("oben"/"unten"), die BEIDE alle `anbaugruppen` enthalten - dasselbe Teil kann oben, unten oder gleichzeitig an beiden Positionen sitzen, je mit eigener Stueckzahl (vorbelegt aus `menge`). Baugruppen ohne `attribute`-Block (Wandbefestigung) bekommen Laenge/Farbe gesperrt, Baugruppen ohne Anbauteile bekommen gar keine Spalten (ein leerer DCL-Cluster ist unzulaessig). Im generierten Label wird `"` zu `''` ersetzt (`geruest-dcl-label`) - fuenf Artikelnamen enthalten ein Anfuehrungszeichen, das das DCL-Label sonst vorzeitig beendet und die Datei zerstoert. **Konfigurationen**: gepflegte Bibliothek je Baugruppe unter `konfigurationen` in `geruest.json` (schreibgeschuetzt) plus eigene in `cfg/geruest_user.json` (gitignored, `geruest-user-schreiben`; getrennte Datei, damit Benutzerdaten und versionierte Bibliothek nicht kollidieren). Eigene Eintraege sind in der Liste mit `*` markiert und nur diese loeschbar. Konfigurationen verweisen ueber den ANZEIGENAMEN auf Variante und Anbauteile; ein unbekannter Name wird gemeldet und uebersprungen, statt die Konfiguration scheitern zu lassen. Speichern/Loeschen laufen ueber `done_dialog 2`/`3` (Dialog schliessen, Aktion, neu zeigen) - `getstring` funktioniert aus einem `action_tile`-Rueckruf heraus nicht. Der Block wird - wie KREISEL_n/VF_n - SELBST zusammengebaut: Dummy-DWG aus `data/geruest` liefert nur Geometrie, das Attribut-Schema kommt aus `*geruest-attrib-defs*` (ID, ARTINR, LAENGE, BEZEICHNUNG, TEILEART, TEILEFARBE, LAYER) und wird per `ssg-attrib-merge` mit den Dummy-Tags zusammengefuehrt - sonst verschluckt `ssg-attrib-set-on` stillschweigend jeden Tag, den die Dummy-DWG nicht als ATTDEF kennt. **Teile-Geometrie**: jede ausgewaehlte Artikelnummer (Basis/oben/unten inkl. aufgeloester Gruppen), fuer die `data/geruest/.dwg` existiert, wird zusaetzlich einmal bei 0,0,0 mit in den Block eingefuegt (`geruest-teile-dwgs`, dedupliziert, fehlende DWGs still uebergangen) - reine visuelle Rueckmeldung, die Attribut-Logik bleibt davon unberuehrt. **TEILEFARBE** ist eine kommagetrennte Liste parallel zu ARTINR (z.B. `,,RAL7030,,RAL7030`): Teile mit `"farbig": true` in `geruest.json` (je Artikel; eine Gruppe vererbt es an ihre Teile, fehlend = false) bekommen die im Dialog gewaehlte Baugruppenfarbe, alle anderen einen leeren Eintrag. ARTINR und TEILEFARBE entstehen aus demselben Durchlauf (`geruest-teile-paare`/`-paare-n`, `geruest-farbliste`), sind also garantiert gleich lang. `export_sivas.py` schreibt daraus je Artikelnummer das Merkmal `{"108": ""}` in `details` (Nummer aus `cfg/export.cfg` `[Sivas] merkmal_teilefarbe`). Blockname `GR__` (Kollisionszaehler wie in OmniModulInsert). **Das `GR_`-Praefix ist nicht kosmetisch**: `SSG_BLOCKEDIT` haelt JEDEN Block mit TEILEART-Attribut fuer ein Omniflo-Element, deshalb steht in `SSG_LIB_Commands.lsp` ein `GR_*`-Zweig VOR dem Omniflo-Zweig. ARTINR listet jede Sivas-ID so oft, wie die gewaehlte Stueckzahl es vorgibt - erst Basis, dann Befestigung oben, dann unten; bei einer benannten Gruppe (`teile`) wird das ganze Set n-mal wiederholt, die Mengen INNERHALB des Sets bleiben dabei erhalten (`geruest-artikelnummern-n`). BEZEICHNUNG nennt Position und Menge je Teil ("oben 2x ...") und verkettet mit `" + "`, NICHT mit Komma - die Artikelbezeichnungen enthalten selbst Kommas ("ROHR R 1\" 33,7 x 2,6"). Zuordnung Menue -> JSON laeuft ueber das ASCII-Feld `id`, weil die aeusseren JSON-Schluessel Umlaute bzw. Anfuehrungszeichen tragen. CSV-/Sivas-Export: `pattern_geruest = GR_*` (cfg/export.cfg), `csv:collect-export-blocks`/`ssg-id-collect-blocks` sammeln GR_-Bloecke wie BTMT eigenstaendig; `*geruest-attrib-defs*` traegt zusaetzlich ein leeres `ID`-ATTDEF (Voraussetzung fuer `ssg-id-check-all`, das nur bestehende ATTRIBs beschreiben kann). ARTINR/BEZEICHNUNG/TEILEART/LAENGE landen in export_csv.py/export_sivas.py in festen Spalten, TEILEFARBE/LAYER (+ ARTINR bei export_csv.py) im Merkmale-/details-JSON. Noch NICHT enthalten: Edit-Pfad (GERUEST_EDIT) | +| `GeruestInsert.lsp` | GERUEST, GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG, GERUEST_TRAEGER, GERUEST_TRAEGER_BESCHRIFTEN | Geruest-Baugruppen aus `data/json/geruest.json` konfigurieren und einfuegen. **Ein Dialog fuer alle Bereiche**: oben ein Dropdown `bereich` (Rohrabhaenger / Saeulen / Wandbefestigung, Reihenfolge = Dateireihenfolge, Anzeigename aus dem ASCII-Feld `titel`). DCL hat **kein Reiter-Tile**, und da sich die Teilezeilen je Bereich unterscheiden, schliesst ein Bereichswechsel den Dialog (`done_dialog 4`) und die Schleife in `c:GERUEST` baut ihn neu auf; der Stand jedes Bereichs bleibt in `*geruest-zustand*` erhalten, ein versehentlicher Wechsel verwirft also nichts. 1"- und 2"-Saeulen liegen in EINER Baugruppe `Saeulen` mit gemeinsamer Anbauteil-Liste; **`teileart` und `dummy` duerfen je Geometrie-Variante ueberschrieben werden** (`geruest-variante-wert`, Variante gewinnt vor Baugruppe) - so liefert `R 1"` weiterhin TEILEART `Geruest Saeule 1 Zoll` und die `R 2"`-Varianten `Geruest Saeule 2 Zoll`, die Groessen bleiben im Export also unterscheidbar. **Die Dialogdefinition wird zur Laufzeit erzeugt** (`geruest-dcl-schreiben` -> temporaere Datei per `vl-filename-mktemp`, nach `unload_dialog` wieder geloescht) - es gibt KEINE `dcl/geruest.dcl`. Grund: je Anbauteil wird ein eigenes Mengenfeld gebraucht, und eine DCL-Liste (`list_box`) kann keine Eingabefelder enthalten; DCL kann weder Dateien einbinden noch Tiles zur Laufzeit erzeugen. Inhalt: Basis-Variante aus `geometrie_varianten` (Dropdown), Laenge (gegen `attribute.Laenge` min/max geprueft, Retry-Schleife), Farbe (`attribute.Teilefarbe`, Freitext bei `frei_option`) und **zwei Befestigungslisten** ("oben"/"unten"), die BEIDE alle `anbaugruppen` enthalten - dasselbe Teil kann oben, unten oder gleichzeitig an beiden Positionen sitzen, je mit eigener Stueckzahl (vorbelegt aus `menge`). Baugruppen ohne `attribute`-Block (Wandbefestigung) bekommen Laenge/Farbe gesperrt, Baugruppen ohne Anbauteile bekommen gar keine Spalten (ein leerer DCL-Cluster ist unzulaessig). Im generierten Label wird `"` zu `''` ersetzt (`geruest-dcl-label`) - fuenf Artikelnamen enthalten ein Anfuehrungszeichen, das das DCL-Label sonst vorzeitig beendet und die Datei zerstoert. **Konfigurationen**: gepflegte Bibliothek je Baugruppe unter `konfigurationen` in `geruest.json` (schreibgeschuetzt) plus eigene in `cfg/geruest_user.json` (gitignored, `geruest-user-schreiben`; getrennte Datei, damit Benutzerdaten und versionierte Bibliothek nicht kollidieren). Eigene Eintraege sind in der Liste mit `*` markiert und nur diese loeschbar. Konfigurationen verweisen ueber den ANZEIGENAMEN auf Variante und Anbauteile; ein unbekannter Name wird gemeldet und uebersprungen, statt die Konfiguration scheitern zu lassen. Speichern/Loeschen laufen ueber `done_dialog 2`/`3` (Dialog schliessen, Aktion, neu zeigen) - `getstring` funktioniert aus einem `action_tile`-Rueckruf heraus nicht. Der Block wird - wie KREISEL_n/VF_n - SELBST zusammengebaut: Dummy-DWG aus `data/geruest` liefert nur Geometrie, das Attribut-Schema kommt aus `*geruest-attrib-defs*` (ID, ARTINR, LAENGE, BEZEICHNUNG, TEILEART, TEILEFARBE, LAYER) und wird per `ssg-attrib-merge` mit den Dummy-Tags zusammengefuehrt - sonst verschluckt `ssg-attrib-set-on` stillschweigend jeden Tag, den die Dummy-DWG nicht als ATTDEF kennt. **Teile-Geometrie**: jede ausgewaehlte Artikelnummer (Basis/oben/unten inkl. aufgeloester Gruppen), fuer die `data/geruest/.dwg` existiert, wird zusaetzlich einmal bei 0,0,0 mit in den Block eingefuegt (`geruest-teile-dwgs`, dedupliziert, fehlende DWGs still uebergangen) - reine visuelle Rueckmeldung, die Attribut-Logik bleibt davon unberuehrt. **TEILEFARBE** ist eine kommagetrennte Liste parallel zu ARTINR (z.B. `,,RAL7030,,RAL7030`): Teile mit `"farbig": true` in `geruest.json` (je Artikel; eine Gruppe vererbt es an ihre Teile, fehlend = false) bekommen die im Dialog gewaehlte Baugruppenfarbe, alle anderen einen leeren Eintrag. ARTINR und TEILEFARBE entstehen aus demselben Durchlauf (`geruest-teile-paare`/`-paare-n`, `geruest-farbliste`), sind also garantiert gleich lang. `export_sivas.py` schreibt daraus je Artikelnummer das Merkmal `{"108": ""}` in `details` (Nummer aus `cfg/export.cfg` `[Sivas] merkmal_teilefarbe`). Blockname `GR__` (Kollisionszaehler wie in OmniModulInsert). **Das `GR_`-Praefix ist nicht kosmetisch**: `SSG_BLOCKEDIT` haelt JEDEN Block mit TEILEART-Attribut fuer ein Omniflo-Element, deshalb steht in `SSG_LIB_Commands.lsp` ein `GR_*`-Zweig VOR dem Omniflo-Zweig. ARTINR listet jede Sivas-ID so oft, wie die gewaehlte Stueckzahl es vorgibt - erst Basis, dann Befestigung oben, dann unten; bei einer benannten Gruppe (`teile`) wird das ganze Set n-mal wiederholt, die Mengen INNERHALB des Sets bleiben dabei erhalten (`geruest-artikelnummern-n`). BEZEICHNUNG nennt Position und Menge je Teil ("oben 2x ...") und verkettet mit `" + "`, NICHT mit Komma - die Artikelbezeichnungen enthalten selbst Kommas ("ROHR R 1\" 33,7 x 2,6"). Zuordnung Menue -> JSON laeuft ueber das ASCII-Feld `id`, weil die aeusseren JSON-Schluessel Umlaute bzw. Anfuehrungszeichen tragen. CSV-/Sivas-Export: `pattern_geruest = GR_*` (cfg/export.cfg), `csv:collect-export-blocks`/`ssg-id-collect-blocks` sammeln GR_-Bloecke wie BTMT eigenstaendig; `*geruest-attrib-defs*` traegt zusaetzlich ein leeres `ID`-ATTDEF (Voraussetzung fuer `ssg-id-check-all`, das nur bestehende ATTRIBs beschreiben kann). ARTINR/BEZEICHNUNG/TEILEART/LAENGE landen in export_csv.py/export_sivas.py in festen Spalten, TEILEFARBE/LAYER (+ ARTINR bei export_csv.py) im Merkmale-/details-JSON. **Attribut-Keys in `geruest.json` sind GROSS** (`LAENGE`, `TEILEFARBE`, ...) = die Block-Attribut-Tags; `ssg-json-get` unterscheidet Gross/Klein. **Rohr-Geruest-Traeger** (`GERUEST_TRAEGER`, Baugruppe mit `"einfuegeart": "linie"` - fehlt darum im Bereichs-Dropdown von GERUEST, gefunden ueber `geruest-baugruppe`): eigener fester Dialog `dcl/geruest_traeger.dcl` (Variante, Farbe, je eine Checkbox + Feld fuer `LAENGENABZUGANFANG`/`LAENGENABZUGENDE`, Vorgabe `vorgabe`/`aktiv` aus dem attribute-Block, je Variante ueberschreibbar via `geruest-attr-feld`); danach Einfuege-Schleife bis ESC/Enter: Startpunkt, dann Endpunkt ODER getippte Laenge (+ Richtung). Aktive Abzuege ruecken die Linie beidseitig ein (Strecke 1000, Abzug Anfang 20/Ende 35 -> Start 20 mm hinter dem Klick, Linie 945 mm); `LAENGE` = Netto-Laenge, gegen `LAENGE.min/max` geprueft. KEINE Dummy-DWG: die Geometrie ist eine per `entmake` erzeugte LINE (0,0,0)-(L,0,0) auf dem `layer` der Variante, eingefuegt mit dem Richtungswinkel (ANGBASE/ANGDIR/AUNITS dafuer kurz auf 0). **Querstreben + Muffe** als verschachtelte Dummy-DWGs im selben Block, reine Grafik ohne Export: `querstrebe.dummy` (`data/geruest/dummy_Strebe_30x4.dwg`, Basispunkt Strebenmitte, 30 mm laengs X) an jeder Strebenposition; fehlt die DWG, Rueckfall auf je eine 25-mm-Querlinie an Strebenanfang/-ende (`laenge`/`querlinie`, Standard 30/25 nur im Code). `muffe.dummy` (`dummy_Muffe_1zoll.dwg`, Basispunkt Muffenmitte) am Linienende, NUR bei Varianten mit ausdruecklichem `"mit_muffe": true` (nicht aus dem Namen geraten; bei "mit 2 Muffen" trotzdem nur eine am Ende); `querstrebe`/`muffe` per Variante ueberschreibbar (`geruest-variante-wert`). Dummys werden ohne Drehung eingefuegt (Traeger laeuft im Block entlang +X), ab dem zweiten Mal per Blockname (`geruest-dummy-einfuegen`). Verteilungs-Konfiguration `querstrebe` (`abstand_max`/`rand_min`/`rand_max`, Variante vor Baugruppe), Verteilung `geruest-traeger-streben`: so wenige Streben wie moeglich, beide Raender gleich; Abstand GENAU `abstand_max`, solange der Rand in `rand_min`..`rand_max` bleibt (1300 -> 150|500|500|150), sonst Rand = `rand_min` und Abstand etwas kleiner (1100 -> 100|450|450|100, mit fest 500 geht die Laenge nicht auf); Netto <= 2*rand_max -> eine Strebe mittig, < 2*rand_min -> keine. Schema `*geruest-traeger-attrib-defs*` = `*geruest-attrib-defs*` + die zwei Abzug-Tags; gemeinsamer Block-Schluss mit den anderen Bereichen in `geruest-block-abschliessen`. Reine Berechnung (`geruest-traeger-laenge`/`-start`/`-pruefen`, `geruest-mm-zahl`) in `tests/test_unit.lsp`. **Traeger-Beschriftung** (Checkbox im Dialog, Standard an; z.B. `RT 80/80 L=2650`): EIGENES TEXT-Objekt neben dem Block, abgeleitet NUR aus dem fertigen Block (Einfuegepunkt, DXF 50, Attribute `LAENGE` + `VARIANTE`) - darum nutzen Einfuegen und `GERUEST_TRAEGER_BESCHRIFTEN` dieselbe Funktion `geruest-traeger-beschriften`, und ein von Hand verschobener/gedrehter Traeger wird beim Neubeschriften korrekt erfasst. Verknuepfung Text -> Block per XDATA `SSG_GR_BESCHR` (1005 = Block-Handle): Neubeschriften ersetzt statt verdoppelt, der Sammelbefehl entfernt verwaiste Texte. JSON `beschriftung` (je FELD Variante vor Baugruppe, `geruest-obj-feld`): Inhalt `format` (`%1` Text, `%2` Laenge auf ganze mm) + `text` (fehlt -> Variantenname) und `layer` (je Variante verschieden, darum in JEDER Variante gepflegt - keine Baugruppen-Vorgabe; fehlt er doch, aktueller Layer); Formatierung NUR `stil`/`ausrichtung`/`hoehe` - alles andere regelt der Textstil ausserhalb, es wird kein Stil angelegt (fehlt er: Meldung, aktueller TEXTSTYLE). `ausrichtung` = Codes von TEXT "Ausrichten" (T/M/B + L/C/R), Bezugspunkt auf der Traegerlinie, L/R in LESErichtung. Textwinkel entlang des Traegers, DIN: fuer 90 < w <= 270 Grad um 180 gedreht (`geruest-text-winkel`). Noch NICHT enthalten: Edit-Pfad (GERUEST_EDIT) | | `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) | | `DrawPlanquadrate.lsp` | DRAW_PLANQUADRATE, DELETE_PLANQUADRATE, PLANQUADRATE_TOGGLE | Zeichnet auf Z=0 ein Planquadrat-Linienraster (senkrecht/waagerecht), im Abstand/Zaehlschema der aktiven `[Planquadrate]`-Konfiguration aus `cfg/export.cfg` (dieselbe Quelle wie `lib/export_planquadrat.py` fuer den CSV-Export). Bereich kommt NICHT aus den Zeichnungs-Extents, sondern aus derselben Blockmenge wie EXPORTCSV (`csv:collect-export-blocks`, export.lsp; siehe `plq-export-bbox`): Ursprung (Index 1) UND obere Grenze kommen BEIDE aus der tatsaechlichen Bounding-Box jedes Blocks (`csv:get-bbox`, wie `bbox_columns()`/`planquadrat_column()`/`_bbox_min()` in `lib/export_csv.py` bzw. `lib/export_planquadrat.py`), NICHT aus dem reinen Einfuegepunkt - bei einem gedrehten/exzentrisch eingefuegten Block (z.B. ein um 90 Grad gedrehter Kreisel) kann das Bounding-Box-Zentrum weit vom Einfuegepunkt abweichen; Ursprung und Zellzuordnung muessen auf derselben Referenz beruhen, sonst driften sie auseinander (realer Bug, behoben). Reine Hilfsgeometrie (Kreisel-Umfahrungsboegen als eigene Linien, Texte) zaehlt bewusst nicht mit, sonst weicht das Raster vom CSV-Export ab. `x_origin`/`y_origin` ueberschreiben den Ursprung, Fallback auf EXTMIN/EXTMAX falls keine Export-Bloecke vorhanden sind bzw. `csv:get-bbox` fuer einen Block scheitert. Spalten-/Zeilenzahl wird IMMER aufgerundet auf volle Rasterschritte, damit alle senkrechten Linien auf der letzten waagerechten enden und umgekehrt - das Raster bildet immer ein geschlossenes Rechteck. Zaehlung (alphabetisch/numerisch je Achse) als Text am linken/unteren Rand. Das fertige Raster (Linien+Texte) wird per `_.-BLOCK`/`_.INSERT` zu einem einzigen Block `ZZ_PLANQUADRATE` bei (0,0,0) zusammengefasst. Layer aus `cfg/layer.cfg` (`[allgemein]` Key `planquadrate`, Fallback `ZZ_Planquadrate`). DRAW_PLANQUADRATE entfernt vor dem Neuaufbau zuerst einen evtl. vorhandenen Block (`plq-block-entfernen`: INSERTs loeschen + `_-PURGE _B`), DELETE_PLANQUADRATE ruft nur diese Entfernung auf. PLANQUADRATE_TOGGLE ("Planquadrate an/aus", Menue: Konfiguration) prueft per `tblsearch`/`ssget "X"`, ob der Block existiert, und dispatcht auf Zeichnen bzw. Loeschen. Lazy geladen ueber `(ssg-ensure "DrawPlanquadrate")`, nicht in der Core-Ladereihenfolge. Die Planquadrat-SPALTE im CSV-Export (`export_csv.py::planquadrat_column`/`resolve_origins`, `lib/export_planquadrat.py::compute_planquadrat`/`_bbox_min`) rechnet ebenfalls durchgaengig auf Bounding-Box-Basis (nicht nur Einfuegepunkt) und liefert eine SPANNE ("A/1-J/1") statt nur einer Zelle, wenn ein Element mehr als eine Zelle ueberdeckt (Kreisel, lange VF-/GF-Ketten). | @@ -124,6 +124,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `sprache.dcl` | SSG_SPRACHE (SSG_LIB_Commands.lsp) | | `tro_insert.dcl` | TRO_INSERT (Tro_Edit.lsp) | | `tro_edit.dcl` | TRO_EDIT (Tro_Edit.lsp) | +| `geruest_traeger.dcl` | GERUEST_TRAEGER (GeruestInsert.lsp, `geruest-traeger-dialog`) | | `vfl_edit.dcl` | Linienzug-Editieren/Fortsetzen (vf_linienzug.lsp, `vfl-dlg-position`, aufgerufen aus `vfl-edit-ent`) | | `vf_linienzug_wizard.dcl` | Linienzug-Assistent (Modus 1, 2 UND 3): zwei generische Einzel-Dialoge (Zahl-Eingabe, Mehrfachauswahl; `vflw-zahl`/`vflw-wahl`, aufgerufen aus `vfl-in-real`/`vfl-in-string`/`vfl-in-int` bei aktivem `*vfl-wizard-mode*`) PLUS sieben Gruppen-Dialoge, die mehrere immer unmittelbar aufeinanderfolgende Fragen in einem Bildschirm zusammenfassen (Kettenstart, AS-Element, GF-Bogen, ES-Element, Vario-Kurve, Gefaelle festlegen, Ziel-Hoehe, Horizontales Stueck - inkl. Punktwahl-Button mit X/Y/Z-Anzeige; `vflw-gruppe-*-impl` in vf_linienzug.lsp fuellen dafuer vorab eine kleine Pending-Queue `*vflw-pending*`, die einzelnen `vfl-in-*`-Aufrufe bleiben dabei unveraendert) PLUS drei Segment-Gruppen-Dialoge fuer die segmentweise Klassifizierung in Modus 2/3 (`vflw_seg_linie_m2` = Typ+GF-Neigung, `vflw_seg_linie_m3` = 4-fach-Typ+kontextabh. Wertfeld, `vflw_seg_bogen` = Typ+Variante; `vflw-seg-*-impl`). Beide Modi heben vor der Frage das aktuelle Pfad-Segment (LINE/ARC) per `vfl-seg-highlight` (`redraw`) in der Zeichnung hervor und zeigen "Segment i/n ..." im Dialogkopf. Details: `doc/variofoerderer.md` | diff --git a/Lisp/GeruestInsert.lsp b/Lisp/GeruestInsert.lsp index 436fe2f..1788ed1 100644 --- a/Lisp/GeruestInsert.lsp +++ b/Lisp/GeruestInsert.lsp @@ -67,6 +67,24 @@ ) ) +;; Rohr-Geruest-Traeger: dasselbe Schema plus die beiden Laengenabzuege und +;; VARIANTE (Name der Geometrie-Variante). Bewusst ein eigenes Schema - die +;; anderen GR_-Bloecke behalten ihres. LAENGE ist beim Traeger die +;; NETTO-Laenge (Strecke minus Abzuege). VARIANTE macht den Block +;; selbstbeschreibend: GERUEST_TRAEGER_BESCHRIFTEN findet darueber die +;; Formatierung der Beschriftung, ohne den Dialog zu kennen. +;; Ohne null-Guard: ein Neuladen der Datei soll ein erweitertes Schema sofort +;; wirksam machen. +(setq *geruest-traeger-attrib-defs* + (append *geruest-attrib-defs* + '(("LAENGENABZUGANFANG" "") + ("LAENGENABZUGENDE" "") + ("VARIANTE" ""))) +) + +;; XDATA-App der Traeger-Beschriftung: Gruppe 1005 = Handle des Traeger-Blocks. +(setq *geruest-beschr-app* "SSG_GR_BESCHR") + (if (null *geruest-block-counter*) (setq *geruest-block-counter* 0)) @@ -116,10 +134,14 @@ ;; Alle Baugruppen als ((id . objekt) ...) in Dateireihenfolge - diese ;; Reihenfolge bestimmt auch die Reihenfolge im Bereichs-Dropdown. +;; Baugruppen mit "einfuegeart": "linie" (Rohr-Geruest-Traeger) fehlen hier: +;; sie haben einen eigenen Dialog und einen eigenen Einfuegeablauf +;; (c:GERUEST_TRAEGER) und gehoeren nicht in das Bereichs-Dropdown. (defun geruest-baugruppen-liste ( / erg) (setq erg nil) (foreach eintrag (geruest-daten) - (if (listp (cdr eintrag)) + (if (and (listp (cdr eintrag)) + (not (equal (ssg-json-get (cdr eintrag) "einfuegeart") "linie"))) (setq erg (append erg (list (cons (ssg-json-get (cdr eintrag) "id") (cdr eintrag))))) ) @@ -623,17 +645,44 @@ (princ) ) -;; Aktuell gewaehlte Farbe als Text. -(defun geruest-dlg-farbwert ( / idx) - (setq idx (atoi *geruest-dlg-farbe*)) +;; Farbliste des Dialogs aus der TEILEFARBE-Definition aufbauen: Optionen + +;; freie Option ans Listenende; deren Index merkt sich der Callback, um das +;; Freitextfeld freizuschalten. Genutzt vom GERUEST- und vom Traeger-Dialog. +(defun geruest-farb-liste-setzen (farb-opts / frei-opt) + (setq *geruest-farb-liste* nil *geruest-frei-idx* -1) + (if farb-opts + (progn + (setq *geruest-farb-liste* (ssg-json-get farb-opts "optionen")) + (if (ssg-json-get farb-opts "frei_erlaubt") + (progn + (setq frei-opt (ssg-json-get farb-opts "frei_option")) + (if (null frei-opt) (setq frei-opt "Individuell")) + (setq *geruest-frei-idx* (length *geruest-farb-liste*)) + (setq *geruest-farb-liste* + (append *geruest-farb-liste* (list frei-opt))) + ) + ) + ) + ) +) + +;; Gewaehlte Farbe als Text. idx-str = Tile-Wert der Farbliste, +;; frei = Inhalt des Freitextfelds. +(defun geruest-farbwert (idx-str frei / idx) + (setq idx (atoi idx-str)) (cond ((null *geruest-farb-liste*) "") - ((= idx *geruest-frei-idx*) *geruest-dlg-frei*) + ((= idx *geruest-frei-idx*) frei) ((nth idx *geruest-farb-liste*) (nth idx *geruest-farb-liste*)) (T "") ) ) +;; Aktuell gewaehlte Farbe des GERUEST-Dialogs als Text. +(defun geruest-dlg-farbwert ( / ) + (geruest-farbwert *geruest-dlg-farbe* *geruest-dlg-frei*) +) + ;; Konfiguration anwenden und die Tiles nachziehen. Wird direkt aus dem ;; popup_list-Rueckruf aufgerufen - set_tile aendert die Anzeige im laufenden ;; Dialog, ein Neuaufbau ist nicht noetig. Index 0 = "(keine)". @@ -919,33 +968,17 @@ ;; ("WECHSEL" bereich-index) - Nutzer hat den Bereich umgestellt ;; nil - abgebrochen (defun geruest-dialog (bg bereich-idx bereiche / dcl-pfad dat attr laenge-def - farb-opts frei-opt min-l max-l fertig rueckgabe + farb-opts min-l max-l fertig rueckgabe ergebnis wert-l oben-m unten-m name neu-idx) (setq *geruest-varianten* (ssg-json-get bg "geometrie_varianten")) (setq *geruest-anbauteile* (ssg-json-get bg "anbaugruppen")) (setq attr (ssg-json-get bg "attribute")) - (setq laenge-def (if attr (ssg-json-get attr "Laenge"))) - (setq farb-opts (if attr (ssg-json-get attr "Teilefarbe"))) + (setq laenge-def (if attr (ssg-json-get attr "LAENGE"))) + (setq farb-opts (if attr (ssg-json-get attr "TEILEFARBE"))) (setq min-l (if laenge-def (ssg-json-get laenge-def "min"))) (setq max-l (if laenge-def (ssg-json-get laenge-def "max"))) - ;; Farboptionen + freie Option ans Listenende; Index davon merkt sich der - ;; Callback, um das Freitextfeld freizuschalten. - (setq *geruest-farb-liste* nil *geruest-frei-idx* -1) - (if farb-opts - (progn - (setq *geruest-farb-liste* (ssg-json-get farb-opts "optionen")) - (if (ssg-json-get farb-opts "frei_erlaubt") - (progn - (setq frei-opt (ssg-json-get farb-opts "frei_option")) - (if (null frei-opt) (setq frei-opt "Individuell")) - (setq *geruest-frei-idx* (length *geruest-farb-liste*)) - (setq *geruest-farb-liste* - (append *geruest-farb-liste* (list frei-opt))) - ) - ) - ) - ) + (geruest-farb-liste-setzen farb-opts) (setq *geruest-konfig-liste* (geruest-konfigs bg)) ;; Frueheren Stand dieses Bereichs wiederherstellen, sonst Ausgangszustand @@ -1136,7 +1169,7 @@ ;; als reine Geometrie bei 0,0,0 mit in den Block wandern. ;; Rueckgabe: (blockname . entity) oder nil. (defun geruest-block-bauen (bg variante werte pt teile-dwgs / datei dummy lastEnt dummyEnt - e ss bname blockEnt dummy-attribs attribs) + dummy-attribs attribs) ;; Eine Variante darf eine eigene Dummy-DWG mitbringen; sonst gilt die der ;; Baugruppe. (setq datei (geruest-variante-wert variante bg "dummy")) @@ -1173,46 +1206,59 @@ ;; ssg-attrib-merge legt alle Tags aus *geruest-attrib-defs* an und ;; uebernimmt zusaetzlich alle Tags der Dummy-DWG. (setq attribs (ssg-attrib-merge dummy-attribs *geruest-attrib-defs*)) - (foreach paar werte - (if (assoc (car paar) attribs) - (setq attribs (subst paar (assoc (car paar) attribs) attribs)) - (setq attribs (append attribs (list paar))) - ) - ) + ;; nil = Drehwinkel interaktiv am Cursor + (geruest-block-abschliessen bg attribs werte lastEnt pt nil) + ) + ) +) - (ssg-attrib-make-defs (ssg-attrib-alist-to-defs attribs) 50.0) +;; Gemeinsamer Schluss aller Geruest-Bloecke: Werte ins Schema eintragen, +;; ATTDEFs erzeugen, alles Neue seit lastEnt zu GR__ zusammenfassen +;; und bei pt einfuegen. +;; attribs = Schema-Alist (Tags + Vorgabewerte), werte = berechnete Werte +;; rot = Drehwinkel in Grad (Zahl) oder nil fuer interaktive Drehung. +;; Bei einer Zahl muss der Aufrufer ANGBASE/ANGDIR/AUNITS auf 0 +;; gesetzt haben, sonst deutet INSERT den Wert anders. +;; Rueckgabe: (blockname . entity) oder nil. +(defun geruest-block-abschliessen (bg attribs werte lastEnt pt rot + / e ss bname blockEnt) + (foreach paar werte + (if (assoc (car paar) attribs) + (setq attribs (subst paar (assoc (car paar) attribs) attribs)) + (setq attribs (append attribs (list paar))) + ) + ) - ;; Alles Neue seit lastEnt einsammeln (Dummy-INSERT + ATTDEFs) - (setq ss (ssadd)) - (setq e (if lastEnt (entnext lastEnt) (entnext))) - (while e - (ssadd e ss) - (setq e (entnext e)) - ) + (ssg-attrib-make-defs (ssg-attrib-alist-to-defs attribs) 50.0) - (setq bname (geruest-blockname (ssg-json-get bg "id"))) - (command "_.-BLOCK" bname (list 0.0 0.0 0.0) ss "") + ;; Alles Neue seit lastEnt einsammeln (Geometrie + ATTDEFs) + (setq ss (ssadd)) + (setq e (if lastEnt (entnext lastEnt) (entnext))) + (while e + (ssadd e ss) + (setq e (entnext e)) + ) - ;; Stand VOR dem Einfuegen merken: bricht der Nutzer die Drehung mit ESC - ;; ab, entsteht kein neues INSERT und (entlast) zeigt auf ein voellig - ;; fremdes Objekt - ohne diesen Vergleich wuerden dessen Attribute - ;; ueberschrieben. - (setq lastEnt (entlast)) - ;; pause = Drehwinkel interaktiv am Cursor - (command "_.INSERT" bname pt 1 1 pause) - ;; Laufende Einfuegung sicher beenden (z.B. ESC waehrend der Drehung) - (if (> (getvar "CMDACTIVE") 0) (command)) - (if (> (getvar "CMDACTIVE") 0) (command)) + (setq bname (geruest-blockname (ssg-json-get bg "id"))) + (command "_.-BLOCK" bname (list 0.0 0.0 0.0) ss "") - (setq blockEnt (entlast)) - (if (and blockEnt (not (eq blockEnt lastEnt)) - (= (cdr (assoc 0 (entget blockEnt))) "INSERT")) - (progn - (ssg-attrib-set-on blockEnt attribs) - (ssg-block-layer-vorgabe blockEnt bname attribs) - (cons bname blockEnt) - ) - ) + ;; Stand VOR dem Einfuegen merken: bricht der Nutzer die Drehung mit ESC + ;; ab, entsteht kein neues INSERT und (entlast) zeigt auf ein voellig + ;; fremdes Objekt - ohne diesen Vergleich wuerden dessen Attribute + ;; ueberschrieben. + (setq lastEnt (entlast)) + (command "_.INSERT" bname pt 1 1 (if rot rot pause)) + ;; Laufende Einfuegung sicher beenden (z.B. ESC waehrend der Drehung) + (if (> (getvar "CMDACTIVE") 0) (command)) + (if (> (getvar "CMDACTIVE") 0) (command)) + + (setq blockEnt (entlast)) + (if (and blockEnt (not (eq blockEnt lastEnt)) + (= (cdr (assoc 0 (entget blockEnt))) "INSERT")) + (progn + (ssg-attrib-set-on blockEnt attribs) + (ssg-block-layer-vorgabe blockEnt bname attribs) + (cons bname blockEnt) ) ) ) @@ -1362,5 +1408,800 @@ (defun c:GERUEST_ROHRABHAENGER ( / ) (geruest-starten "Rohrabhaenger")) (defun c:GERUEST_WANDBEFESTIGUNG ( / ) (geruest-starten "Wandbefestigung")) -(princ "\nGeruestInsert.lsp geladen. Befehle: GERUEST, GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG") + +;; ============================================================ +;; ROHR-GERUEST-TRAEGER (Baugruppe mit "einfuegeart": "linie") +;; ============================================================ +;; Eigener Dialog (dcl/geruest_traeger.dcl): Variante, Farbe und zwei +;; Laengenabzuege. Die Laenge selbst wird DANACH in der Zeichnung bestimmt - +;; Startpunkt, dann Endpunkt oder getippte Laenge (+ Richtung), wie beim +;; Kreisel. Aktive Abzuege ruecken die Linie beidseitig ein: Strecke 1000, +;; Abzug Anfang 20, Ende 35 -> Linie beginnt 20 mm hinter dem Startklick und +;; ist 945 mm lang. +;; +;; Keine Dummy-DWG: die Geometrie ist eine einzige LINE, die je Block eine +;; andere Laenge hat. Sie entsteht per entmake von (0,0,0) nach (L,0,0) auf +;; dem Layer der Variante; der Block wird am eingerueckten Startpunkt mit dem +;; Richtungswinkel eingefuegt. Es wird wiederholt eingefuegt, bis der Nutzer +;; ESC/Enter drueckt - jeder Traeger ist ein eigener GR_Traeger_-Block. + +;; Baugruppe ueber das ASCII-Feld "id" (auch solche, die +;; geruest-baugruppen-liste auslaesst). +(defun geruest-baugruppe (id / erg) + (setq erg nil) + (foreach eintrag (geruest-daten) + (if (and (null erg) (listp (cdr eintrag)) + (equal (ssg-json-get (cdr eintrag) "id") id)) + (setq erg (cdr eintrag)) + ) + ) + erg +) + +;; Feld einer Attribut-Definition (attribute -> TAG -> feld). Eine Variante +;; darf einen eigenen "attribute"-Block mitbringen, der vor dem der Baugruppe +;; gilt (z.B. ein anderer Laengenabzug bei einer Muffen-Variante). assoc +;; statt ssg-json-get, damit ein in der Variante gesetztes false (= nil) den +;; Wert der Baugruppe ueberschreibt, statt als "fehlt" durchzufallen. +(defun geruest-attr-feld (variante bg tag feld) + (geruest-obj-feld variante bg (list "attribute" tag) feld) +) + +;; Objekt unter einem Schluesselpfad, z.B. ("attribute" "LAENGE"); nil, wenn +;; ein Schluessel fehlt. +(defun geruest-json-pfad-get (obj pfad) + (foreach k pfad (setq obj (if (and obj (listp obj)) (ssg-json-get obj k)))) + obj +) + +;; Allgemeine Form von geruest-attr-feld: Feld unter pfad, Variante vor +;; Baugruppe, je FELD aufgeloest (eine Variante nennt nur, was abweicht). +;; Genutzt fuer "attribute" und "beschriftung". +(defun geruest-obj-feld (variante bg pfad feld / def paar) + (setq def (if variante (geruest-json-pfad-get variante pfad))) + (setq paar (if (and def (listp def)) (assoc feld def))) + (if paar + (cdr paar) + (ssg-json-get (geruest-json-pfad-get bg pfad) feld) + ) +) + +;; Millimeter-Eingabe als Zahl >= 0 (Komma wie Punkt), sonst nil. +;; Leere Eingabe -> nil. +(defun geruest-mm-zahl (s / w) + (setq s (vl-string-translate "," "." (ssg-cfg-trim (if s s "")))) + (if (and (/= s "") (setq w (distof s 2)) (>= w 0.0)) w) +) + +;; Abzug-Feld: leer -> 0, gueltige Zahl -> Zahl, sonst nil. +(defun geruest-abzug-wert (s) + (if (= (ssg-cfg-trim (if s s "")) "") + 0.0 + (geruest-mm-zahl s) + ) +) + +;; Millimeterwert fuer Attribute/Meldungen: ganze Zahl ohne Nachkommastelle, +;; sonst eine Stelle. +(defun geruest-mm-string (w / r) + (setq r (fix (+ w 0.5))) + (if (equal w r 1e-6) (itoa r) (rtos w 2 1)) +) + +;; Netto-Laenge der Linie: Strecke minus beide Abzuege, nil wenn <= 0. +(defun geruest-traeger-laenge (strecke abzug-a abzug-e / netto) + (setq netto (- strecke (if abzug-a abzug-a 0.0) (if abzug-e abzug-e 0.0))) + (if (> netto 1e-6) netto) +) + +;; Eingerueckter Startpunkt: abzug-a entlang winkel ab p1, Z von p1. +(defun geruest-traeger-start (p1 winkel abzug-a / p) + (setq p (polar p1 winkel (if abzug-a abzug-a 0.0))) + (list (car p) (cadr p) (if (caddr p1) (caddr p1) 0.0)) +) + +;; Positionen der Querstreben entlang der Traegerlinie (Abstand ab Linienanfang). +;; Regeln: Abstand zwischen zwei Streben hoechstens abstand-max, beide +;; Endabstaende gleich und in [rand-min, rand-max], so wenige Streben wie +;; moeglich. +;; netto <= 2*rand-max -> eine Strebe in der Mitte +;; sonst -> k = aufgerundet (netto - 2*rand-max) / abstand-max +;; Felder (= wenigste Streben). Rand +;; r = max(rand-min, (netto - k*abstand-max) / 2): +;; der Abstand ist damit GENAU abstand-max, solange der +;; Rand >= rand-min bleibt; nur sonst bleibt der Rand +;; bei rand-min und der Abstand wird etwas kleiner. +;; Mit genau abstand-max geht nicht jede Laenge auf (1100 mm: 2 Streben -> +;; Rand 300, 3 Streben -> Rand 50) - dort ergibt sich 100 | 450 | 450 | 100. +;; r <= rand-max ist durch die Wahl von k garantiert. +;; Kuerzer als 2*rand-min -> keine Strebe (der Mindestrand waere verletzt). +(defun geruest-traeger-streben (netto abstand-max rand-min rand-max / k r s i erg) + (cond + ((or (null netto) (< netto (- (* 2.0 rand-min) 1e-6))) nil) + ((<= netto (+ (* 2.0 rand-max) 1e-6)) (list (/ netto 2.0))) + (T + (setq k (/ (- netto (* 2.0 rand-max)) abstand-max)) + ;; aufrunden, Rundungsrauschen (z.B. 2.0000000001) nicht mitzaehlen + (setq k (if (equal k (fix k) 1e-6) (fix k) (1+ (fix k)))) + (setq r (max rand-min (/ (- netto (* k abstand-max)) 2.0))) + (setq s (/ (- netto (* 2.0 r)) k)) + (setq erg nil i k) + (while (>= i 0) + (setq erg (cons (+ r (* i s)) erg)) + (setq i (1- i)) + ) + erg + ) + ) +) + +;; Querstreben-Konfiguration (Variante vor Baugruppe) als +;; (dummy laenge querlinie abstand-max rand-min rand-max) oder nil, wenn keine +;; "querstrebe" definiert ist. +;; dummy = DWG unter data/geruest (Basispunkt Strebenmitte, 30 mm laengs +;; X) oder nil +;; laenge/querlinie = nur fuer den Rueckfall ohne Dummy-DWG: zwei Querlinien +;; im Abstand laenge, je querlinie lang +;; Fehlende Zahlenwerte -> Standard 30/25/500/100/250. +(defun geruest-traeger-strebe-cfg (variante bg / q w d) + (setq q (geruest-variante-wert variante bg "querstrebe")) + (if (and q (listp q)) + (progn + (setq d (ssg-json-get q "dummy")) + (cons (if (and d (= (type d) 'STR) (/= d "")) d) + (mapcar '(lambda (feld std) + (setq w (ssg-json-get q feld)) + (if (numberp w) (float w) std)) + '("laenge" "querlinie" "abstand_max" "rand_min" "rand_max") + '(30.0 25.0 500.0 100.0 250.0))) + ) + ) +) + +;; Muffen-Dummy einer Variante: nur bei "mit_muffe": true die "dummy"-Datei +;; aus "muffe" (Variante vor Baugruppe), sonst nil. Das Flag steht bewusst +;; ausdruecklich je Variante, statt aus dem Namen ("mit Muffe") geraten zu +;; werden. Bei "mit 2 Muffen" wird trotzdem nur eine Muffe gezeichnet. +(defun geruest-traeger-muffe-dummy (variante bg / m d) + (if (and variante (ssg-json-get variante "mit_muffe")) + (progn + (setq m (geruest-variante-wert variante bg "muffe")) + (setq d (if (and m (listp m)) (ssg-json-get m "dummy"))) + (if (and d (= (type d) 'STR) (/= d "")) d) + ) + ) +) + +;; Liegt netto in [min-l, max-l]? Fehlende Grenzen gelten nicht. +(defun geruest-traeger-pruefen (netto min-l max-l) + (and netto + (or (null min-l) (>= netto min-l)) + (or (null max-l) (<= netto max-l))) +) + +;; BEZEICHNUNG: Teileart + Variante + aktive Abzuege, mit " + " verkettet +;; (Artikelnamen enthalten Kommas, siehe geruest-einfuegen). +(defun geruest-traeger-bezeichnung (teileart variante-name abzug-a abzug-e / teile) + (setq teile (list teileart variante-name)) + (if (> abzug-a 0.0) + (setq teile (append teile (list (ssg-textf "gr-tr-bez-abzug-anfang" + (list (geruest-mm-string abzug-a))))))) + (if (> abzug-e 0.0) + (setq teile (append teile (list (ssg-textf "gr-tr-bez-abzug-ende" + (list (geruest-mm-string abzug-e))))))) + (ssg-join teile " + ") +) + +(defun geruest-traeger-dcl-pfad ( / basis) + (setq basis (cond ((getenv "DXFM_DCL")) + ((getenv "DXFMAKRO") (strcat (getenv "DXFMAKRO") "/dcl")))) + (if basis + (strcat (vl-string-translate "\\" "/" basis) "/geruest_traeger.dcl") + ) +) + +;; --- Dialogzustand (Globals, siehe Abschnitt DIALOGZUSTAND oben) --- +;; Bleibt zwischen zwei GERUEST_TRAEGER-Aufrufen erhalten. + +;; Abzug-Vorgaben (aktiv + Wert) der Variante idx in den Zustand laden. +(defun geruest-tr-vorgaben-laden (idx / v) + (setq v (nth idx (ssg-json-get *geruest-tr-bg* "geometrie_varianten"))) + (setq *geruest-tr-abzug-a* + (if (geruest-attr-feld v *geruest-tr-bg* "LAENGENABZUGANFANG" "aktiv") "1" "0")) + (setq *geruest-tr-abzug-a-w* + (geruest-zahl-string (geruest-attr-feld v *geruest-tr-bg* "LAENGENABZUGANFANG" "vorgabe"))) + (setq *geruest-tr-abzug-e* + (if (geruest-attr-feld v *geruest-tr-bg* "LAENGENABZUGENDE" "aktiv") "1" "0")) + (setq *geruest-tr-abzug-e-w* + (geruest-zahl-string (geruest-attr-feld v *geruest-tr-bg* "LAENGENABZUGENDE" "vorgabe"))) +) + +(defun geruest-tr-abzug-schreiben ( / ) + (set_tile "abzug_a" *geruest-tr-abzug-a*) + (set_tile "abzug_a_w" *geruest-tr-abzug-a-w*) + (set_tile "abzug_e" *geruest-tr-abzug-e*) + (set_tile "abzug_e_w" *geruest-tr-abzug-e-w*) + (mode_tile "abzug_a_w" (if (= *geruest-tr-abzug-a* "1") 0 1)) + (mode_tile "abzug_e_w" (if (= *geruest-tr-abzug-e* "1") 0 1)) +) + +;; Variantenwechsel im Dialog: Abzug-Vorgaben der neuen Variante uebernehmen. +(defun geruest-tr-variante-gewaehlt (wert / ) + (setq *geruest-tr-variante* wert) + (geruest-tr-vorgaben-laden (atoi wert)) + (geruest-tr-abzug-schreiben) +) + +(defun geruest-tr-dlg-lesen ( / ) + (setq *geruest-tr-variante* (get_tile "variante")) + (setq *geruest-tr-farbe* (get_tile "farbe")) + (setq *geruest-tr-frei* (get_tile "farbe_frei")) + (setq *geruest-tr-abzug-a* (get_tile "abzug_a")) + (setq *geruest-tr-abzug-a-w* (get_tile "abzug_a_w")) + (setq *geruest-tr-abzug-e* (get_tile "abzug_e")) + (setq *geruest-tr-abzug-e-w* (get_tile "abzug_e_w")) + (setq *geruest-tr-beschriftung* (get_tile "beschriftung")) +) + +;; Wert eines Abzugs aus dem Zustand: inaktiv -> 0, aktiv -> Zahl oder nil. +(defun geruest-tr-abzug (aktiv wert) + (if (= aktiv "1") (geruest-abzug-wert wert) 0.0) +) + +;; Traeger-Dialog. Rueckgabe: +;; (variante-index farbe abzug-anfang abzug-ende beschriften-p) oder nil bei +;; Abbruch. +(defun geruest-traeger-dialog (bg / varianten dcl-pfad dat fertig rueckgabe + ergebnis aw ew) + (setq varianten (ssg-json-get bg "geometrie_varianten")) + (setq *geruest-tr-bg* bg) + (geruest-farb-liste-setzen + (ssg-json-get (ssg-json-get bg "attribute") "TEILEFARBE")) + ;; Ausgangszustand beim ersten Aufruf bzw. wenn der gemerkte Index nach + ;; einer JSON-Aenderung nicht mehr passt. + (if (or (null *geruest-tr-variante*) + (>= (atoi *geruest-tr-variante*) (length varianten))) + (progn + (setq *geruest-tr-variante* "0" *geruest-tr-farbe* "0" *geruest-tr-frei* "") + (geruest-tr-vorgaben-laden 0) + ) + ) + ;; Beschriftung standardmaessig an; der Haken bleibt zwischen Aufrufen + (if (null *geruest-tr-beschriftung*) (setq *geruest-tr-beschriftung* "1")) + (setq dcl-pfad (geruest-traeger-dcl-pfad)) + (setq fertig nil rueckgabe nil) + + ;; Schleife: ungueltige Eingaben zeigen den Dialog mit dem bisherigen + ;; Stand erneut - DCL kann Zahlen nicht selbst pruefen. + (while (not fertig) + (setq dat (if (and dcl-pfad (findfile dcl-pfad)) (load_dialog dcl-pfad) -1)) + (if (or (< dat 0) (not (new_dialog "geruest_traeger" dat))) + (progn + (alert (ssg-textf "gr-tr-fehler-dcl" + (list (if dcl-pfad dcl-pfad "geruest_traeger.dcl")))) + (setq fertig T) + ) + (progn + (start_list "variante") + (foreach v varianten (add_list (geruest-eintrag-name v))) + (end_list) + (set_tile "variante" *geruest-tr-variante*) + + (if *geruest-farb-liste* + (progn + (start_list "farbe") + (foreach f *geruest-farb-liste* (add_list f)) + (end_list) + (set_tile "farbe" *geruest-tr-farbe*) + (mode_tile "farbe_frei" + (if (= (atoi *geruest-tr-farbe*) *geruest-frei-idx*) 0 1)) + (action_tile "farbe" + "(mode_tile \"farbe_frei\" (if (= (atoi $value) *geruest-frei-idx*) 0 1))") + ) + (progn + (mode_tile "farbe" 1) + (mode_tile "farbe_frei" 1) + ) + ) + (set_tile "farbe_frei" *geruest-tr-frei*) + (geruest-tr-abzug-schreiben) + (set_tile "beschriftung" *geruest-tr-beschriftung*) + (set_tile "hinweis" (ssg-text "gr-tr-hinweis")) + + (action_tile "variante" "(geruest-tr-variante-gewaehlt $value)") + (action_tile "abzug_a" + "(mode_tile \"abzug_a_w\" (if (= $value \"1\") 0 1))") + (action_tile "abzug_e" + "(mode_tile \"abzug_e_w\" (if (= $value \"1\") 0 1))") + (action_tile "accept" "(geruest-tr-dlg-lesen) (done_dialog 1)") + (action_tile "cancel" "(done_dialog 0)") + (setq ergebnis (start_dialog)) + (unload_dialog dat) + + (cond + ((= ergebnis 0) (setq fertig T)) + ((or (null (setq aw (geruest-tr-abzug *geruest-tr-abzug-a* *geruest-tr-abzug-a-w*))) + (null (setq ew (geruest-tr-abzug *geruest-tr-abzug-e* *geruest-tr-abzug-e-w*)))) + (alert (ssg-text "gr-tr-alert-abzug")) + ) + (T + (setq rueckgabe + (list (atoi *geruest-tr-variante*) + (geruest-farbwert *geruest-tr-farbe* *geruest-tr-frei*) + aw ew + (= *geruest-tr-beschriftung* "1"))) + (setq fertig T) + ) + ) + ) + ) + ) + rueckgabe +) + +;; X-Positionen der beiden Querlinien einer Strebe: Anfang und Ende des +;; Flacheisens, laenge mittig um die Strebenposition x. +(defun geruest-traeger-strebe-enden (x laenge) + (list (- x (/ laenge 2.0)) (+ x (/ laenge 2.0))) +) + +;; Querstrebe darstellen: an Anfang und Ende je eine Linie quer zum Traeger +;; (Laenge querlinie, mittig auf der Traegerlinie y = 0). +(defun geruest-traeger-strebe-zeichnen (x laenge querlinie lay / hq) + (setq hq (/ querlinie 2.0)) + (foreach xe (geruest-traeger-strebe-enden x laenge) + (entmake (list '(0 . "LINE") (cons 8 lay) + (list 10 xe (- hq) 0.0) (list 11 xe hq 0.0))) + ) +) + +;; Vollstaendiger Pfad einer Dummy-DWG unter data/geruest oder nil (mit +;; Meldung), wenn sie fehlt. datei = nil -> stilles nil (nichts konfiguriert). +(defun geruest-dummy-finden (datei / pfad) + (if datei + (progn + (setq pfad (geruest-dummy-pfad datei)) + (if (and pfad (findfile pfad)) + pfad + (progn + (princ (ssg-textf "gr-fehler-dummy" (list (if pfad pfad datei)))) + nil + ) + ) + ) + ) +) + +;; Dummy-DWG als verschachtelten Block bei pt (Drehung 0) einfuegen. Ist die +;; Blockdefinition (Dateiname ohne .dwg) schon in der Zeichnung, wird per +;; Blockname eingefuegt - sonst wuerde die DWG bei jeder Strebe neu gelesen +;; (und ggf. "Block neu definieren?" gefragt). ATTREQ/ATTDIA muss der Aufrufer +;; auf 0 gesetzt haben. +(defun geruest-dummy-einfuegen (pfad pt / bname) + (setq bname (vl-filename-base pfad)) + (command "_.INSERT" (if (tblsearch "BLOCK" bname) bname pfad) pt 1 1 0) +) + +;; Linie + Querstreben + Muffe + ATTDEFs zu einem Block zusammenfassen und am +;; Startpunkt mit dem Richtungswinkel einfuegen. Im Block laeuft der Traeger +;; entlang +X, die Dummys werden darum ohne Drehung eingefuegt. +;; strebe = Ergebnis von geruest-traeger-strebe-cfg (nil = keine Streben) +;; strebe-pfad = Pfad der Strebe-DWG oder nil -> Rueckfall auf Querlinien +;; muffe-pfad = Pfad der Muffen-DWG oder nil -> keine Muffe; sonst eine +;; Muffe (Basispunkt Muffenmitte) am Linienende +;; Der Aufrufer sichert die Systemvariablen per ssg-start. +;; Rueckgabe: (blockname . entity) oder nil. +(defun geruest-traeger-block-bauen (bg layer netto strebe strebe-pfad muffe-pfad + werte pt winkel / lastEnt lay) + (setvar "ATTREQ" 0) + (setvar "ATTDIA" 0) + (setvar "OSMODE" 0) + ;; Drehwinkel wird als Grad an INSERT uebergeben - nur eindeutig mit + ;; Winkel-Nullrichtung Ost, gegen den Uhrzeigersinn, Einheit Grad. + (setvar "ANGBASE" 0.0) + (setvar "ANGDIR" 0) + (setvar "AUNITS" 0) + ;; Nicht (entlast) - siehe geruest-block-bauen. + (setq lastEnt (ssg-lastent-ohne-attribute)) + + (setq lay (if (and layer (/= layer "")) layer "0")) + ;; Aktiv setzen, damit auch die verschachtelten Dummy-INSERTs auf dem + ;; Traeger-Layer landen (CLAYER sichert ssg-start immer mit). + (ssg-make-layer lay (ssg-layer-farbe-fuer-name lay) T) + (entmake (list '(0 . "LINE") (cons 8 lay) + '(10 0.0 0.0 0.0) (list 11 netto 0.0 0.0))) + ;; strebe = (dummy laenge querlinie abstand-max rand-min rand-max) + (if strebe + (foreach x (geruest-traeger-streben netto (nth 3 strebe) (nth 4 strebe) (nth 5 strebe)) + (if strebe-pfad + (geruest-dummy-einfuegen strebe-pfad (list x 0.0 0.0)) + (geruest-traeger-strebe-zeichnen x (nth 1 strebe) (nth 2 strebe) lay) + ) + ) + ) + (if muffe-pfad + (geruest-dummy-einfuegen muffe-pfad (list netto 0.0 0.0)) + ) + + (geruest-block-abschliessen bg + (ssg-attrib-merge nil *geruest-traeger-attrib-defs*) + werte lastEnt pt (* winkel (/ 180.0 pi))) +) + +;; Einfuege-Schleife: Startpunkt, Endpunkt oder Laenge, bis ESC/Enter. +;; wahl = Rueckgabe von geruest-traeger-dialog. +(defun geruest-traeger-einfuegen (bg wahl / variante teileart layer paare farbe + abzug-a abzug-e min-l max-l bez werte-basis + werte weiter p1 eingabe strecke winkel netto + ergebnis anzahl strebe strebe-pfad muffe-pfad + beschriften) + (setq variante (nth (car wahl) (ssg-json-get bg "geometrie_varianten"))) + (setq farbe (cadr wahl) + abzug-a (caddr wahl) + abzug-e (cadddr wahl) + beschriften (nth 4 wahl)) + (setq *geruest-beschr-gemeldet* nil) + (setq teileart (geruest-variante-wert variante bg "teileart")) + (setq layer (geruest-variante-wert variante bg "layer")) + (setq min-l (geruest-attr-feld variante bg "LAENGE" "min")) + (setq max-l (geruest-attr-feld variante bg "LAENGE" "max")) + (setq paare (geruest-teile-paare variante nil)) + (setq strebe (geruest-traeger-strebe-cfg variante bg)) + ;; DWGs einmal je Durchgang aufloesen - eine fehlende Datei wird so nur + ;; einmal gemeldet, nicht bei jedem Traeger. Fehlt die Strebe-DWG, werden + ;; stattdessen Querlinien gezeichnet; fehlt die Muffe, entfaellt sie. + (setq strebe-pfad (if strebe (geruest-dummy-finden (car strebe)))) + (setq muffe-pfad (geruest-dummy-finden (geruest-traeger-muffe-dummy variante bg))) + (setq bez (geruest-traeger-bezeichnung teileart + (geruest-eintrag-name variante) abzug-a abzug-e)) + + ;; Fuer alle Traeger dieses Durchgangs gleich - nur LAENGE aendert sich. + (setq werte-basis + (list (cons "ARTINR" (ssg-join (mapcar 'car paare) ",")) + (cons "BEZEICHNUNG" bez) + (cons "TEILEART" teileart) + (cons "LAENGENABZUGANFANG" (geruest-mm-string abzug-a)) + (cons "LAENGENABZUGENDE" (geruest-mm-string abzug-e)) + ;; Block selbstbeschreibend - die Beschriftung (auch spaeter per + ;; GERUEST_TRAEGER_BESCHRIFTEN) findet darueber ihre Formatierung + (cons "VARIANTE" (geruest-eintrag-name variante)))) + (if (and layer (/= layer "")) + (setq werte-basis (append werte-basis (list (cons "LAYER" layer))))) + (if (/= farbe "") + (setq werte-basis (append werte-basis (list (cons "TEILEFARBE" + (ssg-join (geruest-farbliste paare farbe) ",")))))) + + (setq weiter T anzahl 0) + (while weiter + (setq strecke nil) + (setq p1 (getpoint (ssg-text "gr-tr-prompt-start"))) + (if (null p1) + (setq weiter nil) + (progn + ;; 128 = beliebige Eingabe: ein Punkt liefert Laenge UND Richtung, + ;; eine getippte Zahl nur die Laenge (Richtung wird nachgefragt). + (initget 128) + (setq eingabe (getpoint p1 (ssg-text "gr-tr-prompt-ende"))) + ;; Reihenfolge wichtig: nil ist auch listp, und "" darf erst nach dem + ;; Punkt-Fall verglichen werden. + (cond + ((null eingabe) (setq weiter nil)) + ((listp eingabe) + ;; Laenge in der XY-Ebene, die Linie liegt auf Z des Startpunkts + (setq strecke (distance (list (car p1) (cadr p1)) + (list (car eingabe) (cadr eingabe)))) + (setq winkel (angle p1 eingabe)) + ) + ((= eingabe "") (setq weiter nil)) + ((setq strecke (geruest-mm-zahl eingabe)) + (setq winkel (getangle p1 (ssg-text "gr-tr-prompt-richtung"))) + (if (null winkel) (setq winkel 0.0)) + ) + (T (princ (ssg-textf "gr-tr-eingabe-ungueltig" (list eingabe)))) + ) + ) + ) + + (if (and weiter strecke) + (progn + (setq netto (geruest-traeger-laenge strecke abzug-a abzug-e)) + (cond + ((null netto) + (princ (ssg-textf "gr-tr-laenge-null" + (list (geruest-mm-string strecke) + (geruest-mm-string (+ abzug-a abzug-e)))))) + ((not (geruest-traeger-pruefen netto min-l max-l)) + (princ (ssg-textf "gr-tr-laenge-bereich" + (list (geruest-mm-string netto) + (if min-l (geruest-mm-string min-l) "0") + (if max-l (geruest-mm-string max-l) "-"))))) + (T + (setq werte (cons (cons "LAENGE" (geruest-mm-string netto)) werte-basis)) + (ssg-start nil '(("OSMODE") ("ATTREQ") ("ATTDIA") + ("ANGBASE") ("ANGDIR") ("AUNITS"))) + (setq ergebnis (geruest-traeger-block-bauen bg layer netto strebe + strebe-pfad muffe-pfad werte + (geruest-traeger-start p1 winkel abzug-a) winkel)) + ;; Beschriftung aus dem fertigen Block ableiten (dieselbe Funktion + ;; wie GERUEST_TRAEGER_BESCHRIFTEN) + (if (and ergebnis beschriften) + (geruest-traeger-beschriften (cdr ergebnis))) + (ssg-end) + (if ergebnis + (progn + (setq anzahl (1+ anzahl)) + (princ (ssg-textf "gr-tr-fertig" + (list (geruest-mm-string netto) (car ergebnis)))) + ) + ) + ) + ) + ) + ) + ) + (princ (ssg-textf "gr-tr-ende" (list (itoa anzahl)))) + (princ) +) + +;; ============================================================ +;; TRAEGER-BESCHRIFTUNG +;; ============================================================ +;; Eigenes TEXT-Objekt neben dem Block, z.B. "RT 80/80 L=2650". Es wird +;; AUSSCHLIESSLICH aus dem fertigen Block abgeleitet (Einfuegepunkt, Drehung, +;; Attribute LAENGE und VARIANTE) - darum nutzen das Einfuegen und +;; GERUEST_TRAEGER_BESCHRIFTEN dieselbe Funktion, und ein von Hand +;; verschobener/gedrehter Traeger wird beim Neubeschriften korrekt erfasst. +;; Der Text traegt per XDATA (*geruest-beschr-app*, 1005) den Handle seines +;; Blocks; so wird er beim Neubeschriften ersetzt statt verdoppelt. +;; +;; Formatierung aus geruest.json, "beschriftung" (Variante vor Baugruppe, je +;; Feld): NUR stil, ausrichtung, hoehe - alles andere regelt der Textstil +;; ausserhalb (es wird kein Stil angelegt). Dazu Inhalt (format/text) und +;; Layer. + +;; Winkel auf [0, 2pi) normieren. +(defun geruest-winkel-norm (w) + (setq w (rem w (* 2.0 pi))) + (if (< w 0.0) (+ w (* 2.0 pi)) w) +) + +;; Textwinkel entlang des Traegers nach DIN-Konvention (lesbar von unten und +;; von rechts): fuer 90 < w <= 270 Grad um 180 Grad gedreht, sonst w. +(defun geruest-text-winkel (w / e) + (setq w (geruest-winkel-norm w) e 1e-9) + (if (and (> w (+ (/ pi 2.0) e)) (<= w (+ (* 1.5 pi) e))) + (geruest-winkel-norm (+ w pi)) + w + ) +) + +;; Ausrichtungs-Code wie bei TEXT "Ausrichten" (T/M/B + L/C/R, z.B. "BC") -> +;; (dxf72 dxf73), nil bei unbekanntem Code. +(defun geruest-ausrichtung-codes (code / h v) + (if (and code (= (type code) 'STR) (= (strlen code) 2)) + (progn + (setq code (strcase code)) + (setq v (cdr (assoc (substr code 1 1) '(("T" . 3) ("M" . 2) ("B" . 1))))) + (setq h (cdr (assoc (substr code 2 1) '(("L" . 0) ("C" . 1) ("R" . 2))))) + (if (and v h) (list h v)) + ) + ) +) + +;; Lage des Textes: (punkt textwinkel dxf72 dxf73). p0 = Traeger-Startpunkt, +;; w = Traegerwinkel, laenge = Traegerlaenge. Der Bezugspunkt liegt auf der +;; Linie: L = in Leserichtung linkes Ende, C = Mitte, R = rechtes Ende. Nach +;; einer 180-Grad-Drehung ist "links" also das Linienende. Unbekannter Code +;; -> BC (die Meldung gibt der Aufrufer aus). +(defun geruest-traeger-text-lage (p0 w laenge code / codes tw p1 links rechts pt) + (setq codes (geruest-ausrichtung-codes code)) + (if (null codes) (setq codes '(1 1))) + (setq tw (geruest-text-winkel w)) + (setq p1 (polar p0 w laenge)) + ;; Projektion auf die Leserichtung entscheidet, welches Ende links liegt + (if (<= (+ (* (car p0) (cos tw)) (* (cadr p0) (sin tw))) + (+ (* (car p1) (cos tw)) (* (cadr p1) (sin tw)))) + (setq links p0 rechts p1) + (setq links p1 rechts p0) + ) + (setq pt (cond ((= (car codes) 0) links) + ((= (car codes) 2) rechts) + (T (polar p0 w (/ laenge 2.0))))) + (list pt tw (car codes) (cadr codes)) +) + +;; Alle Vorkommen von alt in s durch neu ersetzen. +(defun geruest-string-ersetzen (s alt neu / pos) + (setq pos (vl-string-search alt s)) + (while pos + (setq s (strcat (substr s 1 pos) neu (substr s (+ pos (strlen alt) 1)))) + (setq pos (vl-string-search alt s (+ pos (strlen neu)))) + ) + s +) + +;; Beschriftungstext: %1 = Text der Variante, %2 = Laenge auf ganze mm. +(defun geruest-traeger-text-string (fmt txt laenge) + (geruest-string-ersetzen + (geruest-string-ersetzen fmt "%1" txt) + "%2" (itoa (fix (+ laenge 0.5)))) +) + +;; Beschriftungs-Konfiguration als Alist (format text stil ausrichtung hoehe +;; layer), je Feld Variante vor Baugruppe vor Code-Standard. Fehlt "text", +;; gilt der Variantenname bzw. ersatz-text (Block ohne bekannte Variante). +;; stil/layer = nil -> aktueller Textstil/Layer. +(defun geruest-traeger-beschr-cfg (variante bg ersatz-text / txt h) + (setq txt (geruest-beschr-feld variante bg "text")) + (if (not (and txt (= (type txt) 'STR) (/= txt ""))) + (setq txt (if variante (geruest-eintrag-name variante) ersatz-text))) + (setq h (geruest-beschr-feld variante bg "hoehe")) + (list (cons "format" (cond ((geruest-beschr-feld variante bg "format")) ("%1 L=%2"))) + (cons "text" (if txt txt "")) + (cons "stil" (geruest-beschr-feld variante bg "stil")) + (cons "ausrichtung" (cond ((geruest-beschr-feld variante bg "ausrichtung")) ("BC"))) + (cons "hoehe" (if (numberp h) (float h) 50.0)) + (cons "layer" (geruest-beschr-feld variante bg "layer"))) +) + +(defun geruest-beschr-feld (variante bg feld) + (geruest-obj-feld variante bg '("beschriftung") feld) +) + +;; Handle des Traeger-Blocks aus der XDATA einer Beschriftung (oder nil). +(defun geruest-beschr-handle (ent / xd) + (setq xd (cadr (assoc -3 (entget ent (list *geruest-beschr-app*))))) + (if xd (cdr (assoc 1005 (cdr xd)))) +) + +;; Alle Beschriftungen der Zeichnung (Auswahlsatz oder nil). +(defun geruest-beschr-alle ( / ) + (ssget "_X" (list '(0 . "TEXT") (list -3 (list *geruest-beschr-app*)))) +) + +;; Beschriftung(en) zu einem Block-Handle loeschen. +(defun geruest-beschr-entfernen (handle / ss i e) + (if (and handle (setq ss (geruest-beschr-alle))) + (progn + (setq i 0) + (repeat (sslength ss) + (setq e (ssname ss i)) + (if (equal (geruest-beschr-handle e) handle) (entdel e)) + (setq i (1+ i)) + ) + ) + ) +) + +;; Textstil pruefen: vorhanden -> Name, sonst einmal je Lauf melden und den +;; aktuellen TEXTSTYLE nehmen. *geruest-beschr-gemeldet* setzt der Aufrufer +;; je Lauf zurueck. +(defun geruest-beschr-stil (stil / ) + (cond + ((and stil (/= stil "") (tblsearch "STYLE" stil)) stil) + (T + (if (and stil (/= stil "") (not (member stil *geruest-beschr-gemeldet*))) + (progn + (princ (ssg-textf "gr-tr-beschr-stil-fehlt" (list stil (getvar "TEXTSTYLE")))) + (setq *geruest-beschr-gemeldet* (cons stil *geruest-beschr-gemeldet*)) + ) + ) + (getvar "TEXTSTYLE") + ) + ) +) + +;; Einen Traeger-Block beschriften (eine evtl. vorhandene Beschriftung wird +;; ersetzt). Rueckgabe: "ok", "ersatz" (Block ohne bekannte VARIANTE, mit den +;; Vorgaben der Baugruppe beschriftet) oder nil (nicht beschriftbar). +(defun geruest-traeger-beschriften (blockEnt / ed attribs bg vname idx variante + cfg laenge lage lay handle code erg) + (setq ed (entget blockEnt)) + (setq attribs (ssg-attrib-read blockEnt)) + (setq bg (geruest-baugruppe "Traeger")) + (setq laenge (atof (cond ((cdr (assoc "LAENGE" attribs))) ("0")))) + (if (and bg (> laenge 0.0)) + (progn + (setq vname (cdr (assoc "VARIANTE" attribs))) + (setq idx (if (and vname (/= vname "")) + (geruest-name-index vname (ssg-json-get bg "geometrie_varianten")))) + (setq variante (if idx (nth idx (ssg-json-get bg "geometrie_varianten")))) + (setq cfg (geruest-traeger-beschr-cfg variante bg + (cond ((cdr (assoc "TEILEART" attribs))) ("")))) + (setq code (cdr (assoc "ausrichtung" cfg))) + (if (and (null (geruest-ausrichtung-codes code)) + (not (member code *geruest-beschr-gemeldet*))) + (progn + (princ (ssg-textf "gr-tr-beschr-ausrichtung" (list code))) + (setq *geruest-beschr-gemeldet* (cons code *geruest-beschr-gemeldet*)) + ) + ) + (setq lage (geruest-traeger-text-lage (cdr (assoc 10 ed)) (cdr (assoc 50 ed)) + laenge code)) + (setq lay (cdr (assoc "layer" cfg))) + (if (and lay (/= lay "")) + (ssg-make-layer lay (ssg-layer-farbe-fuer-name lay) nil) + (setq lay (getvar "CLAYER")) + ) + (setq handle (cdr (assoc 5 ed))) + (geruest-beschr-entfernen handle) + (if (not (tblsearch "APPID" *geruest-beschr-app*)) (regapp *geruest-beschr-app*)) + ;; 73 ist immer >= 1, damit gilt Gruppe 11 als Ausrichtungspunkt + (if (entmake (list '(0 . "TEXT") + (cons 8 lay) + (cons 7 (geruest-beschr-stil (cdr (assoc "stil" cfg)))) + (cons 10 (nth 0 lage)) + (cons 11 (nth 0 lage)) + (cons 40 (cdr (assoc "hoehe" cfg))) + (cons 1 (geruest-traeger-text-string + (cdr (assoc "format" cfg)) + (cdr (assoc "text" cfg)) laenge)) + (cons 50 (nth 1 lage)) + (cons 72 (nth 2 lage)) + (cons 73 (nth 3 lage)) + (list -3 (list *geruest-beschr-app* (cons 1005 handle))))) + (setq erg (if variante "ok" "ersatz")) + ) + ) + ) + erg +) + +;; Alle Traeger der Zeichnung (neu) beschriften und Beschriftungen, deren +;; Block nicht mehr existiert, entfernen - unabhaengig von der Checkbox im +;; Einfuegedialog. +(defun c:GERUEST_TRAEGER_BESCHRIFTEN ( / ss i n-ok n-ersatz n-fehl n-weg e h ziel erg) + (setq *geruest-beschr-gemeldet* nil) + (setq n-ok 0 n-ersatz 0 n-fehl 0 n-weg 0) + (ssg-start nil nil) + ;; Verwaiste Beschriftungen zuerst entfernen + (if (setq ss (geruest-beschr-alle)) + (progn + (setq i 0) + (repeat (sslength ss) + (setq e (ssname ss i)) + (setq h (geruest-beschr-handle e)) + (setq ziel (if h (handent h))) + (if (not (and ziel (entget ziel) + (= (cdr (assoc 0 (entget ziel))) "INSERT"))) + (progn (entdel e) (setq n-weg (1+ n-weg))) + ) + (setq i (1+ i)) + ) + ) + ) + (if (setq ss (ssget "_X" '((0 . "INSERT") (2 . "GR_Traeger_*")))) + (progn + (setq i 0) + (repeat (sslength ss) + (setq erg (geruest-traeger-beschriften (ssname ss i))) + (cond ((= erg "ok") (setq n-ok (1+ n-ok))) + ((= erg "ersatz") (setq n-ersatz (1+ n-ersatz))) + (T (setq n-fehl (1+ n-fehl)))) + (setq i (1+ i)) + ) + (princ (ssg-textf "gr-tr-beschr-ergebnis" + (list (itoa (+ n-ok n-ersatz)) (itoa n-ersatz) (itoa n-fehl) (itoa n-weg)))) + ) + (princ (ssg-text "gr-tr-beschr-keine")) + ) + (ssg-end) + (princ) +) + +(defun c:GERUEST_TRAEGER ( / bg wahl) + (setq bg (geruest-baugruppe "Traeger")) + (cond + ((null bg) + (princ (ssg-textf "gr-fehler-baugruppe" (list "Traeger")))) + ((null (ssg-json-get bg "geometrie_varianten")) + (princ (ssg-textf "gr-fehler-keine-varianten" (list "Traeger")))) + ((null (setq wahl (geruest-traeger-dialog bg))) + (princ (ssg-text "gr-abgebrochen"))) + (T (geruest-traeger-einfuegen bg wahl)) + ) + (princ) +) + +(princ "\nGeruestInsert.lsp geladen. Befehle: GERUEST, GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG, GERUEST_TRAEGER, GERUEST_TRAEGER_BESCHRIFTEN") (princ) diff --git a/data/geruest/R2-Saeule_dummy.dwg b/data/geruest/R2-Saeule_dummy.dwg index 7c50828..d3b446c 100644 Binary files a/data/geruest/R2-Saeule_dummy.dwg and b/data/geruest/R2-Saeule_dummy.dwg differ diff --git a/data/geruest/dummy_Muffe_1zoll.dwg b/data/geruest/dummy_Muffe_1zoll.dwg new file mode 100644 index 0000000..0e6da75 Binary files /dev/null and b/data/geruest/dummy_Muffe_1zoll.dwg differ diff --git a/data/geruest/dummy_Strebe_30x4.dwg b/data/geruest/dummy_Strebe_30x4.dwg new file mode 100644 index 0000000..b2193b0 Binary files /dev/null and b/data/geruest/dummy_Strebe_30x4.dwg differ diff --git a/data/json/geruest.json b/data/json/geruest.json index 0868ae2..35cb5ba 100644 --- a/data/json/geruest.json +++ b/data/json/geruest.json @@ -5,13 +5,13 @@ "teileart": "Geruest Rohrabhaenger", "dummy": "Rohrabhaenger_dummy.dwg", "attribute": { - "Laenge": { + "LAENGE": { "typ": "number", "min": 0, "max": 6000, "einheit": "mm" }, - "Teilefarbe": { + "TEILEFARBE": { "typ": "auswahl", "optionen": [ "RAL7035", @@ -202,13 +202,13 @@ "teileart": "Geruest Saeule", "dummy": "R2-Saeule_dummy.dwg", "attribute": { - "Laenge": { + "LAENGE": { "typ": "number", "min": 0, "max": 6000, "einheit": "mm" }, - "Teilefarbe": { + "TEILEFARBE": { "typ": "auswahl", "optionen": [ "RAL7035", @@ -231,7 +231,7 @@ ] }, "geometrie_varianten": [ - { + { "name": "R 2\"", "teileart": "Geruest Saeule 2 Zoll", "teile": [ @@ -483,5 +483,197 @@ "unten": [] } ] + }, + "Rohr-Gerüst-Träger": { + "id": "Traeger", + "titel": "Traeger", + "teileart": "Geruest Traeger", + "einfuegeart": "linie", + "querstrebe": { + "dummy": "dummy_Strebe_30x4.dwg", + "abstand_max": 500, + "rand_min": 100, + "rand_max": 250 + }, + "muffe": { + "dummy": "dummy_Muffe_1zoll.dwg" + }, + "beschriftung": { + "format": "%1 L=%2", + "stil": "Lan", + "ausrichtung": "BL", + "hoehe": 100 + }, + "attribute": { + "LAENGE": { + "typ": "number", + "min": 0, + "max": 6000, + "einheit": "mm" + }, + "LAENGENABZUGANFANG": { + "typ": "number", + "einheit": "mm", + "vorgabe": 35, + "aktiv": false + }, + "LAENGENABZUGENDE": { + "typ": "number", + "einheit": "mm", + "vorgabe": 35, + "aktiv": false + }, + "TEILEFARBE": { + "typ": "auswahl", + "optionen": [ + "RAL7035", + "RAL7030" + ], + "frei_erlaubt": true, + "frei_option": "Individuell" + } + }, + "geometrie_varianten": [ + { + "name": "Rohr 1\"", + "beschriftung": { + "text": "Rohr 1\"", + "layer": "D-6-BEM" + }, + "teileart": "Geruest Traeger", + "layer": "D-6", + "teile": [ + { + "artikel": "ROHR R 1\"", + "sivas_id": 821006026, + "farbig": true, + "menge": 1 + } + ] + }, + { + "name": "Rohr 1\" mit Muffe", + "beschriftung": { + "text": "Rohr 1\"", + "layer": "D-6-BEM" + }, + "mit_muffe": true, + "teileart": "Geruest Traeger", + "layer": "D-6", + "teile": [ + { + "artikel": "ROHR R 1\" mit Muffe", + "sivas_id": 825004000, + "farbig": true, + "menge": 1 + } + ] + }, + { + "name": "DRT 80 1\"", + "beschriftung": { + "text": "DRT 80", + "layer": "D-1-BEM" + }, + "teileart": "Geruest Traeger", + "layer": "D-1", + "teile": [ + { + "artikel": "DRT DOPPELROHRTRAEGER 80 1\"", + "sivas_id": 825084000, + "farbig": true, + "menge": 1 + } + ] + }, + { + "name": "DRT 80 1\" mit 2 Muffen", + "beschriftung": { + "text": "DRT 80", + "layer": "D-1-BEM" + }, + "mit_muffe": true, + "teileart": "Geruest Traeger", + "layer": "D-1", + "teile": [ + { + "artikel": "DRT DOPPELROHRTRAEGER 80 1\" mit 2 Muffen", + "sivas_id": 825084007, + "farbig": true, + "menge": 1 + } + ] + }, + { + "name": "DRT 114 1\"", + "beschriftung": { + "text": "DRT 114", + "layer": "D-3-BEM" + }, + "teileart": "Geruest Traeger", + "layer": "D-3", + "teile": [ + { + "artikel": "DRT DOPPELROHRTRAEGER 114 1\"", + "sivas_id": 825104000, + "farbig": true, + "menge": 1 + } + ] + }, + { + "name": "DRT 114 1\" mit 2 Muffen", + "beschriftung": { + "text": "DRT 114", + "layer": "D-3-BEM" + }, + "mit_muffe": true, + "teileart": "Geruest Traeger", + "layer": "D-3", + "teile": [ + { + "artikel": "DRT DOPPELROHRTRAEGER 114 1\" mit 2 Muffen", + "sivas_id": 825104007, + "farbig": true, + "menge": 1 + } + ] + }, + { + "name": "RT 80/80 1\"", + "beschriftung": { + "text": "RT 80/80", + "layer": "D-5-BEM" + }, + "teileart": "Geruest Traeger", + "layer": "D-5", + "teile": [ + { + "artikel": "RT ROHRTRAEGER 80/80 1\"", + "sivas_id": 825144000, + "farbig": true, + "menge": 1 + } + ] + }, + { + "name": "RT 80/80 1\" mit 2 Muffen", + "beschriftung": { + "text": "RT 80/80", + "layer": "D-5-BEM" + }, + "mit_muffe": true, + "teileart": "Geruest Traeger", + "layer": "D-5", + "teile": [ + { + "artikel": "RT ROHRTRAEGER 80/80 1\" mit 2 Muffen", + "sivas_id": 825144007, + "farbig": true, + "menge": 1 + } + ] + } + ] } } \ No newline at end of file diff --git a/dcl/geruest_traeger.dcl b/dcl/geruest_traeger.dcl new file mode 100644 index 0000000..c33cfe1 --- /dev/null +++ b/dcl/geruest_traeger.dcl @@ -0,0 +1,39 @@ +// ============================================================ +// geruest_traeger.dcl - Rohr-Geruest-Traeger konfigurieren +// Verwendet von: GERUEST_TRAEGER (GeruestInsert.lsp, geruest-traeger-dialog) +// +// Die Laenge steht bewusst NICHT im Dialog - sie wird nach dem Dialog in der +// Zeichnung per Start-/Endpunkt (oder getippter Laenge) bestimmt. Aktive +// Laengenabzuege ruecken die Linie am Anfang bzw. Ende ein. +// ============================================================ + +geruest_traeger : dialog { + label = "Rohr-Geruest-Traeger konfigurieren"; + + : boxed_column { + label = "Basis"; + : popup_list { key = "variante"; label = "Variante:"; width = 56; } + : row { + : popup_list { key = "farbe"; label = "Farbe:"; width = 25; } + : edit_box { key = "farbe_frei"; label = "eigene:"; edit_width = 12; } + } + } + + : boxed_column { + label = "Laengenabzug"; + : row { + : toggle { key = "abzug_a"; label = "Laengenabzug Anfang"; width = 24; fixed_width = true; } + : edit_box { key = "abzug_a_w"; label = "mm:"; edit_width = 8; fixed_width = true; } + } + : row { + : toggle { key = "abzug_e"; label = "Laengenabzug Ende"; width = 24; fixed_width = true; } + : edit_box { key = "abzug_e_w"; label = "mm:"; edit_width = 8; fixed_width = true; } + } + } + + : toggle { key = "beschriftung"; label = "Beschriftung einfuegen"; } + + : text { key = "hinweis"; label = ""; width = 56; } + + ok_cancel; +} diff --git a/lang/de_DE.json b/lang/de_DE.json index e9b67f9..2f935b5 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -1022,6 +1022,23 @@ "gr-konfig-teil-unbekannt": "\nGeruest: Anbauteil '%1' aus Konfiguration '%2' ist bei dieser Baugruppe unbekannt - uebersprungen.", "gr-konfig-variante-unbekannt": "\nGeruest: Variante '%1' aus Konfiguration '%2' ist bei dieser Baugruppe unbekannt - Auswahl unveraendert.", "gr-fehler-schreiben": "\nGeruest: Datei konnte nicht geschrieben werden: %1", - "gr-fehler-keine-baugruppen": "\nGeruest: Die Datendatei enthaelt keine Baugruppen." + "gr-fehler-keine-baugruppen": "\nGeruest: Die Datendatei enthaelt keine Baugruppen.", + "gr-tr-fehler-dcl": "Dialog %1 konnte nicht geladen werden.", + "gr-tr-hinweis": "Die Laenge wird nach OK in der Zeichnung bestimmt.", + "gr-tr-alert-abzug": "Laengenabzug ungueltig. Erlaubt ist eine Zahl ab 0 (mm); ein leeres Feld gilt als 0.", + "gr-tr-prompt-start": "\nStartpunkt des Traegers waehlen : ", + "gr-tr-prompt-ende": "\nEndpunkt waehlen oder Laenge (mm) eingeben: ", + "gr-tr-prompt-richtung": "\nRichtung angeben <0>: ", + "gr-tr-eingabe-ungueltig": "\nEingabe '%1' ist weder Punkt noch Laenge.", + "gr-tr-laenge-null": "\nStrecke %1 mm ist nicht laenger als die Abzuege (%2 mm) - kein Traeger eingefuegt.", + "gr-tr-laenge-bereich": "\nTraegerlaenge %1 mm ausserhalb des erlaubten Bereichs %2 bis %3 mm - kein Traeger eingefuegt.", + "gr-tr-fertig": "\nTraeger %1 mm eingefuegt (Block %2).", + "gr-tr-ende": "\n%1 Traeger eingefuegt.", + "gr-tr-bez-abzug-anfang": "Abzug Anfang %1 mm", + "gr-tr-bez-abzug-ende": "Abzug Ende %1 mm", + "gr-tr-beschr-stil-fehlt": "\nTextstil %1 fehlt in der Zeichnung - Beschriftung mit aktuellem Stil %2.", + "gr-tr-beschr-ausrichtung": "\nUnbekannte Ausrichtung %1 fuer die Traeger-Beschriftung - verwende BC.", + "gr-tr-beschr-ergebnis": "\n%1 Traeger beschriftet (davon %2 ohne bekannte Variante), %3 nicht beschriftbar, %4 verwaiste Beschriftungen entfernt.", + "gr-tr-beschr-keine": "\nKeine Rohr-Geruest-Traeger in der Zeichnung." } } diff --git a/lang/en_GB.json b/lang/en_GB.json index bea946d..95a93e9 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -1022,6 +1022,23 @@ "gr-konfig-teil-unbekannt": "\nScaffold: add-on part '%1' from configuration '%2' is unknown for this assembly - skipped.", "gr-konfig-variante-unbekannt": "\nScaffold: variant '%1' from configuration '%2' is unknown for this assembly - selection unchanged.", "gr-fehler-schreiben": "\nScaffold: could not write file: %1", - "gr-fehler-keine-baugruppen": "\nScaffold: the data file contains no assemblies." + "gr-fehler-keine-baugruppen": "\nScaffold: the data file contains no assemblies.", + "gr-tr-fehler-dcl": "Dialog %1 could not be loaded.", + "gr-tr-hinweis": "The length is defined in the drawing after OK.", + "gr-tr-alert-abzug": "Invalid length deduction. Allowed is a number from 0 (mm); an empty field counts as 0.", + "gr-tr-prompt-start": "\nSelect start point of the beam : ", + "gr-tr-prompt-ende": "\nSelect end point or enter length (mm): ", + "gr-tr-prompt-richtung": "\nSpecify direction <0>: ", + "gr-tr-eingabe-ungueltig": "\nInput '%1' is neither a point nor a length.", + "gr-tr-laenge-null": "\nDistance %1 mm is not longer than the deductions (%2 mm) - no beam inserted.", + "gr-tr-laenge-bereich": "\nBeam length %1 mm outside the allowed range %2 to %3 mm - no beam inserted.", + "gr-tr-fertig": "\nBeam %1 mm inserted (block %2).", + "gr-tr-ende": "\n%1 beam(s) inserted.", + "gr-tr-bez-abzug-anfang": "Deduction start %1 mm", + "gr-tr-bez-abzug-ende": "Deduction end %1 mm", + "gr-tr-beschr-stil-fehlt": "\nText style %1 missing in drawing - labelling with current style %2.", + "gr-tr-beschr-ausrichtung": "\nUnknown justification %1 for beam label - using BC.", + "gr-tr-beschr-ergebnis": "\n%1 beam(s) labelled (%2 without known variant), %3 not labellable, %4 orphaned label(s) removed.", + "gr-tr-beschr-keine": "\nNo pipe scaffold beams in the drawing." } } diff --git a/lib/export_csv.py b/lib/export_csv.py index e6e98ed..295f88a 100644 --- a/lib/export_csv.py +++ b/lib/export_csv.py @@ -319,16 +319,25 @@ def build_geruest_merkmale(block): pattern_geruest in cfg/export.cfg, GeruestInsert.lsp *geruest-attrib-defs*). ARTINR/LAENGE/BEZEICHNUNG wandern in feste CSV-Spalten (teileid/ - bezeichnung ueben in process_blocks unten), TEILEART/FARBE/LAYER bleiben - als Rest-Attribute in der Merkmale-JSON-Spalte - so wie bei Separator/ - Scanner/BTMT bereits ueblich.""" + bezeichnung ueben in process_blocks unten), TEILEART/TEILEFARBE/LAYER + bleiben als Rest-Attribute in der Merkmale-JSON-Spalte - so wie bei + Separator/Scanner/BTMT bereits ueblich. + + Die Laengenabzuege gibt es nur beim Rohr-Geruest-Traeger + (*geruest-traeger-attrib-defs*) und erscheinen darum nur, wenn der Block + sie traegt - die Merkmale der anderen GR_-Bloecke bleiben unveraendert.""" attribs = block.get("attribs", {}) - return { + merkmale = { "TeileArt": attribs.get("TEILEART", ""), - "Farbe": attribs.get("FARBE", ""), + "Farbe": attribs.get("TEILEFARBE", ""), "Laenge": attribs.get("LAENGE", ""), "Layer": attribs.get("LAYER", ""), } + for tag, name in (("LAENGENABZUGANFANG", "LaengenabzugAnfang"), + ("LAENGENABZUGENDE", "LaengenabzugEnde")): + if tag in attribs: + merkmale[name] = attribs[tag] + return merkmale def format_sensor_id(prefix, n): diff --git a/menu/SSG_LIB.cui b/menu/SSG_LIB.cui index 8299faa..0cd7164 100644 --- a/menu/SSG_LIB.cui +++ b/menu/SSG_LIB.cui @@ -539,7 +539,7 @@ Rohr-Geruest-Traeger - ^C^C(ssg-ensure "GeruestInsert") GERUEST + ^C^C(ssg-ensure "GeruestInsert") GERUEST_TRAEGER @@ -560,211 +560,223 @@ ^C^C(ssg-ensure "GeruestInsert") GERUEST_WANDBEFESTIGUNG - + + + Gattertraeger + ^C^C(ssg-ensure "GeruestInsert") GERUEST + + + + + Traeger beschriften + ^C^C(ssg-ensure "GeruestInsert") GERUEST_TRAEGER_BESCHRIFTEN + + + Marker einfuegen ^C^C(ssg-ensure "Tro_Edit") TRO_INSERT - + Marker bearbeiten ^C^C(ssg-ensure "Tro_Edit") TRO_EDIT - + Bearbeiten (Auto) ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT - + Verbindung einfuegen ^C^C(ssg-ensure "Connection_Edit") CONNECTION_INSERT - + Verbindung bearbeiten ^C^C(ssg-ensure "Connection_Edit") CONNECTION_EDIT - + Eingang ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_EINGANG_INSERT - + Ausgang ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_AUSGANG_INSERT - + SPS Schliessen ^C^C - + Export Sivas ^C^C(ssg-ensure "export") EXPORTSIVAS - + Export CSV ^C^C(ssg-ensure "export") EXPORTCSV - + Umschalten 2D und 3D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_SWITCH - + Alle Bloecke auf 2D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_ALL_2D - + Alle Bloecke auf 3D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_ALL_3D - + Sprache ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_SPRACHE - + Planquadrate an/aus ^C^C(ssg-ensure "DrawPlanquadrate") PLANQUADRATE_TOGGLE - + CSV-Export ^C^C(ssg-ensure "export") CSV_EXPORT_KONFIG - + alle Tests ausfuehren und exportieren ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) (c:SSG_RUN_ALL_TESTS_EXPORT) - + Tests ausfuehren und stehen lassen ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) (c:SSG_RUN_ALL_TESTS_OFFEN) - + Export CSV/Sivas ALL ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_export_all.lsp")) (c:TEST_EXPORT_ALL) - + Kreisel ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_kreisel.lsp")) (c:TEST_KREISEL) - + Foerderer ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_foerderer.lsp")) (c:TEST_FOERDERER) - + Foerderer-Linienzug ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_linienzug.lsp")) (c:TEST_LINIENZUG) (c:TEST_LINIENZUG_STUFE2) - + Omniflo ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo.lsp")) (c:TEST_OMNIFLO) - + Omniflo Strecke ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo_strecke.lsp")) (c:TEST_OMNIFLO_STRECKE) - + Gefaellestrecke ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_gefaellestrecke.lsp")) (c:TEST_GEFAELLESTRECKE) - + Mubea Gesamtmodell ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_mubea.lsp")) (c:TEST_MUBEA) - + HundM05 Kreisel-Abschnitt ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_hundm05.lsp")) (c:TEST_HUNDM05) - + KS 2D/3D pruefen (CSV) ^C^C(load (strcat (getenv "DXFMAKRO") "/Lisp/ks_pruefung.lsp")) KS_PRUEFEN - + Kreisel bearbeiten (ssg-ensure "KreiselInsert") KreiselEdit - + Omniflo Element bearbeiten (ssg-ensure "OmniModulInsert") OMNI_EDIT - + Gefaellestrecke bearbeiten (ssg-ensure "Gefaellestrecke") GEFAELLESTRECKE_EDIT - + VarioFoerderer bearbeiten (ssg-ensure "VarioFoerderer") VARIOFOERDERER_EDIT - + TRO-Marker bearbeiten (ssg-ensure "Tro_Edit") TRO_EDIT - + Verbindung bearbeiten (ssg-ensure "Connection_Edit") CONNECTION_EDIT - + SSG Bearbeiten (Auto) (ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT @@ -782,10 +794,10 @@ - - - - + + + + ILS @@ -1413,249 +1425,259 @@ Gattertraeger - + + + + + + + Funktionen + + Traeger beschriften + + - + SPS - - + + Eingang - + Ausgang - + SPS Schliessen - + - + TRO Marker einfuegen - + Marker bearbeiten - + Bearbeiten (Auto) - + - + Connections Verbindung einfuegen - + Verbindung bearbeiten - + Bearbeiten (Auto) - + - + Export Export Sivas - + Export CSV - - - - - - - Konfiguration - - Umschalten 2D und 3D + + + Konfiguration - Alle Bloecke auf 2D - - - - - - Alle Bloecke auf 3D + Umschalten 2D und 3D - Sprache + Alle Bloecke auf 2D - Planquadrate an/aus + Alle Bloecke auf 3D - CSV-Export + Sprache + + Planquadrate an/aus + + + + + + CSV-Export + + + + - + Tests alle Tests ausfuehren und exportieren - + Tests ausfuehren und stehen lassen - + Export CSV/Sivas ALL - + Kreisel - + Foerderer - + Foerderer-Linienzug - + Omniflo - + Omniflo Strecke - + Gefaellestrecke - + Mubea Gesamtmodell - + HundM05 Kreisel-Abschnitt - + KS 2D/3D pruefen (CSV) - + - + POP501 SSG_LIB Edit Context Kreisel bearbeiten - + Omniflo Element bearbeiten - + Gefaellestrecke bearbeiten - + VarioFoerderer bearbeiten - + TRO-Marker bearbeiten - + Verbindung bearbeiten - + SSG Bearbeiten (Auto) - + diff --git a/menu/SSG_LIB.mnu b/menu/SSG_LIB.mnu index ac9369e..578eece 100644 --- a/menu/SSG_LIB.mnu +++ b/menu/SSG_LIB.mnu @@ -112,11 +112,13 @@ [<-~APBW 110 R550/67,5 58x497]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_58 [<-Element bearbeiten]^C^C(ssg-ensure "OmniModulInsert") OMNI_EDIT [->Geruest]^C^C(ssg-ensure "GeruestInsert") GERUEST -[Rohr-Geruest-Traeger]^C^C(ssg-ensure "GeruestInsert") GERUEST +[Rohr-Geruest-Traeger]^C^C(ssg-ensure "GeruestInsert") GERUEST_TRAEGER [Saeulen]^C^C(ssg-ensure "GeruestInsert") GERUEST_SAEULEN [Rohrabhaenger]^C^C(ssg-ensure "GeruestInsert") GERUEST_ROHRABHAENGER [Wandbefestigung]^C^C(ssg-ensure "GeruestInsert") GERUEST_WANDBEFESTIGUNG -[<-Gattertraeger]^C^C(ssg-ensure "GeruestInsert") GERUEST +[Gattertraeger]^C^C(ssg-ensure "GeruestInsert") GERUEST +[->Funktionen] +[<-<-Traeger beschriften]^C^C(ssg-ensure "GeruestInsert") GERUEST_TRAEGER_BESCHRIFTEN [->SPS] [->TRO] [Marker einfuegen]^C^C(ssg-ensure "Tro_Edit") TRO_INSERT diff --git a/tests/test_unit.lsp b/tests/test_unit.lsp index 8991c61..23d0ef2 100644 --- a/tests/test_unit.lsp +++ b/tests/test_unit.lsp @@ -754,9 +754,9 @@ (if (findfile _datei) (progn (setq _daten (ssg-json-laden _datei)) - ;; Drei Bereiche: Rohrabhaenger, Saeulen (1 und 2 Zoll zusammengefuehrt), - ;; Wandbefestigung - (tu-eq "json/geruest-baugruppen" 3 (length _daten)) + ;; Vier Baugruppen: Rohrabhaenger, Saeulen (1 und 2 Zoll + ;; zusammengefuehrt), Wandbefestigung, Rohr-Geruest-Traeger + (tu-eq "json/geruest-baugruppen" 4 (length _daten)) ;; Baugruppe ueber das ASCII-Feld "id" finden (aeusserer Schluessel ;; traegt Umlaute bzw. Anfuehrungszeichen) (setq _bg nil) @@ -773,11 +773,16 @@ (ssg-json-get _bg "teileart")) (tu-eq "json/geruest-dummy" "Rohrabhaenger_dummy.dwg" (ssg-json-get _bg "dummy")) - ;; Sivas-ID als Zahl geparst, Laengengrenze aus dem attribute-Block + ;; Sivas-ID als Zahl geparst, Laengengrenze aus dem attribute-Block. + ;; Die Keys unter "attribute" sind die Block-Attribut-Tags und darum + ;; GROSS geschrieben (ssg-json-get unterscheidet Gross/Klein). (tu-eq "json/geruest-sivas" 821006026 (ssg-json-get (car (ssg-json-get (car _var) "teile")) "sivas_id")) (tu-eq "json/geruest-max" 6000 - (ssg-json-get (ssg-json-get (ssg-json-get _bg "attribute") "Laenge") "max")) + (ssg-json-get (ssg-json-get (ssg-json-get _bg "attribute") "LAENGE") "max")) + (tu-eq "json/geruest-farboptionen" '("RAL7035" "RAL7030") + (ssg-json-get (ssg-json-get (ssg-json-get _bg "attribute") "TEILEFARBE") + "optionen")) ) ) ) @@ -978,6 +983,245 @@ (geruest-variante-wert (nth _rec (ssg-json-get _saeulen "geometrie_varianten")) _saeulen "teileart"))) + ;; Attribut-Keys GROSS - sonst findet geruest-dialog min/max und + ;; Farben nicht (Laengenfeld ohne Pruefung, leere Farbliste). + (tu-eq "geruest/saeulen-laenge-max" 6000 + (geruest-attr-feld nil _saeulen "LAENGE" "max")) + (tu-true "geruest/saeulen-farboptionen" + (geruest-attr-feld nil _saeulen "TEILEFARBE" "optionen")) + ) + ) + + ;; --- Rohr-Geruest-Traeger: reine Berechnung --- + ;; Netto-Laenge = Strecke minus beide Abzuege, nil wenn nichts uebrig + (tu-eqf "geruest-traeger-laenge/ende" 965.0 (geruest-traeger-laenge 1000.0 0.0 35.0)) + (tu-eqf "geruest-traeger-laenge/beide" 945.0 (geruest-traeger-laenge 1000.0 20.0 35.0)) + (tu-eqf "geruest-traeger-laenge/ohne" 1000.0 (geruest-traeger-laenge 1000.0 nil nil)) + (tu-nil "geruest-traeger-laenge/zu-kurz" (geruest-traeger-laenge 50.0 30.0 30.0)) + (tu-nil "geruest-traeger-laenge/genau-null" (geruest-traeger-laenge 60.0 30.0 30.0)) + ;; Startpunkt wird um den Anfangsabzug entlang der Richtung eingerueckt, + ;; Z bleibt die des Startklicks + (tu-eqf "geruest-traeger-start/0grad" '(20.0 0.0 500.0) + (geruest-traeger-start '(0.0 0.0 500.0) 0.0 20.0)) + (tu-eqf "geruest-traeger-start/90grad" '(100.0 220.0 0.0) + (geruest-traeger-start '(100.0 200.0 0.0) (/ pi 2.0) 20.0)) + (tu-eqf "geruest-traeger-start/2d-punkt" '(5.0 0.0 0.0) + (geruest-traeger-start '(5.0 0.0) 0.0 0.0)) + ;; Querstreben: Abstand max. 500, Rand 100..250 beidseitig gleich, + ;; so wenige wie moeglich + ;; Abstand genau 500, solange der Rand in 100..250 bleibt + (tu-eqf "geruest-traeger-streben/1200" '(100.0 600.0 1100.0) + (geruest-traeger-streben 1200.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-streben/1300" '(150.0 650.0 1150.0) + (geruest-traeger-streben 1300.0 500.0 100.0 250.0)) + ;; 1100 geht mit genau 500 nicht auf -> Rand 100, Abstand 450 + (tu-eqf "geruest-traeger-streben/1100" '(100.0 550.0 1000.0) + (geruest-traeger-streben 1100.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-streben/1500" '(250.0 750.0 1250.0) + (geruest-traeger-streben 1500.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-streben/1000" '(250.0 750.0) + (geruest-traeger-streben 1000.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-streben/eine" '(200.0) + (geruest-traeger-streben 400.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-streben/grenze-500" '(250.0) + (geruest-traeger-streben 500.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-streben/501" '(100.0 401.0) + (geruest-traeger-streben 501.0 500.0 100.0 250.0)) + (tu-nil "geruest-traeger-streben/zu-kurz" + (geruest-traeger-streben 150.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-streben/min-200" '(100.0) + (geruest-traeger-streben 200.0 500.0 100.0 250.0)) + ;; 6000 mm: 11 Felder a 500 -> 12 Streben, letzte bei 5750 + (setq _rec (geruest-traeger-streben 6000.0 500.0 100.0 250.0)) + (tu-eq "geruest-traeger-streben/6000-anzahl" 12 (length _rec)) + (tu-eqf "geruest-traeger-streben/6000-letzte" 5750.0 (last _rec)) + ;; Konfiguration: fehlende Felder -> Standard, ohne querstrebe -> nil + ;; Ergebnis (dummy laenge querlinie abstand-max rand-min rand-max) + (tu-eqf "geruest-traeger-strebe-cfg/standard" '(nil 30.0 25.0 500.0 100.0 250.0) + (geruest-traeger-strebe-cfg nil + (ssg-json-parse "{\"querstrebe\": {\"rand_min\": 100}}"))) + (tu-eqf "geruest-traeger-strebe-cfg/dummy" '("s.dwg" 30.0 25.0 500.0 100.0 250.0) + (geruest-traeger-strebe-cfg nil + (ssg-json-parse "{\"querstrebe\": {\"dummy\": \"s.dwg\"}}"))) + (tu-eqf "geruest-traeger-strebe-cfg/wert" '(nil 30.0 25.0 400.0 100.0 250.0) + (geruest-traeger-strebe-cfg nil + (ssg-json-parse "{\"querstrebe\": {\"abstand_max\": 400}}"))) + ;; Querlinien an Anfang und Ende der 30 mm langen Strebe + (tu-eqf "geruest-traeger-strebe-enden" '(235.0 265.0) + (geruest-traeger-strebe-enden 250.0 30.0)) + (tu-nil "geruest-traeger-strebe-cfg/ohne" + (geruest-traeger-strebe-cfg nil (ssg-json-parse "{\"id\": \"X\"}"))) + ;; Muffe nur bei "mit_muffe": true; Variante darf eigene Muffe mitbringen + (setq _bgtest (ssg-json-parse "{\"muffe\": {\"dummy\": \"m.dwg\"}}")) + (tu-eq "geruest-traeger-muffe-dummy/flag" "m.dwg" + (geruest-traeger-muffe-dummy + (ssg-json-parse "{\"name\": \"A\", \"mit_muffe\": true}") _bgtest)) + (tu-nil "geruest-traeger-muffe-dummy/ohne-flag" + (geruest-traeger-muffe-dummy + (ssg-json-parse "{\"name\": \"Rohr mit Muffe\"}") _bgtest)) + (tu-eq "geruest-traeger-muffe-dummy/variante" "m2.dwg" + (geruest-traeger-muffe-dummy + (ssg-json-parse + "{\"mit_muffe\": true, \"muffe\": {\"dummy\": \"m2.dwg\"}}") + _bgtest)) + (tu-nil "geruest-traeger-muffe-dummy/ohne-variante" + (geruest-traeger-muffe-dummy nil _bgtest)) + + ;; --- Traeger-Beschriftung: reine Berechnung --- + ;; Textwinkel entlang des Traegers, DIN: 90 < w <= 270 wird gedreht + (tu-eqf "geruest-text-winkel/0" 0.0 (geruest-text-winkel 0.0)) + (tu-eqf "geruest-text-winkel/45" (/ pi 4.0) (geruest-text-winkel (/ pi 4.0))) + (tu-eqf "geruest-text-winkel/90" (/ pi 2.0) (geruest-text-winkel (/ pi 2.0))) + (tu-eqf "geruest-text-winkel/91" (* 271 (/ pi 180.0)) + (geruest-text-winkel (* 91 (/ pi 180.0)))) + (tu-eqf "geruest-text-winkel/180" 0.0 (geruest-text-winkel pi)) + (tu-eqf "geruest-text-winkel/270" (/ pi 2.0) (geruest-text-winkel (* 1.5 pi))) + (tu-eqf "geruest-text-winkel/271" (* 271 (/ pi 180.0)) + (geruest-text-winkel (* 271 (/ pi 180.0)))) + ;; -90 = 270 -> gedreht auf 90 (von unten nach oben lesbar) + (tu-eqf "geruest-text-winkel/-90" (/ pi 2.0) (geruest-text-winkel (- (/ pi 2.0)))) + ;; Ausrichtungs-Codes wie TEXT "Ausrichten" -> (dxf72 dxf73) + (tu-eq "geruest-ausrichtung/TL" '(0 3) (geruest-ausrichtung-codes "TL")) + (tu-eq "geruest-ausrichtung/TC" '(1 3) (geruest-ausrichtung-codes "TC")) + (tu-eq "geruest-ausrichtung/TR" '(2 3) (geruest-ausrichtung-codes "TR")) + (tu-eq "geruest-ausrichtung/ML" '(0 2) (geruest-ausrichtung-codes "ML")) + (tu-eq "geruest-ausrichtung/MC" '(1 2) (geruest-ausrichtung-codes "MC")) + (tu-eq "geruest-ausrichtung/MR" '(2 2) (geruest-ausrichtung-codes "MR")) + (tu-eq "geruest-ausrichtung/BL" '(0 1) (geruest-ausrichtung-codes "BL")) + (tu-eq "geruest-ausrichtung/BC" '(1 1) (geruest-ausrichtung-codes "BC")) + (tu-eq "geruest-ausrichtung/BR" '(2 1) (geruest-ausrichtung-codes "BR")) + (tu-eq "geruest-ausrichtung/klein" '(1 1) (geruest-ausrichtung-codes "bc")) + (tu-nil "geruest-ausrichtung/unbekannt" (geruest-ausrichtung-codes "XY")) + (tu-nil "geruest-ausrichtung/nil" (geruest-ausrichtung-codes nil)) + ;; Textlage: Bezugspunkt auf der Linie, "links" in Leserichtung + (tu-eqf "geruest-text-lage/0-BC" '((1000.0 0.0 0.0) 0.0 1 1) + (geruest-traeger-text-lage '(0.0 0.0 0.0) 0.0 2000.0 "BC")) + (tu-eqf "geruest-text-lage/0-BL" '((0.0 0.0 0.0) 0.0 0 1) + (geruest-traeger-text-lage '(0.0 0.0 0.0) 0.0 2000.0 "BL")) + (tu-eqf "geruest-text-lage/0-BR" '((2000.0 0.0 0.0) 0.0 2 1) + (geruest-traeger-text-lage '(0.0 0.0 0.0) 0.0 2000.0 "BR")) + ;; Traeger nach links (180): Text gedreht auf 0, links = Linienende + (tu-eqf "geruest-text-lage/180-BL" '((-2000.0 0.0 0.0) 0.0 0 1) + (geruest-traeger-text-lage '(0.0 0.0 0.0) pi 2000.0 "BL")) + (tu-eqf "geruest-text-lage/180-BR" '((0.0 0.0 0.0) 0.0 2 1) + (geruest-traeger-text-lage '(0.0 0.0 0.0) pi 2000.0 "BR")) + (tu-eqf "geruest-text-lage/180-BC" '((-1000.0 0.0 0.0) 0.0 1 1) + (geruest-traeger-text-lage '(0.0 0.0 0.0) pi 2000.0 "BC")) + ;; Unbekannter Code -> BC + (tu-eqf "geruest-text-lage/ersatz" '((1000.0 0.0 0.0) 0.0 1 1) + (geruest-traeger-text-lage '(0.0 0.0 0.0) 0.0 2000.0 "XY")) + ;; Text: %1 = Variantentext, %2 = Laenge auf ganze mm + (tu-eq "geruest-text-string/beispiel" "RT 80/80 L=2650" + (geruest-traeger-text-string "%1 L=%2" "RT 80/80" 2649.5)) + (tu-eq "geruest-text-string/abrunden" "L=965 RT" + (geruest-traeger-text-string "L=%2 %1" "RT" 965.4)) + (tu-eq "geruest-text-string/mehrfach" "A A 10" + (geruest-traeger-text-string "%1 %1 %2" "A" 10.0)) + ;; Konfiguration je Feld: Variante vor Baugruppe vor Code-Standard + (setq _bgtest (ssg-json-parse + (strcat "{\"beschriftung\": {\"format\": \"%1 L=%2\", \"stil\": \"S1\"," + " \"ausrichtung\": \"BC\", \"hoehe\": 50, \"layer\": \"D-5-BEM\"}}"))) + (setq _rec (geruest-traeger-beschr-cfg + (ssg-json-parse + "{\"name\": \"RT 80/80 1 Zoll\", \"beschriftung\": {\"text\": \"RT 80/80\", \"layer\": \"D-6-BEM\"}}") + _bgtest "ERSATZ")) + (tu-eq "geruest-beschr-cfg/text" "RT 80/80" (cdr (assoc "text" _rec))) + (tu-eq "geruest-beschr-cfg/layer" "D-6-BEM" (cdr (assoc "layer" _rec))) + (tu-eq "geruest-beschr-cfg/stil" "S1" (cdr (assoc "stil" _rec))) + (tu-eqf "geruest-beschr-cfg/hoehe" 50.0 (cdr (assoc "hoehe" _rec))) + (setq _rec (geruest-traeger-beschr-cfg + (ssg-json-parse "{\"name\": \"Ohne Text\"}") _bgtest "ERSATZ")) + (tu-eq "geruest-beschr-cfg/text-name" "Ohne Text" (cdr (assoc "text" _rec))) + (tu-eq "geruest-beschr-cfg/layer-bg" "D-5-BEM" (cdr (assoc "layer" _rec))) + (setq _rec (geruest-traeger-beschr-cfg nil (ssg-json-parse "{\"id\": \"X\"}") "ERSATZ")) + (tu-eq "geruest-beschr-cfg/ersatz" "ERSATZ" (cdr (assoc "text" _rec))) + (tu-eq "geruest-beschr-cfg/std-format" "%1 L=%2" (cdr (assoc "format" _rec))) + (tu-eq "geruest-beschr-cfg/std-ausr" "BC" (cdr (assoc "ausrichtung" _rec))) + (tu-eqf "geruest-beschr-cfg/std-hoehe" 50.0 (cdr (assoc "hoehe" _rec))) + (tu-nil "geruest-beschr-cfg/std-layer" (cdr (assoc "layer" _rec))) + ;; Bereichspruefung auf der Netto-Laenge + (tu-true "geruest-traeger-pruefen/innen" (geruest-traeger-pruefen 965.0 0 6000)) + (tu-nil "geruest-traeger-pruefen/ueber" (geruest-traeger-pruefen 6001.0 0 6000)) + (tu-true "geruest-traeger-pruefen/grenze" (geruest-traeger-pruefen 6000.0 0 6000)) + (tu-true "geruest-traeger-pruefen/ohne" (geruest-traeger-pruefen 99999.0 nil nil)) + (tu-nil "geruest-traeger-pruefen/nil" (geruest-traeger-pruefen nil 0 6000)) + ;; Eingaben in mm: Komma wie Punkt, negativ/Text ungueltig + (tu-eqf "geruest-mm-zahl/ganz" 35.0 (geruest-mm-zahl "35")) + (tu-eqf "geruest-mm-zahl/komma" 17.5 (geruest-mm-zahl "17,5")) + (tu-nil "geruest-mm-zahl/text" (geruest-mm-zahl "abc")) + (tu-nil "geruest-mm-zahl/negativ" (geruest-mm-zahl "-5")) + (tu-nil "geruest-mm-zahl/leer" (geruest-mm-zahl "")) + (tu-eqf "geruest-abzug-wert/leer" 0.0 (geruest-abzug-wert "")) + (tu-nil "geruest-abzug-wert/text" (geruest-abzug-wert "x")) + (tu-eqf "geruest-tr-abzug/inaktiv" 0.0 (geruest-tr-abzug "0" "x")) + (tu-eqf "geruest-tr-abzug/aktiv" 35.0 (geruest-tr-abzug "1" "35")) + (tu-eq "geruest-mm-string/ganz" "965" (geruest-mm-string 965.0)) + (tu-eq "geruest-mm-string/dezimal" "17.5" (geruest-mm-string 17.5)) + ;; Variante darf Attribut-Felder ueberschreiben - auch mit false + (setq _bgtest (ssg-json-parse + "{\"attribute\": {\"LAENGENABZUGENDE\": {\"vorgabe\": 35, \"aktiv\": true}}}")) + (tu-eq "geruest-attr-feld/baugruppe" 35 + (geruest-attr-feld nil _bgtest "LAENGENABZUGENDE" "vorgabe")) + (tu-eq "geruest-attr-feld/variante" 50 + (geruest-attr-feld + (ssg-json-parse "{\"attribute\": {\"LAENGENABZUGENDE\": {\"vorgabe\": 50}}}") + _bgtest "LAENGENABZUGENDE" "vorgabe")) + (tu-nil "geruest-attr-feld/variante-false" + (geruest-attr-feld + (ssg-json-parse "{\"attribute\": {\"LAENGENABZUGENDE\": {\"aktiv\": false}}}") + _bgtest "LAENGENABZUGENDE" "aktiv")) + + ;; --- Rohr-Geruest-Traeger in der echten Datendatei --- + ;; Eigener Dialog: im Bereichs-Dropdown von GERUEST darf er fehlen, + ;; ueber geruest-baugruppe muss er aber auffindbar sein. + (setq _rec nil) + (foreach _e (geruest-baugruppen-liste) + (if (equal (car _e) "Traeger") (setq _rec T))) + (tu-nil "geruest/traeger-nicht-im-dropdown" _rec) + (setq _traeger (geruest-baugruppe "Traeger")) + (tu-true "geruest/traeger-vorhanden" _traeger) + (if _traeger + (progn + (tu-eq "geruest/traeger-einfuegeart" "linie" + (ssg-json-get _traeger "einfuegeart")) + (tu-eq "geruest/traeger-varianten-artikel" 0 + (tu-geruest-artikel-unvollstaendig + (ssg-json-get _traeger "geometrie_varianten"))) + (tu-true "geruest/traeger-layer" + (geruest-variante-wert + (car (ssg-json-get _traeger "geometrie_varianten")) + _traeger "layer")) + (tu-eq "geruest/traeger-max" 6000 + (geruest-attr-feld nil _traeger "LAENGE" "max")) + (tu-eqf "geruest/traeger-querstrebe" + '("dummy_Strebe_30x4.dwg" 30.0 25.0 500.0 100.0 250.0) + (geruest-traeger-strebe-cfg nil _traeger)) + ;; Muffen-Flag ausdruecklich je Variante: genau die "mit (2) Muffe(n)" + (setq _rec 0) + (foreach _v (ssg-json-get _traeger "geometrie_varianten") + (if (geruest-traeger-muffe-dummy _v _traeger) (setq _rec (1+ _rec)))) + (tu-eq "geruest/traeger-muffen-varianten" 4 _rec) + ;; Jede Variante definiert Beschriftungstext UND -layer selbst - der + ;; Layer ist je Traegervariante verschieden, eine Vorgabe der + ;; Baugruppe gibt es dafuer bewusst nicht. + (setq _rec 0) + (foreach _v (ssg-json-get _traeger "geometrie_varianten") + (setq _cfg (geruest-traeger-beschr-cfg _v _traeger "")) + (if (and (geruest-obj-feld _v _traeger '("beschriftung") "text") + (/= (cdr (assoc "text" _cfg)) "") + (geruest-json-pfad-get _v '("beschriftung" "layer")) + (geruest-ausrichtung-codes (cdr (assoc "ausrichtung" _cfg)))) + (setq _rec (1+ _rec)))) + (tu-eq "geruest/traeger-beschriftung-varianten" + (length (ssg-json-get _traeger "geometrie_varianten")) _rec) + ;; VARIANTE gehoert zum Traeger-Schema (Grundlage fuer das Neubeschriften) + (tu-true "geruest/traeger-attrib-variante" + (assoc "VARIANTE" *geruest-traeger-attrib-defs*)) + ;; Beide Dummy-DWGs liegen unter data/geruest + (tu-true "geruest/traeger-strebe-dwg" + (findfile (geruest-dummy-pfad "dummy_Strebe_30x4.dwg"))) + (tu-true "geruest/traeger-muffe-dwg" + (findfile (geruest-dummy-pfad "dummy_Muffe_1zoll.dwg"))) ) )