diff --git a/CLAUDE.md b/CLAUDE.md index 2cb453f..84ed02c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,7 @@ AutoLISP-Makros (SSG_LIB) fuer BricsCAD Pro zur automatisierten Erstellung von F | `cfg/` | Konfigurationsdateien | | `data/` | JSON-Daten, DXF-Quellen, Block-Libraries | | `data/ils/` | DWG-Bloecke fuer ILS-Kreisel/Eckrad (AN8, SP8, AP-Typen) | -| `data/json/` | Komponentendaten (Masse, Sivas-IDs) | +| `data/json/` | Komponentendaten (Masse, Sivas-IDs); Geruest: `geruest.json` (GERUEST-Dialog) und `geruest_traeger.json` (Traeger mit Linien-Logik) | | `data/block_libraries/` | DXF Block-Libraries (ils_library.dxf) | | `dcl/` | DCL-Dialogdefinitionen | | `doc/` | Dokumentation, Entwicklungsplan | @@ -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_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) | +| `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; fuer `dummy` ueber `geruest-dummy-wahl`: fehlt die DWG der Variante, Meldung + Rueckfall auf den Baugruppen-Dummy; ist der Dummy zugleich eine Teile-DWG, wird er per `geruest-ohne-pfad` nicht doppelt eingefuegt) - 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 Anzahl. **Zwei Mengenfelder im JSON, bewusst verschieden benannt**: `stueckzahl` = wie oft ein Teil TATSAECHLICH geschrieben wird (je Variante bzw. je Satz/Anbauteil, fehlt = 1), `anzahl_vorgabe` = NUR die Vorbelegung des Anzahl-Feldes im Dialog (Anbaugruppen, fehlt = 1); ein Anbauteil wird Anzahl x `stueckzahl` mal geschrieben, bei einer Gruppe (`teile`) zaehlt die Anzahl die Saetze (`geruest-stueckzahl`/`geruest-anzahl-vorgabe`). In Konfigurationen (`oben`/`unten`) heisst der gespeicherte Dialogwert `anzahl`. 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 Anzahl x `stueckzahl` es vorgeben - 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`): Traeger-Baugruppen mit Linien-Logik liegen in einer EIGENEN Datei `data/json/geruest_traeger.json` (gleicher Aufbau wie geruest.json, eigener Lader/Cache `geruest-traeger-daten`, Suche `geruest-baugruppe id daten`; gemeinsamer Lader `geruest-json-laden-cache`) - sie tauchen darum nicht im Bereichs-Dropdown von GERUEST auf; dort kann spaeter auch der Gattertraeger hin. 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). | diff --git a/Lisp/GeruestInsert.lsp b/Lisp/GeruestInsert.lsp index 1788ed1..e331874 100644 --- a/Lisp/GeruestInsert.lsp +++ b/Lisp/GeruestInsert.lsp @@ -5,6 +5,7 @@ ;; Nutzer eine Basis-Variante, Anbauteile fuer "Befestigung oben" UND ;; "Befestigung unten" (je mit eigener Stueckzahl), Laenge und Farbe waehlen, ;; und fuegt das Ergebnis als Block GR__ ein. +;; Rohr-Geruest-Traeger (GERUEST_TRAEGER) lesen data/json/geruest_traeger.json. ;; ;; Beide Befestigungslisten enthalten ALLE Anbauteile der Baugruppe - dasselbe ;; Teil kann oben, unten oder gleichzeitig an beiden Positionen sitzen. @@ -100,9 +101,10 @@ ) ) -(defun geruest-json-pfad ( / basis) +;; Pfad einer Datendatei unter data/json, z.B. "geruest.json". +(defun geruest-json-pfad (datei / basis) (if (setq basis (geruest-data-verzeichnis)) - (strcat basis "/json/geruest.json") + (strcat basis "/json/" datei) ) ) @@ -112,36 +114,48 @@ ) ) -;; Datendatei einmal je Zeichnungssitzung laden. -(defun geruest-daten ( / pfad) - (if (null *geruest-daten*) +;; Datendatei unter data/json einmal je Zeichnungssitzung laden und im +;; globalen Symbol cache-sym ablegen. Rueckgabe: die geparsten Daten oder nil +;; (mit Meldung). +(defun geruest-json-laden-cache (datei cache-sym / pfad daten) + (if (null (eval cache-sym)) (progn - (setq pfad (geruest-json-pfad)) + (setq pfad (geruest-json-pfad datei)) (cond ((null pfad) (princ (ssg-text "gr-fehler-datenpfad"))) ((null (findfile pfad)) (princ (ssg-textf "gr-fehler-json-fehlt" (list pfad)))) (T - (setq *geruest-daten* (ssg-json-laden pfad)) - (if (null *geruest-daten*) + (setq daten (ssg-json-laden pfad)) + (set cache-sym daten) + (if (null daten) (princ (ssg-textf "gr-fehler-json-lesbar" (list pfad))) ) ) ) ) ) - *geruest-daten* + (eval cache-sym) +) + +;; Baugruppen des GERUEST-Dialogs (Rohrabhaenger, Saeulen, Wandbefestigung). +(defun geruest-daten ( / ) + (geruest-json-laden-cache "geruest.json" '*geruest-daten*) +) + +;; Traeger-Baugruppen mit Linien-Logik (Rohr-Geruest-Traeger, spaeter z.B. +;; Gattertraeger) - bewusst eine eigene Datei: eigener Dialog, Laenge aus der +;; Zeichnung, Streben/Muffe/Beschriftung statt Anbaugruppen/Konfigurationen. +(defun geruest-traeger-daten ( / ) + (geruest-json-laden-cache "geruest_traeger.json" '*geruest-traeger-daten*) ) ;; 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. +;; Reihenfolge bestimmt auch die Reihenfolge im Bereichs-Dropdown. Die +;; Traeger stehen in geruest_traeger.json und gehoeren nicht hierher. (defun geruest-baugruppen-liste ( / erg) (setq erg nil) (foreach eintrag (geruest-daten) - (if (and (listp (cdr eintrag)) - (not (equal (ssg-json-get (cdr eintrag) "einfuegeart") "linie"))) + (if (listp (cdr eintrag)) (setq erg (append erg (list (cons (ssg-json-get (cdr eintrag) "id") (cdr eintrag))))) ) @@ -169,6 +183,40 @@ (if (and w (/= w "")) w (ssg-json-get bg schluessel)) ) +;; Pfad der Dummy-DWG fuer den Block. Ein "dummy" in der Geometrie-Variante +;; wird bevorzugt; fehlt die Datei unter data/geruest, wird gemeldet und auf +;; den "dummy" der Baugruppe zurueckgefallen. Rueckgabe: (datei . pfad) - +;; pfad ist nil, wenn kein Datenverzeichnis bekannt ist; ob die +;; Rueckfall-Datei existiert, prueft der Aufrufer. +(defun geruest-dummy-wahl (variante bg / v pfad) + (setq v (if variante (ssg-json-get variante "dummy"))) + (if (and v (= (type v) 'STR) (/= v "") + (setq pfad (geruest-dummy-pfad v)) + (findfile pfad)) + (cons v pfad) + (progn + (if (and v (= (type v) 'STR) (/= v "")) + (princ (ssg-textf "gr-fehler-dummy-variante" + (list (if pfad pfad v) + (if (ssg-json-get bg "dummy") + (ssg-json-get bg "dummy") + "-")))) + ) + (setq v (ssg-json-get bg "dummy")) + (cons v (geruest-dummy-pfad v)) + ) + ) +) + +;; Liste ohne die Eintraege, die (ohne Gross/Klein) gleich pfad sind. Damit +;; landet eine Teile-DWG, die zugleich der Dummy ist, nicht doppelt im Block. +(defun geruest-ohne-pfad (pfad liste) + (if pfad + (vl-remove-if '(lambda (p) (= (strcase p) (strcase pfad))) liste) + liste + ) +) + ;; ============================================================ ;; TEILE AUSWERTEN @@ -184,9 +232,23 @@ ) ) -(defun geruest-menge (eintrag / m) - (setq m (ssg-json-get eintrag "menge")) - (if (and m (numberp m) (> m 0)) (fix m) 1) +;; Zwei Mengenfelder im JSON, bewusst verschieden benannt: +;; "stueckzahl" = wie oft das Teil TATSAECHLICH geschrieben wird - je +;; Einbau (Variante) bzw. je Satz/Anbauteil. Fehlt = 1. +;; "anzahl_vorgabe" = NUR die Vorbelegung des Anzahl-Feldes im Dialog +;; (Anbaugruppen). Fehlt = 1. +;; Ein Anbauteil wird Anzahl (Dialog) x stueckzahl mal geschrieben; bei einer +;; Gruppe ("teile") ist die Anzahl die Zahl der Saetze. +(defun geruest-positiv-int (w / ) + (if (and w (numberp w) (> w 0)) (fix w) 1) +) + +(defun geruest-stueckzahl (eintrag) + (geruest-positiv-int (ssg-json-get eintrag "stueckzahl")) +) + +(defun geruest-anzahl-vorgabe (eintrag) + (geruest-positiv-int (ssg-json-get eintrag "anzahl_vorgabe")) ) ;; Sivas-ID als String. Im JSON stehen rein numerische IDs als Zahl @@ -212,7 +274,7 @@ ) ;; Alle Teile eines Eintrags als ((artnr . farbig) ...), jedes gemaess -;; "menge" wiederholt. Benannte Gruppen ("teile") werden rekursiv aufgeloest. +;; "stueckzahl" wiederholt. Benannte Gruppen ("teile") werden rekursiv aufgeloest. ;; farbig = darf das Teil die Baugruppenfarbe tragen ("farbig" im JSON). Eine ;; Gruppe mit "farbig": true vererbt das an ihre Teile (erbe); ein Teil kann ;; die Vererbung nicht per false aufheben - false und "fehlt" sind beide nil. @@ -229,12 +291,12 @@ (setq erg (mapcar '(lambda (nr) (cons nr farbig)) (geruest-wiederholen (geruest-id-string (ssg-json-get eintrag "sivas_id")) - (geruest-menge eintrag)))) + (geruest-stueckzahl eintrag)))) ) erg ) -;; Alle Artikelnummern eines Eintrags, jede gemaess "menge" wiederholt. +;; Alle Artikelnummern eines Eintrags, jede gemaess "stueckzahl" wiederholt. (defun geruest-artikelnummern (eintrag) (mapcar 'car (geruest-teile-paare eintrag nil)) ) @@ -289,7 +351,7 @@ ;; Eingabe aus einem Mengenfeld auswerten. ;; Leer -> Vorgabewert aus dem JSON, gueltig -> Zahl >= 1, sonst nil. -(defun geruest-menge-wert (s vorgabe) +(defun geruest-anzahl-wert (s vorgabe) (setq s (ssg-cfg-trim (if s s ""))) (cond ((= s "") vorgabe) @@ -310,30 +372,18 @@ ) ) -;; Artikelnummern eines Eintrags bei frei gewaehlter Stueckzahl. -;; Einzelteil: die Sivas-ID anzahl-mal. Benannte Gruppe ("teile"): das -;; komplette Set anzahl-mal - die Mengen INNERHALB des Sets bleiben erhalten +;; Teile eines Anbauteils bei der im Dialog gewaehlten Anzahl: der Eintrag +;; (Einzelteil mit seiner "stueckzahl" bzw. benannte Gruppe als kompletter +;; Satz) anzahl-mal. Die Stueckzahlen INNERHALB eines Satzes bleiben erhalten ;; (ein Schraubenset bleibt 1 Scheibe + 2 Muttern + 1 Schraube je Satz). -(defun geruest-teile-paare-n (eintrag anzahl / teile einmal erg i farbig) - (setq teile (ssg-json-get eintrag "teile")) - (setq farbig (if (ssg-json-get eintrag "farbig") T nil)) - (if teile - (progn - (setq einmal nil) - (foreach teil teile - (setq einmal (append einmal (geruest-teile-paare teil farbig))) - ) - (setq erg nil i 0) - (while (< i anzahl) - (setq erg (append erg einmal)) - (setq i (1+ i)) - ) - erg - ) - (mapcar '(lambda (nr) (cons nr farbig)) - (geruest-wiederholen - (geruest-id-string (ssg-json-get eintrag "sivas_id")) anzahl)) +(defun geruest-teile-paare-n (eintrag anzahl / einmal erg i) + (setq einmal (geruest-teile-paare eintrag nil)) + (setq erg nil i 0) + (while (< i anzahl) + (setq erg (append erg einmal)) + (setq i (1+ i)) ) + erg ) (defun geruest-artikelnummern-n (eintrag anzahl) @@ -441,7 +491,7 @@ ;; Positionsliste ("oben"/"unten") einer Konfiguration auf die Anbauteile ;; abbilden. Rueckgabe: ein Eintrag je Anbauteil - nil (nicht gewaehlt) oder -;; die Stueckzahl. Ein unbekannter Artikelname wird gemeldet und +;; die Anzahl (Feld "anzahl"). Ein unbekannter Artikelname wird gemeldet und ;; uebersprungen, statt die ganze Konfiguration scheitern zu lassen. (defun geruest-konfig-position (konfig schluessel anbauteile / mengen idx n) (setq mengen (geruest-nil-liste (length anbauteile))) @@ -449,7 +499,7 @@ (setq idx (geruest-name-index (ssg-json-get e "artikel") anbauteile)) (if idx (progn - (setq n (ssg-json-get e "menge")) + (setq n (ssg-json-get e "anzahl")) (setq mengen (geruest-liste-setzen mengen idx (if (and n (numberp n) (> n 0)) (fix n) 1))) ) @@ -583,20 +633,20 @@ (defun geruest-dlg-standard ( / erg) (setq erg nil) (foreach a *geruest-anbauteile* - (setq erg (append erg (list (cons "0" (itoa (geruest-menge a)))))) + (setq erg (append erg (list (cons "0" (itoa (geruest-anzahl-vorgabe a)))))) ) erg ) ;; Mengenliste (nil oder Zahl je Teil) in den Tile-Zustand umsetzen. -(defun geruest-mengen->tiles (mengen / erg i a) +(defun geruest-anzahlen->tiles (mengen / erg i a) (setq erg nil i 0) (foreach m mengen (setq a (nth i *geruest-anbauteile*)) (setq erg (append erg (list (if m (cons "1" (itoa m)) - (cons "0" (itoa (geruest-menge a))))))) + (cons "0" (itoa (geruest-anzahl-vorgabe a))))))) (setq i (1+ i)) ) erg @@ -720,10 +770,10 @@ *geruest-dlg-frei* farbe)) ) (setq *geruest-dlg-oben* - (geruest-mengen->tiles + (geruest-anzahlen->tiles (geruest-konfig-position k "oben" *geruest-anbauteile*))) (setq *geruest-dlg-unten* - (geruest-mengen->tiles + (geruest-anzahlen->tiles (geruest-konfig-position k "unten" *geruest-anbauteile*))) ) ) @@ -745,16 +795,16 @@ ) ;; Angehakte Teile einer Spalte mit gueltiger Menge einsammeln. -;; Rueckgabe: (T . ((index . menge) ...)) oder nil bei ungueltigem Mengenfeld. +;; Rueckgabe: (T . ((index . anzahl) ...)) oder nil bei ungueltigem Mengenfeld. ;; Das fuehrende T ist noetig, weil "nichts ausgewaehlt" ein gueltiges ;; Ergebnis ist und sich sonst nicht von einem Fehler unterscheiden liesse. -(defun geruest-mengen-lesen (zustand / erg i a m ok) +(defun geruest-anzahlen-lesen (zustand / erg i a m ok) (setq erg nil i 0 ok T) (foreach paar zustand (setq a (nth i *geruest-anbauteile*)) (if (and ok (= (car paar) "1")) (progn - (setq m (geruest-menge-wert (cdr paar) (geruest-menge a))) + (setq m (geruest-anzahl-wert (cdr paar) (geruest-anzahl-vorgabe a))) (if m (setq erg (append erg (list (cons i m)))) (setq ok nil) @@ -788,11 +838,11 @@ (setq a (nth i *geruest-anbauteile*)) (if (= (car paar) "1") (progn - (setq m (geruest-menge-wert (cdr paar) (geruest-menge a))) + (setq m (geruest-anzahl-wert (cdr paar) (geruest-anzahl-vorgabe a))) (if m (setq erg (append erg (list (list (cons "artikel" (geruest-eintrag-name a)) - (cons "menge" m))))) + (cons "anzahl" m))))) ) ) ) @@ -818,7 +868,7 @@ (write-line (strcat " { \"artikel\": \"" (ssg-json-escape (ssg-json-get e "artikel")) - "\", \"menge\": " (itoa (ssg-json-get e "menge")) " }" + "\", \"anzahl\": " (itoa (ssg-json-get e "anzahl")) " }" (if (< i n) "," "")) f) ) @@ -963,7 +1013,7 @@ ) ;; Dialog fuer einen Bereich zeigen. Rueckgabe: -;; ("OK" variante-index ((idx . menge) ...) ((idx . menge) ...) laenge farbe) +;; ("OK" variante-index ((idx . anzahl) ...) ((idx . anzahl) ...) laenge farbe) ;; - drittes Element = Befestigung oben, viertes = unten ;; ("WECHSEL" bereich-index) - Nutzer hat den Bereich umgestellt ;; nil - abgebrochen @@ -1120,8 +1170,8 @@ ) (T - (setq oben-m (geruest-mengen-lesen *geruest-dlg-oben*)) - (setq unten-m (geruest-mengen-lesen *geruest-dlg-unten*)) + (setq oben-m (geruest-anzahlen-lesen *geruest-dlg-oben*)) + (setq unten-m (geruest-anzahlen-lesen *geruest-dlg-unten*)) (if (or (null oben-m) (null unten-m)) (alert (ssg-text "gr-alert-menge")) (progn @@ -1170,10 +1220,14 @@ ;; Rueckgabe: (blockname . entity) oder nil. (defun geruest-block-bauen (bg variante werte pt teile-dwgs / datei dummy lastEnt dummyEnt dummy-attribs attribs) - ;; Eine Variante darf eine eigene Dummy-DWG mitbringen; sonst gilt die der - ;; Baugruppe. - (setq datei (geruest-variante-wert variante bg "dummy")) - (setq dummy (geruest-dummy-pfad datei)) + ;; Eine Variante darf eine eigene Dummy-DWG mitbringen; sonst (oder wenn + ;; deren Datei fehlt) gilt die der Baugruppe. + (setq datei (geruest-dummy-wahl variante bg)) + (setq dummy (cdr datei) + datei (car datei)) + ;; Ist der Dummy zugleich eine Teile-DWG (z.B. 821006036.dwg beim + ;; T-Abhaenger), nicht ein zweites Mal einfuegen. + (setq teile-dwgs (geruest-ohne-pfad dummy teile-dwgs)) (if (or (null dummy) (null (findfile dummy))) (progn (princ (ssg-textf "gr-fehler-dummy" (list (if dummy dummy datei)))) @@ -1269,7 +1323,7 @@ ;; ============================================================ ;; Teile-Paare ((artnr . farbig) ...) einer Befestigungsauswahl -;; ((index . menge) ...). +;; ((index . anzahl) ...). (defun geruest-auswahl-paare (auswahl anbauteile / erg) (setq erg nil) (foreach paar auswahl @@ -1410,7 +1464,7 @@ ;; ============================================================ -;; ROHR-GERUEST-TRAEGER (Baugruppe mit "einfuegeart": "linie") +;; ROHR-GERUEST-TRAEGER (Daten: data/json/geruest_traeger.json) ;; ============================================================ ;; Eigener Dialog (dcl/geruest_traeger.dcl): Variante, Farbe und zwei ;; Laengenabzuege. Die Laenge selbst wird DANACH in der Zeichnung bestimmt - @@ -1425,11 +1479,10 @@ ;; 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) +;; Baugruppe ueber das ASCII-Feld "id" in daten (z.B. (geruest-traeger-daten)). +(defun geruest-baugruppe (id daten / erg) (setq erg nil) - (foreach eintrag (geruest-daten) + (foreach eintrag daten (if (and (null erg) (listp (cdr eintrag)) (equal (ssg-json-get (cdr eintrag) "id") id)) (setq erg (cdr eintrag)) @@ -2098,7 +2151,7 @@ cfg laenge lage lay handle code erg) (setq ed (entget blockEnt)) (setq attribs (ssg-attrib-read blockEnt)) - (setq bg (geruest-baugruppe "Traeger")) + (setq bg (geruest-baugruppe "Traeger" (geruest-traeger-daten))) (setq laenge (atof (cond ((cdr (assoc "LAENGE" attribs))) ("0")))) (if (and bg (> laenge 0.0)) (progn @@ -2190,7 +2243,7 @@ ) (defun c:GERUEST_TRAEGER ( / bg wahl) - (setq bg (geruest-baugruppe "Traeger")) + (setq bg (geruest-baugruppe "Traeger" (geruest-traeger-daten))) (cond ((null bg) (princ (ssg-textf "gr-fehler-baugruppe" (list "Traeger")))) diff --git a/data/geruest/821004200.dwg b/data/geruest/821004200.dwg new file mode 100644 index 0000000..148b0a3 Binary files /dev/null and b/data/geruest/821004200.dwg differ diff --git a/data/geruest/821006031.dwg b/data/geruest/821006031.dwg new file mode 100644 index 0000000..3c49e4b Binary files /dev/null and b/data/geruest/821006031.dwg differ diff --git a/data/geruest/821006036.dwg b/data/geruest/821006036.dwg new file mode 100644 index 0000000..e98cc36 Binary files /dev/null and b/data/geruest/821006036.dwg differ diff --git a/data/geruest/821006042.dwg b/data/geruest/821006042.dwg new file mode 100644 index 0000000..de1712d Binary files /dev/null and b/data/geruest/821006042.dwg differ diff --git a/data/geruest/821006043.dwg b/data/geruest/821006043.dwg new file mode 100644 index 0000000..ad9fd97 Binary files /dev/null and b/data/geruest/821006043.dwg differ diff --git a/data/geruest/R2-Saeule_dummy.dwg b/data/geruest/821006051.dwg similarity index 68% rename from data/geruest/R2-Saeule_dummy.dwg rename to data/geruest/821006051.dwg index d3b446c..cbf0558 100644 Binary files a/data/geruest/R2-Saeule_dummy.dwg and b/data/geruest/821006051.dwg differ diff --git a/data/geruest/825006009.dwg b/data/geruest/825006009.dwg new file mode 100644 index 0000000..640793e Binary files /dev/null and b/data/geruest/825006009.dwg differ diff --git a/data/json/geruest.json b/data/json/geruest.json index 35cb5ba..cbbb946 100644 --- a/data/json/geruest.json +++ b/data/json/geruest.json @@ -29,13 +29,13 @@ "artikel": "ROHR R 1\" 33,7 x 2,6", "sivas_id": 821006026, "farbig": true, - "menge": 1 + "stueckzahl": 1 }, { "artikel": "CAD - ROHRABH. 1\" NICHT GEQUETSCHT - MONTAGEELEMENTE KPL.", "sivas_id": 821004202, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] }, @@ -46,13 +46,13 @@ "artikel": "ROHR R 1\" 33,7 x 2,6 einseitig gequetscht", "sivas_id": 821006034, "farbig": true, - "menge": 1 + "stueckzahl": 1 }, { "artikel": "CAD - ROHRABHÄNGER 1\" EINSEITIG GEQUETSCHT - MONTAGEELEMENTE KPL.", "sivas_id": 821004203, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] }, @@ -63,13 +63,25 @@ "artikel": "ROHR R 1\" 33,7 x 2,6 beidseitig gequetscht", "sivas_id": 821006035, "farbig": true, - "menge": 1 + "stueckzahl": 1 }, { "artikel": "CAD - ROHRABHÄNGER 1\" BEIDSEITIG GEQUETSCHT - MONTAGEELEMENTE KPL.", "sivas_id": 821004204, "farbig": false, - "menge": 1 + "stueckzahl": 1 + } + ] + }, + { + "name": "T-Abhaenger mit 300 mm Flanschrohr R 1\" 33,7 x 2,6", + "dummy": "821006036.dwg", + "teile": [ + { + "artikel": "T-ABHÄNGER MIT FLANSCH-ROHR 33,7 x 2,6", + "sivas_id": 821006036, + "farbig": true, + "stueckzahl": 1 } ] } @@ -79,34 +91,37 @@ "artikel": "SPANNPRATZE ST - KH 8-11 KPL.SELBSTSICHERND", "sivas_id": 821004120, "farbig": false, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "SPANNPRATZE SELBSTSICHERND KPL.", "sivas_id": 821004058, "farbig": false, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "name": "Schraubenset", + "anzahl_vorgabe": 1, "teile": [ { "artikel": "Scheibe DIN 125 - A 10,5 - 140 HV - St", "sivas_id": 913011010, "farbig": false, - "menge": 1 + "stueckzahl": 1 }, { "artikel": "Sechskantmutter DIN 934 - M10 - 8", "sivas_id": 912011010, "farbig": false, - "menge": 2 + "stueckzahl": 2 }, { "artikel": "Sechskantschraube DIN 933 - M10 x 30 - 8.8", "sivas_id": 911011008, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] }, @@ -114,43 +129,50 @@ "artikel": "U-BÜGEL M7 41X49 FÜR PROFILGERÜST - BG", "sivas_id": 825004049, "farbig": false, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "ROHRKLAMMER 1\" KPL. VERTIKAL", "sivas_id": 825004040, "farbig": false, - "menge": 2 + "stueckzahl": 1, + "anzahl_vorgabe": 2 }, { "artikel": "WINKEL 60X60X6X300", "sivas_id": 821006043, "farbig": false, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "WINKEL 60X60X6X60", "sivas_id": 821006042, "farbig": false, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "ROHRKLAMMER 1\" T-VERBINDUNG KPL.", "sivas_id": 825004030, "farbig": false, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "ROHRKLAMMER 1\" FLACH UND LANG, KPL.", "sivas_id": 825002021, "farbig": false, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "DURCHSTECKANKER HST M12X115X20", "sivas_id": 922021003, "farbig": false, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 } ], "konfigurationen": [ @@ -162,17 +184,17 @@ "oben": [ { "artikel": "SPANNPRATZE SELBSTSICHERND KPL.", - "menge": 1 + "anzahl": 1 }, { "artikel": "Schraubenset", - "menge": 1 + "anzahl": 1 } ], "unten": [ { "artikel": "ROHRKLAMMER 1\" KPL. VERTIKAL", - "menge": 2 + "anzahl": 2 } ] }, @@ -184,13 +206,13 @@ "oben": [ { "artikel": "DURCHSTECKANKER HST M12X115X20", - "menge": 2 + "anzahl": 2 } ], "unten": [ { "artikel": "ROHRKLAMMER 1\" T-VERBINDUNG KPL.", - "menge": 1 + "anzahl": 1 } ] } @@ -200,7 +222,7 @@ "id": "Saeulen", "titel": "Saeulen", "teileart": "Geruest Saeule", - "dummy": "R2-Saeule_dummy.dwg", + "dummy": "821006051.dwg", "attribute": { "LAENGE": { "typ": "number", @@ -239,31 +261,32 @@ "artikel": "BODENSÄULE R 2\" 60,3 MIT FUSSPLATTE", "sivas_id": 821006051, "farbig": true, - "menge": 1 + "stueckzahl": 1 }, { "artikel": "CAD - BODENSÄULE R 2\" - DURCHSTECKANKER KPL.", "sivas_id": 821004201, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] }, { "name": "R 1\"", "teileart": "Geruest Saeule 1 Zoll", + "dummy": "821004200.dwg", "teile": [ { "artikel": "ROHR R 1\" 33,7 x 2,6", "sivas_id": 821006026, "farbig": true, - "menge": 1 + "stueckzahl": 1 }, { "artikel": "CAD - BODENSÄULE R 1\" - BODENPLATTE KPL.", "sivas_id": 821004200, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] } @@ -273,67 +296,78 @@ "artikel": "KLEMMRING MIT MUFFE EINFACH KPL.", "sivas_id": 825002019, "farbig": false, - "menge": 2 + "stueckzahl": 1, + "anzahl_vorgabe": 2 }, { "artikel": "KLEMMRING MIT MUFFE DOPPELT 90 Grad, KPL.", "sivas_id": 825002009, "farbig": false, - "menge": 2 + "stueckzahl": 1, + "anzahl_vorgabe": 2 }, { "artikel": "KLEMMRING MIT MUFFE DOPPELT 180 Grad, KPL.", "sivas_id": 825002008, "farbig": false, - "menge": 2 + "stueckzahl": 1, + "anzahl_vorgabe": 2 }, { "artikel": "KLEMMRING M. MUFFE DREIFACH 90 Grad/180 Grad KPL.", "sivas_id": 825002007, "farbig": false, - "menge": 2 + "stueckzahl": 1, + "anzahl_vorgabe": 2 }, { "artikel": "KLEMMRING MIT LASCHE KPL. ZUSAMMENBAUZEICHNUNG", "sivas_id": 825002020, "farbig": false, - "menge": 2 + "stueckzahl": 1, + "anzahl_vorgabe": 2 }, { "artikel": "QUERSCHELLE F. 1\" UND 2\" ROHR GESCHW./VZ. M. 4X M10X30 KPL.", "sivas_id": 825002022, "farbig": false, - "menge": 2 + "stueckzahl": 1, + "anzahl_vorgabe": 2 }, { "artikel": "KREUZSCHELLE F. 2\" UND 1\" ROHR SCHWENKBAR 360 Grad", "sivas_id": 922083009, "farbig": false, - "menge": 2 + "stueckzahl": 1, + "anzahl_vorgabe": 2 }, { "artikel": "HALTEARM FÜR BODENSÄULE R 2\" 1-ARMIG KPL.", "sivas_id": 821004051, "farbig": true, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "HALTEARM FÜR BODENSÄULE R 2\" 2-ARMIG 90 Grad KPL.", "sivas_id": 821004054, "farbig": true, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "HALTEARM FÜR BODENSÄULE R 2\" 2-ARMIG 180 Grad KPL.", "sivas_id": 821004052, "farbig": true, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 }, { "artikel": "HALTEARM FÜR BODENSÄULE R 2\" 3-ARMIG KPL.", "sivas_id": 821004053, "farbig": true, - "menge": 1 + "stueckzahl": 1, + "anzahl_vorgabe": 1 } ], "konfigurationen": [ @@ -353,7 +387,7 @@ "oben": [ { "artikel": "KLEMMRING MIT MUFFE EINFACH KPL.", - "menge": 2 + "anzahl": 2 } ], "unten": [] @@ -366,13 +400,13 @@ "oben": [ { "artikel": "KLEMMRING MIT MUFFE DOPPELT 90 Grad, KPL.", - "menge": 2 + "anzahl": 2 } ], "unten": [ { "artikel": "QUERSCHELLE F. 1\" UND 2\" ROHR GESCHW./VZ. M. 4X M10X30 KPL.", - "menge": 2 + "anzahl": 2 } ] } @@ -386,45 +420,49 @@ "geometrie_varianten": [ { "name": "WANDFLANSCH EINZELTEIL", + "dummy": "821006031.dwg", "teile": [ { "artikel": "WANDFLANSCH EINZELTEIL", "sivas_id": 821006031, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] }, { "name": "WINKEL 60X60X6X60", + "dummy": "821006042.dwg", "teile": [ { "artikel": "WINKEL 60X60X6X60", "sivas_id": 821006042, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] }, { "name": "WINKEL 60X60X6X300", + "dummy": "821006043.dwg", "teile": [ { "artikel": "WINKEL 60X60X6X300", "sivas_id": 821006043, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] }, { "name": "ROHRSCHELLE 1\" OBERTEIL", + "dummy": "825006009.dwg", "teile": [ { "artikel": "ROHRSCHELLE 1\" OBERTEIL", "sivas_id": 825006009, "farbig": false, - "menge": 1 + "stueckzahl": 1 } ] } @@ -432,29 +470,31 @@ "anbaugruppen": [ { "name": "Nylondübel 12x60 inkl. Holzschrauben", + "anzahl_vorgabe": 2, "teile": [ { "artikel": "HOLZSCHRAUB,10X70, 6KT DIN 571 VZ", "sivas_id": 911271027, "farbig": false, - "menge": 2 + "stueckzahl": 1 }, { "artikel": "NYLON - DUEBEL 12X60 (TYP S)", "sivas_id": 922013003, "farbig": false, - "menge": 2 + "stueckzahl": 1 } ] }, { "name": "HST M12X115X20", + "anzahl_vorgabe": 2, "teile": [ { "artikel": "DURCHSTECKANKER HST M12X115X20 WANDABH.", "sivas_id": 922021003, "farbig": false, - "menge": 2 + "stueckzahl": 1 } ] } @@ -466,7 +506,7 @@ "oben": [ { "artikel": "Nylondübel 12x60 inkl. Holzschrauben", - "menge": 1 + "anzahl": 2 } ], "unten": [] @@ -477,203 +517,11 @@ "oben": [ { "artikel": "HST M12X115X20", - "menge": 1 + "anzahl": 2 } ], "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/data/json/geruest_traeger.json b/data/json/geruest_traeger.json new file mode 100644 index 0000000..42c5385 --- /dev/null +++ b/data/json/geruest_traeger.json @@ -0,0 +1,193 @@ +{ + "Rohr-Gerüst-Träger": { + "id": "Traeger", + "titel": "Traeger", + "teileart": "Geruest Traeger", + "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, + "stueckzahl": 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, + "stueckzahl": 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, + "stueckzahl": 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, + "stueckzahl": 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, + "stueckzahl": 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, + "stueckzahl": 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, + "stueckzahl": 1 + } + ] + }, + { + "name": "RT 80/80 1\" mit 3 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 3 Muffen", + "sivas_id": 825144007, + "farbig": true, + "stueckzahl": 1 + } + ] + } + ] + } +} diff --git a/lang/de_DE.json b/lang/de_DE.json index 2f935b5..055680d 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -1003,13 +1003,14 @@ "gr-fehler-baugruppe": "\nGeruest: Baugruppe '%1' steht nicht in der Datendatei.", "gr-fehler-keine-varianten": "\nGeruest: Baugruppe '%1' hat keine Geometrie-Varianten.", "gr-fehler-dummy": "\nGeruest: Dummy-Baugruppe nicht gefunden: %1", + "gr-fehler-dummy-variante": "\nGeruest: Dummy der Variante nicht gefunden: %1 - verwende Dummy der Baugruppe (%2)", "gr-fehler-dcl": "Dialog geruest.dcl konnte nicht geladen werden.", "gr-dlg-kopf": "%1 konfigurieren", "gr-alert-laenge": "Laenge ungueltig: '%1' mm. Erlaubt: %2 bis %3 mm.", "gr-prompt-einfuegepunkt": "\nEinfuegepunkt waehlen: ", "gr-abgebrochen": "\nAbgebrochen.", "gr-fertig": "\nGeruest-Baugruppe '%1' eingefuegt (Block %2).", - "gr-alert-menge": "Ungueltige Stueckzahl. Erlaubt ist eine ganze Zahl ab 1; ein leeres Feld uebernimmt den Vorgabewert.", + "gr-alert-menge": "Ungueltige Anzahl. Erlaubt ist eine ganze Zahl ab 1; ein leeres Feld uebernimmt den Vorgabewert.", "gr-position-oben": "oben", "gr-position-unten": "unten", "gr-konfig-keine": "", diff --git a/lang/en_GB.json b/lang/en_GB.json index 95a93e9..2714170 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -1003,6 +1003,7 @@ "gr-fehler-baugruppe": "\nScaffold: assembly '%1' is not in the data file.", "gr-fehler-keine-varianten": "\nScaffold: assembly '%1' has no geometry variants.", "gr-fehler-dummy": "\nScaffold: dummy assembly not found: %1", + "gr-fehler-dummy-variante": "\nScaffold: dummy of the variant not found: %1 - using dummy of the assembly (%2)", "gr-fehler-dcl": "Dialog geruest.dcl could not be loaded.", "gr-dlg-kopf": "Configure %1", "gr-alert-laenge": "Invalid length: '%1' mm. Allowed: %2 to %3 mm.", diff --git a/tests/test_unit.lsp b/tests/test_unit.lsp index 23d0ef2..7c8c66e 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)) - ;; Vier Baugruppen: Rohrabhaenger, Saeulen (1 und 2 Zoll - ;; zusammengefuehrt), Wandbefestigung, Rohr-Geruest-Traeger - (tu-eq "json/geruest-baugruppen" 4 (length _daten)) + ;; Drei Bereiche: Rohrabhaenger, Saeulen (1 und 2 Zoll zusammengefuehrt), + ;; Wandbefestigung. Die Traeger liegen in geruest_traeger.json. + (tu-eq "json/geruest-baugruppen" 3 (length _daten)) ;; Baugruppe ueber das ASCII-Feld "id" finden (aeusserer Schluessel ;; traegt Umlaute bzw. Anfuehrungszeichen) (setq _bg nil) @@ -768,7 +768,7 @@ (progn (setq _var (ssg-json-get _bg "geometrie_varianten")) (setq _anb (ssg-json-get _bg "anbaugruppen")) - (tu-eq "json/geruest-varianten" 3 (length _var)) + (tu-eq "json/geruest-varianten" 4 (length _var)) (tu-eq "json/geruest-teileart" "Geruest Rohrabhaenger" (ssg-json-get _bg "teileart")) (tu-eq "json/geruest-dummy" "Rohrabhaenger_dummy.dwg" @@ -824,24 +824,24 @@ (tu-eq "geruest-id-string/str" "0_B10071" (geruest-id-string "0_B10071")) (tu-eq "geruest-id-string/nil" nil (geruest-id-string nil)) - ;; Einzelteil mit menge 2 -> Artikelnummer zweimal (ARTINR-Regel) + ;; Einzelteil mit stueckzahl 2 -> Artikelnummer zweimal (ARTINR-Regel) (setq _eintrag (ssg-json-parse - "{\"artikel\": \"X\", \"sivas_id\": 825002019, \"menge\": 2}")) - (tu-eq "geruest-artnr/menge2" '("825002019" "825002019") + "{\"artikel\": \"X\", \"sivas_id\": 825002019, \"stueckzahl\": 2}")) + (tu-eq "geruest-artnr/stueckzahl2" '("825002019" "825002019") (geruest-artikelnummern _eintrag)) (tu-eq "geruest-name/artikel" "X" (geruest-eintrag-name _eintrag)) ;; Benannte Gruppe -> teile rekursiv aufloesen, Mengen beachten (setq _gruppe (ssg-json-parse (strcat "{\"name\": \"Schraubenset\", \"teile\": [" - "{\"artikel\": \"A\", \"sivas_id\": 111, \"menge\": 1}," - "{\"artikel\": \"B\", \"sivas_id\": 222, \"menge\": 2}]}"))) + "{\"artikel\": \"A\", \"sivas_id\": 111, \"stueckzahl\": 1}," + "{\"artikel\": \"B\", \"sivas_id\": 222, \"stueckzahl\": 2}]}"))) (tu-eq "geruest-artnr/gruppe" '("111" "222" "222") (geruest-artikelnummern _gruppe)) (tu-eq "geruest-name/gruppe" "Schraubenset" (geruest-eintrag-name _gruppe)) - ;; Fehlendes menge-Feld -> 1 - (tu-eq "geruest-artnr/ohne-menge" '("333") + ;; Fehlendes stueckzahl-Feld -> 1 + (tu-eq "geruest-artnr/ohne-stueckzahl" '("333") (geruest-artikelnummern (ssg-json-parse "{\"artikel\": \"C\", \"sivas_id\": 333}"))) @@ -859,21 +859,62 @@ (tu-eq "geruest-teile-dwgs/vorhanden" (list _pfad) (geruest-teile-dwgs '("825002019" "999999999" "825002019"))) ) + ;; --- Anzahl-Vorgabe (Dialogfeld) vs. stueckzahl (wirklich geschrieben) --- + (tu-eq "geruest-anzahl-vorgabe/gruppe" 2 + (geruest-anzahl-vorgabe (ssg-json-parse + "{\"name\": \"G\", \"anzahl_vorgabe\": 2, \"teile\": [{\"sivas_id\": 1, \"stueckzahl\": 1}]}"))) + ;; stueckzahl ist KEINE Vorgabe fuer das Dialogfeld + (tu-eq "geruest-anzahl-vorgabe/stueckzahl-zaehlt-nicht" 1 + (geruest-anzahl-vorgabe (ssg-json-parse "{\"sivas_id\": 1, \"stueckzahl\": 3}"))) + (tu-eq "geruest-anzahl-vorgabe/ohne" 1 + (geruest-anzahl-vorgabe (ssg-json-parse "{\"name\": \"G\", \"teile\": []}"))) + ;; anzahl_vorgabe bestimmt nur die Vorbelegung, nicht den Satzinhalt: + ;; 3 Saetze a (1 Schraube + 1 Duebel) = 6 Nummern + (tu-eq "geruest-artikelnummern-n/anzahl-vorgabe" '("1" "2" "1" "2" "1" "2") + (geruest-artikelnummern-n (ssg-json-parse + "{\"name\": \"G\", \"anzahl_vorgabe\": 2, \"teile\": [{\"sivas_id\": 1, \"stueckzahl\": 1}, {\"sivas_id\": 2, \"stueckzahl\": 1}]}") + 3)) + ;; Einzelteil-Anbauteil: Anzahl x stueckzahl + (tu-eq "geruest-artikelnummern-n/einzelteil-stueckzahl" '("7" "7" "7" "7") + (geruest-artikelnummern-n (ssg-json-parse + "{\"artikel\": \"X\", \"sivas_id\": 7, \"stueckzahl\": 2, \"anzahl_vorgabe\": 5}") + 2)) + ;; Dummy, der zugleich Teile-DWG ist, faellt aus der Teileliste + (tu-eq "geruest-ohne-pfad/entfernt" '("b/2.dwg") + (geruest-ohne-pfad "A/1.DWG" '("a/1.dwg" "b/2.dwg"))) + (tu-eq "geruest-ohne-pfad/nil" '("a/1.dwg") + (geruest-ohne-pfad nil '("a/1.dwg"))) + ;; Dummy-Wahl: Variante gewinnt, fehlende Varianten-DWG -> Baugruppe + (setq _pfad (geruest-dummy-pfad "821006036.dwg")) + (if (and _pfad (findfile _pfad)) + (tu-eq "geruest-dummy-wahl/variante" "821006036.dwg" + (car (geruest-dummy-wahl + (ssg-json-parse "{\"dummy\": \"821006036.dwg\"}") + (ssg-json-parse "{\"dummy\": \"basis.dwg\"}")))) + ) + (tu-eq "geruest-dummy-wahl/fehlt" "basis.dwg" + (car (geruest-dummy-wahl + (ssg-json-parse "{\"dummy\": \"gibtsnicht_999.dwg\"}") + (ssg-json-parse "{\"dummy\": \"basis.dwg\"}")))) + (tu-eq "geruest-dummy-wahl/ohne" "basis.dwg" + (car (geruest-dummy-wahl + (ssg-json-parse "{\"name\": \"X\"}") + (ssg-json-parse "{\"dummy\": \"basis.dwg\"}")))) ;; --- Mengenfeld --- (tu-eq "geruest-zahl-p/ziffern" T (geruest-zahl-p "12")) (tu-eq "geruest-zahl-p/text" nil (geruest-zahl-p "1a")) (tu-eq "geruest-zahl-p/leer" nil (geruest-zahl-p "")) ;; Leeres Feld uebernimmt die JSON-Vorgabe, ungueltiges liefert nil - (tu-eq "geruest-menge-wert/leer" 2 (geruest-menge-wert "" 2)) - (tu-eq "geruest-menge-wert/zahl" 5 (geruest-menge-wert "5" 2)) - (tu-eq "geruest-menge-wert/null" nil (geruest-menge-wert "0" 2)) - (tu-eq "geruest-menge-wert/text" nil (geruest-menge-wert "abc" 2)) - (tu-eq "geruest-menge-wert/negativ" nil (geruest-menge-wert "-3" 2)) + (tu-eq "geruest-anzahl-wert/leer" 2 (geruest-anzahl-wert "" 2)) + (tu-eq "geruest-anzahl-wert/zahl" 5 (geruest-anzahl-wert "5" 2)) + (tu-eq "geruest-anzahl-wert/null" nil (geruest-anzahl-wert "0" 2)) + (tu-eq "geruest-anzahl-wert/text" nil (geruest-anzahl-wert "abc" 2)) + (tu-eq "geruest-anzahl-wert/negativ" nil (geruest-anzahl-wert "-3" 2)) - ;; --- Stueckzahl ersetzt die JSON-Menge (Einzelteil) --- - (tu-eq "geruest-artnr-n/einzelteil" '("825002019" "825002019" "825002019") - (geruest-artikelnummern-n _eintrag 3)) + ;; --- Einzelteil: Anzahl (Dialog) x stueckzahl (JSON, hier 2) --- + (tu-eq "geruest-artnr-n/einzelteil" 6 + (length (geruest-artikelnummern-n _eintrag 3))) ;; --- Gruppe: ganzes Set n-mal, Mengen INNERHALB bleiben erhalten --- (tu-eq "geruest-artnr-n/gruppe" '("111" "222" "222" "111" "222" "222") (geruest-artikelnummern-n _gruppe 2)) @@ -894,7 +935,7 @@ (setq _teile (ssg-json-parse (strcat "{\"name\": \"Set\", \"farbig\": true, \"teile\": [" "{\"artikel\": \"A\", \"sivas_id\": 111}," - "{\"artikel\": \"B\", \"sivas_id\": 222, \"menge\": 2}]}"))) + "{\"artikel\": \"B\", \"sivas_id\": 222, \"stueckzahl\": 2}]}"))) (tu-eq "geruest-paare/gruppe-erbt" '(("111" . T) ("222" . T) ("222" . T)) (geruest-teile-paare _teile nil)) (tu-eq "geruest-paare-n/gruppe" 6 (length (geruest-teile-paare-n _teile 2))) @@ -934,8 +975,8 @@ ;; die ganze Konfiguration verworfen) (setq _konfig (ssg-json-parse (strcat "{\"name\": \"K1\", \"oben\": [" - "{\"artikel\": \"Schraubenset\", \"menge\": 3}," - "{\"artikel\": \"unbekannt\", \"menge\": 1}]}"))) + "{\"artikel\": \"Schraubenset\", \"anzahl\": 3}," + "{\"artikel\": \"unbekannt\", \"anzahl\": 1}]}"))) (tu-eq "geruest-konfig-position" '(nil 3) (geruest-konfig-position _konfig "oben" _teile)) @@ -1172,18 +1213,21 @@ _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. + ;; Eigene Datei data/json/geruest_traeger.json: im Bereichs-Dropdown von + ;; GERUEST darf er nicht auftauchen, ueber geruest-traeger-daten muss er + ;; 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-datei" + (findfile (geruest-json-pfad "geruest_traeger.json"))) + (setq _traeger (geruest-baugruppe "Traeger" (geruest-traeger-daten))) (tu-true "geruest/traeger-vorhanden" _traeger) + (tu-nil "geruest/traeger-nicht-in-geruest-json" + (geruest-baugruppe "Traeger" (geruest-daten))) (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"))) @@ -1236,7 +1280,7 @@ (cons "laenge" "2000") (cons "teilefarbe" "RAL 7035 Lichtgrau") (cons "oben" (list (list (cons "artikel" "ROHRKLAMMER 1\" KPL. VERTIKAL") - (cons "menge" 2)))) + (cons "anzahl" 2)))) (cons "unten" nil))) (setq _pfad (vl-filename-mktemp "grtest" nil ".json")) (setq _f (open _pfad "w")) @@ -1256,8 +1300,8 @@ (ssg-json-get _zurueck "teilefarbe")) (tu-eq "geruest-schreiber/oben-artikel" "ROHRKLAMMER 1\" KPL. VERTIKAL" (ssg-json-get (car (ssg-json-get _zurueck "oben")) "artikel")) - (tu-eq "geruest-schreiber/oben-menge" 2 - (ssg-json-get (car (ssg-json-get _zurueck "oben")) "menge")) + (tu-eq "geruest-schreiber/oben-anzahl" 2 + (ssg-json-get (car (ssg-json-get _zurueck "oben")) "anzahl")) (tu-eq "geruest-schreiber/unten-leer" nil (ssg-json-get _zurueck "unten")) )