diff --git a/CLAUDE.md b/CLAUDE.md index d198d53..95750b3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -78,11 +78,10 @@ Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD. | VarioFoerderer | `VarioFoerderer` | FOERDERANLAGE, VARIOFOERDERER_EDIT, Vario_Kette_Merge | | Gefaellestrecke | `Gefaellestrecke` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT | | Kettenfoerderer | `KettenFoerderer` | KETTENFOERDERER (Menue: Omniflo -> KettenFoerderer), KF_EDIT (Doppelklick auf KF_n). KF_KS_PRUEFEN ist ein reiner Diagnosebefehl und bewusst NICHT im Menue | -| Omniflo (komplett) | `OmniModulInsert` + `GeruestInsert` | OMNI_APB_*, OMNI_W*_*, OMNI_TEF_*, OMNI_TV_*, OMNI_LADESCHLEIFE_*, OMNI_EDIT; OMNI_FAHRSTRECKE / OMNI_FAHRSTRECKE_BESCHRIFTEN (GeruestInsert, Linien-Logik wie GERUEST_TRAEGER) | +| Omniflo (komplett) | `OmniModulInsert` + `GeruestInsert` | OMNI_APB_*, OMNI_W90/OMNI_W45/OMNI_WP/OMNI_WK (je Winkel ein Dialog, Einzel/Doppel/Dreiwege ueber "Richtung"), OMNI_WKomb_*, OMNI_WB_* (Untermenue Weichenbatterien), OMNI_TEF_*, OMNI_TV_*, OMNI_LADESCHLEIFE_*, OMNI_EDIT; OMNI_FAHRSTRECKE / OMNI_FAHRSTRECKE_BESCHRIFTEN (GeruestInsert, Linien-Logik wie GERUEST_TRAEGER) | | Geruest | `GeruestInsert` | GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG (je eigener Dialog aus der Vorlage geruest.dcl, keine Umschaltung), GERUEST_TRAEGER (eigener Dialog), GERUEST_TRAEGER_BESCHRIFTEN (Untermenue Geruest -> Funktionen -> Traeger beschriften; alle Traeger der Zeichnung neu beschriften); Gattertraeger noch Platzhalter auf GERUEST (zeigt nur einen Hinweis) | | Connections | `Connection_Edit` + `SSG_LIB_Commands` | CONNECTION_INSERT, CONNECTION_EDIT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT | -| HW Planung | `HwPlanung` | HW_MATERIALFLUSS (Materialfluss erzeugen), HW_SYMBOLE (Symbole erzeugen, noch Platzhalter) | -| Lager | `LagerInsert` + `LagerPruefung` | LG_GESCHOSS, LG_GESCHOSS_AKTIV, LG_GESCHOSS_KOPIEREN, LG_BEREICH, LG_REIHE, LG_GANG, LG_EDIT, LG_REGALE, LAGER_HAND_YAML, LAGER_EXPORT, LG_REGELN | +| Lager | `LagerInsert` + `LagerPruefung` | LG_GESCHOSS, LG_GESCHOSS_AKTIV, LG_GESCHOSS_KOPIEREN, LG_BEREICH, LG_REIHE, LG_GANG, LG_EDIT, LG_REGALE, LG_DARSTELLUNG, LAGER_EXPORT, LG_REGELN | | HW Planung | `HwPlanung` | HW_MATERIALFLUSS (Materialfluss erzeugen), HW_SYMBOLE (Symbole erzeugen), HW_NUMMERIEREN (Symbole nummerieren). Einzelbefehle HW_SYM_VENTILE/_SENSOREN/_MOTOREN/_MOTORSCHUTZ/_ENCODER/_SCANNER und HW_SYM_LOESCHEN bewusst NICHT im Menue. Ablauf: `doc/hw_planung.md` | | Export | `export` | EXPORTSIVAS, EXPORTCSV, CALLPYTHON | | Werkzeuge | `ssg_blocktools`, `ssg_texttools`, `ssg_stueckliste`, `DinFormate` | SSG_BLOCK_COUNT, SSG_BLOCK_DELETE, SSG_ATTR_ERSETZEN, SSG_TEXT_ERSETZEN, SSG_TEXT_PARALLEL, SSG_TEXT_HOEHE, SSG_TEXT_STIL, SSG_FAEHNCHEN_STUECKLISTE, DIN_FORMATE | @@ -116,7 +115,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `vf_spec.lsp` (von vf_core.lsp NACH vf_linienzug.lsp geladen) | VF_SPEC_BAU | Linienzug-Ketten aus **Eingabedaten** bauen, ohne Dialog und ohne Konsolenfrage (Stufe 1 aus `doc/todo/plan-vf-interactive.md`). Eine **Spec** beschreibt eine Kette in Domaenenwerten (`"links"`, `"winkel"`, `"aussen"`, ja/nein) statt in Menue-Codes; `vsp-journal` uebersetzt sie in ein Eingabe-Journal, `vsp-bau-aus-spec` spielt es per `vfl-journal-replay-start` durch den UNVERAENDERTEN `vf-linienzug-modus` (Replay-Kern `vsp-bau-journal` - nimmt auch ein unveraendert uebernommenes, aufgezeichnetes Journal, z.B. aus `dxf_anlage_export.py`). Damit traegt der fertige Block dasselbe `SSG_VF_EDIT`-Journal wie eine handgebaute Kette und bleibt per Doppelklick editier- und 2D/3D-konvertierbar - kein Journal-Konsument muss etwas von Specs wissen. Wichtige Regeln, die der Uebersetzer kennt: der Menue-Code haengt am Frame (erste Sektion 4 Optionen ohne GF-Bogen, danach 5), `hz` steht nur beim ERSTEN Segment im Journal, und `erst-hor` unterscheidet den horizontalen Erstkoerper einer VF-Einheit (Separator-/Endpunktfragen vorab) vom gewinkelten (keine Frage). Fehlerverhalten: fail fast - `vsp-pruefen` sammelt ALLE Spec-Fehler, gebaut wird dann nichts (nichts wird geraten). Ergebnis-Record je Kette mit `status` (`executed`/`warnung`/`desync`/`abbruch`/`spec-fehler`), Block/Handle/Einfuegepunkt/Attributen, `prompts` (muss 0 sein), `glieder_soll` vs. `glieder_ist` (Desync-Detektor, der auch bei aufgehender Queue greift) und den gesammelten `meldungen`. Headless-Rahmen `vsp-headless-an`/`-aus` (Save/Restore von `*vfl-headless*`, `*vfl-wizard-mode*`, `*ssg-gui-aus*` + zaehlende Eingabe-Stubs). Spec-Datei flach als JSON (`ssg-load-json` liest zeilenweise), erzeugt von `lib/vf_spec_export.py`. Gegenstueck/Referenz in Python: derselbe Emitter, gegen die 5 echten HundM-Ketten rundlaufgeprueft | | `Gefaellestrecke.lsp` | GEFAELLESTRECKE, GEFAELLESTRECKE_EDIT | Gefaelle-Foerderanlage (AUS -> Staustrecke skaliert -> Separator -> EIN); Modus 1 per DCL-Dialog (Einfuegehoehe, Element-Winkel 30/90); Doppelklick auf GF_n-Block ruft GEFAELLESTRECKE_EDIT (Dialog vorbelegt, Neuaufbau; die Einfuegehoehe kommt aus der aktuellen Z des Einfuegepunkts statt aus XDATA/HOEHE_VON_mm, damit ein in Z verschobener Block per OK direkt auf der neuen Hoehe neu entsteht - gleiches gilt fuer die 2D/3D-Umschaltung `gf-konvertiere-ent`; der GF-Linienzug-Rebuild nutzt weiter die absoluten Segmentpunkte aus XDATA) | | `export.lsp` | EXPORTSIVAS, EXPORTCSV, OMNI_UPDATE_ATTRIBS, CSV_EXPORT_KONFIG | JSON-Sammlung und Python-Export (Omniflo-Merkmale/Sum-Zeile via lib/export_csv.py). **Gefrorene Layer**: `csv:collect-export-blocks` laesst Bloecke auf gefrorenen Layern aus (ausgeschaltete Layer zaehlen NICHT), Schalter `*csv-gefrorene-ausschliessen*` (Standard an, Toggle im Dialog CSV_EXPORT_KONFIG). Die Hilfsobjekte eines gefrorenen VF_n/GF_n (Separator-/Element-Kopien, Einheiten-/AS-ES-Marker) liegen auf eigenen Layern und werden darum ueber `*csv-ausschluss-enames*` mit ausgelassen (gesetzt in `csv:export-vorbereiten` per `csv:hilfskopien-ausschluss`); erzeugt und nummeriert werden sie trotzdem, damit IDs stabil bleiben. DrawPlanquadrate nutzt dieselbe Sammlung und folgt dem Filter. **Hoehen-Neuberechnung**: erster Schritt von `csv:export-vorbereiten` ist `csv:hoehen-aktualisieren` - in Z verschobene `KREISEL_*`/`ECKRAD_*`/`VF_*`/`GF_*` bekommen ihre Hoehen-Attribute aus der Einfuege-Z neu (reiner Kern `csv:hoehen-werte`, getestet; Formeln/Rundung wie beim Bau: Kreisel HOEHE + MONTAGEHOEHE_m=z/1000, Eckrad HOEHE, GF/VF HOEHE_VON_mm=(fix z), MONTAGEHOEHE_m GF=z/1000 bzw. VF=(VON+BIS)/2000). HOEHE_BIS_mm = VON - (VON_alt - BIS_alt), bewusst NICHT z - DELTA_H_mm (ohne Vorzeichen -> steigende VF falsch, separat abgeschnitten -> 1 mm Abweichung); DELTA_H_mm nur Rueckfall. Nicht verschobene Bloecke (Attribut passt zu z) bleiben unangetastet, damit Bau-Werte und Hand-Korrekturen (z.B. Buehnen-Abzug aus HOEHEN_CHECK) bit-genau erhalten bleiben | -| `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W*_*, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_LADESCHLEIFE_AP110, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder (`OMNI_TV_*`: DWGs dimensionsunabhaengig in `data/omniflo/Verbinder`, `omni:insert-verbinder` -> gemeinsamer Einfuegekern `omni:insert-datei`, den auch `omni:insert-dxf` nutzt; im Export ueber `pattern_verbinder` = `VB_*, TV_*` gesammelt (`csv:collect-export-blocks`, `ssg-id-collect-blocks`), Sivas-Zeilen ueber TEILEART/ARTINR wie alle Omniflo-Teile), Transferwagen, Ladeschleifen (`data/json/omniflo_ladeschleifen.json`, per `ssg-json-laden`, da die Beschreibungen Kommas enthalten; Blockdatei darf `.dwg` statt `.dxf` sein), Edit-Dialog | +| `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W90, OMNI_W45, OMNI_WP, OMNI_WK, OMNI_WKomb_*, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_WB_*, OMNI_LADESCHLEIFE_AP110, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen (je Winkel EIN Dialog; Einzel/Doppel/Dreiwege ueber die Radiogruppe "Richtung" = KurvenRichtung 1/2/3/7, `*omni-weichen-std-typen*`/`omni:weichen-basis-liste`/`omni:weichen-richtung-key` getestet; Deltaweichen tragen ebenfalls 3/7 und bleiben darum per WeichenTyp draussen; Richtungen ohne Katalogeintrag ausgegraut; OMNI_EDIT erlaubt so den Wechsel Einzel <-> Doppel <-> Dreiwege), Weichenbatterien (`OMNI_WB_`: DWG aus `data/omniflo/2D`, Menuetexte/Nummern aus `data/omniflo/weichenbatterien_artinr_quelle.dxf`; im Katalog `omniflo_weichen.json` als `WeichenTyp` "Weichenbatterie" ohne Winkel/Breite/Laenge, damit der Doppelklick den Weichen-Dialog mit Richtung/Schaltung oeffnet), Verbinder (`OMNI_TV_*`: DWGs dimensionsunabhaengig in `data/omniflo/Verbinder`, `omni:insert-verbinder` -> gemeinsamer Einfuegekern `omni:insert-datei`, den auch `omni:insert-dxf` nutzt; im Export ueber `pattern_verbinder` = `VB_*, TV_*` gesammelt (`csv:collect-export-blocks`, `ssg-id-collect-blocks`), Sivas-Zeilen ueber TEILEART/ARTINR wie alle Omniflo-Teile), Transferwagen, Ladeschleifen (`data/json/omniflo_ladeschleifen.json`, per `ssg-json-laden`, da die Beschreibungen Kommas enthalten; Blockdatei darf `.dwg` statt `.dxf` sein), Edit-Dialog (OMNI_EDIT waehlt das bearbeitete Bauteil im Dropdown vor - globale `*omni-dlg-vorwahl*` statt neuer Dialog-Parameter; im Weichen-Dialog stehen Schaltung/Richtung auf seinen Werten, ein Filterwechsel waehlt das Gegenstueck mit dem aehnlichsten ProfilTyp, reine Kerne `omni:profil-aehnlichkeit`/`omni:vorwahl-index` getestet) | | `SSG_LIB_Commands.lsp` | ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_SCANNER_INSERT, ILS_SEPARATOR_INSERT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT, SSG_BLOCKEDIT, SSG_DIM_SWITCH, SSG_SPRACHE | BTMT Be-/Entladung (`ils-insert-station`: wiederholtes Einfuegen von `BTMT-Beladung` bzw. `SC_Entladung`, Drehung interaktiv, Layer aus `LAYER`-Attribut, Dimension via `ssg-ils-block-laden`) + Sensoren (`ils-insert-sensor`) + Eingang-/Ausgang-Symbol (frei platzierbar wie BTMT Be-/Entladung, ueber `ils-insert-station` mit den Rohnamen `Eingang`/`Ausgang`, Bloecke `Eingang_.dwg`/`Ausgang_.dwg` in data/ils) + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) | | `Tro_Edit.lsp` | TRO_INSERT, TRO_EDIT | TRO-Marker (Block `TRO_SYM_`) fuer sps_skel (lib/tro_annotate.py): TRO_INSERT fuegt eine bestehende Blockdefinition an einem gewaehlten Punkt ein und setzt ID/TYPE (bricht ab, wenn der Typ noch keine Blockdefinition in der Zeichnung hat - die entsteht nur ueber tro_annotate.py); TRO_EDIT aendert ID/TYPE eines bestehenden Markers per Dialog. Typliste aus `tro_types.lsp` (von `tro_annotate.py --emit-lisp` nach DXFM_LISP geschrieben). Der Dispatcher SSG_BLOCKEDIT leitet Blocknamen `TRO_*` zu TRO_EDIT. | | `Connection_Edit.lsp` | CONNECTION_INSERT, CONNECTION_EDIT | Verbindung zwischen zwei TRO-Markern als Block `CONNECTION_ARROW` (Pfeilmitte); Beziehung ueber die INTERNEN IDs der TROs (`FROM_ID`/`TO_ID`, sichtbar `FROM_TRO`/`TO_TRO`, `KIND` flow/colocated), damit Umbenennen/Verschieben die Zuordnung nicht bricht. Dialog `connection_edit.dcl`; SSG_BLOCKEDIT leitet `CONNECTION_*` hierher (vor dem TRO-Zweig) | @@ -126,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, HW_SYM_VENTILE, HW_SYM_SENSOREN, HW_SYM_MOTOREN, HW_SYM_MOTORSCHUTZ, HW_SYM_ENCODER, HW_SYM_SCANNER, HW_SYM_LOESCHEN, HW_NUMMERIEREN | Menue "HW Planung" (zwischen Lager und SPS), Ablauf und Renamer-Regeln in `doc/hw_planung.md`. **Ausgabeziel per Dialog** `dcl/hw_ausgabe.dcl` vor jedem Erzeugungsbefehl (`hw-ausgabe-waehlen`, letzte Wahl je Sitzung in `*hw-ausgabe-letzt*`, ohne GUI Standarddatei `_HW.dxf`): **aktuelle Zeichnung** (Python schreibt eine EINHEITENLOSE Zwischendatei `_HW_tmp.dxf` (`--einheitenlos`, sonst skaliert BricsCAD beim Einfuegen), `hw-in-aktuelle-zeichnung` fuegt sie per `vla-InsertBlock` bei 0,0 ein, loest sie per `vla-Explode` auf und loescht ERST DANACH die fruehere Ausgabe - `hw-alte-ausgabe` ueber XDATA `SSG_HW_MF` (Materialfluss) bzw. `SSG_HW_SYM` je Praefix), **bestehende Datei ergaenzen** (getfiled ueber `done_dialog 2`, da getfiled aus einem action_tile nicht geht) oder **neue Datei** (Name, Ordner DXFM_RESULTS; existiert sie, bleibt der Dialog mit Hinweis offen). Reine Kerne `hw-name-ohne-dxf`/`hw-name-gueltig-p`/`hw-neu-pfad`/`hw-ausgabe-pruefen` getestet. In einer Datei ersetzt jeder Befehl nur seinen eigenen Anteil (Materialfluss = XDATA `SSG_HW_MF` bzw. HW_*-Layer, Symbole = XDATA `SSG_HW_SYM` je Praefix) - vom Anwender Gezeichnetes (Renamer-Bereiche) bleibt; die Ursprungsdatei auf der Platte wird nie geaendert. Python-Aufrufe zentral ueber `hw-python` (Log je Befehl in DXFM_LOG, `ok-codes` fuer create_numbers' Exit 1 bei Planungsfehlern). HW_MATERIALFLUSS: EXPORTCSV (alte CSV vorher geloescht) -> `lib/hw_materialfluss.py`. **Symbole**: Regelwerk `cfg/io_regeln.json` (reduzierte Kopie aus kabellaengen: Rollen mit Praefix/Symbolblock, Bauteile, `io_vorlage`; Erkennungs-Regex/Radien/Nummernpaare/altZuNeu entfernt). **Aussehen und Attribute der Symbole stehen in `cfg/hw_symbole.json`** (Vorlagen mit Rahmen/Schraffur + Attribut-Lage/-Hoehe/-Stil, je Symbol Layer/Farbe/`versatz`/Abweichungen je Tag/Werte) - es gibt KEINE Symbol-Bibliothek als Referenzdokument. Die Symbole tragen DIESELBEN Blocknamen wie die ILS-Katalogsymbole in kabellaengen und sind ihnen exakt nachgebaut (inkl. Einfuegepunkt: Eingaenge/Motoren haengen nach unten) - `test_symbole_gleichen_dem_katalog` prueft das gegen `kabellaengen/doc/Symbole/ILS-Symbole.dxf`; aendert sich dort ein Symbol, faellt der Test und die Konfiguration wird nachgezogen. `hw-sym-bauteile-sammeln` findet die Mechanik-Bloecke der Ursprungszeichnung top-level UND verschachtelt in VF_n/GF_n/KREISEL_n (Weltlage ueber `csv:wrapper-welt-records`), `hw-sym-plan` legt je Rolle Symbolblock, flachen ZIELPUNKT (Bauteil-Einfuegepunkt, `hw-sym-ziel`) und ID-VORLAGE (`hw-sym-io-vorlage`, z.B. `MB1@@@`) fest; bei Alternativen in `benoetigt` die erste. `hw-sym-plan->json` (Zahlen ueber `hw-json-zahl`, DIMZIN-unabhaengig) -> `_hw_symbole.json` -> `lib/hw_symbole.py`; der Plan ist IMMER vollstaendig (alle Praefixe), `praefixe` sagt nur, was eingefuegt wird - so haengt die Lage nicht vom Einzelbefehl ab. Die LAGE rechnet Python (kennt die Symbolgeometrie), nicht LISP. Die Nummern vergibt NICHT das Erzeugen, sondern HW_NUMMERIEREN in der geoeffneten _HW.dxf: QSAVE, `lib/create_numbers.py --dryrun --info`, dann `hw-num-anwenden` (Zuordnung je Attribut mit `@` ueber Wert + Einfuegepunkt, `hw-num-eintrag-p`) in die offene Zeichnung. Reine Kerne in `tu-tests-hw` | | `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, LG_DARSTELLUNG, 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. **Bereich bearbeiten ueberschreibt nichts**: Nicht-Geometrie-Werte (Belag, Haengeebenen) werden auf alle vorhandenen Kinder uebertragen (`lg-bereich-attribute-uebertragen`), neu berechnet wird nur auf Rueckfrage und mit Vorgabe Ja nur bei Geometrieaenderung (`lg-bereich-geometrie-geaendert-p`). Die Neuberechnung (`lg-bereich-fuellen`) entfernt nur `QUELLE=auto`; ALLE `manuell`/`auto_geaendert`-Objekte des Geschosses (`lg-von-hand-auf-geschoss`) sperren ihre Flaeche - auch in den Randgaengen (`lg-randgang-stuecke`), ein manueller Gang ersetzt den Randgang statt von ihm ueberlagert zu werden. `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`). **Darstellung der Absturzsicherung** (`lg-darstellung-geschoss`): auf Buehnen je Reihe eine Schraffur fuer gitterrost bzw. gitterkorb, beim Gitterkorb zusaetzlich die seitliche Abgrenzung als dicke Polylinie NUR an offenen Kanten (reiner Kern `lg-sicherung-geometrie` ueber `lg-kante-offen-intervalle`, gleiche Regel wie der Export). Lose Objekte auf `LG_Sicherung_G` mit XDATA `rolle=sicherung`, bei jedem Neuaufbau komplett ersetzt; automatisch nach Bereich fuellen, Reihe/Gang/Geschoss bearbeiten, `LG_REIHE`/`LG_GANG` und Geschoss kopieren. Farben/Muster aus `lager.json` (`darstellung.reihe.farbe`, `darstellung.unter_reihe.*`, `belag_schraffur..farbe`; ACI oder "r,g,b", `lg-farbe-dxf`/`lg-farbe-setzen`). `LG_DARSTELLUNG` (Menue Lager -> Darstellung aktualisieren) liest lager.json neu, frischt die Definitionen `LG_REIHE_*`/`LG_GANG_*` auf (`lg-darstellung-definitionen`) und zeichnet alle Geschosse neu. 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; ALLE Gaenge bekommen den gewaehlten Belag, auch manuelle (`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). | @@ -140,7 +139,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `gefaellestrecke.dcl` | GEFAELLESTRECKE Modus 1 (Gefaellestrecke.lsp, `gf-dialog-eingabe`) | | `variofoerderer.dcl` | FOERDERANLAGE Standardfall + Werteingabe (vf_standard.lsp, `vfs-dialog-eingabe-basis`/`vfs-dialog-winkel-verteilung`) | | `omniflo_boegen.dcl` | OMNI_APB_* (OmniModulInsert.lsp) | -| `omniflo_weichen.dcl` | OMNI_W*_* (OmniModulInsert.lsp) | +| `omniflo_weichen.dcl` | OMNI_W90/W45/WP/WK, OMNI_WKomb_*, OMNI_EDIT (OmniModulInsert.lsp, `omni:weichen-dialog`); Radiogruppe Richtung `ri_alle`/`ri_links`/`ri_rechts`/`ri_doppel`/`ri_dreiwege` | | `omniflo_ladeschleifen.dcl` | OMNI_LADESCHLEIFE_* (OmniModulInsert.lsp, `omni:ladeschleifen-dialog`) | | `sprache.dcl` | SSG_SPRACHE (SSG_LIB_Commands.lsp) | | `tro_insert.dcl` | TRO_INSERT (Tro_Edit.lsp) | @@ -228,7 +227,6 @@ Abhaengigkeiten: `ezdxf`, Standard-Library. Benoetigen Umgebungsvariablen (`DXFM | `hw_symbole.py` | HW-Planung: setzt die E-Geraete-Symbole aus dem Plan `_hw_symbole.json` (HW_SYMBOLE, HwPlanung.lsp) in die `_HW.dxf` (`hw_materialfluss.hw_dokument_oeffnen`: vorhandene Datei ergaenzen statt ueberschreiben). Entfernt vorher nur die erzeugten Symbole der Praefixe des Plans (XDATA `SSG_HW_SYM`), baut die Blockdefinitionen bei jedem Lauf neu aus `cfg/hw_symbole.json` (`block_aufbauen`: Rahmen, ATTDEFs, Textstil, Layer), **Lage** per `platzieren`: Marke `REALE_POSITION` mit x genau auf dem Zielpunkt, Kasten daneben, Symbole eines Bauteils luekenlos uebereinander (Reihenfolge `benoetigt`), Gruppe um das Ziel zentriert; Ueberlappung mit schon gesetzten Rahmen (2D-Bounding-Boxen, `platzierung` in hw_symbole.json) wird NUR in y ausgewichen, x bleibt auf dem Ziel; Plan immer vollstaendig, eingefuegt nur `praefixe`. IO = Vorlage, Platzhalter-ID in VERW/BEZEICHNUNG ersetzt (`attribut_werte`). Test `tests/test_hw_symbole.py` (inkl. Abdeckung io_regeln -> hw_symbole und Kette Symbole -> Renamer-Polylinie -> create_numbers). Aufruf: `python hw_symbole.py --symbole cfg/hw_symbole.json` | | `create_numbers.py` | Nummerierung der Symbol-Vorlagen (`@`) entlang von Renamer-Bereichen (Rechteck mit Richtung oder `POLYLINE_PATH`), Layer/Parameter aus `cfg/enumerate.cfg`; Fehler/Warnungen als zwei einfache Listen `(art, text)` (`neue_meldungen`/`meldungen_als_dict`, Format der Fehlerdatei unveraendert) - KEINE Kopie von kabellaengens `error_collector.py`/`utils.py`; die wenigen Helfer daraus stehen einmalig im Modul. 2026-11-03 aus kabellaengen umgezogen (dort entfernt), die benoetigten Helfer aus kabellaengen/lib/utils.py stehen direkt im Modul, `--all-examples` entfallen. Nummer wird OKTAL gebildet (`oct(counter)`, so gewollt - nicht auf dezimal "korrigieren"). Genutzt von HW_NUMMERIEREN. Test `tests/test_create_numbers.py`. Aufruf: `python create_numbers.py --filename [--config ...] [--info ...] [--errorfile ...] [--dryrun\|--overwrite]` | | `lager_yaml_export.py` | Lagerplanung: `_lager_raw.json` (LAGER_EXPORT) -> `_drawing.yaml` (Overlay im Schema der RFQ-Hand-YAML, nur Zeichnungsfelder, plus `_provenance`/`_conflicts`/`_warnings`) und optional `--nachweis` HTML. `--hand ` gleicht ab (Hand gewinnt; Konflikte bei > 1 % bzw. 0,005). Aggregiert nur, Regeln leben in LISP. Braucht `pyyaml`. Test `tests/test_lager_yaml.py`. Aufruf: `python lager_yaml_export.py [--hand ...] [--nachweis ...]` | - | `dxf_scan_components.py` | Erkennt ILS-/Omniflo-Komponenten in einer **fremden** Projektzeichnung (ohne unsere Wrapper-Bloecke) und schreibt sie im JSON-Schema aus `doc/json-input-lisp.md` (Nachfolger des geloeschten `tests/testdata/object_data.md`) — Grundlage fuer Nachbau-Testfaelle wie `tests/testdata/mubea.json`. Liest binaere DXF im GB-Bereich streamend per mmap (ezdxf-DOM waere zu gross), loest INSERTs inkl. OCS/Extrusionsrichtung rekursiv in Weltkoordinaten auf, paart AN8/SP8 zu Kreiseln und Antrieb/Umlenkung zu Foerderern. Gefaellestrecken, die als 3D-LINE auf einem Staustrecken-Layer gezeichnet sind (`GF_LINIE_LAYER`, z.B. `6-SP`), werden in einem zweiten Lesedurchgang zu Modus-1-Eintraegen: Start/Ende werden auf die Ketten der anschliessenden Kreisel verlaengert (gezeichnet ist nur die Staustrecke; `deltaL` reicht von AS- bis ES-Ursprung), AS-Seite aus dem Ausschleuselement am oberen Ende; dieses und Separatoren auf der Achse entfallen als Einzel-Insert (die GF baut beide selbst). Sitzt der AS am UNTEREN Ende, ist es ein Steigfoerderer und wird nur gemeldet (`gf_eintraege_aus_linien`, Test `tests/test_dxf_scan_gf.py`). `--ohne-hoehen` setzt alle Z auf 0, `--kreisel-hoehe X Y Z` gibt einem Kreisel seine Hoehe - die daran haengenden GF bekommen daraus `start_mm.z`/`hoehe_ende_mm`, den Winkel rechnet der Treiber (`dematic_arvato:gf-geometrie`: atan ueber die HORIZONTALE Laenge, ES-Laenge UND -Abfall bei der Einlaufneigung gemessen und iteriert, Staustrecke daraus - die flache ES-Laenge liess steile GF ~144 mm vor der Kette enden - NICHT `gf-winkel-berechnen`, dessen asin bei steilen GF wie im Showroom ~50 statt ~37 Grad liefert; `dematic_arvato:gf-endhoehe-pruefen` meldet `warnung` bei > 5 mm Abweichung von HOEHE_BIS). Flache 2D-Plaene: `--flach` (waagrechte Staustrecke mit AS an genau einem Ende = GF, zerstueckelte Linien werden vereint, ES am unteren Ende wird verbraucht, AS/ES-Seite ohne Namensangabe aus der Lage zur Fahrtrichtung), `--kreisel-achse X1 Y1 X2 Y2` (Kreisel ohne AN8/SP8), Einzelteile auf einer Kreisel-Kette erben dessen Anwender-Hoehe (`sensor_hoehen_von_kreiseln`). Kreisel-Paarung mit Tausch-Nachbesserung auf minimale Abstandssumme (zwei Kreisel auf einer Achse). Genutzt fuer `tests/testdata/showroom_ils.json` (`TEST_SHOWROOM_ILS`). Aufruf: `python dxf_scan_components.py [--fenster X0 Y0 X1 Y1]` — ohne `--fenster` liefert eine Anlagenzeichnung leicht ueber 1300 Eintraege, zuviel fuer einen Testlauf | ### Entwickler-Tools (`lib/`) - kein ezdxf, reine Text-/AutoLISP-Verarbeitung diff --git a/Lisp/LagerInsert.lsp b/Lisp/LagerInsert.lsp index 6b36b27..a81da2a 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* @@ -769,12 +768,51 @@ "")) ) -;; Reihe: Rechteck L x T um die Schienenlinie (0,0)-(L,0). -(defun lg-reihe-blockdef (laenge tiefe / h) - (setq h (/ tiefe 2.0)) +;; ------------------------------------------------------------ +;; Farben (lager.json: ACI-Nummer 1..255 oder RGB-Text "r,g,b") +;; ------------------------------------------------------------ + +;; "r,g,b" -> (r g b), sonst nil. Rein, getestet. +(defun lg-farbe-rgb (farbe / teile) + (if (= (type farbe) 'STR) + (progn + (setq teile (mapcar '(lambda (s) (atoi (vl-string-trim " " s))) + (ssg-sepliste-split-feld farbe ","))) + (if (and (= (length teile) 3) (vl-every '(lambda (x) (<= 0 x 255)) teile)) teile))) +) + +;; Farbe als DXF-Gruppen fuer entmake: ACI -> ((62 . n)), RGB -> ((420 . rgb)), +;; nil/ungueltig -> nil (VONLAYER). Rein, getestet. +(defun lg-farbe-dxf (farbe / rgb) + (cond + ((and (numberp farbe) (<= 1 (fix farbe) 255)) (list (cons 62 (fix farbe)))) + ((setq rgb (lg-farbe-rgb farbe)) + (list (cons 420 (+ (* 65536 (car rgb)) (* 256 (cadr rgb)) (caddr rgb))))) + (T nil) + ) +) + +;; Farbe auf ein ActiveX-Objekt setzen; ohne gueltige Farbe -> sonst +;; (ACI-Nummer, z.B. 0 = VONBLOCK, 256 = VONLAYER). +(defun lg-farbe-setzen (obj farbe sonst / rgb c) + (cond + ((and (numberp farbe) (<= 1 (fix farbe) 255)) (vla-put-Color obj (fix farbe))) + ((setq rgb (lg-farbe-rgb farbe)) + (setq c (vla-get-TrueColor obj)) + (vla-SetRGB c (car rgb) (cadr rgb) (caddr rgb)) + (vla-put-TrueColor obj c)) + (T (vla-put-Color obj sonst)) + ) +) + +;; Reihe: Rechteck L x T um die Schienenlinie (0,0)-(L,0), Farbe aus +;; lager.json darstellung.reihe.farbe (sonst VONLAYER). +(defun lg-reihe-blockdef (laenge tiefe / h f) + (setq h (/ tiefe 2.0) + f (lg-farbe-dxf (lg-vorgabe '("darstellung" "reihe" "farbe") nil))) (lg-blockdef (lg-reihe-blockname laenge tiefe) - (append (list (lg-geom-rechteck 0.0 (- h) laenge h) - (lg-geom-linie '(0.0 0.0 0.0) (list laenge 0.0 0.0))) + (append (list (append (lg-geom-rechteck 0.0 (- h) laenge h) f) + (append (lg-geom-linie '(0.0 0.0 0.0) (list laenge 0.0 0.0)) f)) (lg-attdefs-unsichtbar *lg-schema-reihe*))) ) @@ -796,33 +834,53 @@ (if (not (boundp '*lg-schraffur-gemeldet*)) (setq *lg-schraffur-gemeldet* nil)) -;; Schraffur in eine vorhandene Blockdefinition einsetzen: umrandet die -;; erste Polylinie der Definition, Layer 0 + Farbe VONBLOCK (erbt den -;; Geschoss-Layer der Referenz). vorgabe = (muster massstab winkel-grad). -;; Rueckgabe: T oder nil (Muster unbekannt o.ae., Meldung). -(defun lg-schraffur-einsetzen (bname vorgabe / blk pl h res) +;; Schraffur anlegen (Block oder Modellbereich): owner = Block-/Bereichs- +;; objekt, pl = geschlossene Polylinie (vla) als Umgrenzung, vorgabe = +;; (muster massstab winkel-grad), farbe aus lager.json, sonst-farbe wie bei +;; lg-farbe-setzen, z = Erhebung. Rueckgabe: Hatch-Objekt oder nil (Meldung). +(defun lg-schraffur-anlegen (owner pl vorgabe farbe sonst-farbe layer z wo / h res) (setq res (vl-catch-all-apply '(lambda () - (setq blk (vla-Item (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))) bname)) - (vlax-for o blk - (if (and (null pl) (= (vla-get-ObjectName o) "AcDbPolyline")) (setq pl o))) - (setq h (vla-AddHatch blk 1 (car vorgabe) :vlax-false)) ; 1 = vordefiniert - (vla-put-Layer h "0") - (vla-put-Color h 0) ; 0 = VONBLOCK + (setq h (vla-AddHatch owner 1 (car vorgabe) :vlax-false)) ; 1 = vordefiniert + (vla-put-Layer h layer) + (lg-farbe-setzen h farbe sonst-farbe) (vla-put-PatternScale h (cadr vorgabe)) (vla-put-PatternAngle h (* (/ (caddr vorgabe) 180.0) pi)) + (if (and z (/= z 0.0)) (vla-put-Elevation h z)) (vlax-invoke h 'AppendOuterLoop (list pl)) (vla-Evaluate h) - T))) + h))) (if (vl-catch-all-error-p res) (progn (if h (vl-catch-all-apply 'vla-Delete (list h))) - (princ (ssg-textf "lg-schraffur-fehler" (list (car vorgabe) bname (vl-catch-all-error-message res)))) + (princ (ssg-textf "lg-schraffur-fehler" (list (car vorgabe) wo (vl-catch-all-error-message res)))) nil) res) ) +(defun lg-bloecke () + (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))) +) + +;; Schraffur in eine vorhandene Blockdefinition einsetzen: umrandet die +;; erste Polylinie der Definition, Layer 0; ohne farbe VONBLOCK (erbt den +;; Geschoss-Layer der Referenz). Rueckgabe: T oder nil. +(defun lg-schraffur-einsetzen (bname vorgabe farbe / blk pl) + (setq blk (vl-catch-all-apply 'vla-Item (list (lg-bloecke) bname))) + (if (not (vl-catch-all-error-p blk)) + (progn + (vlax-for o blk + (if (and (null pl) (= (vla-get-ObjectName o) "AcDbPolyline")) (setq pl o))) + (if (and pl (lg-schraffur-anlegen blk pl vorgabe farbe 0 "0" nil bname)) T))) +) + +;; Farbe der Gangschraffur eines Belags (belag_schraffur..farbe). +(defun lg-schraffur-farbe (belag tabelle / e) + (if (and belag (= (type belag) 'STR) (setq e (ssg-json-get tabelle belag)) (listp e)) + (ssg-json-get e "farbe")) +) + (defun lg-gang-blockdef (laenge breite belag / h bname tab vorgabe) (setq h (/ breite 2.0) bname (lg-gang-blockname laenge breite belag) @@ -839,7 +897,7 @@ ;; Schraffur nur einmal je Definition (auch nach einer Neudefinition) (if (and vorgabe (not (vl-some '(lambda (ed) (= (cdr (assoc 0 ed)) "HATCH")) (lg-blockdef-objekte bname)))) - (lg-schraffur-einsetzen bname vorgabe)) + (lg-schraffur-einsetzen bname vorgabe (lg-schraffur-farbe belag tab))) bname ) @@ -874,7 +932,9 @@ ;; anwenden) - fuer das Bearbeiten von Hand. Rueckgabe: neuer ename. (defun lg-linie-neu-aufbauen-sperre (ent werte / neu) (if (setq neu (lg-linie-neu-aufbauen ent werte)) - (lg-sperre-anwenden neu)) + (progn + (lg-sperre-anwenden neu) + (lg-darstellung-geschoss (atoi (cond ((cdr (assoc "GESCHOSS" (ssg-attrib-read neu)))) ("0")))))) neu ) @@ -1125,11 +1185,30 @@ ) ) ) + ;; Randgaenge selbst an den AEUSSEREN Sperrflaechen (manuelle/geaenderte + ;; Objekte) beschneiden - ein von Hand gesetzter Gang ersetzt den Randgang + ;; dort, wo er liegt, statt von ihm ueberlagert zu werden. (foreach s rand-str - (setq recs (cons (list "randgang" (cadr s) (caddr s) (cadddr s)) recs))) + (foreach st (lg-randgang-stuecke (cadr s) (caddr s) (cadddr s) (lg-param params "sperr" nil) min-g) + (setq recs (cons (list "randgang" (car st) (cadr st) (cadddr s)) recs)))) (list (reverse recs) (- (- ymax oben) y) module) ) +;; Stuecke eines Randgangs (Mittellinie p1-p2, Breite b) ohne die Flaechen +;; der Sperrpolygone (gleiches System). Reiner Kern ueber lg-linie-zuschnitt. +;; Rueckgabe ((q1 q2) ...); ohne Ueberdeckung ((p1 p2)). +(defun lg-randgang-stuecke (p1 p2 b sperr min-g / a l lok st) + (setq a (angle p1 p2) l (distance p1 p2)) + (setq lok (mapcar '(lambda (poly) + (ssg-poly-drehen (mapcar '(lambda (q) (list (- (car q) (car p1)) (- (cadr q) (cadr p1)))) poly) + (- a) '(0.0 0.0))) + sperr)) + (setq st (if lok (lg-linie-zuschnitt l b lok min-g) 'unveraendert)) + (if (eq st 'unveraendert) + (list (list p1 p2)) + (mapcar '(lambda (i) (list (polar p1 a (car i)) (polar p1 a (cadr i)))) st)) +) + ;; Richtung der Reihen als Vorgabe: Winkel der laengsten Konturkante (Grad, ;; auf [0,180) normiert). (defun lg-kontur-richtung (pts / best w l) @@ -1321,6 +1400,15 @@ (append (lg-alle-bloecke "LG_REIHE_*") (lg-alle-bloecke "LG_GANG_*"))) ) +;; Alle von Hand gesetzten oder geaenderten Reihen/Gaenge (QUELLE manuell +;; oder auto_geaendert) des Geschosses gs (String) - gleich welchem Bereich +;; sie gehoeren und wo ihre Mitte liegt. Sie sind Sperre fuer jede Fuellung. +(defun lg-von-hand-auf-geschoss (gs) + (vl-remove-if-not + '(lambda (e) (and (= (cdr (assoc "GESCHOSS" (ssg-attrib-read e))) gs) (lg-von-hand-p e))) + (append (lg-alle-bloecke "LG_REIHE_*") (lg-alle-bloecke "LG_GANG_*"))) +) + ;; Von Hand gesetzte Reihen/Gaenge (QUELLE manuell) desselben Geschosses, ;; die nicht mit einem Bereich verknuepft sind, aber mit ihrer Mitte in der ;; Kontur pts liegen (z.B. Altbestand von LG_REIHE vor der Verknuepfung). @@ -1342,8 +1430,8 @@ ;; Die automatisch erzeugten Kinder (QUELLE auto) werden vorher entfernt ;; (Sektions-Neuaufbau statt Feld-Splice). Von Hand gesetzte (manuell) und ;; von Hand geaenderte (auto_geaendert) Reihen und Gaenge bleiben stehen und -;; sparen ihre Flaeche aus - ebenso unverknuepfte manuelle Objekte in der -;; Kontur. Rueckgabe: (reihen gaenge restbreite). +;; sparen ihre Flaeche aus - das gilt fuer alle von-Hand-Objekte des +;; Geschosses, auch aus den Randgaengen. Rueckgabe: (reihen gaenge restbreite). (defun lg-bereich-fuellen (bereich-ent / a kontur pts w pts-l erg z gs n-reihen n-gaenge werte-reihe werte-gang p1 p2 behalten) (setq a (ssg-attrib-read bereich-ent) @@ -1373,13 +1461,14 @@ (cons "min_gang" (lg-zahl (lg-vorgabe '("bereich" "min_ganglaenge_mm") 100))) (cons "rand" (lg-bereich-rand a)) (cons "richtung" w) + ;; Sperre: ALLE von Hand gesetzten/geaenderten Objekte des + ;; Geschosses (auch fremder Bereiche, auch nur teilweise in der Kontur) (cons "sperr" (mapcar '(lambda (g) (ssg-poly-drehen (lg-linie-polygon g) (- w) '(0.0 0.0))) - behalten))))) + (lg-von-hand-auf-geschoss (cdr (assoc "GESCHOSS" a)))))))) (setq gs (cdr (assoc "GESCHOSS" a)) n-reihen 0 n-gaenge 0) (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)) @@ -1400,6 +1489,7 @@ (lg-attribute-setzen bereich-ent (list (cons "RESTBREITE_mm" (lg-mm-str (cadr erg))))) (princ (ssg-textf "lg-bereich-gefuellt" (list (cdr (assoc "NR" a)) (itoa n-reihen) (itoa n-gaenge) (lg-mm-str (cadr erg))))) + (lg-darstellung-geschoss (atoi gs)) (list n-reihen n-gaenge (cadr erg)) ) ) @@ -1513,11 +1603,13 @@ ;; (dx dy) versetzt; in einer 3D-Zeichnung (Konturen auf Belagshoehe) ;; zusaetzlich in Z um den Hoehenabstand. -;; 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. +;; Reiner Kern: Belag eines kopierten Bereichs/Gangs. Ist fuer die Kopie +;; ein Belag gewaehlt, bekommen ALLE Gaenge und Bereiche ihn - auch von Hand +;; gesetzte Rand-/Sondergaenge (sonst blieb der alte Belag stehen). Ohne +;; Wahl (neu leer) bleibt der Belag. alt (Belag der Quelle) wird nicht mehr +;; ausgewertet, bleibt aber fuer die Aufrufer in der Signatur. (defun lg-kopie-belag (belag alt neu) - (if (and belag alt neu (= (strcase belag) (strcase alt))) neu belag) + (if (and belag neu (= (type neu) 'STR) (/= neu "")) neu belag) ) ;; Reiner Kern: Attributwerte einer kopierten Reihe/eines Gangs fuer @@ -1698,14 +1790,146 @@ (progn (lg-ldata-setzen "GESCHOSS_AKTIV" (car erg)) (princ (ssg-text "lg-kopie-hinweis-aktiv")))) + (foreach nr erg (lg-darstellung-geschoss nr)) (reverse erg)) ) ) +;; ============================================================ +;; DARSTELLUNG (Absturzsicherung unter den Reihen, Farben) +;; ============================================================ +;; Unter den Reihen einer Buehne wird die Sicherung je UNTER_REIHE gezeigt: +;; gitterrost / gitterkorb als Schraffur (Muster/Farbe aus lager.json +;; darstellung.unter_reihe), der Gitterkorb zusaetzlich mit seiner +;; seitlichen Abgrenzung als dicke Linie - aber nur an den OFFENEN Kanten: +;; wo eine andere Reihe anliegt (Ruecken an Ruecken), gibt es keine +;; Abgrenzung (lg-sicherung-geometrie, gleiche Regel wie der Export). +;; Die Objekte sind lose (Layer LG_Sicherung_G, XDATA rolle=sicherung) +;; und werden bei jedem Neuaufbau des Geschosses komplett ersetzt. + +;; wirksames UNTER_REIHE einer Reihe (Bereich ueber XDATA, sonst Vorgabe). +(defun lg-reihe-unter-ent (ent buehne-p / b) + (setq b (lg-ent-aus-handle (lg-xdata-wert ent "bereich"))) + (lg-unter-reihe-wert (if b (cdr (assoc "UNTER_REIHE" (ssg-attrib-read b)))) + (lg-unter-reihe-vorgabe) buehne-p) +) + +;; Alle Sicherungs-Objekte auf layer loeschen. Rueckgabe: Anzahl. +(defun lg-sicherung-loeschen (layer / ss i) + (setq i 0) + (if (setq ss (ssget "_X" (list (cons 8 layer) (list -3 (list *lg-app*))))) + (repeat (sslength ss) + (if (= (lg-xdata-wert (ssname ss i) "rolle") "sicherung") (entdel (ssname ss i))) + (setq i (1+ i)))) + i +) + +(defun lg-sicherung-markieren (ent) + (lg-xdata-setzen ent (list (cons "rolle" (cons 1000 "sicherung")))) + ent +) + +;; LWPOLYLINE in WCS (2D-Punkte + Erhebung z) per entmake. Rueckgabe: ename. +(defun lg-lwpoly-make (pts z layer geschlossen breite farbe / ) + (entmakex + (append + (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") (cons 8 layer)) + (lg-farbe-dxf farbe) + (list '(100 . "AcDbPolyline") (cons 90 (length pts)) (cons 70 (if geschlossen 1 0)) (cons 38 z)) + (if breite (list (cons 43 breite))) + (mapcar '(lambda (p) (list 10 (car p) (cadr p))) pts))) +) + +;; Sicherung unter den Reihen eines Geschosses neu zeichnen. Auf +;; Hallenboden wird nur geloescht. Rueckgabe: Anzahl neuer Objekte. +(defun lg-darstellung-geschoss (nr / g lay buehne ents reihen zs tab vorgabe rand-farbe breite n pl h ent) + (setq n 0) + (if (setq g (lg-geschoss-finden nr)) + (progn + (setq lay (lg-layer "sicherung" nr)) + (lg-sicherung-loeschen lay) + (setq buehne (lg-buehne-p (cdr (assoc "BELAG_ART" (caddr g))))) + (if buehne + (progn + (setq ents (vl-remove-if-not '(lambda (e) (= (cdr (assoc "GESCHOSS" (ssg-attrib-read e))) (itoa nr))) + (lg-alle-bloecke "LG_REIHE_*")) + reihen (mapcar '(lambda (e) (list (lg-linie-polygon e) (lg-reihe-unter-ent e T))) ents) + zs (mapcar '(lambda (e) (cond ((caddr (cdr (assoc 10 (entget e))))) (0.0))) ents) + tab (lg-vorgabe '("darstellung" "unter_reihe") nil) + rand-farbe (lg-vorgabe '("darstellung" "unter_reihe" "gitterkorb" "rand" "farbe") nil) + breite (lg-zahl (lg-vorgabe '("darstellung" "unter_reihe" "gitterkorb" "rand" "breite_mm") 50))) + (foreach x (lg-sicherung-geometrie reihen 1.0) + (if (= (car x) "flaeche") + (if (setq vorgabe (lg-schraffur-vorgabe (cadr x) tab)) + (progn + (setq pl (lg-lwpoly-make (caddr x) (nth (cadddr x) zs) lay T nil nil) + h (lg-schraffur-anlegen (lg-modelspace) (vlax-ename->vla-object pl) vorgabe + (lg-schraffur-farbe (cadr x) tab) 256 lay + (nth (cadddr x) zs) lay)) + (entdel pl) + (if h (progn (lg-sicherung-markieren (vlax-vla-object->ename h)) (setq n (1+ n)))))) + (if (setq ent (lg-lwpoly-make (list (cadr x) (caddr x)) (nth (cadddr x) zs) lay nil breite rand-farbe)) + (progn (lg-sicherung-markieren ent) (setq n (1+ n))))))))) + ) + n +) + +;; Belag einer Gang-Blockdefinition aus ihrem Namen LG_GANG___. +;; Rein, getestet. +(defun lg-gang-belag-aus-name (bname / teile) + (setq teile (ssg-sepliste-split-feld bname "_")) + (if (> (length teile) 4) (strcase (ssg-join (cddddr teile) "_") T)) +) + +;; Vorhandene Blockdefinitionen an die Farben/Schraffuren aus lager.json +;; anpassen: LG_REIHE_* bekommen die Reihenfarbe, LG_GANG_* ihre Schraffur +;; neu (Muster und Farbe je Belag). +(defun lg-darstellung-definitionen ( / rf tab nm hs belag vorgabe) + (setq rf (lg-vorgabe '("darstellung" "reihe" "farbe") nil) + tab (lg-vorgabe '("belag_schraffur") nil)) + (vlax-for b (lg-bloecke) + (setq nm (strcase (vla-get-Name b))) + (cond + ((wcmatch nm "LG_REIHE_*") + (vlax-for o b + (if (member (vla-get-ObjectName o) '("AcDbPolyline" "AcDbLine")) + (lg-farbe-setzen o rf 256)))) + ((wcmatch nm "LG_GANG_*") + (setq hs nil) + (vlax-for o b (if (= (vla-get-ObjectName o) "AcDbHatch") (setq hs (cons o hs)))) + (foreach h hs (vla-Delete h)) + (setq belag (lg-gang-belag-aus-name nm)) + (if (setq vorgabe (lg-schraffur-vorgabe belag tab)) + (lg-schraffur-einsetzen (vla-get-Name b) vorgabe (lg-schraffur-farbe belag tab)))) + ) + ) +) + +;; Alles neu: Definitionen und die Sicherung aller Geschosse. +(defun lg-darstellung-alle ( / n) + (lg-darstellung-definitionen) + (setq n 0) + (foreach g (lg-geschosse) (setq n (+ n (lg-darstellung-geschoss (cadr g))))) + n +) + ;; ============================================================ ;; BEFEHLE ;; ============================================================ +;; Darstellung aktualisieren: Farben/Schraffuren aus lager.json auf alle +;; Reihen-/Gang-Definitionen, Sicherung unter den Reihen aller Geschosse +;; neu (z.B. nach Loeschen von Hand oder Aenderung von lager.json). +(defun c:LG_DARSTELLUNG ( / n) + (ssg-start (ssg-text "lg-titel-darstellung") nil) + (setq *lg-daten* nil) ; lager.json neu lesen + (setq n (lg-darstellung-alle)) + (command "_.REGEN") + (princ (ssg-textf "lg-darstellung-fertig" (list (itoa n)))) + (ssg-end) + (princ) +) + (defun c:LG_GESCHOSS ( / kontur nr werte blk) (ssg-start (ssg-text "lg-titel-geschoss") nil) (setq kontur (lg-kontur-waehlen (ssg-text "lg-prompt-kontur-geschoss"))) @@ -1916,8 +2140,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 @@ -1926,6 +2149,7 @@ (setq n (lg-linien-schleife (ssg-text "lg-prompt-reihe-start") '(lambda (p1 p2) (lg-manuell-einfuegen "reihe" p1 p2 werte)) nil)) + (if (> n 0) (lg-darstellung-geschoss gs)) (princ (ssg-textf "lg-reihen-eingefuegt" (list (itoa n)))))))) (ssg-end) (princ) @@ -1987,11 +2211,74 @@ (setq n (lg-linien-schleife (ssg-text "lg-prompt-gang-start") '(lambda (p1 p2) (lg-gang-einfuegen p1 p2 werte)) '(lambda (ecken) (lg-gang-rechteck-einfuegen ecken werte)))) + ;; ein Gang kann Reihen zerschneiden -> neue offene Kanten + (if (> n 0) (lg-darstellung-geschoss gs)) (princ (ssg-textf "lg-gaenge-eingefuegt" (list (itoa n)))))))) (ssg-end) (princ) ) +;; ------------------------------------------------------------ +;; Bereich bearbeiten: was eingezeichnet ist, wird aktualisiert, nicht +;; ueberschrieben. Nur eine Geometrieaenderung fuehrt (auf Rueckfrage) zur +;; Neuberechnung der automatisch erzeugten Kinder. +;; ------------------------------------------------------------ + +;; Bereichs-Attribute, deren Aenderung die Lage der Reihen/Gaenge aendert. +(setq *lg-bereich-geometrie-tags* + '("GANGBREITE_mm" "REGALTIEFE_mm" "REIHEN_JE_GANG" "QUERGANG_ABSTAND_mm" "QUERGANG_BREITE_mm" + "RICHTUNG" "RANDGANG_N_mm" "RANDGANG_O_mm" "RANDGANG_S_mm" "RANDGANG_W_mm")) + +;; Reiner Kern: T, wenn sich zwischen alt und neu (Attribut-Alists) ein +;; Geometrie-Wert aendert (numerisch verglichen, leer = 0; fehlt ein Tag in +;; neu, gilt er als unveraendert). +(defun lg-bereich-geometrie-geaendert-p (alt neu) + (if (vl-some '(lambda (tag / x y) + (if (lg-wert-fuer-tag tag neu) + (progn + (setq x (cond ((lg-zahl (lg-wert-fuer-tag tag alt))) (0.0)) + y (cond ((lg-zahl (lg-wert-fuer-tag tag neu))) (0.0))) + (not (equal x y 1e-6))))) + *lg-bereich-geometrie-tags*) + T) +) + +;; Geaenderte Nicht-Geometrie-Werte auf ALLE vorhandenen Kinder des Bereichs +;; uebertragen (QUELLE egal, nichts wird geloescht oder neu gelegt): +;; BELAG -> jeder Gang wird mit dem neuen Belag an derselben Stelle neu +;; aufgebaut (Belag steckt im Blocknamen/der Schraffur), HAENGEEBENEN -> +;; Attribut jeder Reihe. Rueckgabe: Anzahl geaenderter Objekte. +(defun lg-bereich-attribute-uebertragen (ent alt neu / b-alt b-neu e-alt e-neu n ka) + (setq b-alt (lg-wert-fuer-tag "BELAG" alt) b-neu (lg-wert-fuer-tag "BELAG" neu) + e-alt (lg-wert-fuer-tag "HAENGEEBENEN" alt) e-neu (lg-wert-fuer-tag "HAENGEEBENEN" neu) + n 0) + (foreach k (lg-bereich-kinder ent) + (setq ka (ssg-attrib-read k)) + (cond + ((wcmatch (strcase (lg-blockname k)) "LG_GANG_*") + (if (and b-neu (/= b-neu "") (not (equal b-alt b-neu)) + (not (equal (lg-wert-fuer-tag "BELAG" ka) b-neu))) + (if (lg-linie-neu-aufbauen k (lg-wert-setzen ka "BELAG" b-neu)) (setq n (1+ n))))) + ((wcmatch (strcase (lg-blockname k)) "LG_REIHE_*") + (if (and e-neu (not (equal e-alt e-neu))) + (progn (lg-attribute-setzen k (list (cons "HAENGEEBENEN" e-neu))) (setq n (1+ n))))) + ) + ) + n +) + +;; Nach dem Bereichsdialog: Werte uebertragen, bei Geometrieaenderung +;; Rueckfrage "neu berechnen?" (Vorgabe Ja; ohne Aenderung Vorgabe Nein - +;; damit laesst sich ein Bereich auch bewusst neu berechnen). +(defun lg-bereich-aktualisieren (ent alt neu / geo n) + (setq n (lg-bereich-attribute-uebertragen ent alt neu) + geo (lg-bereich-geometrie-geaendert-p alt neu)) + (if (> n 0) (princ (ssg-textf "lg-bereich-uebertragen" (list (itoa n))))) + (if (ssg-in-yesno (ssg-text "lg-frage-neu-berechnen") geo) + (lg-bereich-fuellen ent) + (lg-darstellung-geschoss (atoi (cond ((cdr (assoc "GESCHOSS" (ssg-attrib-read ent)))) ("0"))))) +) + ;; Doppelklick-Ziel (SSG_BLOCKEDIT, Zweig LG_*) und Befehl LG_EDIT. (defun lg-edit-ent (ent / name a neu) (setq name (strcase (lg-blockname ent)) @@ -2000,7 +2287,10 @@ ((= name "LG_GESCHOSS") ;; Nummer bleibt fest - an ihr haengen Layer und GESCHOSS der Kinder (if (setq neu (lg-dialog "lg_geschoss" *lg-felder-geschoss* a '("nr"))) - (progn (lg-attribute-setzen ent neu) (princ (ssg-text "lg-geaendert"))))) + (progn (lg-attribute-setzen ent neu) + ;; Belag kann zwischen Buehne und Hallenboden wechseln + (lg-darstellung-geschoss (atoi (cond ((cdr (assoc "NR" a))) ("0")))) + (princ (ssg-text "lg-geaendert"))))) ((= name "LG_BEREICH") (if (setq neu (lg-dialog "lg_bereich" *lg-felder-bereich* a nil)) (progn @@ -2008,7 +2298,7 @@ ;; Pfeil des Symbols folgt der Reihenrichtung (vla-put-Rotation (vlax-ename->vla-object ent) (* (/ (cond ((lg-zahl (cdr (assoc "RICHTUNG" neu)))) (0.0)) 180.0) pi)) - (lg-bereich-fuellen ent)))) + (lg-bereich-aktualisieren ent a neu)))) ((wcmatch name "LG_REIHE_*") (if (setq neu (lg-dialog "lg_reihe" *lg-felder-reihe* a nil)) (progn @@ -2100,11 +2390,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 +2439,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 +2449,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 +2466,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 +2533,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)) ) @@ -2235,13 +2583,13 @@ (<= (cadr (car b)) (+ (cadr (cadr a)) tol)) (<= (cadr (car a)) (+ (cadr (cadr b)) tol))) ) -;; Offener Teil der Kante (p q): Laenge minus die Abschnitte, auf denen eine -;; Kante eines Nachbar-Rechtecks kollinear (Abstand < tol) aufliegt. -(defun lg-kante-offen (kante nachbarn tol / p q len ux uy zu c d dx dy dl t1 t2 lo hi) +;; Offene Abschnitte der Kante (p q) als ((t0 t1) ...) in mm ab p: die +;; Kante ohne die Abschnitte, auf denen eine Kante eines Nachbar-Rechtecks +;; kollinear (Abstand < tol) aufliegt. Stuecke bis tol fallen weg. +(defun lg-kante-offen-intervalle (kante nachbarn tol / p q len ux uy zu c d dx dy dl t1 t2 lo hi) (setq p (car kante) q (cadr kante) zu nil len (distance (list (car p) (cadr p)) (list (car q) (cadr q)))) - (if (< len 1e-9) - 0.0 + (if (>= len 1e-9) (progn (setq ux (/ (- (car q) (car p)) len) uy (/ (- (cadr q) (cadr p)) len)) (foreach f nachbarn @@ -2258,22 +2606,35 @@ lo (max 0.0 (min t1 t2)) hi (min len (max t1 t2))) (if (> (- hi lo) tol) (setq zu (cons (list lo hi) zu))))))) - (apply '+ (cons 0.0 (mapcar '(lambda (i) (- (cadr i) (car i))) - (ssg-intervalle-minus (list (list 0.0 len)) zu)))))) + (vl-remove-if '(lambda (i) (<= (- (cadr i) (car i)) tol)) + (ssg-intervalle-minus (list (list 0.0 len)) zu)))) +) + +;; Offene Laenge der Kante (Summe von lg-kante-offen-intervalle). +(defun lg-kante-offen (kante nachbarn tol) + (apply '+ (cons 0.0 (mapcar '(lambda (i) (- (cadr i) (car i))) + (lg-kante-offen-intervalle kante nachbarn tol)))) +) + +;; Ecken der Rechtecke aus ecken-liste, deren Huelle die von Nr. i beruehrt +;; (ohne i selbst). bbs = Huellen in derselben Reihenfolge. +(defun lg-nachbarn (i ecken-liste bbs tol / j erg) + (setq j 0 erg nil) + (foreach f ecken-liste + (if (and (/= i j) (lg-bbox-beruehrt-p (nth i bbs) (nth j bbs) tol)) + (setq erg (cons f erg))) + (setq j (1+ j))) + erg ) ;; Offene Kantenlaenge je Reihe. ecken-liste = je Reihe die 4 Ecken (2D) ;; aus lg-linie-polygon. Eine Kante ist dort zu, wo eine Kante einer ANDEREN ;; Reihe kollinear darauf liegt (z.B. Ruecken an Ruecken). Rueckgabe je ;; Reihe (offen-laengs offen-stirn) in mm. -(defun lg-reihen-offene-kanten (ecken-liste tol / bbs erg i j k bb nachbarn l s o) +(defun lg-reihen-offene-kanten (ecken-liste tol / bbs erg i k nachbarn l s o) (setq bbs (mapcar 'ssg-poly-bbox ecken-liste) erg nil i 0) (foreach e ecken-liste - (setq bb (nth i bbs) nachbarn nil j 0 l 0.0 s 0.0 k 0) - (foreach f ecken-liste - (if (and (/= i j) (lg-bbox-beruehrt-p bb (nth j bbs) tol)) - (setq nachbarn (cons f nachbarn))) - (setq j (1+ j))) + (setq nachbarn (lg-nachbarn i ecken-liste bbs tol) l 0.0 s 0.0 k 0) (foreach kante (lg-rechteck-kanten e) (setq o (lg-kante-offen kante nachbarn tol)) (if (= 0 (rem k 2)) (setq l (+ l o)) (setq s (+ s o))) @@ -2282,6 +2643,39 @@ (reverse erg) ) +;; Geometrie der Absturzsicherung unter den Reihen EINES Geschosses (rein, +;; getestet). reihen = ((ecken unter) ...), ecken 2D aus lg-linie-polygon, +;; unter = gitterrost/gitterkorb/keine. Rueckgabe: +;; ("flaeche" unter ecken i) je Reihe mit gitterrost oder gitterkorb +;; ("rand" p1 p2 i) je OFFENEM Kantenabschnitt einer Gitterkorb- +;; Reihe - wo eine andere Reihe (gleich welche +;; Sicherung) anliegt, gibt es keine Abgrenzung +;; i = Index der Reihe (fuer Z und Zuordnung). +(defun lg-sicherung-geometrie (reihen tol / alle bbs erg i e u nachbarn p q len ux uy) + (setq alle (mapcar 'car reihen) bbs (mapcar 'ssg-poly-bbox alle) erg nil i 0) + (foreach r reihen + (setq e (car r) u (cadr r)) + (if (member u '("gitterrost" "gitterkorb")) + (setq erg (cons (list "flaeche" u e i) erg))) + (if (= u "gitterkorb") + (progn + (setq nachbarn (lg-nachbarn i alle bbs tol)) + (foreach k (lg-rechteck-kanten e) + (setq p (car k) q (cadr k) + len (distance (list (car p) (cadr p)) (list (car q) (cadr q)))) + (if (> len 1e-9) + (progn + (setq ux (/ (- (car q) (car p)) len) uy (/ (- (cadr q) (cadr p)) len)) + (foreach iv (lg-kante-offen-intervalle k nachbarn tol) + (setq erg (cons (list "rand" + (list (+ (car p) (* ux (car iv))) (+ (cadr p) (* uy (car iv)))) + (list (+ (car p) (* ux (cadr iv))) (+ (cadr p) (* uy (cadr iv)))) + i) + erg)))))))) + (setq i (1+ i))) + (reverse erg) +) + ;; Gitterkorb der Reihen EINES Geschosses vervollstaendigen: Reihen mit ;; gitterkorb (OBJ hoehe_mm) bekommen Boden (Laenge x Tiefe), offene Kanten ;; (gegen alle Reihen des Geschosses) und Seitenflaeche (offen x Hoehe). @@ -2311,12 +2705,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 +2728,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 +2738,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 +2797,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 +2833,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 +2988,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 +3006,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 +3025,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 +3040,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 +3073,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 +3105,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 +3123,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/Lisp/OmniModulInsert.lsp b/Lisp/OmniModulInsert.lsp index 5a2e8b2..c5990bd 100644 --- a/Lisp/OmniModulInsert.lsp +++ b/Lisp/OmniModulInsert.lsp @@ -123,6 +123,66 @@ ) +;; --- Aehnlichkeit zweier ProfilTyp-Texte --- +;; Anzahl gleicher Zeichen an gleicher Position minus Laengendifferenz. +;; Gegenstuecke unterscheiden sich im Katalog nur in einzelnen Zeichen +;; ("45-L-" / "45-R-", "MIT M" / "MIT P", "L1S" / "R1S"), darum bewertet das +;; ohne schemaabhaengiges Zerlegen die passende Weiche am hoechsten. +;; Kein String auf einer Seite -> 0. +(defun omni:profil-aehnlichkeit (a b / la lb n) + (if (and (= (type a) 'STR) (= (type b) 'STR)) + (progn + (setq la (vl-string->list a) + lb (vl-string->list b) + n 0) + (while (and la lb) + (if (= (car la) (car lb)) (setq n (1+ n))) + (setq la (cdr la) lb (cdr lb)) + ) + (- n (abs (- (strlen a) (strlen b)))) + ) + 0 + ) +) + + +;; --- Vorwahl-Index fuer ein Dialog-Dropdown --- +;; ziel = Katalog-Eintrag, der vorgewaehlt werden soll (z.B. das per +;; Doppelklick bearbeitete Bauteil oder die bisherige Auswahl) +;; liste = aktuell angezeigte Eintraege +;; Rueckgabe: Index des Eintrags mit gleicher Sivasnr, sonst des Eintrags mit +;; dem aehnlichsten ProfilTyp (Gleichstand: erster); nil ohne Ziel/Liste. +(defun omni:vorwahl-index (ziel liste / nr profil i idx best wert) + (if (and ziel liste) + (progn + (setq nr (omni:sivasid-to-str (cdr (assoc "Sivasnr" ziel))) + i 0) + (if (/= nr "") + (foreach e liste + (if (and (null idx) + (= (omni:sivasid-to-str (cdr (assoc "Sivasnr" e))) nr)) + (setq idx i)) + (setq i (1+ i)) + ) + ) + (if (null idx) + (progn + (setq profil (cdr (assoc "ProfilTyp" ziel)) + i 0) + (foreach e liste + (setq wert (omni:profil-aehnlichkeit profil (cdr (assoc "ProfilTyp" e)))) + (if (or (null best) (> wert best)) + (setq best wert idx i)) + (setq i (1+ i)) + ) + ) + ) + idx + ) + ) +) + + ;; --- Einzelnen Wert aus einem Eintrag lesen --- ;; eintrag = Assoziationsliste (Rueckgabe von omni:get-bogen etc.) ;; key = Schluesselname z.B. "Radius" @@ -331,8 +391,9 @@ ;; profiltyp = optionales Praefix zum Filtern des ProfilTyp-Textes, ;; z.B. "APB 60" oder "APB 110" (nil = keine Einschraenkung) ;; Rueckgabe: (eintrag hoehe drehung) oder nil bei Abbruch +;; Vorwahl: *omni-dlg-vorwahl* (von OMNI_EDIT gesetzt) wird vorgewaehlt. (defun omni:bogen-dialog (winkel init-hoehe init-drehung profiltyp / dcl-pfad dat boegen-liste - profil-liste ergebnis dlg-hoehe profil) + profil-liste ergebnis dlg-hoehe profil idx) (if (null *OMNI-BOEGEN*) (omni:load-data)) ;; Defaults @@ -387,13 +448,16 @@ (start_list "bogenart") (mapcar 'add_list profil-liste) (end_list) - (set_tile "bogenart" "0") + ;; Beim Edit (OMNI_EDIT) das bearbeitete Bauteil vorwaehlen + (setq idx (omni:vorwahl-index *omni-dlg-vorwahl* boegen-liste)) + (if (null idx) (setq idx 0)) + (set_tile "bogenart" (itoa idx)) ;; Hoehe initialisieren (Drehung erfolgt interaktiv nach dem Einfuegen) (set_tile "val_hoehe" init-hoehe) ;; Startwerte anzeigen - (omni:bogen-dlg-update "0") + (omni:bogen-dlg-update (itoa idx)) ;; Callback bei Dropdown-Aenderung (action_tile "bogenart" "(omni:bogen-dlg-update $value)") @@ -488,14 +552,58 @@ ;; ============================================================ +;; --- Standard-Weichentypen eines Winkel-Dialogs --- +;; Einzel-, Doppel- und Dreiwegeweiche eines Winkels stehen in EINEM Dialog, +;; unterschieden ueber die Radiogruppe "Richtung" (KurvenRichtung 1/2/3/7). +;; Delta-/Stern-/Weichenbatterie bleiben eigene Dialoge - Deltaweichen tragen +;; ebenfalls KurvenRichtung 3/7 und duerfen darum nicht in diese Liste. +(setq *omni-weichen-std-typen* '("Einzelweiche" "Doppelweiche" "Dreiwegeweiche")) + + +;; --- KurvenRichtung -> Radiobutton der Richtungsgruppe --- +;; Katalog: 1 = links, 2 = rechts, 3 = Doppel, 7 = Dreiwege. +(setq *omni-weichen-richtungen* + '(("1" . "ri_links") ("2" . "ri_rechts") ("3" . "ri_doppel") ("7" . "ri_dreiwege"))) + +;; kr = KurvenRichtung als String; Rueckgabe Tile-Key oder nil (unbekannt) +(defun omni:weichen-richtung-key (kr) + (cdr (assoc kr *omni-weichen-richtungen*)) +) + + +;; --- Basisliste eines Weichen-Dialogs (reiner Kern) --- +;; lst = Weichenkatalog +;; winkel = KurvenWinkel oder nil (alle Winkel) +;; weichentyp = WeichenTyp-String, Liste von WeichenTypen oder nil (alle) +;; breite = Breite oder nil (z.B. Delta 1400/700 vs. 1600/800) +(defun omni:weichen-basis-liste (lst winkel weichentyp breite / typen) + (if winkel (setq lst (omni:filter lst "KurvenWinkel" winkel))) + (if weichentyp + (progn + (setq typen (if (listp weichentyp) weichentyp (list weichentyp))) + (setq lst (vl-remove-if-not + '(lambda (e) (member (cdr (assoc "WeichenTyp" e)) typen)) + lst)) + ) + ) + (if breite + (setq lst (vl-remove-if-not + '(lambda (e) (= (cdr (assoc "Breite" e)) breite)) + lst)) + ) + lst +) + + ;; --- Aktuelle Filterwerte aus Radio-Buttons lesen --- -(defun omni:weichen-get-filter ( / sch ri) +(defun omni:weichen-get-filter ( / sch ri paar) (setq sch "alle") (if (= (get_tile "sch_m") "1") (setq sch "M")) (if (= (get_tile "sch_p") "1") (setq sch "P")) (setq ri "alle") - (if (= (get_tile "ri_links") "1") (setq ri "1")) - (if (= (get_tile "ri_rechts") "1") (setq ri "2")) + (foreach paar *omni-weichen-richtungen* + (if (= (get_tile (cdr paar)) "1") (setq ri (car paar))) + ) (list sch ri) ) @@ -503,7 +611,7 @@ ;; --- Gefilterte Weichen-Liste aufbauen --- ;; basis-liste = alle Weichen fuer den gewaehlten Winkel/Typ ;; sch-filter = "M", "P" oder "alle" -;; ri-filter = "1", "2" oder "alle" +;; ri-filter = KurvenRichtung "1", "2", "3", "7" oder "alle" (defun omni:weichen-filter-liste (basis-liste sch-filter ri-filter / eintrag sch kr ergebnis) (setq ergebnis nil) (foreach eintrag basis-liste @@ -522,7 +630,11 @@ ;; --- Dropdown mit gefilterter Liste neu befuellen --- -(defun omni:weichen-dlg-refresh ( / filter sch-f ri-f gefiltert profil-liste) +;; Die bisher angezeigte Weiche (*omni-dlg-weiche-akt*) bleibt gewaehlt, wenn sie +;; den Filter passiert; sonst wird ihr Gegenstueck (aehnlichster ProfilTyp) +;; gewaehlt - ein Klick auf "Rechts" macht aus 45-L-400/750 MIT M also +;; 45-R-400/750 MIT M statt des ersten Listeneintrags. +(defun omni:weichen-dlg-refresh ( / filter sch-f ri-f gefiltert profil-liste idx) (setq filter (omni:weichen-get-filter)) (setq sch-f (car filter)) (setq ri-f (cadr filter)) @@ -536,11 +648,13 @@ (mapcar 'add_list profil-liste) (end_list) - ;; Ersten Eintrag anzeigen (falls vorhanden) + ;; Bisherige Weiche bzw. ihr Gegenstueck anzeigen (falls vorhanden) (if gefiltert (progn - (set_tile "profiltyp" "0") - (omni:weichen-dlg-update "0") + (setq idx (omni:vorwahl-index *omni-dlg-weiche-akt* gefiltert)) + (if (null idx) (setq idx 0)) + (set_tile "profiltyp" (itoa idx)) + (omni:weichen-dlg-update (itoa idx)) ) (progn (set_tile "val_sivasnr" "---") @@ -553,23 +667,29 @@ ;; --- Detail-Felder im Weichen-Dialog aktualisieren --- -(defun omni:weichen-dlg-update (idx-str / idx eintrag wkl) +;; Fehlende Werte (null im Katalog, z.B. Weichenbatterien ohne KurvenWinkel/ +;; Breite/Laenge) werden als "---" angezeigt. +(defun omni:weichen-dlg-update (idx-str / idx eintrag wkl br lg) (setq idx (atoi idx-str)) (setq eintrag (nth idx *OMNI-DLG-WEICHEN*)) (if eintrag (progn + ;; Merken fuer den naechsten Filterwechsel (omni:weichen-dlg-refresh) + (setq *omni-dlg-weiche-akt* eintrag) (set_tile "val_sivasnr" (omni:sivasid-to-str (omni:val eintrag "Sivasnr"))) (setq wkl (omni:val eintrag "KurvenWinkel")) (set_tile "val_winkel" - (if (= (type wkl) 'INT) (strcat (itoa wkl) " Grad") - (strcat (rtos wkl 2 1) " Grad") + (cond + ((= (type wkl) 'INT) (strcat (itoa wkl) " Grad")) + ((numberp wkl) (strcat (rtos wkl 2 1) " Grad")) + (T "---") ) ) - (set_tile "val_breite" - (itoa (fix (omni:val eintrag "Breite")))) - (set_tile "val_laenge" - (itoa (fix (omni:val eintrag "Länge")))) + (setq br (omni:val eintrag "Breite")) + (setq lg (omni:val eintrag "Länge")) + (set_tile "val_breite" (if (numberp br) (itoa (fix br)) "---")) + (set_tile "val_laenge" (if (numberp lg) (itoa (fix lg)) "---")) ) ) ) @@ -577,11 +697,15 @@ ;; --- Weichen-Auswahl-Dialog oeffnen --- ;; winkel = KurvenWinkel (90, 45, 0, 22.5) -;; weichentyp = "Einzelweiche", "Doppelweiche", "Dreiwegeweiche" oder nil fuer alle +;; weichentyp = WeichenTyp-String, Liste von WeichenTypen (z.B. +;; *omni-weichen-std-typen*) oder nil fuer alle ;; init-hoehe / init-drehung = Vorbelegung (optional, fuer Edit-Modus) ;; Rueckgabe: (eintrag hoehe drehung) oder nil bei Abbruch +;; Vorwahl: *omni-dlg-vorwahl* (von OMNI_EDIT gesetzt) wird vorgewaehlt, die +;; Filter Schaltung/Richtung stehen dann auf dessen Werten. +;; Richtungs-Buttons ohne passenden Katalogeintrag werden ausgegraut. (defun omni:weichen-dialog (winkel weichentyp init-hoehe init-drehung breite / dcl-pfad dat basis-liste - profil-liste ergebnis dlg-hoehe) + ergebnis dlg-hoehe sch kr key paar vorhanden) (if (null *OMNI-WEICHEN*) (omni:load-data)) ;; Defaults @@ -589,27 +713,8 @@ ;; dem Einfuegen interaktiv abgefragt (omni:insert-dxf mit drehung=nil). (if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))) - ;; Weichen nach Winkel filtern (nil = alle Winkel) - (if winkel - (setq basis-liste (omni:filter *OMNI-WEICHEN* "KurvenWinkel" winkel)) - (setq basis-liste *OMNI-WEICHEN*) - ) - - ;; Optional nach WeichenTyp filtern - (if weichentyp - (setq basis-liste - (vl-remove-if-not - '(lambda (e) (= (cdr (assoc "WeichenTyp" e)) weichentyp)) - basis-liste)) - ) - - ;; Optional nach Breite filtern (z.B. Weichenkombinationen Delta 1400/700 vs. 1600/800) - (if breite - (setq basis-liste - (vl-remove-if-not - '(lambda (e) (= (cdr (assoc "Breite" e)) breite)) - basis-liste)) - ) + ;; Weichen nach Winkel, WeichenTyp(en) und Breite eingrenzen + (setq basis-liste (omni:weichen-basis-liste *OMNI-WEICHEN* winkel weichentyp breite)) (if (null basis-liste) (progn @@ -620,7 +725,11 @@ ((= (type winkel) 'INT) (strcat (itoa winkel) (ssg-text "omni-grad"))) (T (strcat (rtos winkel 2 1) (ssg-text "omni-grad"))) ) - (if weichentyp (strcat " / " weichentyp) "") + (cond + ((null weichentyp) "") + ((listp weichentyp) (strcat " / " (ssg-join weichentyp ", "))) + (T (strcat " / " weichentyp)) + ) ) )) nil @@ -630,28 +739,43 @@ (setq *OMNI-DLG-WEICHEN-BASIS* basis-liste) (setq *OMNI-DLG-WEICHEN* basis-liste) - ;; ProfilTyp-Liste fuer Dropdown aufbauen - (setq profil-liste - (mapcar '(lambda (e) (cdr (assoc "ProfilTyp" e))) basis-liste)) - ;; DCL laden (setq dcl-pfad (strcat (getenv "DXFM_DCL") "/omniflo_weichen.dcl")) (setq dat (load_dialog dcl-pfad)) (if (not (new_dialog "omniflo_weichen" dat)) (progn (alert (ssg-text "omni-weiche-dialog-ladefehler")) nil) (progn - ;; Dropdown befuellen - (start_list "profiltyp") - (mapcar 'add_list profil-liste) - (end_list) - (set_tile "profiltyp" "0") + ;; Richtungen ohne Katalogeintrag ausgrauen (z.B. Weichenbatterie: + ;; kein Doppel/Dreiwege, Stern: kein Links/Rechts); "Alle" bleibt. + (setq vorhanden + (mapcar '(lambda (e) (omni:sivasid-to-str (cdr (assoc "KurvenRichtung" e)))) + basis-liste)) + (foreach paar *omni-weichen-richtungen* + (if (not (member (car paar) vorhanden)) + (mode_tile (cdr paar) 1)) + ) + + ;; Beim Edit (OMNI_EDIT, *omni-dlg-vorwahl*) die Filter auf Schaltung/ + ;; Richtung des Bauteils stellen; ohne Vorwahl bleibt "Alle". + (setq *omni-dlg-weiche-akt* *omni-dlg-vorwahl*) + (if *omni-dlg-vorwahl* + (progn + (setq sch (cdr (assoc "Schaltungstyp" *omni-dlg-vorwahl*))) + (setq kr (omni:sivasid-to-str (cdr (assoc "KurvenRichtung" *omni-dlg-vorwahl*)))) + (cond ((= sch "M") (set_tile "sch_m" "1")) + ((= sch "P") (set_tile "sch_p" "1"))) + (if (setq key (omni:weichen-richtung-key kr)) + (set_tile key "1")) + ) + ) + + ;; Dropdown befuellen und Weiche waehlen (vorgewaehltes Bauteil bzw. + ;; ohne Vorwahl der erste Eintrag) + (omni:weichen-dlg-refresh) ;; Hoehe initialisieren (Drehung erfolgt interaktiv nach dem Einfuegen) (set_tile "val_hoehe" init-hoehe) - ;; Startwerte anzeigen - (omni:weichen-dlg-update "0") - ;; Callback bei Dropdown-Aenderung (action_tile "profiltyp" "(omni:weichen-dlg-update $value)") @@ -660,8 +784,8 @@ (action_tile "sch_m" "(omni:weichen-dlg-refresh)") (action_tile "sch_p" "(omni:weichen-dlg-refresh)") (action_tile "ri_alle" "(omni:weichen-dlg-refresh)") - (action_tile "ri_links" "(omni:weichen-dlg-refresh)") - (action_tile "ri_rechts" "(omni:weichen-dlg-refresh)") + (foreach paar *omni-weichen-richtungen* + (action_tile (cdr paar) "(omni:weichen-dlg-refresh)")) ;; OK/Abbrechen (action_tile "accept" @@ -879,9 +1003,11 @@ ;; OMNIFLO WEICHEN-BEFEHLE ;; ============================================================ -;; --- Omniflo / Weiche 90 Grad --- -(defun c:OMNI_W90_Einfach ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 90 "Einzelweiche" nil nil nil)) +;; Je Winkel EIN Dialog mit Einzel-, Doppel- und Dreiwegeweichen; der Typ wird +;; ueber die Radiogruppe "Richtung" gewaehlt (Links/Rechts/Doppel/Dreiwege). +;; Ersetzt die frueheren OMNI_W_Einfach/_Doppel/_Dreiwege. +(defun omni:weichen-befehl (winkel / dlg-result) + (setq dlg-result (omni:weichen-dialog winkel *omni-weichen-std-typen* nil nil nil)) (if dlg-result (omni:insert-from-entry dlg-result) (princ (ssg-text "omni-abbruch-weiche")) @@ -889,107 +1015,17 @@ (princ) ) -(defun c:OMNI_W90_Doppel ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 90 "Doppelweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) +;; --- Omniflo / Weichen 90 Grad --- +(defun c:OMNI_W90 () (omni:weichen-befehl 90)) -(defun c:OMNI_W90_Dreiwege ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 90 "Dreiwegeweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) +;; --- Omniflo / Weichen 45 Grad --- +(defun c:OMNI_W45 () (omni:weichen-befehl 45)) -;; --- Omniflo / Weiche 45 Grad --- -(defun c:OMNI_W45_Einfach ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 45 "Einzelweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) +;; --- Omniflo / Weichen Parallel (KurvenWinkel 0) --- +(defun c:OMNI_WP () (omni:weichen-befehl 0)) -(defun c:OMNI_W45_Doppel ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 45 "Doppelweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) - -(defun c:OMNI_W45_Dreiwege ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 45 "Dreiwegeweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) - -;; --- Omniflo / Weichen Parallel --- -(defun c:OMNI_WP_Einfach ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 0 "Einzelweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) - -(defun c:OMNI_WP_Doppel ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 0 "Doppelweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) - -(defun c:OMNI_WP_Dreiwege ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 0 "Dreiwegeweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) - -;; --- Omniflo / Weichenkoerper --- -(defun c:OMNI_WK_Einfach ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 22.5 "Einzelweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) - -(defun c:OMNI_WK_Doppel ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 22.5 "Doppelweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) - -(defun c:OMNI_WK_Dreiwege ( / dlg-result) - (setq dlg-result (omni:weichen-dialog 22.5 "Dreiwegeweiche" nil nil nil)) - (if dlg-result - (omni:insert-from-entry dlg-result) - (princ (ssg-text "omni-abbruch-weiche")) - ) - (princ) -) +;; --- Omniflo / Weichenkoerper (KurvenWinkel 22.5) --- +(defun c:OMNI_WK () (omni:weichen-befehl 22.5)) ;; --- Omniflo / Weichenkombinationen --- (defun c:OMNI_WKomb_Delta_1400 ( / dlg-result) @@ -1129,8 +1165,11 @@ ) ) - ;; 4. Dialog oeffnen mit vorhandenen Werten + ;; 4. Dialog oeffnen mit vorhandenen Werten; das bearbeitete Bauteil wird + ;; ueber *omni-dlg-vorwahl* im Dropdown vorgewaehlt (danach zuruecksetzen, + ;; damit die Menuebefehle wieder ohne Vorwahl starten). (setq dlg-result nil) + (setq *omni-dlg-vorwahl* eintrag) (cond ((= typ "bogen") (setq winkel (cdr (assoc "KurvenWinkel" eintrag))) @@ -1142,9 +1181,13 @@ (T (setq winkel (cdr (assoc "KurvenWinkel" eintrag))) (setq weichentyp (cdr (assoc "WeichenTyp" eintrag))) + ;; Einzel/Doppel/Dreiwege teilen sich einen Dialog - Wechsel ueber "Richtung" + (if (member weichentyp *omni-weichen-std-typen*) + (setq weichentyp *omni-weichen-std-typen*)) (setq dlg-result (omni:weichen-dialog winkel weichentyp hoehe drehung nil)) ) ) + (setq *omni-dlg-vorwahl* nil) (if (null dlg-result) (progn (princ (ssg-text "omni-abbruch")) (ssg-end) (exit)) @@ -1249,6 +1292,77 @@ (princ) ) +;; --- Omniflo / Weichenbatterien --- +;; Fertige Weichenbatterien, DWG = ARTINR (aktuell nur in data/omniflo/2D, +;; omni:omniflo-datei-finden faellt bei 3D darauf zurueck). Menuetexte (BESCHR) +;; und Nummern aus data/omniflo/weichenbatterien_artinr_quelle.dxf. Der +;; Doppelklick (OMNI_EDIT) findet sie im Weichen-Katalog omniflo_weichen.json +;; unter WeichenTyp "Weichenbatterie" (Richtung/Schaltung umstellbar). +(defun c:OMNI_WB_834372536 () + (omni:insert-dxf "834372536" nil nil) + (princ) +) +(defun c:OMNI_WB_834372537 () + (omni:insert-dxf "834372537" nil nil) + (princ) +) +(defun c:OMNI_WB_834372512 () + (omni:insert-dxf "834372512" nil nil) + (princ) +) +(defun c:OMNI_WB_834372513 () + (omni:insert-dxf "834372513" nil nil) + (princ) +) +(defun c:OMNI_WB_834372524 () + (omni:insert-dxf "834372524" nil nil) + (princ) +) +(defun c:OMNI_WB_834372525 () + (omni:insert-dxf "834372525" nil nil) + (princ) +) +(defun c:OMNI_WB_834372500 () + (omni:insert-dxf "834372500" nil nil) + (princ) +) +(defun c:OMNI_WB_834372501 () + (omni:insert-dxf "834372501" nil nil) + (princ) +) +(defun c:OMNI_WB_834372539 () + (omni:insert-dxf "834372539" nil nil) + (princ) +) +(defun c:OMNI_WB_834372540 () + (omni:insert-dxf "834372540" nil nil) + (princ) +) +(defun c:OMNI_WB_834372515 () + (omni:insert-dxf "834372515" nil nil) + (princ) +) +(defun c:OMNI_WB_834372516 () + (omni:insert-dxf "834372516" nil nil) + (princ) +) +(defun c:OMNI_WB_834372527 () + (omni:insert-dxf "834372527" nil nil) + (princ) +) +(defun c:OMNI_WB_834372528 () + (omni:insert-dxf "834372528" nil nil) + (princ) +) +(defun c:OMNI_WB_834372503 () + (omni:insert-dxf "834372503" nil nil) + (princ) +) +(defun c:OMNI_WB_834372504 () + (omni:insert-dxf "834372504" nil nil) + (princ) +) + @@ -1335,7 +1449,8 @@ ;; profiltyp = Praefix zum Filtern des ProfilTyp, z.B. "AP 110" (nil = alle) ;; init-hoehe = Vorbelegung Hoehe (nil = Default aus cfg) ;; Rueckgabe: (eintrag hoehe nil) wie omni:bogen-dialog, oder nil bei Abbruch -(defun omni:ladeschleifen-dialog (profiltyp init-hoehe / liste dat ergebnis dlg-hoehe profil) +;; Vorwahl: *omni-dlg-vorwahl* (von OMNI_EDIT gesetzt) wird vorgewaehlt. +(defun omni:ladeschleifen-dialog (profiltyp init-hoehe / liste dat ergebnis dlg-hoehe profil idx) (if (null *OMNI-LADESCHLEIFEN*) (omni:load-ladeschleifen)) (if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))) @@ -1367,9 +1482,12 @@ (start_list "ladeschleife") (mapcar '(lambda (e) (add_list (omni:sivasid-to-str (omni:val e "Beschreibung")))) liste) (end_list) - (set_tile "ladeschleife" "0") + ;; Beim Edit (OMNI_EDIT) das bearbeitete Bauteil vorwaehlen + (setq idx (omni:vorwahl-index *omni-dlg-vorwahl* liste)) + (if (null idx) (setq idx 0)) + (set_tile "ladeschleife" (itoa idx)) (set_tile "val_hoehe" init-hoehe) - (omni:ladeschleife-dlg-update "0") + (omni:ladeschleife-dlg-update (itoa idx)) (action_tile "ladeschleife" "(omni:ladeschleife-dlg-update $value)") (action_tile "accept" diff --git a/Lisp/README.md b/Lisp/README.md index d6383a8..85ef0c1 100644 --- a/Lisp/README.md +++ b/Lisp/README.md @@ -703,13 +703,14 @@ AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbind | --- | --- | --- | | Daten | `OMNI_LOAD`, `OMNI_INFO_BOGEN`, `OMNI_INFO_WEICHE` | JSON-Daten laden und abfragen | | Boegen | `OMNI_APB_630_90`, `OMNI_APB_550_675`, `OMNI_APB_630_45`, `OMNI_APB_550_225`, `OMNI_APB_650_180` | Omniflo-Boegen ueber DCL-Dialog einfuegen | -| Weichen | `OMNI_W90_*`, `OMNI_W45_*`, `OMNI_WP_*`, `OMNI_WK_*`, `OMNI_WKomb_*` | Omniflo-Weichen (Einfach/Doppel/Dreiwege, Delta, Stern) | +| Weichen | `OMNI_W90`, `OMNI_W45`, `OMNI_WP`, `OMNI_WK`, `OMNI_WKomb_*` | Omniflo-Weichen: je Winkel EIN Dialog mit Einzel-, Doppel- und Dreiwegeweichen, Typwahl ueber die Radiogruppe "Richtung" (Links/Rechts/Doppel/Dreiwege = KurvenRichtung 1/2/3/7, Basisliste `omni:weichen-basis-liste` mit `*omni-weichen-std-typen*`, nicht belegte Richtungen ausgegraut); Delta/Stern eigene Dialoge | +| Weichenbatterien | `OMNI_WB_` (16) | Fertige Weichenbatterien, DWG `data/omniflo/2D/.dwg` (nur 2D, Rueckfall per `omni:omniflo-datei-finden`), Menuetexte/Nummern aus `data/omniflo/weichenbatterien_artinr_quelle.dxf` (BESCHR/ARTINR). Im Katalog `omniflo_weichen.json` als `WeichenTyp` "Weichenbatterie" (ohne Winkel/Breite/Laenge), darum oeffnet der Doppelklick (`OMNI_EDIT`) den Weichen-Dialog mit allen Batterien - Richtung und Schaltung umstellbar | | Ladeschleifen | `OMNI_LADESCHLEIFE_AP110` | Ladeschleife aus `omniflo_ladeschleifen.json` ueber DCL-Dialog (`dcl/omniflo_ladeschleifen.dcl`) einfuegen; Daten per `ssg-json-laden` (Beschreibungen enthalten Kommas). Blockdatei `.dwg` unter `DXFM_OMNIFLO` (`omni:insert-dxf` faellt auf `.dwg` zurueck, wenn keine `.dxf` existiert). Per `OMNI_EDIT` editierbar | | TEF Elemente | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade` | Feste TEF-Bauteile ohne Sivas-Auswahl, direkt per `omni:insert-dxf` an gewaehltem Punkt eingefuegt (Dateien unter `DXFM_OMNIFLO`) | | Anbaugruppen | `OMNI_STOPPER`, `OMNI_SCANNER`, `OMNI_BUERSTENBREMSE` | Implementiert | | Verbinder | `OMNI_TV_*` | Verbinder-DWG aus `data/omniflo/Verbinder` (dimensionsunabhaengig, `omni:insert-verbinder` -> `omni:insert-datei`, Punkt + Drehung interaktiv). Zuordnung Befehl -> DWG nach Dateiname, z.B. `OMNI_TV_W_AP60` -> `TV_W-AP60_oben`, `OMNI_TV_ENDPLATTE` -> `VB_ENDP_AP`, `OMNI_TV_W_AP60_KPL` -> `TV_W-AP60_kpl`, `OMNI_TV_ANSCHLAG` -> `VB_ENDP_AP_Spulenzug`, `OMNI_TV_SW_I_AP110` -> `TV_SW_I_SW-AP110`, `OMNI_TV_MUFFE` -> `VB_Muffe`. Alle 18 Eintraege aktiv | | Bogenweichen ⚠️ | `OMNI_APBW_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) | -| Bearbeiten | `OMNI_EDIT` | Omniflo-Block selektieren und Attribute bearbeiten | +| Bearbeiten | `OMNI_EDIT` | Omniflo-Block selektieren und im Bogen-/Weichen-/Ladeschleifen-Dialog neu waehlen. Das bearbeitete Bauteil ist im Dropdown vorgewaehlt (`*omni-dlg-vorwahl*`, `omni:vorwahl-index`); im Weichen-Dialog stehen Schaltung/Richtung auf seinen Werten, und ein Filterwechsel waehlt das Gegenstueck mit dem aehnlichsten ProfilTyp (`omni:profil-aehnlichkeit`) statt des ersten Eintrags - nur L/R oder M/P umstellen braucht damit kein Dropdown | Daneben zeichnet [`TEFInsert.lsp`](#tefinsertlsp--tef-geradenstuecke-entlang-einer-linie) (`TEF_FOERDERER_LINIE`) eine Kette von TEF-Geradenelementen (1000 mm) entlang einer frei gewaehlten Linie – @@ -879,12 +880,13 @@ Phase 0 + 1 (Mengen, 2D). | --- | --- | | `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` der anderen Geschosse frieren (0 = alle zeigen) | -| `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` 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). Alle Gaenge (auch manuelle) bekommen den gewaehlten Belag; Verknuepfungen, Layer `_G` und IDs sind neu | | `c:LG_BEREICH` | Lagerbereich-Kontur + Dialog `lg_bereich`; Auto-Fuellung mit `LG_REIHE__` / `LG_GANG___`, optional Randgaenge Nord/Ost/Sued/West entlang der Konturkanten (auch L-Form) und Absturzsicherung unter den Reihen (`UNTER_REIHE` gitterrost/gitterkorb/keine, `GITTERKORB_HOEHE_mm`) | | `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_EDIT` | Bearbeiten (auch per Doppelklick ueber `SSG_BLOCKEDIT`, Zweig `LG_*`): Bereich -> geaenderter Belag/Haengeebenen werden auf alle vorhandenen Reihen/Gaenge uebertragen, Neuberechnung nur auf Rueckfrage (Vorgabe Ja bei Geometrieaenderung; von Hand eingefuegte und geaenderte Reihen/Gaenge des Geschosses bleiben stehen und werden ausgespart, auch aus den Randgaengen), Reihe/Gang -> Neuaufbau, danach Zuschnitt der rangniedrigeren Objekte (`auto` < `auto_geaendert` < `manuell`, `lg-quelle-rang`) statt Neuberechnung des Bereichs | | `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:LG_DARSTELLUNG` | Darstellung aktualisieren: Farben/Schraffuren aus `lager.json` (`darstellung`, `belag_schraffur`) auf die Reihen-/Gang-Definitionen, Absturzsicherung unter den Reihen aller Geschosse neu zeichnen (Gitterrost/Gitterkorb als Schraffur, Gitterkorb-Abgrenzung nur an offenen Kanten, Layer `LG_Sicherung_G`). Geschieht nach Aenderungen automatisch fuer das betroffene Geschoss | | `c:LAGER_EXPORT` | `_lager.json` in `DXFM_RESULTS`: alle Geschosse, Bereiche, Reihen und Gaenge mit Attributen und Geometrie, Kennwerte je Geschoss und gesamt (inkl. Gitterkorb mit offenen Kanten), Herkunft je Kennwert, Warnungen. Kein Python-Schritt | | `c:LG_REGELN` | Regelprofil (`cfg/stahlbau/regelwerk/.json`) mit aufgeloesten Werten und Quellen anzeigen | diff --git a/cfg/layer.cfg b/cfg/layer.cfg index 6f1f6bc..01e9110 100644 --- a/cfg/layer.cfg +++ b/cfg/layer.cfg @@ -190,6 +190,7 @@ geschoss = LG_Geschoss, 7 bereich = LG_Bereich, 4 reihe = LG_Reihe, 3 gang = LG_Gang, 8 +sicherung = LG_Sicherung, 30 # ============================================================ diff --git a/data/ils/ES_Element_30_links_2D.dwg b/data/ils/ES_Element_30_links_2D.dwg index 29b4c92..a876a15 100644 Binary files a/data/ils/ES_Element_30_links_2D.dwg and b/data/ils/ES_Element_30_links_2D.dwg differ diff --git a/data/ils/ES_Element_30_links_3D.dwg b/data/ils/ES_Element_30_links_3D.dwg index 9f99b3a..68aea87 100644 Binary files a/data/ils/ES_Element_30_links_3D.dwg and b/data/ils/ES_Element_30_links_3D.dwg differ diff --git a/data/ils/ES_Element_30_rechts_2D.dwg b/data/ils/ES_Element_30_rechts_2D.dwg index 4c6738d..2e0cd4c 100644 Binary files a/data/ils/ES_Element_30_rechts_2D.dwg and b/data/ils/ES_Element_30_rechts_2D.dwg differ diff --git a/data/ils/ES_Element_30_rechts_3D.dwg b/data/ils/ES_Element_30_rechts_3D.dwg index c0c7543..9c9ea9d 100644 Binary files a/data/ils/ES_Element_30_rechts_3D.dwg and b/data/ils/ES_Element_30_rechts_3D.dwg differ diff --git a/data/ils/ES_Element_90_links_2D.dwg b/data/ils/ES_Element_90_links_2D.dwg index a2cdc74..a22211b 100644 Binary files a/data/ils/ES_Element_90_links_2D.dwg and b/data/ils/ES_Element_90_links_2D.dwg differ diff --git a/data/ils/ES_Element_90_links_3D.dwg b/data/ils/ES_Element_90_links_3D.dwg index 929e7cd..0acd697 100644 Binary files a/data/ils/ES_Element_90_links_3D.dwg and b/data/ils/ES_Element_90_links_3D.dwg differ diff --git a/data/ils/ES_Element_90_rechts_2D.dwg b/data/ils/ES_Element_90_rechts_2D.dwg index 96192bb..1e34934 100644 Binary files a/data/ils/ES_Element_90_rechts_2D.dwg and b/data/ils/ES_Element_90_rechts_2D.dwg differ diff --git a/data/ils/ES_Element_90_rechts_3D.dwg b/data/ils/ES_Element_90_rechts_3D.dwg index 6e4148b..19860e1 100644 Binary files a/data/ils/ES_Element_90_rechts_3D.dwg and b/data/ils/ES_Element_90_rechts_3D.dwg differ diff --git a/data/json/lager.json b/data/json/lager.json index ff67684..cdbc064 100644 --- a/data/json/lager.json +++ b/data/json/lager.json @@ -34,15 +34,24 @@ }, "belag_schraffur": { - "beschreibung": "Schraffur der Gangflaechen (LG_GANG_*) je Belag: muster = Schraffurmuster aus der BricsCAD-Musterdatei (metrisch: iso.pat), massstab, winkel in Grad; null = keine Schraffur. ANSI31 x 50 = Linien alle ca. 160 mm, GRID x 8 = Raster ca. 200 mm.", - "spanplatte": {"muster": "ANSI31", "massstab": 50, "winkel": 0}, - "gitterrost": {"muster": "GRID", "massstab": 8, "winkel": 0}, + "beschreibung": "Schraffur der Gangflaechen (LG_GANG_*) je Belag: muster = Schraffurmuster aus der BricsCAD-Musterdatei (metrisch: iso.pat), massstab, winkel in Grad, farbe (siehe darstellung); null = keine Schraffur. ANSI31 x 50 = Linien alle ca. 160 mm, GRID x 8 = Raster ca. 200 mm.", + "spanplatte": {"muster": "ANSI31", "massstab": 50, "winkel": 0, "farbe": null}, + "gitterrost": {"muster": "GRID", "massstab": 8, "winkel": 0, "farbe": null}, "hallenboden": null }, "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" + }, + + "darstellung": { + "beschreibung": "Farben und Schraffuren in der Zeichnung. farbe = ACI-Nummer (1..255) oder RGB-Text \"r,g,b\"; null = VONLAYER (Reihe) bzw. VONBLOCK (Gangschraffur). unter_reihe: Darstellung der Absturzsicherung unter den Regalreihen auf Buehnen (Layer LG_Sicherung_G), gitterkorb.rand = dicke Linie an den OFFENEN Kanten (an anliegenden Nachbarreihen keine). Aenderungen wirken auf den Bestand nach LG_DARSTELLUNG (Menue Lager -> Darstellung aktualisieren).", + "reihe": {"farbe": null}, + "unter_reihe": { + "gitterrost": {"muster": "ANSI37", "massstab": 30, "winkel": 45, "farbe": 8}, + "gitterkorb": {"muster": "ANSI38", "massstab": 30, "winkel": 0, "farbe": 30, + "rand": {"farbe": 30, "breite_mm": 50}} + } } } diff --git a/data/json/omniflo_weichen.json b/data/json/omniflo_weichen.json index 03f2adb..4784cba 100644 --- a/data/json/omniflo_weichen.json +++ b/data/json/omniflo_weichen.json @@ -926,5 +926,197 @@ "Länge": 360, "KurvenRichtung": 7, "SivasnrTEF": null + }, + { + "Sivasnr": 834372536, + "ProfilTyp": "Weiche S C L1S 1C 200/1200/950 mit M", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "M", + "Breite": null, + "Länge": null, + "KurvenRichtung": 1, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372537, + "ProfilTyp": "Weiche S C L1S 1C 200/1200/950 mit P", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "P", + "Breite": null, + "Länge": null, + "KurvenRichtung": 1, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372512, + "ProfilTyp": "Weiche S C L1S 2C 200/1200/950 mit M", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "M", + "Breite": null, + "Länge": null, + "KurvenRichtung": 1, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372513, + "ProfilTyp": "Weiche S C L1S 2C 200/1200/950 mit P", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "P", + "Breite": null, + "Länge": null, + "KurvenRichtung": 1, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372524, + "ProfilTyp": "Weiche S C L2S 2C 200/1200/950 mit M", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "M", + "Breite": null, + "Länge": null, + "KurvenRichtung": 1, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372525, + "ProfilTyp": "Weiche S C L2S 2C 200/1200/950 mit P", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "P", + "Breite": null, + "Länge": null, + "KurvenRichtung": 1, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372500, + "ProfilTyp": "Weiche S C L2S 3C 200/1400/950 mit M", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "M", + "Breite": null, + "Länge": null, + "KurvenRichtung": 1, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372501, + "ProfilTyp": "Weiche S C L2S 3C 200/1400/950 mit P", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "P", + "Breite": null, + "Länge": null, + "KurvenRichtung": 1, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372539, + "ProfilTyp": "Weiche S C R1S 1C 200/1200/950 mit M", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "M", + "Breite": null, + "Länge": null, + "KurvenRichtung": 2, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372540, + "ProfilTyp": "Weiche S C R1S 1C 200/1200/950 mit P", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "P", + "Breite": null, + "Länge": null, + "KurvenRichtung": 2, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372515, + "ProfilTyp": "Weiche S C R1S 2C 200/1200/950 mit M", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "M", + "Breite": null, + "Länge": null, + "KurvenRichtung": 2, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372516, + "ProfilTyp": "Weiche S C R1S 2C 200/1200/950 mit P", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "P", + "Breite": null, + "Länge": null, + "KurvenRichtung": 2, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372527, + "ProfilTyp": "Weiche S C R2S 2C 200/1200/950 mit M", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "M", + "Breite": null, + "Länge": null, + "KurvenRichtung": 2, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372528, + "ProfilTyp": "Weiche S C R2S 2C 200/1200/950 mit P", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "P", + "Breite": null, + "Länge": null, + "KurvenRichtung": 2, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372503, + "ProfilTyp": "Weiche S C R2S 3C 200/1400/950 mit M", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "M", + "Breite": null, + "Länge": null, + "KurvenRichtung": 2, + "SivasnrTEF": null, + "WeichenkörperLänge": null + }, + { + "Sivasnr": 834372504, + "ProfilTyp": "Weiche S C R2S 3C 200/1400/950 mit P", + "WeichenTyp": "Weichenbatterie", + "KurvenWinkel": null, + "Schaltungstyp": "P", + "Breite": null, + "Länge": null, + "KurvenRichtung": 2, + "SivasnrTEF": null, + "WeichenkörperLänge": null } ] \ No newline at end of file diff --git a/data/omniflo/2D/834372500.dwg b/data/omniflo/2D/834372500.dwg new file mode 100644 index 0000000..c3f6020 Binary files /dev/null and b/data/omniflo/2D/834372500.dwg differ diff --git a/data/omniflo/2D/834372501.dwg b/data/omniflo/2D/834372501.dwg new file mode 100644 index 0000000..2a0df0e Binary files /dev/null and b/data/omniflo/2D/834372501.dwg differ diff --git a/data/omniflo/2D/834372503.dwg b/data/omniflo/2D/834372503.dwg new file mode 100644 index 0000000..1d7a866 Binary files /dev/null and b/data/omniflo/2D/834372503.dwg differ diff --git a/data/omniflo/2D/834372504.dwg b/data/omniflo/2D/834372504.dwg new file mode 100644 index 0000000..53fd5f8 Binary files /dev/null and b/data/omniflo/2D/834372504.dwg differ diff --git a/data/omniflo/2D/834372512.dwg b/data/omniflo/2D/834372512.dwg new file mode 100644 index 0000000..01a365b Binary files /dev/null and b/data/omniflo/2D/834372512.dwg differ diff --git a/data/omniflo/2D/834372513.dwg b/data/omniflo/2D/834372513.dwg new file mode 100644 index 0000000..8aa39e5 Binary files /dev/null and b/data/omniflo/2D/834372513.dwg differ diff --git a/data/omniflo/2D/834372515.dwg b/data/omniflo/2D/834372515.dwg new file mode 100644 index 0000000..06dc715 Binary files /dev/null and b/data/omniflo/2D/834372515.dwg differ diff --git a/data/omniflo/2D/834372516.dwg b/data/omniflo/2D/834372516.dwg new file mode 100644 index 0000000..f3b878a Binary files /dev/null and b/data/omniflo/2D/834372516.dwg differ diff --git a/data/omniflo/2D/834372524.dwg b/data/omniflo/2D/834372524.dwg new file mode 100644 index 0000000..c7ee238 Binary files /dev/null and b/data/omniflo/2D/834372524.dwg differ diff --git a/data/omniflo/2D/834372525.dwg b/data/omniflo/2D/834372525.dwg new file mode 100644 index 0000000..4459e55 Binary files /dev/null and b/data/omniflo/2D/834372525.dwg differ diff --git a/data/omniflo/2D/834372527.dwg b/data/omniflo/2D/834372527.dwg new file mode 100644 index 0000000..7ebc511 Binary files /dev/null and b/data/omniflo/2D/834372527.dwg differ diff --git a/data/omniflo/2D/834372528.dwg b/data/omniflo/2D/834372528.dwg new file mode 100644 index 0000000..f96647d Binary files /dev/null and b/data/omniflo/2D/834372528.dwg differ diff --git a/data/omniflo/2D/834372536.dwg b/data/omniflo/2D/834372536.dwg new file mode 100644 index 0000000..2e1a81c Binary files /dev/null and b/data/omniflo/2D/834372536.dwg differ diff --git a/data/omniflo/2D/834372537.dwg b/data/omniflo/2D/834372537.dwg new file mode 100644 index 0000000..857a4f3 Binary files /dev/null and b/data/omniflo/2D/834372537.dwg differ diff --git a/data/omniflo/2D/834372539.dwg b/data/omniflo/2D/834372539.dwg new file mode 100644 index 0000000..94b277f Binary files /dev/null and b/data/omniflo/2D/834372539.dwg differ diff --git a/data/omniflo/2D/834372540.dwg b/data/omniflo/2D/834372540.dwg new file mode 100644 index 0000000..77af03b Binary files /dev/null and b/data/omniflo/2D/834372540.dwg differ 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/dcl/omniflo_weichen.dcl b/dcl/omniflo_weichen.dcl index f894814..99a1bf6 100644 --- a/dcl/omniflo_weichen.dcl +++ b/dcl/omniflo_weichen.dcl @@ -28,6 +28,8 @@ omniflo_weichen : dialog { : radio_button { key = "ri_alle"; label = "Alle"; value = "1"; } : radio_button { key = "ri_links"; label = "Links"; } : radio_button { key = "ri_rechts"; label = "Rechts"; } + : radio_button { key = "ri_doppel"; label = "Doppel"; } + : radio_button { key = "ri_dreiwege"; label = "Dreiwege"; } } } diff --git a/doc/kommandos.md b/doc/kommandos.md index 0e9654b..d236c2c 100644 --- a/doc/kommandos.md +++ b/doc/kommandos.md @@ -91,10 +91,10 @@ Gross-/Kleinschreibung spielt an der Kommandozeile keine Rolle. | `OMNI_LOAD` | Omniflo-Komponentendaten laden | | `OMNI_INFO_BOGEN` / `OMNI_INFO_WEICHE` | Daten eines Bogens / einer Weiche anzeigen | | `OMNI_APB60_90`, `OMNI_APB_630_90`, `OMNI_APB_630_45`, `OMNI_APB_550_675`, `OMNI_APB_550_225`, `OMNI_APB_650_180` | Boegen einfuegen (Dialog `omniflo_boegen.dcl`) | -| `OMNI_W90_Einfach`/`_Doppel`/`_Dreiwege` | Weichen 90 Grad (Dialog `omniflo_weichen.dcl`) | -| `OMNI_W45_Einfach`/`_Doppel`/`_Dreiwege` | Weichen 45 Grad | -| `OMNI_WP_Einfach`/`_Doppel`/`_Dreiwege` | Parallelweichen | -| `OMNI_WK_Einfach`/`_Doppel`/`_Dreiwege` | Weichenkoerper | +| `OMNI_W90` | Weichen 90 Grad (Dialog `omniflo_weichen.dcl`; Einzel/Doppel/Dreiwege ueber "Richtung": Links/Rechts/Doppel/Dreiwege) | +| `OMNI_W45` | Weichen 45 Grad | +| `OMNI_WP` | Parallelweichen | +| `OMNI_WK` | Weichenkoerper | | `OMNI_WKomb_Delta_1400`, `OMNI_WKomb_Delta_1600`, `OMNI_WKomb_Star` | Weichenkombinationen (Delta, Stern) | | `OMNI_APBW_R400_45_140`, `OMNI_APBW_R400_675_260`, `OMNI_APBW_R550_45_77`, `OMNI_APBW_R550_45_194`, `OMNI_APBW_R550_225_360`, `OMNI_APBW_R550_225_410A`/`B`/`C`, `OMNI_APBW_R550_675_58`/`_125`/`_208`/`_360`, `OMNI_APBW_R650_90_300`, `OMNI_APBW_R750_90_200` | Boegen fuer Weichen (fest, ohne Dialog) | | `OMNI_TEF_UmlenkL`/`R`, `OMNI_TEF_AntriebL`/`R`, `OMNI_TEF_Gerade` | TEF-Elemente (fest, ohne Drehung) | diff --git a/doc/plan/lager_rfq.md b/doc/plan/lager_rfq.md index 3a6d92b..f0f7ab5 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, @@ -123,8 +145,9 @@ Stattdessen entsteht jedes Objekt ueber die normalen Einfuegefunktionen neu: - 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. +- Ist im Dialog ein Belag gewaehlt, bekommen ALLE Gaenge und Bereiche des neuen + Geschosses ihn, inklusive Schraffur - auch von Hand gesetzte Rand- und + Sondergaenge (`lg-kopie-belag`). ### Auto-Fuellung (`lg-fuellung-berechnen`) @@ -140,12 +163,25 @@ 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. +`RESTBREITE_mm`. + +**Bereich bearbeiten: aktualisieren statt ueberschreiben.** Was eingezeichnet ist, +bleibt stehen. Geaenderte Werte ohne Geometrie werden auf ALLE vorhandenen Kinder +uebertragen (`lg-bereich-attribute-uebertragen`): `BELAG` -> jeder Gang wird mit dem +neuen Belag an derselben Stelle neu aufgebaut, `HAENGEEBENEN` -> Attribut jeder +Reihe. Nur wenn sich ein Geometrie-Wert aendert (`lg-bereich-geometrie-geaendert-p`: +Gangbreite, Regaltiefe, Reihen je Gang, Quergaenge, Richtung, Randgang-Breiten), +fragt der Befehl "Bereich neu berechnen?" (Vorgabe Ja; ohne Aenderung Vorgabe +Nein - so laesst sich ein Bereich auch bewusst neu berechnen). + +Die Neuberechnung (`lg-bereich-fuellen`) ersetzt nur die automatisch erzeugten +Kinder (`QUELLE=auto`). Sperre sind ALLE von Hand eingefuegten (`manuell`) und +geaenderten (`auto_geaendert`) Reihen und Gaenge des Geschosses +(`lg-von-hand-auf-geschoss`) - auch solche eines anderen Bereichs oder nur +teilweise in der Kontur. Sie werden aus Reihen, Haupt-, Quer- UND Randgaengen +ausgeschnitten (`lg-randgang-stuecke`): ein manueller Gang ersetzt den Randgang +dort, wo er liegt, statt von ihm ueberlagert zu werden. Von Hand geloeschte +automatische Objekte entstehen bei der 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, @@ -199,6 +235,26 @@ Reihen bleiben unschraffiert. Altbestand: fehlen einer vorhandenen Blockdefinition ATTDEFs des Schemas, definiert `lg-blockdef` sie neu und uebertraegt sie per `_.ATTSYNC` auf die Referenzen. +## Darstellung in der Zeichnung + +- **Absturzsicherung unter den Reihen** (nur Buehnen): je Reihe eine + Schraffur nach `UNTER_REIHE` - `gitterrost` und `gitterkorb` mit eigenem + Muster und eigener Farbe (`lager.json darstellung.unter_reihe`). Der + Gitterkorb bekommt zusaetzlich seine seitliche Abgrenzung als dicke Linie + (`rand.farbe`, `rand.breite_mm`), und zwar NUR an den offenen Kanten: wo eine + andere Reihe anliegt (z.B. Ruecken an Ruecken), wird keine Abgrenzung + gezeichnet (`lg-sicherung-geometrie`, gleiche Regel wie `offen_laengs_mm`). +- Die Objekte liegen lose auf `LG_Sicherung_G` (XDATA `rolle=sicherung`, + wird mit dem Geschoss gefroren) und werden bei jedem Neuaufbau des Geschosses + komplett ersetzt - automatisch nach Bereich fuellen/bearbeiten (Doppelklick), + Reihe/Gang bearbeiten, `LG_REIHE`/`LG_GANG`, Geschoss bearbeiten/kopieren. +- **Farben**: `darstellung.reihe.farbe` (Regalreihen), `belag_schraffur..farbe` + (Gangschraffur); ACI-Nummer oder `"r,g,b"`, `null` = VONLAYER/VONBLOCK. +- **`LG_DARSTELLUNG`** (Menue Lager -> Darstellung aktualisieren): liest + `lager.json` neu, passt alle vorhandenen `LG_REIHE_*`/`LG_GANG_*`-Definitionen + an und zeichnet die Sicherung aller Geschosse neu - noetig nach Loeschen von + Hand oder nach Aenderungen in `lager.json`. + ## Kennwerte <- Zeichnung Reine Kerne in `LagerInsert.lsp` (getestet in `tu-tests-lager`). Jeder @@ -208,14 +264,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 1e7e7d5..0ec3e81 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -1219,7 +1219,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)", @@ -1241,7 +1240,9 @@ "lg-rechteck-zu-klein": "\n[Lager] Rechteck zu klein (Seite unter 1 mm) - kein Gang eingefuegt.", "lg-gaenge-eingefuegt": "\n%1 Gang/Gaenge eingefuegt.", "lg-schraffur-unbekannt": "\n[Lager] Belag %1 hat keinen Eintrag in belag_schraffur (lager.json) - Gaenge ohne Schraffur.", - "lg-schraffur-fehler": "\n[Lager] Schraffur %1 fuer %2 nicht moeglich (%3) - Gang ohne Schraffur.", + "lg-schraffur-fehler": "\n[Lager] Schraffur %1 fuer %2 nicht moeglich (%3) - ohne Schraffur.", + "lg-darstellung-fertig": "\n[Lager] Darstellung aktualisiert: %1 Objekt(e) Absturzsicherung unter den Reihen.", + "lg-titel-darstellung": "Lager - Darstellung aktualisieren", "lg-blockdef-ergaenzt": "\n[Lager] Blockdefinition %1 um %2 ergaenzt (Altbestand).", "lg-titel-kopie": "Lager: Geschoss kopieren", "lg-feld-quelle": "\nQuellgeschoss (Nr.)", @@ -1279,6 +1280,8 @@ "lg-geaendert": "\nGeaendert.", "lg-bereich-ohne-kontur": "\n[Lager] Die Kontur des Bereichs fehlt - Fuellung nicht moeglich.", "lg-bereich-beibehalten": "\nBereich %2: %1 von Hand eingefuegte oder geaenderte Reihe(n)/Gaenge bleiben erhalten und werden ausgespart.", + "lg-bereich-uebertragen": "\n[Lager] %1 vorhandene Reihe(n)/Gang/Gaenge an die geaenderten Werte angepasst.", + "lg-frage-neu-berechnen": "\nBereich neu berechnen? (automatisch erzeugte Reihen/Gaenge neu legen; von Hand gesetzte und geaenderte bleiben)", "lg-bereich-gefuellt": "\nBereich %1: %2 Regalreihe(n), %3 Gang-/Quergangflaeche(n), Restbreite %4 mm.", "lg-prompt-reihe-start": "\nStartpunkt der Regalreihe : ", "lg-prompt-reihe-ende": "\nEndpunkt oder Laenge (mm): ", @@ -1291,6 +1294,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 10d2a7b..f8d1c9d 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -1219,7 +1219,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)", @@ -1241,7 +1240,9 @@ "lg-rechteck-zu-klein": "\n[Storage] Rectangle too small (side below 1 mm) - no aisle inserted.", "lg-gaenge-eingefuegt": "\n%1 aisle(s) inserted.", "lg-schraffur-unbekannt": "\n[Storage] Floor type %1 has no entry in belag_schraffur (lager.json) - aisles without hatch.", - "lg-schraffur-fehler": "\n[Storage] Hatch %1 for %2 not possible (%3) - aisle without hatch.", + "lg-schraffur-fehler": "\n[Storage] Hatch %1 for %2 not possible (%3) - without hatch.", + "lg-darstellung-fertig": "\n[Storage] Display updated: %1 fall protection object(s) below the rows.", + "lg-titel-darstellung": "Storage - update display", "lg-blockdef-ergaenzt": "\n[Storage] Block definition %1 extended by %2 (existing drawing).", "lg-titel-kopie": "Storage: copy level", "lg-feld-quelle": "\nSource level (no.)", @@ -1279,6 +1280,8 @@ "lg-geaendert": "\nChanged.", "lg-bereich-ohne-kontur": "\n[Storage] The contour of the area is missing - cannot fill.", "lg-bereich-beibehalten": "\nArea %2: %1 manually inserted or changed row(s)/aisle(s) are kept and left out.", + "lg-bereich-uebertragen": "\n[Storage] %1 existing row(s)/aisle(s) updated to the changed values.", + "lg-frage-neu-berechnen": "\nRecalculate area? (re-create automatically generated rows/aisles; manually placed and modified ones stay)", "lg-bereich-gefuellt": "\nArea %1: %2 rack row(s), %3 aisle/cross aisle area(s), remaining width %4 mm.", "lg-prompt-reihe-start": "\nStart point of the rack row : ", "lg-prompt-reihe-ende": "\nEnd point or length (mm): ", @@ -1291,6 +1294,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/menu/SSG_LIB.cui b/menu/SSG_LIB.cui index 20cda01..0a26bd9 100644 --- a/menu/SSG_LIB.cui +++ b/menu/SSG_LIB.cui @@ -212,787 +212,841 @@ ^C^C(ssg-ensure "OmniModulInsert") OMNI_APB60_90 - + - Einfach 90 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Einfach + Weichen 90 + ^C^C(ssg-ensure "OmniModulInsert") OMNI_W90 + + + + + Weichen 45 + ^C^C(ssg-ensure "OmniModulInsert") OMNI_W45 + + + + + Weichen Parallel + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WP + + + + + Weichen 22.5 + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WK - - Doppel 90 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Doppel - - - - - Dreiwege 90 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Dreiwege - - - - - Einfach 45 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Einfach - - - - - Doppel 45 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Doppel - - - - - Dreiwege 45 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Dreiwege - - - - - Einfach Parallel - ^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Einfach - - - - - Doppel Parallel - ^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Doppel - - - - - Dreiwege Parallel - ^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Dreiwege - - - - - Einfach 22.5 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Einfach - - - - - Doppel 22.5 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Doppel - - - - - Dreiwege 22.5 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Dreiwege - - - Delta 1600/800 ^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Delta_1600 - + Delta 1400/700 ^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Delta_1400 - + Star 1400/1400 ^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Star + + + Weiche S C L1S 1C 200/1200/950 mit M + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372536 + + + + + Weiche S C L1S 1C 200/1200/950 mit P + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372537 + + + + + Weiche S C L1S 2C 200/1200/950 mit M + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372512 + + + + + Weiche S C L1S 2C 200/1200/950 mit P + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372513 + + + + + Weiche S C L2S 2C 200/1200/950 mit M + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372524 + + + + + Weiche S C L2S 2C 200/1200/950 mit P + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372525 + + + + + Weiche S C L2S 3C 200/1400/950 mit M + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372500 + + + + + Weiche S C L2S 3C 200/1400/950 mit P + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372501 + + + + + Weiche S C R1S 1C 200/1200/950 mit M + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372539 + + + + + Weiche S C R1S 1C 200/1200/950 mit P + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372540 + + + + + Weiche S C R1S 2C 200/1200/950 mit M + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372515 + + + + + Weiche S C R1S 2C 200/1200/950 mit P + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372516 + + + + + Weiche S C R2S 2C 200/1200/950 mit M + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372527 + + + + + Weiche S C R2S 2C 200/1200/950 mit P + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372528 + + + + Weiche S C R2S 3C 200/1400/950 mit M + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372503 + + + + + Weiche S C R2S 3C 200/1400/950 mit P + ^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372504 + + + TEF Antriebst. rechts ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebR - + TEF Umlenkspannst. rechts ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkR - + TEF Antriebst. links ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebL - + TEF Umlenkspannst. links ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkL - + TEF Gerade auf Linie ^C^C(ssg-ensure "TEFInsert") TEF_FOERDERER_LINIE - + TEF Gerade ^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_Gerade - + Stopper AP ^C^C(ssg-ensure "OmniModulInsert") OMNI_STOPPER - + Scanner ^C^C(ssg-ensure "OmniModulInsert") OMNI_SCANNER - + Bürstenbremse ^C^C(ssg-ensure "OmniModulInsert") OMNI_BUERSTENBREMSE - + Schwenkschiene Schiebetür L ^C^C(ssg-ensure "OmniModulInsert") OMNI_SCHW_400_L - + Schwenkschiene Schiebetür R ^C^C(ssg-ensure "OmniModulInsert") OMNI_SCHW_400_R - + Schwenkschiene Schiebetür L mit Sensorik ^C^C(ssg-ensure "OmniModulInsert") OMNI_SCHW_400_L_SENSORIK - + Schwenkschiene Schiebetür R mit Sensorik ^C^C(ssg-ensure "OmniModulInsert") OMNI_SCHW_400_R_SENSORIK - + KettenFoerderer ^C^C(ssg-ensure "KettenFoerderer") KETTENFOERDERER - + Ladeschleifen ^C^C(ssg-ensure "OmniModulInsert") OMNI_LADESCHLEIFE_AP110 - + TV W-AP110 kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110 - + TV W-AP60 oben kpl. ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP60 - + TV W-W kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_W - + TV W-AP110-W kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110_W - + TV W-AP60 kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP60_KPL - + TV 80 ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_80 - + TV 50 ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_50 - + Endplatte Al-Profil AP schraubbar ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_ENDPLATTE - + Anschlag AP-Ende für Spulenzug ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_ANSCHLAG - + TV-A für AP110/AP60 kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP110_AP60 - + TV-A für AP60/ST ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP60_ST - + TV-A für AP110/ST kpl ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP110_ST - + TV-SW II für SW-SW ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_II_SW_SW - + TV-SW III für SW-AP110-SW ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_III_AP110_SW - + TV-SW I für SW-AP110 ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_I_AP110 - + TV-SW IV für Anschluss SW-AP60 ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_IV_AP60 - + TV-SW IV für SW-ST ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_IV_ST - + Muffe ^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_MUFFE - + APB 110 R400/45 140 nur fuer Delta ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R400_45_140 - + APB 110 R550/45 194 nur fuer Delta ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_45_194 - + APBW 110 R550/22,5 360x248,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_360 - + APBW 110 R550/22,5 410x298,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410A - + APBW 110 R550/22,5 410x78,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410B - + APBW 110 R550/22,5 410x98,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410C - + APBW 110 R550/67,5 360x598,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_360 - + APBW 110 R400/67,5 260x398,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R400_675_260 - + APBW 110 R550/45 77x160 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_45_77 - + APBW 110 R550/67,5 125x83,5 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_125 - + APBW 110 R750/90 200x290 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R750_90_200 - + APBW 110 R650/90 300x190 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R650_90_300 - + APBW 110 R550/67,5 208x347 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_208 - + APBW 110 R550/67,5 58x497 ^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_58 - + Element bearbeiten ^C^C(ssg-ensure "OmniModulInsert") OMNI_EDIT - + Rohr-Gerüst-Traeger ^C^C(ssg-ensure "GeruestInsert") GERUEST_TRAEGER - + Säulen ^C^C(ssg-ensure "GeruestInsert") GERUEST_SAEULEN - + Rohrabhänger ^C^C(ssg-ensure "GeruestInsert") GERUEST_ROHRABHAENGER - + Wandbefestigung ^C^C(ssg-ensure "GeruestInsert") GERUEST_WANDBEFESTIGUNG - + Gatterträger ^C^C(ssg-ensure "GeruestInsert") GERUEST - + Traeger beschriften ^C^C(ssg-ensure "GeruestInsert") GERUEST_TRAEGER_BESCHRIFTEN - + Geschoss anlegen ^C^C(ssg-ensure "LagerInsert") LG_GESCHOSS - + Aktives Geschoss ^C^C(ssg-ensure "LagerInsert") LG_GESCHOSS_AKTIV - + Geschoss kopieren ^C^C(ssg-ensure "LagerInsert") LG_GESCHOSS_KOPIEREN - + Lagerbereich (Auto-Fuellung) ^C^C(ssg-ensure "LagerInsert") LG_BEREICH - + Regalreihen einzeln ^C^C(ssg-ensure "LagerInsert") LG_REIHE - + Gaenge einzeln ^C^C(ssg-ensure "LagerInsert") LG_GANG - + Bearbeiten ^C^C(ssg-ensure "LagerInsert") LG_EDIT - + + + Darstellung aktualisieren + ^C^C(ssg-ensure "LagerInsert") LG_DARSTELLUNG + + + Regale zaehlen ^C^C(ssg-ensure "LagerInsert") LG_REGALE - + Regelprofil anzeigen ^C^C(ssg-ensure "LagerPruefung") LG_REGELN - + Export Lager-JSON ^C^C(ssg-ensure "LagerInsert") LAGER_EXPORT - + Materialfluss erzeugen ^C^C(ssg-ensure "HwPlanung") HW_MATERIALFLUSS - + Symbole erzeugen ^C^C(ssg-ensure "HwPlanung") HW_SYMBOLE - + Symbole nummerieren ^C^C(ssg-ensure "HwPlanung") HW_NUMMERIEREN - + Marker einfuegen ^C^C(ssg-ensure "Tro_Edit") TRO_INSERT - + Marker bearbeiten ^C^C(ssg-ensure "Tro_Edit") TRO_EDIT - + Bearbeiten (Auto) ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT - + Verbindung einfuegen ^C^C(ssg-ensure "Connection_Edit") CONNECTION_INSERT - + Verbindung bearbeiten ^C^C(ssg-ensure "Connection_Edit") CONNECTION_EDIT - + Eingang ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_EINGANG_INSERT - + Ausgang ^C^C(ssg-ensure "SSG_LIB_Commands") ILS_AUSGANG_INSERT - + SPS Schliessen ^C^C - + Hoehen-Check (Montagehoehe/Buehne) ^C^C(ssg-ensure "check_hoehen") HOEHEN_CHECK - + Export Sivas ^C^C(ssg-ensure "export") EXPORTSIVAS - + Export CSV ^C^C(ssg-ensure "export") EXPORTCSV - + Umschalten 2D und 3D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_SWITCH - + Alle Bloecke auf 2D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_ALL_2D - + Alle Bloecke auf 3D ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_ALL_3D - + Sprache ^C^C(ssg-ensure "SSG_LIB_Commands") SSG_SPRACHE - + Planquadrate an/aus ^C^C(ssg-ensure "DrawPlanquadrate") PLANQUADRATE_TOGGLE - + CSV-Export ^C^C(ssg-ensure "export") CSV_EXPORT_KONFIG - + Bloecke zaehlen ^C^C(ssg-ensure "ssg_blocktools") SSG_BLOCK_COUNT - + Bloecke loeschen ^C^C(ssg-ensure "ssg_blocktools") SSG_BLOCK_DELETE - + Attribute ersetzen ^C^C(ssg-ensure "ssg_blocktools") SSG_ATTR_ERSETZEN - + Text ersetzen ^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_ERSETZEN - + Text parallel beschriften ^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_PARALLEL - + Texthoehe aendern ^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_HOEHE - + Textstil aendern ^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_STIL - + Faehnchen + Stueckliste aus Zeichnung ^C^C(ssg-ensure "ssg_stueckliste") SSG_FAEHNCHEN_STUECKLISTE - + Din Formate ^C^C(ssg-ensure "DinFormate") DIN_FORMATE - + alle Tests ausfuehren und exportieren ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) (c:SSG_RUN_ALL_TESTS_EXPORT) - + Tests ausfuehren und stehen lassen ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) (c:SSG_RUN_ALL_TESTS_OFFEN) - + Export CSV/Sivas ALL ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_export_all.lsp")) (c:TEST_EXPORT_ALL) - + Kreisel ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_kreisel.lsp")) (c:TEST_KREISEL) - + Foerderer ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_foerderer.lsp")) (c:TEST_FOERDERER) - + Foerderer-Linienzug ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_linienzug.lsp")) (c:TEST_LINIENZUG) (c:TEST_LINIENZUG_STUFE2) (c:TEST_LINIENZUG_MODUS2) - + Omniflo ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo.lsp")) (c:TEST_OMNIFLO) - + Omniflo Strecke ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo_strecke.lsp")) (c:TEST_OMNIFLO_STRECKE) - + Gefaellestrecke ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_gefaellestrecke.lsp")) (c:TEST_GEFAELLESTRECKE) - + Mubea Gesamtmodell ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_mubea.lsp")) (c:TEST_MUBEA) - + HundM05 Kreisel-Abschnitt ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_hundm05.lsp")) (c:TEST_HUNDM05) - + Dematic/Arvato Flowpuffer (Vorlage) ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_dematic_arvato.lsp")) (c:TEST_DEMATIC_ARVATO) - + ILS 3.0 Showroom (Vorlage) ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_showroom_ils.lsp")) (c:TEST_SHOWROOM_ILS) - + Testanlage test_system ^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_test_system.lsp")) (c:TEST_TEST_SYSTEM) - + KS 2D/3D pruefen (CSV) ^C^C(load (strcat (getenv "DXFMAKRO") "/Lisp/ks_pruefung.lsp")) KS_PRUEFEN - + Kreisel bearbeiten (ssg-ensure "KreiselInsert") KreiselEdit - + Eckrad bearbeiten (ssg-ensure "KreiselInsert") EckradEdit - + Omniflo Element bearbeiten (ssg-ensure "OmniModulInsert") OMNI_EDIT - + Gefaellestrecke bearbeiten (ssg-ensure "Gefaellestrecke") GEFAELLESTRECKE_EDIT - + VarioFoerderer bearbeiten (ssg-ensure "VarioFoerderer") VARIOFOERDERER_EDIT - + TRO-Marker bearbeiten (ssg-ensure "Tro_Edit") TRO_EDIT - + Verbindung bearbeiten (ssg-ensure "Connection_Edit") CONNECTION_EDIT - + SSG Bearbeiten (Auto) (ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT @@ -1009,14 +1063,14 @@ SSG_LIB - - - - - - - - + + + + + + + + ILS @@ -1212,28 +1266,29 @@ - - - - + + + + + KettenFoerderer - + Ladeschleifen - + - - + + Element bearbeiten - + @@ -1279,856 +1334,911 @@ - + Weichen - Einfach 90 + Weichen 90 - + - Doppel 90 + Weichen 45 - + - Dreiwege 90 + Weichen Parallel - - - - - - Einfach 45 - - + - Doppel 45 + Weichen 22.5 - - - - - Dreiwege 45 - - - - - - - Einfach Parallel - - - - - - Doppel Parallel - - - - - - Dreiwege Parallel - - - - - - - Einfach 22.5 - - - - - - Doppel 22.5 - - - - - - Dreiwege 22.5 - - + Delta 1600/800 - + Delta 1400/700 - + Star 1400/1400 - + - - TEF Elemente + + Weichenbatterien - TEF Antriebst. rechts + Weiche S C L1S 1C 200/1200/950 mit M + + + + + + Weiche S C L1S 1C 200/1200/950 mit P + + + + + + Weiche S C L1S 2C 200/1200/950 mit M + + + + + + Weiche S C L1S 2C 200/1200/950 mit P + + + + + + Weiche S C L2S 2C 200/1200/950 mit M + + + + + + Weiche S C L2S 2C 200/1200/950 mit P + + + + + + Weiche S C L2S 3C 200/1400/950 mit M + + + + + + Weiche S C L2S 3C 200/1400/950 mit P + + + + + + + Weiche S C R1S 1C 200/1200/950 mit M + + + + + + Weiche S C R1S 1C 200/1200/950 mit P + + + + + + Weiche S C R1S 2C 200/1200/950 mit M + + + + + + Weiche S C R1S 2C 200/1200/950 mit P + + + + + + Weiche S C R2S 2C 200/1200/950 mit M + + + + + + Weiche S C R2S 2C 200/1200/950 mit P + + + + + + Weiche S C R2S 3C 200/1400/950 mit M - TEF Umlenkspannst. rechts + Weiche S C R2S 3C 200/1400/950 mit P - + + + TEF Elemente - TEF Antriebst. links + TEF Antriebst. rechts - TEF Umlenkspannst. links + TEF Umlenkspannst. rechts - TEF Gerade auf Linie + TEF Antriebst. links - TEF Gerade + TEF Umlenkspannst. links - - - Anbaugruppen + - Stopper AP + TEF Gerade auf Linie - Scanner + TEF Gerade + + + Anbaugruppen + + Stopper AP + + + + + + Scanner + + + + Bürstenbremse - + - + Spez. Streckenelemente - + - + Türlösungen - + - + Schwenkschienen Schwenkschiene Schiebetür L - + Schwenkschiene Schiebetür R - + Schwenkschiene Schiebetür L mit Sensorik - + Schwenkschiene Schiebetür R mit Sensorik - + - + Verbinder TV W-AP110 kpl - - - - - - TV W-AP60 oben kpl. - - - - - - TV W-W kpl - - - - - - TV W-AP110-W kpl - TV W-AP60 kpl + TV W-AP60 oben kpl. - TV 80 + TV W-W kpl - TV 50 + TV W-AP110-W kpl - Endplatte Al-Profil AP schraubbar + TV W-AP60 kpl - Anschlag AP-Ende für Spulenzug + TV 80 - TV-A für AP110/AP60 kpl + TV 50 - TV-A für AP60/ST + Endplatte Al-Profil AP schraubbar - TV-A für AP110/ST kpl + Anschlag AP-Ende für Spulenzug - TV-SW II für SW-SW + TV-A für AP110/AP60 kpl - TV-SW III für SW-AP110-SW + TV-A für AP60/ST - TV-SW I für SW-AP110 + TV-A für AP110/ST kpl - TV-SW IV für Anschluss SW-AP60 + TV-SW II für SW-SW - TV-SW IV für SW-ST + TV-SW III für SW-AP110-SW - Muffe + TV-SW I für SW-AP110 - - - Boegen fuer Weichen - ~APB 110 R400/45 140 nur fuer Delta + TV-SW IV für Anschluss SW-AP60 + + + + + + TV-SW IV für SW-ST - ~APB 110 R550/45 194 nur fuer Delta + Muffe + + + Boegen fuer Weichen - ~APBW 110 R550/22,5 360x248,5 - - - - - - ~APBW 110 R550/22,5 410x298,5 + ~APB 110 R400/45 140 nur fuer Delta - ~APBW 110 R550/22,5 410x78,5 + ~APB 110 R550/45 194 nur fuer Delta - ~APBW 110 R550/22,5 410x98,5 + ~APBW 110 R550/22,5 360x248,5 - ~APBW 110 R550/67,5 360x598,5 + ~APBW 110 R550/22,5 410x298,5 - ~APBW 110 R400/67,5 260x398,5 + ~APBW 110 R550/22,5 410x78,5 - ~APBW 110 R550/45 77x160 + ~APBW 110 R550/22,5 410x98,5 - ~APBW 110 R550/67,5 125x83,5 + ~APBW 110 R550/67,5 360x598,5 - ~APBW 110 R750/90 200x290 + ~APBW 110 R400/67,5 260x398,5 - ~APBW 110 R650/90 300x190 + ~APBW 110 R550/45 77x160 - ~APBW 110 R550/67,5 208x347 + ~APBW 110 R550/67,5 125x83,5 - ~APBW 110 R550/67,5 58x497 + ~APBW 110 R750/90 200x290 - - - Gerüst - Rohr-Gerüst-Traeger + ~APBW 110 R650/90 300x190 + + + + + + ~APBW 110 R550/67,5 208x347 + + + + + + ~APBW 110 R550/67,5 58x497 + + + Gerüst - Säulen - - - - - - Rohrabhänger - - - - - - Wandbefestigung + Rohr-Gerüst-Traeger - Gatterträger + Säulen - - - - Funktionen - Traeger beschriften + Rohrabhänger + + + + + + Wandbefestigung + + Gatterträger + + + + + - + + Funktionen + + Traeger beschriften + + + + + + Lager Geschoss anlegen - + Aktives Geschoss - + Geschoss kopieren - + Lagerbereich (Auto-Fuellung) - + Regalreihen einzeln - + Gaenge einzeln - + Bearbeiten - + + + Darstellung aktualisieren + + + + Regale zaehlen - + Regelprofil anzeigen - + Export Lager-JSON - + - + HW Planung Materialfluss erzeugen - + Symbole erzeugen - + Symbole nummerieren - + - + SPS - - + + Eingang - + Ausgang - + SPS Schliessen - + - + TRO Marker einfuegen - + Marker bearbeiten - + Bearbeiten (Auto) - + - + Connections Verbindung einfuegen - + Verbindung bearbeiten - + Bearbeiten (Auto) - + - + Export Hoehen-Check (Montagehoehe/Buehne) - + Export Sivas - + Export CSV - - - - - - - Konfiguration - - Umschalten 2D und 3D - - - - - - Alle Bloecke auf 2D + + + Konfiguration - Alle Bloecke auf 3D - - - - - - Sprache + Umschalten 2D und 3D - Planquadrate an/aus + Alle Bloecke auf 2D - CSV-Export + Alle Bloecke auf 3D - - - Werkzeuge - Bloecke zaehlen + Sprache + + + + + + Planquadrate an/aus - Bloecke loeschen + CSV-Export + + + Werkzeuge + + Bloecke zaehlen + + + + + + Bloecke loeschen + + + + Attribute ersetzen - + Text ersetzen - + Text parallel beschriften - + Texthoehe aendern - + Textstil aendern - + Faehnchen + Stueckliste aus Zeichnung - + Din Formate - + - + Tests alle Tests ausfuehren und exportieren - + Tests ausfuehren und stehen lassen - + Export CSV/Sivas ALL - + Kreisel - + Foerderer - + Foerderer-Linienzug - + Omniflo - + Omniflo Strecke - + Gefaellestrecke - + Mubea Gesamtmodell - + HundM05 Kreisel-Abschnitt - + Dematic/Arvato Flowpuffer (Vorlage) - + ILS 3.0 Showroom (Vorlage) - + Testanlage test_system - + KS 2D/3D pruefen (CSV) - + - + POP501 SSG_LIB Edit Context Kreisel bearbeiten - + Eckrad bearbeiten - + Omniflo Element bearbeiten - + Gefaellestrecke bearbeiten - + VarioFoerderer bearbeiten - + TRO-Marker bearbeiten - + Verbindung bearbeiten - + SSG Bearbeiten (Auto) - + diff --git a/menu/SSG_LIB.mnu b/menu/SSG_LIB.mnu index 874672e..644e8cb 100644 --- a/menu/SSG_LIB.mnu +++ b/menu/SSG_LIB.mnu @@ -49,25 +49,32 @@ [->Boegen APB60] [<-90]^C^C(ssg-ensure "OmniModulInsert") OMNI_APB60_90 [->Weichen] -[Einfach 90]^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Einfach -[Doppel 90]^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Doppel -[Dreiwege 90]^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Dreiwege -[--] -[Einfach 45]^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Einfach -[Doppel 45]^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Doppel -[Dreiwege 45]^C^C(ssg-ensure "OmniModulInsert") OMNI_W45_Dreiwege -[--] -[Einfach Parallel]^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Einfach -[Doppel Parallel]^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Doppel -[Dreiwege Parallel]^C^C(ssg-ensure "OmniModulInsert") OMNI_WP_Dreiwege -[--] -[Einfach 22.5]^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Einfach -[Doppel 22.5]^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Doppel -[Dreiwege 22.5]^C^C(ssg-ensure "OmniModulInsert") OMNI_WK_Dreiwege +[Weichen 90]^C^C(ssg-ensure "OmniModulInsert") OMNI_W90 +[Weichen 45]^C^C(ssg-ensure "OmniModulInsert") OMNI_W45 +[Weichen Parallel]^C^C(ssg-ensure "OmniModulInsert") OMNI_WP +[Weichen 22.5]^C^C(ssg-ensure "OmniModulInsert") OMNI_WK [--] [Delta 1600/800]^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Delta_1600 [Delta 1400/700]^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Delta_1400 [<-Star 1400/1400]^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Star +[->Weichenbatterien] +[Weiche S C L1S 1C 200/1200/950 mit M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372536 +[Weiche S C L1S 1C 200/1200/950 mit P]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372537 +[Weiche S C L1S 2C 200/1200/950 mit M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372512 +[Weiche S C L1S 2C 200/1200/950 mit P]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372513 +[Weiche S C L2S 2C 200/1200/950 mit M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372524 +[Weiche S C L2S 2C 200/1200/950 mit P]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372525 +[Weiche S C L2S 3C 200/1400/950 mit M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372500 +[Weiche S C L2S 3C 200/1400/950 mit P]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372501 +[--] +[Weiche S C R1S 1C 200/1200/950 mit M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372539 +[Weiche S C R1S 1C 200/1200/950 mit P]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372540 +[Weiche S C R1S 2C 200/1200/950 mit M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372515 +[Weiche S C R1S 2C 200/1200/950 mit P]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372516 +[Weiche S C R2S 2C 200/1200/950 mit M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372527 +[Weiche S C R2S 2C 200/1200/950 mit P]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372528 +[Weiche S C R2S 3C 200/1400/950 mit M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372503 +[<-Weiche S C R2S 3C 200/1400/950 mit P]^C^C(ssg-ensure "OmniModulInsert") OMNI_WB_834372504 [->TEF Elemente] [TEF Antriebst. rechts]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebR [TEF Umlenkspannst. rechts]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkR @@ -143,6 +150,7 @@ [Gaenge einzeln]^C^C(ssg-ensure "LagerInsert") LG_GANG [Bearbeiten]^C^C(ssg-ensure "LagerInsert") LG_EDIT [--] +[Darstellung aktualisieren]^C^C(ssg-ensure "LagerInsert") LG_DARSTELLUNG [Regale zaehlen]^C^C(ssg-ensure "LagerInsert") LG_REGALE [Regelprofil anzeigen]^C^C(ssg-ensure "LagerPruefung") LG_REGELN [<-Export Lager-JSON]^C^C(ssg-ensure "LagerInsert") LAGER_EXPORT diff --git a/tests/test_lager.lsp b/tests/test_lager.lsp index b849d5a..78f830c 100644 --- a/tests/test_lager.lsp +++ b/tests/test_lager.lsp @@ -79,12 +79,28 @@ (mapcar '(lambda (ed) (cons (cdr (assoc 2 ed)) T)) (vl-remove-if-not '(lambda (ed) (= (cdr (assoc 0 ed)) "ATTDEF")) (lg-blockdef-objekte bname)))) +;; Objekte eines Typs (Wildcard) auf einem Layer. +(defun tlg-auf-layer (typ layer / ss i erg) + (setq erg nil) + (if (setq ss (ssget "_X" (list (cons 0 typ) (cons 8 layer)))) + (progn (setq i 0) + (repeat (sslength ss) (setq erg (cons (ssname ss i) erg) i (1+ i))))) + erg) + +;; Laenge einer offenen Polylinie (Punktliste). +(defun tlg-linienlaenge (pts / s) + (setq s 0.0) + (while (cdr pts) + (setq s (+ s (distance (list (car (car pts)) (cadr (car pts))) (list (car (cadr pts)) (cadr (cadr pts))))) + pts (cdr pts))) + s) + ;; Geschoss-Objekt Nr. nr aus den geparsten Export-Daten. (defun tlg-export-geschoss (daten nr) (vl-some '(lambda (g) (if (= (ssg-json-get g "nr") nr) g)) (ssg-json-get daten "geschosse"))) -(defun lager:tests ( / k0 k1 g0 g1 kb bereich reihen gaenge r0 neu raw daten pfad f eg0 eg1 kr - kb2 b2 kinder mg mg2 hg alt eb +(defun lager:tests ( / k0 k1 g0 g1 kb bereich reihen gaenge r0 neu raw daten pfad f eg0 eg1 kr sl + kb2 b2 kinder mg mg2 hg alt eb mr ba 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) @@ -154,7 +170,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 +190,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 +207,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)) @@ -228,6 +244,39 @@ (setq mg2 (lg-linie-neu-aufbauen mg (lg-wert-setzen (ssg-attrib-read mg) "BELAG" "spanplatte"))) (tlg-eq "manuell: belag geaendert" "LG_GANG_4000_1000_SPANPLATTE" (if mg2 (cdr (assoc 2 (entget mg2))))) (tlg-eq "manuell: bleibt kind" T (if (member mg2 (lg-bereich-kinder b2)) T nil)) + ;; Manueller Gang IM Nord-Randgang: Neuberechnung legt keinen Randgang darueber + (setq mr (lg-gang-einfuegen '(21000.0 5500.0 0.0) '(23000.0 5500.0 0.0) + (list (cons "GESCHOSS" "1") (cons "BREITE_mm" "1000") (cons "ART" "randgang") + (cons "BELAG" "gitterrost")))) + (lg-bereich-fuellen b2) + (tlg-eq "randgang: manueller bleibt" T (if (entget mr) T nil)) + (tlg-eq "randgang: kein ueberlappender auto-randgang" nil + (vl-some '(lambda (k / bb) + (setq bb (ssg-poly-bbox (lg-linie-polygon k))) + (if (and (= (tlg-attr k "QUELLE") "auto") + (> (- (min (car (cadr bb)) 23000.0) (max (car (car bb)) 21000.0)) 1.0) + (> (- (min (cadr (cadr bb)) 6000.0) (max (cadr (car bb)) 5000.0)) 1.0)) + k)) + (tlg-nur (lg-bereich-kinder b2) "LG_GANG_*"))) + (tlg-eq "randgang: nord ausgespart (2 stuecke + sued)" 3 + (tlg-anzahl-art (vl-remove-if-not '(lambda (k) (= (tlg-attr k "QUELLE") "auto")) (lg-bereich-kinder b2)) + "randgang")) + ;; Belag des Bereichs aendern: vorhandene Gaenge werden umgestellt, nichts neu gelegt + (setq ba (ssg-attrib-read b2) n-kinder (length (lg-bereich-kinder b2))) + (tlg-eq "uebertragen: geaendert" T + (> (lg-bereich-attribute-uebertragen b2 ba (lg-wert-setzen ba "BELAG" "gitterrost")) 0)) + (setq kinder (lg-bereich-kinder b2)) + (tlg-eq "uebertragen: anzahl gleich" n-kinder (length kinder)) + (tlg-eq "uebertragen: alle gitterrost" (length (tlg-nur kinder "LG_GANG_*")) + (tlg-anzahl-attr (tlg-nur kinder "LG_GANG_*") "BELAG" "gitterrost")) + (tlg-eq "uebertragen: manuell bleibt manuell" 2 (tlg-anzahl-attr kinder "QUELLE" "manuell")) + ;; Zustand fuer die folgenden Tests wiederherstellen + (lg-bereich-attribute-uebertragen b2 (lg-wert-setzen ba "BELAG" "gitterrost") ba) + (tlg-eq "uebertragen: zurueck auf spanplatte" 0 + (tlg-anzahl-attr (tlg-nur (lg-bereich-kinder b2) "LG_GANG_*") "BELAG" "gitterrost")) + (entdel (vl-some '(lambda (k) (if (wcmatch (cdr (assoc 2 (entget k))) "LG_GANG_2000_1000_*") k)) + (lg-bereich-kinder b2))) + (lg-bereich-fuellen b2) ;; Hallenboden: keine Schraffur; ausserhalb jedes Bereichs: nicht verknuepft (setq hg (lg-gang-einfuegen '(40000.0 0.0 0.0) '(42000.0 0.0 0.0) (list (cons "GESCHOSS" "1") (cons "BREITE_mm" "1500") (cons "ART" "gang") @@ -281,6 +330,26 @@ (ssg-json-get daten "bereiche")) "unter_reihe")) + ;; --- Darstellung der Sicherung (G1): Schraffur je Reihe, Rand nur an offenen Kanten --- + (lg-darstellung-geschoss 1) + (setq sl (lg-layer-name (car (lg-layer-basis "sicherung")) 1)) + (tlg-eq "darstellung: korb-schraffuren" (length kr) + (length (vl-remove-if-not '(lambda (e) (= (cdr (assoc 2 (entget e))) "ANSI38")) + (tlg-auf-layer "HATCH" sl)))) + (tlg-eq "darstellung: alle reihen schraffiert" (length (tlg-gs "LG_REIHE_*" 1)) + (length (tlg-auf-layer "HATCH" sl))) + (tlg-eq "darstellung: randlaenge = offene kanten" + (apply '+ (mapcar '(lambda (r) (+ (ssg-json-get (ssg-json-get r "gitterkorb") "offen_laengs_mm") + (ssg-json-get (ssg-json-get r "gitterkorb") "offen_stirn_mm"))) + kr)) + (apply '+ (mapcar '(lambda (e) (tlg-linienlaenge (ssg-lwpoly-punkte e))) + (tlg-auf-layer "LWPOLYLINE" sl)))) + (setq n3 (length (tlg-auf-layer "*" sl))) + (lg-darstellung-geschoss 1) + (tlg-eq "darstellung: kein doppeltes zeichnen" n3 (length (tlg-auf-layer "*" sl))) + (tlg-eq "darstellung: hallenboden ohne" 0 + (lg-darstellung-geschoss 0)) + (setq pfad (strcat (getenv "DXFMAKRO") "/tests/output/lager_tests_lager.json")) (if (setq f (open pfad "w")) (progn (princ raw f) (close f))) @@ -326,12 +395,14 @@ (setq nr (tlg-attr b "NR")) (vl-every '(lambda (k) (= (tlg-attr k "BEREICH") nr)) (lg-bereich-kinder b))) (tlg-gs "LG_BEREICH" 2))) - ;; Belag folgt dem Geschoss (Spanplatte -> Gitterrost), Hallenboden-Gang bleibt + ;; ALLE Gaenge bekommen den gewaehlten Belag (Gitterrost) - auch manuelle + ;; und der Hallenboden-Gang (tlg-eq "kopie: belag folgt" 0 (tlg-anzahl-attr gg2 "BELAG" "spanplatte")) + (tlg-eq "kopie: alle gaenge neuer belag" (length gg2) (tlg-anzahl-attr gg2 "BELAG" "gitterrost")) (tlg-eq "kopie: manueller gang gitterrost" 1 (length (tlg-nur (vl-remove-if-not '(lambda (e) (= (tlg-attr e "QUELLE") "manuell")) gg2) "LG_GANG_4000_1000_GITTERROST"))) - (tlg-eq "kopie: hallenboden bleibt" 1 (length (tlg-nur gg2 "LG_GANG_2000_1500_HALLENBODEN"))) + (tlg-eq "kopie: hallenboden-gang folgt" 1 (length (tlg-nur gg2 "LG_GANG_2000_1500_GITTERROST"))) (tlg-eq "kopie: bereich belag" T (vl-every '(lambda (b) (= (tlg-attr b "BELAG") "gitterrost")) (tlg-gs "LG_BEREICH" 2))) (tlg-eq "kopie: unter_reihe gitterkorb" 1 (tlg-anzahl-attr (tlg-gs "LG_BEREICH" 2) "UNTER_REIHE" "gitterkorb")) diff --git a/tests/test_unit.lsp b/tests/test_unit.lsp index a7067af..447dbea 100644 --- a/tests/test_unit.lsp +++ b/tests/test_unit.lsp @@ -1218,6 +1218,75 @@ (tu-eq "omni:verbinder-pfad/trenner" "C:/x/data/omniflo/Verbinder/VB_ENDP_AP.dwg" (omni:verbinder-pfad "C:/x/data/" "VB_ENDP_AP")) + + ;; Aehnlichkeit: Gegenstueck (nur L/R bzw. M/P anders) schlaegt andere Groesse + (tu-eq "omni:profil-aehnlichkeit/gleich" 5 (omni:profil-aehnlichkeit "ABCDE" "ABCDE")) + (tu-eq "omni:profil-aehnlichkeit/laenge" 2 (omni:profil-aehnlichkeit "ABC" "ABCD")) + (tu-eq "omni:profil-aehnlichkeit/kein-string" 0 (omni:profil-aehnlichkeit nil "ABC")) + (tu-true "omni:profil-aehnlichkeit/lr-vor-groesse" + (> (omni:profil-aehnlichkeit "WEICHE S 45-L-400/750, KPL. MIT M" + "WEICHE S 45-R-400/750, KPL. MIT M") + (omni:profil-aehnlichkeit "WEICHE S 45-L-400/750, KPL. MIT M" + "WEICHE S 45-R-350/700, KPL. MIT M"))) + + ;; Vorwahl-Index: exakte Sivasnr, sonst Gegenstueck nach Filterwechsel + (setq _wl + '((("Sivasnr" . 1) ("ProfilTyp" . "WEICHE S 45-L-350/700, KPL. MIT M")) + (("Sivasnr" . 2) ("ProfilTyp" . "WEICHE S 45-L-400/750, KPL. MIT M")) + (("Sivasnr" . 3) ("ProfilTyp" . "WEICHE S 45-R-400/750, KPL. MIT M")))) + (tu-eq "omni:vorwahl-index/sivasnr" 2 + (omni:vorwahl-index '(("Sivasnr" . 3) ("ProfilTyp" . "egal")) _wl)) + (tu-eq "omni:vorwahl-index/gegenstueck-lr" 1 + (omni:vorwahl-index + '(("Sivasnr" . 9) ("ProfilTyp" . "WEICHE S 45-L-400/750, KPL. MIT P")) _wl)) + ;; P mit TEF -> M ohne TEF: gleiche Groesse statt der kuerzeren 350/700 + (tu-eq "omni:vorwahl-index/tef-nach-m" 1 + (omni:vorwahl-index + '(("Sivasnr" . "834372008+0_BG190090") + ("ProfilTyp" . "WEICHE S 45-L-400/750, KPL. MIT P mit TEF Ihnen")) + (list (car _wl) (cadr _wl)))) + (tu-eq "omni:vorwahl-index/batterie" 1 + (omni:vorwahl-index + '(("Sivasnr" . 834372536) ("ProfilTyp" . "Weiche S C L1S 1C 200/1200/950 mit M")) + '((("Sivasnr" . 834372540) ("ProfilTyp" . "Weiche S C R1S 1C 200/1200/950 mit P")) + (("Sivasnr" . 834372539) ("ProfilTyp" . "Weiche S C R1S 1C 200/1200/950 mit M")) + (("Sivasnr" . 834372515) ("ProfilTyp" . "Weiche S C R1S 2C 200/1200/950 mit M"))))) + (tu-nil "omni:vorwahl-index/leer" (omni:vorwahl-index (car _wl) nil)) + (tu-nil "omni:vorwahl-index/ohne-ziel" (omni:vorwahl-index nil _wl)) + + ;; Richtungs-Radiobuttons: KurvenRichtung 1/2/3/7 -> Tile-Key + (tu-eq "omni:weichen-richtung-key/links" "ri_links" (omni:weichen-richtung-key "1")) + (tu-eq "omni:weichen-richtung-key/rechts" "ri_rechts" (omni:weichen-richtung-key "2")) + (tu-eq "omni:weichen-richtung-key/doppel" "ri_doppel" (omni:weichen-richtung-key "3")) + (tu-eq "omni:weichen-richtung-key/dreiwege" "ri_dreiwege" (omni:weichen-richtung-key "7")) + (tu-nil "omni:weichen-richtung-key/unbekannt" (omni:weichen-richtung-key "5")) + + ;; Basisliste eines Winkel-Dialogs: Einzel/Doppel/Dreiwege gemeinsam, + ;; Deltaweiche (ebenfalls KurvenRichtung 3) bleibt draussen + (setq _wk + '((("Sivasnr" . 1) ("KurvenWinkel" . 90) ("WeichenTyp" . "Einzelweiche") ("KurvenRichtung" . 1) ("Schaltungstyp" . "M")) + (("Sivasnr" . 2) ("KurvenWinkel" . 90) ("WeichenTyp" . "Einzelweiche") ("KurvenRichtung" . 2) ("Schaltungstyp" . "P")) + (("Sivasnr" . 3) ("KurvenWinkel" . 90) ("WeichenTyp" . "Doppelweiche") ("KurvenRichtung" . 3) ("Schaltungstyp" . "M")) + (("Sivasnr" . 4) ("KurvenWinkel" . 90) ("WeichenTyp" . "Dreiwegeweiche") ("KurvenRichtung" . 7) ("Schaltungstyp" . "P")) + (("Sivasnr" . 5) ("KurvenWinkel" . 90) ("WeichenTyp" . "Deltaweiche") ("KurvenRichtung" . 3) ("Schaltungstyp" . "M") ("Breite" . 1400)) + (("Sivasnr" . 6) ("KurvenWinkel" . 45) ("WeichenTyp" . "Doppelweiche") ("KurvenRichtung" . 3) ("Schaltungstyp" . "M")))) + (setq _bl (omni:weichen-basis-liste _wk 90 *omni-weichen-std-typen* nil)) + (tu-eq "omni:weichen-basis-liste/std-typen" '(1 2 3 4) + (mapcar '(lambda (e) (cdr (assoc "Sivasnr" e))) _bl)) + (tu-eq "omni:weichen-basis-liste/typ-string" 1 + (length (omni:weichen-basis-liste _wk 90 "Doppelweiche" nil))) + (tu-eq "omni:weichen-basis-liste/breite" 1 + (length (omni:weichen-basis-liste _wk nil "Deltaweiche" 1400))) + (tu-eq "omni:weichen-basis-liste/alle" 6 + (length (omni:weichen-basis-liste _wk nil nil nil))) + + ;; Filter ueber die neuen Richtungen + (tu-eq "omni:weichen-filter-liste/doppel" 3 + (cdr (assoc "Sivasnr" (car (omni:weichen-filter-liste _bl "alle" "3"))))) + (tu-eq "omni:weichen-filter-liste/dreiwege" 4 + (cdr (assoc "Sivasnr" (car (omni:weichen-filter-liste _bl "alle" "7"))))) + (tu-nil "omni:weichen-filter-liste/dreiwege-m" + (omni:weichen-filter-liste _bl "M" "7")) ) @@ -3312,9 +3381,38 @@ ;; --- Geschoss kopieren --- (setq _kand2 (list (list 1 0.0 _sq0) (list 2 3100.0 _sq0))) + ;; Kopie: ALLE Gaenge bekommen den gewaehlten Belag, auch abweichende (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-eq "lg-kopie-belag/eigen" "spanplatte" (lg-kopie-belag "gitterrost" "hallenboden" "spanplatte")) + (tu-eq "lg-kopie-belag/ohne-wahl" "gitterrost" (lg-kopie-belag "gitterrost" "hallenboden" "")) (tu-nil "lg-kopie-belag/nil" (lg-kopie-belag nil "hallenboden" "spanplatte")) + ;; Randgang an Sperrflaechen (manueller Gang) beschnitten + (tu-eqf "lg-randgang-stuecke/geteilt" + '(((0.0 5800.0) (4000.0 5800.0)) ((5000.0 5800.0) (10000.0 5800.0))) + (lg-randgang-stuecke '(0.0 5800.0) '(10000.0 5800.0) 400.0 + '(((4000.0 5500.0) (5000.0 5500.0) (5000.0 6000.0) (4000.0 6000.0))) 100.0)) + (tu-eqf "lg-randgang-stuecke/frei" '(((0.0 5800.0) (10000.0 5800.0))) + (lg-randgang-stuecke '(0.0 5800.0) '(10000.0 5800.0) 400.0 nil 100.0)) + (tu-nil "lg-randgang-stuecke/ganz-ueberdeckt" + (lg-randgang-stuecke '(0.0 5800.0) '(10000.0 5800.0) 400.0 + '(((-10.0 5500.0) (10010.0 5500.0) (10010.0 6000.0) (-10.0 6000.0))) 100.0)) + (setq _fr (lg-fuellung-berechnen '((0.0 0.0) (10000.0 0.0) (10000.0 6000.0) (0.0 6000.0)) + (list (cons "rand" '(("N" . 1000.0) ("O" . 0.0) ("S" . 0.0) ("W" . 0.0))) + (cons "sperr" '(((4000.0 5000.0) (5000.0 5000.0) (5000.0 6000.0) (4000.0 6000.0))))))) + (tu-eq "lg-fuellung/randgang-ausgespart" 2 + (length (vl-remove-if-not '(lambda (r) (= (car r) "randgang")) (car _fr)))) + ;; Bereich bearbeiten: nur Geometrie fuehrt zur Neuberechnung + (setq _ba '(("GANGBREITE_mm" . "1000") ("REGALTIEFE_mm" . "700") ("BELAG" . "spanplatte") + ("HAENGEEBENEN" . "2300/1200") ("RANDGANG_N_mm" . "0"))) + (tu-nil "lg-bereich-geometrie/belag" + (lg-bereich-geometrie-geaendert-p _ba (lg-wert-setzen (lg-wert-setzen _ba "BELAG" "gitterrost") + "HAENGEEBENEN" "2400/1000"))) + (tu-nil "lg-bereich-geometrie/gleich-zahl" + (lg-bereich-geometrie-geaendert-p _ba (lg-wert-setzen _ba "GANGBREITE_mm" "1000.0"))) + (tu-eq "lg-bereich-geometrie/gangbreite" T + (lg-bereich-geometrie-geaendert-p _ba (lg-wert-setzen _ba "GANGBREITE_mm" "1200"))) + (tu-eq "lg-bereich-geometrie/randgang" T + (lg-bereich-geometrie-geaendert-p _ba (lg-wert-setzen _ba "RANDGANG_N_mm" "1600"))) (setq _w (lg-kopie-werte '(("ID" . "2A") ("GESCHOSS" . "1") ("LAYER" . "LG_Gang_G1") ("LAENGE" . "9000") ("BREITE_mm" . "1000") ("ART" . "gang") ("BELAG" . "hallenboden") ("BEREICH" . "3") ("QUELLE" . "manuell")) @@ -3415,8 +3513,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 +3567,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 +3590,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 +3604,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 @@ -3501,6 +3635,43 @@ (tu-eqf "lg-offene-kanten/abstand" '((8000.0 1400.0) (8000.0 1400.0)) (lg-reihen-offene-kanten (list _e1 '((0.0 360.0) (4000.0 360.0) (4000.0 1060.0) (0.0 1060.0))) 1.0)) + ;; offene Abschnitte einer Kante + (tu-eqf "lg-kante-offen-intervalle/frei" '((0.0 4000.0)) + (lg-kante-offen-intervalle '((4000.0 350.0) (0.0 350.0)) nil 1.0)) + (tu-nil "lg-kante-offen-intervalle/ganz-zu" + (lg-kante-offen-intervalle '((4000.0 350.0) (0.0 350.0)) (list _e2) 1.0)) + ;; _e3 liegt auf x 2000..6000 an; Kante laeuft von x 4000 nach 0 + (tu-eqf "lg-kante-offen-intervalle/halb" '((2000.0 4000.0)) + (lg-kante-offen-intervalle '((4000.0 1050.0) (0.0 1050.0)) (list _e3) 1.0)) + ;; Darstellung der Sicherung: Ruecken an Ruecken -> keine Abgrenzung dazwischen + (setq _sg (lg-sicherung-geometrie (list (list _e1 "gitterkorb") (list _e2 "gitterkorb")) 1.0)) + (tu-eq "lg-sicherung/flaechen" 2 (length (vl-remove-if-not '(lambda (x) (= (car x) "flaeche")) _sg))) + (tu-eq "lg-sicherung/raender" 6 (length (vl-remove-if-not '(lambda (x) (= (car x) "rand")) _sg))) + (tu-eqf "lg-sicherung/randlaenge = offene kanten" + (apply '+ (mapcar '(lambda (o) (+ (car o) (cadr o))) (lg-reihen-offene-kanten (list _e1 _e2) 1.0))) + (apply '+ (mapcar '(lambda (x) (distance (cadr x) (caddr x))) + (vl-remove-if-not '(lambda (x) (= (car x) "rand")) _sg)))) + (tu-eq "lg-sicherung/keine-abgrenzung-auf-beruehrlinie" T + (not (vl-some '(lambda (x) (and (= (car x) "rand") + (equal (cadr (cadr x)) 350.0 1e-6) + (equal (cadr (caddr x)) 350.0 1e-6))) + _sg))) + ;; Gitterrost ohne Rand, "keine" ohne alles - schliesst aber die Kante des Korbs + (tu-eq "lg-sicherung/gitterrost-keine" + '(("flaeche" . "gitterrost")) + (mapcar '(lambda (x) (cons (car x) (cadr x))) + (lg-sicherung-geometrie (list (list _e1 "gitterrost") (list _e2 "keine")) 1.0))) + (tu-eq "lg-sicherung/nachbar-ohne-sicherung" 3 + (length (vl-remove-if-not '(lambda (x) (= (car x) "rand")) + (lg-sicherung-geometrie (list (list _e1 "gitterkorb") (list _e2 "keine")) 1.0)))) + ;; Farben und Gang-Belag + (tu-eq "lg-farbe-dxf/aci" '((62 . 3)) (lg-farbe-dxf 3)) + (tu-eq "lg-farbe-dxf/rgb" '((420 . 16744448)) (lg-farbe-dxf "255,128,0")) + (tu-nil "lg-farbe-dxf/nil" (lg-farbe-dxf nil)) + (tu-nil "lg-farbe-dxf/0" (lg-farbe-dxf 0)) + (tu-nil "lg-farbe-dxf/kaputt" (lg-farbe-dxf "1,2")) + (tu-eq "lg-gang-belag-aus-name" "gitterrost" (lg-gang-belag-aus-name "LG_GANG_4000_1000_GITTERROST")) + (tu-nil "lg-gang-belag-aus-name/ohne" (lg-gang-belag-aus-name "LG_GANG_4000_1000")) ;; Gitterkorb vervollstaendigen: Boden, offene Kanten, Seitenflaeche (setq _rk (lg-reihen-gitterkorb-berechnen (list (list 'OBJ (cons "laenge_mm" 4000.0) (cons "tiefe_mm" 700.0) @@ -3520,16 +3691,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))