[FIX] Lagerbereiche für GOH werden nun korrekt gezählt und in die yaml geschrieben

This commit is contained in:
Simon Hensch committed 2026-11-02 09:56:03 +01:00
1 parent d9043ebca5
commit b324362351
14 files changed
+98 -615

No files matched your search

+1 -1
View File
@@ -123,7 +123,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
| `GeruestInsert.lsp` | GERUEST, GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG, GERUEST_TRAEGER, GERUEST_TRAEGER_BESCHRIFTEN, OMNI_FAHRSTRECKE, OMNI_FAHRSTRECKE_BESCHRIFTEN | Geruest-Baugruppen aus `data/json/geruest.json` konfigurieren und einfuegen. **Ein Dialog je Bereich**: Rohrabhaenger / Saeulen / Wandbefestigung oeffnen NUR ueber ihren eigenen Menuebefehl (`geruest-starten id`, Dialogtitel aus dem ASCII-Feld `titel`); eine Umschaltung im Dialog gibt es nicht (DCL hat kein Reiter-Tile), `GERUEST` ohne Bereich zeigt nur einen Hinweis. Der Dialogstand beginnt je Aufruf frisch. 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. **Das Layout steht als Vorlage in `dcl/geruest.dcl`** (bzw. `dcl/geruest_traeger.dcl`); nur die datenabhaengigen Bloecke - ein `radio_button` je Variante (Key `v<i>`, `geruest-radio-key`/`-index`), Mengenfeld + Ankreuzfeld je Anbauteil - werden zur Laufzeit an Markerzeilen `//@NAME@` eingesetzt (`geruest-dcl-ersetzungen` -> `ssg-dcl-vorlage-fuellen` in ssg_core, Temp-Datei, nach `unload_dialog` geloescht). Grund: DCL kann Tiles weder zur Laufzeit erzeugen noch ausblenden, Radiobutton-Labels lassen sich per `set_tile` nicht aendern, und eine `list_box` kann keine Eingabefelder enthalten. Varianten bewusst als Radiobuttons statt `list_box`: BricsCAD zeichnet die Listenspalte nur halb so breit, und ein `tabs`-Wert passt nur schrift-/skalierungsabhaengig. Inhalt: Basis-Variante aus `geometrie_varianten` (Radiobuttons, siehe oben), **Winkel Platte** (0/90 Grad, `*geruest-winkel-werte*`): Ausrichtung der Anbauteile zur Basis - die Teile-DWGs aus oben/unten/sonstiges werden um diesen Winkel um Z gedreht in den Block eingefuegt, Basis und Dummy bleiben ungedreht (`geruest-teile-dwgs-rot`; in Konfigurationen als echter Wert `winkel_platte`, kein Block-Attribut), Laenge (gegen `attribute.Laenge` min/max geprueft, Retry-Schleife), Farbe (`attribute.Teilefarbe`, Freitext bei `frei_option`) und **eine Befestigungsspalte** "Befestigung oben und unten" mit allen `anbaugruppen.befestigung` - die Anzahl ist die GESAMTanzahl je Teil (oben und unten zusammen; Tile-Keys `b<i>`/`bm<i>`, Zustand `*geruest-dlg-bef*`). Unter jedem Teil (auch in Sonstiges) zeigt eine Textzeile "Art.-Nr. ..." die Artikelnummer(n) (`geruest-artnr-anzeige`: Einzelteil -> `sivas_id`, Gruppe -> eindeutige Nummern der Teile; DCL kennt keine Schriftgroesse, darum normale Groesse in eigener Zeile). `anbaugruppen` ist ein Objekt mit zwei Listen: `befestigung` (Befestigungsspalte) und `sonstiges` (Teile, die weder oben noch unten sitzen, z.B. die Saeulen-Haltearme) - letztere bekommen eine eigene Zeile darunter (nur wenn nicht leer), in ARTINR/BEZEICHNUNG nach "unten" als "sonstiges" (`geruest-anbau-liste`; ein altes flaches Array gilt als `befestigung`). **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 (`befestigung`/`sonstiges`, dazu `winkel_platte`) heisst der gespeicherte Dialogwert `anzahl`. Aeltere Konfigurationen mit getrennten `oben`/`unten`-Listen laden weiter: deren Mengen werden zur Gesamtanzahl addiert (`geruest-konfig-befestigung`), Sonstiges-Teile darin still in die Sonstiges-Zeile umgehaengt (`geruest-konfig-sonstiges`); beim naechsten Speichern steht alles im neuen Format. 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. **Geaenderte Konfiguration**: beim Anwenden wird der Dialogstand als VergleichsbasLine truncated
| `KettenFoerderer.lsp` | KETTENFOERDERER, KF_EDIT, KF_KS_PRUEFEN | Kettenfoerderer/Schraegfoerderer Stahl: baut aus `KF_UM_<winkel>` -> `KF_LAENGE` -> `KF_AN_<winkel>` (je KS_AUS auf KS_EIN) plus der Draufsicht `KF_2D` EINEN Block `KF_<n>`. Daten `data/json/kettenfoerderer.json`, Dialog `dcl/kettenfoerderer.dcl`. **Geometrie**: die Bausteine sind in der XY-Ebene gezeichnet (Hoehe = Y), werden aber AUFGERICHTET eingebaut `Rz(basis)*Rx(90)*Rz(eigen)` (`kf-matrix-aufrecht`) - die Hoehe laeuft in **Z**; dafuer `insert-block-ks-matrix` (freie 3x3-Rotation) in ssg_ks_insert.lsp. Die Neigung (26/30 Grad) ist KEIN Rechenparameter: sie steckt in den Varianten-Bloecken, der Einbauwinkel jedes Folgebausteins wird zur Laufzeit aus der RICHTUNG des KS_AUS seines Vorgaengers gemessen (`ks-xy-winkel`/`kf-hz-folge`) - keine gepflegte Winkeltabelle. `KF_LAENGE` wird in X skaliert, die Einbauhoehe H bestimmt seine Laenge ueber die Hoehenbilanz (`kf-laenge-berechnen`). `KF_2D` liegt DECKUNGSGLEICH mit der Kette (KS_EIN/KS_AUS auf denen von Umlenkung/Antrieb), ist flach gezeichnet, nur um die Steigung geneigt und auf die Schraeglaenge skaliert. **Attribut-Schema** `*kf-attrib-defs-liste*` ist EIGENSTAENDIG und bewusst NICHT von `ssg-strecke-attrib-defs` abgeleitet (sonst ~24 geerbte VF-Tags am Block); die Reihenfolge folgt dem Sivas-Merkmalstamm. FOERDERERTYP = Bauart im Klartext, WINKEL = nackte Zahl 26/30 (der Klartext mit Gradzeichen entsteht erst ueber `[kf_typ_anzeige]` in cfg/sivas.cfg, damit Attributwerte ASCII bleiben); kein TEILEART (Festwert `KF_TEILEART` im Export). Alle Auswahllisten stehen mit ihren Sivas-Optionstexten in der JSON. **Das `KF_`-Praefix ist wie `GR_` nicht kosmetisch**: `SSG_BLOCKEDIT` haelt JEDEN Block mit TEILEART-Attribut fuer ein Omniflo-Element, darum steht ein `KF_*`-Zweig VOR dem Omniflo-Zweig (Doppelklick -> KF_EDIT, der die vorgewaehlte Auswahl nutzt und nur echte `KF_<n>` zulaesst - die Bausteine `KF_UM_26`, `KF_2D` usw. tragen dasselbe Praefix). **Die Blocknummer wird ueber die Blocktabelle vergeben** (`kf-naechste-nummer` ueberspringt jede Nummer mit vorhandener Block-DEFINITION, wie bei `GF_n`/`VF_n`): nur ueber die Referenzen im Modell zu zaehlen war ein realer Fehler - `KF_EDIT` loescht den alten Block, die Definition lebt aber weiter, `_.-BLOCK` traf auf den vorhandenen Namen, die "Neu definieren?"-Abfrage verschluckte die Folge-Eingaben, und die Einzelteile blieben lose liegen ("Block aufgeloest"). **Sivas-Export** (`[kettenfoerderer]` in cfg/sivas.cfg, `build_kettenfoerderer_details` in export_sivas.py): baugleiche Foerderer werden zu EINER Zeile zusammengefasst (`kettenfoerderer_signature`), die Gruppengroesse traegt Merkmal 353 (entsteht erst aus der Gruppierung, daher Code); Farbe (354) und Antriebsmotor (355) sind ZWEI Merkmale, und jedes merkmalbildende Attribut steht auch in der Signatur, sonst verschmelzen unterschiedlich ausgefuehrte Foerderer. Reine Kerne in `tests/test_unit.lsp` (`tu-tests-kf`); das Modul wird in der MNL vorgeladen, Laufzeit-Messung ueber den dbg-Schalter `kf-zeit` |
| `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) |
| `LagerInsert.lsp` | LG_GESCHOSS, LG_GESCHOSS_AKTIV, LG_GESCHOSS_KOPIEREN, LG_BEREICH, LG_REIHE, LG_GANG, LG_EDIT, LG_REGALE, LAGER_EXPORT, LAGER_HAND_YAML | Lagerplanung GOH-Buehnenlager -> RFQ-YAML (Phase 0+1: Mengen, 2D; Konzept/Schema/YAML-Zuordnung in `doc/plan/lager_rfq.md`). Bloecke `LG_GESCHOSS` (Kopfsymbol, XDATA `SSG_LG` `kontur` -> Belagskontur), `LG_BEREICH` (Kontur + Parameter, fuellt sich selbst), `LG_REIHE_<L>_<T>`/`LG_GANG_<L>_<B>_<BELAG>` (Definition je Geometrie wiederverwendet, Werte in den Attributen der Referenz; Kinder tragen XDATA `bereich`; der Belag steht im Gang-Blocknamen, weil die Definition seine Schraffur enthaelt - Muster aus `lager.json belag_schraffur`, per `vla-AddHatch` auf Layer 0/VONBLOCK, `hallenboden` ohne; BricsCAD-`iso.pat` kennt kein `NET`, Gitterrost = `GRID`). Alle tragen `ID`, `GESCHOSS`, `LAYER`. Blockdefinitionen per `entmake` (BLOCK...ENDBLK), Einfuegen per `vla-InsertBlock` in WCS - kein `_.-BLOCK`/`_.INSERT`. **Attribut-Tags haben gemischte Schreibweise** (`HOEHE_BELAG_mm`) - beim Setzen ueber `vla-get-TagString` daher case-insensitiv zuordnen (`lg-wert-fuer-tag`), sonst bleiben diese Attribute still leer (realer Fehler beim Bau). Layer je Geschoss = Basis aus `cfg/layer.cfg [lager]` + `_G<nr>`; `LG_GESCHOSS_AKTIV` friert die uebrigen (2D-Grundrisse liegen uebereinander), aktives Geschoss als `vlax-ldata` (Dictionary `SSG_LAGER`). Geschosszuordnung `lg-geschoss-fuer-punkt-kern`: eine Kontur -> eindeutig, mehrere nur ueber Z unterscheidbar, wenn die Konturen auf verschiedenen Hoehen liegen (3D), sonst nil. Jede Kontur gehoert genau einem Block (vergebene Kontur wird kopiert). Auto-Fuellung `lg-fuellung-berechnen` (reiner Kern, Muster Reihe|Gang|Reihe Ruecken an Ruecken bzw. Reihe|Gang, nur volle Module, Streifen an Unter-/Mittel-/Oberkante gegen die Kontur geschnitten, Quergaenge ausgerichtet und nicht am Reihenende); Bereichs-Edit = Neuaufbau aller Kinder. **Randgaenge** `RANDGANG_N/O/S/W_mm` (Nord = +Y Welt) laufen entlang der echten Konturkanten (`lg-randgang-streifen`, Himmelsrichtung der Aussennormale ueber `lg-kompass`, auch L-Form; Ecken: N/S besitzen sie - konvex O/W kuerzen, einspringend N/S verlaengern) und werden wie manuelle Gaenge (`LG_GANG`, `QUELLE=manuell`, Kern `lg-gang-einfuegen`; per Linie oder Option `Rechteck` = Flaeche mit dem echten BricsCAD-Befehl RECHTECK gezeichnet, inkl. aller seiner Optionen (`lg-rechteck-zeichnen`: `_.RECTANG` + `(command pause)`-Schleife bei CMDECHO 1, Polylinie danach ueber `lg-rechteck-ecken-aus-poly` gelesen und geloescht; nur 4 Ecken ohne Boegen, sonst Meldung), Breite/Lage aus dem Rechteck ueber `lg-gang-aus-ecken`, Schleife `lg-linien-schleife` mit `rechteck-fn`) als **Sperrflaechen** aus Reihen/Haupt-/Quergaengen ausgeschnitten (`ssg-poly-band-x`). **Von Hand Gesetztes loest KEINE Neuberechnung aus**: `LG_REIHE`/`LG_GANG` (`lg-manuell-einfuegen`) und das Bearbeiten einer Reihe/eines Gangs (`lg-linie-neu-aufbauen-sperre`) schneiden nur die eigene Flaeche aus den rangniedrigeren Objekten heraus (`lg-sperre-anwenden`, reiner Kern `lg-linie-zuschnitt`; Rang `lg-quelle-rang`: auto < auto_geaendert < manuell) - frueher fuellte ein manueller Gang den ganzen Bereich neu, dabei kamen geloeschte Objekte zurueck und geaenderte wurden ersetzt. Die ausdrueckliche Neuberechnung (`lg-bereich-fuellen`, Bereich bearbeiten) entfernt nur `QUELLE=auto`; `manuell`/`auto_geaendert`-Kinder und unverknuepfte manuelle Objekte in der Kontur (`lg-manuelle-in-kontur`) bleiben und sperren ihre Flaeche. `lg-blockdef` ergaenzt bei Altbestand fehlende ATTDEFs (Neudefinition + `_.ATTSYNC`). `LAGER_EXPORT` schreibt `<dwg>_lager_raw.json` (eigener JSON-Schreiber `lg-json-*`), zaehlt `goh_rack` ueber die eigene Erkennung `lg-racks-sammeln`/`lg-racks-finden` mit (parametrischer BricsCAD-Block: Name ueber `getpropertyvalue "EffectiveName"`, Parameter `Laenge`/`Ebenen` als MCAD-Eigenschaft `<Name>~MCAD` vor dynamischer Eigenschaft vor Attribut vor ATTDEF-Vorgabe, Einheit -> mm per `lg-zahl-einheit`; auch in assoziativen Arrays, MINSERT-Rastern und verschachtelten Bloecken, Transformationen `lg-insert-tf`/`lg-tf-verketten`; Ergebnis je Rack `(name laenge ebenen mitte top-ent)`, Zugriff `lg-rk-*`; Befehl `LG_REGALE` (Menue Lager -> Regale zaehlen) zeigt Anzahl, Laenge und Laenge x Ebenen je Geschoss in der Befehlszeile, reiner Kern `lg-racks-auswerten`) und ruft `lib/lager_yaml_export.py` ueber `export:run-python`. Vorgaben aus `data/json/lager.json`. Dialoge `dcl/lager.dcl` ueber den generischen Treiber `lg-dialog` (Feldlisten `*lg-felder-*`, Konsolen-Rueckfall `lg-konsole`, ohne GUI Vorgaben). **Geschoss kopieren** (`LG_GESCHOSS_KOPIEREN`, Dialog `lg_geschoss_kopie`, Kern `lg-geschosse-kopieren`): Quelle (Vorgabe oberstes Geschoss, Erweitern G3 -> G4), Anzahl, Geschosshoehe je Kopie, Belag, Versatz X/Y je Kopie (0 = deckungsgleich; 3D-Zeichnung zusaetzlich +Z). Kein BricsCAD-KOPIEREN (XDATA-Verweise zeigten aufs Original): jedes Objekt entsteLine truncated
| `LagerInsert.lsp` | LG_GESCHOSS, LG_GESCHOSS_AKTIV, LG_GESCHOSS_KOPIEREN, LG_BEREICH, LG_REIHE, LG_GANG, LG_EDIT, LG_REGALE, LAGER_EXPORT, LAGER_HAND_YAML | Lagerplanung GOH-Buehnenlager -> RFQ-YAML (Phase 0+1: Mengen, 2D; Konzept/Schema/YAML-Zuordnung in `doc/plan/lager_rfq.md`). Bloecke `LG_GESCHOSS` (Kopfsymbol, XDATA `SSG_LG` `kontur` -> Belagskontur), `LG_BEREICH` (Kontur + Parameter, fuellt sich selbst), `LG_REIHE_<L>_<T>`/`LG_GANG_<L>_<B>_<BELAG>` (Definition je Geometrie wiederverwendet, Werte in den Attributen der Referenz; Kinder tragen XDATA `bereich`; der Belag steht im Gang-Blocknamen, weil die Definition seine Schraffur enthaelt - Muster aus `lager.json belag_schraffur`, per `vla-AddHatch` auf Layer 0/VONBLOCK, `hallenboden` ohne; BricsCAD-`iso.pat` kennt kein `NET`, Gitterrost = `GRID`). Alle tragen `ID`, `GESCHOSS`, `LAYER`. Blockdefinitionen per `entmake` (BLOCK...ENDBLK), Einfuegen per `vla-InsertBlock` in WCS - kein `_.-BLOCK`/`_.INSERT`. **Attribut-Tags haben gemischte Schreibweise** (`HOEHE_BELAG_mm`) - beim Setzen ueber `vla-get-TagString` daher case-insensitiv zuordnen (`lg-wert-fuer-tag`), sonst bleiben diese Attribute still leer (realer Fehler beim Bau). Layer je Geschoss = Basis aus `cfg/layer.cfg [lager]` + `_G<nr>`; `LG_GESCHOSS_AKTIV` friert die uebrigen (2D-Grundrisse liegen uebereinander), aktives Geschoss als `vlax-ldata` (Dictionary `SSG_LAGER`). Geschosszuordnung `lg-geschoss-fuer-punkt-kern`: eine Kontur -> eindeutig, mehrere nur ueber Z unterscheidbar, wenn die Konturen auf verschiedenen Hoehen liegen (3D), sonst nil. Jede Kontur gehoert genau einem Block (vergebene Kontur wird kopiert). Auto-Fuellung `lg-fuellung-berechnen` (reiner Kern, Muster Reihe|Gang|Reihe Ruecken an Ruecken bzw. Reihe|Gang, nur volle Module, Streifen an Unter-/Mittel-/Oberkante gegen die Kontur geschnitten, Quergaenge ausgerichtet und nicht am Reihenende); Bereichs-Edit = Neuaufbau aller Kinder. **Randgaenge** `RANDGANG_N/O/S/W_mm` (Nord = +Y Welt) laufen entlang der echten Konturkanten (`lg-randgang-streifen`, Himmelsrichtung der Aussennormale ueber `lg-kompass`, auch L-Form; Ecken: N/S besitzen sie - konvex O/W kuerzen, einspringend N/S verlaengern) und werden wie manuelle Gaenge (`LG_GANG`, `QUELLE=manuell`, Kern `lg-gang-einfuegen`; per Linie oder Option `Rechteck` = Flaeche mit dem echten BricsCAD-Befehl RECHTECK gezeichnet, inkl. aller seiner Optionen (`lg-rechteck-zeichnen`: `_.RECTANG` + `(command pause)`-Schleife bei CMDECHO 1, Polylinie danach ueber `lg-rechteck-ecken-aus-poly` gelesen und geloescht; nur 4 Ecken ohne Boegen, sonst Meldung), Breite/Lage aus dem Rechteck ueber `lg-gang-aus-ecken`, Schleife `lg-linien-schleife` mit `rechteck-fn`) als **Sperrflaechen** aus Reihen/Haupt-/Quergaengen ausgeschnitten (`ssg-poly-band-x`). **Von Hand Gesetztes loest KEINE Neuberechnung aus**: `LG_REIHE`/`LG_GANG` (`lg-manuell-einfuegen`) und das Bearbeiten einer Reihe/eines Gangs (`lg-linie-neu-aufbauen-sperre`) schneiden nur die eigene Flaeche aus den rangniedrigeren Objekten heraus (`lg-sperre-anwenden`, reiner Kern `lg-linie-zuschnitt`; Rang `lg-quelle-rang`: auto < auto_geaendert < manuell) - frueher fuellte ein manueller Gang den ganzen Bereich neu, dabei kamen geloeschte Objekte zurueck und geaenderte wurden ersetzt. Die ausdrueckliche Neuberechnung (`lg-bereich-fuellen`, Bereich bearbeiten) entfernt nur `QUELLE=auto`; `manuell`/`auto_geaendert`-Kinder und unverknuepfte manuelle Objekte in der Kontur (`lg-manuelle-in-kontur`) bleiben und sperren ihre Flaeche. `lg-blockdef` ergaenzt bei Altbestand fehlende ATTDEFs (Neudefinition + `_.ATTSYNC`). `LAGER_EXPORT` schreibt `<dwg>_lager_raw.json` (eigener JSON-Schreiber `lg-json-*`; Geschosse, Bereiche, Reihen, Gaenge) und ruft `lib/lager_yaml_export.py` ueber `export:run-python`. Befehl `LG_REGALE` (Menue Lager -> Regale zaehlen) zaehlt die Regalreihen `LG_REIHE_*` (Anzahl, Laenge, Laenge x Haengeebenen je Geschoss aus den Attributen GESCHOSS/LAENGE/HAENGEEBENEN, reine Kerne `lg-reihe-eintrag`/`lg-reihen-auswerten`). **Der parametrische BricsCAD-Block `goh_rack` wird nicht mehr unterstuetzt** (veraltet, 2026-10-30 aus Zaehlung, Export und Geschoss-Kopie entfernt). Vorgaben aus `data/json/lager.json`. Dialoge `dcl/lager.dcl` ueber den generischen Treiber `lg-dialog` (Feldlisten `*lg-felder-*`, Konsolen-Rueckfall `lg-konsole`, ohne GUI Vorgaben). **Geschoss kopieren** (`LG_GESCHOSS_KOPIEREN`, Dialog `lg_geschoss_kopie`, Kern `lg-geschosse-kopieren`): Quelle (Vorgabe oberstes Geschoss, Erweitern G3 -> G4), Anzahl, Geschosshoehe je Kopie, Belag, Versatz X/Y je Kopie (0 = deckungsgleich; 3D-Zeichnung zusaetzlich +Z). Kein BricsCAD-KOPIEREN (XDATA-Verweise zeigten aufs Original): jedes Objekt entsteht ueber die normalen Einfuegefunktionen neu (`lg-geschoss-anlegen`, `lg-bereich-block-anlegen` = Bereich ohne Fuellung, `lg-linie-einfuegen`), Kinder 1:1 inkl. `auto_geaendert`/manuell, kein Neufuellen; Belaege gleich dem Quell-Geschossbelag folgen dem neuLine truncated
| `LagerPruefung.lsp` | LG_REGELN | Regelprofile der Lagerplanung: `cfg/regelwerk/<LAND>.json` laden, `erbt_von` aufloesen (`lg-profil-mischen`), je Regel den STRENGSTEN Wert aller zutreffenden Quellen (`lg-regel-aufloesen`: `art` min/max/wert, `bedingung` gegen einen Kontext - fehlt der Schluessel, konservativ einbezogen -, `tabelle` + `tabellen_schluessel`) mit Protokoll. Jede Pruefregel der Lagerplanung wird genau hier implementiert (Python rendert nur). Alle Startwerte `verifiziert: false` |
| `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). |
+46 -415
View File
@@ -11,8 +11,6 @@
;; LG_REIHE_<L>_<T> Regalreihe (Rechteck L x T + Schienenlinie)
;; LG_GANG_<L>_<B>_<BELAG> Gang/Quergang/Randgang (Rechteck L x B, Schraffur
;; je Belag aus lager.json belag_schraffur)
;; goh_rack parametrischer BricsCAD-Block (Bestand), wird als
;; Regalreihe mitgezaehlt (lg-racks-sammeln)
;;
;; Befehle: LG_GESCHOSS, LG_GESCHOSS_AKTIV, LG_GESCHOSS_KOPIEREN, LG_BEREICH,
;; LG_REIHE, LG_GANG, LG_EDIT, LG_REGALE, LAGER_EXPORT, LAGER_HAND_YAML
@@ -132,16 +130,6 @@
";")
)
;; Haengeebenen auf n Ebenen begrenzen (goh_rack kennt nur die Anzahl):
;; die obersten n der Vorgabe. Fehlen Ebenen in der Vorgabe, bleibt es bei
;; dem, was da ist.
(defun lg-haengeebenen-n (s n / ebenen erg i)
(setq ebenen (lg-haengeebenen-parse s) erg nil i 0)
(while (and ebenen (< i n))
(setq erg (cons (car ebenen) erg) ebenen (cdr ebenen) i (1+ i)))
(lg-haengeebenen-string (reverse erg))
)
;; Feldwert pruefen/normalisieren. art: "mm" (Zahl >= 0), "mm_leer" (wie mm,
;; leer erlaubt), "int" (ganze Zahl >= 1), "int0" (>= 0), "grad" (beliebige
;; Zahl), "mm_vz" (mm mit Vorzeichen, z.B. Versatz), "text", "ebenen"
@@ -1427,261 +1415,14 @@
)
;; ============================================================
;; GOH_RACK-ERKENNUNG (lg-racks-sammeln, Befehl LG_REGALE)
;; REGALE ZAEHLEN (LG_REGALE)
;; ============================================================
;; goh_rack ist ein parametrischer BricsCAD-Block (MCAD-Parametrik), KEIN
;; AutoCAD-Dynamikblock: seine Referenzen tragen einen anonymen Namen
;; ("*U29"), IsDynamicBlock ist FALSE, und der echte Name sowie die
;; Parameter stehen nur in den Objekteigenschaften:
;; (getpropertyvalue ent "EffectiveName") -> "goh_rack"
;; (getpropertyvalue ent "Laenge~MCAD") -> "7187.52 mm"
;; Gefunden werden Racks direkt im Modellbereich, in assoziativen Arrays
;; (anonymer Block mit Referenzen), in MINSERT-Rastern und in beliebig
;; verschachtelten Bloecken (bis *lg-rack-max-tiefe*). Blockname und
;; Parameternamen aus lager.json "goh_rack".
;; Ergebnis je Rack: (name laenge-mm ebenen mitte top-ent), Zugriff ueber
;; lg-rk-*. top-ent = oberstes INSERT im Modellbereich, in dem das Rack
;; steckt (bei einem direkt eingefuegten Rack es selbst) - ueber dessen
;; Layer _G<nr> ordnet lg-rack-geschoss das Geschoss zu.
(setq *lg-rack-max-tiefe* 8)
(defun lg-rk-name (r) (nth 0 r))
(defun lg-rk-laenge (r) (nth 1 r))
(defun lg-rk-ebenen (r) (nth 2 r))
(defun lg-rk-mitte (r) (nth 3 r))
(defun lg-rk-top (r) (nth 4 r))
;; Reiner Kern: Zahl aus einem Parameterwert. MCAD-Parameter kommen als
;; Text mit Einheit ("700 mm", "71.8752 cm", "12.9 m") - auf mm umgerechnet;
;; ohne Einheit unveraendert. Unbekannte Einheit/kein Zahlanfang -> nil.
(defun lg-zahl-einheit (v / s i c ziffern zahl rest faktor)
(cond
((numberp v) (float v))
((= (type v) 'STR)
(setq s (vl-string-translate "," "." (vl-string-trim " \t\r\n" v))
i 1 ziffern "")
(while (and (<= i (strlen s))
(setq c (substr s i 1))
(or (wcmatch c "#") (member c '("." "-" "+"))))
(setq ziffern (strcat ziffern c) i (1+ i)))
(setq zahl (if (/= ziffern "") (distof ziffern 2))
rest (strcase (vl-string-trim " \t" (substr s i)))
faktor (cdr (assoc rest '(("" . 1.0) ("MM" . 1.0) ("CM" . 10.0) ("DM" . 100.0) ("M" . 1000.0)))))
(if (and zahl faktor) (* zahl faktor)))
(T nil))
)
;; Reiner Kern: ein echter Blockname (nicht leer, nicht anonym "*U..").
(defun lg-name-brauchbar-p (s)
(if (and (= (type s) 'STR) (/= s "") (/= (substr s 1 1) "*")) T)
)
;; Objekteigenschaft lesen, nil wenn es sie nicht gibt.
(defun lg-prop (ent name / r)
(setq r (vl-catch-all-apply 'getpropertyvalue (list ent name)))
(if (vl-catch-all-error-p r) nil r)
)
;; Name, unter dem eine Referenz gefuehrt wird: Objekteigenschaft
;; EffectiveName (auch fuer MCAD-Bloecke), sonst ActiveX-EffectiveName,
;; sonst DXF-Blockname.
(defun lg-rack-name (ent / n)
(cond
((lg-name-brauchbar-p (setq n (lg-prop ent "EffectiveName"))) n)
(T (lg-blockname ent)))
)
(defun lg-rack-p (ent / n)
(setq n (lg-rack-name ent))
(and n (= (strcase n) (strcase *lg-rack-suchname*)))
)
;; MCAD-Parameter (Kennung "<Name>~MCAD" in listallproperties, Gross-/
;; Kleinschreibung egal).
(defun lg-mcad-param (ent name / props id soll)
(setq props (vl-catch-all-apply 'listallproperties (list ent))
soll (strcase (strcat name "~MCAD")))
(if (and (not (vl-catch-all-error-p props)) (listp props)
(setq id (vl-some '(lambda (p / s)
(setq s (vl-princ-to-string p))
(if (= (strcase s) soll) s))
props)))
(lg-prop ent id))
)
;; Dynamische Blockeigenschaft (AutoCAD-Dynamikbloecke).
(defun lg-dyn-param (ent name / r)
(setq r (vl-catch-all-apply
'(lambda ( / obj)
(setq obj (vlax-ename->vla-object ent))
(if (and (vlax-property-available-p obj 'IsDynamicBlock)
(= :vlax-true (vla-get-IsDynamicBlock obj)))
(vl-some '(lambda (p)
(if (= (strcase (vla-get-PropertyName p)) (strcase name))
(vlax-variant-value (vla-get-Value p))))
(vlax-invoke obj 'GetDynamicBlockProperties))))))
(if (vl-catch-all-error-p r) nil r)
)
;; Parameterwert einer Referenz: MCAD-Parameter vor dynamischer
;; Eigenschaft vor Attribut vor konstanter ATTDEF-Vorgabe.
(defun lg-rack-param (ent name / w)
(cond
((setq w (lg-mcad-param ent name)) w)
((setq w (lg-dyn-param ent name)) w)
((setq w (lg-wert-fuer-tag name (ssg-attrib-read ent))) w)
((lg-wert-fuer-tag name
(mapcar '(lambda (ed) (cons (cdr (assoc 2 ed)) (cdr (assoc 1 ed))))
(vl-remove-if-not '(lambda (ed) (= (cdr (assoc 0 ed)) "ATTDEF"))
(lg-blockdef-objekte (cdr (assoc 2 (entget ent))))))))
)
)
;; --- Transformationen: tf = (ursprung x-achse y-achse z-achse), Achsen
;; mit Skalierung; p' = o + px*ax + py*ay + pz*az (rein, getestet) ---
(defun lg-v3 (p) (list (float (car p)) (float (cadr p)) (if (caddr p) (float (caddr p)) 0.0)))
(defun lg-v+ (a b) (mapcar '+ a b))
(defun lg-v* (v k) (mapcar '(lambda (x) (* x k)) v))
(defun lg-tf-id () '((0.0 0.0 0.0) (1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0)))
(defun lg-tf-vek (tf v / v3)
(setq v3 (lg-v3 v))
(lg-v+ (lg-v* (nth 1 tf) (car v3)) (lg-v+ (lg-v* (nth 2 tf) (cadr v3)) (lg-v* (nth 3 tf) (caddr v3))))
)
(defun lg-tf-pkt (tf p) (lg-v+ (car tf) (lg-tf-vek tf p)))
;; innen ist im System von aussen beschrieben -> Gesamttransformation
(defun lg-tf-verketten (aussen innen)
(list (lg-tf-pkt aussen (car innen)) (lg-tf-vek aussen (nth 1 innen))
(lg-tf-vek aussen (nth 2 innen)) (lg-tf-vek aussen (nth 3 innen)))
)
(defun lg-skal (s) (if (and s (not (equal s 0.0 1e-12))) s 1.0))
;; Transformation einer INSERT (entget-Liste) im System ihres Containers.
;; sp/zl = MINSERT-Spalte/-Zeile (0/0 = Basis). Beruecksichtigt Extrusion
;; (210), Drehung, Skalierung, Rasterabstaende (44/45, entlang der
;; gedrehten Achsen) und den Basispunkt der Blockdefinition.
(defun lg-insert-tf (ed sp zl / nor rot ax ay az xr yr o bp)
(setq nor (lg-v3 (cond ((cdr (assoc 210 ed))) ('(0.0 0.0 1.0))))
rot (cond ((cdr (assoc 50 ed))) (0.0)))
(if (equal nor '(0.0 0.0 1.0) 1e-12)
(setq ax '(1.0 0.0 0.0) ay '(0.0 1.0 0.0) az '(0.0 0.0 1.0))
(setq ax (lg-v3 (trans '(1.0 0.0 0.0) nor 0 T))
ay (lg-v3 (trans '(0.0 1.0 0.0) nor 0 T))
az (lg-v3 (trans '(0.0 0.0 1.0) nor 0 T))))
(setq xr (lg-v+ (lg-v* ax (cos rot)) (lg-v* ay (sin rot)))
yr (lg-v+ (lg-v* ax (- (sin rot))) (lg-v* ay (cos rot)))
o (lg-tf-pkt (list '(0.0 0.0 0.0) ax ay az) (cdr (assoc 10 ed)))
o (lg-v+ o (lg-v+ (lg-v* xr (* sp (cond ((cdr (assoc 44 ed))) (0.0))))
(lg-v* yr (* zl (cond ((cdr (assoc 45 ed))) (0.0)))))))
(setq xr (lg-v* xr (lg-skal (cdr (assoc 41 ed))))
yr (lg-v* yr (lg-skal (cdr (assoc 42 ed))))
az (lg-v* az (lg-skal (cdr (assoc 43 ed))))
bp (lg-v3 (cond ((cdr (assoc 10 (tblsearch "BLOCK" (cdr (assoc 2 ed)))))) ('(0.0 0.0 0.0)))))
;; der Basispunkt der Definition liegt auf dem Einfuegepunkt
(list (lg-v+ o (lg-v* (lg-tf-vek (list nil xr yr az) bp) -1.0)) xr yr az)
)
;; Bounding-Box (min max) eines Objekts in den Koordinaten seines
;; Containers, nil wenn nicht ermittelbar.
(defun lg-bbox (ent / r)
(setq r (vl-catch-all-apply
'(lambda ( / ll ur)
(vla-GetBoundingBox (vlax-ename->vla-object ent) 'll 'ur)
(list (lg-v3 (vlax-safearray->list ll)) (lg-v3 (vlax-safearray->list ur))))))
(if (vl-catch-all-error-p r) nil r)
)
;; Enthaelt die Blockdefinition (rekursiv) ein Rack? Gemerkt in
;; *lg-rack-cache*, Zirkelschutz ueber *lg-rack-pfad*, XRefs ausgenommen.
(defun lg-rack-enthaelt-p (bname tiefe / k vorh def res)
(setq k (strcase bname))
(cond
((setq vorh (assoc k *lg-rack-cache*)) (cdr vorh))
((or (>= tiefe *lg-rack-max-tiefe*) (member k *lg-rack-pfad*)) nil)
(T
(setq def (tblsearch "BLOCK" bname) res nil)
(if (and def (= 0 (logand (cond ((cdr (assoc 70 def))) (0)) 4)))
(progn
(setq *lg-rack-pfad* (cons k *lg-rack-pfad*))
(setq res (vl-some '(lambda (ed)
(if (= (cdr (assoc 0 ed)) "INSERT")
(or (lg-rack-p (cdr (assoc -1 ed)))
(lg-rack-enthaelt-p (cdr (assoc 2 ed)) (1+ tiefe)))))
(lg-blockdef-objekte bname)))
(setq *lg-rack-pfad* (cdr *lg-rack-pfad*))))
(setq *lg-rack-cache* (cons (cons k res) *lg-rack-cache*))
res))
)
;; Eine INSERT pruefen (inkl. MINSERT-Raster) bzw. in ihre Definition
;; absteigen. ptf = Transformation des Containers nach Welt.
(defun lg-rack-insert (ent ptf tiefe top / ed spalten zeilen raster sp zl ctf bb name laenge ebenen)
(setq ed (entget ent)
spalten (max 1 (cond ((cdr (assoc 70 ed))) (1)))
zeilen (max 1 (cond ((cdr (assoc 71 ed))) (1)))
raster (> (* spalten zeilen) 1))
(cond
((lg-rack-p ent)
(setq name (lg-rack-name ent)
laenge (lg-zahl-einheit (lg-rack-param ent *lg-rack-param-laenge*))
ebenen (lg-zahl-einheit (lg-rack-param ent *lg-rack-param-ebenen*))
bb (if (not raster) (lg-bbox ent))
sp 0)
(repeat spalten
(setq zl 0)
(repeat zeilen
(setq *lg-racks*
(cons (list name laenge ebenen
(if bb
(lg-tf-pkt ptf (mapcar '(lambda (a b) (/ (+ a b) 2.0)) (car bb) (cadr bb)))
(car (lg-tf-verketten ptf (lg-insert-tf ed sp zl))))
top)
*lg-racks*)
zl (1+ zl)))
(setq sp (1+ sp))))
((and (< tiefe *lg-rack-max-tiefe*) (lg-rack-enthaelt-p (cdr (assoc 2 ed)) 0))
(setq sp 0)
(repeat spalten
(setq zl 0)
(repeat zeilen
(setq ctf (lg-tf-verketten ptf (lg-insert-tf ed sp zl)))
(foreach sub (lg-blockdef-objekte (cdr (assoc 2 ed)))
(if (= (cdr (assoc 0 sub)) "INSERT")
(lg-rack-insert (cdr (assoc -1 sub)) ctf (1+ tiefe) top)))
(setq zl (1+ zl)))
(setq sp (1+ sp))))
)
)
;; Alle goh_racks im Modellbereich (Blockname/Parameter aus lager.json).
;; Rueckgabe: Liste (name laenge-mm ebenen mitte top-ent), Fundreihenfolge.
(defun lg-racks-sammeln ( / )
(lg-racks-finden (lg-vorgabe '("goh_rack" "blockname") "goh_rack")
(lg-vorgabe '("goh_rack" "param_laenge") "Laenge")
(lg-vorgabe '("goh_rack" "param_ebenen") "Ebenen"))
)
;; Wie lg-racks-sammeln, Blockname und Parameternamen als Argument.
(defun lg-racks-finden (name p-laenge p-ebenen / ss i)
(setq *lg-rack-suchname* name
*lg-rack-param-laenge* p-laenge
*lg-rack-param-ebenen* p-ebenen
*lg-racks* nil *lg-rack-cache* nil *lg-rack-pfad* nil)
(if (setq ss (ssget "_X" '((0 . "INSERT") (410 . "Model"))))
(progn
(setq i 0)
(repeat (sslength ss)
(lg-rack-insert (ssname ss i) (lg-tf-id) 0 (ssname ss i))
(setq i (1+ i)))))
(reverse *lg-racks*)
)
;; Reiner Kern: Racks je Geschoss zusammenfassen. eintraege = ((geschoss
;; Reiner Kern: Regalreihen je Geschoss zusammenfassen. eintraege = ((geschoss
;; laenge-mm ebenen) ...), geschoss nil = nicht zuordenbar, fehlende Laenge/
;; Ebenen zaehlen 0. Rueckgabe ((geschoss anzahl summe-laenge
;; summe-laenge-x-ebenen) ...), nach Geschoss sortiert, nil zuletzt.
(defun lg-racks-auswerten (eintraege / erg vorh l k)
(defun lg-reihen-auswerten (eintraege / erg vorh l k)
(setq erg nil)
(foreach x eintraege
(setq l (cond ((cadr x)) (0.0))
@@ -1693,30 +1434,39 @@
(vl-sort erg '(lambda (a b) (cond ((null (car a)) nil) ((null (car b)) T) (T (< (car a) (car b))))))
)
;; Befehl LG_REGALE: goh_racks zaehlen, Anzahl, Laenge und Laenge x Ebenen
;; (Haengekapazitaet) je Geschoss in der Befehlszeile.
(defun c:LG_REGALE ( / kand racks zeilen ohne-laenge)
(setq kand (lg-geschoss-kandidaten)
racks (lg-racks-sammeln))
(if (null racks)
(princ (ssg-textf "lg-regale-keine" (list (lg-vorgabe '("goh_rack" "blockname") "goh_rack"))))
(progn
(setq zeilen (lg-racks-auswerten
(mapcar '(lambda (r) (list (lg-rack-geschoss (lg-ent-layer (lg-rk-top r)) (lg-rk-mitte r) kand)
(lg-rk-laenge r) (lg-rk-ebenen r)))
racks))
ohne-laenge (length (vl-remove-if 'lg-rk-laenge racks)))
(princ (ssg-text "lg-regale-kopf"))
(foreach z zeilen
(princ (ssg-textf "lg-regale-zeile"
(list (if (car z) (ssg-textf "lg-regale-geschoss" (list (itoa (car z))))
(ssg-text "lg-regale-ohne-geschoss"))
(itoa (cadr z)) (rtos (/ (caddr z) 1000.0) 2 2) (rtos (/ (cadddr z) 1000.0) 2 2)))))
(princ (ssg-textf "lg-regale-zeile"
(list (ssg-text "lg-regale-summe") (itoa (length racks))
(rtos (/ (apply '+ (mapcar 'caddr zeilen)) 1000.0) 2 2)
(rtos (/ (apply '+ (mapcar 'cadddr zeilen)) 1000.0) 2 2))))
(if (> ohne-laenge 0) (princ (ssg-textf "lg-regale-ohne-laenge" (list (itoa ohne-laenge)))))))
;; Reiner Kern: Eintrag (geschoss laenge-mm ebenen) einer Regalreihe
;; (LG_REIHE_*) fuer lg-reihen-auswerten, aus ihren Attributen. Ebenen =
;; Anzahl der Haengeebenen in HAENGEEBENEN, Geschoss nil wenn nicht lesbar.
(defun lg-reihe-eintrag (a / gs)
(setq gs (lg-zahl (cdr (assoc "GESCHOSS" a))))
(list (if gs (fix gs))
(lg-zahl (cdr (assoc "LAENGE" a)))
(float (length (lg-haengeebenen-parse (cdr (assoc "HAENGEEBENEN" a))))))
)
;; Zeilen von lg-reihen-auswerten in der Befehlszeile ausgeben (Kopf, je
;; Geschoss eine Zeile, Summe). zeile-key: Textschluessel mit %1..%4.
(defun lg-regale-ausgeben (kopf-key zeile-key zeilen)
(princ (ssg-text kopf-key))
(foreach z zeilen
(princ (ssg-textf zeile-key
(list (if (car z) (ssg-textf "lg-regale-geschoss" (list (itoa (car z))))
(ssg-text "lg-regale-ohne-geschoss"))
(itoa (cadr z)) (rtos (/ (caddr z) 1000.0) 2 2) (rtos (/ (cadddr z) 1000.0) 2 2)))))
(princ (ssg-textf zeile-key
(list (ssg-text "lg-regale-summe") (itoa (apply '+ (mapcar 'cadr zeilen)))
(rtos (/ (apply '+ (mapcar 'caddr zeilen)) 1000.0) 2 2)
(rtos (/ (apply '+ (mapcar 'cadddr zeilen)) 1000.0) 2 2))))
)
;; Befehl LG_REGALE: Regalreihen (LG_REIHE_* aus LG_BEREICH/LG_REIHE)
;; zaehlen - je Geschoss Anzahl, Laenge und Laenge x Ebenen
;; (Haengekapazitaet) in der Befehlszeile.
(defun c:LG_REGALE ( / reihen)
(if (setq reihen (lg-alle-bloecke "LG_REIHE_*"))
(lg-regale-ausgeben "lg-regale-kopf" "lg-regale-zeile"
(lg-reihen-auswerten (mapcar '(lambda (e) (lg-reihe-eintrag (ssg-attrib-read e))) reihen)))
(princ (ssg-text "lg-regale-keine")))
(princ)
)
@@ -1730,40 +1480,11 @@
;; normalen Einfuegefunktionen NEU erzeugt (Layer, ID, Verknuepfung,
;; Blockname/Schraffur, ATTSYNC kommen von dort) - die Kinder 1:1 aus der
;; Quelle, ohne Neufuellen, damit Handaenderungen (auto_geaendert, manuelle
;; Reihen/Gaenge) erhalten bleiben. goh_rack-Bloecke (parametrisch) werden
;; per vla-Copy kopiert und auf den Regal-Layer des Zielgeschosses gelegt.
;; Reihen/Gaenge) erhalten bleiben.
;; Die Kopie liegt deckungsgleich (2D uebereinander), optional je Kopie um
;; (dx dy) versetzt; in einer 3D-Zeichnung (Konturen auf Belagshoehe)
;; zusaetzlich in Z um den Hoehenabstand.
;; Layer eines Objekts oder nil.
(defun lg-ent-layer (ent / ed)
(if (and ent (setq ed (entget ent))) (cdr (assoc 8 ed)))
)
;; Reiner Kern: Geschossnummer aus einem Lager-Layer "LG_<x>_G<nr>"
;; (Muster wie lg-geschoss-aktivieren), sonst nil.
(defun lg-geschoss-aus-layer (name / s p rest)
(if (and (= (type name) 'STR) (wcmatch (setq s (strcase name)) "LG_*_G#*"))
(progn
(setq p (vl-string-position (ascii "_") s nil T)
rest (substr s (+ p 2)))
(if (and (> (strlen rest) 1) (= (substr rest 1 1) "G")
(vl-every '(lambda (c) (<= 48 c 57)) (vl-string->list (substr rest 2))))
(atoi (substr rest 2)))))
)
;; Reiner Kern: Geschoss eines goh_rack. Ein Lager-Layer _G<nr> eines
;; vorhandenen Geschosses entscheidet (eindeutig auch bei 2D-Geschossen
;; uebereinander), sonst die Kontur (lg-geschoss-fuer-punkt-kern).
;; kandidaten = ((nr hoehe-mm kontur-punkte) ...)
(defun lg-rack-geschoss (layer pt kandidaten / n)
(setq n (lg-geschoss-aus-layer layer))
(if (and n (assoc n kandidaten))
n
(lg-geschoss-fuer-punkt-kern pt kandidaten))
)
;; Reiner Kern: Belag eines kopierten Bereichs/Gangs. Entsprach er dem
;; Geschossbelag der Quelle, folgt er dem neuen Geschossbelag; bewusst
;; abweichende (z.B. Gitterrost-Gang auf Spanplatte-Buehne) bleiben.
@@ -1847,59 +1568,9 @@
(if (setq neu (lg-kontur-kopieren ent)) (lg-ent-verschieben neu v))
)
;; goh_rack-Bloecke des Geschosses src als oberste INSERTs im Modellbereich
;; (ein Array mit Racks zaehlt als ein Objekt). Vor der ersten Kopie
;; aufrufen: danach waere die Kontur-Zuordnung deckungsgleicher Geschosse
;; mehrdeutig. Rueckgabe: (racks anzahl-mehrdeutig)
(defun lg-racks-der-quelle (src kandidaten / src-pts racks mehrdeutig top gs)
(setq racks nil mehrdeutig nil
src-pts (caddr (assoc src kandidaten)))
(foreach r (lg-racks-sammeln)
(setq top (lg-rk-top r)
gs (lg-rack-geschoss (lg-ent-layer top) (lg-rk-mitte r) kandidaten))
(cond
((and gs (= gs src))
(if (not (member top racks)) (setq racks (cons top racks))))
((and (null gs) src-pts (ssg-punkt-in-poly-p (lg-rk-mitte r) src-pts))
(if (not (member top mehrdeutig)) (setq mehrdeutig (cons top mehrdeutig))))))
(list (reverse racks)
(length (vl-remove-if '(lambda (m) (member m racks)) mehrdeutig)))
)
;; Racks der Quelle ohne Lager-Layer auf den Regal-Layer der Quelle legen -
;; nach der Kopie liegen sie deckungsgleich mit den Kopien, nur der Layer
;; trennt sie dann (Export, LG_GESCHOSS_AKTIV). Rueckgabe: Anzahl.
(defun lg-racks-umhaengen (racks src / lay n)
(setq n 0)
(foreach r racks
(if (null (lg-geschoss-aus-layer (lg-ent-layer r)))
(progn
(if (null lay) (setq lay (lg-layer "goh_rack" src)))
(vla-put-Layer (vlax-ename->vla-object r) lay)
(setq n (1+ n)))))
n
)
;; Racks per vla-Copy (MCAD-Parameter bleiben) um v versetzt ins Geschoss
;; nr kopieren. Rueckgabe: Anzahl.
(defun lg-racks-kopieren (racks nr v / lay n res)
(setq n 0 lay (if racks (lg-layer "goh_rack" nr)))
(foreach r racks
(setq res (vl-catch-all-apply
'(lambda ( / obj)
(setq obj (vla-Copy (vlax-ename->vla-object r)))
(vla-Move obj (vlax-3d-point '(0.0 0.0 0.0)) (vlax-3d-point v))
(vla-put-Layer obj lay)
T)))
(if (vl-catch-all-error-p res)
(princ (ssg-textf "lg-einfuegen-fehler" (list (lg-blockname r) (vl-catch-all-error-message res))))
(setq n (1+ n))))
n
)
;; Eine Kopie des Geschosses src-nr als Geschoss nr auf hoehe, um v versetzt.
;; Rueckgabe: (geschoss-ent reihen gaenge racks) oder nil.
(defun lg-geschoss-kopieren (src-nr nr hoehe belag-neu v racks
;; Rueckgabe: (geschoss-ent reihen gaenge) oder nil.
(defun lg-geschoss-kopieren (src-nr nr hoehe belag-neu v
/ src a belag-alt k werte blk zuordnung kk nb ab ed p1 p2 rot
laenge nb-h art n-reihen n-gaenge s-gs)
(setq src (lg-geschoss-finden src-nr)
@@ -1961,8 +1632,7 @@
belag-alt belag-neu)
nb)
(if (= art "reihe") (setq n-reihen (1+ n-reihen)) (setq n-gaenge (1+ n-gaenge)))))))
;; 4. goh_rack
(list blk n-reihen n-gaenge (lg-racks-kopieren racks nr v))))
(list blk n-reihen n-gaenge)))
)
)
)
@@ -1971,7 +1641,7 @@
;; VERSATZ_X_mm VERSATZ_Y_mm), nicht interaktiv - auch fuer Tests.
;; Rueckgabe: Liste der neuen Geschossnummern oder nil.
(defun lg-geschosse-kopieren (werte / src-nr src n abstand belag dx dy kandidaten
rq racks nr erg neu)
nr erg neu)
(setq src-nr (atoi (cond ((cdr (assoc "QUELLE" werte))) ("0")))
src (lg-geschoss-finden src-nr)
n (atoi (cond ((cdr (assoc "ANZAHL" werte))) ("1")))
@@ -1985,23 +1655,17 @@
((< n 1) nil)
(T
(setq kandidaten (lg-geschoss-kandidaten))
;; Racks VOR der ersten Kopie bestimmen (danach waere die Kontur mehrdeutig)
(setq rq (lg-racks-der-quelle src-nr kandidaten)
racks (car rq))
(if (> (cadr rq) 0) (princ (ssg-textf "lg-kopie-racks-mehrdeutig" (list (itoa (cadr rq))))))
(if (> (setq neu (lg-racks-umhaengen racks src-nr)) 0)
(princ (ssg-textf "lg-kopie-racks-umgehaengt" (list (itoa neu) (itoa src-nr)))))
(setq erg nil)
(foreach p (lg-kopie-plan (lg-geschoss-hoehe src) abstand n dx dy (lg-kopie-3d-p kandidaten))
(if (vl-some '(lambda (k) (equal (cadr k) (cadr p) 1.0)) (lg-geschoss-kandidaten))
(princ (ssg-textf "lg-kopie-hoehe-belegt" (list (lg-mm-str (cadr p))))))
(setq nr (lg-geschoss-naechste-nr))
(if (setq neu (lg-geschoss-kopieren src-nr nr (cadr p) belag (caddr p) racks))
(if (setq neu (lg-geschoss-kopieren src-nr nr (cadr p) belag (caddr p)))
(progn
(setq erg (cons nr erg))
(princ (ssg-textf "lg-kopie-fertig"
(list (itoa src-nr) (itoa nr) (lg-mm-str (cadr p))
(itoa (cadr neu)) (itoa (caddr neu)) (itoa (cadddr neu))))))))
(itoa (cadr neu)) (itoa (caddr neu))))))))
(if erg
(progn
(lg-ldata-setzen "GESCHOSS_AKTIV" (car erg))
@@ -2061,7 +1725,7 @@
(entmod (subst (cons 70 f) (assoc 70 ed) ed))))
)
;; Geschoss mit Belag, Bereichen, Reihen, Gaengen und goh_racks in ein oder
;; Geschoss mit Belag, Bereichen, Reihen und Gaengen in ein oder
;; mehrere neue Geschosse kopieren (siehe lg-geschosse-kopieren).
(defun c:LG_GESCHOSS_KOPIEREN ( / werte)
(ssg-start (ssg-text "lg-titel-kopie") nil)
@@ -2472,41 +2136,9 @@
(cons "handle" (lg-handle e)))))
)
;; goh_rack-Bloecke sammeln (lg-racks-sammeln). Geschoss ueber den Layer
;; des obersten INSERTs (_G<nr>), sonst ueber die Kontur (lg-rack-geschoss).
;; Rueckgabe: (json-texte warnungen)
(defun lg-export-goh-racks (kandidaten / texte warn gs ebenen vorgabe)
(setq texte nil warn nil
vorgabe (lg-vorgabe '("reihe" "haengeebenen") "2300/1200;1100/1100"))
(foreach r (lg-racks-sammeln)
(setq gs (lg-rack-geschoss (lg-ent-layer (lg-rk-top r)) (lg-rk-mitte r) kandidaten))
(if (and (null gs) kandidaten)
(setq warn (cons (ssg-textf "lg-exp-rack-ohne-geschoss"
(list (rtos (car (lg-rk-mitte r)) 2 0) (rtos (cadr (lg-rk-mitte r)) 2 0)))
warn)))
(setq ebenen (if (lg-rk-ebenen r) (fix (lg-rk-ebenen r))))
(if (null (lg-rk-laenge r))
(setq warn (cons (ssg-textf "lg-exp-rack-ohne-laenge" (list (lg-rk-name r))) warn)))
(setq texte (cons
(lg-json-obj
(list (cons "geschoss" gs)
(cons "name" (lg-rk-name r))
(cons "laenge_mm" (lg-rk-laenge r))
(cons "ebenen" ebenen)
(cons "tiefe_mm" (lg-zahl (lg-vorgabe '("goh_rack" "tiefe_mm") 700)))
(cons "haengeebenen" (lg-json-ebenen (if ebenen (lg-haengeebenen-n vorgabe ebenen) vorgabe)))
(cons "haengeebenen_quelle" "vorgabe")
(cons "position" (lg-json-zahlen (lg-rk-mitte r)))))
texte)))
(list (reverse texte) (reverse warn))
)
;; Alle Daten als JSON-Text.
(defun lg-export-json ( / gs kandidaten racks warn gs-ohne)
(setq gs (lg-geschosse)
kandidaten (lg-geschoss-kandidaten)
racks (lg-export-goh-racks kandidaten)
warn (cadr racks))
(defun lg-export-json ( / gs warn)
(setq gs (lg-geschosse) warn nil)
(if (null gs) (setq warn (cons (ssg-text "lg-exp-keine-geschosse") warn)))
(foreach g gs
(if (null (cadddr g))
@@ -2526,7 +2158,6 @@
" \"bereiche\": " (lg-json-arr (mapcar 'lg-export-bereich (lg-alle-bloecke "LG_BEREICH")) " ") ",\n"
" \"reihen\": " (lg-json-arr (mapcar '(lambda (e) (lg-export-linie e "reihe")) (lg-alle-bloecke "LG_REIHE_*")) " ") ",\n"
" \"gaenge\": " (lg-json-arr (mapcar '(lambda (e) (lg-export-linie e "gang")) (lg-alle-bloecke "LG_GANG_*")) " ") ",\n"
" \"goh_racks\": " (lg-json-arr (car racks) " ") ",\n"
" \"warnungen\": " (lg-json-arr (mapcar 'lg-json-wert warn) " ") "\n"
"}\n")
)
+7 -15
View File
@@ -879,12 +879,12 @@ Mengen gehen ueber `LAGER_EXPORT` als Overlay-YAML an das RFQ-Programm
| --- | --- |
| `c:LG_GESCHOSS` | Belagskontur waehlen/zeichnen, Dialog `lg_geschoss` (`dcl/lager.dcl`), Block `LG_GESCHOSS` + XDATA-Verknuepfung zur Kontur |
| `c:LG_GESCHOSS_AKTIV` | Aktives Geschoss setzen, Layer `LG_*_G<n>` der anderen Geschosse frieren (0 = alle zeigen) |
| `c:LG_GESCHOSS_KOPIEREN` | Geschoss mit Belagskontur, Bereichen, Reihen, Gaengen und goh_racks 1:1 in ein oder mehrere neue Geschosse kopieren (Dialog `lg_geschoss_kopie`: Quelle - Vorgabe oberstes Geschoss -, Anzahl, Geschosshoehe je Kopie, Belag, Versatz X/Y je Kopie, 0 = deckungsgleich). Belaege gleich dem Quell-Geschossbelag folgen dem neuen Belag; Verknuepfungen, Layer `_G<n>` und IDs sind neu |
| `c:LG_GESCHOSS_KOPIEREN` | Geschoss mit Belagskontur, Bereichen, Reihen und Gaengen 1:1 in ein oder mehrere neue Geschosse kopieren (Dialog `lg_geschoss_kopie`: Quelle - Vorgabe oberstes Geschoss -, Anzahl, Geschosshoehe je Kopie, Belag, Versatz X/Y je Kopie, 0 = deckungsgleich). Belaege gleich dem Quell-Geschossbelag folgen dem neuen Belag; Verknuepfungen, Layer `_G<n>` und IDs sind neu |
| `c:LG_BEREICH` | Lagerbereich-Kontur + Dialog `lg_bereich`; Auto-Fuellung mit `LG_REIHE_<L>_<T>` / `LG_GANG_<L>_<B>_<BELAG>`, optional Randgaenge Nord/Ost/Sued/West entlang der Konturkanten (auch L-Form) |
| `c:LG_REIHE` | Einzelne Regalreihen per Start/Ende oder getippter Laenge; wie bei `LG_GANG` mit dem Bereich verknuepft und ausgeschnitten statt neu berechnet (`lg-manuell-einfuegen`) |
| `c:LG_GANG` | Einzelne Gaenge (Dialog `lg_gang`: Breite, Art gang/randgang/quergang, Belag), mittig auf der Linie - oder ueber die Option `Rechteck` als Flaeche, gezeichnet mit dem BricsCAD-Befehl RECHTECK samt aller seiner Optionen (Abmessungen, Flaeche, Drehung ...; `lg-rechteck-zeichnen`, Auswertung `lg-rechteck-ecken-aus-poly`, Fase/Rundung wird abgelehnt) (Lage und Breite aus dem Rechteck, laengere Seite = Gangrichtung; Kern `lg-gang-aus-ecken`, `lg-gang-rechteck-einfuegen`, `Linie` schaltet zurueck); liegt die Mitte in einem Bereich, wird der Gang mit ihm verknuepft. Der Gang schneidet seine Flaeche aus den automatisch erzeugten Reihen/Gaengen heraus (`lg-sperre-anwenden`), OHNE den Bereich neu zu berechnen - von Hand geloeschte oder geaenderte Objekte bleiben, wie sie sind; bei jeder Neuberechnung bleibt er stehen (Sperrflaeche) |
| `c:LG_EDIT` | Bearbeiten (auch per Doppelklick ueber `SSG_BLOCKEDIT`, Zweig `LG_*`): Bereich -> Neuberechnung (von Hand eingefuegte und geaenderte Reihen/Gaenge bleiben stehen und werden ausgespart), Reihe/Gang -> Neuaufbau, danach Zuschnitt der rangniedrigeren Objekte (`auto` < `auto_geaendert` < `manuell`, `lg-quelle-rang`) statt Neuberechnung des Bereichs |
| `c:LG_REGALE` | goh_racks zaehlen (`lg-racks-sammeln`): Anzahl, Laenge und Laenge x Ebenen je Geschoss (Zuordnung wie beim Export) plus Gesamtsumme in der Befehlszeile |
| `c:LG_REGALE` | Regalreihen `LG_REIHE_*` zaehlen (`lg-reihe-eintrag` + `lg-reihen-auswerten`): Anzahl, Laenge und Laenge x Haengeebenen je Geschoss plus Gesamtsumme in der Befehlszeile |
| `c:LAGER_EXPORT` | `<dwg>_lager_raw.json` + Python -> `<dwg>_drawing.yaml` und `<dwg>_nachweis.html` in `DXFM_RESULTS` |
| `c:LAGER_HAND_YAML` | Hand-YAML fuer den Abgleich (Konfliktliste) festlegen |
| `c:LG_REGELN` | Regelprofil (`cfg/regelwerk/<Land>.json`) mit aufgeloesten Werten und Quellen anzeigen |
@@ -894,21 +894,13 @@ Gangflaechen sind je Belag schraffiert (Schraffur in der Blockdefinition, Muster
Hallenboden keine).
Reine Kerne (`lg-fuellung-berechnen`, `lg-randgang-streifen`, `lg-kompass`,
`lg-schraffur-vorgabe`, `lg-geschoss-fuer-punkt-kern`, `lg-geschoss-aus-layer`,
`lg-rack-geschoss`, `lg-kopie-*`, `lg-zahl-einheit`, `lg-insert-tf`/`lg-tf-verketten`,
`lg-regel-aufloesen`, `lg-profil-mischen`, JSON-Schreiber, Feldpruefung) in
`lg-schraffur-vorgabe`, `lg-geschoss-fuer-punkt-kern`, `lg-kopie-*`,
`lg-reihe-eintrag`/`lg-reihen-auswerten`, `lg-regel-aufloesen`, `lg-profil-mischen`, JSON-Schreiber, Feldpruefung) in
`tests/test_unit.lsp` (`tu-tests-lager`); Zeichnungsablauf in
`tests/test_lager.lsp` (`TEST_LAGER`, inkl. Rack-Erkennung mit Verschachtelung und
MINSERT sowie goh_rack-Regression gegen `tests/testdata/goh_storage_test.dwg`).
`tests/test_lager.lsp` (`TEST_LAGER`).
`goh_rack`-Bloecke (parametrischer BricsCAD-Block) erkennt und zaehlt `LagerInsert.lsp`
selbst (`lg-racks-sammeln`): Name ueber die Objekteigenschaft `EffectiveName`,
Parameter `Laenge`/`Ebenen` (`lager.json` `goh_rack`) als MCAD-Eigenschaft, dynamische
Eigenschaft, Attribut oder ATTDEF-Vorgabe, Einheiten auf mm umgerechnet; gefunden auch
in assoziativen Arrays, MINSERT-Rastern und verschachtelten Bloecken. `LAGER_EXPORT`
ordnet jedes goh_rack zuerst ueber den Layer `LG_*_G<n>` seines obersten INSERTs
(`lg-rk-top`), erst dann ueber die Geschosskontur zu. `LG_REGALE` zeigt die Zaehlung
je Geschoss in der Befehlszeile.
Der parametrische BricsCAD-Block `goh_rack` wird nicht mehr unterstuetzt (veraltet):
Regale entstehen nur noch als `LG_REIHE_*` ueber `LG_BEREICH`/`LG_REIHE`.
---
-1
View File
@@ -188,7 +188,6 @@ geschoss = LG_Geschoss, 7
bereich = LG_Bereich, 4
reihe = LG_Reihe, 3
gang = LG_Gang, 8
goh_rack = LG_Regal, 3
# ============================================================
-8
View File
@@ -3,14 +3,6 @@
"beschreibung": "Vorgaben fuer die Lagerplanung (LagerInsert.lsp). Alle Masse in mm, Winkel in Grad. Die Werte belegen die Dialoge vor; was im Dialog bzw. am Block steht, gewinnt.",
"land": "DE",
"goh_rack": {
"beschreibung": "Parametrischer BricsCAD-Block, der als Regalreihe mitgezaehlt wird (lg-racks-sammeln in LagerInsert.lsp). param_laenge/param_ebenen = Namen der MCAD-Parameter.",
"blockname": "goh_rack",
"param_laenge": "Laenge",
"param_ebenen": "Ebenen",
"tiefe_mm": 700
},
"geschoss": {
"konstr_hoehe_mm": 250,
"personen": 20,
+1 -1
View File
@@ -96,7 +96,7 @@ lg_geschoss_kopie : dialog {
: edit_box { key = "versatz_y"; label = "Y:"; edit_width = 10; }
}
}
: text { label = "Kopiert Belag, Bereiche, Reihen, Gaenge und goh_rack 1:1."; }
: text { label = "Kopiert Belag, Bereiche, Reihen und Gaenge 1:1."; }
: text { label = "Belaege gleich dem Quell-Geschossbelag folgen dem neuen Belag."; }
}
ok_cancel;
+4 -9
View File
@@ -1236,17 +1236,14 @@
"lg-feld-versatz_y": "\nVersatz Y je Kopie (mm, 0 = deckungsgleich)",
"lg-kopie-abstand-ungueltig": "\n[Lager] Geschosshoehe je Kopie muss groesser 0 sein - nichts kopiert.",
"lg-kopie-hoehe-belegt": "\n[Lager] Auf Belagshoehe %1 mm liegt bereits ein Geschoss - Kopie wird trotzdem angelegt.",
"lg-kopie-racks-mehrdeutig": "\n[Lager] %1 goh_rack ohne eindeutiges Geschoss (Konturen uebereinander, kein Layer _G<nr>) - nicht kopiert.",
"lg-kopie-racks-umgehaengt": "\n%1 goh_rack auf den Regal-Layer von Geschoss %2 gelegt (Zuordnung bei deckungsgleichen Geschossen).",
"lg-kopie-fertig": "\nGeschoss %1 kopiert -> Geschoss %2 auf %3 mm: %4 Regalreihe(n), %5 Gang-/Quergangflaeche(n), %6 goh_rack.",
"lg-kopie-fertig": "\nGeschoss %1 kopiert -> Geschoss %2 auf %3 mm: %4 Regalreihe(n), %5 Gang-/Quergangflaeche(n).",
"lg-kopie-hinweis-aktiv": "\nLetzte Kopie ist aktives Geschoss. Anzeige umschalten mit LG_GESCHOSS_AKTIV.",
"lg-regale-keine": "\n[Lager] Keine Bloecke %1 im Modellbereich gefunden.",
"lg-regale-kopf": "\nRegale (goh_rack) je Geschoss: Anzahl, Laenge, Laenge x Ebenen",
"lg-regale-zeile": "\n %1: %2 Regal(e), %3 m, %4 m",
"lg-regale-keine": "\n[Lager] Keine Regalreihen (LG_REIHE) in der Zeichnung gefunden.",
"lg-regale-kopf": "\nRegalreihen (LG_REIHE) je Geschoss: Anzahl, Laenge, Laenge x Ebenen",
"lg-regale-zeile": "\n %1: %2 Reihe(n), %3 m, %4 m",
"lg-regale-geschoss": "Geschoss %1",
"lg-regale-ohne-geschoss": "ohne Geschoss",
"lg-regale-summe": "Gesamt",
"lg-regale-ohne-laenge": "\n[Lager] %1 Regal(e) ohne lesbare Laenge - mit 0 gezaehlt.",
"lg-titel-geschoss": "Lager: Geschoss anlegen",
"lg-titel-bereich": "Lager: Lagerbereich anlegen",
"lg-titel-reihe": "Lager: Regalreihen einfuegen",
@@ -1275,8 +1272,6 @@
"lg-reihen-eingefuegt": "\n%1 Regalreihe(n) eingefuegt.",
"lg-exp-keine-geschosse": "Keine Geschosse (LG_GESCHOSS) in der Zeichnung - levels bleiben leer.",
"lg-exp-geschoss-ohne-kontur": "Geschoss %1 hat keine Belagskontur mehr.",
"lg-exp-rack-ohne-geschoss": "goh_rack bei X=%1 Y=%2 keinem Geschoss eindeutig zuzuordnen.",
"lg-exp-rack-ohne-laenge": "goh_rack %1 ohne lesbare Laenge.",
"lg-exp-datei-fehler": "\n[Lager] Datei nicht schreibbar: %1",
"lg-exp-raw": "\n[Lager] Rohdaten: %1",
"lg-exp-yaml": "\n[Lager] Overlay-YAML: %1\n[Lager] Nachweis: %2",
+4 -9
View File
@@ -1236,17 +1236,14 @@
"lg-feld-versatz_y": "\nOffset Y per copy (mm, 0 = congruent)",
"lg-kopie-abstand-ungueltig": "\n[Storage] Level height per copy must be greater than 0 - nothing copied.",
"lg-kopie-hoehe-belegt": "\n[Storage] A level already exists at floor height %1 mm - copy is created anyway.",
"lg-kopie-racks-mehrdeutig": "\n[Storage] %1 goh_rack without a unique level (stacked contours, no layer _G<no>) - not copied.",
"lg-kopie-racks-umgehaengt": "\n%1 goh_rack moved to the rack layer of level %2 (assignment for congruent levels).",
"lg-kopie-fertig": "\nLevel %1 copied -> level %2 at %3 mm: %4 rack row(s), %5 aisle/cross aisle area(s), %6 goh_rack.",
"lg-kopie-fertig": "\nLevel %1 copied -> level %2 at %3 mm: %4 rack row(s), %5 aisle/cross aisle area(s).",
"lg-kopie-hinweis-aktiv": "\nLast copy is the active level. Switch the display with LG_GESCHOSS_AKTIV.",
"lg-regale-keine": "\n[Storage] No %1 blocks found in model space.",
"lg-regale-kopf": "\nRacks (goh_rack) per level: count, length, length x levels",
"lg-regale-zeile": "\n %1: %2 rack(s), %3 m, %4 m",
"lg-regale-keine": "\n[Storage] No rack rows (LG_REIHE) found in the drawing.",
"lg-regale-kopf": "\nRack rows (LG_REIHE) per level: count, length, length x levels",
"lg-regale-zeile": "\n %1: %2 row(s), %3 m, %4 m",
"lg-regale-geschoss": "Level %1",
"lg-regale-ohne-geschoss": "no level",
"lg-regale-summe": "Total",
"lg-regale-ohne-laenge": "\n[Storage] %1 rack(s) without readable length - counted as 0.",
"lg-titel-geschoss": "Storage: create level",
"lg-titel-bereich": "Storage: create storage area",
"lg-titel-reihe": "Storage: insert rack rows",
@@ -1275,8 +1272,6 @@
"lg-reihen-eingefuegt": "\n%1 rack row(s) inserted.",
"lg-exp-keine-geschosse": "No levels (LG_GESCHOSS) in the drawing - levels stay empty.",
"lg-exp-geschoss-ohne-kontur": "Level %1 has no floor contour any more.",
"lg-exp-rack-ohne-geschoss": "goh_rack at X=%1 Y=%2 cannot be assigned to a level.",
"lg-exp-rack-ohne-laenge": "goh_rack %1 without readable length.",
"lg-exp-datei-fehler": "\n[Storage] File not writable: %1",
"lg-exp-raw": "\n[Storage] Raw data: %1",
"lg-exp-yaml": "\n[Storage] Overlay YAML: %1\n[Storage] Report: %2",
+1 -7
View File
@@ -121,12 +121,8 @@ def aggregiere(raw):
key=lambda g: (_zahl(g.get("hoehe_belag_mm")), g.get("nr") or 0))
bereiche = raw.get("bereiche") or []
alle_reihen = list(raw.get("reihen") or [])
racks = raw.get("goh_racks") or []
gaenge = raw.get("gaenge") or []
# goh_rack-Bloecke zaehlen wie Regalreihen (Herkunft wird mitgefuehrt)
for r in racks:
alle_reihen.append(dict(r, quelle="goh_rack"))
ohne_geschoss = [r for r in alle_reihen if r.get("geschoss") is None]
if ohne_geschoss and geschosse:
s.warnung("%d Regalreihe(n) ohne Geschoss - nicht in levels enthalten" % len(ohne_geschoss))
@@ -226,11 +222,9 @@ def aggregiere(raw):
hl = _haengeebenen(reihen)
if hl:
lv["hanging_levels"] = hl
n_rack = sum(1 for r in reihen if r.get("quelle") == "goh_rack")
for j, e in enumerate(hl):
s.herkunft("%s.hanging_levels[%d].rack_length_m" % (p, j), e["rack_length_m"],
"%d Regalreihe(n) Geschoss %s (davon %d goh_rack, Haengeebenen aus Vorgabe)"
% (len(reihen), nr, n_rack),
"%d Regalreihe(n) Geschoss %s" % (len(reihen), nr),
"Summe LAENGE aller Reihen mit Schienenhoehe %s / Warenlaenge %s"
% (e["rail_height_m"], e["goods_length_m"]))
+2 -2
View File
@@ -688,7 +688,7 @@
</MenuMacro>
<MenuMacro UID="MM_00150">
<Macro>
<Name>Regale zaehlen (goh_rack)</Name>
<Name>Regale zaehlen</Name>
<Command>^C^C(ssg-ensure "LagerInsert") LG_REGALE</Command>
</Macro>
</MenuMacro>
@@ -1782,7 +1782,7 @@
</PopMenuItem>
<PopMenuItem IsSeparator="true"/>
<PopMenuItem>
<NameRef>Regale zaehlen (goh_rack)</NameRef>
<NameRef>Regale zaehlen</NameRef>
<MenuItem>
<MacroRef MenuMacroID="MM_00150"/>
</MenuItem>
+1 -1
View File
@@ -147,7 +147,7 @@
[Gaenge einzeln]^C^C(ssg-ensure "LagerInsert") LG_GANG
[Bearbeiten]^C^C(ssg-ensure "LagerInsert") LG_EDIT
[--]
[Regale zaehlen (goh_rack)]^C^C(ssg-ensure "LagerInsert") LG_REGALE
[Regale zaehlen]^C^C(ssg-ensure "LagerInsert") LG_REGALE
[Regelprofil anzeigen]^C^C(ssg-ensure "LagerPruefung") LG_REGELN
[Hand-YAML fuer Abgleich]^C^C(ssg-ensure "LagerInsert") LAGER_HAND_YAML
[<-Export RFQ-YAML]^C^C(ssg-ensure "LagerInsert") LAGER_EXPORT
+12 -88
View File
@@ -5,10 +5,8 @@
;; - zwei Geschosse auf derselben 2D-Kontur (EG Hallenboden, OG 3100 mm)
;; - einen Lagerbereich 10000 x 6000 im OG mit Auto-Fuellung
;; und prueft Bloecke, Attribute, Layer, Neuberechnung (keine Verdopplung),
;; den Neuaufbau einer geaenderten Reihe und die Rohdaten von LAGER_EXPORT.
;; Zum Schluss Regression der goh_rack-Erkennung (lg-racks-sammeln) gegen
;; tests/testdata/goh_storage_test.dwg (Referenzwerte aus
;; goh_storage_test_regal_report.txt: 38946.39 mm / 77892.78 mm).
;; den Neuaufbau einer geaenderten Reihe, die Rohdaten von LAGER_EXPORT und
;; die Zaehlung von LG_REGALE.
;;
;; Aufruf in BricsCAD:
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_lager.lsp"))
@@ -83,8 +81,8 @@
(vl-remove-if-not '(lambda (ed) (= (cdr (assoc 0 ed)) "ATTDEF")) (lg-blockdef-objekte bname))))
(defun lager:tests ( / k0 k1 g0 g1 kb bereich reihen gaenge r0 neu raw daten pfad f
racks laengen kap tr kb2 b2 kinder mg mg2 hg alt eb
r1 gg1 n-alt g2 r2 gg2 ids b2k n-kinder bb gr rg grp rk kand zl
kb2 b2 kinder mg mg2 hg alt eb
r1 gg1 n-alt g2 r2 gg2 ids b2k n-kinder bb rg rk zl
b3 rh3 mg3 ge3 ag3 n3 mr3 alt3)
(setvar "CMDECHO" 0)
(ssg-gui-aus)
@@ -366,88 +364,14 @@
(tlg-eq "rechteck-befehl: fase abgelehnt" 'kein-rechteck (lg-rechteck-ecken-aus-poly (entlast)))
(entdel (entlast))
;; --- Rack-Erkennung: direkt, verschachtelt + gedreht, MINSERT ---
;; eigener Testblock (Parameter als Attribut bzw. ATTDEF-Vorgabe), damit
;; die Suche nach goh_rack davon unberuehrt bleibt
(lg-blockdef "TLG_RACK" (list (lg-geom-linie '(0.0 0.0 0.0) '(1000.0 0.0 0.0))
(lg-geom-attdef "Laenge" "500" '(0.0 0.0 0.0) 50.0 nil)
(lg-geom-attdef "Ebenen" "3" '(0.0 0.0 0.0) 50.0 nil)))
(lg-blockdef "TLG_GRUPPE" (list '((0 . "INSERT") (8 . "0") (2 . "TLG_RACK") (10 0.0 0.0 0.0))
'((0 . "INSERT") (8 . "0") (2 . "TLG_RACK") (10 0.0 2000.0 0.0))))
(lg-block-einfuegen "TLG_RACK" '(-100000.0 0.0 0.0) 0.0 "0" '(("Laenge" . "100 cm") ("Ebenen" . "2")))
(setq grp (lg-block-einfuegen "TLG_GRUPPE" '(-200000.0 0.0 0.0) (/ pi 2.0) "0" nil))
(vla-AddMInsertBlock (lg-modelspace) (vlax-3d-point '(-300000.0 0.0 0.0)) "TLG_RACK"
1.0 1.0 1.0 0.0 1 3 1000.0 3000.0)
(setq rk (lg-racks-finden "TLG_RACK" "Laenge" "Ebenen"))
(tlg-eq "racks: anzahl" 6 (length rk))
(tlg-eq "racks: laenge (attribut mit einheit + vorgaben)" 3500.0
(apply '+ (mapcar '(lambda (r) (cond ((lg-rk-laenge r)) (0.0))) rk)))
(tlg-eq "racks: ebenen" 17.0 (apply '+ (mapcar '(lambda (r) (cond ((lg-rk-ebenen r)) (0.0))) rk)))
(tlg-eq "racks: verschachtelt top" 2
(length (vl-remove-if-not '(lambda (r) (equal (lg-rk-top r) grp)) rk)))
;; Gruppe um 90 Grad gedreht: zweites Rack (lokal y = 2000) liegt bei x = -202000
(tlg-eq "racks: verschachtelt gedreht" T
(equal (vl-sort (mapcar '(lambda (r) (car (lg-rk-mitte r)))
(vl-remove-if-not '(lambda (r) (equal (lg-rk-top r) grp)) rk))
'<)
'(-202000.0 -200000.0) 100.0))
;; MINSERT 1 Zeile x 3 Spalten, Abstand 3000: Mitten = Einfuegepunkte
(tlg-eq "racks: minsert" '(-300000.0 -297000.0 -294000.0)
(vl-sort (mapcar '(lambda (r) (car (lg-rk-mitte r)))
(vl-remove-if-not '(lambda (r) (< (car (lg-rk-mitte r)) -250000.0)) rk))
'<))
;; --- goh_rack-Regression (Referenzwerte goh_storage_test_regal_report.txt) ---
(setq pfad (strcat (getenv "DXFMAKRO") "/tests/testdata/goh_storage_test.dwg"))
(if (findfile pfad)
(progn
;; "*" = aufgeloest einfuegen: die goh_rack-Bloecke liegen danach
;; direkt im Modellbereich wie in der Originalzeichnung
(command "_.-INSERT" (strcat "*" pfad) '(50000.0 0.0 0.0) 1 0)
(setq racks (lg-export-goh-racks nil))
(tlg-eq "goh_rack anzahl" 4 (length (car racks)))
(setq laengen (tlg-summe (car racks) "laenge_mm"))
(setq kap 0.0)
(foreach t1 (car racks)
(setq tr (ssg-json-parse t1))
(setq kap (+ kap (* (ssg-json-get tr "laenge_mm") (ssg-json-get tr "ebenen")))))
(tlg-eq "goh_rack laenge gesamt" T (equal laengen 38946.39 0.1))
(tlg-eq "goh_rack laenge x ebenen" T (equal kap 77892.78 0.1))
(princ (strcat "\n goh_rack: " (rtos laengen 2 2) " mm / " (rtos kap 2 2) " mm"))
;; --- Geschoss mit goh_racks kopieren (deckungsgleich, 2D) ---
;; Geschosskontur um die Racks legen (Mitten aus lg-racks-sammeln + Rand)
(setq bb (ssg-poly-bbox (mapcar '(lambda (p) (list (car p) (cadr p)))
(mapcar 'lg-rk-mitte (lg-racks-sammeln)))))
(setq gr (lg-geschoss-naechste-nr))
(lg-geschoss-anlegen (tlg-rechteck (- (car (car bb)) 20000.0) (- (cadr (car bb)) 20000.0)
(+ (car (cadr bb)) 20000.0) (+ (cadr (cadr bb)) 20000.0))
(append (list (cons "HOEHE_BELAG_mm" "20000")) (lg-geschoss-vorgaben gr)))
(setq neu (lg-geschosse-kopieren (list (cons "QUELLE" (itoa gr)) (cons "ANZAHL" "1")
(cons "ABSTAND_mm" "3000") (cons "BELAG_ART" "spanplatte"))))
(setq racks (lg-export-goh-racks (lg-geschoss-kandidaten)))
(tlg-eq "rack-kopie: anzahl" 8 (length (car racks)))
(tlg-eq "rack-kopie: quelle" 4
(length (vl-remove-if-not '(lambda (t1) (equal (ssg-json-get (ssg-json-parse t1) "geschoss") gr))
(car racks))))
(tlg-eq "rack-kopie: kopie" 4
(length (vl-remove-if-not '(lambda (t1) (equal (ssg-json-get (ssg-json-parse t1) "geschoss") (car neu)))
(car racks))))
(tlg-eq "rack-kopie: keine warnung" nil (cadr racks))
(tlg-eq "rack-kopie: laenge kopie" T
(equal (tlg-summe (car racks) "laenge_mm") (* 2 38946.39) 0.2))
(tlg-eq "rack-kopie: layer" T (if (tblsearch "LAYER" (strcat "LG_Regal_G" (itoa (car neu)))) T nil))
;; Auswertung je Geschoss wie LG_REGALE: je 4 Racks in Quelle und Kopie
(setq kand (lg-geschoss-kandidaten))
(setq zl (lg-racks-auswerten
(mapcar '(lambda (r) (list (lg-rack-geschoss (lg-ent-layer (lg-rk-top r)) (lg-rk-mitte r) kand)
(lg-rk-laenge r) (lg-rk-ebenen r)))
(lg-racks-sammeln))))
(tlg-eq "lg_regale: geschosse" (list gr (car neu)) (mapcar 'car zl))
(tlg-eq "lg_regale: anzahl" '(4 4) (mapcar 'cadr zl))
(tlg-eq "lg_regale: laenge x ebenen" T (equal (cadddr (car zl)) 77892.78 0.2))
(tlg-eq "lg_regale: befehl laeuft" nil (vl-catch-all-error-p (vl-catch-all-apply 'c:LG_REGALE nil))))
(tlg-eq "goh_storage_test.dwg vorhanden" T nil))
;; --- LG_REGALE: zaehlt die Regalreihen aus den Makros (LG_REIHE_*) je Geschoss ---
(setq zl (lg-reihen-auswerten (mapcar '(lambda (e) (lg-reihe-eintrag (ssg-attrib-read e)))
(lg-alle-bloecke "LG_REIHE_*"))))
(tlg-eq "lg_regale: reihen gezaehlt" (length (lg-alle-bloecke "LG_REIHE_*"))
(apply '+ (mapcar 'cadr zl)))
(tlg-eq "lg_regale: reihen vorhanden" T (> (apply '+ (mapcar 'cadr zl)) 0))
(tlg-eq "lg_regale: reihen mit geschoss" nil (assoc nil zl))
(tlg-eq "lg_regale: befehl laeuft (reihen)" nil (vl-catch-all-error-p (vl-catch-all-apply 'c:LG_REGALE nil)))
;; --- Von Hand Gesetztes bleibt: Einfuegen loest keine Neuberechnung aus ---
(setq kb (tlg-rechteck 600000.0 0.0 610000.0 6000.0))
+9 -11
View File
@@ -7,8 +7,8 @@ Laeuft ohne BricsCAD: die Rohdaten sind von Hand nachgestellt, im Format von
LAGER_EXPORT (Lisp/LagerInsert.lsp, lg-export-json). Geprueft wird:
1. levels: Belagshoehen, lichte Hoehe aus dem Geschoss darueber,
Haengeebenen (Summe aller Reihen je Schienenhoehe/Warenlaenge, inkl.
goh_rack-Bloecke), Belag/Gitterrost nur auf Buehnen.
Haengeebenen (Summe aller Reihen je Schienenhoehe/Warenlaenge),
Belag/Gitterrost nur auf Buehnen.
2. layout: Bereichsparameter, Ganganzahl/-laenge, Huelle.
3. Provenienz: jeder Overlay-Wert hat einen Herkunfts-Eintrag.
4. Abgleich gegen cfg/example_goh_storage.yaml: Abweichungen -> Konflikte,
@@ -73,8 +73,6 @@ def raw():
"gaenge": [_gang(0, 10000), _gang(1, 10000),
_gang(1, 700, breite=1200, art="quergang"),
_gang(1, 500, breite=1200, art="quergang", belag="gitterrost")],
"goh_racks": [{"geschoss": 1, "name": "goh_rack", "laenge_mm": 5000, "ebenen": 2,
"tiefe_mm": 700, "haengeebenen": EBENEN_OG, "haengeebenen_quelle": "vorgabe"}],
"warnungen": ["Testwarnung"],
}
@@ -90,15 +88,15 @@ def test_levels_sortiert_und_hoehen(raw):
assert "clear_height_m" not in lv[1]
def test_haengeebenen_summe_inkl_goh_rack(raw):
def test_haengeebenen_summe(raw):
overlay, _ = lye.aggregiere(raw)
eg, og = overlay["levels"]
assert eg["hanging_levels"] == [
{"rail_height_m": 2.3, "rack_length_m": 20.0, "goods_length_m": 1.2},
{"rail_height_m": 1.1, "rack_length_m": 20.0, "goods_length_m": 1.1},
]
# 2 Reihen a 10 m + goh_rack 5 m, oberste Schiene zuerst
assert [h["rack_length_m"] for h in og["hanging_levels"]] == [25.0, 25.0]
# 2 Reihen a 10 m, oberste Schiene zuerst
assert [h["rack_length_m"] for h in og["hanging_levels"]] == [20.0, 20.0]
assert og["hanging_levels"][0]["rail_height_m"] == 2.8
@@ -109,16 +107,16 @@ def test_belag_nur_auf_buehne(raw):
# Belag: Hauptgang 10 m2 + Quergang Spanplatte 0,84 m2
assert og["walkway"]["area_m2"] == pytest.approx(10.8)
assert og["walkway"]["spec"] == "chipboard"
# Gitterrost: Quergang 0,6 m2 + Reihen 2 x 7 m2 + goh_rack 3,5 m2
assert og["grating"] == pytest.approx(18.1)
# Gitterrost: Quergang 0,6 m2 + Reihen 2 x 7 m2
assert og["grating"] == pytest.approx(14.6)
def test_belag_ohne_gaenge_aus_kontur(raw):
raw["gaenge"] = []
overlay, s = lye.aggregiere(raw)
og = overlay["levels"][1]
# 60 m2 Kontur - (2 x 7 + 3,5) m2 Reihen
assert og["walkway"]["area_m2"] == pytest.approx(42.5)
# 60 m2 Kontur - 2 x 7 m2 Reihen
assert og["walkway"]["area_m2"] == pytest.approx(46.0)
assert "Konturflaeche" in s.provenance["levels[1].walkway.area_m2"]["formel"]
+10 -47
View File
@@ -3145,8 +3145,6 @@
(tu-nil "lg-haengeebenen-parse/ungueltig" (lg-haengeebenen-parse "x"))
(tu-eq "lg-haengeebenen-string" "2300/1200;1100/1100"
(lg-haengeebenen-string '((2300.0 1200.0) (1100.0 1100.0))))
(tu-eq "lg-haengeebenen-n/1" "2300/1200" (lg-haengeebenen-n "2300/1200;1100/1100" 1))
(tu-eq "lg-haengeebenen-n/zuviel" "2300/1200;1100/1100" (lg-haengeebenen-n "2300/1200;1100/1100" 5))
(tu-eq "lg-feld-pruefen/mm" "1000" (lg-feld-pruefen "mm" " 1000 "))
(tu-nil "lg-feld-pruefen/mm-neg" (lg-feld-pruefen "mm" "-5"))
(tu-nil "lg-feld-pruefen/mm-leer" (lg-feld-pruefen "mm" ""))
@@ -3300,19 +3298,7 @@
(tu-eq "lg-geschoss-punkt/3d-unten" 1 (lg-geschoss-fuer-punkt-kern '(50.0 50.0 100.0) _kand))
;; --- Geschoss kopieren ---
(tu-eq "lg-geschoss-aus-layer/regal" 2 (lg-geschoss-aus-layer "LG_Regal_G2"))
(tu-eq "lg-geschoss-aus-layer/12" 12 (lg-geschoss-aus-layer "LG_Reihe_G12"))
(tu-nil "lg-geschoss-aus-layer/ohne" (lg-geschoss-aus-layer "LG_Reihe"))
(tu-nil "lg-geschoss-aus-layer/0" (lg-geschoss-aus-layer "0"))
(tu-nil "lg-geschoss-aus-layer/suffix" (lg-geschoss-aus-layer "LG_X_G2a"))
(tu-nil "lg-geschoss-aus-layer/nil" (lg-geschoss-aus-layer nil))
;; 2D uebereinander: Kontur mehrdeutig, Layer entscheidet
(setq _kand2 (list (list 1 0.0 _sq0) (list 2 3100.0 _sq0)))
(tu-eq "lg-rack-geschoss/layer" 2 (lg-rack-geschoss "LG_Regal_G2" '(50.0 50.0 0.0) _kand2))
(tu-nil "lg-rack-geschoss/mehrdeutig" (lg-rack-geschoss "0" '(50.0 50.0 0.0) _kand2))
(tu-eq "lg-rack-geschoss/kontur" 1 (lg-rack-geschoss "0" '(50.0 50.0 0.0) (list (list 1 0.0 _sq0))))
;; Layer eines nicht vorhandenen Geschosses zaehlt nicht
(tu-eq "lg-rack-geschoss/layer-fremd" 1 (lg-rack-geschoss "LG_Regal_G7" '(50.0 50.0 0.0) (list (list 1 0.0 _sq0))))
(tu-eq "lg-kopie-belag/folgt" "spanplatte" (lg-kopie-belag "hallenboden" "hallenboden" "spanplatte"))
(tu-eq "lg-kopie-belag/eigen" "gitterrost" (lg-kopie-belag "gitterrost" "hallenboden" "spanplatte"))
(tu-nil "lg-kopie-belag/nil" (lg-kopie-belag nil "hallenboden" "spanplatte"))
@@ -3387,41 +3373,18 @@
'(((300.0 -500.0) (10000.0 -500.0) (10000.0 500.0) (300.0 500.0))) 500.0))
(tu-eq "lg-quelle-rang" '(2 1 0 0)
(mapcar 'lg-quelle-rang '("manuell" "auto_geaendert" "auto" nil)))
;; --- goh_rack-Erkennung: Parameterwerte, Namen, Transformationen ---
(tu-eqf "lg-zahl-einheit/mm" 700.0 (lg-zahl-einheit "700 mm"))
(tu-eqf "lg-zahl-einheit/cm" 718.752 (lg-zahl-einheit "71.8752 cm"))
(tu-eqf "lg-zahl-einheit/m" 12900.0 (lg-zahl-einheit "12,9 m"))
(tu-eqf "lg-zahl-einheit/ohne" 2.0 (lg-zahl-einheit "2"))
(tu-eqf "lg-zahl-einheit/zahl" 3.0 (lg-zahl-einheit 3))
(tu-nil "lg-zahl-einheit/km" (lg-zahl-einheit "5 km"))
(tu-nil "lg-zahl-einheit/text" (lg-zahl-einheit "abc"))
(tu-nil "lg-zahl-einheit/leer" (lg-zahl-einheit ""))
(tu-nil "lg-zahl-einheit/nil" (lg-zahl-einheit nil))
(tu-eqf "lg-racks-auswerten"
(tu-eqf "lg-reihen-auswerten"
'((1 2 3000.0 6000.0) (2 1 500.0 1500.0) (nil 2 700.0 1400.0))
(lg-racks-auswerten '((2 500.0 3.0) (nil 700.0 2.0) (1 1000.0 2.0)
(lg-reihen-auswerten '((2 500.0 3.0) (nil 700.0 2.0) (1 1000.0 2.0)
(1 2000.0 2.0) (nil nil 2.0))))
(tu-nil "lg-racks-auswerten/leer" (lg-racks-auswerten nil))
(tu-eq "lg-name-brauchbar-p/name" T (lg-name-brauchbar-p "goh_rack"))
(tu-nil "lg-name-brauchbar-p/anonym" (lg-name-brauchbar-p "*U29"))
(tu-nil "lg-name-brauchbar-p/leer" (lg-name-brauchbar-p ""))
;; Einfuegung bei (100,0), 90 Grad, x-Skalierung 2: lokales (1,0,0) -> (100,2,0)
(tu-eqf "lg-insert-tf/drehung-skalierung" '(100.0 2.0 0.0)
(lg-tf-pkt (lg-insert-tf (list '(2 . "TU_KEIN_BLOCK") '(10 100.0 0.0 0.0)
(cons 50 (/ pi 2.0)) '(41 . 2.0))
0 0)
'(1.0 0.0 0.0)))
;; MINSERT-Spalte 2 bei Spaltenabstand 3000, gedreht um 90 Grad -> entlang +Y
(tu-eqf "lg-insert-tf/minsert" '(0.0 6000.0 0.0)
(car (lg-insert-tf (list '(2 . "TU_KEIN_BLOCK") '(10 0.0 0.0 0.0) (cons 50 (/ pi 2.0))
'(70 . 3) '(44 . 3000.0))
2 0)))
;; verschachtelt: Container bei (1000,0) um 90 Grad, Kind bei lokal (0,2000)
(tu-eqf "lg-tf-verketten" '(-1000.0 0.0 0.0)
(car (lg-tf-verketten
(lg-insert-tf (list '(2 . "TU_KEIN_BLOCK") '(10 1000.0 0.0 0.0) (cons 50 (/ pi 2.0))) 0 0)
(lg-insert-tf (list '(2 . "TU_KEIN_BLOCK") '(10 0.0 2000.0 0.0)) 0 0))))
(tu-nil "lg-reihen-auswerten/leer" (lg-reihen-auswerten nil))
(tu-eqf "lg-reihe-eintrag"
'(2 4500.0 2.0)
(lg-reihe-eintrag '(("GESCHOSS" . "2") ("LAENGE" . "4500")
("HAENGEEBENEN" . "2300/1200;1100/1100"))))
(tu-eqf "lg-reihe-eintrag/leer"
'(nil nil 0.0)
(lg-reihe-eintrag '(("GESCHOSS" . "") ("HAENGEEBENEN" . ""))))
(tu-nil "lg-gang-aus-ecken/entartet"
(lg-gang-aus-ecken '((0.0 0.0) (4000.0 0.0) (4000.0 0.0) (0.0 0.0))))