diff --git a/CLAUDE.md b/CLAUDE.md index 0bf1c17..e3808d3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -125,7 +125,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `KettenFoerderer.lsp` | KETTENFOERDERER, KF_EDIT, KF_KS_PRUEFEN | Kettenfoerderer/Schraegfoerderer Stahl: baut aus `KF_UM_` -> `KF_LAENGE` -> `KF_AN_` (je KS_AUS auf KS_EIN) plus der Draufsicht `KF_2D` EINEN Block `KF_`. Daten `data/json/kettenfoerderer.json`, Dialog `dcl/kettenfoerderer.dcl`. **Geometrie**: SEITENANSICHT in der XY-Ebene (Hoehe = Y), ungedreht und nicht aufgerichtet, Einfuegepunkt = KS_EIN der Umlenkung; jeder Baustein bekommt nur den aus den KS gemessenen Verkettungswinkel (`insert-block-by-ks`/`insert-block-ks-skaliert`). 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`). **Hauptblock + Hilfsblock**: `KF_` traegt Beschriftung (`KF_1 26 Grad H=..mm L_horizontal=..mm`, Layer `kettenfoerderer_beschriftung`) und ein Hoehenmass (ActiveX `AddDimRotated`, scheitert es, wird ohne Mass gebaut) und ist der EINZIGE exportierte Block. Die Draufsicht `KF_2D` ist ein getrennter Hilfsblock `KF2D_` (kein Objekt, nur zum Anschliessen von Schienen): flach, auf die PROJIZIERTE Laenge skaliert (`kf-waagerecht-laenge`), beim ersten Einfuegen `ansicht_2d.versatz_y` (-1000) mm unter dem Hauptblock, danach frei verschieb- und loeschbar, gleiche Beschriftung. Beide Bloecke tragen denselben Schluessel als XDATA `SSG_KF_EDIT` (`kf-xdata-key`); KF_EDIT findet damit den - auch verschobenen - Hilfsblock (`kf-hilfsblock-finden`), behaelt dessen Lage und erzeugt ihn bei jedem Edit neu (auch wenn er geloescht war). Der Hilfsblock passt nicht aufs Export-Muster `KF_*`; `export_sivas.py` nimmt ausserdem nur `KF_`. Eine von Hand gesetzte Drehung des Hauptblocks (DXF 50) wird beim Edit wieder aufgesetzt. **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). `L_KF_mm` ist die WAAGERECHTE Laenge des ganzen Foerderers (der Draufsicht `KF_2D`, `kf-waagerecht-laenge`), nicht die Laenge des schraegen Mittelstuecks; sie geht NICHT in die Sivas-Zeile (Spalte Laenge bleibt leer) - Sivas berechnet ZL, EL und Kettenlaenge selbst, uebernommen wird nur die Hoehe (360). 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_` 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` | | `HwPlanung.lsp` | HW_MATERIALFLUSS, HW_SYMBOLE | Menue "HW Planung" (zwischen Lager und SPS). HW_MATERIALFLUSS ruft EXPORTCSV auf (alte `_export.csv` wird vorher geloescht, damit kein veralteter Stand gezeichnet wird) und danach `lib/hw_materialfluss.py` ueber `export:run-python` (Log `DXFM_LOG/hw_materialfluss.log`); Ergebnis ist eine NEUE Datei `DXFM_RESULTS/_HW.dxf` (`hw-dxf-name`, getestet), die offene Zeichnung bleibt unveraendert. HW_SYMBOLE ist noch ein Platzhalter (Hinweis) | | `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 | Lagerplanung GOH-Buehnenlager -> technische Daten als JSON fuer die RFQ-Dokumentation (Phase 0+1: Mengen, 2D; Konzept/Schema/Kennwerte in `doc/plan/lager_rfq.md`). Bloecke `LG_GESCHOSS` (Kopfsymbol, XDATA `SSG_LG` `kontur` -> Belagskontur), `LG_BEREICH` (Kontur + Parameter, fuellt sich selbst), `LG_REIHE__`/`LG_GANG___` (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`; `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 NUR `_lager.json` nach `DXFM_RESULTS` (Format `ssg-lager` Version 2, kein Python-Schritt; das RFQ-Projekt uebernimmt Mapping und Hand-Abgleich): alle Geschosse, Bereiche, Reihen und Gaenge mit Attributen und voller Geometrie (Konturpunkte, Start/Ende/Mitte, 4 Ecken) plus `kennwerte` je Geschoss und `lager` gesamt (lichte Hoehe, Regal-/Schienenlaenge, Haengeebenen, Gaenge je Art, Belags-/Gitterrostflaeche, Gitterkorb), je Geschoss-Kennwert `herkunft` (Formel + Quelle). Eigener JSON-Schreiber `lg-json-*` ueber getaggte Werte `(OBJ ...)`/`(ARR ...)` (`lg-json-text` rueckt ein, Nicht-ASCII als `\uXXXX`), Kennwerte in reinen Kernen (`lg-kennwerte-geschoss`/`-lager`, `lg-haengeebenen-summen`, `lg-gaenge-je-art`, `lg-reihen-offene-kanten`, `lg-reihen-gitterkorb-berechnen`). **Absturzsicherung unter den Reihen** je Bereich (`UNTER_REIHE` = `gitterrost`/`gitterkorb`/`keine`, Vorgabe `lager.json bereich.unter_reihe`, nur auf Buehnen wirksam): Gitterrost zaehlt die Reihengrundflaeche zur Gitterrostflaeche, Gitterkorb liefert Boden (Laenge x Tiefe) und Seitenflaeche = OFFENE Kantenlaenge x `GITTERKORB_HOEHE_mm` (Kanten an einer direkt anliegenden Nachbarreihe desselben Geschosses, z.B. Ruecken an Ruecken, zaehlen nicht; die Korbhoehe soll spaeter aus den Attributen berechnet werden). Regelwerk-Werte stehen noch nicht im Export (`doc/todo.md`). 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 neuen (`lg-kopie-belag`). Tests: `tu-tests-lager` (test_unit) und `tests/test_lager.lsp` | +| `LagerInsert.lsp` | LG_GESCHOSS, LG_GESCHOSS_AKTIV, LG_GESCHOSS_KOPIEREN, LG_BEREICH, LG_REIHE, LG_GANG, LG_EDIT, LG_REGALE, LAGER_EXPORT | Lagerplanung GOH-Buehnenlager -> technische Daten als JSON fuer die RFQ-Dokumentation (Phase 0+1: Mengen, 2D; Konzept/Schema/Kennwerte in `doc/plan/lager_rfq.md`). Bloecke `LG_GESCHOSS` (Kopfsymbol, XDATA `SSG_LG` `kontur` -> Belagskontur), `LG_BEREICH` (Kontur + Parameter, fuellt sich selbst), `LG_REIHE__`/`LG_GANG___` (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`; `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 NUR `_lager.json` nach `DXFM_RESULTS` (Format `ssg-lager` Version 2, kein Python-Schritt; das RFQ-Projekt uebernimmt Mapping und Hand-Abgleich): alle Geschosse, Bereiche, Reihen und Gaenge mit Attributen und voller Geometrie (Konturpunkte, Start/Ende/Mitte, 4 Ecken) plus `kennwerte` je Geschoss und `lager` gesamt (lichte Hoehe, Regal-/Schienenlaenge, Haengeebenen, Gaenge je Art und Breite, Belags-/Gitterrostflaeche, Gitterkorb, Regalrohr = Laenge x Haengeebenen), je Geschoss-Kennwert `herkunft` (Formel + Quelle). **`null` = fehlt (offener Punkt), nicht Zutreffendes wird weggelassen** (Marker `'ENTFAELLT`, `lg-json-ohne-entfallend`). Plausibilitaetswarnungen je Geschoss (`lg-plausibilitaet`, Grenzwerte aus dem Regelprofil). Das Reihen-Attribut `SCHIENEN` ist entfallen; `SCHIENEN_JE_GANG` am Bereich (Trolley) wird noch nicht ausgewertet. Eigener JSON-Schreiber `lg-json-*` ueber getaggte Werte `(OBJ ...)`/`(ARR ...)` (`lg-json-text` rueckt ein, Nicht-ASCII als `\uXXXX`), Kennwerte in reinen Kernen (`lg-kennwerte-geschoss`/`-lager`, `lg-haengeebenen-summen`, `lg-gaenge-je-art`, `lg-reihen-offene-kanten`, `lg-reihen-gitterkorb-berechnen`). **Absturzsicherung unter den Reihen** je Bereich (`UNTER_REIHE` = `gitterrost`/`gitterkorb`/`keine`, Vorgabe `lager.json bereich.unter_reihe`, nur auf Buehnen wirksam): Gitterrost zaehlt die Reihengrundflaeche zur Gitterrostflaeche, Gitterkorb liefert Boden (Laenge x Tiefe) und Seitenflaeche = OFFENE Kantenlaenge x `GITTERKORB_HOEHE_mm` (Kanten an einer direkt anliegenden Nachbarreihe desselben Geschosses, z.B. Ruecken an Ruecken, zaehlen nicht; die Korbhoehe soll spaeter aus den Attributen berechnet werden). Regelwerk-Werte stehen noch nicht im Export (`doc/todo.md`). 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 neuen (`lg-kopie-belag`). Tests: `tu-tests-lager` (test_unit) und `tests/test_lager.lsp` | | `LagerPruefung.lsp` | LG_REGELN | Regelprofile der Lagerplanung: `cfg/stahlbau/regelwerk/.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). | diff --git a/Lisp/LagerInsert.lsp b/Lisp/LagerInsert.lsp index 6b36b27..4ccc536 100644 --- a/Lisp/LagerInsert.lsp +++ b/Lisp/LagerInsert.lsp @@ -384,7 +384,7 @@ (setq *lg-schema-reihe* '(("ID" . "") ("GESCHOSS" . "") ("LAYER" . "") ("LAENGE" . "") ("TIEFE_mm" . "") - ("HAENGEEBENEN" . "") ("SCHIENEN" . "") ("BEREICH" . "") ("QUELLE" . ""))) + ("HAENGEEBENEN" . "") ("BEREICH" . "") ("QUELLE" . ""))) (setq *lg-schema-gang* '(("ID" . "") ("GESCHOSS" . "") ("LAYER" . "") ("LAENGE" . "") ("BREITE_mm" . "") @@ -638,8 +638,7 @@ (setq *lg-felder-reihe* '(("laenge" "LAENGE" "mm" nil) ("tiefe" "TIEFE_mm" "mm" nil) - ("ebenen" "HAENGEEBENEN" "ebenen" nil) - ("schienen" "SCHIENEN" "int0" nil))) + ("ebenen" "HAENGEEBENEN" "ebenen" nil))) ;; LG_GESCHOSS_KOPIEREN - die Tags sind reine Dialogwerte, kein Block-Schema. (setq *lg-felder-kopie* @@ -1379,7 +1378,6 @@ (setq werte-reihe (list (cons "GESCHOSS" gs) (cons "TIEFE_mm" (cdr (assoc "REGALTIEFE_mm" a))) (cons "HAENGEEBENEN" (cdr (assoc "HAENGEEBENEN" a))) - (cons "SCHIENEN" (cdr (assoc "SCHIENEN_JE_GANG" a))) (cons "BEREICH" (cdr (assoc "NR" a))) (cons "QUELLE" "auto"))) (foreach r (car erg) (setq p1 (ssg-punkt-drehen (cadr r) w '(0.0 0.0)) @@ -1916,8 +1914,7 @@ (setq werte (lg-dialog "lg_reihe" *lg-felder-reihe* (list (cons "LAENGE" "0") (cons "TIEFE_mm" (lg-mm-str (lg-zahl (lg-vorgabe '("bereich" "regaltiefe_mm") 700)))) - (cons "HAENGEEBENEN" (lg-vorgabe '("reihe" "haengeebenen") "2300/1200;1100/1100")) - (cons "SCHIENEN" (itoa (fix (lg-zahl (lg-vorgabe '("reihe" "schienen") 1)))))) + (cons "HAENGEEBENEN" (lg-vorgabe '("reihe" "haengeebenen") "2300/1200;1100/1100"))) '("laenge"))) (if werte (progn @@ -2100,11 +2097,19 @@ (defun lg-json-obj (paare) (strcat "{" - (ssg-join (mapcar '(lambda (p) (strcat (lg-json-str (car p)) ": " (lg-json-wert (cdr p)))) paare) + (ssg-join (mapcar '(lambda (p) (strcat (lg-json-str (car p)) ": " (lg-json-wert (cdr p)))) + (lg-json-ohne-entfallend paare)) ", ") "}") ) +;; Regel fuer fehlende Werte: null = "fehlt, muesste eingegeben werden" +;; (offener Punkt fuer den Konsumenten); 'ENTFAELLT = "trifft hier nicht zu" +;; - solche Felder werden gar nicht geschrieben. +(defun lg-json-ohne-entfallend (paare) + (vl-remove-if '(lambda (p) (eq (cdr p) 'ENTFAELLT)) paare) +) + (defun lg-json-container-p (v) (and v (listp v) (member (car v) '(OBJ ARR))) ) @@ -2141,7 +2146,8 @@ (setq innen (strcat einr " ") obj-p (eq (car v) 'OBJ)) (setq zeilen (if obj-p - (mapcar '(lambda (p) (strcat innen (lg-json-str (car p)) ": " (lg-json-text (cdr p) innen))) (cdr v)) + (mapcar '(lambda (p) (strcat innen (lg-json-str (car p)) ": " (lg-json-text (cdr p) innen))) + (lg-json-ohne-entfallend (cdr v))) (mapcar '(lambda (x) (strcat innen (lg-json-text x innen))) (cdr v)))) (if zeilen (strcat (if obj-p "{" "[") "\n" (ssg-join zeilen ",\n") "\n" einr (if obj-p "}" "]")) @@ -2150,7 +2156,12 @@ ) ;; --- Zugriff auf OBJ-Records --- -(defun lg-j (obj key) (cdr (assoc key (cdr obj)))) +;; Feld eines OBJ; nil, wenn es fehlt, ENTFAELLT ist oder obj kein OBJ ist. +(defun lg-j (obj key / v) + (if (and obj (listp obj) (eq (car obj) 'OBJ)) + (progn (setq v (cdr (assoc key (cdr obj)))) + (if (eq v 'ENTFAELLT) nil v))) +) (defun lg-j-setzen (obj key wert / alt) (if (setq alt (assoc key (cdr obj))) @@ -2162,10 +2173,36 @@ (defun lg-j-bbox (bb) (if bb (cons 'ARR (append (car bb) (cadr bb))))) (defun lg-n (v) (if (numberp v) (float v) 0.0)) +;; Freiraum unter der Ware je Haengeebene (reiner Kern): Schienenhoehe - +;; Warenlaenge - naechsttiefere Schienenhoehe (unterste Ebene: - 0 = Belag). +;; ebenen = ((schienenhoehe warenlaenge) ...); Rueckgabe ((h w frei) ...), +;; nach Schienenhoehe absteigend. frei <= 0: Ware stoesst an. +(defun lg-ebenen-freiraum (ebenen / sort erg rest) + (setq sort (vl-sort ebenen '(lambda (a b) (> (car a) (car b)))) erg nil) + (while sort + (setq rest (cdr sort)) + (setq erg (cons (list (car (car sort)) (cadr (car sort)) + (- (car (car sort)) (cadr (car sort)) (if rest (car (car rest)) 0.0))) + erg) + sort rest)) + (reverse erg) +) + (defun lg-j-ebenen (s) (cons 'ARR - (mapcar '(lambda (e) (list 'OBJ (cons "schienenhoehe_mm" (car e)) (cons "warenlaenge_mm" (cadr e)))) - (lg-haengeebenen-parse s))) + (mapcar '(lambda (e) (list 'OBJ (cons "schienenhoehe_mm" (car e)) (cons "warenlaenge_mm" (cadr e)) + (cons "freiraum_unter_mm" (caddr e)))) + (lg-ebenen-freiraum (lg-haengeebenen-parse s)))) +) + +;; Ausrichtung eines Gangs gegen die Reihenrichtung seines Bereichs (beide +;; in Grad): "laengs" (Abweichung < 45 Grad, Richtung egal) oder "quer"; +;; nil ohne Reihenrichtung. Rein. +(defun lg-ausrichtung (winkel richtung / d) + (if (and (numberp winkel) (numberp richtung)) + (progn + (setq d (rem (abs (- winkel richtung)) 180.0)) + (if (< (min d (- 180.0 d)) 45.0) "laengs" "quer"))) ) ;; Attributwert als Zahl bzw. Ganzzahl (nil, wenn leer). @@ -2203,22 +2240,40 @@ (> (car (car a)) (car (car b)))))))) ) -;; Gaenge je ART: (OBJ ("gang" . (OBJ anzahl laenge_mm flaeche_mm2)) ...), -;; gang/quergang/randgang immer vorhanden, weitere Arten dahinter. -(defun lg-gaenge-je-art (gaenge / erg art x l f) - (setq erg (mapcar '(lambda (a) (list a 0 0.0 0.0)) '("gang" "quergang" "randgang"))) +;; Gaenge je ART: (OBJ ("gang" . (OBJ anzahl laenge_mm flaeche_mm2 +;; anzahl_quer nach_breite)) ...), gang/quergang/randgang immer vorhanden, +;; weitere Arten dahinter. anzahl_quer = Gaenge mit ausrichtung "quer"; +;; nach_breite = je Breite Anzahl/Laenge/Flaeche (Sonderflaechen erkennbar, +;; keine verfaelschte Durchschnittsbreite). +(defun lg-gaenge-je-art (gaenge / erg art x l b f br bx) + (setq erg (mapcar '(lambda (a) (list a 0 0.0 0.0 0 nil)) '("gang" "quergang" "randgang"))) (foreach g gaenge - (setq art (cond ((lg-j g "art")) ("unbekannt")) - x (assoc art erg) + (setq art (cond ((lg-j g "art")) ("unbekannt"))) + (if (null (assoc art erg)) (setq erg (append erg (list (list art 0 0.0 0.0 0 nil))))) + (setq x (assoc art erg) l (lg-n (lg-j g "laenge_mm")) - f (* l (lg-n (lg-j g "breite_mm")))) - (setq erg (if x - (subst (list art (1+ (cadr x)) (+ (caddr x) l) (+ (cadddr x) f)) x erg) - (append erg (list (list art 1 l f)))))) + b (lg-n (lg-j g "breite_mm")) + f (* l b) + br (nth 5 x) + bx (assoc b br) + br (if bx + (subst (list b (1+ (cadr bx)) (+ (caddr bx) l) (+ (cadddr bx) f)) bx br) + (cons (list b 1 l f) br))) + (setq erg (subst (list art (1+ (nth 1 x)) (+ (nth 2 x) l) (+ (nth 3 x) f) + (+ (nth 4 x) (if (equal (lg-j g "ausrichtung") "quer") 1 0)) br) + x erg))) (cons 'OBJ - (mapcar '(lambda (x) (cons (car x) (list 'OBJ (cons "anzahl" (cadr x)) - (cons "laenge_mm" (caddr x)) - (cons "flaeche_mm2" (cadddr x))))) + (mapcar '(lambda (x) + (cons (car x) + (list 'OBJ (cons "anzahl" (nth 1 x)) + (cons "laenge_mm" (nth 2 x)) + (cons "flaeche_mm2" (nth 3 x)) + (cons "anzahl_quer" (nth 4 x)) + (cons "nach_breite" + (cons 'ARR + (mapcar '(lambda (y) (list 'OBJ (cons "breite_mm" (car y)) (cons "anzahl" (cadr y)) + (cons "laenge_mm" (caddr y)) (cons "flaeche_mm2" (cadddr y)))) + (vl-sort (nth 5 x) '(lambda (a b) (< (car a) (car b)))))))))) erg)) ) @@ -2311,12 +2366,22 @@ (cons key (list 'OBJ (cons "formel" formel) (cons "quelle" quelle))) ) +;; Huelle einer bbox (ARR xmin ymin xmax ymax) als OBJ, nil ohne bbox. +(defun lg-huelle (bbox / b dx dy) + (if (setq b (cdr bbox)) + (progn + (setq dx (- (caddr b) (car b)) dy (- (cadddr b) (cadr b))) + (list 'OBJ (cons "bbox" bbox) (cons "laenge_mm" (max dx dy)) (cons "breite_mm" (min dx dy))))) +) + ;; Kennwerte eines Geschosses. g = Geschoss-Record, nx = Record des ;; naechsthoeheren Geschosses (nil = oberstes), reihen/gaenge = Records ;; dieses Geschosses (Reihen mit unter_reihe/gitterkorb), n-bereiche = -;; Anzahl Bereiche. Rueckgabe (kennwerte herkunft), beide OBJ. +;; Anzahl Bereiche. Rueckgabe (kennwerte herkunft), beide OBJ. Felder, die +;; nicht zutreffen (Belag/Gitterrost/Gitterkorb auf Hallenboden), sind +;; ENTFAELLT; nil = nicht berechenbar (fehlende Eingabe). (defun lg-kennwerte-geschoss (g nx reihen gaenge n-bereiche / nrs q qr buehne hk lichte regal grund - schienen gitter-r korb gk l f belag-g gitter-g belag gitter) + rohr gitter-r offen-r korb gk l f u belag-g gitter-g belag gitter) (setq nrs (vl-princ-to-string (lg-j g "nr")) q (strcat "LG_GESCHOSS " nrs) qr (strcat (itoa (length reihen)) " Regalreihe(n) LG_REIHE_* Geschoss " nrs) @@ -2324,8 +2389,8 @@ hk nil) ;; lichte Hoehe: Vorgabe am Geschoss, sonst aus dem Geschoss darueber (cond - ((numberp (lg-j g "lichte_hoehe_mm")) - (setq lichte (lg-j g "lichte_hoehe_mm") + ((numberp (lg-j g "lichte_hoehe_vorgabe_mm")) + (setq lichte (lg-j g "lichte_hoehe_vorgabe_mm") hk (cons (lg-herkunft "lichte_hoehe_mm" "LICHTE_HOEHE_mm (Vorgabe am Geschoss)" q) hk))) (nx (setq lichte (- (lg-n (lg-j nx "hoehe_belag_mm")) (lg-n (lg-j nx "konstr_hoehe_mm")) @@ -2334,31 +2399,37 @@ "HOEHE_BELAG_mm darueber - KONSTR_HOEHE_mm darueber - eigene HOEHE_BELAG_mm" (strcat q " / " (vl-princ-to-string (lg-j nx "nr")))) hk))) - (T (setq lichte nil)) + (T (setq lichte nil + hk (cons (lg-herkunft "lichte_hoehe_mm" + "oberstes Geschoss ohne LICHTE_HOEHE_mm: nicht berechenbar (Eingabe fehlt)" q) hk))) ) ;; Regalreihen - (setq regal 0.0 grund 0.0 schienen 0.0 gitter-r 0.0 korb (list 0 0.0 0.0 0.0 0.0)) + (setq regal 0.0 grund 0.0 rohr 0.0 gitter-r 0.0 offen-r 0.0 korb (list 0 0.0 0.0 0.0 0.0)) (foreach r reihen (setq l (lg-n (lg-j r "laenge_mm")) - f (* l (lg-n (lg-j r "tiefe_mm")))) + f (* l (lg-n (lg-j r "tiefe_mm"))) + u (lg-j r "unter_reihe")) (setq regal (+ regal l) grund (+ grund f) - schienen (+ schienen (* l (if (numberp (lg-j r "schienen")) (lg-j r "schienen") 1)))) + rohr (+ rohr (* l (length (cdr (lg-j r "haengeebenen")))))) (cond - ((equal (lg-j r "unter_reihe") "gitterrost") (setq gitter-r (+ gitter-r f))) + ((equal u "gitterrost") (setq gitter-r (+ gitter-r f))) ((setq gk (lg-j r "gitterkorb")) (setq korb (list (1+ (nth 0 korb)) (+ (nth 1 korb) (lg-n (lg-j gk "bodenflaeche_mm2"))) (+ (nth 2 korb) (lg-n (lg-j gk "seitenflaeche_mm2"))) (+ (nth 3 korb) (lg-n (lg-j gk "offen_laengs_mm"))) - (+ (nth 4 korb) (lg-n (lg-j gk "offen_stirn_mm"))))))) + (+ (nth 4 korb) (lg-n (lg-j gk "offen_stirn_mm")))))) + ((equal u "keine") (setq offen-r (+ offen-r f)))) ) (setq hk (append (reverse (list (lg-herkunft "regallaenge_mm" "Summe LAENGE der Regalreihen" qr) (lg-herkunft "regalgrundflaeche_mm2" "Summe LAENGE x TIEFE_mm der Regalreihen" qr) - (lg-herkunft "schienenlaenge_mm" "Summe LAENGE x SCHIENEN der Regalreihen" qr) + (lg-herkunft "regalrohrlaenge_mm" + "Summe LAENGE x Anzahl Haengeebenen der Regalreihen (Regalrohr je Haengeebene; Trolley-Schienen nicht enthalten)" qr) (lg-herkunft "haengeebenen" "je Schienenhoehe/Warenlaenge: Summe LAENGE aller Reihen mit dieser Haengeebene" qr) - (lg-herkunft "gaenge" "je ART: Anzahl, Summe LAENGE, Summe LAENGE x BREITE_mm" - (strcat (itoa (length gaenge)) " Flaeche(n) LG_GANG_* Geschoss " nrs)))) + (lg-herkunft "gaenge" "je ART: Anzahl, Summe LAENGE, Summe LAENGE x BREITE_mm, Anzahl quer zur Reihenrichtung, Aufteilung nach BREITE_mm" + (strcat (itoa (length gaenge)) " Flaeche(n) LG_GANG_* Geschoss " nrs)) + (lg-herkunft "huelle" "achsparallele Huelle der Belagskontur, laenge_mm = laengere Seite" q))) hk)) ;; Belag und Gitterrost (nur Buehne) (setq belag-g 0.0 gitter-g 0.0) @@ -2387,28 +2458,35 @@ (strcat "Reihen mit UNTER_REIHE gitterkorb: Boden = LAENGE x TIEFE_mm," " Seiten = offene Kantenlaenge x GITTERKORB_HOEHE_mm" " (Kanten an einer direkt anliegenden Nachbarreihe zaehlen nicht)") + qr) hk)) + (setq hk (cons (lg-herkunft "ohne_absturzsicherung_mm2" + "LAENGE x TIEFE_mm der Reihen mit UNTER_REIHE keine (offene Flaeche zum Geschoss darunter)" qr) hk))) - (setq belag nil gitter nil - hk (cons (lg-herkunft "buehne" "BELAG_ART hallenboden (oder leer): keine Buehne, kein Belag/Gitterrost/Gitterkorb" q) hk)) + (setq belag 'ENTFAELLT gitter 'ENTFAELLT + hk (cons (lg-herkunft "buehne" "BELAG_ART hallenboden (oder leer): keine Buehne - Belag, Gitterrost, Gitterkorb und Absturzsicherung entfallen" q) hk)) ) (list (list 'OBJ (cons "lichte_hoehe_mm" lichte) (cons "buehne" (if buehne T 'FALSE)) + (cons "huelle" (lg-huelle (lg-j (lg-j g "kontur") "bbox"))) (cons "bereiche" n-bereiche) (cons "reihen" (length reihen)) (cons "regallaenge_mm" regal) (cons "regalgrundflaeche_mm2" grund) - (cons "schienenlaenge_mm" schienen) + (cons "regalrohrlaenge_mm" rohr) (cons "haengeebenen" (lg-haengeebenen-summen reihen)) (cons "gaenge" (lg-gaenge-je-art gaenge)) (cons "belagsflaeche_mm2" belag) (cons "gitterrostflaeche_mm2" gitter) - (cons "gitterkorb" (list 'OBJ (cons "reihen" (nth 0 korb)) - (cons "bodenflaeche_mm2" (nth 1 korb)) - (cons "seitenflaeche_mm2" (nth 2 korb)) - (cons "offen_laengs_mm" (nth 3 korb)) - (cons "offen_stirn_mm" (nth 4 korb))))) + (cons "gitterkorb" (if buehne + (list 'OBJ (cons "reihen" (nth 0 korb)) + (cons "bodenflaeche_mm2" (nth 1 korb)) + (cons "seitenflaeche_mm2" (nth 2 korb)) + (cons "offen_laengs_mm" (nth 3 korb)) + (cons "offen_stirn_mm" (nth 4 korb))) + 'ENTFAELLT)) + (cons "ohne_absturzsicherung_mm2" (if buehne offen-r 'ENTFAELLT))) (cons 'OBJ (reverse hk))) ) @@ -2416,36 +2494,134 @@ (apply '+ (cons 0.0 (mapcar '(lambda (o) (lg-n (lg-j o key))) objs))) ) -;; Kennwerte des ganzen Lagers. geschosse = Geschoss-Records mit kennwerte -;; und kontur, reihen/gaenge = alle einem Geschoss zugeordneten Records. -(defun lg-kennwerte-lager (geschosse reihen gaenge n-bereiche / kws korb bbs xmin ymin xmax ymax dx dy) +;; Kennwerte des ganzen Lagers. geschosse = Geschoss-Records mit kennwerte, +;; reihen/gaenge = alle einem Geschoss zugeordneten Records. Die Summen +;; stehen ausdruecklich unter summe_alle_geschosse; grundriss_max ist der +;; groesste Geschossgrundriss (die Geschosse koennen im Plan nebeneinander +;; liegen - eine gemeinsame Huelle waere kein Gebaeudemass). +(defun lg-kennwerte-lager (geschosse reihen gaenge n-bereiche / kws korb hs) (setq kws (mapcar '(lambda (g) (lg-j g "kennwerte")) geschosse) - korb (mapcar '(lambda (k) (lg-j k "gitterkorb")) kws) - bbs (vl-remove nil (mapcar '(lambda (g) (cdr (lg-j (lg-j g "kontur") "bbox"))) geschosse))) - (if bbs - (setq xmin (apply 'min (mapcar 'car bbs)) ymin (apply 'min (mapcar 'cadr bbs)) - xmax (apply 'max (mapcar 'caddr bbs)) ymax (apply 'max (mapcar 'cadddr bbs)) - dx (- xmax xmin) dy (- ymax ymin))) + korb (vl-remove nil (mapcar '(lambda (k) (lg-j k "gitterkorb")) kws)) + hs (vl-remove nil (mapcar '(lambda (k) (lg-j k "huelle")) kws))) (list 'OBJ (cons "geschosse" (length geschosse)) (cons "bereiche" n-bereiche) - (cons "reihen" (length reihen)) - (cons "regallaenge_mm" (lg-summe-feld kws "regallaenge_mm")) - (cons "regalgrundflaeche_mm2" (lg-summe-feld kws "regalgrundflaeche_mm2")) - (cons "schienenlaenge_mm" (lg-summe-feld kws "schienenlaenge_mm")) - (cons "haengeebenen" (lg-haengeebenen-summen reihen)) - (cons "gaenge" (lg-gaenge-je-art gaenge)) - (cons "belagsflaeche_mm2" (lg-summe-feld kws "belagsflaeche_mm2")) - (cons "gitterrostflaeche_mm2" (lg-summe-feld kws "gitterrostflaeche_mm2")) - (cons "gitterkorb" (list 'OBJ (cons "reihen" (fix (lg-summe-feld korb "reihen"))) - (cons "bodenflaeche_mm2" (lg-summe-feld korb "bodenflaeche_mm2")) - (cons "seitenflaeche_mm2" (lg-summe-feld korb "seitenflaeche_mm2")) - (cons "offen_laengs_mm" (lg-summe-feld korb "offen_laengs_mm")) - (cons "offen_stirn_mm" (lg-summe-feld korb "offen_stirn_mm")))) - (cons "huelle" (if bbs - (list 'OBJ (cons "bbox" (list 'ARR xmin ymin xmax ymax)) - (cons "laenge_mm" (max dx dy)) - (cons "breite_mm" (min dx dy)))))) + (cons "grundriss_max" (if hs + (list 'OBJ (cons "laenge_mm" (apply 'max (mapcar '(lambda (h) (lg-j h "laenge_mm")) hs))) + (cons "breite_mm" (apply 'max (mapcar '(lambda (h) (lg-j h "breite_mm")) hs)))))) + (cons "summe_alle_geschosse" + (list 'OBJ + (cons "reihen" (length reihen)) + (cons "regallaenge_mm" (lg-summe-feld kws "regallaenge_mm")) + (cons "regalgrundflaeche_mm2" (lg-summe-feld kws "regalgrundflaeche_mm2")) + (cons "regalrohrlaenge_mm" (lg-summe-feld kws "regalrohrlaenge_mm")) + (cons "haengeebenen" (lg-haengeebenen-summen reihen)) + (cons "gaenge" (lg-gaenge-je-art gaenge)) + (cons "belagsflaeche_mm2" (lg-summe-feld kws "belagsflaeche_mm2")) + (cons "gitterrostflaeche_mm2" (lg-summe-feld kws "gitterrostflaeche_mm2")) + (cons "gitterkorb" (list 'OBJ (cons "reihen" (fix (lg-summe-feld korb "reihen"))) + (cons "bodenflaeche_mm2" (lg-summe-feld korb "bodenflaeche_mm2")) + (cons "seitenflaeche_mm2" (lg-summe-feld korb "seitenflaeche_mm2")) + (cons "offen_laengs_mm" (lg-summe-feld korb "offen_laengs_mm")) + (cons "offen_stirn_mm" (lg-summe-feld korb "offen_stirn_mm")))) + (cons "ohne_absturzsicherung_mm2" (lg-summe-feld kws "ohne_absturzsicherung_mm2"))))) +) + +;; --- Plausibilitaet (reiner Kern, getestet) --- +;; Prueft ein Geschoss auf Eingaben, die fuer die Ausschreibung kaum stimmen +;; koennen. grenzen = Alist aus dem Regelwerk (("gang_min" wert quelle) +;; ("lichte_min" wert quelle)), fehlende Grenzen werden nicht geprueft. +;; Rueckgabe: Liste von Warntexten. +(defun lg-plausibilitaet (g kw reihen gaenge grenzen / nrs w buehne gm lm schmal quer rand neben + ebenen-texte frei top lichte) + (setq nrs (vl-princ-to-string (lg-j g "nr")) w nil + buehne (lg-buehne-p (lg-j g "belag_art")) + lichte (lg-j kw "lichte_hoehe_mm") + gm (cdr (assoc "gang_min" grenzen)) + lm (cdr (assoc "lichte_min" grenzen))) + ;; Buehne ohne Konstruktionshoehe + (if (and buehne (<= (lg-n (lg-j g "konstr_hoehe_mm")) 0.0)) + (setq w (cons (ssg-textf "lg-pl-konstr-null" (list nrs)) w))) + ;; Buehne mit offenen Flaechen unter Reihen + (if (and buehne (> (lg-n (lg-j kw "ohne_absturzsicherung_mm2")) 0.0)) + (setq w (cons (ssg-textf "lg-pl-unter-keine" + (list nrs (rtos (/ (lg-j kw "ohne_absturzsicherung_mm2") 1.0e6) 2 1))) w))) + ;; lichte Hoehe unter dem Regelwerk + (if (and lm (numberp lichte) (< lichte (car lm))) + (setq w (cons (ssg-textf "lg-pl-lichte-klein" + (list nrs (lg-mm-str lichte) (lg-mm-str (car lm)) (cadr lm))) w))) + ;; zu schmale Gaenge + (if gm + (progn + (setq schmal (vl-remove-if-not '(lambda (x) (< (lg-n (lg-j x "breite_mm")) (car gm))) gaenge)) + (if schmal + (setq w (cons (ssg-textf "lg-pl-gang-schmal" + (list nrs (itoa (length schmal)) + (ssg-join (lg-unikat (mapcar '(lambda (x) (lg-mm-str (lg-j x "breite_mm"))) schmal)) ", ") + (lg-mm-str (car gm)) (cadr gm))) w))))) + ;; als "gang" eingetragen, liegt aber quer zur Reihenrichtung + (setq quer (vl-remove-if-not '(lambda (x) (and (equal (lg-j x "art") "gang") + (equal (lg-j x "ausrichtung") "quer"))) + gaenge)) + (if quer + (setq w (cons (ssg-textf "lg-pl-gang-quer" + (list nrs (itoa (length quer)) (ssg-join (mapcar '(lambda (x) (vl-princ-to-string (lg-j x "id"))) quer) ", "))) + w))) + ;; Gang direkt neben einem Randgang (doppelte Randzone?) + (setq rand (mapcar '(lambda (x) (mapcar 'cdr (cdr (lg-j x "ecken")))) + (vl-remove-if-not '(lambda (x) (equal (lg-j x "art") "randgang")) gaenge))) + (if rand + (progn + (setq neben (vl-remove-if-not + '(lambda (x / e k) + (if (not (equal (lg-j x "art") "randgang")) + (progn + (setq e (mapcar 'cdr (cdr (lg-j x "ecken"))) k (lg-rechteck-kanten e)) + (vl-some '(lambda (kante / len) + (setq len (distance (car kante) (cadr kante))) + (< (lg-kante-offen kante rand 1.0) (- len 1.0))) + (list (nth 0 k) (nth 2 k)))))) + gaenge)) + (if neben + (setq w (cons (ssg-textf "lg-pl-gang-neben-randgang" + (list nrs (itoa (length neben)) (ssg-join (mapcar '(lambda (x) (vl-princ-to-string (lg-j x "id"))) neben) ", "))) + w))))) + ;; Haengeebenen: kein Freiraum unter der Ware, oberste Schiene ueber der lichten Hoehe + (setq ebenen-texte nil top nil) + (foreach r reihen + (foreach e (cdr (lg-j r "haengeebenen")) + (if (or (null top) (> (lg-n (lg-j e "schienenhoehe_mm")) top)) (setq top (lg-n (lg-j e "schienenhoehe_mm")))) + (if (<= (lg-n (lg-j e "freiraum_unter_mm")) 0.0) + (setq ebenen-texte (cons (strcat (lg-mm-str (lg-j e "schienenhoehe_mm")) "/" (lg-mm-str (lg-j e "warenlaenge_mm")) + " (" (lg-mm-str (lg-j e "freiraum_unter_mm")) ")") + ebenen-texte))))) + (if ebenen-texte + (setq w (cons (ssg-textf "lg-pl-freiraum" (list nrs (ssg-join (lg-unikat (reverse ebenen-texte)) ", "))) w))) + (if (and top (numberp lichte) (>= top lichte)) + (setq w (cons (ssg-textf "lg-pl-schiene-ueber-lichte" (list nrs (lg-mm-str top) (lg-mm-str lichte))) w))) + (reverse w) +) + +;; Liste ohne Wiederholungen, Reihenfolge des ersten Auftretens. +(defun lg-unikat (l / erg) + (foreach x l (if (not (member x erg)) (setq erg (cons x erg)))) + (reverse erg) +) + +;; Grenzwerte fuer lg-plausibilitaet aus dem Regelprofil des Landes, mit +;; dem Geschoss als Kontext. Fehlt das Profil, bleibt die Liste leer. +(defun lg-plausibilitaet-grenzen (g land / kontext regel erg w) + (setq kontext (vl-remove-if '(lambda (p) (null (cdr p))) + (list (cons "brandgefaehrdung" (lg-j g "brandgefaehrdung")) + (cons "personen" (lg-j g "personen")))) + erg nil) + (foreach p '(("gang_min" . "gang.breite_nebengang_min") ("lichte_min" . "lichte_hoehe.verkehrsweg_min")) + (if (and (car (atoms-family 1 '("LG-REGEL-AUFLOESEN"))) + (setq regel (lg-regel-finden (lg-profil land) (cdr p))) + (setq w (lg-regel-aufloesen regel kontext)) + (numberp (car w))) + (setq erg (cons (list (car p) (float (car w)) (strcat (cdr p) ": " (lg-eintrag-quelle (cadr w)))) erg)))) + erg ) ;; --- Records aus der Zeichnung --- @@ -2473,7 +2649,8 @@ (cons "layer" (lg-ent-layer (car g))) (cons "hoehe_belag_mm" (lg-a-zahl a "HOEHE_BELAG_mm")) (cons "konstr_hoehe_mm" (lg-a-zahl a "KONSTR_HOEHE_mm")) - (cons "lichte_hoehe_mm" (lg-a-zahl a "LICHTE_HOEHE_mm")) + ;; nur die Eingabe am Geschoss; der wirksame Wert steht in kennwerte + (cons "lichte_hoehe_vorgabe_mm" (cond ((lg-a-zahl a "LICHTE_HOEHE_mm")) ('ENTFAELLT))) (cons "belag_art" (cdr (assoc "BELAG_ART" a))) (cons "personen" (lg-a-int a "PERSONEN")) (cons "brandgefaehrdung" (cdr (assoc "BRANDGEFAEHRDUNG" a))) @@ -2490,7 +2667,8 @@ (cons "gangbreite_mm" (lg-a-zahl a "GANGBREITE_mm")) (cons "regaltiefe_mm" (lg-a-zahl a "REGALTIEFE_mm")) (cons "reihen_je_gang" (lg-a-int a "REIHEN_JE_GANG")) - (cons "schienen_je_gang" (lg-a-int a "SCHIENEN_JE_GANG")) + ;; Trolley-Schienen je Gang: Eingabe, wird noch nicht ausgewertet + (cons "trolleyschienen_je_gang" (lg-a-int a "SCHIENEN_JE_GANG")) (cons "quergang_abstand_mm" (lg-a-zahl a "QUERGANG_ABSTAND_mm")) (cons "quergang_breite_mm" (lg-a-zahl a "QUERGANG_BREITE_mm")) (cons "richtung_grad" (lg-a-zahl a "RICHTUNG")) @@ -2508,8 +2686,8 @@ ;; Reihe oder Gang: Attribute plus Geometrie (Start/Ende/Mitte in WCS mit Z, ;; Ecken des Grundrisses 2D aus lg-linie-polygon). -(defun lg-export-linie-rec (e art / a ed p1 z rot l b p2 quelle) - (setq a (ssg-attrib-read e) ed (entget e) +(defun lg-export-linie-rec (e art / a ed p1 z rot l b p2 quelle bh) + (setq a (ssg-attrib-read e) ed (entget e) bh (lg-xdata-wert e "bereich") p1 (cdr (assoc 10 ed)) z (cond ((caddr p1)) (0.0)) rot (cond ((cdr (assoc 50 ed))) (0.0)) l (lg-a-zahl a "LAENGE") @@ -2523,13 +2701,13 @@ (cons "handle" (lg-handle e)) (cons "layer" (lg-ent-layer e)) (cons "geschoss" (lg-a-int a "GESCHOSS")) - (cons "bereich" (lg-a-int a "BEREICH")) - (cons "bereich_handle" (lg-xdata-wert e "bereich")) + ;; ohne Bereich (frei gesetzt) entfallen beide Felder + (cons "bereich" (if bh (lg-a-int a "BEREICH") 'ENTFAELLT)) + (cons "bereich_handle" (if bh bh 'ENTFAELLT)) (cons "quelle" quelle) (cons "laenge_mm" l)) (if (= art "reihe") (list (cons "tiefe_mm" b) - (cons "schienen" (lg-a-int a "SCHIENEN")) (cons "haengeebenen" (lg-j-ebenen (cdr (assoc "HAENGEEBENEN" a))))) (list (cons "breite_mm" b) (cons "art" (cdr (assoc "ART" a))) @@ -2556,12 +2734,25 @@ "gitterkorb" (if (= u "gitterkorb") (list 'OBJ (cons "hoehe_mm" (cond ((lg-j br "gitterkorb_hoehe_mm")) - ((lg-zahl (lg-vorgabe '("bereich" "gitterkorb_hoehe_mm") nil))))))))) + ((lg-zahl (lg-vorgabe '("bereich" "gitterkorb_hoehe_mm") nil)))))) + 'ENTFAELLT))) reihen) ) +;; ausrichtung je Gang (laengs/quer) gegen die Reihenrichtung seines Bereichs; +;; ohne Bereich entfaellt das Feld. +(defun lg-gaenge-ausrichtung-setzen (gaenge bereiche / br) + (mapcar + '(lambda (x / br) + (setq br (if (lg-j x "bereich_handle") + (vl-some '(lambda (b) (if (equal (lg-j b "handle") (lg-j x "bereich_handle")) b)) bereiche))) + (lg-j-setzen x "ausrichtung" + (cond ((lg-ausrichtung (lg-j x "winkel_grad") (lg-j br "richtung_grad"))) ('ENTFAELLT)))) + gaenge) +) + ;; Alle Daten des Lagers als OBJ (Grundlage von lg-export-json). -(defun lg-export-daten ( / warn gs bereiche reihen gaenge g-recs vorgabe g-neu r-neu r-gs g-gs i g nx nr nrs kw) +(defun lg-export-daten ( / warn gs bereiche reihen gaenge g-recs vorgabe g-neu r-neu r-gs g-gs i g nx nr nrs kw t1) (setq gs (lg-geschosse) warn nil vorgabe (lg-unter-reihe-vorgabe)) (if (null gs) (setq warn (cons (ssg-text "lg-exp-keine-geschosse") warn))) (foreach g gs @@ -2575,7 +2766,8 @@ '(lambda (a b / ha hb) (setq ha (lg-n (lg-j a "hoehe_belag_mm")) hb (lg-n (lg-j b "hoehe_belag_mm"))) (if (equal ha hb 1e-6) (< (lg-j a "nr") (lg-j b "nr")) (< ha hb))))) - (setq reihen (lg-reihen-unter-setzen reihen bereiche g-recs vorgabe)) + (setq reihen (lg-reihen-unter-setzen reihen bereiche g-recs vorgabe) + gaenge (lg-gaenge-ausrichtung-setzen gaenge bereiche)) (setq g-neu nil r-neu nil r-gs nil g-gs nil i 0) (foreach g g-recs (setq nr (lg-j g "nr") @@ -2592,6 +2784,9 @@ (if (and (equal (lg-j b "geschoss") nr) (= (lg-j b "unter_reihe") "gitterkorb")) (setq warn (cons (ssg-textf "lg-exp-korb-hallenboden" (list (vl-princ-to-string (lg-j b "nr")) (itoa nr))) warn))))) + ;; Plausibilitaet gegen das Regelprofil (nur Warnungen) + (foreach t1 (lg-plausibilitaet g (car kw) r-gs g-gs (lg-plausibilitaet-grenzen g (lg-land))) + (setq warn (cons t1 warn))) (setq g-neu (cons (lg-j-setzen (lg-j-setzen g "kennwerte" (car kw)) "herkunft" (cadr kw)) g-neu) r-neu (append r-neu r-gs) i (1+ i))) diff --git a/data/json/lager.json b/data/json/lager.json index ff67684..b89f2c3 100644 --- a/data/json/lager.json +++ b/data/json/lager.json @@ -41,8 +41,7 @@ }, "reihe": { - "beschreibung": "haengeebenen = Schienenhoehe ueber Belag / max. Warenlaenge je Haengeebene, durch Semikolon getrennt, oberste zuerst.", - "haengeebenen": "2300/1200;1100/1100", - "schienen": 1 + "beschreibung": "haengeebenen = Schienenhoehe ueber Belag / max. Warenlaenge je Haengeebene, durch Semikolon getrennt, oberste zuerst. Jede Haengeebene ist ein Regalrohr ueber die Reihenlaenge.", + "haengeebenen": "2300/1200;1100/1100" } } diff --git a/dcl/lager.dcl b/dcl/lager.dcl index bc2c2d1..7d91f4b 100644 --- a/dcl/lager.dcl +++ b/dcl/lager.dcl @@ -41,7 +41,7 @@ lg_bereich : dialog { : edit_box { key = "gang"; label = "Gangbreite:"; edit_width = 10; } : edit_box { key = "tiefe"; label = "Regaltiefe:"; edit_width = 10; } : popup_list { key = "reihen"; label = "Reihen je Gang:"; width = 20; } - : edit_box { key = "schienen"; label = "Schienen je Gang:"; edit_width = 10; } + : edit_box { key = "schienen"; label = "Trolley-Schienen je Gang:"; edit_width = 10; } : edit_box { key = "richtung"; label = "Reihenrichtung (Grad):"; edit_width = 10; } } : boxed_column { @@ -114,7 +114,6 @@ lg_reihe : dialog { : edit_box { key = "laenge"; label = "Laenge (mm):"; edit_width = 10; } : edit_box { key = "tiefe"; label = "Regaltiefe (mm):"; edit_width = 10; } : edit_box { key = "ebenen"; label = "Haengeebenen (Schiene/Ware;...):"; edit_width = 24; } - : edit_box { key = "schienen"; label = "Schienen:"; edit_width = 10; } } ok_cancel; errtile; diff --git a/doc/plan/lager_rfq.md b/doc/plan/lager_rfq.md index 3a6d92b..749b250 100644 --- a/doc/plan/lager_rfq.md +++ b/doc/plan/lager_rfq.md @@ -26,32 +26,41 @@ Overlay-YAML `lib/lager_yaml_export.py` und `LAGER_HAND_YAML` sind entfernt). ## JSON-Schnittstelle (`format` = `ssg-lager`, `version` = 2) Einheiten mm, mm2, Grad; Koordinaten WCS, Nord = +Y. Werte stehen -selbstbeschreibend drin (`"belag_art": "spanplatte"`, keine Index-Codes). Fehlende -Werte sind `null`. Nicht-ASCII-Zeichen in Texten werden als `\uXXXX` geschrieben. +selbstbeschreibend drin (`"belag_art": "spanplatte"`, keine Index-Codes). +Nicht-ASCII-Zeichen in Texten werden als `\uXXXX` geschrieben. + +**Regel fuer fehlende Werte:** `null` heisst ausschliesslich "fehlt, muesste +eingegeben werden" (offener Punkt, z.B. `kennwerte.lichte_hoehe_mm` des obersten +Geschosses ohne Vorgabe). Was nicht zutrifft, wird WEGGELASSEN: Belag, +Gitterrost, Gitterkorb und `ohne_absturzsicherung_mm2` auf Hallenboden, +`gitterkorb` an Reihen ohne Korb, `bereich`/`bereich_handle`/`ausrichtung` an frei +gesetzten Reihen und Gaengen, `lichte_hoehe_vorgabe_mm` ohne Vorgabe. ``` { "format": "ssg-lager", "version": 2, "zeichnung", "erzeugt", "land", "einheiten": {"laenge": "mm", "flaeche": "mm2", "winkel": "grad"}, "koordinaten": "WCS, Nord = +Y", - "lager": { geschosse, bereiche, reihen, regallaenge_mm, regalgrundflaeche_mm2, - schienenlaenge_mm, haengeebenen[], gaenge{}, belagsflaeche_mm2, - gitterrostflaeche_mm2, gitterkorb{}, huelle{bbox, laenge_mm, breite_mm} }, + "lager": { geschosse, bereiche, grundriss_max{laenge_mm, breite_mm}, + summe_alle_geschosse{reihen, regallaenge_mm, regalgrundflaeche_mm2, + regalrohrlaenge_mm, haengeebenen[], gaenge{}, belagsflaeche_mm2, + gitterrostflaeche_mm2, gitterkorb{}, ohne_absturzsicherung_mm2} }, "geschosse": [ { nr, bezeichnung, id, handle, layer, hoehe_belag_mm, konstr_hoehe_mm, - lichte_hoehe_mm (Attribut), belag_art, personen, brandgefaehrdung, + lichte_hoehe_vorgabe_mm (nur wenn eingegeben), belag_art, personen, brandgefaehrdung, kontur{handle, z, punkte[[x,y]...], flaeche_mm2, umfang_mm, bbox}, kennwerte{...}, herkunft{: {formel, quelle}} } ], "bereiche": [ { nr, id, handle, layer, geschoss, gangbreite_mm, regaltiefe_mm, - reihen_je_gang, schienen_je_gang, quergang_abstand_mm, quergang_breite_mm, + reihen_je_gang, trolleyschienen_je_gang, quergang_abstand_mm, quergang_breite_mm, richtung_grad, haengeebenen[], belag, unter_reihe, gitterkorb_hoehe_mm, randgang_mm{n,o,s,w}, restbreite_mm, anzahl_reihen, anzahl_gaenge, kontur{} } ], "reihen": [ { id, handle, layer, geschoss, bereich, bereich_handle, quelle, laenge_mm, - tiefe_mm, schienen, haengeebenen[], start, ende, mitte, winkel_grad, - ecken[4], flaeche_mm2, unter_reihe, + tiefe_mm, haengeebenen[{schienenhoehe_mm, warenlaenge_mm, freiraum_unter_mm}], + start, ende, mitte, winkel_grad, ecken[4], flaeche_mm2, unter_reihe, gitterkorb{hoehe_mm, bodenflaeche_mm2, offen_laengs_mm, offen_stirn_mm, - seitenflaeche_mm2} | null } ], + seitenflaeche_mm2} (nur bei Gitterkorb) } ], "gaenge": [ { id, handle, layer, geschoss, bereich, bereich_handle, quelle, laenge_mm, - breite_mm, art, belag, start, ende, mitte, winkel_grad, ecken[4], flaeche_mm2 } ], + breite_mm, art, belag, start, ende, mitte, winkel_grad, ecken[4], flaeche_mm2, + ausrichtung ("laengs"/"quer" zur Reihenrichtung des Bereichs) } ], "warnungen": [ ... ] } ``` @@ -59,12 +68,25 @@ Werte sind `null`. Nicht-ASCII-Zeichen in Texten werden als `\uXXXX` geschrieben `geschosse` ist nach Belagshoehe sortiert (von unten nach oben). `start`/`ende`/ `mitte` sind 3D (Z der Einfuegung), `ecken` sind die vier Ecken des Grundrisses (2D), Kante 1-2 und 3-4 laengs, 2-3 und 4-1 an den Stirnseiten. -`kennwerte` je Geschoss: `lichte_hoehe_mm`, `buehne` (true/false), `bereiche`, -`reihen`, `regallaenge_mm`, `regalgrundflaeche_mm2`, `schienenlaenge_mm`, -`haengeebenen` (je Schienenhoehe/Warenlaenge: `reihen`, `regallaenge_mm`), -`gaenge` (je Art gang/quergang/randgang: `anzahl`, `laenge_mm`, `flaeche_mm2`), -`belagsflaeche_mm2`, `gitterrostflaeche_mm2`, `gitterkorb` (Summen). Formeln: -Abschnitt "Kennwerte <- Zeichnung". +`kennwerte` je Geschoss: `lichte_hoehe_mm` (wirksamer Wert: Vorgabe oder +berechnet), `buehne` (true/false), `huelle` (Grundriss dieses Geschosses), +`bereiche`, `reihen`, `regallaenge_mm`, `regalgrundflaeche_mm2`, +`regalrohrlaenge_mm`, `haengeebenen` (je Schienenhoehe/Warenlaenge: `reihen`, +`regallaenge_mm`), `gaenge` (je Art gang/quergang/randgang: `anzahl`, +`laenge_mm`, `flaeche_mm2`, `anzahl_quer`, `nach_breite[]`), +`belagsflaeche_mm2`, `gitterrostflaeche_mm2`, `gitterkorb` (Summen), +`ohne_absturzsicherung_mm2`. Formeln: Abschnitt "Kennwerte <- Zeichnung". +Alles unter `lager.summe_alle_geschosse` ist ueber ALLE Geschosse summiert. +Trolley-Schienen werden noch nicht berechnet (`trolleyschienen_je_gang` ist nur +die Eingabe am Bereich). + +`warnungen` enthaelt neben fehlenden Daten Plausibilitaetshinweise je Geschoss +(`lg-plausibilitaet`; Grenzwerte aus dem Regelprofil, `lg-plausibilitaet-grenzen`): +Buehne ohne Konstruktionshoehe, Reihen ohne Absturzsicherung auf einer Buehne, +lichte Hoehe unter `lichte_hoehe.verkehrsweg_min`, Gaenge schmaler als +`gang.breite_nebengang_min`, `art` gang quer zur Reihenrichtung, Gang direkt +neben einem Randgang, kein Freiraum unter der Ware, oberste Schiene nicht unter +der lichten Hoehe. Sie aendern keine Werte. Erzeugt von `LAGER_EXPORT` (Menue Lager -> Export Lager-JSON), Beispiel: `tests/output/lager_tests_lager.json` nach `TEST_LAGER`. @@ -78,8 +100,8 @@ Werte selbstbeschreibend (keine Index-Codes). Verknuepfungen als XDATA | Block | Geometrie | Attribute | XDATA | |---|---|---|---| | `LG_GESCHOSS` | Kopfsymbol unten links an der Belagskontur | `NR`, `BEZEICHNUNG`, `HOEHE_BELAG_mm`, `KONSTR_HOEHE_mm`, `LICHTE_HOEHE_mm` (leer = berechnet), `BELAG_ART` (`spanplatte`/`gitterrost`/`hallenboden`), `PERSONEN`, `BRANDGEFAEHRDUNG` | `kontur` -> Polylinie; Kontur: `besitzer`, `rolle` | -| `LG_BEREICH` | Symbol mit Pfeil in Reihenrichtung | `NR`, `GANGBREITE_mm`, `REGALTIEFE_mm`, `REIHEN_JE_GANG` (1/2), `SCHIENEN_JE_GANG`, `QUERGANG_ABSTAND_mm` (0 = keine), `QUERGANG_BREITE_mm`, `RICHTUNG`, `HAENGEEBENEN`, `BELAG`, `RANDGANG_N_mm`/`_O_`/`_S_`/`_W_` (0 = keiner), `UNTER_REIHE` (`gitterrost`/`gitterkorb`/`keine`, Absturzsicherung unter den Reihen, nur auf Buehnen), `GITTERKORB_HOEHE_mm`, `RESTBREITE_mm` (Ergebnis) | `kontur` -> Polylinie | -| `LG_REIHE__` | Rechteck L x T um die Schienenlinie, Einfuegepunkt = Reihenanfang | `LAENGE`, `TIEFE_mm`, `HAENGEEBENEN`, `SCHIENEN`, `BEREICH`, `QUELLE` (`auto`/`auto_geaendert`/`manuell`) | `bereich` -> LG_BEREICH (nur Auto-Fuellung) | +| `LG_BEREICH` | Symbol mit Pfeil in Reihenrichtung | `NR`, `GANGBREITE_mm`, `REGALTIEFE_mm`, `REIHEN_JE_GANG` (1/2), `SCHIENEN_JE_GANG` (Trolley-Schienen, noch nicht ausgewertet), `QUERGANG_ABSTAND_mm` (0 = keine), `QUERGANG_BREITE_mm`, `RICHTUNG`, `HAENGEEBENEN`, `BELAG`, `RANDGANG_N_mm`/`_O_`/`_S_`/`_W_` (0 = keiner), `UNTER_REIHE` (`gitterrost`/`gitterkorb`/`keine`, Absturzsicherung unter den Reihen, nur auf Buehnen), `GITTERKORB_HOEHE_mm`, `RESTBREITE_mm` (Ergebnis) | `kontur` -> Polylinie | +| `LG_REIHE__` | Rechteck L x T um die Schienenlinie, Einfuegepunkt = Reihenanfang | `LAENGE`, `TIEFE_mm`, `HAENGEEBENEN` (je Ebene ein Regalrohr), `BEREICH`, `QUELLE` (`auto`/`auto_geaendert`/`manuell`) | `bereich` -> LG_BEREICH (nur Auto-Fuellung) | | `LG_GANG___` | Rechteck L x B um die Gangachse + Schraffur je Belag (`lager.json belag_schraffur`, Layer 0/VONBLOCK; `hallenboden` ohne) | `LAENGE`, `BREITE_mm`, `ART` (`gang`/`quergang`/`randgang`), `BELAG`, `BEREICH`, `QUELLE` (`auto`/`auto_geaendert`/`manuell`) | `bereich` (Auto-Fuellung und manuelle Gaenge im Bereich) | `HAENGEEBENEN` = `Schienenhoehe/Warenlaenge;...` ueber Belag, oberste zuerst, @@ -208,14 +230,18 @@ Geschoss-Kennwert steht mit Formel und Quelle unter `herkunft`. |---|---| | `lichte_hoehe_mm` | `LICHTE_HOEHE_mm`, sonst Belag darueber - Konstruktionshoehe darueber - eigener Belag; oberstes Geschoss nur mit Vorgabe (sonst `null` + Warnung) | | `buehne` | `BELAG_ART` gesetzt und nicht `hallenboden`. Ohne Buehne: kein Belag, kein Gitterrost, kein Gitterkorb | -| `regallaenge_mm`, `regalgrundflaeche_mm2`, `schienenlaenge_mm` | Summe `LAENGE`, `LAENGE x TIEFE_mm`, `LAENGE x SCHIENEN` der Reihen des Geschosses | +| `regallaenge_mm`, `regalgrundflaeche_mm2`, `regalrohrlaenge_mm` | Summe `LAENGE`, `LAENGE x TIEFE_mm`, `LAENGE x Anzahl Haengeebenen` der Reihen des Geschosses | +| `ohne_absturzsicherung_mm2` | Buehne: Summe `LAENGE x TIEFE_mm` der Reihen mit `UNTER_REIHE = keine` | +| `haengeebenen[].freiraum_unter_mm` (Reihe/Bereich) | Schienenhoehe - Warenlaenge - naechsttiefere Schienenhoehe (unterste: Belag); <= 0 = Ware stoesst an (`lg-ebenen-freiraum`) | +| `gaenge[].ausrichtung` | Gangwinkel gegen `RICHTUNG` des Bereichs, Abweichung < 45 Grad = laengs (`lg-ausrichtung`) | | `haengeebenen[]` | je (Schienenhoehe, Warenlaenge): Anzahl Reihen und Summe `LAENGE`, nach Schienenhoehe absteigend (`lg-haengeebenen-summen`) | | `gaenge` | je `ART` (gang/quergang/randgang, auch manuelle): Anzahl, Summe `LAENGE`, Summe `LAENGE x BREITE_mm` (`lg-gaenge-je-art`) | | `belagsflaeche_mm2` | Summe `LAENGE x BREITE_mm` der Gaenge mit Belag != gitterrost; ohne Gangflaechen: Konturflaeche - Reihengrundflaeche | | `gitterrostflaeche_mm2` | Gaenge mit Belag gitterrost + Grundflaeche der Reihen mit `UNTER_REIHE = gitterrost` | | `gitterkorb` (je Reihe und Summe) | Reihen mit `UNTER_REIHE = gitterkorb`: Boden = `LAENGE x TIEFE_mm`; Seiten = offene Kantenlaenge x `GITTERKORB_HOEHE_mm`, getrennt nach Laengs- und Stirnseiten. Offen ist eine Kante, soweit keine Kante einer ANDEREN Reihe desselben Geschosses kollinear darauf liegt (Abstand < 1 mm, z.B. Ruecken an Ruecken; `lg-reihen-offene-kanten`) | -| `lager.huelle` | achsparallele Huelle aller Geschosskonturen, `laenge_mm` = laengere Seite | -| `lager.*` sonst | Summen der Geschoss-Kennwerte; `haengeebenen`/`gaenge` ueber alle zugeordneten Reihen/Gaenge | +| `kennwerte.huelle` | achsparallele Huelle der Geschosskontur, `laenge_mm` = laengere Seite | +| `lager.grundriss_max` | groesste Laenge/Breite der Geschoss-Huellen (die Geschosse koennen im Plan nebeneinander liegen - eine gemeinsame Huelle waere kein Gebaeudemass) | +| `lager.summe_alle_geschosse` | Summen der Geschoss-Kennwerte; `haengeebenen`/`gaenge` ueber alle zugeordneten Reihen/Gaenge | `UNTER_REIHE` kommt aus dem verknuepften Bereich; Reihen ohne Bereich (und Bereiche ohne Attribut, Altbestand) nehmen die Vorgabe `lager.json diff --git a/lang/de_DE.json b/lang/de_DE.json index d73de5d..9b96752 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -1203,7 +1203,6 @@ "lg-feld-gang": "\nGangbreite (mm)", "lg-feld-tiefe": "\nRegaltiefe (mm)", "lg-feld-reihen": "\nReihen je Gang", - "lg-feld-schienen": "\nSchienen je Gang", "lg-feld-q_abstand": "\nQuergang-Abstand (mm, 0 = keine)", "lg-feld-q_breite": "\nQuergang-Breite (mm)", "lg-feld-richtung": "\nReihenrichtung (Grad)", @@ -1275,6 +1274,15 @@ "lg-exp-lichte-hoehe-oben": "Geschoss %1 (oberstes): lichte Hoehe nicht berechenbar - LICHTE_HOEHE_mm setzen.", "lg-exp-korb-hallenboden": "Bereich %1 hat Gitterkorb unter den Reihen, Geschoss %2 ist aber Hallenboden - nicht gezaehlt.", "lg-exp-reihen-ohne-geschoss": "%1 Regalreihe(n) ohne bekanntes Geschoss - nicht in den Kennwerten enthalten.", + "lg-feld-schienen": "\nTrolley-Schienen je Gang", + "lg-pl-konstr-null": "Geschoss %1 ist eine Buehne, hat aber keine Konstruktionshoehe (KONSTR_HOEHE_mm = 0).", + "lg-pl-unter-keine": "Geschoss %1: %2 m2 Regalgrundflaeche ohne Absturzsicherung (UNTER_REIHE keine) - offene Flaeche zum Geschoss darunter.", + "lg-pl-lichte-klein": "Geschoss %1: lichte Hoehe %2 mm unter dem Mindestmass %3 mm (%4).", + "lg-pl-gang-schmal": "Geschoss %1: %2 Gang/Gaenge schmaler als %4 mm (Breiten %3 mm; %5).", + "lg-pl-gang-quer": "Geschoss %1: %2 Gang/Gaenge mit ART gang liegen quer zur Reihenrichtung (ID %3) - Quergang?", + "lg-pl-gang-neben-randgang": "Geschoss %1: %2 Gang/Gaenge liegen direkt neben einem Randgang (ID %3) - doppelte Randzone?", + "lg-pl-freiraum": "Geschoss %1: kein Freiraum unter der Ware bei Haengeebene(n) Schiene/Ware (Freiraum) %2 mm.", + "lg-pl-schiene-ueber-lichte": "Geschoss %1: oberste Schiene %2 mm liegt nicht unter der lichten Hoehe %3 mm.", "lg-regel-profil-fehlt": "\n[Lager] Regelprofil %1 nicht gefunden (%2).", "lg-regel-profil-ungepflegt": "\n[Lager] WARNUNG: Regelprofil %1 ist nicht gepflegt - es gelten die geerbten Werte.", "lg-regel-unbekannt": "\n[Lager] Regel %1 nicht im Profil.", diff --git a/lang/en_GB.json b/lang/en_GB.json index 06c1968..4857b10 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -1203,7 +1203,6 @@ "lg-feld-gang": "\nAisle width (mm)", "lg-feld-tiefe": "\nRack depth (mm)", "lg-feld-reihen": "\nRows per aisle", - "lg-feld-schienen": "\nRails per aisle", "lg-feld-q_abstand": "\nCross aisle spacing (mm, 0 = none)", "lg-feld-q_breite": "\nCross aisle width (mm)", "lg-feld-richtung": "\nRow direction (degrees)", @@ -1275,6 +1274,15 @@ "lg-exp-lichte-hoehe-oben": "Level %1 (top): clear height cannot be calculated - set LICHTE_HOEHE_mm.", "lg-exp-korb-hallenboden": "Area %1 has a mesh basket below the rows, but level %2 is a hall floor - not counted.", "lg-exp-reihen-ohne-geschoss": "%1 rack row(s) without a known level - not included in the key figures.", + "lg-feld-schienen": "\nTrolley rails per aisle", + "lg-pl-konstr-null": "Level %1 is a platform but has no construction depth (KONSTR_HOEHE_mm = 0).", + "lg-pl-unter-keine": "Level %1: %2 m2 of rack footprint without fall protection (UNTER_REIHE keine) - open area to the level below.", + "lg-pl-lichte-klein": "Level %1: clear height %2 mm below the minimum of %3 mm (%4).", + "lg-pl-gang-schmal": "Level %1: %2 aisle(s) narrower than %4 mm (widths %3 mm; %5).", + "lg-pl-gang-quer": "Level %1: %2 aisle(s) of type gang run across the row direction (ID %3) - cross aisle?", + "lg-pl-gang-neben-randgang": "Level %1: %2 aisle(s) lie directly next to a perimeter aisle (ID %3) - double edge zone?", + "lg-pl-freiraum": "Level %1: no clearance below the goods at hanging level(s) rail/goods (clearance) %2 mm.", + "lg-pl-schiene-ueber-lichte": "Level %1: top rail %2 mm is not below the clear height %3 mm.", "lg-regel-profil-fehlt": "\n[Storage] Rule profile %1 not found (%2).", "lg-regel-profil-ungepflegt": "\n[Storage] WARNING: rule profile %1 is not maintained - inherited values apply.", "lg-regel-unbekannt": "\n[Storage] Rule %1 not in profile.", diff --git a/tests/test_lager.lsp b/tests/test_lager.lsp index b849d5a..a5b64c9 100644 --- a/tests/test_lager.lsp +++ b/tests/test_lager.lsp @@ -154,7 +154,7 @@ ;; --- Einzelne Reihe aendern (Neuaufbau, Kennzeichnung) --- (setq r0 (car (lg-alle-bloecke "LG_REIHE_*"))) (setq neu (lg-linie-neu-aufbauen r0 (list (cons "LAENGE" "2000") (cons "TIEFE_mm" "700") - (cons "HAENGEEBENEN" "2300/1200") (cons "SCHIENEN" "1") + (cons "HAENGEEBENEN" "2300/1200") (cons "GESCHOSS" "1") (cons "BEREICH" "1") (cons "QUELLE" "auto_geaendert")))) (tlg-eq "reihe neu aufgebaut" "LG_REIHE_2000_700" (if neu (cdr (assoc 2 (entget neu))))) @@ -174,8 +174,8 @@ (tlg-eq "export konturflaeche" 6.0e7 (ssg-json-get (ssg-json-get eg1 "kontur") "flaeche_mm2")) (tlg-eq "export konturpunkte" 4 (length (ssg-json-get (ssg-json-get eg1 "kontur") "punkte"))) (tlg-eq "export haengeebenen" - '((("schienenhoehe_mm" . 2300) ("warenlaenge_mm" . 1200)) - (("schienenhoehe_mm" . 1100) ("warenlaenge_mm" . 1100))) + '((("schienenhoehe_mm" . 2300) ("warenlaenge_mm" . 1200) ("freiraum_unter_mm" . 0)) + (("schienenhoehe_mm" . 1100) ("warenlaenge_mm" . 1100) ("freiraum_unter_mm" . 0))) (ssg-json-get (vl-some '(lambda (r) (if (= (ssg-json-get r "laenge_mm") 4000) r)) (ssg-json-get daten "reihen")) "haengeebenen")) @@ -191,7 +191,7 @@ (tlg-eq "export G1 unter gitterrost" T (vl-every '(lambda (r) (= (ssg-json-get r "unter_reihe") "gitterrost")) (ssg-json-get daten "reihen"))) (tlg-eq "export lager regallaenge" (ssg-json-get (ssg-json-get eg1 "kennwerte") "regallaenge_mm") - (ssg-json-get (ssg-json-get daten "lager") "regallaenge_mm")) + (ssg-json-get (ssg-json-get (ssg-json-get daten "lager") "summe_alle_geschosse") "regallaenge_mm")) ;; --- Randgaenge Nord + Sued, Schraffur je Belag --- (setq kb2 (tlg-rechteck 20000.0 0.0 30000.0 6000.0)) diff --git a/tests/test_unit.lsp b/tests/test_unit.lsp index c2becc6..27a43c0 100644 --- a/tests/test_unit.lsp +++ b/tests/test_unit.lsp @@ -3415,8 +3415,26 @@ (tu-eq "lg-json-wert/obj-arr" "{\"p\": [1, 2.5], \"o\": {\"x\": null}}" (lg-json-wert (list 'OBJ (cons "p" (list 'ARR 1 2.5)) (cons "o" (list 'OBJ (cons "x" nil)))))) (tu-eq "lg-json-wert/leer" "[]" (lg-json-wert (list 'ARR))) - (tu-eq "lg-j-ebenen" "[{\"schienenhoehe_mm\": 2300, \"warenlaenge_mm\": 1200}]" + (tu-eq "lg-j-ebenen" "[{\"schienenhoehe_mm\": 2300, \"warenlaenge_mm\": 1200, \"freiraum_unter_mm\": 1100}]" (lg-json-wert (lg-j-ebenen "2300/1200"))) + ;; nicht zutreffende Felder werden weggelassen, null bleibt null + (tu-eq "lg-json-obj/entfaellt" "{\"a\": 1, \"c\": null}" + (lg-json-obj (list (cons "a" 1) (cons "b" 'ENTFAELLT) (cons "c" nil)))) + (tu-eq "lg-json-text/entfaellt" T + (not (vl-string-search "\"b\"" + (lg-json-text (cons 'OBJ (cons (cons "b" 'ENTFAELLT) + (mapcar '(lambda (i) (cons (itoa i) i)) '(1 2 3 4 5 6 7 8 9 10 11 12 13)))) + "")))) + (tu-nil "lg-j/entfaellt" (lg-j (list 'OBJ (cons "b" 'ENTFAELLT)) "b")) + (tu-nil "lg-j/kein-obj" (lg-j 'ENTFAELLT "b")) + ;; Freiraum unter der Ware: 2300-1200-1100 = 0, 1100-1100-0 = 0 + (tu-eqf "lg-ebenen-freiraum" '((2300.0 1200.0 0.0) (1100.0 1100.0 0.0)) + (lg-ebenen-freiraum '((1100.0 1100.0) (2300.0 1200.0)))) + (tu-eqf "lg-ebenen-freiraum/luft" '((2400.0 1000.0 300.0) (1100.0 1000.0 100.0)) + (lg-ebenen-freiraum '((2400.0 1000.0) (1100.0 1000.0)))) + (tu-eq "lg-ausrichtung" '("laengs" "laengs" "quer" "quer" nil) + (list (lg-ausrichtung 90.0 90.0) (lg-ausrichtung 270.0 90.0) (lg-ausrichtung 180.0 90.0) + (lg-ausrichtung 0.0 270.0) (lg-ausrichtung 0.0 nil))) ;; kleine Container einzeilig, grosse je Eintrag eine Zeile (tu-eq "lg-json-text/klein" "{\"a\": 1}" (lg-json-text (list 'OBJ (cons "a" 1)) "")) (setq _gross (cons 'OBJ (mapcar '(lambda (i) (cons (itoa i) i)) '(1 2 3 4 5 6 7 8 9 10 11 12 13)))) @@ -3451,10 +3469,19 @@ (list 'OBJ (cons "art" "randgang") (cons "belag" "gitterrost") (cons "laenge_mm" 5000.0) (cons "breite_mm" 800.0)) (list 'OBJ (cons "art" "gang") (cons "belag" "spanplatte") (cons "laenge_mm" 2000.0) (cons "breite_mm" 1000.0)))) (tu-eqf "lg-gaenge-je-art" - '(OBJ ("gang" OBJ ("anzahl" . 2) ("laenge_mm" . 12000.0) ("flaeche_mm2" . 1.2e7)) - ("quergang" OBJ ("anzahl" . 0) ("laenge_mm" . 0.0) ("flaeche_mm2" . 0.0)) - ("randgang" OBJ ("anzahl" . 1) ("laenge_mm" . 5000.0) ("flaeche_mm2" . 4.0e6))) + '(OBJ ("gang" OBJ ("anzahl" . 2) ("laenge_mm" . 12000.0) ("flaeche_mm2" . 1.2e7) ("anzahl_quer" . 0) + ("nach_breite" ARR (OBJ ("breite_mm" . 1000.0) ("anzahl" . 2) ("laenge_mm" . 12000.0) ("flaeche_mm2" . 1.2e7)))) + ("quergang" OBJ ("anzahl" . 0) ("laenge_mm" . 0.0) ("flaeche_mm2" . 0.0) ("anzahl_quer" . 0) + ("nach_breite" ARR)) + ("randgang" OBJ ("anzahl" . 1) ("laenge_mm" . 5000.0) ("flaeche_mm2" . 4.0e6) ("anzahl_quer" . 0) + ("nach_breite" ARR (OBJ ("breite_mm" . 800.0) ("anzahl" . 1) ("laenge_mm" . 5000.0) ("flaeche_mm2" . 4.0e6))))) (lg-gaenge-je-art _ga)) + ;; Breiten getrennt, quer liegende gezaehlt + (setq _gq (lg-gaenge-je-art + (list (list 'OBJ (cons "art" "gang") (cons "laenge_mm" 10000.0) (cons "breite_mm" 1000.0) (cons "ausrichtung" "laengs")) + (list 'OBJ (cons "art" "gang") (cons "laenge_mm" 25200.0) (cons "breite_mm" 3600.0) (cons "ausrichtung" "quer"))))) + (tu-eq "lg-gaenge-je-art/quer" 1 (lg-j (lg-j _gq "gang") "anzahl_quer")) + (tu-eq "lg-gaenge-je-art/breiten" 2 (length (cdr (lg-j (lg-j _gq "gang") "nach_breite")))) ;; Geschoss 1 (Spanplatte, 3100) unter Geschoss 2 (6100, Konstr. 250) (setq _g1 (list 'OBJ (cons "nr" 1) (cons "hoehe_belag_mm" 3100.0) (cons "konstr_hoehe_mm" 250.0) (cons "lichte_hoehe_mm" nil) (cons "belag_art" "spanplatte") @@ -3465,7 +3492,9 @@ (tu-eqf "lg-kennwerte/lichte-berechnet" 2750.0 (lg-j _kw "lichte_hoehe_mm")) (tu-eqf "lg-kennwerte/regallaenge" 6000.0 (lg-j _kw "regallaenge_mm")) (tu-eqf "lg-kennwerte/grundflaeche" 4.2e6 (lg-j _kw "regalgrundflaeche_mm2")) - (tu-eqf "lg-kennwerte/schienen" 8000.0 (lg-j _kw "schienenlaenge_mm")) + ;; Regalrohr = Laenge x Haengeebenen: 4000 x 2 + 2000 x 1 + (tu-eqf "lg-kennwerte/regalrohr" 10000.0 (lg-j _kw "regalrohrlaenge_mm")) + (tu-eqf "lg-kennwerte/ohne-absturz" 0.0 (lg-j _kw "ohne_absturzsicherung_mm2")) (tu-eqf "lg-kennwerte/belag-gaenge" 1.2e7 (lg-j _kw "belagsflaeche_mm2")) ;; Gitterrost = Randgang gitterrost 4e6 + Reihen 4.2e6 (tu-eqf "lg-kennwerte/gitterrost" 8.2e6 (lg-j _kw "gitterrostflaeche_mm2")) @@ -3477,13 +3506,20 @@ (tu-eqf "lg-kennwerte/belag-kontur" (- 6.0e7 4.2e6) (lg-j _kw "belagsflaeche_mm2")) (tu-nil "lg-kennwerte/lichte-oben" (lg-j _kw "lichte_hoehe_mm")) (tu-eqf "lg-kennwerte/lichte-vorgabe" 2800.0 - (lg-j (car (lg-kennwerte-geschoss (lg-j-setzen _g1 "lichte_hoehe_mm" 2800.0) _g2 nil nil 0)) + (lg-j (car (lg-kennwerte-geschoss (lg-j-setzen _g1 "lichte_hoehe_vorgabe_mm" 2800.0) _g2 nil nil 0)) "lichte_hoehe_mm")) - ;; Hallenboden: keine Buehne, keine Flaechen + ;; Reihe ohne Absturzsicherung auf der Buehne + (tu-eqf "lg-kennwerte/ohne-absturz-keine" 2.8e6 + (lg-j (car (lg-kennwerte-geschoss _g1 _g2 (list (lg-j-setzen _r1 "unter_reihe" "keine")) nil 1)) + "ohne_absturzsicherung_mm2")) + ;; Hallenboden: keine Buehne, Flaechen entfallen (werden nicht geschrieben) (setq _kw (car (lg-kennwerte-geschoss (lg-j-setzen _g1 "belag_art" "hallenboden") _g2 (list _r1) _ga 1))) (tu-eq "lg-kennwerte/hallenboden" 'FALSE (lg-j _kw "buehne")) (tu-nil "lg-kennwerte/hallenboden-belag" (lg-j _kw "belagsflaeche_mm2")) (tu-nil "lg-kennwerte/hallenboden-gitter" (lg-j _kw "gitterrostflaeche_mm2")) + (tu-nil "lg-kennwerte/hallenboden-korb" (lg-j _kw "gitterkorb")) + (tu-eq "lg-kennwerte/hallenboden-entfaellt" T + (not (vl-string-search "belagsflaeche" (lg-json-wert _kw)))) ;; --- Gitterkorb: offene Kanten --- ;; Einzelreihe 4000 x 700: alles offen @@ -3520,16 +3556,48 @@ (tu-eqf "lg-kennwerte/korb-seite" (* 500.0 5400.0) (lg-j (lg-j _kw "gitterkorb") "seitenflaeche_mm2")) (tu-eq "lg-kennwerte/korb-reihen" 1 (lg-j (lg-j _kw "gitterkorb") "reihen")) (tu-eqf "lg-kennwerte/korb-kein-gitterrost" 0.0 (lg-j _kw "gitterrostflaeche_mm2")) - ;; Lager-Summen ueber zwei Geschosse + ;; Lager-Summen ueber zwei Geschosse; die Grundrisse liegen im Plan + ;; nebeneinander - grundriss_max ist der groesste, keine gemeinsame Huelle + (setq _g1b (lg-j-setzen _g1 "kontur" (list 'OBJ (cons "bbox" (list 'ARR 0.0 0.0 10000.0 6000.0)))) + _g2b (lg-j-setzen _g2 "kontur" (list 'OBJ (cons "bbox" (list 'ARR 0.0 50000.0 12000.0 55000.0))))) + (tu-eqf "lg-kennwerte/huelle-geschoss" '(10000.0 6000.0) + (list (lg-j (lg-j (car (lg-kennwerte-geschoss _g1b _g2b nil nil 1)) "huelle") "laenge_mm") + (lg-j (lg-j (car (lg-kennwerte-geschoss _g1b _g2b nil nil 1)) "huelle") "breite_mm"))) (setq _kl (lg-kennwerte-lager - (list (lg-j-setzen (lg-j-setzen _g1 "kennwerte" (car (lg-kennwerte-geschoss _g1 _g2 (list _r1) nil 1))) - "kontur" (list 'OBJ (cons "bbox" (list 'ARR 0.0 0.0 10000.0 6000.0)))) - (lg-j-setzen (lg-j-setzen _g2 "kennwerte" (car (lg-kennwerte-geschoss _g2 nil (list _r2) nil 1))) - "kontur" (list 'OBJ (cons "bbox" (list 'ARR 0.0 0.0 12000.0 5000.0))))) + (list (lg-j-setzen _g1b "kennwerte" (car (lg-kennwerte-geschoss _g1b _g2b (list _r1) nil 1))) + (lg-j-setzen _g2b "kennwerte" (car (lg-kennwerte-geschoss _g2b nil (list _r2) nil 1)))) (list _r1 _r2) nil 2)) - (tu-eqf "lg-kennwerte-lager/regal" 6000.0 (lg-j _kl "regallaenge_mm")) - (tu-eqf "lg-kennwerte-lager/huelle" '(12000.0 6000.0) - (list (lg-j (lg-j _kl "huelle") "laenge_mm") (lg-j (lg-j _kl "huelle") "breite_mm"))) + (tu-eqf "lg-kennwerte-lager/regal" 6000.0 (lg-j (lg-j _kl "summe_alle_geschosse") "regallaenge_mm")) + (tu-eqf "lg-kennwerte-lager/grundriss-max" '(12000.0 6000.0) + (list (lg-j (lg-j _kl "grundriss_max") "laenge_mm") (lg-j (lg-j _kl "grundriss_max") "breite_mm"))) + + ;; --- Plausibilitaet --- + (setq _grenzen '(("gang_min" 750.0 "Q1") ("lichte_min" 2000.0 "Q2"))) + ;; alles daneben: 8 Warnungen + (setq _pw (lg-plausibilitaet + (list 'OBJ (cons "nr" 2) (cons "belag_art" "spanplatte") (cons "konstr_hoehe_mm" 0.0)) + (list 'OBJ (cons "lichte_hoehe_mm" 1800.0) (cons "ohne_absturzsicherung_mm2" 1.0e6)) + (list (list 'OBJ (cons "haengeebenen" (lg-j-ebenen "2300/1200;1100/1100")))) + (list (list 'OBJ (cons "id" "GQ") (cons "art" "gang") (cons "ausrichtung" "quer") (cons "breite_mm" 500.0) + (cons "ecken" (lg-j-pkte '((0.0 0.0) (10000.0 0.0) (10000.0 500.0) (0.0 500.0))))) + (list 'OBJ (cons "id" "RG") (cons "art" "randgang") (cons "breite_mm" 1600.0) + (cons "ecken" (lg-j-pkte '((0.0 500.0) (10000.0 500.0) (10000.0 2100.0) (0.0 2100.0)))))) + _grenzen)) + (tu-eq "lg-plausibilitaet/alle" 8 (length _pw)) + ;; sauber: keine Warnung + (tu-nil "lg-plausibilitaet/sauber" + (lg-plausibilitaet + (list 'OBJ (cons "nr" 2) (cons "belag_art" "spanplatte") (cons "konstr_hoehe_mm" 250.0)) + (list 'OBJ (cons "lichte_hoehe_mm" 3000.0) (cons "ohne_absturzsicherung_mm2" 0.0)) + (list (list 'OBJ (cons "haengeebenen" (lg-j-ebenen "2400/1000;1100/1000")))) + (list (list 'OBJ (cons "id" "G") (cons "art" "gang") (cons "ausrichtung" "laengs") (cons "breite_mm" 1000.0) + (cons "ecken" (lg-j-pkte '((0.0 0.0) (10000.0 0.0) (10000.0 1000.0) (0.0 1000.0)))))) + _grenzen)) + ;; Hallenboden: Konstruktionshoehe 0 ist dort kein Fehler + (tu-nil "lg-plausibilitaet/hallenboden" + (lg-plausibilitaet (list 'OBJ (cons "nr" 1) (cons "belag_art" "hallenboden") (cons "konstr_hoehe_mm" 0.0)) + (list 'OBJ (cons "lichte_hoehe_mm" 3000.0)) nil nil _grenzen)) + (tu-eq "lg-unikat" '("a" "b") (lg-unikat '("a" "b" "a"))) ;; --- Regelprofil-Aufloesung --- (tu-eq "lg-bedingung/leer" 'ja (lg-bedingung-pruefen nil nil))