Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros
This commit is contained in:
commit
3c729ea604
16 files changed
+736
-159
No files matched your search
@@ -82,6 +82,7 @@ Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD.
|
||||
| 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 |
|
||||
| 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 |
|
||||
| HW Planung | `HwPlanung` | HW_MATERIALFLUSS (Materialfluss erzeugen), HW_SYMBOLE (Symbole erzeugen, noch Platzhalter) |
|
||||
| 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 |
|
||||
| Konfiguration | `SSG_LIB_Commands` + `DrawPlanquadrate` | SSG_DIM_SWITCH, SSG_SPRACHE, PLANQUADRATE_TOGGLE (DRAW_PLANQUADRATE/DELETE_PLANQUADRATE) |
|
||||
@@ -122,6 +123,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
|
||||
| `TEFInsert.lsp` | TEF_FOERDERER_LINIE | Linie zwischen zwei Punkten zeichnen und mit 1000-mm-TEF-Geraden (`0_B10030`) belegen; Rest ueber ein zurueckversetztes Element, damit der Foerderer exakt am Linienende endet; geneigte Linien per Rz*Ry wie `ssg_ks_insert.lsp` |
|
||||
| `GeruestInsert.lsp` | GERUEST, GERUEST_SAEULEN, GERUEST_ROHRABHAENGER, GERUEST_WANDBEFESTIGUNG, GERUEST_TRAEGER, GERUEST_TRAEGER_BESCHRIFTEN, OMNI_FAHRSTRECKE, OMNI_FAHRSTRECKE_BESCHRIFTEN | Geruest-Baugruppen aus `data/json/geruest.json` konfigurieren und einfuegen. **Ein Dialog je Bereich**: Rohrabhaenger / Saeulen / Wandbefestigung oeffnen NUR ueber ihren eigenen Menuebefehl (`geruest-starten id`, Dialogtitel aus dem ASCII-Feld `titel`); eine Umschaltung im Dialog gibt es nicht (DCL hat kein Reiter-Tile), `GERUEST` ohne Bereich zeigt nur einen Hinweis. Der Dialogstand beginnt je Aufruf frisch. 1"- und 2"-Saeulen liegen in EINER Baugruppe `Saeulen` mit gemeinsamer Anbauteil-Liste; **`teileart` und `dummy` duerfen je Geometrie-Variante ueberschrieben werden** (`geruest-variante-wert`, Variante gewinnt vor Baugruppe; fuer `dummy` ueber `geruest-dummy-wahl`: fehlt die DWG der Variante, Meldung + Rueckfall auf den Baugruppen-Dummy; ist der Dummy zugleich eine Teile-DWG, wird er per `geruest-ohne-pfad` nicht doppelt eingefuegt) - so liefert `R 1"` weiterhin TEILEART `Geruest Saeule 1 Zoll` und die `R 2"`-Varianten `Geruest Saeule 2 Zoll`, die Groessen bleiben im Export also unterscheidbar. **Das Layout steht als Vorlage in `dcl/geruest.dcl`** (bzw. `dcl/geruest_traeger.dcl`); nur die datenabhaengigen Bloecke - ein `radio_button` je Variante (Key `v<i>`, `geruest-radio-key`/`-index`), Mengenfeld + Ankreuzfeld je Anbauteil - werden zur Laufzeit an Markerzeilen `//@NAME@` eingesetzt (`geruest-dcl-ersetzungen` -> `ssg-dcl-vorlage-fuellen` in ssg_core, Temp-Datei, nach `unload_dialog` geloescht). Grund: DCL kann Tiles weder zur Laufzeit erzeugen noch ausblenden, Radiobutton-Labels lassen sich per `set_tile` nicht aendern, und eine `list_box` kann keine Eingabefelder enthalten. Varianten bewusst als Radiobuttons statt `list_box`: BricsCAD zeichnet die Listenspalte nur halb so breit, und ein `tabs`-Wert passt nur schrift-/skalierungsabhaengig. Inhalt: Basis-Variante aus `geometrie_varianten` (Radiobuttons, siehe oben), **Winkel Platte** (0/90 Grad, `*geruest-winkel-werte*`): Ausrichtung der Anbauteile zur Basis - die Teile-DWGs aus oben/unten/sonstiges werden um diesen Winkel um Z gedreht in den Block eingefuegt, Basis und Dummy bleiben ungedreht (`geruest-teile-dwgs-rot`; in Konfigurationen als echter Wert `winkel_platte`, kein Block-Attribut), Laenge (gegen `attribute.Laenge` min/max geprueft, Retry-Schleife), Farbe (`attribute.Teilefarbe`, Freitext bei `frei_option`) und **eine Befestigungsspalte** "Befestigung oben und unten" mit allen `anbaugruppen.befestigung` - die Anzahl ist die GESAMTanzahl je Teil (oben und unten zusammen; Tile-Keys `b<i>`/`bm<i>`, Zustand `*geruest-dlg-bef*`). Unter jedem Teil (auch in Sonstiges) zeigt eine Textzeile "Art.-Nr. ..." die Artikelnummer(n) (`geruest-artnr-anzeige`: Einzelteil -> `sivas_id`, Gruppe -> eindeutige Nummern der Teile; DCL kennt keine Schriftgroesse, darum normale Groesse in eigener Zeile). `anbaugruppen` ist ein Objekt mit zwei Listen: `befestigung` (Befestigungsspalte) und `sonstiges` (Teile, die weder oben noch unten sitzen, z.B. die Saeulen-Haltearme) - letztere bekommen eine eigene Zeile darunter (nur wenn nicht leer), in ARTINR/BEZEICHNUNG nach "unten" als "sonstiges" (`geruest-anbau-liste`; ein altes flaches Array gilt als `befestigung`). **Zwei Mengenfelder im JSON, bewusst verschieden benannt**: `stueckzahl` = wie oft ein Teil TATSAECHLICH geschrieben wird (je Variante bzw. je Satz/Anbauteil, fehlt = 1), `anzahl_vorgabe` = NUR die Vorbelegung des Anzahl-Feldes im Dialog (Anbaugruppen, fehlt = 1); ein Anbauteil wird Anzahl x `stueckzahl` mal geschrieben, bei einer Gruppe (`teile`) zaehlt die Anzahl die Saetze (`geruest-stueckzahl`/`geruest-anzahl-vorgabe`). In Konfigurationen (`befestigung`/`sonstiges`, dazu `winkel_platte`) heisst der gespeicherte Dialogwert `anzahl`. Aeltere Konfigurationen mit getrennten `oben`/`unten`-Listen laden weiter: deren Mengen werden zur Gesamtanzahl addiert (`geruest-konfig-befestigung`), Sonstiges-Teile darin still in die Sonstiges-Zeile umgehaengt (`geruest-konfig-sonstiges`); beim naechsten Speichern steht alles im neuen Format. Baugruppen ohne `attribute`-Block (Wandbefestigung) bekommen Laenge/Farbe gesperrt, Baugruppen ohne Anbauteile bekommen gar keine Spalten (ein leerer DCL-Cluster ist unzulaessig). Im generierten Label wird `"` zu `''` ersetzt (`geruest-dcl-label`) - fuenf Artikelnamen enthalten ein Anfuehrungszeichen, das das DCL-Label sonst vorzeitig beendet und die Datei zerstoert. **Konfigurationen**: gepflegte Bibliothek je Baugruppe unter `konfigurationen` in `geruest.json` (schreibgeschuetzt) plus eigene in `cfg/geruest_user.json` (gitignored, `geruest-user-schreiben`; getrennte Datei, damit Benutzerdaten und versionierte Bibliothek nicht kollidieren). Eigene Eintraege sind in der Liste mit `*` markiert und nur diese loeschbar. **Geaenderte Konfiguration**: beim Anwenden wird der Dialogstand als VergleichsbasLine truncated
|
||||
| `KettenFoerderer.lsp` | KETTENFOERDERER, KF_EDIT, KF_KS_PRUEFEN | Kettenfoerderer/Schraegfoerderer Stahl: baut aus `KF_UM_<winkel>` -> `KF_LAENGE` -> `KF_AN_<winkel>` (je KS_AUS auf KS_EIN) plus der Draufsicht `KF_2D` EINEN Block `KF_<n>`. Daten `data/json/kettenfoerderer.json`, Dialog `dcl/kettenfoerderer.dcl`. **Geometrie**: 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 | Menue "HW Planung" (zwischen Lager und SPS). HW_MATERIALFLUSS ruft EXPORTCSV auf (alte `<dwg>_export.csv` wird vorher geloescht, damit kein veralteter Stand gezeichnet wird) und danach `lib/hw_materialfluss.py` ueber `export:run-python` (Log `DXFM_LOG/hw_materialfluss.log`); Ergebnis ist eine NEUE Datei `DXFM_RESULTS/<dwg>_HW.dxf` (`hw-dxf-name`, getestet), die offene Zeichnung bleibt unveraendert. HW_SYMBOLE ist noch ein Platzhalter (Hinweis) |
|
||||
| `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) |
|
||||
| `LagerInsert.lsp` | LG_GESCHOSS, LG_GESCHOSS_AKTIV, LG_GESCHOSS_KOPIEREN, LG_BEREICH, LG_REIHE, LG_GANG, LG_EDIT, LG_REGALE, LAGER_EXPORT, LAGER_HAND_YAML | Lagerplanung GOH-Buehnenlager -> RFQ-YAML (Phase 0+1: Mengen, 2D; Konzept/Schema/YAML-Zuordnung in `doc/plan/lager_rfq.md`). Bloecke `LG_GESCHOSS` (Kopfsymbol, XDATA `SSG_LG` `kontur` -> Belagskontur), `LG_BEREICH` (Kontur + Parameter, fuellt sich selbst), `LG_REIHE_<L>_<T>`/`LG_GANG_<L>_<B>_<BELAG>` (Definition je Geometrie wiederverwendet, Werte in den Attributen der Referenz; Kinder tragen XDATA `bereich`; der Belag steht im Gang-Blocknamen, weil die Definition seine Schraffur enthaelt - Muster aus `lager.json belag_schraffur`, per `vla-AddHatch` auf Layer 0/VONBLOCK, `hallenboden` ohne; BricsCAD-`iso.pat` kennt kein `NET`, Gitterrost = `GRID`). Alle tragen `ID`, `GESCHOSS`, `LAYER`. Blockdefinitionen per `entmake` (BLOCK...ENDBLK), Einfuegen per `vla-InsertBlock` in WCS - kein `_.-BLOCK`/`_.INSERT`. **Attribut-Tags haben gemischte Schreibweise** (`HOEHE_BELAG_mm`) - beim Setzen ueber `vla-get-TagString` daher case-insensitiv zuordnen (`lg-wert-fuer-tag`), sonst bleiben diese Attribute still leer (realer Fehler beim Bau). Layer je Geschoss = Basis aus `cfg/layer.cfg [lager]` + `_G<nr>`; `LG_GESCHOSS_AKTIV` friert die uebrigen (2D-Grundrisse liegen uebereinander), aktives Geschoss als `vlax-ldata` (Dictionary `SSG_LAGER`). Geschosszuordnung `lg-geschoss-fuer-punkt-kern`: eine Kontur -> eindeutig, mehrere nur ueber Z unterscheidbar, wenn die Konturen auf verschiedenen Hoehen liegen (3D), sonst nil. Jede Kontur gehoert genau einem Block (vergebene Kontur wird kopiert). Auto-Fuellung `lg-fuellung-berechnen` (reiner Kern, Muster Reihe|Gang|Reihe Ruecken an Ruecken bzw. Reihe|Gang, nur volle Module, Streifen an Unter-/Mittel-/Oberkante gegen die Kontur geschnitten, Quergaenge ausgerichtet und nicht am Reihenende); Bereichs-Edit = Neuaufbau aller Kinder. **Randgaenge** `RANDGANG_N/O/S/W_mm` (Nord = +Y Welt) laufen entlang der echten Konturkanten (`lg-randgang-streifen`, Himmelsrichtung der Aussennormale ueber `lg-kompass`, auch L-Form; Ecken: N/S besitzen sie - konvex O/W kuerzen, einspringend N/S verlaengern) und werden wie manuelle Gaenge (`LG_GANG`, `QUELLE=manuell`, Kern `lg-gang-einfuegen`; per Linie oder Option `Rechteck` = Flaeche mit dem echten BricsCAD-Befehl RECHTECK gezeichnet, inkl. aller seiner Optionen (`lg-rechteck-zeichnen`: `_.RECTANG` + `(command pause)`-Schleife bei CMDECHO 1, Polylinie danach ueber `lg-rechteck-ecken-aus-poly` gelesen und geloescht; nur 4 Ecken ohne Boegen, sonst Meldung), Breite/Lage aus dem Rechteck ueber `lg-gang-aus-ecken`, Schleife `lg-linien-schleife` mit `rechteck-fn`) als **Sperrflaechen** aus Reihen/Haupt-/Quergaengen ausgeschnitten (`ssg-poly-band-x`). **Von Hand Gesetztes loest KEINE Neuberechnung aus**: `LG_REIHE`/`LG_GANG` (`lg-manuell-einfuegen`) und das Bearbeiten einer Reihe/eines Gangs (`lg-linie-neu-aufbauen-sperre`) schneiden nur die eigene Flaeche aus den rangniedrigeren Objekten heraus (`lg-sperre-anwenden`, reiner Kern `lg-linie-zuschnitt`; Rang `lg-quelle-rang`: auto < auto_geaendert < manuell) - frueher fuellte ein manueller Gang den ganzen Bereich neu, dabei kamen geloeschte Objekte zurueck und geaenderte wurden ersetzt. Die ausdrueckliche Neuberechnung (`lg-bereich-fuellen`, Bereich bearbeiten) entfernt nur `QUELLE=auto`; `manuell`/`auto_geaendert`-Kinder und unverknuepfte manuelle Objekte in der Kontur (`lg-manuelle-in-kontur`) bleiben und sperren ihre Flaeche. `lg-blockdef` ergaenzt bei Altbestand fehlende ATTDEFs (Neudefinition + `_.ATTSYNC`). `LAGER_EXPORT` schreibt `<dwg>_lager_raw.json` (eigener JSON-Schreiber `lg-json-*`; Geschosse, Bereiche, Reihen, Gaenge) und ruft `lib/lager_yaml_export.py` ueber `export:run-python`. Befehl `LG_REGALE` (Menue Lager -> Regale zaehlen) zaehlt die Regalreihen `LG_REIHE_*` (Anzahl, Laenge, Laenge x Haengeebenen je Geschoss aus den Attributen GESCHOSS/LAENGE/HAENGEEBENEN, reine Kerne `lg-reihe-eintrag`/`lg-reihen-auswerten`). **Der parametrische BricsCAD-Block `goh_rack` wird nicht mehr unterstuetzt** (veraltet, 2026-10-30 aus Zaehlung, Export und Geschoss-Kopie entfernt). Vorgaben aus `data/json/lager.json`. Dialoge `dcl/lager.dcl` ueber den generischen Treiber `lg-dialog` (Feldlisten `*lg-felder-*`, Konsolen-Rueckfall `lg-konsole`, ohne GUI Vorgaben). **Geschoss kopieren** (`LG_GESCHOSS_KOPIEREN`, Dialog `lg_geschoss_kopie`, Kern `lg-geschosse-kopieren`): Quelle (Vorgabe oberstes Geschoss, Erweitern G3 -> G4), Anzahl, Geschosshoehe je Kopie, Belag, Versatz X/Y je Kopie (0 = deckungsgleich; 3D-Zeichnung zusaetzlich +Z). Kein BricsCAD-KOPIEREN (XDATA-Verweise zeigten aufs Original): jedes Objekt entsteht ueber die normalen Einfuegefunktionen neu (`lg-geschoss-anlegen`, `lg-bereich-block-anlegen` = Bereich ohne Fuellung, `lg-linie-einfuegen`), Kinder 1:1 inkl. `auto_geaendert`/manuell, kein Neufuellen; Belaege gleich dem Quell-Geschossbelag folgen dem neuLine truncated
|
||||
| `LagerPruefung.lsp` | LG_REGELN | Regelprofile der Lagerplanung: `cfg/regelwerk/<LAND>.json` laden, `erbt_von` aufloesen (`lg-profil-mischen`), je Regel den STRENGSTEN Wert aller zutreffenden Quellen (`lg-regel-aufloesen`: `art` min/max/wert, `bedingung` gegen einen Kontext - fehlt der Schluessel, konservativ einbezogen -, `tabelle` + `tabellen_schluessel`) mit Protokoll. Jede Pruefregel der Lagerplanung wird genau hier implementiert (Python rendert nur). Alle Startwerte `verifiziert: false` |
|
||||
@@ -220,6 +222,7 @@ Abhaengigkeiten: `ezdxf`, Standard-Library. Benoetigen Umgebungsvariablen (`DXFM
|
||||
| `vf_spec_export.py` | Uebersetzt ein Eingabe-Journal in eine **Spec** und zurueck (`spec_aus_journal` / `journal_aus_spec`) - Gegenstueck zu `vsp-journal` in `Lisp/vf_spec.lsp`, beide muessen dieselbe Tokenfolge liefern. Der Rundlauf `journal_aus_spec(spec_aus_journal(tok)) == tok` laeuft in `tests/test_vf_spec.py` gegen die 5 echten HundM-Ketten und beweist, dass die Spec das Journal verlustfrei abbildet. Schreibt das flache Spec-JSON (vom LISP-Parser lesbar). Objekte der Ziel-Datei, die keine Kette beschreiben (von Hand ergaenzte Anlagenteile mit `function`, z.B. Kreisel), werden beim Neuschreiben unveraendert ans Dateiende uebernommen - sonst waeren sie beim naechsten Lauf weg. Aufruf: `python vf_spec_export.py <protokoll.json> <spec.json>` — erzeugt `tests/testdata/hundm05.json` (Spec, Eingabe fuer `TEST_HUNDM05`/`VF_SPEC_BAU`) aus `tests/testdata/hm_recformat.json` (Aufzeichnung) |
|
||||
| `dxf_anlage_export.py` | Gegenstueck zum Scanner: liest eine mit unseren Makros GEBAUTE (und von Hand nachbearbeitete) Anlage aus der Zeichnung zurueck in Nachbau-Testdaten - je Wrapper genau die Parameter, die auch dessen Edit-Befehl liest (KREISEL_n: Einfuegepunkt, `abstand` exakt aus der Blockdefinition, `drehrichtung` aus DREHRICHTUNG; GF_n: SSG_GF_EDIT + SEITE_AS/ES, endet die GF auf einer Kreisel-Kette, wird dessen Hoehe `hoehe_ende_mm`; VF_n `standard`/`etage`: mubea-Schema wie `vfs-edit-basis-lesen`; VF_n `linienzug`: Journal UNVERAENDERT als `"typ": "linienzug_journal"` - bewusst keine Spec, weil der Bau-Dialog neuer ist als die Spec-Grammatik; uebrige Bloecke als Einzel-Insert ohne `_2D`/`_3D`-Suffix). Reihenfolge Kreisel, VF, GF, Einzelbloecke (VF vor GF wie mubea). Aufruf: `python dxf_anlage_export.py <dxf> <output.json> [--projekt NAME]` — erzeugt `tests/testdata/dematic_arvato.json` aus `Dematic_TST.dxf`. Test `tests/test_dxf_anlage_export.py` |
|
||||
| (`io_zuordnung_pruefen.py`) | **Nicht hier**: die Zuordnung E-Geraete (Sensoren/Aktoren/Motoren) -> Anlagenbauteile (Separator, AS, Kreisel AN8/SP8, Vario-Stationen, Scanner) liegt im Kabeltool-Repo `kabellaengen`: Pruefskript `lib/io_zuordnung_pruefen.py` (`bin\io_zuordnung_pruefen.bat`), Konverter alter `io`-Symbole `lib/altZuNeu.py` (`bin\altZuNeu.bat`), gemeinsames Regelwerk `cfg/io_regeln.json`, Doku `doc/Anwenderdoku_altZuNeu.md`. Die dort erkannten Mechanik-Bloecke sind die dxfmakros-Bloecke (`Separator_SP*`, `AS_Element*`, `AN8_*`/`SP8_*`, `Vario_Motorstation*`/`Vario_Umlenkstation*`, `Scanner*`) - wer sie umbenennt, muss `bauteile` in `io_regeln.json` mitziehen |
|
||||
| `hw_materialfluss.py` | HW-Planung: Materialfluss-Skizze aus dem CSV-Export (EXPORTCSV) als neue DXF, flach in XY. Kreisel/Eckrad = geschlossenes Rechteck (Position/Boundingbox, Merkmal `Drehung`; schraeg: Abstand + 800 mm), Punktfolge in Drehrichtung (UZS = Uhrzeigersinn) plus Pfeile; Strecke/GF = Polylinie AS -> Separatoren -> ES ueber `TrackIds` (ES vorn -> umgedreht) plus Endpfeil; `ILS Weiche` = kleiner Kreis; BTMT Beladung = grosser Kreis K1 + kleiner Kreis K2 + Linie, Entladung = kleiner Kreis K1 + grosser Kreis K2 + Linie (K1/K2 per `decode_trans` aus `export_graph.py`, dessen `load_elements` auch die CSV liest). Layer/Farben aus `cfg/layer.cfg` `[hw_planung]` (eigener Mini-Parser, Vorgaben im Code). Test `tests/test_hw_materialfluss.py`. Aufruf: `python hw_materialfluss.py <export.csv> <out_HW.dxf> [--layer-cfg ...]` |
|
||||
| `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 |
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
;; ============================================================
|
||||
;; HwPlanung.lsp - Hardware-Planung (Menue "HW Planung")
|
||||
;;
|
||||
;; HW_MATERIALFLUSS ("Materialfluss erzeugen"):
|
||||
;; 1. exportiert das aktuelle Hardware-Layout per EXPORTCSV
|
||||
;; (csv:run-export, export.lsp) nach DXFM_RESULTS/<dwg>_export.csv
|
||||
;; 2. ruft lib/hw_materialfluss.py auf, das daraus die Materialfluss-
|
||||
;; Skizze (Kreisel-Rechtecke in Drehrichtung, Strecken-Polylinien
|
||||
;; AS -> Separatoren -> ES, Weichen, Be-/Entladungen) zeichnet
|
||||
;; 3. Ergebnis: DXFM_RESULTS/<dwg>_HW.dxf (neue Datei, die offene
|
||||
;; Zeichnung bleibt unveraendert)
|
||||
;;
|
||||
;; HW_SYMBOLE ("Symbole erzeugen"): noch Platzhalter, zeigt nur einen Hinweis.
|
||||
;;
|
||||
;; Setzt export.lsp voraus (laedt die MNL vor).
|
||||
;; ============================================================
|
||||
|
||||
(setq *hw-skript* "hw_materialfluss.py")
|
||||
|
||||
;; Name der Ausgabedatei aus dem Zeichnungsnamen (reiner Kern, getestet):
|
||||
;; "Mubea.dwg" -> "Mubea_HW.dxf"
|
||||
(defun hw-dxf-name (dwgname)
|
||||
(strcat (vl-filename-base dwgname) "_HW.dxf")
|
||||
)
|
||||
|
||||
(defun c:HW_MATERIALFLUSS ( / label out-dir csv-pfad dxf-pfad py-skript
|
||||
py-exe log-pfad rc)
|
||||
(setq label "HW_MATERIALFLUSS")
|
||||
(if (null (getenv "DXFM_LIB"))
|
||||
(princ (ssg-textf "exp-dxfm-lib-missing" (list label)))
|
||||
(progn
|
||||
(setq out-dir (if *export-test-override*
|
||||
*export-test-override*
|
||||
(getenv "DXFM_RESULTS")))
|
||||
(setq csv-pfad (strcat out-dir "/" (export:dwg-praefix)
|
||||
(export:filename "csv_csv")))
|
||||
(setq dxf-pfad (strcat out-dir "/" (hw-dxf-name (getvar "DWGNAME"))))
|
||||
;; Alte CSV entfernen - sonst wuerde nach einem gescheiterten Export
|
||||
;; still die Skizze aus dem vorigen Stand gezeichnet.
|
||||
(if (findfile csv-pfad) (vl-file-delete csv-pfad))
|
||||
|
||||
(c:EXPORTCSV)
|
||||
|
||||
(if (not (findfile csv-pfad))
|
||||
(princ (ssg-textf "hw-csv-fehlt" (list csv-pfad)))
|
||||
(progn
|
||||
(setq py-skript (strcat (getenv "DXFM_LIB") "/" *hw-skript*))
|
||||
(setq py-exe (export:python-exe))
|
||||
(setq log-pfad (strcat (cond ((getenv "DXFM_LOG")) (out-dir))
|
||||
"/hw_materialfluss.log"))
|
||||
(setq rc (export:run-python py-exe py-skript
|
||||
(list csv-pfad dxf-pfad) log-pfad))
|
||||
(cond
|
||||
((null rc)
|
||||
(princ (ssg-textf "exp-python-call-failed" (list label))))
|
||||
((/= rc 0)
|
||||
(princ (ssg-textf "exp-python-error" (list label rc log-pfad)))
|
||||
(export:log-ausgeben log-pfad 12))
|
||||
(t
|
||||
(export:log-ausgeben log-pfad 12)
|
||||
(princ (ssg-textf "hw-fertig" (list dxf-pfad))))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(princ)
|
||||
)
|
||||
|
||||
(defun c:HW_SYMBOLE ()
|
||||
(alert (ssg-text "hw-symbole-offen"))
|
||||
(princ)
|
||||
)
|
||||
|
||||
(princ "\n>>> HwPlanung.lsp geladen")
|
||||
(princ)
|
||||
+32
-9
@@ -208,19 +208,40 @@
|
||||
;; draw-module verwendet eine vorhandene Definition KREISEL_n_TYP_ABSTAND
|
||||
;; wieder (Edit/Redraw) - ein geaenderter Name kaeme sonst nie in die
|
||||
;; Beschriftung. Wirkt auf alle Referenzen dieser Definition.
|
||||
(defun kreisel-label-aktualisieren (bname textStr / e ed)
|
||||
(defun kreisel-label-aktualisieren (bname textStr winkel / e ed)
|
||||
(setq e (tblobjname "BLOCK" bname))
|
||||
(while (setq e (entnext e))
|
||||
(setq ed (entget e))
|
||||
(if (and (= (cdr (assoc 0 ed)) "TEXT")
|
||||
(/= (cdr (assoc 1 ed)) textStr))
|
||||
(entmod (subst (cons 1 textStr) (assoc 1 ed) ed))
|
||||
(or (/= (cdr (assoc 1 ed)) textStr)
|
||||
(not (equal (cdr (assoc 50 ed)) (kreisel-grad->rad winkel) 1e-6))))
|
||||
(progn
|
||||
(setq ed (subst (cons 1 textStr) (assoc 1 ed) ed))
|
||||
(setq ed (subst (cons 50 (kreisel-grad->rad winkel)) (assoc 50 ed) ed))
|
||||
(entmod ed)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun kreisel-grad->rad (grad)
|
||||
(* grad (/ pi 180.0))
|
||||
)
|
||||
|
||||
;; Textwinkel INNERHALB der Blockdefinition (Grad, reiner Kern, getestet).
|
||||
;; Der Block wird mit `rotation` eingefuegt; die Schrift soll in der Welt von
|
||||
;; unten oder von links lesbar sein, also Weltwinkel in [270,360) und [0,90).
|
||||
;; Liegt der Block im Bereich [90,270) (z.B. horizontal SM / vertikal MS),
|
||||
;; wird die Schrift um 180 Grad um ihren Mittelpunkt gedreht (Text ist
|
||||
;; mittig ausgerichtet, die Mitte bleibt daher stehen).
|
||||
(defun kreisel-label-winkel (rotation / w)
|
||||
(setq w (- rotation (* 360.0 (fix (/ rotation 360.0)))))
|
||||
(if (< w 0.0) (setq w (+ w 360.0)))
|
||||
(if (and (>= w 89.999 ) (< w 269.999)) 180.0 0.0)
|
||||
)
|
||||
|
||||
;; Beschriftungstext erzeugen
|
||||
(defun kreisel-make-label (nummer abstand kreiselart name / textStr insertPoint radius mitteX mitteY textHoehe lay)
|
||||
(defun kreisel-make-label (nummer abstand kreiselart name winkel / textStr insertPoint radius mitteX mitteY textHoehe lay)
|
||||
(setq textStr (kreisel-label-text nummer name kreiselart abstand))
|
||||
|
||||
;; Geometrie berechnen
|
||||
@@ -258,8 +279,8 @@
|
||||
(cons 10 insertPoint)
|
||||
(cons 40 textHoehe)
|
||||
(cons 1 textStr)
|
||||
(cons 50 0.0)
|
||||
(cons 7 "Kreisel_Arial") ;; Arial Textstil
|
||||
(cons 50 (kreisel-grad->rad winkel))
|
||||
(cons 7 "Kreisel_Arial") ;; Arial Textstil
|
||||
(cons 62 *kreisel-beschriftung-farbe*)
|
||||
'(72 . 1) ;; Horizontale Ausrichtung: Mitte
|
||||
'(73 . 2) ;; Vertikale Ausrichtung: Mitte
|
||||
@@ -561,8 +582,9 @@
|
||||
|
||||
;; BESCHRIFTUNG einfügen (vor Block-Erzeugung, damit sie im Block ist)
|
||||
(kreisel-make-label kreisel-nummer abstand (if is-pin "PIN" "STANDARD")
|
||||
(cdr (assoc "Bezeichnung" attribs)))
|
||||
|
||||
(cdr (assoc "Bezeichnung" attribs))
|
||||
(kreisel-label-winkel rotation))
|
||||
|
||||
;; Unsichtbare Attribut-Definitionen erzeugen
|
||||
(ssg-attrib-make-defs *kreisel-attrib-defs* 50.0)
|
||||
|
||||
@@ -593,7 +615,8 @@
|
||||
;; Beschriftung der wiederverwendeten Definition an den Namen anpassen
|
||||
(kreisel-label-aktualisieren bname
|
||||
(kreisel-label-text kreisel-nummer (cdr (assoc "Bezeichnung" attribs))
|
||||
(if is-pin "PIN" "STANDARD") abstand))
|
||||
(if is-pin "PIN" "STANDARD") abstand)
|
||||
(kreisel-label-winkel rotation))
|
||||
;; ebenso die Spiegelung der Drehrichtungspfeile
|
||||
(kreisel-pfeil-aktualisieren bname (cdr (assoc "DREHRICHTUNG" attribs)))
|
||||
)
|
||||
|
||||
+7
-6
@@ -229,14 +229,15 @@ Beispiel:
|
||||
(dbgclose)
|
||||
```
|
||||
|
||||
#### Zentrale Debug-Schalter (default je nach Schalter)
|
||||
#### Zentrale Debug-Schalter (Standard: alle aus)
|
||||
|
||||
Damit `dbg*`-Aufrufe dauerhaft im Code stehen bleiben können, ohne im
|
||||
Normalbetrieb ungeplant `.dbg`-Dateien zu erzeugen, gibt es eine zentrale
|
||||
Schalter-Sammlung (`*dbg-schalter*`, Symbol → 0/1). Eine Routine öffnet ihre
|
||||
Debug-Datei nur, wenn ihr Schalter eingeschaltet ist. Unbekannte/neue Schalter
|
||||
gelten implizit als 0/aus; die VF-Linienzug-Schalter unten sind bewusst mit
|
||||
Default 1/an vorregistriert (siehe Tabelle).
|
||||
gelten implizit als 0/aus. Seit 2026-11-02 stehen auch alle vorregistrierten
|
||||
Schalter auf 0 und `*dbg-active*` auf `nil` - standardmaessig entsteht keine
|
||||
`.dbg`-Datei; zum Debuggen `(dbgon)` bzw. `(dbg-schalter-on "name")`.
|
||||
|
||||
| Funktion | Beschreibung |
|
||||
| --- | --- |
|
||||
@@ -250,9 +251,9 @@ Bekannte Schalter:
|
||||
|
||||
| Schalter | Default | Modul | Loggt nach |
|
||||
| --- | --- | --- | --- |
|
||||
| `"vfl-modus1"` | **AN (1)** | Linienzug Modus 1 (manuelle Eingabe, `vf-linienzug-modus`) | `DXFM_LOG/vfl_modus1.dbg` |
|
||||
| `"vfl-modus2"` | **AN (1)** | Linienzug Modus 2 (3D-Objekte + Ziel-Höhe, `vf-linienzug-modus2`) | `DXFM_LOG/vfl_modus2.dbg` |
|
||||
| `"vfl-modus3"` | **AN (1)** | Linienzug Modus 3 (Vorwärts-Nachbau, `vf-linienzug-modus3`) | `DXFM_LOG/vfl_modus3.dbg` |
|
||||
| `"vfl-modus1"` | aus (0) | Linienzug Modus 1 (manuelle Eingabe, `vf-linienzug-modus`) | `DXFM_LOG/vfl_modus1.dbg` |
|
||||
| `"vfl-modus2"` | aus (0) | Linienzug Modus 2 (3D-Objekte + Ziel-Höhe, `vf-linienzug-modus2`) | `DXFM_LOG/vfl_modus2.dbg` |
|
||||
| `"vfl-modus3"` | aus (0) | Linienzug Modus 3 (Vorwärts-Nachbau, `vf-linienzug-modus3`) | `DXFM_LOG/vfl_modus3.dbg` |
|
||||
|
||||
Alle drei Modi loggen automatisch **jede** interaktive Eingabe, weil sie
|
||||
durchgehend über die gemeinsamen Wrapper `vfl-in-point`/`-string`/`-real`/
|
||||
|
||||
+14
-14
@@ -31,7 +31,8 @@
|
||||
;; Globale Variablen
|
||||
(setq *dbg-path* nil) ; Voller Dateipfad (String)
|
||||
(setq *dbg-indent* 0) ; Aktuelle Einruecktiefe
|
||||
(setq *dbg-active* T) ; Debug-Ausgabe aktiv (Standard: ein)
|
||||
(setq *dbg-active* nil) ; Debug-Ausgabe aktiv (Standard: AUS - keine .dbg-Dateien;
|
||||
; einschalten mit (dbgon) bzw. einem Schalter unten)
|
||||
(setq *dbg-buffer* nil) ; Zeilenpuffer (Liste von Strings)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
@@ -41,8 +42,8 @@
|
||||
;; Neue/unbekannte Schalter (die NICHT unten vorregistriert sind) gelten
|
||||
;; implizit als AUS (0) - so bleiben (dbg-schalter-open "name" ...)-Aufrufe
|
||||
;; im Code stehen, ohne dass beim normalen Arbeiten ungeplant .dbg-Dateien
|
||||
;; entstehen. Die VF-Linienzug-Schalter unten sind bewusst mit Default 1
|
||||
;; (EIN) vorregistriert, siehe Kommentar dort.
|
||||
;; entstehen. Seit 2026-11-02 stehen ALLE vorregistrierten Schalter auf 0
|
||||
;; und *dbg-active* auf nil: standardmaessig wird keine .dbg-Datei geschrieben.
|
||||
;;
|
||||
;; (dbg-schalter-on "vfl-modus3") ; Schalter einschalten (1)
|
||||
;; (dbg-schalter-off "vfl-modus3") ; Schalter ausschalten (0)
|
||||
@@ -54,13 +55,11 @@
|
||||
;; ------------------------------------------------------------
|
||||
(if (not (boundp '*dbg-schalter*)) (setq *dbg-schalter* nil))
|
||||
|
||||
;; VF-Linienzug (Modus 1/2/3) Debug-Schalter, Default 1 (EIN): der Nutzer
|
||||
;; will die Session + alle Eingaben durchgehend geloggt haben, ohne den
|
||||
;; Schalter vor jedem Aufruf manuell einzuschalten. Bei Bedarf einzeln
|
||||
;; abschaltbar: (dbg-schalter-off "vfl-modus1") usw.
|
||||
;; VF-Linienzug (Modus 1/2/3) Debug-Schalter, Default 0 (AUS). Bei Bedarf
|
||||
;; einzeln einschalten: (dbg-schalter-on "vfl-modus1") usw.
|
||||
(foreach nm '("vfl-modus1" "vfl-modus2" "vfl-modus3")
|
||||
(if (not (assoc nm *dbg-schalter*))
|
||||
(setq *dbg-schalter* (cons (cons nm 1) *dbg-schalter*))))
|
||||
(setq *dbg-schalter* (cons (cons nm 0) *dbg-schalter*))))
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; TEMPORAER - Diagnose "gespiegelte Sepliste-Koordinate" (lfdnr=2)
|
||||
@@ -98,8 +97,10 @@
|
||||
;; Zeilen je Test, siehe testrun:log in
|
||||
;; tests/test_run_all.lsp.
|
||||
;; ------------------------------------------------------------
|
||||
(foreach nm '(("vf-sepliste" . 1) ("csv_leave_proxies" . 0) ("kf-zeit" . 0)
|
||||
("testlauf" . 1))
|
||||
;; Alle .dbg-Schalter Standard 0 (2026-11-02). csv_leave_proxies ist kein
|
||||
;; .dbg-Schalter, sondern steuert die Export-Hilfskopien.
|
||||
(foreach nm '(("vf-sepliste" . 0) ("csv_leave_proxies" . 0) ("kf-zeit" . 0)
|
||||
("testlauf" . 0))
|
||||
(if (not (assoc (car nm) *dbg-schalter*))
|
||||
(setq *dbg-schalter* (cons nm *dbg-schalter*))))
|
||||
|
||||
@@ -204,11 +205,10 @@
|
||||
;; Wenn nil oder nicht gesetzt, wird "." verwendet.
|
||||
;; ------------------------------------------------------------
|
||||
(defun dbgopen (filename envvar / dir fullpath fh ts)
|
||||
;; Ohne Meldung: bei Standard "aus" wuerde jeder dbgopen-Aufruf sonst
|
||||
;; die Kommandozeile zuschreiben.
|
||||
(if (not *dbg-active*)
|
||||
(progn
|
||||
(prompt "\n[DBG] Debug deaktiviert - keine Datei angelegt.")
|
||||
(princ)
|
||||
)
|
||||
(princ)
|
||||
(progn
|
||||
;; Verzeichnis bestimmen
|
||||
(setq dir nil)
|
||||
|
||||
@@ -220,3 +220,16 @@ gang = LG_Gang, 8
|
||||
#_3D_ILS_SEP-SP = 82
|
||||
#_3D_ILS_Anbaugruppen = 6
|
||||
#_3D_ZZ_Scanner = 6
|
||||
|
||||
# ============================================================
|
||||
# HW-Planung: Materialfluss-Skizze (lib/hw_materialfluss.py, Befehl
|
||||
# HW_MATERIALFLUSS). Gilt fuer die erzeugte <dwg>_HW.dxf, nicht fuer die
|
||||
# offene Zeichnung. Gelesen vom Python-Skript selbst (eigener Mini-Parser).
|
||||
# ============================================================
|
||||
[hw_planung]
|
||||
hw_kreisel = HW_Kreisel, 3
|
||||
hw_strecke = HW_Materialfluss, 5
|
||||
hw_weiche = HW_Weiche, 1
|
||||
hw_beladung = HW_Beladung, 4
|
||||
hw_entladung = HW_Entladung, 6
|
||||
hw_richtung = HW_Richtung, 2
|
||||
@@ -1137,6 +1137,9 @@
|
||||
"tt-stil": "\nTextstil",
|
||||
"tt-stil-fehlt": "\nTextstil %1 existiert nicht in der Zeichnung.",
|
||||
"tt-stil-titel": "Textstil aendern",
|
||||
"hw-csv-fehlt": "\n[HW_MATERIALFLUSS] FEHLER: CSV-Export fehlt: %1 - Materialfluss wird nicht erzeugt.",
|
||||
"hw-fertig": "\n[HW_MATERIALFLUSS] Materialfluss geschrieben: %1",
|
||||
"hw-symbole-offen": "HW Planung - Symbole erzeugen ist noch nicht umgesetzt.",
|
||||
"dinformate-dialog-fehlt": "DIN-Formate-Dialog nicht gefunden: %1",
|
||||
"dinformate-datei-fehlt": "DIN-Formate: Datei nicht gefunden: %1",
|
||||
"dinformate-prompt-rahmen": "\nEinfuegepunkt Rahmen (untere linke Ecke): ",
|
||||
|
||||
@@ -1137,6 +1137,9 @@
|
||||
"tt-stil": "\nText style",
|
||||
"tt-stil-fehlt": "\nText style %1 does not exist in the drawing.",
|
||||
"tt-stil-titel": "Change text style",
|
||||
"hw-csv-fehlt": "\n[HW_MATERIALFLUSS] ERROR: CSV export missing: %1 - material flow not created.",
|
||||
"hw-fertig": "\n[HW_MATERIALFLUSS] Material flow written: %1",
|
||||
"hw-symbole-offen": "HW planning - create symbols is not implemented yet.",
|
||||
"dinformate-dialog-fehlt": "DIN formats dialog not found: %1",
|
||||
"dinformate-datei-fehlt": "DIN formats: file not found: %1",
|
||||
"dinformate-prompt-rahmen": "\nBorder insertion point (lower left corner): ",
|
||||
|
||||
@@ -197,6 +197,7 @@ def load_elements(csv_pfad):
|
||||
"insertpoint": decode_insertpoint(zeile.get("Insertpoint")),
|
||||
"ks_ein": decode_trans(zeile.get("K1")),
|
||||
"ks_aus": decode_trans(zeile.get("K2")),
|
||||
"trackids": (zeile.get("TrackIds") or "").strip(),
|
||||
}
|
||||
element["footprint"] = _footprint(element)
|
||||
element["z_bereich"] = (mitte[2] - masse[2] / 2.0, mitte[2] + masse[2] / 2.0)
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
hw_materialfluss.py - Materialfluss-Skizze fuer die HW-Planung aus dem CSV-Export.
|
||||
|
||||
Aufruf:
|
||||
python hw_materialfluss.py <export.csv> <ausgabe_HW.dxf> [--layer-cfg <layer.cfg>]
|
||||
|
||||
Gestartet vom Befehl HW_MATERIALFLUSS (Lisp/HwPlanung.lsp, Menue HW Planung ->
|
||||
Materialfluss erzeugen) direkt nach EXPORTCSV; die Ausgabe heisst wie die
|
||||
Zeichnung mit Anhang "_HW.dxf". Alles wird flach in die XY-Ebene (Z = 0)
|
||||
gezeichnet - es geht um den Grundriss des Materialflusses.
|
||||
|
||||
Was gezeichnet wird:
|
||||
* Kreisel/Eckrad: geschlossene Polylinie als Rechteck um die Laufbahn
|
||||
(Mitte + Abmessungen aus Position/Boundingbox, Ausrichtung aus dem Merkmal
|
||||
"Drehung"), Punktfolge in Drehrichtung (UZS = im Uhrzeigersinn,
|
||||
GUZ = gegen den Uhrzeigersinn). Dazu je ein Pfeil auf den Laengsseiten
|
||||
(Layer hw_richtung), damit die Richtung in der Zeichnung sichtbar ist.
|
||||
* Strecken (VF/GF): je Strecke eine Polylinie in Materialflussrichtung,
|
||||
vom Ausschleuselement (AS) ueber die Separatoren bis zum
|
||||
Einschleuselement (ES), Stuetzpunkte = x/y der Elemente aus der Spalte
|
||||
TrackIds; am Ende ein Richtungspfeil.
|
||||
* Weiche: kleiner Kreis an der Beruehrposition zweier Kreisel.
|
||||
* BTMT Beladung: grosser Kreis auf K1, kleiner Kreis auf K2 (auf der
|
||||
Strecke), dazwischen eine Linie.
|
||||
* BTMT Entladung: kleiner Kreis auf K1 (auf der Strecke), grosser Kreis
|
||||
auf K2, dazwischen eine Linie.
|
||||
|
||||
Layer und Farben stehen in cfg/layer.cfg, Abschnitt [hw_planung]; fehlt ein
|
||||
Eintrag, gilt die Vorgabe aus LAYER_VORGABEN.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
|
||||
import ezdxf
|
||||
|
||||
from export_graph import load_elements
|
||||
|
||||
KREISEL_ARTEN = {"ILS 2.0 Kreisel", "ILS 2.0 Eckrad"}
|
||||
STRECKEN_ARTEN = {"ILS 2.0 Strecke", "ILS 2.0 Strecke - Modul", "ILS 2.0 Gefaellestrecke"}
|
||||
AS_ART = "ILS Ausschleuselement"
|
||||
ES_ART = "ILS Einschleuselement"
|
||||
WEICHE_ARTEN = {"ILS Weiche"}
|
||||
BELADUNG_ARTEN = {"ILS 2.0 BTMT Beladung"}
|
||||
ENTLADUNG_ARTEN = {"ILS 2.0 BTMT Entladung"}
|
||||
|
||||
# Kreisel-Durchmesser (Laufbahnbreite), falls die Bounding-Box ihn nicht
|
||||
# liefert (schraeg gedrehter Kreisel).
|
||||
KREISEL_DURCHMESSER_MM = 800.0
|
||||
|
||||
RADIUS_WEICHE_MM = 100.0
|
||||
RADIUS_GROSS_MM = 200.0
|
||||
RADIUS_KLEIN_MM = 80.0
|
||||
PFEIL_LAENGE_MM = 250.0
|
||||
PFEIL_BREITE_MM = 150.0
|
||||
|
||||
# Schluessel -> (Layername, Farbnummer); ueberschreibbar in cfg/layer.cfg [hw_planung]
|
||||
LAYER_VORGABEN = {
|
||||
"hw_kreisel": ("HW_Kreisel", 3),
|
||||
"hw_strecke": ("HW_Materialfluss", 5),
|
||||
"hw_weiche": ("HW_Weiche", 1),
|
||||
"hw_beladung": ("HW_Beladung", 4),
|
||||
"hw_entladung": ("HW_Entladung", 6),
|
||||
"hw_richtung": ("HW_Richtung", 2),
|
||||
}
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Konfiguration
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def layer_cfg_lesen(pfad):
|
||||
"""Abschnitt [hw_planung] aus layer.cfg -> {key: (layer, farbe)}.
|
||||
|
||||
Eigener Mini-Parser statt configparser: layer.cfg ist fuer ssg-load-ini
|
||||
geschrieben (Kommentare mit '#', Werte 'Layername, Farbe').
|
||||
"""
|
||||
layer = dict(LAYER_VORGABEN)
|
||||
if not pfad or not os.path.isfile(pfad):
|
||||
return layer
|
||||
abschnitt = None
|
||||
with open(pfad, encoding="utf-8", errors="replace") as fh:
|
||||
for zeile in fh:
|
||||
zeile = zeile.split("#", 1)[0].strip()
|
||||
if not zeile:
|
||||
continue
|
||||
if zeile.startswith("[") and zeile.endswith("]"):
|
||||
abschnitt = zeile[1:-1].strip().lower()
|
||||
continue
|
||||
if abschnitt != "hw_planung" or "=" not in zeile:
|
||||
continue
|
||||
key, wert = (t.strip() for t in zeile.split("=", 1))
|
||||
teile = [t.strip() for t in wert.split(",")]
|
||||
name = teile[0]
|
||||
farbe = LAYER_VORGABEN.get(key, ("", 7))[1]
|
||||
if len(teile) > 1:
|
||||
try:
|
||||
farbe = int(teile[1])
|
||||
except ValueError:
|
||||
pass
|
||||
if name:
|
||||
layer[key] = (name, farbe)
|
||||
return layer
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Reine Geometrie (in tests/test_hw_materialfluss.py getestet)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _drehen(px, py, winkel_grad):
|
||||
w = math.radians(winkel_grad)
|
||||
c, s = math.cos(w), math.sin(w)
|
||||
return (px * c - py * s, px * s + py * c)
|
||||
|
||||
|
||||
def kreisel_rechteck(mitte, masse, drehung_grad, drehrichtung, abstand_m=None):
|
||||
"""Eckpunkte (x, y) des Kreisel-Rechtecks in Drehrichtung.
|
||||
|
||||
Laenge/Breite kommen bei achsparalleler Lage exakt aus der Bounding-Box;
|
||||
bei schraeger Drehung (Bounding-Box nicht mehr die Laufbahn) aus dem
|
||||
Abstand AN8-SP8 plus Durchmesser. UZS -> Punkte im Uhrzeigersinn,
|
||||
sonst gegen den Uhrzeigersinn.
|
||||
"""
|
||||
dx, dy = masse["dx"], masse["dy"]
|
||||
w = (drehung_grad or 0.0) % 360.0
|
||||
if abs(w % 90.0) < 1e-6 or abs(w % 90.0 - 90.0) < 1e-6:
|
||||
laenge, breite = max(dx, dy), min(dx, dy)
|
||||
else:
|
||||
breite = KREISEL_DURCHMESSER_MM
|
||||
laenge = (abstand_m or 0.0) * 1000.0 + breite
|
||||
hl, hb = laenge / 2.0, breite / 2.0
|
||||
# gegen den Uhrzeigersinn im lokalen KS (Laengsachse = lokales X)
|
||||
lokal = [(-hl, -hb), (hl, -hb), (hl, hb), (-hl, hb)]
|
||||
if (drehrichtung or "").upper() == "UZS":
|
||||
lokal.reverse()
|
||||
cx, cy = mitte["x"], mitte["y"]
|
||||
punkte = []
|
||||
for px, py in lokal:
|
||||
rx, ry = _drehen(px, py, drehung_grad or 0.0)
|
||||
punkte.append((cx + rx, cy + ry))
|
||||
return punkte
|
||||
|
||||
|
||||
def pfeil(spitze, richtung, laenge=PFEIL_LAENGE_MM, breite=PFEIL_BREITE_MM):
|
||||
"""Offener Pfeilkopf (3 Punkte) mit Spitze in `spitze`, zeigend in `richtung`."""
|
||||
rx, ry = richtung
|
||||
n = math.hypot(rx, ry)
|
||||
if n < 1e-9:
|
||||
return None
|
||||
rx, ry = rx / n, ry / n
|
||||
bx, by = spitze[0] - rx * laenge, spitze[1] - ry * laenge
|
||||
qx, qy = -ry * breite / 2.0, rx * breite / 2.0
|
||||
return [(bx + qx, by + qy), spitze, (bx - qx, by - qy)]
|
||||
|
||||
|
||||
def kreisel_pfeile(punkte):
|
||||
"""Richtungspfeile auf der Mitte der beiden laengeren Rechteckseiten."""
|
||||
pfeile = []
|
||||
n = len(punkte)
|
||||
seiten = [(punkte[i], punkte[(i + 1) % n]) for i in range(n)]
|
||||
max_l = max(math.dist(a, b) for a, b in seiten)
|
||||
for a, b in seiten:
|
||||
if math.dist(a, b) >= max_l - 1e-6:
|
||||
mitte = ((a[0] + b[0]) / 2.0, (a[1] + b[1]) / 2.0)
|
||||
p = pfeil(mitte, (b[0] - a[0], b[1] - a[1]))
|
||||
if p:
|
||||
pfeile.append(p)
|
||||
return pfeile
|
||||
|
||||
|
||||
def strecken_pfad(strecke, nach_id):
|
||||
"""Stuetzpunkte (x, y) einer Strecke in Materialflussrichtung (AS -> ES).
|
||||
|
||||
Grundlage ist die Spalte TrackIds (AS, Separatoren, ES in Kettenfolge).
|
||||
Steht das ES vorn, wird umgedreht. Unbekannte IDs werden uebersprungen.
|
||||
"""
|
||||
ids = [t.strip() for t in (strecke.get("trackids") or "").split(",") if t.strip()]
|
||||
glieder = [nach_id[i] for i in ids if i in nach_id]
|
||||
if len(glieder) < 2:
|
||||
return []
|
||||
if glieder[0]["teileart"] == ES_ART or glieder[-1]["teileart"] == AS_ART:
|
||||
glieder.reverse()
|
||||
punkte = []
|
||||
for g in glieder:
|
||||
p = (g["mitte"]["x"], g["mitte"]["y"])
|
||||
if not punkte or math.dist(punkte[-1], p) > 1e-6:
|
||||
punkte.append(p)
|
||||
return punkte
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# DXF schreiben
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _xy(punkt):
|
||||
return (punkt[0], punkt[1]) if punkt else None
|
||||
|
||||
|
||||
def zeichnen(elemente, ausgabe, layer):
|
||||
doc = ezdxf.new("R2018", setup=True)
|
||||
doc.header["$INSUNITS"] = 4 # mm
|
||||
msp = doc.modelspace()
|
||||
for name, farbe in layer.values():
|
||||
if name not in doc.layers:
|
||||
doc.layers.add(name, color=farbe)
|
||||
|
||||
def ly(key):
|
||||
return {"layer": layer[key][0]}
|
||||
|
||||
nach_id = {e["teileid"]: e for e in elemente if e["teileid"]}
|
||||
zaehler = {"kreisel": 0, "strecken": 0, "weichen": 0, "beladung": 0, "entladung": 0}
|
||||
warnungen = []
|
||||
|
||||
for el in elemente:
|
||||
art = el["teileart"]
|
||||
m = el["merkmale"]
|
||||
if art in KREISEL_ARTEN:
|
||||
abstand = None
|
||||
for k, v in m.items():
|
||||
if k.startswith("Abstand"):
|
||||
try:
|
||||
abstand = float(str(v).replace(",", "."))
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
drehung = float(m.get("Drehung") or 0.0)
|
||||
except (TypeError, ValueError):
|
||||
drehung = 0.0
|
||||
punkte = kreisel_rechteck(el["mitte"], el["masse"], drehung,
|
||||
m.get("Drehrichtung"), abstand)
|
||||
msp.add_lwpolyline(punkte, close=True, dxfattribs=ly("hw_kreisel"))
|
||||
for p in kreisel_pfeile(punkte):
|
||||
msp.add_lwpolyline(p, dxfattribs=ly("hw_richtung"))
|
||||
zaehler["kreisel"] += 1
|
||||
elif art in STRECKEN_ARTEN:
|
||||
punkte = strecken_pfad(el, nach_id)
|
||||
if len(punkte) < 2:
|
||||
warnungen.append(f"{el['teileid']} {el['bezeichnung']}: keine Track-Punkte")
|
||||
continue
|
||||
msp.add_lwpolyline(punkte, dxfattribs=ly("hw_strecke"))
|
||||
p = pfeil(punkte[-1], (punkte[-1][0] - punkte[-2][0],
|
||||
punkte[-1][1] - punkte[-2][1]))
|
||||
if p:
|
||||
msp.add_lwpolyline(p, dxfattribs=ly("hw_richtung"))
|
||||
zaehler["strecken"] += 1
|
||||
elif art in WEICHE_ARTEN:
|
||||
msp.add_circle((el["mitte"]["x"], el["mitte"]["y"]), RADIUS_WEICHE_MM,
|
||||
dxfattribs=ly("hw_weiche"))
|
||||
zaehler["weichen"] += 1
|
||||
elif art in BELADUNG_ARTEN or art in ENTLADUNG_ARTEN:
|
||||
k1, k2 = _xy(el["ks_ein"]), _xy(el["ks_aus"])
|
||||
if not (k1 and k2):
|
||||
warnungen.append(f"{el['teileid']} {el['bezeichnung']}: K1/K2 fehlt")
|
||||
continue
|
||||
if art in BELADUNG_ARTEN:
|
||||
msp.add_circle(k1, RADIUS_GROSS_MM, dxfattribs=ly("hw_beladung"))
|
||||
msp.add_circle(k2, RADIUS_KLEIN_MM, dxfattribs=ly("hw_beladung"))
|
||||
msp.add_line(k1, k2, dxfattribs=ly("hw_beladung"))
|
||||
zaehler["beladung"] += 1
|
||||
else:
|
||||
msp.add_circle(k1, RADIUS_KLEIN_MM, dxfattribs=ly("hw_entladung"))
|
||||
msp.add_circle(k2, RADIUS_GROSS_MM, dxfattribs=ly("hw_entladung"))
|
||||
msp.add_line(k1, k2, dxfattribs=ly("hw_entladung"))
|
||||
zaehler["entladung"] += 1
|
||||
|
||||
doc.saveas(ausgabe)
|
||||
return zaehler, warnungen
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
ap = argparse.ArgumentParser(description=__doc__.split("\n")[1])
|
||||
ap.add_argument("csv")
|
||||
ap.add_argument("ausgabe")
|
||||
ap.add_argument("--layer-cfg", default=None,
|
||||
help="Pfad zu layer.cfg (Vorgabe: $DXFM_CFG/layer.cfg)")
|
||||
args = ap.parse_args(argv)
|
||||
|
||||
cfg = args.layer_cfg
|
||||
if cfg is None and os.environ.get("DXFM_CFG"):
|
||||
cfg = os.path.join(os.environ["DXFM_CFG"], "layer.cfg")
|
||||
|
||||
elemente = load_elements(args.csv)
|
||||
zaehler, warnungen = zeichnen(elemente, args.ausgabe, layer_cfg_lesen(cfg))
|
||||
print(f"HW-Materialfluss geschrieben: {args.ausgabe}")
|
||||
print(" " + ", ".join(f"{k}: {v}" for k, v in zaehler.items()))
|
||||
for w in warnungen:
|
||||
print(f" WARNUNG: {w}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
+168
-128
@@ -692,289 +692,307 @@
|
||||
<Command>^C^C(ssg-ensure "LagerInsert") LAGER_EXPORT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00155">
|
||||
<Macro>
|
||||
<Name>Materialfluss erzeugen</Name>
|
||||
<Command>^C^C(ssg-ensure "HwPlanung") HW_MATERIALFLUSS</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00156">
|
||||
<Macro>
|
||||
<Name>Symbole erzeugen</Name>
|
||||
<Command>^C^C(ssg-ensure "HwPlanung") HW_SYMBOLE</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00159">
|
||||
<Macro>
|
||||
<Name>Marker einfuegen</Name>
|
||||
<Command>^C^C(ssg-ensure "Tro_Edit") TRO_INSERT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00157">
|
||||
<MenuMacro UID="MM_00160">
|
||||
<Macro>
|
||||
<Name>Marker bearbeiten</Name>
|
||||
<Command>^C^C(ssg-ensure "Tro_Edit") TRO_EDIT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00158">
|
||||
<MenuMacro UID="MM_00161">
|
||||
<Macro>
|
||||
<Name>Bearbeiten (Auto)</Name>
|
||||
<Command>^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00160">
|
||||
<MenuMacro UID="MM_00163">
|
||||
<Macro>
|
||||
<Name>Verbindung einfuegen</Name>
|
||||
<Command>^C^C(ssg-ensure "Connection_Edit") CONNECTION_INSERT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00161">
|
||||
<MenuMacro UID="MM_00164">
|
||||
<Macro>
|
||||
<Name>Verbindung bearbeiten</Name>
|
||||
<Command>^C^C(ssg-ensure "Connection_Edit") CONNECTION_EDIT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00163">
|
||||
<MenuMacro UID="MM_00166">
|
||||
<Macro>
|
||||
<Name>Eingang</Name>
|
||||
<Command>^C^C(ssg-ensure "SSG_LIB_Commands") ILS_EINGANG_INSERT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00164">
|
||||
<MenuMacro UID="MM_00167">
|
||||
<Macro>
|
||||
<Name>Ausgang</Name>
|
||||
<Command>^C^C(ssg-ensure "SSG_LIB_Commands") ILS_AUSGANG_INSERT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00165">
|
||||
<MenuMacro UID="MM_00168">
|
||||
<Macro>
|
||||
<Name>SPS Schliessen</Name>
|
||||
<Command>^C^C</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00167">
|
||||
<MenuMacro UID="MM_00170">
|
||||
<Macro>
|
||||
<Name>Hoehen-Check (Montagehoehe/Buehne)</Name>
|
||||
<Command>^C^C(ssg-ensure "check_hoehen") HOEHEN_CHECK</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00171">
|
||||
<Macro>
|
||||
<Name>Export Sivas</Name>
|
||||
<Command>^C^C(ssg-ensure "export") EXPORTSIVAS</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00168">
|
||||
<MenuMacro UID="MM_00172">
|
||||
<Macro>
|
||||
<Name>Export CSV</Name>
|
||||
<Command>^C^C(ssg-ensure "export") EXPORTCSV</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00170">
|
||||
<MenuMacro UID="MM_00174">
|
||||
<Macro>
|
||||
<Name>Umschalten 2D und 3D</Name>
|
||||
<Command>^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_SWITCH</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00171">
|
||||
<MenuMacro UID="MM_00175">
|
||||
<Macro>
|
||||
<Name>Alle Bloecke auf 2D</Name>
|
||||
<Command>^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_ALL_2D</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00172">
|
||||
<MenuMacro UID="MM_00176">
|
||||
<Macro>
|
||||
<Name>Alle Bloecke auf 3D</Name>
|
||||
<Command>^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_ALL_3D</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00173">
|
||||
<MenuMacro UID="MM_00177">
|
||||
<Macro>
|
||||
<Name>Sprache</Name>
|
||||
<Command>^C^C(ssg-ensure "SSG_LIB_Commands") SSG_SPRACHE</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00174">
|
||||
<MenuMacro UID="MM_00178">
|
||||
<Macro>
|
||||
<Name>Planquadrate an/aus</Name>
|
||||
<Command>^C^C(ssg-ensure "DrawPlanquadrate") PLANQUADRATE_TOGGLE</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00175">
|
||||
<MenuMacro UID="MM_00179">
|
||||
<Macro>
|
||||
<Name>CSV-Export</Name>
|
||||
<Command>^C^C(ssg-ensure "export") CSV_EXPORT_KONFIG</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00177">
|
||||
<MenuMacro UID="MM_00181">
|
||||
<Macro>
|
||||
<Name>Bloecke zaehlen</Name>
|
||||
<Command>^C^C(ssg-ensure "ssg_blocktools") SSG_BLOCK_COUNT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00178">
|
||||
<MenuMacro UID="MM_00182">
|
||||
<Macro>
|
||||
<Name>Bloecke loeschen</Name>
|
||||
<Command>^C^C(ssg-ensure "ssg_blocktools") SSG_BLOCK_DELETE</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00179">
|
||||
<MenuMacro UID="MM_00183">
|
||||
<Macro>
|
||||
<Name>Attribute ersetzen</Name>
|
||||
<Command>^C^C(ssg-ensure "ssg_blocktools") SSG_ATTR_ERSETZEN</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00181">
|
||||
<MenuMacro UID="MM_00185">
|
||||
<Macro>
|
||||
<Name>Text ersetzen</Name>
|
||||
<Command>^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_ERSETZEN</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00182">
|
||||
<MenuMacro UID="MM_00186">
|
||||
<Macro>
|
||||
<Name>Text parallel beschriften</Name>
|
||||
<Command>^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_PARALLEL</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00183">
|
||||
<MenuMacro UID="MM_00187">
|
||||
<Macro>
|
||||
<Name>Texthoehe aendern</Name>
|
||||
<Command>^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_HOEHE</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00184">
|
||||
<MenuMacro UID="MM_00188">
|
||||
<Macro>
|
||||
<Name>Textstil aendern</Name>
|
||||
<Command>^C^C(ssg-ensure "ssg_texttools") SSG_TEXT_STIL</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00186">
|
||||
<MenuMacro UID="MM_00190">
|
||||
<Macro>
|
||||
<Name>Faehnchen + Stueckliste aus Zeichnung</Name>
|
||||
<Command>^C^C(ssg-ensure "ssg_stueckliste") SSG_FAEHNCHEN_STUECKLISTE</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00187">
|
||||
<MenuMacro UID="MM_00191">
|
||||
<Macro>
|
||||
<Name>Din Formate</Name>
|
||||
<Command>^C^C(ssg-ensure "DinFormate") DIN_FORMATE</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00189">
|
||||
<MenuMacro UID="MM_00193">
|
||||
<Macro>
|
||||
<Name>alle Tests ausfuehren und exportieren</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) (c:SSG_RUN_ALL_TESTS_EXPORT)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00190">
|
||||
<MenuMacro UID="MM_00194">
|
||||
<Macro>
|
||||
<Name>Tests ausfuehren und stehen lassen</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) (c:SSG_RUN_ALL_TESTS_OFFEN)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00191">
|
||||
<MenuMacro UID="MM_00195">
|
||||
<Macro>
|
||||
<Name>Export CSV/Sivas ALL</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_export_all.lsp")) (c:TEST_EXPORT_ALL)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00193">
|
||||
<MenuMacro UID="MM_00197">
|
||||
<Macro>
|
||||
<Name>Kreisel</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_kreisel.lsp")) (c:TEST_KREISEL)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00194">
|
||||
<MenuMacro UID="MM_00198">
|
||||
<Macro>
|
||||
<Name>Foerderer</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_foerderer.lsp")) (c:TEST_FOERDERER)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00195">
|
||||
<MenuMacro UID="MM_00199">
|
||||
<Macro>
|
||||
<Name>Foerderer-Linienzug</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_linienzug.lsp")) (c:TEST_LINIENZUG) (c:TEST_LINIENZUG_STUFE2)</Command>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_linienzug.lsp")) (c:TEST_LINIENZUG) (c:TEST_LINIENZUG_STUFE2) (c:TEST_LINIENZUG_MODUS2)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00196">
|
||||
<MenuMacro UID="MM_00200">
|
||||
<Macro>
|
||||
<Name>Omniflo</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo.lsp")) (c:TEST_OMNIFLO)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00197">
|
||||
<MenuMacro UID="MM_00201">
|
||||
<Macro>
|
||||
<Name>Omniflo Strecke</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo_strecke.lsp")) (c:TEST_OMNIFLO_STRECKE)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00198">
|
||||
<MenuMacro UID="MM_00202">
|
||||
<Macro>
|
||||
<Name>Gefaellestrecke</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_gefaellestrecke.lsp")) (c:TEST_GEFAELLESTRECKE)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00199">
|
||||
<MenuMacro UID="MM_00203">
|
||||
<Macro>
|
||||
<Name>Mubea Gesamtmodell</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_mubea.lsp")) (c:TEST_MUBEA)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00200">
|
||||
<MenuMacro UID="MM_00204">
|
||||
<Macro>
|
||||
<Name>HundM05 Kreisel-Abschnitt</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_hundm05.lsp")) (c:TEST_HUNDM05)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00201">
|
||||
<MenuMacro UID="MM_00205">
|
||||
<Macro>
|
||||
<Name>Dematic/Arvato Flowpuffer (Vorlage)</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_dematic_arvato.lsp")) (c:TEST_DEMATIC_ARVATO)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00202">
|
||||
<MenuMacro UID="MM_00206">
|
||||
<Macro>
|
||||
<Name>ILS 3.0 Showroom (Vorlage)</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_showroom_ils.lsp")) (c:TEST_SHOWROOM_ILS)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00203">
|
||||
<MenuMacro UID="MM_00207">
|
||||
<Macro>
|
||||
<Name>Testanlage test_system</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_test_system.lsp")) (c:TEST_TEST_SYSTEM)</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00204">
|
||||
<MenuMacro UID="MM_00208">
|
||||
<Macro>
|
||||
<Name>KS 2D/3D pruefen (CSV)</Name>
|
||||
<Command>^C^C(load (strcat (getenv "DXFMAKRO") "/Lisp/ks_pruefung.lsp")) KS_PRUEFEN</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00216">
|
||||
<MenuMacro UID="MM_00220">
|
||||
<Macro>
|
||||
<Name>Kreisel bearbeiten</Name>
|
||||
<Command>(ssg-ensure "KreiselInsert") KreiselEdit</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00217">
|
||||
<MenuMacro UID="MM_00221">
|
||||
<Macro>
|
||||
<Name>Eckrad bearbeiten</Name>
|
||||
<Command>(ssg-ensure "KreiselInsert") EckradEdit</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00218">
|
||||
<MenuMacro UID="MM_00222">
|
||||
<Macro>
|
||||
<Name>Omniflo Element bearbeiten</Name>
|
||||
<Command>(ssg-ensure "OmniModulInsert") OMNI_EDIT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00219">
|
||||
<MenuMacro UID="MM_00223">
|
||||
<Macro>
|
||||
<Name>Gefaellestrecke bearbeiten</Name>
|
||||
<Command>(ssg-ensure "Gefaellestrecke") GEFAELLESTRECKE_EDIT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00220">
|
||||
<MenuMacro UID="MM_00224">
|
||||
<Macro>
|
||||
<Name>VarioFoerderer bearbeiten</Name>
|
||||
<Command>(ssg-ensure "VarioFoerderer") VARIOFOERDERER_EDIT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00221">
|
||||
<MenuMacro UID="MM_00225">
|
||||
<Macro>
|
||||
<Name>TRO-Marker bearbeiten</Name>
|
||||
<Command>(ssg-ensure "Tro_Edit") TRO_EDIT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00222">
|
||||
<MenuMacro UID="MM_00226">
|
||||
<Macro>
|
||||
<Name>Verbindung bearbeiten</Name>
|
||||
<Command>(ssg-ensure "Connection_Edit") CONNECTION_EDIT</Command>
|
||||
</Macro>
|
||||
</MenuMacro>
|
||||
<MenuMacro UID="MM_00224">
|
||||
<MenuMacro UID="MM_00228">
|
||||
<Macro>
|
||||
<Name>SSG Bearbeiten (Auto)</Name>
|
||||
<Command>(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT</Command>
|
||||
@@ -994,10 +1012,11 @@
|
||||
<PopMenuRef pUID="PM_00132"/>
|
||||
<PopMenuRef pUID="PM_00140"/>
|
||||
<PopMenuRef pUID="PM_00154"/>
|
||||
<PopMenuRef pUID="PM_00166"/>
|
||||
<PopMenuRef pUID="PM_00157"/>
|
||||
<PopMenuRef pUID="PM_00169"/>
|
||||
<PopMenuRef pUID="PM_00176"/>
|
||||
<PopMenuRef pUID="PM_00188"/>
|
||||
<PopMenuRef pUID="PM_00173"/>
|
||||
<PopMenuRef pUID="PM_00180"/>
|
||||
<PopMenuRef pUID="PM_00192"/>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00005">
|
||||
<Name>ILS</Name>
|
||||
@@ -1767,327 +1786,348 @@
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00154">
|
||||
<Name>HW Planung</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Materialfluss erzeugen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00155"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Symbole erzeugen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00156"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00157">
|
||||
<Name>SPS</Name>
|
||||
<PopMenuRef pUID="PM_00155"/>
|
||||
<PopMenuRef pUID="PM_00159"/>
|
||||
<PopMenuRef pUID="PM_00158"/>
|
||||
<PopMenuRef pUID="PM_00162"/>
|
||||
<PopMenuItem>
|
||||
<NameRef>Eingang</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00163"/>
|
||||
<MacroRef MenuMacroID="MM_00166"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Ausgang</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00164"/>
|
||||
<MacroRef MenuMacroID="MM_00167"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>SPS Schliessen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00165"/>
|
||||
<MacroRef MenuMacroID="MM_00168"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00155">
|
||||
<PopMenu UID="PM_00158">
|
||||
<Name>TRO</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Marker einfuegen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00156"/>
|
||||
<MacroRef MenuMacroID="MM_00159"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Marker bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00157"/>
|
||||
<MacroRef MenuMacroID="MM_00160"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Bearbeiten (Auto)</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00158"/>
|
||||
<MacroRef MenuMacroID="MM_00161"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00159">
|
||||
<PopMenu UID="PM_00162">
|
||||
<Name>Connections</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Verbindung einfuegen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00160"/>
|
||||
<MacroRef MenuMacroID="MM_00163"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Verbindung bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00161"/>
|
||||
<MacroRef MenuMacroID="MM_00164"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Bearbeiten (Auto)</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00158"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00166">
|
||||
<Name>Export</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Export Sivas</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00167"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Export CSV</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00168"/>
|
||||
<MacroRef MenuMacroID="MM_00161"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00169">
|
||||
<Name>Konfiguration</Name>
|
||||
<Name>Export</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Umschalten 2D und 3D</NameRef>
|
||||
<NameRef>Hoehen-Check (Montagehoehe/Buehne)</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00170"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Alle Bloecke auf 2D</NameRef>
|
||||
<NameRef>Export Sivas</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00171"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Alle Bloecke auf 3D</NameRef>
|
||||
<NameRef>Export CSV</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00172"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00173">
|
||||
<Name>Konfiguration</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Sprache</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00173"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Planquadrate an/aus</NameRef>
|
||||
<NameRef>Umschalten 2D und 3D</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00174"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>CSV-Export</NameRef>
|
||||
<NameRef>Alle Bloecke auf 2D</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00175"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00176">
|
||||
<Name>Werkzeuge</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Bloecke zaehlen</NameRef>
|
||||
<NameRef>Alle Bloecke auf 3D</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00176"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Sprache</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00177"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Bloecke loeschen</NameRef>
|
||||
<NameRef>Planquadrate an/aus</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00178"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Attribute ersetzen</NameRef>
|
||||
<NameRef>CSV-Export</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00179"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00180">
|
||||
<Name>Werkzeuge</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Bloecke zaehlen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00181"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Bloecke loeschen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00182"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Attribute ersetzen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00183"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem IsSeparator="true"/>
|
||||
<PopMenuItem>
|
||||
<NameRef>Text ersetzen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00181"/>
|
||||
<MacroRef MenuMacroID="MM_00185"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Text parallel beschriften</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00182"/>
|
||||
<MacroRef MenuMacroID="MM_00186"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Texthoehe aendern</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00183"/>
|
||||
<MacroRef MenuMacroID="MM_00187"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Textstil aendern</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00184"/>
|
||||
<MacroRef MenuMacroID="MM_00188"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem IsSeparator="true"/>
|
||||
<PopMenuItem>
|
||||
<NameRef>Faehnchen + Stueckliste aus Zeichnung</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00186"/>
|
||||
<MacroRef MenuMacroID="MM_00190"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Din Formate</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00187"/>
|
||||
<MacroRef MenuMacroID="MM_00191"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00188">
|
||||
<PopMenu UID="PM_00192">
|
||||
<Name>Tests</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>alle Tests ausfuehren und exportieren</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00189"/>
|
||||
<MacroRef MenuMacroID="MM_00193"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Tests ausfuehren und stehen lassen</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00190"/>
|
||||
<MacroRef MenuMacroID="MM_00194"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Export CSV/Sivas ALL</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00191"/>
|
||||
<MacroRef MenuMacroID="MM_00195"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem IsSeparator="true"/>
|
||||
<PopMenuItem>
|
||||
<NameRef>Kreisel</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00193"/>
|
||||
<MacroRef MenuMacroID="MM_00197"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Foerderer</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00194"/>
|
||||
<MacroRef MenuMacroID="MM_00198"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Foerderer-Linienzug</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00195"/>
|
||||
<MacroRef MenuMacroID="MM_00199"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Omniflo</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00196"/>
|
||||
<MacroRef MenuMacroID="MM_00200"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Omniflo Strecke</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00197"/>
|
||||
<MacroRef MenuMacroID="MM_00201"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Gefaellestrecke</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00198"/>
|
||||
<MacroRef MenuMacroID="MM_00202"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Mubea Gesamtmodell</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00199"/>
|
||||
<MacroRef MenuMacroID="MM_00203"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>HundM05 Kreisel-Abschnitt</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00200"/>
|
||||
<MacroRef MenuMacroID="MM_00204"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Dematic/Arvato Flowpuffer (Vorlage)</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00201"/>
|
||||
<MacroRef MenuMacroID="MM_00205"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>ILS 3.0 Showroom (Vorlage)</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00202"/>
|
||||
<MacroRef MenuMacroID="MM_00206"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Testanlage test_system</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00203"/>
|
||||
<MacroRef MenuMacroID="MM_00207"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>KS 2D/3D pruefen (CSV)</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00204"/>
|
||||
<MacroRef MenuMacroID="MM_00208"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
<PopMenu UID="PM_00215">
|
||||
<PopMenu UID="PM_00219">
|
||||
<Alias>POP501</Alias>
|
||||
<Name>SSG_LIB Edit Context</Name>
|
||||
<PopMenuItem>
|
||||
<NameRef>Kreisel bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00216"/>
|
||||
<MacroRef MenuMacroID="MM_00220"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Eckrad bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00217"/>
|
||||
<MacroRef MenuMacroID="MM_00221"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Omniflo Element bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00218"/>
|
||||
<MacroRef MenuMacroID="MM_00222"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Gefaellestrecke bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00219"/>
|
||||
<MacroRef MenuMacroID="MM_00223"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>VarioFoerderer bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00220"/>
|
||||
<MacroRef MenuMacroID="MM_00224"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>TRO-Marker bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00221"/>
|
||||
<MacroRef MenuMacroID="MM_00225"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem>
|
||||
<NameRef>Verbindung bearbeiten</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00222"/>
|
||||
<MacroRef MenuMacroID="MM_00226"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
<PopMenuItem IsSeparator="true"/>
|
||||
<PopMenuItem>
|
||||
<NameRef>SSG Bearbeiten (Auto)</NameRef>
|
||||
<MenuItem>
|
||||
<MacroRef MenuMacroID="MM_00224"/>
|
||||
<MacroRef MenuMacroID="MM_00228"/>
|
||||
</MenuItem>
|
||||
</PopMenuItem>
|
||||
</PopMenu>
|
||||
|
||||
@@ -147,6 +147,9 @@
|
||||
[Regelprofil anzeigen]^C^C(ssg-ensure "LagerPruefung") LG_REGELN
|
||||
[Hand-YAML fuer Abgleich]^C^C(ssg-ensure "LagerInsert") LAGER_HAND_YAML
|
||||
[<-Export RFQ-YAML]^C^C(ssg-ensure "LagerInsert") LAGER_EXPORT
|
||||
[->HW Planung]
|
||||
[Materialfluss erzeugen]^C^C(ssg-ensure "HwPlanung") HW_MATERIALFLUSS
|
||||
[<-Symbole erzeugen]^C^C(ssg-ensure "HwPlanung") HW_SYMBOLE
|
||||
[->SPS]
|
||||
[->TRO]
|
||||
[Marker einfuegen]^C^C(ssg-ensure "Tro_Edit") TRO_INSERT
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
"""Tests fuer lib/hw_materialfluss.py (Materialfluss-Skizze der HW-Planung)."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import ezdxf
|
||||
import pytest
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
|
||||
|
||||
import hw_materialfluss as hw # noqa: E402
|
||||
|
||||
|
||||
def _umlaufsinn(punkte):
|
||||
""">0 = gegen den Uhrzeigersinn, <0 = im Uhrzeigersinn (Gauss)."""
|
||||
return sum(a[0] * b[1] - b[0] * a[1]
|
||||
for a, b in zip(punkte, punkte[1:] + punkte[:1]))
|
||||
|
||||
|
||||
def test_kreisel_rechteck_uzs_senkrecht():
|
||||
# Kreisel2 aus Mubea: senkrecht (Drehung 90), UZS
|
||||
p = hw.kreisel_rechteck({"x": 0.0, "y": 4529.5}, {"dx": 800.0, "dy": 20815.0},
|
||||
90.0, "UZS")
|
||||
xs = sorted(round(x) for x, _ in p)
|
||||
ys = sorted(round(y) for _, y in p)
|
||||
assert xs[0] == -400 and xs[-1] == 400
|
||||
assert ys[0] == round(4529.5 - 20815 / 2) and ys[-1] == round(4529.5 + 20815 / 2)
|
||||
assert _umlaufsinn(p) < 0
|
||||
|
||||
|
||||
def test_kreisel_rechteck_guz_waagrecht():
|
||||
p = hw.kreisel_rechteck({"x": 3300.0, "y": -5478.0}, {"dx": 5800.0, "dy": 800.0},
|
||||
0.0, "GUZ")
|
||||
assert _umlaufsinn(p) > 0
|
||||
assert {round(x) for x, _ in p} == {400, 6200}
|
||||
|
||||
|
||||
def test_kreisel_rechteck_schraeg_aus_abstand():
|
||||
p = hw.kreisel_rechteck({"x": 0.0, "y": 0.0}, {"dx": 9999.0, "dy": 9999.0},
|
||||
45.0, "GUZ", abstand_m=5.0)
|
||||
seiten = sorted(round(((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 0.5)
|
||||
for a, b in zip(p, p[1:] + p[:1]))
|
||||
assert seiten == [800, 800, 5800, 5800]
|
||||
|
||||
|
||||
def _el(tid, art, x, y, trackids=""):
|
||||
return {"teileid": tid, "teileart": art, "mitte": {"x": x, "y": y},
|
||||
"trackids": trackids}
|
||||
|
||||
|
||||
def test_strecken_pfad_as_nach_es():
|
||||
els = [_el("1", hw.AS_ART, 0, 0), _el("2", "ILS 2.0 Separator", 50, 0),
|
||||
_el("3", hw.ES_ART, 100, 0)]
|
||||
nach_id = {e["teileid"]: e for e in els}
|
||||
strecke = _el("9", "ILS 2.0 Strecke", 0, 0, "1, 2, 3, 77")
|
||||
assert hw.strecken_pfad(strecke, nach_id) == [(0, 0), (50, 0), (100, 0)]
|
||||
# umgekehrte Kettenfolge -> trotzdem AS zuerst
|
||||
strecke["trackids"] = "3, 2, 1"
|
||||
assert hw.strecken_pfad(strecke, nach_id) == [(0, 0), (50, 0), (100, 0)]
|
||||
|
||||
|
||||
def test_pfeil_spitze_und_richtung():
|
||||
p = hw.pfeil((100.0, 0.0), (1.0, 0.0), laenge=10.0, breite=4.0)
|
||||
assert p[1] == (100.0, 0.0)
|
||||
assert p[0] == pytest.approx((90.0, 2.0)) and p[2] == pytest.approx((90.0, -2.0))
|
||||
|
||||
|
||||
def test_layer_cfg_abschnitt(tmp_path):
|
||||
cfg = tmp_path / "layer.cfg"
|
||||
cfg.write_text("[allgemein]\nhw_kreisel = FALSCH, 1\n"
|
||||
"[hw_planung]\n# Kommentar\nhw_kreisel = MeinKreisel, 9\n",
|
||||
encoding="utf-8")
|
||||
layer = hw.layer_cfg_lesen(str(cfg))
|
||||
assert layer["hw_kreisel"] == ("MeinKreisel", 9)
|
||||
assert layer["hw_weiche"] == hw.LAYER_VORGABEN["hw_weiche"]
|
||||
|
||||
|
||||
def test_csv_nach_dxf(tmp_path):
|
||||
kopf = ("Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;"
|
||||
"Boundingbox;Insertpoint;K1;K2;K3;K4;Nachbarn;TrackIds;Fehler;Warnungen;Merkmale")
|
||||
zeilen = [
|
||||
kopf,
|
||||
'1;"ILS 2.0 Kreisel";"0001";"K1";"";1;"0.00, 0.00, 0.00";"5800.00, 800.00, 1.00";'
|
||||
'"";"";"";"";"";"";"";"";"";{"Drehrichtung": "UZS", "Drehung": 0}',
|
||||
'2;"ILS Weiche";"0002";"W";"";1;"10.00, 20.00, 0.00";"100.00, 250.00, 30.00";'
|
||||
'"";"";"";"";"";"";"";"";"";{}',
|
||||
]
|
||||
csv_pfad = tmp_path / "export.csv"
|
||||
csv_pfad.write_text("\n".join(zeilen) + "\n", encoding="utf-8")
|
||||
dxf_pfad = tmp_path / "Test_HW.dxf"
|
||||
assert hw.main([str(csv_pfad), str(dxf_pfad), "--layer-cfg", ""]) == 0
|
||||
msp = ezdxf.readfile(str(dxf_pfad)).modelspace()
|
||||
assert len(msp.query('LWPOLYLINE[layer=="HW_Kreisel"]')) == 1
|
||||
assert len(msp.query('CIRCLE[layer=="HW_Weiche"]')) == 1
|
||||
+21
-1
@@ -1272,6 +1272,14 @@
|
||||
(tu-eq "kreisel-label-text/leer"
|
||||
"KREISEL 3: PIN_4000" (kreisel-label-text 3 "" "PIN" 4000.0))
|
||||
|
||||
;; Beschriftungswinkel: von unten oder links lesbar
|
||||
(tu-eq "kreisel-label-winkel/0" 0.0 (kreisel-label-winkel 0.0))
|
||||
(tu-eq "kreisel-label-winkel/90" 180.0 (kreisel-label-winkel 90.0))
|
||||
(tu-eq "kreisel-label-winkel/180" 180.0 (kreisel-label-winkel 180.0))
|
||||
(tu-eq "kreisel-label-winkel/270" 0.0 (kreisel-label-winkel 270.0))
|
||||
(tu-eq "kreisel-label-winkel/-90" 0.0 (kreisel-label-winkel -90.0))
|
||||
(tu-eq "kreisel-label-winkel/450" 180.0 (kreisel-label-winkel 450.0))
|
||||
|
||||
;; Eckrad-Dialog: Eingaben -> (attribs . rotation)
|
||||
(setq _e (eckrad-dialog-werte '(("NUMMER" . "3") ("HOEHE" . "0") ("DREHRICHTUNG" . "UZS"))
|
||||
"Eck3" "2500" "-90" "1" "0" "1"))
|
||||
@@ -3469,6 +3477,18 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; HW-Planung: Ausgabename der Materialfluss-Skizze
|
||||
(defun tu-tests-hw ()
|
||||
(princ "\n[HwPlanung]")
|
||||
(if (not (car (atoms-family 1 '("HW-DXF-NAME"))))
|
||||
(tu-record nil "HwPlanung-Modul geladen"
|
||||
"HwPlanung.lsp nicht geladen - siehe tests/test_unit.scr")
|
||||
(progn
|
||||
(tu-eq "hw-dxf-name/dwg" "Mubea_HW.dxf" (hw-dxf-name "Mubea.dwg"))
|
||||
(tu-eq "hw-dxf-name/punkt" "A.B_HW.dxf" (hw-dxf-name "A.B.dwg")))
|
||||
)
|
||||
)
|
||||
|
||||
(defun c:TEST_UNIT ( / out-dir report)
|
||||
(tu-reset)
|
||||
(princ "\n================================================================")
|
||||
@@ -3481,7 +3501,7 @@
|
||||
"tu-tests-export" "tu-tests-hoehen" "tu-tests-gf" "tu-tests-omni" "tu-tests-kreisel" "tu-tests-kreisel-bp"
|
||||
"tu-tests-sepliste" "tu-tests-json" "tu-tests-geruest"
|
||||
"tu-tests-sepscan" "tu-tests-vfl-segs" "tu-tests-vfl-abbruch"
|
||||
"tu-tests-werkzeuge" "tu-tests-poly" "tu-tests-lager" "tu-tests-kf" "tu-tests-hoehen-fam")
|
||||
"tu-tests-werkzeuge" "tu-tests-poly" "tu-tests-lager" "tu-tests-kf" "tu-tests-hoehen-fam" "tu-tests-hw")
|
||||
(tu-run-block fn))
|
||||
|
||||
(princ "\n\n----------------------------------------------------------------")
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
(load (strcat (getenv "DXFM_LISP") "/count_sep_scan.lsp") "count_sep_scan.lsp nicht gefunden")
|
||||
(load (strcat (getenv "DXFM_LISP") "/KettenFoerderer.lsp") "KettenFoerderer.lsp nicht gefunden")
|
||||
(load (strcat (getenv "DXFM_LISP") "/check_hoehen.lsp") "check_hoehen.lsp nicht gefunden")
|
||||
(load (strcat (getenv "DXFM_LISP") "/HwPlanung.lsp") "HwPlanung.lsp nicht gefunden")
|
||||
(load (strcat (getenv "DXFMAKRO") "/tests/test_unit.lsp"))
|
||||
(c:TEST_UNIT)
|
||||
(command "_.QUIT")
|
||||
Vendored
+1
-1
@@ -105,7 +105,7 @@
|
||||
"x": 9910,
|
||||
"y": -5878,
|
||||
"z": 2028,
|
||||
"abstand": 20015,
|
||||
"abstand": 20690,
|
||||
"rotation": 90.0,
|
||||
"typ": "STANDARD",
|
||||
"expect_block_prefix": "KREISEL_",
|
||||
|
||||
Reference in new issue
Block a user