# Conflicts:
#	CLAUDE.md
This commit is contained in:
Michael Stangl committed 2026-11-06 16:43:22 +01:00
commit 69b0197a05
41 files changed
+2173 -842

No files matched your search

+5 -7
View File
@@ -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_<ARTINR>`: 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_<DIM>.dwg`/`Ausgang_<DIM>.dwg` in data/ils) + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) |
| `Tro_Edit.lsp` | TRO_INSERT, TRO_EDIT | TRO-Marker (Block `TRO_SYM_<Typ>`) 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_<winkel>` -> `KF_LAENGE` -> `KF_AN_<winkel>` (je KS_AUS auf KS_EIN) plus der Draufsicht `KF_2D` EINEN Block `KF_<n>`. Daten `data/json/kettenfoerderer.json`, Dialog `dcl/kettenfoerderer.dcl`. **Geometrie**: 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_<n>` 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_<n>` (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_<Ziffern>`. 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_<n>` zulaesst - die Bausteine `KF_UM_26`, `KF_2D` usw. tragen dasselbe Praefix). **Die Blocknummer wird ueber die Blocktabelle vergeben** (`kf-naechste-nummer` ueberspringt jede Nummer mit vorhandener Block-DEFINITION, wie bei `GF_n`/`VF_n`): nur ueber die Referenzen im Modell zu zaehlen war ein realer Fehler - `KF_EDIT` loescht den alten Block, die Definition lebt aber weiter, `_.-BLOCK` traf auf den vorhandenen Namen, die "Neu definieren?"-Abfrage verschluckte die Folge-Eingaben, und die Einzelteile blieben lose liegen ("Block aufgeloest"). **Sivas-Export** (`[kettenfoerderer]` in cfg/sivas.cfg, `build_kettenfoerderer_details` in export_sivas.py): baugleiche Foerderer werden zu EINER Zeile zusammengefasst (`kettenfoerderer_signature`), die Gruppengroesse traegt Merkmal 353 (entsteht erst aus der Gruppierung, daher Code); Farbe (354) und Antriebsmotor (355) sind ZWEI Merkmale, und jedes merkmalbildende Attribut steht auch in der Signatur, sonst verschmelzen unterschiedlich ausgefuehrte Foerderer. Reine Kerne in `tests/test_unit.lsp` (`tu-tests-kf`); das Modul wird in der MNL vorgeladen, Laufzeit-Messung ueber den dbg-Schalter `kf-zeit` |
| `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 `<dwg>_HW.dxf`): **aktuelle Zeichnung** (Python schreibt eine EINHEITENLOSE Zwischendatei `<dwg>_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) -> `<dwg>_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_<L>_<T>`/`LG_GANG_<L>_<B>_<BELAG>` (Definition je Geometrie wiederverwendet, Werte in den Attributen der Referenz; Kinder tragen XDATA `bereich`; der Belag steht im Gang-Blocknamen, weil die Definition seine Schraffur enthaelt - Muster aus `lager.json belag_schraffur`, per `vla-AddHatch` auf Layer 0/VONBLOCK, `hallenboden` ohne; BricsCAD-`iso.pat` kennt kein `NET`, Gitterrost = `GRID`). Alle tragen `ID`, `GESCHOSS`, `LAYER`. Blockdefinitionen per `entmake` (BLOCK...ENDBLK), Einfuegen per `vla-InsertBlock` in WCS - kein `_.-BLOCK`/`_.INSERT`. **Attribut-Tags haben gemischte Schreibweise** (`HOEHE_BELAG_mm`) - beim Setzen ueber `vla-get-TagString` daher case-insensitiv zuordnen (`lg-wert-fuer-tag`), sonst bleiben diese Attribute still leer (realer Fehler beim Bau). Layer je Geschoss = Basis aus `cfg/layer.cfg [lager]` + `_G<nr>`; `LG_GESCHOSS_AKTIV` friert die uebrigen (2D-Grundrisse liegen uebereinander), aktives Geschoss als `vlax-ldata` (Dictionary `SSG_LAGER`). Geschosszuordnung `lg-geschoss-fuer-punkt-kern`: eine Kontur -> eindeutig, mehrere nur ueber Z unterscheidbar, wenn die Konturen auf verschiedenen Hoehen liegen (3D), sonst nil. Jede Kontur gehoert genau einem Block (vergebene Kontur wird kopiert). Auto-Fuellung `lg-fuellung-berechnen` (reiner Kern, Muster Reihe|Gang|Reihe Ruecken an Ruecken bzw. Reihe|Gang, nur volle Module, Streifen an Unter-/Mittel-/Oberkante gegen die Kontur geschnitten, Quergaenge ausgerichtet und nicht am Reihenende); Bereichs-Edit = Neuaufbau aller Kinder. **Randgaenge** `RANDGANG_N/O/S/W_mm` (Nord = +Y Welt) laufen entlang der echten Konturkanten (`lg-randgang-streifen`, Himmelsrichtung der Aussennormale ueber `lg-kompass`, auch L-Form; Ecken: N/S besitzen sie - konvex O/W kuerzen, einspringend N/S verlaengern) und werden wie manuelle Gaenge (`LG_GANG`, `QUELLE=manuell`, Kern `lg-gang-einfuegen`; per Linie oder Option `Rechteck` = Flaeche mit dem echten BricsCAD-Befehl RECHTECK gezeichnet, inkl. aller seiner Optionen (`lg-rechteck-zeichnen`: `_.RECTANG` + `(command pause)`-Schleife bei CMDECHO 1, Polylinie danach ueber `lg-rechteck-ecken-aus-poly` gelesen und geloescht; nur 4 Ecken ohne Boegen, sonst Meldung), Breite/Lage aus dem Rechteck ueber `lg-gang-aus-ecken`, Schleife `lg-linien-schleife` mit `rechteck-fn`) als **Sperrflaechen** aus Reihen/Haupt-/Quergaengen ausgeschnitten (`ssg-poly-band-x`). **Von Hand Gesetztes loest KEINE Neuberechnung aus**: `LG_REIHE`/`LG_GANG` (`lg-manuell-einfuegen`) und das Bearbeiten einer Reihe/eines Gangs (`lg-linie-neu-aufbauen-sperre`) schneiden nur die eigene Flaeche aus den rangniedrigeren Objekten heraus (`lg-sperre-anwenden`, reiner Kern `lg-linie-zuschnitt`; Rang `lg-quelle-rang`: auto < auto_geaendert < manuell) - frueher fuellte ein manueller Gang den ganzen Bereich neu, dabei kamen geloeschte Objekte zurueck und geaenderte wurden ersetzt. Die ausdrueckliche Neuberechnung (`lg-bereich-fuellen`, Bereich bearbeiten) entfernt nur `QUELLE=auto`; `manuell`/`auto_geaendert`-Kinder und unverknuepfte manuelle Objekte in der Kontur (`lg-manuelle-in-kontur`) bleiben und sperren ihre Flaeche. `lg-blockdef` ergaenzt bei Altbestand fehlende ATTDEFs (Neudefinition + `_.ATTSYNC`). `LAGER_EXPORT` schreibt NUR `<dwg>_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 Line truncated
| `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_<L>_<T>`/`LG_GANG_<L>_<B>_<BELAG>` (Definition je Geometrie wiederverwendet, Werte in den Attributen der Referenz; Kinder tragen XDATA `bereich`; der Belag steht im Gang-Blocknamen, weil die Definition seine Schraffur enthaelt - Muster aus `lager.json belag_schraffur`, per `vla-AddHatch` auf Layer 0/VONBLOCK, `hallenboden` ohne; BricsCAD-`iso.pat` kennt kein `NET`, Gitterrost = `GRID`). Alle tragen `ID`, `GESCHOSS`, `LAYER`. Blockdefinitionen per `entmake` (BLOCK...ENDBLK), Einfuegen per `vla-InsertBlock` in WCS - kein `_.-BLOCK`/`_.INSERT`. **Attribut-Tags haben gemischte Schreibweise** (`HOEHE_BELAG_mm`) - beim Setzen ueber `vla-get-TagString` daher case-insensitiv zuordnen (`lg-wert-fuer-tag`), sonst bleiben diese Attribute still leer (realer Fehler beim Bau). Layer je Geschoss = Basis aus `cfg/layer.cfg [lager]` + `_G<nr>`; `LG_GESCHOSS_AKTIV` friert die uebrigen (2D-Grundrisse liegen uebereinander), aktives Geschoss als `vlax-ldata` (Dictionary `SSG_LAGER`). Geschosszuordnung `lg-geschoss-fuer-punkt-kern`: eine Kontur -> eindeutig, mehrere nur ueber Z unterscheidbar, wenn die Konturen auf verschiedenen Hoehen liegen (3D), sonst nil. Jede Kontur gehoert genau einem Block (vergebene Kontur wird kopiert). Auto-Fuellung `lg-fuellung-berechnen` (reiner Kern, Muster Reihe|Gang|Reihe Ruecken an Ruecken bzw. Reihe|Gang, nur volle Module, Streifen an Unter-/Mittel-/Oberkante gegen die Kontur geschnitten, Quergaenge ausgerichtet und nicht am Reihenende); Bereichs-Edit = Neuaufbau aller Kinder. **Randgaenge** `RANDGANG_N/O/S/W_mm` (Nord = +Y Welt) laufen entlang der echten Konturkanten (`lg-randgang-streifen`, Himmelsrichtung der Aussennormale ueber `lg-kompass`, auch L-Form; Ecken: N/S besitzen sie - konvex O/W kuerzen, einspringend N/S verlaengern) und werden wie manuelle Gaenge (`LG_GANG`, `QUELLE=manuell`, Kern `lg-gang-einfuegen`; per Linie oder Option `Rechteck` = Flaeche mit dem echten BricsCAD-Befehl RECHTECK gezeichnet, inkl. aller seiner Optionen (`lg-rechteck-zeichnen`: `_.RECTANG` + `(command pause)`-Schleife bei CMDECHO 1, Polylinie danach ueber `lg-rechteck-ecken-aus-poly` gelesen und geloescht; nur 4 Ecken ohne Boegen, sonst Meldung), Breite/Lage aus dem Rechteck ueber `lg-gang-aus-ecken`, Schleife `lg-linien-schleife` mit `rechteck-fn`) als **Sperrflaechen** aus Reihen/Haupt-/Quergaengen ausgeschnitten (`ssg-poly-band-x`). **Von Hand Gesetztes loest KEINE Neuberechnung aus**: `LG_REIHE`/`LG_GANG` (`lg-manuell-einfuegen`) und das Bearbeiten einer Reihe/eines Gangs (`lg-linie-neu-aufbauen-sperre`) schneiden nur die eigene Flaeche aus den rangniedrigeren Objekten heraus (`lg-sperre-anwenden`, reiner Kern `lg-linie-zuschnitt`; Rang `lg-quelle-rang`: auto < auto_geaendert < manuell) - frueher fuellte ein manueller Gang den ganzen Bereich neu, dabei kamen geloeschte Objekte zurueck und geaenderte wurden ersetzt. **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 `<dwg>_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 einLine truncated
| `LagerPruefung.lsp` | LG_REGELN | Regelprofile der Lagerplanung: `cfg/stahlbau/regelwerk/<LAND>.json` laden, `erbt_von` aufloesen (`lg-profil-mischen`), je Regel den STRENGSTEN Wert aller zutreffenden Quellen (`lg-regel-aufloesen`: `art` min/max/wert, `bedingung` gegen einen Kontext - fehlt der Schluessel, konservativ einbezogen -, `tabelle` + `tabellen_schluessel`) mit Protokoll. Jede Pruefregel der Lagerplanung wird genau hier implementiert (Python rendert nur). Alle Startwerte `verifiziert: false` |
| `DinFormate.lsp` | DIN_FORMATE | Ersatz fuer das alte ACADSST-Makro `DINFORM.LSP`/`.DCL` (SSG2-Menue "DIN-FORMATE..."): fuegt einen DIN-Rahmen (A0-A3, A4 quer/hoch) und optional einen Schriftkopf (KOPF11, Sprachen DE/EN/FR/IT) per Dialog (`dcl/dinformate.dcl`) ein. Block-DWGs liegen flach in `cfg/rahmen/` (kopiert aus `\\infor-ln\SSG_Tools\ACADSST\KOEPFE` - nur die von DINFORM.LSP tatsaechlich referenzierten Dateien: `A0`/`A1`/`A2`/`A3`/`A4Q`/`A4H.DWG` + `Kopf11`/`Kopf11e`/`Kopf11f`/`Kopf11i.dwg`). Rahmen wird im Zeichenmassstab-Faktor eingefuegt, der Kopf im Faktor/100 (Kopf-DWG ist 100x groesser als die Rahmen-DWGs angelegt) - unveraendert aus dem Original-Massstabsschema uebernommen. Blockdefinitionen werden einmalig per `_.-INSERT ... _X 0` nachgeladen (`dinformate-block-laden`), falls noch nicht in der Zeichnung vorhanden. Lazy geladen ueber `(ssg-ensure "DinFormate")`, Menue: Werkzeuge > Din Formate. |
| `DrawPlanquadrate.lsp` | DRAW_PLANQUADRATE, DELETE_PLANQUADRATE, PLANQUADRATE_TOGGLE | Zeichnet auf Z=0 ein Planquadrat-Linienraster (senkrecht/waagerecht), im Abstand/Zaehlschema der aktiven `[Planquadrate]`-Konfiguration aus `cfg/export.cfg` (dieselbe Quelle wie `lib/export_planquadrat.py` fuer den CSV-Export). Bereich kommt NICHT aus den Zeichnungs-Extents, sondern aus derselben Blockmenge wie EXPORTCSV (`csv:collect-export-blocks`, export.lsp; siehe `plq-export-bbox`): Ursprung (Index 1) UND obere Grenze kommen BEIDE aus der tatsaechlichen Bounding-Box jedes Blocks (`csv:get-bbox`, wie `bbox_columns()`/`planquadrat_column()`/`_bbox_min()` in `lib/export_csv.py` bzw. `lib/export_planquadrat.py`), NICHT aus dem reinen Einfuegepunkt - bei einem gedrehten/exzentrisch eingefuegten Block (z.B. ein um 90 Grad gedrehter Kreisel) kann das Bounding-Box-Zentrum weit vom Einfuegepunkt abweichen; Ursprung und Zellzuordnung muessen auf derselben Referenz beruhen, sonst driften sie auseinander (realer Bug, behoben). Reine Hilfsgeometrie (Kreisel-Umfahrungsboegen als eigene Linien, Texte) zaehlt bewusst nicht mit, sonst weicht das Raster vom CSV-Export ab. `x_origin`/`y_origin` ueberschreiben den Ursprung, Fallback auf EXTMIN/EXTMAX falls keine Export-Bloecke vorhanden sind bzw. `csv:get-bbox` fuer einen Block scheitert. Spalten-/Zeilenzahl wird IMMER aufgerundet auf volle Rasterschritte, damit alle senkrechten Linien auf der letzten waagerechten enden und umgekehrt - das Raster bildet immer ein geschlossenes Rechteck. Zaehlung (alphabetisch/numerisch je Achse) als Text am linken/unteren Rand. Das fertige Raster (Linien+Texte) wird per `_.-BLOCK`/`_.INSERT` zu einem einzigen Block `ZZ_PLANQUADRATE` bei (0,0,0) zusammengefasst. Layer aus `cfg/layer.cfg` (`[allgemein]` Key `planquadrate`, Fallback `ZZ_Planquadrate`). DRAW_PLANQUADRATE entfernt vor dem Neuaufbau zuerst einen evtl. vorhandenen Block (`plq-block-entfernen`: INSERTs loeschen + `_-PURGE _B`), DELETE_PLANQUADRATE ruft nur diese Entfernung auf. PLANQUADRATE_TOGGLE ("Planquadrate an/aus", Menue: Konfiguration) prueft per `tblsearch`/`ssget "X"`, ob der Block existiert, und dispatcht auf Zeichnen bzw. Loeschen. Lazy geladen ueber `(ssg-ensure "DrawPlanquadrate")`, nicht in der Core-Ladereihenfolge. Die Planquadrat-SPALTE im CSV-Export (`export_csv.py::planquadrat_column`/`resolve_origins`, `lib/export_planquadrat.py::compute_planquadrat`/`_bbox_min`) rechnet ebenfalls durchgaengig auf Bounding-Box-Basis (nicht nur Einfuegepunkt) und liefert eine SPANNE ("A/1-J/1") statt nur einer Zelle, wenn ein Element mehr als eine Zelle ueberdeckt (Kreisel, lange VF-/GF-Ketten). |
@@ -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 `<dwg>_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 <plan.json> <out_HW.dxf> --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 <dxf> [--config ...] [--info ...] [--errorfile ...] [--dryrun\|--overwrite]` |
| `lager_yaml_export.py` | Lagerplanung: `<dwg>_lager_raw.json` (LAGER_EXPORT) -> `<dwg>_drawing.yaml` (Overlay im Schema der RFQ-Hand-YAML, nur Zeichnungsfelder, plus `_provenance`/`_conflicts`/`_warnings`) und optional `--nachweis` HTML. `--hand <yaml>` 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 <raw.json> <out.yaml> [--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 <dxf> <data_dir> <output.json> [--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
+658 -124
View File
File diff suppressed because it is too large. Load diff
+279 -161
View File
@@ -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<winkel>_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"
+6 -4
View File
@@ -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_<ARTINR>` (16) | Fertige Weichenbatterien, DWG `data/omniflo/2D/<ARTINR>.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 `<Sivasnr>.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<n>` 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<n>` und IDs sind neu |
| `c:LG_GESCHOSS_KOPIEREN` | Geschoss mit Belagskontur, Bereichen, Reihen und Gaengen 1:1 in ein oder mehrere neue Geschosse kopieren (Dialog `lg_geschoss_kopie`: Quelle - Vorgabe oberstes Geschoss -, Anzahl, Geschosshoehe je Kopie, Belag, Versatz X/Y je Kopie, 0 = deckungsgleich). Alle Gaenge (auch manuelle) bekommen den gewaehlten Belag; Verknuepfungen, Layer `_G<n>` und IDs sind neu |
| `c:LG_BEREICH` | Lagerbereich-Kontur + Dialog `lg_bereich`; Auto-Fuellung mit `LG_REIHE_<L>_<T>` / `LG_GANG_<L>_<B>_<BELAG>`, optional Randgaenge Nord/Ost/Sued/West entlang der Konturkanten (auch L-Form) 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<n>`). Geschieht nach Aenderungen automatisch fuer das betroffene Geschoss |
| `c:LAGER_EXPORT` | `<dwg>_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/<Land>.json`) mit aufgeloesten Werten und Quellen anzeigen |
+1
View File
@@ -190,6 +190,7 @@ geschoss = LG_Geschoss, 7
bereich = LG_Bereich, 4
reihe = LG_Reihe, 3
gang = LG_Gang, 8
sicherung = LG_Sicherung, 30
# ============================================================
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+15 -6
View File
@@ -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<n>), 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}}
}
}
}
+192
View File
@@ -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
}
]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -2
View File
@@ -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;
+2
View File
@@ -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"; }
}
}
+4 -4
View File
@@ -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) |
+90 -30
View File
@@ -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{<kennwert>: {formel, quelle}} } ],
"bereiche": [ { nr, id, handle, layer, geschoss, gangbreite_mm, regaltiefe_mm,
reihen_je_gang, schienen_je_gang, quergang_abstand_mm, quergang_breite_mm,
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_<L>_<T>` | Rechteck L x T um die Schienenlinie, Einfuegepunkt = Reihenanfang | `LAENGE`, `TIEFE_mm`, `HAENGEEBENEN`, `SCHIENEN`, `BEREICH`, `QUELLE` (`auto`/`auto_geaendert`/`manuell`) | `bereich` -> LG_BEREICH (nur Auto-Fuellung) |
| `LG_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_<L>_<T>` | 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_<L>_<B>_<BELAG>` | Rechteck L x B um die Gangachse + Schraffur je Belag (`lager.json belag_schraffur`, Layer 0/VONBLOCK; `hallenboden` ohne) | `LAENGE`, `BREITE_mm`, `ART` (`gang`/`quergang`/`randgang`), `BELAG`, `BEREICH`, `QUELLE` (`auto`/`auto_geaendert`/`manuell`) | `bereich` (Auto-Fuellung und manuelle Gaenge im Bereich) |
`HAENGEEBENEN` = `Schienenhoehe/Warenlaenge;...` ueber Belag, oberste zuerst,
@@ -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<n>` (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.<belag>.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
+14 -2
View File
@@ -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 <Enter = Ende>: ",
"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.",
+14 -2
View File
@@ -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 <Enter = finish>: ",
"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.",
+571 -461
View File
File diff suppressed because it is too large. Load diff
+23 -15
View File
@@ -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
+79 -8
View File
@@ -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"))
+219 -16
View File
@@ -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))