diff --git a/CLAUDE.md b/CLAUDE.md index 859235c..462a468 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,7 +113,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; 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) | +| `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`/`rand_min`/`rand_max`, Variante vor Baugruppe), Plan `geruest-traeger-streben-plan` -> (rand positionen): der Abstand zwischen zwei Streben ist IMMER genau `abstand`, beide Raender gleich (netto = k*abstand + 2*rand); gewaehlt wird die Strebenzahl, deren Rand am naechsten an `rand_min`..`rand_max` liegt (Gleichstand -> weniger Streben). Mit 500/100..250 geht das nur auf, wenn netto mod 500 = 0 oder in [200, 500) liegt (z.B. 1300 -> 150|500|500|150); sonst (1001..1199, unter 200 mm) liegt der Rand ausserhalb (1100 -> 300|500|300) - `geruest-traeger-rand-pruefen` zeigt dann eine Messagebox (ohne GUI: Konsole), der Traeger wird trotzdem eingefuegt. 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) | | `DinFormate.lsp` | DIN_FORMATE | Ersatz fuer das alte ACADSST-Makro `DINFORM.LSP`/`.DCL` (SSG2-Menue "DIN-FORMATE..."): fuegt einen DIN-Rahmen (A0-A3, A4 quer/hoch) und optional einen Schriftkopf (KOPF11, Sprachen DE/EN/FR/IT) per Dialog (`dcl/dinformate.dcl`) ein. Block-DWGs liegen flach in `cfg/rahmen/` (kopiert aus `\\infor-ln\SSG_Tools\ACADSST\KOEPFE` - nur die von DINFORM.LSP tatsaechlich referenzierten Dateien: `A0`/`A1`/`A2`/`A3`/`A4Q`/`A4H.DWG` + `Kopf11`/`Kopf11e`/`Kopf11f`/`Kopf11i.dwg`). Rahmen wird im Zeichenmassstab-Faktor eingefuegt, der Kopf im Faktor/100 (Kopf-DWG ist 100x groesser als die Rahmen-DWGs angelegt) - unveraendert aus dem Original-Massstabsschema uebernommen. Blockdefinitionen werden einmalig per `_.-INSERT ... _X 0` nachgeladen (`dinformate-block-laden`), falls noch nicht in der Zeichnung vorhanden. Lazy geladen ueber `(ssg-ensure "DinFormate")`, Menue: Werkzeuge > Din Formate. | | `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 e331874..e38fde2 100644 --- a/Lisp/GeruestInsert.lsp +++ b/Lisp/GeruestInsert.lsp @@ -1553,43 +1553,81 @@ (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) +;; Abweichung eines Randes vom erlaubten Bereich [rand-min, rand-max] +;; (0 = innerhalb). +(defun geruest-rand-abweichung (r rand-min rand-max) + (cond ((< r rand-min) (- rand-min r)) + ((> r rand-max) (- r rand-max)) + (T 0.0)) +) + +;; Querstreben-Plan: (rand positionen). Regel: der Abstand zwischen zwei +;; Streben ist IMMER genau abstand, beide Raender sind gleich: +;; netto = k * abstand + 2 * rand (k = Felder, k+1 Streben) +;; Gewaehlt wird das k, dessen Rand am naechsten am Bereich [rand-min, +;; rand-max] liegt (bei Gleichstand das mit weniger Streben). Weil der +;; Bereich schmaler ist als abstand, geht nicht jede Laenge auf: mit 500/ +;; 100..250 liegt der Rand genau dann im Bereich, wenn netto mod 500 = 0 oder +;; in [200, 500) ist - bei 1001..1199 mm oder unter 200 mm z.B. nicht. Der Plan +;; wird dann trotzdem geliefert, die Pruefung (geruest-rand-abweichung) und +;; die Meldung uebernimmt der Aufrufer. netto <= 0 -> nil. +(defun geruest-traeger-streben-plan (netto abstand rand-min rand-max + / k kmax r dev best-k best-r best-dev i erg) + (if (and netto (> netto 1e-6) abstand (> abstand 1e-6)) + (progn + (setq kmax (fix (+ (/ netto abstand) 1e-9)) k 0 best-k nil) + (while (<= k kmax) + (setq r (/ (- netto (* k abstand)) 2.0)) + (if (>= r -1e-9) + (progn + (setq dev (geruest-rand-abweichung r rand-min rand-max)) + ;; strikt kleiner: bei Gleichstand bleibt das kleinere k + (if (or (null best-k) (< dev (- best-dev 1e-6))) + (setq best-k k best-r (max r 0.0) best-dev dev)) + ) + ) + (setq k (1+ k)) + ) + (setq erg nil i best-k) (while (>= i 0) - (setq erg (cons (+ r (* i s)) erg)) + (setq erg (cons (+ best-r (* i abstand)) erg)) (setq i (1- i)) ) - erg + (list best-r erg) ) ) ) +;; Rand des Streben-Plans gegen [rand-min, rand-max] pruefen und bei +;; Abweichung den Benutzer informieren (Messagebox, ohne GUI auf die +;; Konsole). strebe = Ergebnis von geruest-traeger-strebe-cfg. +;; Rueckgabe: T = Rand im Bereich. +(defun geruest-traeger-rand-pruefen (netto strebe / plan txt) + (setq plan (geruest-traeger-streben-plan netto (nth 3 strebe) (nth 4 strebe) (nth 5 strebe))) + (if (and plan + (> (geruest-rand-abweichung (car plan) (nth 4 strebe) (nth 5 strebe)) 1e-6)) + (progn + (setq txt (ssg-textf "gr-tr-strebe-rand" + (list (geruest-mm-string netto) + (geruest-mm-string (car plan)) + (geruest-mm-string (nth 4 strebe)) + (geruest-mm-string (nth 5 strebe)) + (geruest-mm-string (nth 3 strebe)) + (itoa (length (cadr plan)))))) + (if (ssg-gui-p) (alert txt) (princ (strcat "\n" txt))) + nil + ) + T + ) +) + +;; Nur die Positionen der Querstreben (Abstand ab Linienanfang). +(defun geruest-traeger-streben (netto abstand rand-min rand-max) + (cadr (geruest-traeger-streben-plan netto abstand rand-min rand-max)) +) + ;; Querstreben-Konfiguration (Variante vor Baugruppe) als -;; (dummy laenge querlinie abstand-max rand-min rand-max) oder nil, wenn keine +;; (dummy laenge querlinie abstand rand-min rand-max) oder nil, wenn keine ;; "querstrebe" definiert ist. ;; dummy = DWG unter data/geruest (Basispunkt Strebenmitte, 30 mm laengs ;; X) oder nil @@ -1605,7 +1643,7 @@ (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") + '("laenge" "querlinie" "abstand" "rand_min" "rand_max") '(30.0 25.0 500.0 100.0 250.0))) ) ) @@ -1863,7 +1901,7 @@ (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) + ;; strebe = (dummy laenge querlinie abstand rand-min rand-max) (if strebe (foreach x (geruest-traeger-streben netto (nth 3 strebe) (nth 4 strebe) (nth 5 strebe)) (if strebe-pfad @@ -1969,6 +2007,9 @@ (if min-l (geruest-mm-string min-l) "0") (if max-l (geruest-mm-string max-l) "-"))))) (T + ;; Streben-Rand ausserhalb der Grenzen: informieren, aber trotzdem + ;; einfuegen (der Abstand zwischen den Streben bleibt immer exakt) + (if strebe (geruest-traeger-rand-pruefen netto strebe)) (setq werte (cons (cons "LAENGE" (geruest-mm-string netto)) werte-basis)) (ssg-start nil '(("OSMODE") ("ATTREQ") ("ATTDIA") ("ANGBASE") ("ANGDIR") ("AUNITS"))) diff --git a/data/geruest/400000782.dwg b/data/geruest/400000782.dwg new file mode 100644 index 0000000..7c2a7bc Binary files /dev/null and b/data/geruest/400000782.dwg differ diff --git a/data/geruest/821004200.dwg b/data/geruest/821004200.dwg index 148b0a3..d82726c 100644 Binary files a/data/geruest/821004200.dwg and b/data/geruest/821004200.dwg differ diff --git a/data/json/geruest.json b/data/json/geruest.json index cbbb946..d19f920 100644 --- a/data/json/geruest.json +++ b/data/json/geruest.json @@ -6,13 +6,10 @@ "dummy": "Rohrabhaenger_dummy.dwg", "attribute": { "LAENGE": { - "typ": "number", "min": 0, - "max": 6000, - "einheit": "mm" + "max": 6000 }, "TEILEFARBE": { - "typ": "auswahl", "optionen": [ "RAL7035", "RAL7030" @@ -225,13 +222,10 @@ "dummy": "821006051.dwg", "attribute": { "LAENGE": { - "typ": "number", "min": 0, - "max": 6000, - "einheit": "mm" + "max": 6000 }, "TEILEFARBE": { - "typ": "auswahl", "optionen": [ "RAL7035", "RAL7030" @@ -240,18 +234,6 @@ "frei_option": "Individuell" } }, - "einbauwinkel": { - "Platte": [ - 0, - 90 - ], - "Arm": [ - 0, - 90, - 180, - 270 - ] - }, "geometrie_varianten": [ { "name": "R 2\"", diff --git a/data/json/geruest_traeger.json b/data/json/geruest_traeger.json index 42c5385..19f0da3 100644 --- a/data/json/geruest_traeger.json +++ b/data/json/geruest_traeger.json @@ -5,7 +5,7 @@ "teileart": "Geruest Traeger", "querstrebe": { "dummy": "dummy_Strebe_30x4.dwg", - "abstand_max": 500, + "abstand": 500, "rand_min": 100, "rand_max": 250 }, diff --git a/lang/de_DE.json b/lang/de_DE.json index a7092e5..8b0bc08 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -1010,6 +1010,7 @@ "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.", + "gr-tr-strebe-rand": "Traeger %1 mm: Der Randabstand der Querstreben betraegt %2 mm und liegt ausserhalb des erlaubten Bereichs %3 bis %4 mm (Strebenabstand %5 mm, %6 Streben). Der Traeger wird trotzdem eingefuegt.", "in-yesno-keys": "Ja Nein", "in-keys-bereich": "Alle Auswahl", "in-keys-modus": "Teil Gesamt", diff --git a/lang/en_GB.json b/lang/en_GB.json index 3ade428..a37b090 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -1010,6 +1010,7 @@ "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.", + "gr-tr-strebe-rand": "Beam %1 mm: the edge distance of the cross braces is %2 mm, outside the allowed range %3 to %4 mm (brace spacing %5 mm, %6 braces). The beam is inserted anyway.", "in-yesno-keys": "Yes No", "in-keys-bereich": "All Selection", "in-keys-modus": "Part Whole", diff --git a/tests/test_unit.lsp b/tests/test_unit.lsp index 7f4d864..92b812d 100644 --- a/tests/test_unit.lsp +++ b/tests/test_unit.lsp @@ -1048,36 +1048,57 @@ (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)) + ;; Querstreben: Abstand IMMER genau 500, beide Raender gleich; gewaehlt + ;; wird die Strebenzahl mit dem Rand am naechsten an 100..250 + ;; (Gleichstand -> weniger Streben). Plan = (rand positionen). + ;; Im Bereich: + (tu-eqf "geruest-traeger-plan/1000" '(250.0 (250.0 750.0)) + (geruest-traeger-streben-plan 1000.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-plan/1200" '(100.0 (100.0 600.0 1100.0)) + (geruest-traeger-streben-plan 1200.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-plan/1300" '(150.0 (150.0 650.0 1150.0)) + (geruest-traeger-streben-plan 1300.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-plan/1500" '(250.0 (250.0 750.0 1250.0)) + (geruest-traeger-streben-plan 1500.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-plan/400" '(200.0 (200.0)) + (geruest-traeger-streben-plan 400.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-plan/500" '(250.0 (250.0)) + (geruest-traeger-streben-plan 500.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-plan/200" '(100.0 (100.0)) + (geruest-traeger-streben-plan 200.0 500.0 100.0 250.0)) + ;; Ausserhalb (netto mod 500 in (0, 200) oder netto < 200) - der Plan + ;; kommt trotzdem, der Abstand bleibt 500: + ;; 1100: Rand 300 (k=1) oder 50 (k=2), beide 50 daneben -> weniger Streben + (tu-eqf "geruest-traeger-plan/1100" '(300.0 (300.0 800.0)) + (geruest-traeger-streben-plan 1100.0 500.0 100.0 250.0)) + ;; 1050: Rand 275 (25 daneben) schlaegt 25 (75 daneben) + (tu-eqf "geruest-traeger-plan/1050" '(275.0 (275.0 775.0)) + (geruest-traeger-streben-plan 1050.0 500.0 100.0 250.0)) + ;; 1150: Rand 75 (25 daneben) schlaegt 325 (75 daneben) + (tu-eqf "geruest-traeger-plan/1150" '(75.0 (75.0 575.0 1075.0)) + (geruest-traeger-streben-plan 1150.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-plan/501" '(250.5 (250.5)) + (geruest-traeger-streben-plan 501.0 500.0 100.0 250.0)) + (tu-eqf "geruest-traeger-plan/kurz-150" '(75.0 (75.0)) + (geruest-traeger-streben-plan 150.0 500.0 100.0 250.0)) + (tu-nil "geruest-traeger-plan/null" + (geruest-traeger-streben-plan 0.0 500.0 100.0 250.0)) + ;; Abstand zwischen zwei Streben ist in jedem Fall exakt 500 + (foreach _l '(700.0 1100.0 1150.0 2345.0 5999.0) + (setq _rec (geruest-traeger-streben _l 500.0 100.0 250.0)) + (tu-true (strcat "geruest-traeger-streben/abstand-" (rtos _l 2 0)) + (vl-every '(lambda (a b) (equal (- b a) 500.0 1e-6)) + _rec (cdr _rec)))) + ;; Rand-Abweichung + (tu-eqf "geruest-rand-abweichung/innen" 0.0 (geruest-rand-abweichung 150.0 100.0 250.0)) + (tu-eqf "geruest-rand-abweichung/unten" 25.0 (geruest-rand-abweichung 75.0 100.0 250.0)) + (tu-eqf "geruest-rand-abweichung/oben" 50.0 (geruest-rand-abweichung 300.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) + ;; Ergebnis (dummy laenge querlinie abstand 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}}"))) @@ -1086,7 +1107,7 @@ (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}}"))) + (ssg-json-parse "{\"querstrebe\": {\"abstand\": 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))