From 98106a6af4a14a296e91d4cf6d13c72e6ce03521 Mon Sep 17 00:00:00 2001 From: Simon Hensch Date: Tue, 3 Nov 2026 07:40:01 +0100 Subject: [PATCH] =?UTF-8?q?[FIX]=20Omniflo=20TEF=20einf=C3=BCgen=20entlang?= =?UTF-8?q?=20Gerade=20funktioniert=20wieder;=20Omniflo=20Gerade=20ist=20a?= =?UTF-8?q?us=20dem=20Men=C3=BC=20entfernt=20worden,=20da=20entweder=20?= =?UTF-8?q?=C3=BCber=20das=20Men=C3=BC=20Fahrstrecke=20oder=20nur=20als=20?= =?UTF-8?q?Linie=20gezeichnet=20wird?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 4 +- Lisp/OmniModulInsert.lsp | 257 ---------------------- Lisp/README.md | 3 +- Lisp/TEFInsert.lsp | 25 ++- README.md | 2 +- data/json/component_defaults.json | 3 - doc/json-input-lisp.md | 15 +- doc/kommandos.md | 1 - doc/lisp_methods.md | 3 - lang/de_DE.json | 6 - lang/en_GB.json | 6 - menu/SSG_LIB.cui | 40 ---- menu/SSG_LIB.mnu | 4 - tests/README.md | 7 +- tests/test_omniflo_strecke.lsp | 95 ++------ tests/test_omniflo_strecke.py | 72 ++---- tests/testdata/omniflo_strecke_tests.json | 64 +----- 17 files changed, 59 insertions(+), 548 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0a8de29..04f67e8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -78,7 +78,7 @@ 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_AP*, 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_W*_*, 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 | | 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 | @@ -114,7 +114,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_AP60/AP110, 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_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 | | `SSG_LIB_Commands.lsp` | ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_SCANNER_INSERT, ILS_SEPARATOR_INSERT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT, SSG_BLOCKEDIT, SSG_DIM_SWITCH, SSG_SPRACHE | BTMT Be-/Entladung (`ils-insert-station`: wiederholtes Einfuegen von `BTMT-Beladung` bzw. `SC_Entladung`, Drehung interaktiv, Layer aus `LAYER`-Attribut, Dimension via `ssg-ils-block-laden`) + Sensoren (`ils-insert-sensor`) + Eingang-/Ausgang-Symbol (frei platzierbar wie BTMT Be-/Entladung, ueber `ils-insert-station` mit den Rohnamen `Eingang`/`Ausgang`, Bloecke `Eingang_.dwg`/`Ausgang_.dwg` in data/ils) + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) | | `Tro_Edit.lsp` | TRO_INSERT, TRO_EDIT | TRO-Marker (Block `TRO_SYM_`) fuer sps_skel (lib/tro_annotate.py): TRO_INSERT fuegt eine bestehende Blockdefinition an einem gewaehlten Punkt ein und setzt ID/TYPE (bricht ab, wenn der Typ noch keine Blockdefinition in der Zeichnung hat - die entsteht nur ueber tro_annotate.py); TRO_EDIT aendert ID/TYPE eines bestehenden Markers per Dialog. Typliste aus `tro_types.lsp` (von `tro_annotate.py --emit-lisp` nach DXFM_LISP geschrieben). Der Dispatcher SSG_BLOCKEDIT leitet Blocknamen `TRO_*` zu TRO_EDIT. | | `Connection_Edit.lsp` | CONNECTION_INSERT, CONNECTION_EDIT | Verbindung zwischen zwei TRO-Markern als Block `CONNECTION_ARROW` (Pfeilmitte); Beziehung ueber die INTERNEN IDs der TROs (`FROM_ID`/`TO_ID`, sichtbar `FROM_TRO`/`TO_TRO`, `KIND` flow/colocated), damit Umbenennen/Verschieben die Zuordnung nicht bricht. Dialog `connection_edit.dcl`; SSG_BLOCKEDIT leitet `CONNECTION_*` hierher (vor dem TRO-Zweig) | diff --git a/Lisp/OmniModulInsert.lsp b/Lisp/OmniModulInsert.lsp index 19aefc2..5a2e8b2 100644 --- a/Lisp/OmniModulInsert.lsp +++ b/Lisp/OmniModulInsert.lsp @@ -481,263 +481,6 @@ (princ) ) -;; --- Omniflo / Aluprofil Gerade --- - -;; Aluprofil-Fahrstrecke einfuegen. -;; -;; Ablauf: -;; 1. Quell-Block (.dwg) temporaer einfuegen, Attribute lesen, loeschen -;; 2. Nutzer waehlt Einfuegepunkt -> Text "blockname" wird horizontal platziert -;; 3. Nutzer klickt Endpunkt -> Linie definiert Fahrstreckenlaenge und Richtung -;; 4. Laenge wird gegen laengemax geprueft (Fehlermeldung bei Ueberschreitung) -;; 5. Compound-Block aus Linie + ATTDEFs (mit Quell-Werten) wird erzeugt -;; Blockname: blockname_YYYYMMDDHHMMSS -;; 6. Text wird gedreht, oberhalb der Linie positioniert, Inhalt aktualisiert -;; z.B. "APG110 L=2879" -;; -;; blockname = Profiltyp (z.B. "AP60", "AP110", "APG110") -;; laengemax = Maximale Fahrstreckenlaenge in mm -;; --- Quell-Attribute einer Aluprofil-.dwg lesen (mit ID-Feld) --- -;; blockname = Profiltyp (z.B. "AP60", "AP110", "APG110") -;; -;; Seit dem ILS-Flach-Refactor tragen die Quell-Bloecke das Dimensionssuffix -;; _2D/_3D und liegen flach unter data/ils/ (z.B. AP60_3D.dwg). Die Aufloesung -;; laeuft daher ueber den zentralen Resolver ssg-ils-block-datei (mit -;; automatischem 3D-Fallback) statt ueber *block-path* + Name. Nur wenn der -;; Resolver nichts findet, wird als Rueckfall der alte Pfad (*block-path* + -;; Name ohne Suffix) versucht. -;; Rueckgabe: Attribut-Alist (mit angehaengtem leeren "ID"-Feld) oder nil, -;; wenn keine Quell-.dwg gefunden wird bzw. sie keine Attribute hat. -(defun omni:read-src-attribs (blockname / datei srcAttribs) - (if (car (atoms-family 1 '("SSG-ILS-BLOCK-DATEI"))) - (setq datei (ssg-ils-block-datei blockname)) - ) - (if (and (null datei) (boundp '*block-path*) *block-path*) - (setq datei (strcat *block-path* blockname ".dwg")) - ) - (if datei - (progn - (setq srcAttribs (ssg-attrib-read-dwg datei)) - (if (and srcAttribs (not (assoc "ID" srcAttribs))) - (setq srcAttribs (append srcAttribs (list (cons "ID" "")))) - ) - ) - ) - srcAttribs -) - - -;; --- Aluprofil-Gerade non-interaktiv aus zwei Punkten erzeugen --- -;; -;; Skriptfaehiger Kern von omni:insert-block: baut aus zwei bekannten -;; Punkten (Anfang pt, Ende pt2) den Compound-Block (Linie + ATTDEFs) und -;; fuegt ihn ein. Fuehrt KEINE Nutzerabfrage und KEIN ssg-start/ssg-end aus - -;; der Aufrufer sichert die Umgebung und setzt OSMODE/ATTREQ/ATTDIA=0. -;; -;; blockname = Profiltyp (z.B. "AP110") -;; pt / pt2 = Anfangs-/Endpunkt (Liste x y [z]) -;; srcAttribs = Quell-Attribute (Alist) oder nil (dann Block ohne ATTDEFs) -;; textHeight / textGap = Textparameter -;; textEnt = optionaler, bereits erzeugter Vorschau-Text (Tag 1 = blockname); -;; nil -> wird hier erzeugt -;; Rueckgabe: Entity-Name des eingefuegten INSERT-Blocks oder nil. -(defun omni:make-gerade (blockname pt pt2 srcAttribs textHeight textGap textEnt / - laenge laengeStr dx dy angle angleDeg - perpX perpY textPt ed lastEnt ss e bname blockEnt - attribs attribDefs) - (setq laenge (distance (list (car pt) (cadr pt)) - (list (car pt2) (cadr pt2)))) - (setq laengeStr (rtos laenge 2 0)) - (setq dx (- (car pt2) (car pt)) - dy (- (cadr pt2) (cadr pt))) - (setq angle (atan dy dx)) - (setq angleDeg (* (/ 180.0 pi) angle)) - - ;; 1. Vorschau-Text erzeugen, falls nicht vom Aufrufer uebergeben - (if (null textEnt) - (progn - (entmake (list '(0 . "TEXT") - (cons 8 (getvar "CLAYER")) - (cons 10 (list (car pt) (cadr pt) - (if (caddr pt) (caddr pt) 0.0))) - (cons 40 textHeight) - (cons 1 blockname) - '(50 . 0.0))) - (setq textEnt (entlast)) - ) - ) - (setq lastEnt textEnt) - - ;; 2. Compound-Block: Linie bei (0,0)..(laenge,0) + ATTDEFs aus Quell-Attributen - (command "_.LINE" (list 0.0 0.0) (list laenge 0.0) "") - (setq attribDefs (ssg-attrib-alist-to-defs srcAttribs)) - (ssg-attrib-make-defs attribDefs 50.0) - - ;; Neue Entities einsammeln (alles nach textEnt) - (setq ss (ssadd)) - (setq e (entnext lastEnt)) - (while e (ssadd e ss) (setq e (entnext e))) - - ;; Block mit eindeutigem Zeitstempel-Namen erzeugen. ssg-timestamp hat nur - ;; Sekundenaufloesung - bei mehreren Aufrufen innerhalb derselben Sekunde - ;; (z.B. Streckenzug-Schleife) kollidiert der Name; dann einen laufenden - ;; Zaehler anhaengen, bis der Name frei ist. (Fruehere Variante haengte - ;; (itoa (fix (* CDATE 1000000))) an - das sprengt den 32-Bit-INT-Bereich - ;; von itoa und brach mit einem Lisp-Fehler ab.) - (setq bname (strcat blockname "_" (ssg-timestamp))) - (if (tblsearch "BLOCK" bname) - (progn - (if (null *omni-gerade-block-counter*) (setq *omni-gerade-block-counter* 0)) - (while (tblsearch "BLOCK" bname) - (setq *omni-gerade-block-counter* (1+ *omni-gerade-block-counter*)) - (setq bname (strcat blockname "_" (ssg-timestamp) "_" - (itoa *omni-gerade-block-counter*))) - ) - ) - ) - ;; Objektfang aus: sonst kann _.INSERT den Einfuegepunkt pt auf ein Objekt - ;; umfangen (z.B. den Text bei pt) und die Hoehe verfaelschen. - (setvar "OSMODE" 0) - (command "_.-BLOCK" bname (list 0.0 0.0 0.0) ss "") - - ;; Block einfuegen (ATTREQ/ATTDIA bereits auf 0) - (command "_.INSERT" bname pt 1 1 angleDeg) - (setq blockEnt (entlast)) - - ;; 3. Attribute setzen: Quell-Werte + LAENGE/A aktualisieren - (setq attribs srcAttribs) - (if (assoc "LAENGE" attribs) - (setq attribs (subst (cons "LAENGE" laengeStr) - (assoc "LAENGE" attribs) attribs)) - (setq attribs (cons (cons "LAENGE" laengeStr) attribs)) - ) - (if (assoc "A" attribs) - (setq attribs (subst (cons "A" laengeStr) - (assoc "A" attribs) attribs)) - (setq attribs (cons (cons "A" laengeStr) attribs)) - ) - (ssg-attrib-set-on blockEnt attribs) - - ;; Layer aus dem LAYER-Attribut setzen - dieselbe Vorgabe-Konvention wie in - ;; omni:insert-dxf und c:OMNI_EDIT. Die Quell-Attribute (srcAttribs) tragen - ;; den Layer bereits, er wurde hier bisher nur nicht angewendet. - (ssg-block-layer-vorgabe blockEnt bname attribs) - - ;; 4. Text oberhalb der Linie positionieren, um Linienwinkel drehen, - ;; Inhalt mit Laenge ergaenzen - (setq perpX (* (- (sin angle)) textGap) - perpY (* (cos angle) textGap)) - (setq textPt (list (+ (car pt) perpX) - (+ (cadr pt) perpY) - (if (caddr pt) (caddr pt) 0.0))) - (setq ed (entget textEnt)) - (setq ed (subst (cons 10 textPt) (assoc 10 ed) ed)) - (if (assoc 50 ed) - (setq ed (subst (cons 50 angle) (assoc 50 ed) ed)) - (setq ed (append ed (list (cons 50 angle)))) - ) - (setq ed (subst (cons 1 (strcat blockname " L=" laengeStr)) - (assoc 1 ed) ed)) - (entmod ed) - (entupd textEnt) - - ;; 5. Eindeutige ID zuweisen - (if (and blockEnt (atoms-family 1 '("ssg-id-generate"))) - (ssg-id-generate blockEnt) - ) - - (princ (ssg-textf "omni-insert-block-eingefuegt" (list bname laengeStr))) - blockEnt -) - - -;; Aluprofil-Fahrstrecke interaktiv einfuegen (siehe Ablaufbeschreibung oben). -;; Fragt Einfuege- und Endpunkt ab und delegiert die Blockerzeugung an -;; omni:make-gerade. -(defun omni:insert-block (blockname laengemax / - pt pt2 laenge textEnt textHeight textGap srcAttribs ok) - - (setq textHeight (ssg-cfg-or "omniflo" "text_height" 100.0)) - (setq textGap (ssg-cfg-or "omniflo" "text_gap" 20.0)) - - ;; 0. Attribute aus der Quell-.dwg lesen (vor ssg-start, da eigene INSERT/ERASE) - (setq srcAttribs (omni:read-src-attribs blockname)) - (if (null srcAttribs) - (progn (princ (ssg-text "omni-insert-keine-attribute")) nil) - (progn - ;; LAENGEMAX aus Quell-Attribut lesen (falls vorhanden), sonst Parameter - (if (and (assoc "LAENGEMAX" srcAttribs) - (> (strlen (cdr (assoc "LAENGEMAX" srcAttribs))) 0)) - (setq laengemax (atof (cdr (assoc "LAENGEMAX" srcAttribs)))) - ) - - (setq pt (getpoint (ssg-text "omni-prompt-einfuegepunkt"))) - (if (null pt) - (progn (princ (ssg-text "omni-abbruch-omni")) nil) - (progn - (ssg-start "OMNI Aluprofil" '(("OSMODE") ("ATTREQ") ("ATTDIA"))) - ;; ATTREQ/ATTDIA auf 0 setzen (werden durch ssg-end wiederhergestellt) - (setvar "ATTREQ" 0) - (setvar "ATTDIA" 0) - - ;; Vorschau-Text horizontal am Einfuegepunkt (waehrend Endpunktwahl) - (entmake (list '(0 . "TEXT") - (cons 8 (getvar "CLAYER")) - (cons 10 (list (car pt) (cadr pt) - (if (caddr pt) (caddr pt) 0.0))) - (cons 40 textHeight) - (cons 1 blockname) - '(50 . 0.0))) - (setq textEnt (entlast)) - - ;; Endpunkt fuer Fahrstrecke abfragen (Schleife bei Ueberschreitung) - (setq ok nil) - (while (not ok) - (setq pt2 (getpoint pt (ssg-text "omni-prompt-endpunkt-fahrstrecke"))) - (if (null pt2) - (progn - ;; Abbruch: Vorschau-Text loeschen - (command "_.ERASE" textEnt "") - (princ (ssg-text "omni-abbruch-omni")) - (setq ok T pt nil) - ) - (progn - (setq laenge (distance (list (car pt) (cadr pt)) - (list (car pt2) (cadr pt2)))) - (if (> laenge laengemax) - (alert (ssg-textf "omni-laenge-ueberschritten" - (list (rtos laenge 2 0) (rtos laengemax 2 0)))) - (progn - (omni:make-gerade blockname pt pt2 srcAttribs - textHeight textGap textEnt) - (setq ok T) - ) - ) - ) - ) - ) - - (ssg-end) - pt - ) - ) - ) - ) -) - -(defun c:OMNI_AP60 () - (omni:insert-block "AP60" (ssg-cfg-or "omniflo" "laengemax_ap60" 7000.0)) - (princ) -) -(defun c:OMNI_AP110 () - (omni:insert-block "AP110" (ssg-cfg-or "omniflo" "laengemax_ap110" 6000.0)) - (princ) -) -(defun c:OMNI_APG110 () - (omni:insert-block "APG110" (ssg-cfg-or "omniflo" "laengemax_apg110" 6000.0)) - (princ) -) - ;; ============================================================ ;; OMNIFLO WEICHEN-DIALOG ;; Generischer Dialog fuer Weichen-Auswahl nach Winkel/Typ diff --git a/Lisp/README.md b/Lisp/README.md index 8a5d093..9bf6d08 100644 --- a/Lisp/README.md +++ b/Lisp/README.md @@ -48,7 +48,7 @@ ebenfalls aktiv (Modul `KettenFoerderer.lsp`, Beschreibung in `CLAUDE.md`). Aktiv (implementiert) sind u.a.: Kreisel, Eckrad, VarioFoerderer (Standard/Etage/ Linienzug), Gefaellestrecke, Geruest (Saeulen/Rohrabhaenger/Wandbefestigung/ Rohr-Geruest-Traeger), TRO-Marker, Connections, BTMT Be-/Entladung, Scanner/ -Separator, Omniflo Boegen (APB)/TEF-Elemente/Aluprofil-Geraden (AP)/alle Weichen +Separator, Omniflo Boegen (APB)/TEF-Elemente/alle Weichen (W90/W45/WP/WK/WKomb)/Ladeschleifen/Schwenkschienen/Fahrstrecke, Kettenfoerderer, Export (Sivas/CSV), Werkzeuge (Block-/Text-Tools, Faehnchen + Stueckliste, DIN-Formate, Planquadrate) und die Tests. Die frueheren Dummy-Befehle fuer ILS-Kurven @@ -703,7 +703,6 @@ 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) | -| Geraden | `OMNI_AP60`, `OMNI_AP110`, `OMNI_APG110` | Omniflo-Geradenstuecke | | Ladeschleifen | `OMNI_LADESCHLEIFE_AP110` | Ladeschleife aus `omniflo_ladeschleifen.json` ueber DCL-Dialog (`dcl/omniflo_ladeschleifen.dcl`) einfuegen; Daten per `ssg-json-laden` (Beschreibungen enthalten Kommas). Blockdatei `.dwg` unter `DXFM_OMNIFLO` (`omni:insert-dxf` faellt auf `.dwg` zurueck, wenn keine `.dxf` existiert). Per `OMNI_EDIT` editierbar | | TEF Elemente | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade` | Feste TEF-Bauteile ohne Sivas-Auswahl, direkt per `omni:insert-dxf` an gewaehltem Punkt eingefuegt (Dateien unter `DXFM_OMNIFLO`) | | Anbaugruppen | `OMNI_STOPPER`, `OMNI_SCANNER`, `OMNI_BUERSTENBREMSE` | Implementiert | diff --git a/Lisp/TEFInsert.lsp b/Lisp/TEFInsert.lsp index c5cf2e3..9c358cd 100644 --- a/Lisp/TEFInsert.lsp +++ b/Lisp/TEFInsert.lsp @@ -3,7 +3,8 @@ ;; ;; Zeichnet eine Linie zwischen zwei vom Benutzer gewaehlten Punkten ;; und reiht darauf 1000 mm lange TEF-Geradenelemente -;; (data/omniflo//0_B10030.dxf, $INSBASE=Ursprung=Anfang des +;; (data/omniflo//0_B10030.dxf - Dimensionsrueckfall wie bei +;; omni:insert-dxf, $INSBASE=Ursprung=Anfang des ;; Elements, Ende bei lokal X=1000) aneinander. ;; ;; Ist die Linienlaenge kein exaktes Vielfaches von 1000 mm, wird fuer @@ -34,13 +35,27 @@ (if (null *tefl-blockname*) (setq *tefl-blockname* "0_B10030")) ;; ------------------------------------------------------------ -;; Pfad zur Element-DXF ermitteln (DXFM_OMNIFLO, wie omni:insert-dxf -;; in OmniModulInsert.lsp). +;; Pfad zur Element-DXF ermitteln - ueber denselben Resolver wie +;; omni:insert-dxf (omni:omniflo-datei-finden, OmniModulInsert.lsp): .dxf +;; bzw. .dwg im aktuellen Dimensionsordner, sonst Rueckfall auf den anderen +;; (2D<->3D). Das Element liegt derzeit nur in data/omniflo/2D/, ein +;; fester Pfad in DXFM_OMNIFLO (= .../3D) fand es deshalb nicht. +;; Rueckgabe: vorhandener Dateipfad; ohne Fund der erwartete .dxf-Pfad (fuer +;; die Fehlermeldung); nil nur, wenn DXFM_OMNIFLO fehlt. ;; ------------------------------------------------------------ -(defun tefl-dxf-pfad ( / omniflo-pfad) +(defun tefl-dxf-pfad ( / omniflo-pfad gefunden) (setq omniflo-pfad (getenv "DXFM_OMNIFLO")) (if omniflo-pfad - (strcat (vl-string-translate "\\" "/" omniflo-pfad) "/" *tefl-blockname* ".dxf") + (progn + (if (null (car (atoms-family 1 '("OMNI:OMNIFLO-DATEI-FINDEN")))) + (ssg-ensure "OmniModulInsert") + ) + (setq gefunden (omni:omniflo-datei-finden *tefl-blockname* omniflo-pfad)) + (if gefunden + gefunden + (strcat (vl-string-translate "\\" "/" omniflo-pfad) "/" *tefl-blockname* ".dxf") + ) + ) ) ) diff --git a/README.md b/README.md index 89a9e1c..6a3c7a6 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ SSG_LIB │ └── QC Linie mit GF (auch U-Form) → QcLinieMitGf / QcLinieMitGfUForm ├── Omniflo │ ├── Fahrstrecke / Fahrstrecken beschriften → OMNI_FAHRSTRECKE / OMNI_FAHRSTRECKE_BESCHRIFTEN -│ ├── Boegen APB110 / APB60, Aluprofil Gerade (AP60/AP110/APG110) +│ ├── Boegen APB110 / APB60 │ ├── Weichen (90/45/Parallel/22.5, Delta, Star) │ ├── TEF Elemente (inkl. TEF Gerade auf Linie → TEF_FOERDERER_LINIE) │ ├── Anbaugruppen (Stopper, Scanner, Buerstenbremse) diff --git a/data/json/component_defaults.json b/data/json/component_defaults.json index a5473eb..7a2918e 100644 --- a/data/json/component_defaults.json +++ b/data/json/component_defaults.json @@ -25,9 +25,6 @@ "text_gap": 20.0, "default_hoehe": "2000", "default_drehung": "0", - "laengemax_ap60": 7000.0, - "laengemax_ap110": 6000.0, - "laengemax_apg110": 6000.0, "default_gerade_laenge": "2000", "bogen_winkel": [180, 90, 67.5, 45, 22.5], "weichen_winkel_90": 90, diff --git a/doc/json-input-lisp.md b/doc/json-input-lisp.md index 5fecd8f..ac30d70 100644 --- a/doc/json-input-lisp.md +++ b/doc/json-input-lisp.md @@ -34,7 +34,6 @@ Literale - gleiches Schema, noch nicht auf das gemeinsame Modul umgestellt. | [VF-Linienzug-Kette (Spec)](#5-vf-linienzug-kette-spec) | Kopf mit `spec_id`, danach `glied`/`sub` | `vsp-bau-aus-spec` (Replay durch `vf-linienzug-modus`) | `start_punkt` = Kettenanfang | `hundm05.json` | | [VF-Linienzug (Journal)](#6-vf-linienzug-eingabe-journal) | Kopf mit `test_id`, danach `typ` = `point_abs`/`real`/`string`/... | `vfl-journal-replay-start` + `vf-linienzug-modus` | erstes `point_abs` | `linienzug_tests.json`, `hm_recformat.json` | | [Omniflo Bogen/Weiche](#71-bogen-und-weiche) | `"type": "bogen"` / `"weiche"` + `sivasnr` | `_.INSERT` der `.dxf` (Kern `omni:insert-dxf` fragt den Punkt interaktiv) | `x`,`y`, Z = `hoehe` | `omniflo_tests.json`, `omniflo_strecke_tests.json` | -| [Omniflo Gerade](#72-aluprofil-gerade) | `"type": "gerade"` + `profil` | `omni:make-gerade` | `x`,`y` -> `x_ende`,`y_ende`, Z = `hoehe` | `omniflo_strecke_tests.json` | | [Waagrechte Foerderstrecke](#8-waagrechte-foerderstrecke-gerade---noch-ohne-bau-pfad) | `"typ": "gerade"` + `startpunkt` | **kein Bau-Pfad** (wird gemeldet und uebersprungen) | `startpunkt`, `endpunkt` | `dematic_arvato.json` | Nicht aus JSON baubar (es gibt keine Testdaten und keinen Treiber): Eckrad, @@ -380,18 +379,6 @@ Sivas-Nummern: `data/json/omniflo_boegen.json`, `omniflo_weichen.json`. Treiber: `omni:test-insert` (`test_omniflo.lsp`), `omnistr:insert-bogen` (`test_omniflo_strecke.lsp`). -### 7.2 Aluprofil-Gerade - -```json -{ "seq": 1, "type": "gerade", "profil": "AP110", "laenge": 1000.0, - "x": 2000.0, "y": 0.0, "x_ende": 3000.0, "y_ende": 0.0, - "drehung": 0.0, "hoehe": 2000, "id": "0003" } -``` - -`profil` = `"AP60"`, `"AP110"` oder `"APG110"`. Die Gerade laeuft von -(`x`,`y`) nach (`x_ende`,`y_ende`) auf Z = `hoehe`; Laenge und Drehung folgen -aus den Punkten (`laenge` ist nur Doku). Gebaut mit `omni:make-gerade`. - --- ## 8. Waagrechte Foerderstrecke (`gerade`) - noch ohne Bau-Pfad @@ -418,7 +405,7 @@ ueberspringt sie. Passende Primitive waere `insert-hz-scaled-block-by-ks` | `foerderer_tests.json` | Kopf `y_abstand` + 17 VF Standard | `TEST_FOERDERER` | | `gefaellestrecke_tests.json` | Kopf + GF Modus 1/2/3 | `TEST_GEFAELLESTRECKE` | | `omniflo_tests.json` | 27 Boegen, 80 Weichen | `TEST_OMNIFLO` | -| `omniflo_strecke_tests.json` | Streckenzug aus Geraden und Boegen | `TEST_OMNIFLO_STRECKE` | +| `omniflo_strecke_tests.json` | Streckenzug aus Boegen und Weiche | `TEST_OMNIFLO_STRECKE` | | `linienzug_tests.json` / `_stufe2.json` | Eingabe-Journal je einer Kette | `TEST_LINIENZUG` / `TEST_LINIENZUG_STUFE2` | | `hm_recformat.json` | 5 HundM-Ketten als Journal | `TEST_HM_RECFORMAT` | | `hundm05.json` | 5 HundM-Ketten als Spec + Kreisel, Separatoren, Scanner, BTMT | `TEST_HUNDM05`, `VF_SPEC_BAU` | diff --git a/doc/kommandos.md b/doc/kommandos.md index 79ab06d..0e9654b 100644 --- a/doc/kommandos.md +++ b/doc/kommandos.md @@ -91,7 +91,6 @@ 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_AP60`, `OMNI_AP110`, `OMNI_APG110` | Gerade Profile einfuegen | | `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 | diff --git a/doc/lisp_methods.md b/doc/lisp_methods.md index 72c3163..6da1992 100644 --- a/doc/lisp_methods.md +++ b/doc/lisp_methods.md @@ -29,7 +29,6 @@ Einheiten: mm und Grad. `hz` = Fahrtrichtung in der XY-Ebene, 0 = +X, | Separator, Scanner | `ILS_SEPARATOR_INSERT`, `ILS_SCANNER_INSERT` | - (Schleife mit `getpoint`); Kern: `ssg-ils-block-laden` + `_.INSERT` | Einzelblock | `SSG_LIB_Commands.lsp`, `ssg_core.lsp` | | BTMT, Eingang/Ausgang | `ILS_BTMT_*`, `ILS_EINGANG_INSERT`/`ILS_AUSGANG_INSERT` | wie Separator | Einzelblock | `SSG_LIB_Commands.lsp` | | Omniflo Bogen/Weiche/TEF | `OMNI_APB_*`, `OMNI_W*_*`, `OMNI_TEF_*` ... | `_.INSERT` der `.dxf` (Kern `omni:insert-dxf` fragt den Punkt) | Einzelblock | `OmniModulInsert.lsp` | -| Omniflo Gerade | `OMNI_AP60`/`AP110`/`APG110` | `omni:make-gerade` | Compound-Block | `OmniModulInsert.lsp` | | TEF-Foerderer-Linie | `TEF_FOERDERER_LINIE` | `tefl-insert-element` (ein Element) | Einzelbloecke | `TEFInsert.lsp` | | Geruest (Saeule, Rohrabhaenger, Wandbefestigung) | `GERUEST`, `GERUEST_SAEULEN` ... | `geruest-block-bauen` | `GR__` | `GeruestInsert.lsp` | | Geruest-Traeger | `GERUEST_TRAEGER` | `geruest-traeger-block-bauen` | `GR__` | `GeruestInsert.lsp` | @@ -256,8 +255,6 @@ beantworten, nicht ungebremst: eine Rueckfrage, die Enter ablehnt, haelt |---|---| | `omni:insert-dxf (sivasnr-str hoehe drehung)` | `%DXFM_OMNIFLO%/.dxf` einfuegen, `HOEHE`/`DREHUNG` setzen, Layer. **Einfuegepunkt per Maus** (`pause`); Rueckgabe: Einfuegepunkt oder nil | | `omni:insert-from-entry (dlg-result)` | Dialog-Ergebnis von Bogen/Weiche -> `omni:insert-dxf` | -| `omni:make-gerade (blockname pt pt2 srcAttribs textHeight textGap textEnt)` | **skriptfaehig**: Aluprofil-Gerade `"AP60"`/`"AP110"`/`"APG110"` von `pt` nach `pt2` als Compound-Block mit Text. `srcAttribs` per `omni:read-src-attribs`, `textEnt` nil. Kein `ssg-start` - Aufrufer setzt OSMODE/ATTREQ/ATTDIA = 0. Rueckgabe: Entity | -| `omni:insert-block (blockname laengemax)` | Befehls-Kern der Geraden (fragt `pt`/`pt2` per `getpoint`) | | `omni:ladeschleifen-dialog (profiltyp init-hoehe)` | Dialog Ladeschleife, danach `omni:insert-dxf` | Skriptfaehig fuer Boegen/Weichen: `_.INSERT` der DXF direkt mit Punkt diff --git a/lang/de_DE.json b/lang/de_DE.json index 8fa019f..da65fa6 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -362,8 +362,6 @@ "omni-edit-dxf-nicht-gefunden": "DXF nicht gefunden: %1", "omni-einfuegen-info": "\n[OMNI] Einfuegen: %1 (%2)", "omni-fehler-dxf-nicht-gefunden": "\n[OMNI] FEHLER: DXF nicht gefunden: %1", - "omni-insert-block-eingefuegt": "\n[OMNI] %1 eingefuegt. Laenge=%2 mm", - "omni-laenge-ueberschritten": "Die gewuenschte Fahrstreckenlaenge von %1 mm ueberschreitet die Maximallaenge von %2 mm des Fahrstreckenprofils.\nBitte neu definieren!", "omni-weiche-info-breite": "\n Breite: %1", "omni-weiche-info-kurvenrichtung": "\n KurvenRichtung: %1", "omni-weiche-info-kurvenwinkel": "\n KurvenWinkel: %1", @@ -537,7 +535,6 @@ "omni-abbruch-ladeschleife": "\n[LADESCHLEIFE] Abgebrochen.", "omni-ladeschleife-dialog-ladefehler": "Ladeschleifen-Dialog konnte nicht geladen werden.", "omni-ladeschleife-keine-gefunden": "Keine Ladeschleifen%1 gefunden.", - "omni-abbruch-omni": "\n[OMNI] Abgebrochen.", "omni-abbruch-weiche": "\n[WEICHE] Abgebrochen.", "omni-bogen-dialog-ladefehler": "Bogen-Dialog konnte nicht geladen werden.", "omni-edit-kein-block": "Kein Block ausgewaehlt!", @@ -547,10 +544,7 @@ "omni-fehler-dxfm-omniflo": "\n[OMNI] FEHLER: DXFM_OMNIFLO nicht gesetzt!", "omni-info-bogen-prompt": "\nSivasId des Bogens eingeben: ", "omni-info-weiche-prompt": "\nSivasId der Weiche eingeben: ", - "omni-insert-keine-attribute": "\n[OMNI] Keine Attribute im Quell-Block gefunden.", "omni-prompt-drehwinkel": "\nDrehwinkel angeben: ", - "omni-prompt-einfuegepunkt": "\nEinfuegepunkt waehlen: ", - "omni-prompt-endpunkt-fahrstrecke": "\nEndpunkt der Fahrstrecke waehlen: ", "omni-weiche-dialog-ladefehler": "Weichen-Dialog konnte nicht geladen werden.", "prompt-wahl-1-2-3-4": "\nIhre Wahl (1/2/3/4) [1]: ", "vfc-alert-keine-gueltige-linie": "Keine gueltige Linie ausgewaehlt!", diff --git a/lang/en_GB.json b/lang/en_GB.json index 9d87d38..72ed56d 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -362,8 +362,6 @@ "omni-edit-dxf-nicht-gefunden": "DXF not found: %1", "omni-einfuegen-info": "\n[OMNI] Inserting: %1 (%2)", "omni-fehler-dxf-nicht-gefunden": "\n[OMNI] ERROR: DXF not found: %1", - "omni-insert-block-eingefuegt": "\n[OMNI] %1 inserted. Length=%2 mm", - "omni-laenge-ueberschritten": "The requested travel path length of %1 mm exceeds the maximum length of %2 mm of the travel path profile.\nPlease redefine!", "omni-weiche-info-breite": "\n Width: %1", "omni-weiche-info-kurvenrichtung": "\n Curve direction:%1", "omni-weiche-info-kurvenwinkel": "\n Curve angle: %1", @@ -537,7 +535,6 @@ "omni-abbruch-ladeschleife": "\n[LOADING LOOP] Cancelled.", "omni-ladeschleife-dialog-ladefehler": "Loading loop dialog could not be loaded.", "omni-ladeschleife-keine-gefunden": "No loading loops%1 found.", - "omni-abbruch-omni": "\n[OMNI] Cancelled.", "omni-abbruch-weiche": "\n[SWITCH] Cancelled.", "omni-bogen-dialog-ladefehler": "Arc dialog could not be loaded.", "omni-edit-kein-block": "No block selected!", @@ -547,10 +544,7 @@ "omni-fehler-dxfm-omniflo": "\n[OMNI] ERROR: DXFM_OMNIFLO not set!", "omni-info-bogen-prompt": "\nEnter Sivas ID of the arc: ", "omni-info-weiche-prompt": "\nEnter Sivas ID of the switch: ", - "omni-insert-keine-attribute": "\n[OMNI] No attributes found on source block.", "omni-prompt-drehwinkel": "\nSpecify rotation angle: ", - "omni-prompt-einfuegepunkt": "\nSelect insertion point: ", - "omni-prompt-endpunkt-fahrstrecke": "\nSelect end point of the travel path: ", "omni-weiche-dialog-ladefehler": "Switch dialog could not be loaded.", "prompt-wahl-1-2-3-4": "\nYour choice (1/2/3/4) [1]: ", "vfc-alert-keine-gueltige-linie": "No valid line selected!", diff --git a/menu/SSG_LIB.cui b/menu/SSG_LIB.cui index bd3f31b..97bd176 100644 --- a/menu/SSG_LIB.cui +++ b/menu/SSG_LIB.cui @@ -212,24 +212,6 @@ ^C^C(ssg-ensure "OmniModulInsert") OMNI_APB60_90 - - - AP 60 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_AP60 - - - - - AP 110 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_AP110 - - - - - APG 110 - ^C^C(ssg-ensure "OmniModulInsert") OMNI_APG110 - - Einfach 90 @@ -1211,7 +1193,6 @@ - @@ -1279,27 +1260,6 @@ - - Aluprofil Gerade - - AP 60 - - - - - - AP 110 - - - - - - APG 110 - - - - - Weichen diff --git a/menu/SSG_LIB.mnu b/menu/SSG_LIB.mnu index 896026e..9a3479b 100644 --- a/menu/SSG_LIB.mnu +++ b/menu/SSG_LIB.mnu @@ -48,10 +48,6 @@ [<-180 ]^C^C(ssg-ensure "OmniModulInsert") OMNI_APB_650_180 [->Boegen APB60] [<-90]^C^C(ssg-ensure "OmniModulInsert") OMNI_APB60_90 -[->Aluprofil Gerade] -[AP 60]^C^C(ssg-ensure "OmniModulInsert") OMNI_AP60 -[AP 110]^C^C(ssg-ensure "OmniModulInsert") OMNI_AP110 -[<-APG 110]^C^C(ssg-ensure "OmniModulInsert") OMNI_APG110 [->Weichen] [Einfach 90]^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Einfach [Doppel 90]^C^C(ssg-ensure "OmniModulInsert") OMNI_W90_Doppel diff --git a/tests/README.md b/tests/README.md index ce4c51c..e945802 100644 --- a/tests/README.md +++ b/tests/README.md @@ -338,7 +338,7 @@ tests/ testdata/ kreisel_tests.json # Testfall-Definitionen fuer Kreisel omniflo_tests.json # Testfall-Definitionen fuer Omniflo - omniflo_strecke_tests.json # Streckenzug: 4 Geraden + 2 Boegen + 1 Weiche (7 Elemente) + omniflo_strecke_tests.json # Streckenzug: 2 Boegen + 1 Weiche (3 Elemente) hm_recformat.json # Aufzeichnung: rohes Journal der 5 Ketten hundm05.json # daraus abgeleitete Spec (wird erweitert) foerderer_tests.json / mubea.json / ... @@ -707,14 +707,13 @@ def _ref_dxf(): ### test_omniflo_strecke.py -Streckenzug **4 Geraden -> 180-Grad-Kurve (4x 45-Grad-Bogen) -> 4 Geraden**. +Streckenzug aus **2 Boegen + 1 Weiche**. Die Geometrie wird ohne BricsCAD direkt aus `omniflo_strecke_tests.json` geprueft. | Klasse | Prueft | |---|---| -| `TestStreckeStruktur` | 4+4+4 = 12 Elemente, Reihenfolge der Gruppen, Typen | +| `TestStreckeStruktur` | 3 Elemente, Gruppenverteilung, Typen | | `TestStreckeKatalog` | Bogen-SivasNummern existieren in `omniflo_boegen.json` (Radius/Winkel) | -| `TestStreckeGeometrie` | Lueckenlose Verkettung, Kurvensumme 180 Grad, gemeinsamer Bogen-Mittelpunkt | | `TestStreckeResults` | omniflo_strecke_results.json aus BricsCAD: Elemente vollstaendig, Status OK | ## Umgebungsvariablen diff --git a/tests/test_omniflo_strecke.lsp b/tests/test_omniflo_strecke.lsp index c3af79f..43df599 100644 --- a/tests/test_omniflo_strecke.lsp +++ b/tests/test_omniflo_strecke.lsp @@ -3,20 +3,12 @@ ;; ;; Baut aus tests/testdata/omniflo_strecke_tests.json einen verketteten ;; Streckenzug auf: -;; 4 Geraden -> 180-Grad-Kurve (4x 45-Grad-Bogen) -> 4 Geraden +;; 2 Boegen + 1 Weiche ;; -;; Jedes Element traegt bereits seine absolute Platzierung (x, y, drehung) -;; sowie Endpunkt (x_ende, y_ende). Die Elemente sind lueckenlos verkettet -;; (Ende[i] = Anfang[i+1]), sodass eine durchgehende U-foermige Strecke -;; entsteht. +;; Jedes Element traegt bereits seine absolute Platzierung (x, y, drehung). ;; -;; - Boegen (type "bogen"): DXF aus DXFM_OMNIFLO an (x,y) mit Drehung -;; einfuegen (wie test_omniflo.lsp). -;; - Geraden (type "gerade"): echter Aluprofil-Block ueber den skript- -;; faehigen Kern omni:make-gerade (aus OmniModulInsert.lsp). Fehlt die -;; Quell-.dwg (kein AP110.dwg im Blockpfad), werden Ersatz-Attribute -;; verwendet, sodass dennoch ein Compound-Block (Linie + ATTDEFs) statt -;; einer nackten Linie entsteht. +;; - Boegen/Weichen (type "bogen"): DXF aus DXFM_OMNIFLO an (x,y) mit +;; Drehung einfuegen (wie test_omniflo.lsp). ;; ;; Ergebnisse -> tests/output/omniflo_strecke_results.json ;; (via omniflo_strecke:export-results, aufgerufen von SSG_RUN_ALL_TESTS @@ -90,54 +82,6 @@ ) -;; --- Gerade non-interaktiv als echten Aluprofil-Block erzeugen --- -;; Nutzt den skriptfaehigen Kern omni:make-gerade aus OmniModulInsert.lsp. -;; profil = Profiltyp (z.B. "AP110") -;; pt-anf = Anfangspunkt, pt-end = Endpunkt (bestimmen Laenge + Drehung) -;; hoehe-str / drehung-str = Attributwerte HOEHE/DREHUNG -;; Rueckgabe: Block-Entity oder nil. -(defun omnistr:build-gerade (profil pt-anf pt-end hoehe-str drehung-str / - srcAttribs textHeight textGap blockEnt) - (dbgf "omnistr:build-gerade") - (dbgmsg (strcat "profil=" (if profil profil "nil") - " hoehe=" (if hoehe-str hoehe-str "nil") - " drehung=" (if drehung-str drehung-str "nil"))) - (dbgreturn - (if (null (car (atoms-family 1 '("OMNI:MAKE-GERADE")))) - (progn - ;; Precondition-Fehler (Modul nicht geladen): bleibt im Fenster sichtbar - (princ "\n[TEST_OMNIFLO_STRECKE] FEHLER: omni:make-gerade nicht geladen (OmniModulInsert.lsp)!") - nil - ) - (progn - (setq textHeight (ssg-cfg-or "omniflo" "text_height" 100.0)) - (setq textGap (ssg-cfg-or "omniflo" "text_gap" 20.0)) - ;; Quell-Attribute lesen; falls keine .dwg vorhanden, Ersatz erzeugen - (setq srcAttribs (omni:read-src-attribs profil)) - (if (null srcAttribs) - (progn - (dbgmsg (strcat "keine Quell-.dwg fuer " profil " - Ersatz-Attribute")) - (setq srcAttribs (list (cons "PROFILTYP" profil) - (cons "HOEHE" (if hoehe-str hoehe-str "2000")) - (cons "ID" ""))) - ) - ) - (setvar "ATTREQ" 0) - (setvar "ATTDIA" 0) - (setq blockEnt (omni:make-gerade profil pt-anf pt-end - srcAttribs textHeight textGap nil)) - (if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT")) - (ssg-attrib-set-on blockEnt - (list (cons "HOEHE" (if hoehe-str hoehe-str "2000")) - (cons "DREHUNG" (if drehung-str drehung-str "0")))) - ) - blockEnt - ) - ) - ) -) - - ;; --- Ergebnis eines Streckenelements als JSON-String erzeugen --- (defun omnistr:test-result-json (test-id seq typ description status / ) (strcat " {\n" @@ -184,9 +128,9 @@ ;; Liest omniflo_strecke_tests.json und baut den Streckenzug auf. ;; ============================================================ (defun c:TEST_OMNIFLO_STRECKE (/ tests-json-pfad elemente - idx eintrag typ sivasnr profil hoehe-str drehung-str - description x-val y-val xe-val ye-val seq - insert-pt pt-end anzahl-ok anzahl-fehler + idx eintrag typ sivasnr hoehe-str drehung-str + description x-val y-val seq + insert-pt anzahl-ok anzahl-fehler results-list ergebnis) (ssg-start "TEST_OMNIFLO_STRECKE" @@ -245,22 +189,15 @@ (if (null drehung-str) (setq drehung-str "0")) (if (numberp drehung-str) (setq drehung-str (rtos drehung-str 2 4))) - ;; Anfangs- und Endpunkt lesen - (setq x-val (ssg-val eintrag "x") - y-val (ssg-val eintrag "y") - xe-val (ssg-val eintrag "x_ende") - ye-val (ssg-val eintrag "y_ende")) - (if (null x-val) (setq x-val 0.0)) - (if (null y-val) (setq y-val 0.0)) - (if (null xe-val) (setq xe-val x-val)) - (if (null ye-val) (setq ye-val y-val)) - (if (not (numberp x-val)) (setq x-val (atof x-val))) - (if (not (numberp y-val)) (setq y-val (atof y-val))) - (if (not (numberp xe-val)) (setq xe-val (atof xe-val))) - (if (not (numberp ye-val)) (setq ye-val (atof ye-val))) + ;; Einfuegepunkt lesen + (setq x-val (ssg-val eintrag "x") + y-val (ssg-val eintrag "y")) + (if (null x-val) (setq x-val 0.0)) + (if (null y-val) (setq y-val 0.0)) + (if (not (numberp x-val)) (setq x-val (atof x-val))) + (if (not (numberp y-val)) (setq y-val (atof y-val))) (setq insert-pt (list x-val y-val (atof hoehe-str))) - (setq pt-end (list xe-val ye-val (atof hoehe-str))) (dbgmsg (strcat (itoa seq) ". " (if typ typ "?") ": " (if description description "") @@ -273,10 +210,6 @@ ((= typ "bogen") (setq sivasnr (ssg-val eintrag "sivasnr")) (omnistr:insert-bogen sivasnr insert-pt hoehe-str drehung-str)) - ((= typ "gerade") - (setq profil (ssg-val eintrag "profil")) - (if (null profil) (setq profil "AP110")) - (omnistr:build-gerade profil insert-pt pt-end hoehe-str drehung-str)) (T (dbgmsg (strcat "WARNUNG: unbekannter Typ '" (if typ typ "nil") "'")) diff --git a/tests/test_omniflo_strecke.py b/tests/test_omniflo_strecke.py index 27d6a73..2166c5f 100644 --- a/tests/test_omniflo_strecke.py +++ b/tests/test_omniflo_strecke.py @@ -4,28 +4,25 @@ test_omniflo_strecke.py - Validiert den Omniflo-Streckenzug. Testfall (tests/testdata/omniflo_strecke_tests.json), aktuelles Datenmodell: - 7 Elemente: 2x gerade_unten (Fahrtrichtung 0 Grad), 2x gerade_oben - (Fahrtrichtung 180 Grad), 2x bogen (echte Omniflo-Boegen), 1x weiche. + 3 Elemente: 2x bogen (echte Omniflo-Boegen), 1x weiche. Prueft (ohne BricsCAD): - 1. Struktur: 7 Elemente in der richtigen Gruppen-/Typ-Verteilung, seq lueckenlos + 1. Struktur: 3 Elemente in der richtigen Gruppen-/Typ-Verteilung, seq lueckenlos 2. Katalog: die Bogen-SivasNummern (gruppe "bogen") existieren in data/json/omniflo_boegen.json mit passendem Radius/Kurvenwinkel; die Weichen-SivasNummer in data/json/omniflo_weichen.json - 3. Geometrie: die Geraden haben eine zur Laenge passende Distanz Anfang->Ende - und behalten ihre Fahrtrichtung (drehung). Hinweis: Boegen/Weichen tragen im aktuellen Testdaten-Modell KEINE Endpunkte (x_ende/y_ende = null) und keine Mittelpunkte - die frueheren Halbkreis-/ Verkettungs-Tests (drehung_ende, x_mitte, kurve_180, 12 Elemente) bezogen sich -auf ein anderes, nicht mehr vorhandenes Modell und wurden entfernt. +auf ein anderes, nicht mehr vorhandenes Modell und wurden entfernt. Die +Aluprofil-Geraden (AP60/AP110/APG110) wurden samt Menue und Befehlen entfernt. Optional (nach BricsCAD-Lauf c:TEST_OMNIFLO_STRECKE): - 4. Integrationstest gegen tests/output/omniflo_strecke_results.json + 3. Integrationstest gegen tests/output/omniflo_strecke_results.json """ import json -import math import os import pytest @@ -103,8 +100,8 @@ def weichen_lookup(): class TestStreckeStruktur: def test_gesamtzahl(self, strecke): - """4 Geraden + 2 Boegen + 1 Weiche = 7 Elemente.""" - assert len(strecke) == 7, f"Erwartet 7 Elemente, erhalten {len(strecke)}" + """2 Boegen + 1 Weiche = 3 Elemente.""" + assert len(strecke) == 3, f"Erwartet 3 Elemente, erhalten {len(strecke)}" def test_seq_lueckenlos(self, strecke): """seq muss lueckenlos bei 1 beginnend aufsteigen.""" @@ -112,33 +109,18 @@ class TestStreckeStruktur: assert el["seq"] == i + 1, f"Element {i}: seq={el['seq']}, erwartet {i + 1}" def test_gruppen_verteilung(self, strecke): - """Erwartete Gruppen-Verteilung: 2x gerade_unten, 2x gerade_oben, - 2x bogen, 1x weiche.""" + """Erwartete Gruppen-Verteilung: 2x bogen, 1x weiche.""" from collections import Counter ist = Counter(el["gruppe"] for el in strecke) - erwartet = {"gerade_unten": 2, "gerade_oben": 2, "bogen": 2, "weiche": 1} - assert dict(ist) == erwartet, f"Gruppen-Verteilung abweichend:\n Ist: {dict(ist)}\n Soll: {erwartet}" + erwartet = {"bogen": 2, "weiche": 1} + assert dict(ist) == erwartet, ( + f"Gruppen-Verteilung abweichend: Ist {dict(ist)}, Soll {erwartet}") def test_typen(self, strecke): - """gerade_* -> type 'gerade', bogen/weiche -> type 'bogen'.""" + """bogen/weiche -> type 'bogen'.""" for el in strecke: - erwartet = "gerade" if el["gruppe"].startswith("gerade") else "bogen" - assert el["type"] == erwartet, ( - f"seq {el['seq']}: type={el['type']}, erwartet {erwartet}") - - def test_vier_geraden(self, strecke): - """Vier Geraden gesamt (2 unten + 2 oben).""" - assert sum(1 for el in strecke if el["type"] == "gerade") == 4 - - def test_geraden_richtungen(self, strecke): - """gerade_unten faehrt 0 Grad, gerade_oben 180 Grad (Gegenrichtung).""" - for el in strecke: - if el["gruppe"] == "gerade_unten": - assert el["drehung"] == pytest.approx(0.0, abs=_TOL), ( - f"seq {el['seq']}: gerade_unten drehung={el['drehung']}, erwartet 0") - elif el["gruppe"] == "gerade_oben": - assert el["drehung"] == pytest.approx(180.0, abs=_TOL), ( - f"seq {el['seq']}: gerade_oben drehung={el['drehung']}, erwartet 180") + assert el["type"] == "bogen", ( + f"seq {el['seq']}: type={el['type']}, erwartet bogen") # --------------------------------------------------------------------------- @@ -174,31 +156,7 @@ class TestStreckeKatalog: # --------------------------------------------------------------------------- -# 3. Geometrie der Geraden -# --------------------------------------------------------------------------- - -class TestStreckeGeometrie: - - def test_geraden_laenge(self, strecke): - """Die euklidische Distanz Anfang->Ende entspricht der Laenge.""" - for el in strecke: - if el["type"] != "gerade": - continue - dist = math.hypot(el["x_ende"] - el["x"], el["y_ende"] - el["y"]) - assert dist == pytest.approx(el["laenge"], abs=0.5), ( - f"seq {el['seq']}: Distanz {dist:.2f} != Laenge {el['laenge']}") - - def test_geraden_haben_endpunkt(self, strecke): - """Geraden tragen einen Endpunkt (x_ende/y_ende gesetzt).""" - for el in strecke: - if el["type"] != "gerade": - continue - assert el.get("x_ende") is not None and el.get("y_ende") is not None, ( - f"seq {el['seq']}: Gerade ohne Endpunkt") - - -# --------------------------------------------------------------------------- -# 4. Integrationstest gegen BricsCAD-Ergebnis (optional) +# 3. Integrationstest gegen BricsCAD-Ergebnis (optional) # --------------------------------------------------------------------------- class TestStreckeResults: diff --git a/tests/testdata/omniflo_strecke_tests.json b/tests/testdata/omniflo_strecke_tests.json index 4889639..29c460d 100644 --- a/tests/testdata/omniflo_strecke_tests.json +++ b/tests/testdata/omniflo_strecke_tests.json @@ -1,66 +1,6 @@ [ { "seq": 1, - "gruppe": "gerade_unten", - "type": "gerade", - "profil": "AP110", - "laenge": 1000.0, - "x": 2000.0, - "y": 0.0, - "drehung": 0.0, - "x_ende": 3000.0, - "y_ende": 0.0, - "hoehe": 2000, - "id": "0003", - "description": "Gerade AP110 L=1000" - }, - { - "seq": 2, - "gruppe": "gerade_unten", - "type": "gerade", - "profil": "AP110", - "laenge": 1000.0, - "x": 3000.0, - "y": 0.0, - "drehung": 0.0, - "x_ende": 4000.0, - "y_ende": 0.0, - "hoehe": 2000, - "id": "0004", - "description": "Gerade AP110 L=1000" - }, - { - "seq": 3, - "gruppe": "gerade_oben", - "type": "gerade", - "profil": "AP110", - "laenge": 1000.0, - "x": 4000.0, - "y": 990.34, - "drehung": 180.0, - "x_ende": 3000.0, - "y_ende": 990.34, - "hoehe": 2000, - "id": "0005", - "description": "Gerade AP110 L=1000" - }, - { - "seq": 4, - "gruppe": "gerade_oben", - "type": "gerade", - "profil": "AP110", - "laenge": 1000.0, - "x": 3000.0, - "y": 990.34, - "drehung": 180.0, - "x_ende": 2000.0, - "y_ende": 990.34, - "hoehe": 2000, - "id": "0006", - "description": "Gerade AP110 L=1000" - }, - { - "seq": 5, "gruppe": "bogen", "type": "bogen", "sivasnr": "821104022", @@ -74,7 +14,7 @@ "description": "APB 110 R 400/90 - 500/500" }, { - "seq": 6, + "seq": 2, "gruppe": "bogen", "type": "bogen", "sivasnr": "821104022", @@ -88,7 +28,7 @@ "description": "APB 110 R 400/90 - 500/500" }, { - "seq": 7, + "seq": 3, "gruppe": "weiche", "type": "bogen", "sivasnr": "834372100",