17 KiB
Lagerplanung in BricsCAD -> Lager-JSON (GOH-Buehnenlager)
Schema und Schnittstelle der Lagerplanung. Code: Lisp/LagerInsert.lsp,
Lisp/LagerPruefung.lsp. Daten: data/json/lager.json,
cfg/stahlbau/regelwerk/*.json, cfg/layer.cfg Abschnitt [lager], Dialoge dcl/lager.dcl.
Ziel und Datenfluss
Das RFQ-Programm (eigenes Repo) erzeugt das Ausschreibungsdokument. Die Makros liefern ihm die technischen Daten des Lagers aus der Zeichnung, als EINE JSON-Datei. Mapping auf das RFQ-Schema, Abgleich mit Handwerten und Darstellung sind Sache des RFQ-Projekts.
BricsCAD (LISP) RFQ-Repo
LG_GESCHOSS / LG_BEREICH / LG_REIHE / LG_GANG
--LAGER_EXPORT--> DXFM_RESULTS/<dwg>_lager.json --> Dokument
^ Regelprofil cfg/stahlbau/regelwerk/<Land>.json (LagerPruefung.lsp, noch nicht im Export)
Grundsatz: jede fachliche Regel und jeder Kennwert wird genau einmal
implementiert, in LISP (LagerInsert.lsp Abschnitt EXPORT, Regeln in
LagerPruefung.lsp). Es gibt keinen Python-Schritt mehr (die fruehere
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.
{
"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} },
"geschosse": [ { nr, bezeichnung, id, handle, layer, hoehe_belag_mm, konstr_hoehe_mm,
lichte_hoehe_mm (Attribut), belag_art, personen, brandgefaehrdung,
kontur{handle, z, punkte[[x,y]...], flaeche_mm2, umfang_mm, bbox},
kennwerte{...}, herkunft{<kennwert>: {formel, quelle}} } ],
"bereiche": [ { nr, id, handle, layer, geschoss, gangbreite_mm, regaltiefe_mm,
reihen_je_gang, schienen_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,
gitterkorb{hoehe_mm, bodenflaeche_mm2, offen_laengs_mm, offen_stirn_mm,
seitenflaeche_mm2} | null } ],
"gaenge": [ { id, handle, layer, geschoss, bereich, bereich_handle, quelle, laenge_mm,
breite_mm, art, belag, start, ende, mitte, winkel_grad, ecken[4], flaeche_mm2 } ],
"warnungen": [ ... ]
}
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".
Erzeugt von LAGER_EXPORT (Menue Lager -> Export Lager-JSON), Beispiel:
tests/output/lager_tests_lager.json nach TEST_LAGER.
Bloecke und Attribute
Alle Bloecke tragen ID, GESCHOSS, LAYER. Masse in mm, Winkel in Grad,
Werte selbstbeschreibend (keine Index-Codes). Verknuepfungen als XDATA
(App SSG_LG, Paare 1000 schluessel + 1005 handle/1000 text).
| 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_<L>_<T> |
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_GANG_<L>_<B>_<BELAG> |
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,
z.B. 2300/1200;1100/1100. Die Definitionen LG_REIHE_*/LG_GANG_* werden je
Geometrie wiederverwendet; die Werte stehen in den Attributen der Referenz.
Geschosse und Layer
Layer je Geschoss: Basis aus cfg/layer.cfg [lager] + _G<nr>
(LG_Reihe_G2). LG_GESCHOSS_AKTIV friert die Layer der uebrigen Geschosse,
weil die 2D-Grundrisse uebereinander liegen. Neue Objekte bekommen das aktive
Geschoss; ohne aktives Geschoss entscheidet die Kontur, in der sie liegen. In
2D (alle Konturen auf Z = 0) ist eine Lage in mehreren Konturen nicht
eindeutig -> Rueckfrage bzw. Export-Warnung; in 3D entscheidet Z.
Jede Kontur gehoert genau einem Block. Wird eine schon vergebene Kontur gewaehlt (z.B. dieselbe Halle fuer mehrere Geschosse), wird sie kopiert.
Der parametrische BricsCAD-Block goh_rack (frueher als Bestand mitgezaehlt)
wird nicht mehr unterstuetzt: Regale gibt es nur noch als LG_REIHE_*.
Geschoss kopieren (LG_GESCHOSS_KOPIEREN)
Obergeschosse gleichen meist dem Geschoss darunter. Dialog lg_geschoss_kopie:
- Quelle: Vorgabe ist das oberste Geschoss. Damit wird ein weiteres Geschoss nachtraeglich angehaengt, z.B. G3 -> G4.
- Anzahl.
- Geschosshoehe je Kopie: Vorgabe ist der Abstand zum Geschoss darunter, sonst lichte Hoehe + Konstruktion.
- Belag.
- Versatz X/Y je Kopie: 0 = deckungsgleich. In einer 3D-Zeichnung (Konturen auf Belagshoehe) wandert die Kopie zusaetzlich in Z.
Ein BricsCAD-KOPIEREN taugt nicht. Die XDATA-Verweise kontur/besitzer/bereich
zeigten dann weiter auf die Originale, und GESCHOSS, Layer und IDs blieben die alten.
Stattdessen entsteht jedes Objekt ueber die normalen Einfuegefunktionen neu:
- Geschoss und Bereiche mit kopierter Kontur; die Bereiche ohne Fuellung
(
lg-bereich-block-anlegen). - Reihen und Gaenge 1:1 aus der Quelle (
lg-linie-einfuegen). Es wird nicht neu gefuellt, damit Handaenderungen (auto_geaendert, manuelle Reihen/Gaenge) erhalten bleiben. - Belaege, die dem Geschossbelag der Quelle entsprachen, folgen dem neuen Belag, inklusive Schraffur. Bewusst abweichende bleiben.
Auto-Fuellung (lg-fuellung-berechnen)
Die Kontur wird in ein lokales System gedreht (Reihen entlang +X, RICHTUNG;
Vorgabe = Richtung der laengsten Konturkante). Quer dazu wird ab Unterkante ein
Modul nach dem anderen gelegt, nur volle Module:
- 2 Reihen je Gang:
Reihe | Gang | Reihe, benachbarte Module Ruecken an Ruecken - 1 Reihe je Gang:
Reihe | Gang
Ein Streifen ist dort belegbar, wo Unter-, Mittel- und Oberkante in der Kontur
liegen (konkave Konturen werden korrekt beschnitten). Quergaenge: Luecken der
Breite QUERGANG_BREITE_mm nach je QUERGANG_ABSTAND_mm, ueber alle Reihen
ausgerichtet; keine Luecke am Reihenende, wenn dahinter kein Mindeststueck mehr
passt. Hauptgaenge laufen durch. Der Rest quer zu den Reihen steht in
RESTBREITE_mm. Edit des Bereichs = Neuaufbau aller Kinder (Sektions-Neuaufbau,
kein Feld-Splice) - aber nur der automatisch erzeugten (QUELLE=auto). Von Hand
eingefuegte (manuell) und von Hand geaenderte (auto_geaendert) Reihen und Gaenge
bleiben stehen und werden ausgespart, ebenso unverknuepfte manuelle Objekte, deren
Mitte in der Kontur liegt; die Anzahl wird gemeldet. Von Hand geloeschte
automatische Objekte entstehen bei dieser ausdruecklichen Neuberechnung neu.
Randgaenge (RANDGANG_N/O/S/W_mm, Nord = +Y Welt): jede Konturkante bekommt
den Randgang ihrer Himmelsrichtung (Aussennormale, auf N/O/S/W eingerastet,
45 Grad zaehlt zu N/S) als Rechteck von der Kante nach innen - auch bei L-Form
entlang der echten Kanten (dort bekommt z.B. auch die Stufenkante den
Nord-Randgang; Ausnahmen per LG_GANG). Ecken: N/S-Randgaenge besitzen sie;
an konvexen Ecken wird der O/W-Randgang gekuerzt, an einspringenden Ecken der
N/S-Randgang verlaengert (sonst bliebe ein freies Quadrat). Randgaenge an der
Unter-/Oberkante der Huelle verschieben den Modulstapel, an der linken/rechten
den Bezug der Quergaenge; Stufenkanten mitten im Stapel kappen nur die
betroffenen Reihen. Nicht rechtwinklige Ecken sind eine Naeherung.
Sperrflaechen: Randgaenge sowie von Hand eingefuegte und geaenderte Reihen und
Gaenge werden aus Reihen, Haupt- und Quergaengen ausgeschnitten - exakt ueber den
Band-Clip des Streifens (ssg-poly-band-x), Reststuecke unter der
Mindestlaenge fallen weg. Eine von Hand eingefuegte Reihe (LG_REIHE) oder ein
Gang (LG_GANG), dessen Mitte in einem Bereich liegt, wird mit ihm verknuepft.
Von Hand Gesetztes loest KEINE Neuberechnung aus. Beim Einfuegen und
Bearbeiten (LG_REIHE, LG_GANG, LG_EDIT einer Reihe/eines Gangs) schneidet das
Objekt nur seine Flaeche aus den ueberdeckten Objekten heraus
(lg-sperre-anwenden, Kern lg-linie-zuschnitt); die Reste behalten ihre Attribute.
Geschnitten wird nur, was rangniedriger ist (lg-quelle-rang: auto <
auto_geaendert < manuell) - ein manuelles Objekt schneidet aus automatischen und
geaenderten, ein geaendertes nur aus automatischen, manuelle untereinander nie. Alles
andere bleibt, wie der Anwender es hinterlassen hat: von Hand geloeschte Objekte
kommen nicht zurueck. Wird ein manueller Gang verkleinert oder geloescht, bleibt die
Luecke bis zur naechsten ausdruecklichen Neuberechnung (Doppelklick auf den
Bereich, OK).
LG_GANG zeichnet einen Gang entweder als Linie (Gangmitte, Breite aus dem
Dialog) oder ueber die Option Rechteck als Flaeche. Beim Rechteck
ergeben sich Lage und Breite aus der Flaeche, man muss sie also vorher nicht
kennen: die laengere Seite ist die Gangrichtung, die kuerzere die Breite (auf
ganze mm). Die Rundung verschiebt nur die Laengsseite gegenueber der ersten
gezeichneten Ecke - die Kante, an der man ansetzt (z.B. buendig an einer
Regalreihe), bleibt exakt liegen, sonst wuerde der Gang die Reihe um Bruchteile
eines mm ueberdecken und sie beim Zuschnitt entfernen; ebenso beginnt der Gang an
der Querseite der ersten Ecke (lg-gang-aus-ecken). Gezeichnet wird mit dem echten BricsCAD-Befehl RECHTECK
(lg-rechteck-zeichnen) - mit allen seinen Optionen (Abmessungen, Flaeche,
Drehung, Objektfang); ein gedrehtes Rechteck ergibt einen schraeg liegenden Gang.
Die gezeichnete Polylinie wird ausgewertet (lg-rechteck-ecken-aus-poly) und
wieder geloescht; mit Fase oder Rundung gezeichnete Flaechen werden abgelehnt.
Nach jedem Rechteck startet RECHTECK erneut, Enter ohne Rechteck beendet. Im Block
entsteht derselbe LG_GANG_* wie bei der Linie.
Schraffur: steckt in der Gang-Blockdefinition (Belag im Blocknamen), Muster
aus lager.json belag_schraffur - spanplatte ANSI31, gitterrost GRID,
hallenboden keine. Unbekannter Belag/Muster -> Meldung, Gang ohne Schraffur.
Reihen bleiben unschraffiert. Altbestand: fehlen einer vorhandenen
Blockdefinition ATTDEFs des Schemas, definiert lg-blockdef sie neu und
uebertraegt sie per _.ATTSYNC auf die Referenzen.
Kennwerte <- Zeichnung
Reine Kerne in LagerInsert.lsp (getestet in tu-tests-lager). Jeder
Geschoss-Kennwert steht mit Formel und Quelle unter herkunft.
| Kennwert | Quelle / Formel |
|---|---|
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 |
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 |
UNTER_REIHE kommt aus dem verknuepften Bereich; Reihen ohne Bereich (und
Bereiche ohne Attribut, Altbestand) nehmen die Vorgabe lager.json bereich.unter_reihe. GITTERKORB_HOEHE_mm ist vorerst ein Attribut am Bereich
und soll spaeter aus den Attributen berechnet werden.
Spaetere Phasen: Gelaender/Bordbrett, Oeffnungen, Treppen, Leitern, Zugaenge (Phase 2), Schnitte (Phase 3), Fluchtwege (Phase 4/5), Regelwerk-Werte je Geschoss im Export.
Regelprofil
cfg/stahlbau/regelwerk/<LAND>.json, aufgeloest von LagerPruefung.lsp:
{"id": "treppe.schrittmass_min", "art": "min", "einheit": "mm",
"werte": [{"wert": 590, "quelle": "ASR A1.8", "abschnitt": "4.5", "fassung": "...", "verifiziert": false},
{"wert": 600, "quelle": "EN ISO 14122-3", "abschnitt": "5", "fassung": "...", "verifiziert": false}]}
art:min(strengster = groesster),max(strengster = kleinster),wert.bedingung:<schluessel> <op> <wert>(=,<=,>=,<,>) gegen einen Kontext (z.B.brandgefaehrdung,absturzhoehe,personen). Fehlt der Schluessel im Kontext, wird der Eintrag konservativ einbezogen.tabelle+tabellen_schluessel: Wert der ersten Zeile[bis, wert], die den Kontextwert abdeckt (Fluchtwegbreite nach Personen).erbt_von: Laenderprofil erbt alle Regeln, eigene Records mit gleicheridersetzen sie.SK.json/PL.jsonsind Gerueste (gepflegt: false-> Warnung).LG_REGELNzeigt alle Regeln mit Ergebnis und Protokoll (welche Quelle gewann).
Alle Startwerte stehen auf verifiziert: false. Wert, Abschnitt und
Fassung muessen gegen die Originaltexte (ASR A1.8, A2.1, A2.3, DGUV Regel
108-007, EN ISO 14122-3/-4) geprueft werden; besonders unsicher sind die
DGUV-Gangbreiten und die Abschnittsnummern.
Stand
| Phase | Inhalt | Stand |
|---|---|---|
| 0 | Regelprofil + Resolver, Schema (dieses Dokument), Layer, Sprach-Keys, Menue, Laden | erledigt, Regelwerte unverifiziert |
| 1 | Geschoss, aktives Geschoss, Bereich + Auto-Fuellung, Einzelreihe, Edit, LAGER_EXPORT als Lager-JSON mit Kennwerten und Herkunft, Gitterkorb/Gitterrost unter den Reihen |
erledigt (2D) |
| 1a | Regelwerk-Werte (aufgeloest je Geschoss) im Lager-JSON; Gitterkorb-Hoehe aus den Attributen berechnen | offen |
| 2 | Gelaender/Bordbrett aus Kontur, Kanten-Ausnahmen, Oeffnungen, Treppe (Auslegung nach Profil), Leiter | offen |
| 3 | Schema-Schnitt, 3D-Varianten | offen |
| 4 | LAGER_PRUEFEN, Fluchtweg (gezeichnet), Verstoss-Marker, Nachweis mit Regelpruefung |
offen |
| 5 | automatische Fluchtweganalyse | offen |
| 6 | SK/PL-Profile, Kapazitaet, Kopplung Geruest, Stuecklisten-Klassen | offen |
Tests
tests/test_unit.lsp:tu-tests-poly(Polygon-Helfer inssg_core.lsp),tu-tests-lager(Fuellung, Geschosszuordnung, JSON-Schreiber, Kennwerte, offene Kanten/Gitterkorb, Feldpruefung, Regelprofil).tests/test_lager.lsp(TEST_LAGER,alltests.json): Ablauf in einer Zeichnung inkl. Neuberechnung, Reihen-Edit, Export (Schema, Geometrie, Kennwerte, Gitterkorb), Geschoss-Kopie undLG_REGALE.