4d0d689815
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
324 lines
16 KiB
Common Lisp
324 lines
16 KiB
Common Lisp
;; ============================================================
|
|
;; test_dematic_arvato.lsp - Nachbau des Abschnitts Flowpuffer/Kreisel der
|
|
;; Anlage Dematic/Arvato.
|
|
;;
|
|
;; Datenquelle: tests/testdata/dematic_arvato.json. Entstehung in zwei
|
|
;; Stufen:
|
|
;; 1. Vorlage aus der Fremdzeichnung (Scanner, raet vieles):
|
|
;; python lib/dxf_scan_components.py \
|
|
;; C:/develop/sps_skel/data/Dematic_arvato_reduced.dxf data \
|
|
;; tests/testdata/dematic_arvato.json --projekt Arvato \
|
|
;; --fenster -2534 -4549 49466 29451 --ohne-hoehen \
|
|
;; --kreisel-hoehe 35860.37 12519.72 2437 \
|
|
;; --kreisel-hoehe 36661.24 24878.8 1826
|
|
;; 2. Vorlage mit diesem Treiber bauen, in BricsCAD von Hand korrigieren
|
|
;; und ergaenzen (VF-Ketten, Hoehen, Sensoren aufgeraeumt), als DXF
|
|
;; speichern und daraus die Testdaten neu schreiben - AKTUELLER STAND:
|
|
;; python lib/dxf_anlage_export.py \
|
|
;; C:/develop/sps_skel/data/Dematic_TST.dxf \
|
|
;; tests/testdata/dematic_arvato.json --projekt Arvato
|
|
;;
|
|
;; Eintragsarten:
|
|
;; "function": "insert" ohne "block" -> Kreisel (hundm05:bau-kreisel ->
|
|
;; kreisel-insert-script; x/y = Einfuegepunkt,
|
|
;; abstand = Mittenabstand AN8-SP8)
|
|
;; "function": "insert" + "block" -> Einzelblock (hundm05:bau-sensor)
|
|
;; "typ": "standard"/"etage" + "test_id"
|
|
;; -> VarioFoerderer ueber mubea:vario-bauen
|
|
;; (mubea-Schema: deltaL, deltaH, richtung,
|
|
;; winkel, L_GF1, seite, hz, x/y/z), optional
|
|
;; "motorseite"
|
|
;; "typ": "linienzug_journal"
|
|
;; -> Linienzug-Kette: das aufgezeichnete Eingabe-
|
|
;; Journal (SSG_VF_EDIT) wird 1:1 abgespielt
|
|
;; (vsp-bau-journal) - keine Spec, weil der
|
|
;; Dialog neuer ist als die Spec-Grammatik
|
|
;; "modus": 1 -> Gefaellestrecke ueber mubea:gf-bauen
|
|
;; (start_mm + deltaL_mm, kein Endpunkt). Mit
|
|
;; hoehe_ende_mm (Hoehe des Kreisels am Ende)
|
|
;; rechnet dematic_arvato:gf-winkel den Winkel,
|
|
;; sonst gilt winkel_grad.
|
|
;; "typ": "gerade" -> waagrechter Foerderer aus der Scanner-Vorlage -
|
|
;; kein Bau-Pfad, wird gemeldet und uebersprungen
|
|
;;
|
|
;; Reihenfolge wie mubea.json (VF vor GF): gf-init-bibliothek setzt die
|
|
;; globalen AS/ES-Masse um, siehe mubea:ensure-gf-init.
|
|
;;
|
|
;; Keine eigene Bau-Logik: hundm05:bau-kreisel/-sensor aus
|
|
;; tests/test_hundm05.lsp und mubea:gf-bauen/-vario-bauen aus
|
|
;; tests/test_mubea.lsp werden mitgeladen (beide Dateien definieren nur
|
|
;; Funktionen), Linienzug-Ketten laufen ueber vsp-bau-journal (vf_spec.lsp).
|
|
;;
|
|
;; Aufruf in BricsCAD:
|
|
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_dematic_arvato.lsp"))
|
|
;; TEST_DEMATIC_ARVATO
|
|
;; ============================================================
|
|
|
|
(if (not (boundp '*dematic-arvato-records*)) (setq *dematic-arvato-records* nil))
|
|
|
|
;; Module und die Bau-Funktionen aus test_hundm05.lsp beim LADEN dieser Datei
|
|
;; holen, nicht erst in c:TEST_DEMATIC_ARVATO: in BricsCAD werden per load
|
|
;; definierte Funktionen erst nach Rueckkehr zum Top-Level sichtbar (siehe
|
|
;; tests/test_unit.scr).
|
|
(ssg-ensure "KreiselInsert")
|
|
(ssg-ensure "VarioFoerderer")
|
|
(ssg-ensure "SSG_LIB_Commands")
|
|
(ssg-ensure "Gefaellestrecke")
|
|
(if (null (car (atoms-family 1 '("HUNDM05:BAU-SENSOR"))))
|
|
(load (strcat (getenv "DXFMAKRO") "/tests/test_hundm05.lsp")))
|
|
(if (null (car (atoms-family 1 '("MUBEA:VARIO-BAUEN"))))
|
|
(load (strcat (getenv "DXFMAKRO") "/tests/test_mubea.lsp")))
|
|
|
|
(defun dematic_arvato:datei ()
|
|
(strcat (getenv "DXFMAKRO") "/tests/testdata/dematic_arvato.json"))
|
|
|
|
;; Record um den gebauten Block ergaenzen (oder als Abbruch markieren).
|
|
(defun dematic_arvato:rec-block (rec ent fehlertext / ed)
|
|
(if (and ent (= (type ent) 'ENAME))
|
|
(progn
|
|
(setq ed (entget ent))
|
|
(princ (strcat " -> Block " (cdr (assoc 2 ed))))
|
|
(setq rec (vsp-set rec "block_name" (cdr (assoc 2 ed))))
|
|
(setq rec (vsp-set rec "block_handle" (cdr (assoc 5 ed))))
|
|
(setq rec (vsp-set rec "insert_point" (cdr (assoc 10 ed))))
|
|
(setq rec (vsp-set rec "attribs" (ssg-attrib-read ent)))
|
|
(vsp-set rec "status" "executed"))
|
|
(progn
|
|
(princ (strcat " FEHLER: " fehlertext))
|
|
(vsp-set (vsp-set rec "status" "abbruch") "fehler_text" fehlertext))))
|
|
|
|
;; Foerderer "gerade": noch kein Bau-Pfad - nur melden.
|
|
(defun dematic_arvato:gerade-melden (obj / tid rec)
|
|
(setq tid (ssg-val obj "test_id"))
|
|
(princ (strcat "\n [GERADE] " (if tid tid "?")
|
|
" uebersprungen - waagrechter Foerderer noch nicht unterstuetzt"))
|
|
(setq rec (vsp-rec-neu (if tid tid "(ohne id)")))
|
|
(setq rec (vsp-set rec "kind" "gerade"))
|
|
(vsp-set (vsp-set rec "status" "uebersprungen") "fehler_text"
|
|
"kein Bau-Pfad fuer typ gerade"))
|
|
|
|
;; Gefaellewinkel aus Start- und Endhoehe - derselbe Loeser wie Modus 3
|
|
;; (gf-winkel-berechnen, Gefaellestrecke.lsp) mit den AS/ES-Massen der
|
|
;; aktuellen 2D/3D-Bibliothek. Die Kette ist eine einzige Gerade plus der
|
|
;; eine Separator vor dem ES (extra-sep 1); ihre Laenge ohne AS/ES/Separator
|
|
;; ist deltaL - aus-dx - ein-dx - 300, damit ergibt der Loeser als
|
|
;; Gesamtlaenge wieder genau deltaL (deltaL reicht von AS- bis ES-Ursprung).
|
|
;; VORZEICHEN: vf-set-as-masse (vf_core) misst dz als KS_AUS.z - KS_EIN.z
|
|
;; (bei AS/ES negativ), gf-winkel-berechnen erwartet die Konvention von
|
|
;; gf-init-bibliothek (KS_EIN.z - KS_AUS.z, positiv) und zieht den Wert ab.
|
|
;; Mit der VF-Konvention wurde der feste AS/ES-Abfall addiert statt
|
|
;; abgezogen - real gebaut: 3.79 statt ~2.49 Grad, GF endete 258 mm unter
|
|
;; dem Kreisel (HOEHE_BIS 1568 statt 1826). Darum hier der Betrag.
|
|
(defun dematic_arvato:gf-winkel (deltaL hz as-seite es-seite as-winkel es-winkel
|
|
z-start z-ende / winkel)
|
|
(mubea:ensure-gf-init)
|
|
(vf-set-as-masse as-winkel as-seite)
|
|
(vf-set-es-masse es-winkel es-seite)
|
|
(setq aus-dz (abs (float aus-dz)) ein-dz (abs (float ein-dz)))
|
|
(setq winkel
|
|
(gf-winkel-berechnen
|
|
(list (list "Linie" hz (- deltaL (float aus-dx) (float ein-dx) 300.0) 0 "links"))
|
|
(- z-start z-ende) 1))
|
|
(vf-set-as-masse "90" as-seite)
|
|
(vf-set-es-masse "90" es-seite)
|
|
winkel)
|
|
|
|
;; Gefaellestrecke (Modus 1) bauen - Felder wie mubea:build-gf, ohne dessen
|
|
;; anzahl/delta-Vervielfaeltigung (jede GF steht einzeln in der Datei).
|
|
;; Mit "hoehe_ende_mm" (Hoehe des Kreisels am Ende) wird der Winkel daraus
|
|
;; gerechnet, sonst gilt "winkel_grad" (Default 3.0).
|
|
(defun dematic_arvato:bau-gf (obj / tid start deltaL hz winkel z-ende
|
|
as-seite es-seite as-winkel es-winkel rec)
|
|
(setq tid (ssg-val obj "test_id")
|
|
start (ssg-val obj "start_mm")
|
|
deltaL (ssg-val obj "deltaL_mm")
|
|
hz (ssg-val obj "hz_grad")
|
|
winkel (ssg-val obj "winkel_grad")
|
|
z-ende (ssg-val obj "hoehe_ende_mm")
|
|
as-seite (cond ((ssg-val obj "as_seite")) ("links"))
|
|
es-seite (cond ((ssg-val obj "es_seite")) ("links"))
|
|
as-winkel (cond ((ssg-val obj "as_winkel")) ("90"))
|
|
es-winkel (cond ((ssg-val obj "es_winkel")) ("90")))
|
|
(setq rec (vsp-rec-neu (if tid tid "(ohne id)")))
|
|
(setq rec (vsp-set rec "kind" "gefaellestrecke"))
|
|
(setq rec (vsp-set rec "dimension" (vsp-dim-text)))
|
|
(cond
|
|
((not (and (= (type start) 'LIST) (= (length start) 3)
|
|
(numberp deltaL) (numberp hz)))
|
|
(princ (strcat "\n [GF] " (if tid tid "?")
|
|
" - FEHLER: start_mm, deltaL_mm und hz_grad muessen gesetzt sein"))
|
|
(vsp-set (vsp-set rec "status" "spec-fehler") "fehler_text"
|
|
"start_mm, deltaL_mm oder hz_grad fehlt bzw. ist ungueltig"))
|
|
((and (numberp z-ende) (>= z-ende (caddr start)))
|
|
(princ (strcat "\n [GF] " (if tid tid "?")
|
|
" - FEHLER: hoehe_ende_mm liegt nicht unter der Starthoehe"))
|
|
(vsp-set (vsp-set rec "status" "spec-fehler") "fehler_text"
|
|
"hoehe_ende_mm >= start_mm.z - kein Gefaelle"))
|
|
(T
|
|
(setq winkel
|
|
(cond
|
|
((numberp z-ende)
|
|
(dematic_arvato:gf-winkel (float deltaL) (float hz) as-seite es-seite
|
|
as-winkel es-winkel
|
|
(float (caddr start)) (float z-ende)))
|
|
((numberp winkel) (float winkel))
|
|
(T 3.0)))
|
|
;; Winkel und Soll-Endhoehe als Meldung (das Record-Schema aus vf_spec
|
|
;; kennt dafuer kein Feld); die Ist-Endhoehe steht in attribs HOEHE_BIS.
|
|
(setq rec (vsp-set rec "meldungen"
|
|
(list (strcat "winkel_grad " (rtos winkel 2 3)
|
|
(if (numberp z-ende)
|
|
(strcat " aus Hoehe " (rtos (caddr start) 2 1)
|
|
" -> " (rtos z-ende 2 1))
|
|
"")))))
|
|
(dematic_arvato:rec-block rec
|
|
(mubea:gf-bauen tid (mapcar 'float start) (float deltaL) (float hz)
|
|
as-seite es-seite as-winkel es-winkel winkel)
|
|
"gefaellestrecke-einfuegen lieferte keinen GF-Block"))))
|
|
|
|
;; VarioFoerderer "standard"/"etage" - mubea-Schema, Bau ueber
|
|
;; mubea:vario-bauen. "motorseite" wirkt wie im Edit-Dialog ueber den
|
|
;; Override *vf-motorseite* (vf-block-erstellen liest ihn).
|
|
(defun dematic_arvato:bau-vf (obj / tid typ rec ent)
|
|
(setq tid (ssg-val obj "test_id")
|
|
typ (cond ((ssg-val obj "typ")) ("standard")))
|
|
(setq rec (vsp-rec-neu (if tid tid "(ohne id)")))
|
|
(setq rec (vsp-set rec "kind" "vario"))
|
|
(setq rec (vsp-set rec "dimension" (vsp-dim-text)))
|
|
(setq *vf-motorseite* (ssg-val obj "motorseite"))
|
|
(setq ent
|
|
(vl-catch-all-apply 'mubea:vario-bauen
|
|
(list tid typ (ssg-val obj "richtung")
|
|
(float (ssg-val obj "deltaL")) (float (ssg-val obj "deltaH"))
|
|
(ssg-val obj "winkel") (float (cond ((ssg-val obj "L_GF1")) (0.0)))
|
|
(ssg-val obj "seite") (ssg-val obj "hz")
|
|
(list (float (ssg-val obj "x")) (float (ssg-val obj "y"))
|
|
(float (ssg-val obj "z"))))))
|
|
(setq *vf-motorseite* nil)
|
|
(if (vl-catch-all-error-p ent)
|
|
(vsp-set (vsp-set rec "status" "abbruch") "fehler_text"
|
|
(vl-catch-all-error-message ent))
|
|
(dematic_arvato:rec-block rec ent
|
|
"kein VF-Block (deltaL beim gewuenschten Winkel nicht loesbar?)")))
|
|
|
|
;; Linienzug-Kette: aufgezeichnetes Journal ("ART:wert"-Tokens, wie in der
|
|
;; SSG_VF_EDIT-XDATA) 1:1 abspielen. Headless-Rahmen wie vsp-bau-datei; er
|
|
;; MUSS auch nach einem Fehler zurueck, sonst bleiben getstring/getpoint der
|
|
;; Sitzung ersetzt.
|
|
(defun dematic_arvato:bau-journal (obj / tid journal res)
|
|
(setq tid (cond ((ssg-val obj "test_id")) ("(ohne id)")))
|
|
(setq journal (mapcar 'vfl-string->entry (ssg-val obj "journal")))
|
|
(vsp-headless-an)
|
|
(setq res (vl-catch-all-apply 'vsp-bau-journal
|
|
(list tid journal nil
|
|
(if journal nil (list "Feld \"journal\" fehlt oder ist leer")))))
|
|
(vsp-headless-aus)
|
|
(if (vl-catch-all-error-p res)
|
|
(vsp-set (vsp-set (vsp-rec-neu tid) "status" "abbruch") "fehler_text"
|
|
(vl-catch-all-error-message res))
|
|
res))
|
|
|
|
(defun dematic_arvato:bau-eintrag (obj / kind res typ)
|
|
(setq typ (ssg-val obj "typ"))
|
|
(cond
|
|
((ssg-val obj "modus")
|
|
(setq kind "gefaellestrecke")
|
|
(setq res (vl-catch-all-apply 'dematic_arvato:bau-gf (list obj))))
|
|
((= typ "linienzug_journal")
|
|
(setq kind "linienzug")
|
|
(setq res (dematic_arvato:bau-journal obj)))
|
|
((and (member typ '("standard" "etage")) (ssg-val obj "test_id"))
|
|
(setq kind "vario")
|
|
(setq res (dematic_arvato:bau-vf obj)))
|
|
((and (= (ssg-val obj "function") "insert") (ssg-val obj "block"))
|
|
(setq kind "sensor")
|
|
(setq res (vl-catch-all-apply 'hundm05:bau-sensor (list obj))))
|
|
((= (ssg-val obj "function") "insert")
|
|
(setq kind "kreisel")
|
|
(setq res (vl-catch-all-apply 'hundm05:bau-kreisel (list obj))))
|
|
((= typ "gerade")
|
|
(setq kind "gerade")
|
|
(setq res (dematic_arvato:gerade-melden obj)))
|
|
(T
|
|
(setq kind "unbekannt")
|
|
(princ "\n WARNUNG: unbekannter Eintrag uebersprungen")
|
|
(setq res (vsp-set (vsp-rec-neu "(unbekannt)") "status" "uebersprungen"))))
|
|
(if (vl-catch-all-error-p res)
|
|
(progn
|
|
(princ (strcat "\n [" (strcase kind) "] Ausnahme: "
|
|
(vl-catch-all-error-message res)))
|
|
(vsp-set (vsp-set (vsp-set (vsp-rec-neu (cond ((ssg-val obj "id"))
|
|
((ssg-val obj "test_id"))
|
|
((ssg-val obj "block"))
|
|
("?")))
|
|
"kind" kind) "status" "abbruch")
|
|
"fehler_text" (vl-catch-all-error-message res)))
|
|
res))
|
|
|
|
;; Alle Eintraege einer Nachbau-Datei bauen und die Records zurueckgeben
|
|
;; (nil bei Fehler vor dem Bau). Gemeinsamer Lauf fuer jeden Treiber mit
|
|
;; diesem Eintragsschema - auch tests/test_showroom_ils.lsp.
|
|
;; befehl = Name fuer Meldungen/ssg-start, titel = Kopfzeile, datei = JSON
|
|
(defun dematic_arvato:bau-datei (befehl titel datei / daten out records zaehler st)
|
|
(princ "\n\n================================================================")
|
|
(princ (strcat "\n " befehl " - " titel))
|
|
(princ (strcat "\n " datei))
|
|
(princ "\n================================================================")
|
|
(cond
|
|
((null (car (atoms-family 1 '("VSP-BAU-JOURNAL"))))
|
|
(princ (strcat "\n[" befehl "] FEHLER: vf_spec.lsp nicht geladen"
|
|
" (VarioFoerderer laden)."))
|
|
nil)
|
|
((null (findfile datei))
|
|
(princ (strcat "\n[" befehl "] FEHLER: " datei " nicht gefunden!"))
|
|
nil)
|
|
(T
|
|
(setq daten (ssg-json-laden datei))
|
|
(princ (strcat "\n " (itoa (length daten)) " Eintraege geladen"))
|
|
(ssg-start befehl '(("OSMODE") ("CECOLOR") ("ATTREQ") ("ATTDIA")))
|
|
(setvar "OSMODE" 0)
|
|
(setvar "ATTREQ" 0)
|
|
(setvar "ATTDIA" 0)
|
|
;; Vario-Bibliothek (Bogen-/AS-/ES-Masse) wie C:TEST_MUBEA, und die
|
|
;; GF-Elementmasse in jeder Zeichnung neu ermitteln.
|
|
(if (vsp-lib-noetig-p) (init-bibliothek))
|
|
(setq *mubea-gf-init-done* nil)
|
|
(setq out '())
|
|
(foreach obj daten
|
|
(setq out (cons (dematic_arvato:bau-eintrag obj) out)))
|
|
(ssg-end)
|
|
(setq records (reverse out))
|
|
;; Zusammenfassung je Status
|
|
(setq zaehler '())
|
|
(foreach r records
|
|
(setq st (cond ((ssg-val r "status")) ("?")))
|
|
(if (assoc st zaehler)
|
|
(setq zaehler (subst (cons st (1+ (cdr (assoc st zaehler))))
|
|
(assoc st zaehler) zaehler))
|
|
(setq zaehler (cons (cons st 1) zaehler))))
|
|
(princ "\n================================================================")
|
|
(foreach z (reverse zaehler)
|
|
(princ (strcat "\n " (car z) ": " (itoa (cdr z)))))
|
|
(princ "\n================================================================")
|
|
(command "_.ZOOM" "_E")
|
|
records)))
|
|
|
|
(defun c:TEST_DEMATIC_ARVATO ()
|
|
(setq *dematic-arvato-records*
|
|
(dematic_arvato:bau-datei "TEST_DEMATIC_ARVATO" "Abschnitt Flowpuffer/Kreisel"
|
|
(dematic_arvato:datei)))
|
|
(princ))
|
|
|
|
;; Ergebnis-Export (Konvention <name>:export-results fuer test_run_all.lsp)
|
|
(defun dematic_arvato:export-results (out-dir / pfad)
|
|
(if (null *dematic-arvato-records*)
|
|
(princ "\n Keine Dematic/Arvato-Ergebnisse vorhanden.")
|
|
(progn
|
|
(vl-mkdir out-dir)
|
|
(setq pfad (strcat out-dir "/dematic_arvato_results.json"))
|
|
(vsp-results-schreiben *dematic-arvato-records* pfad)))
|
|
(princ))
|
|
|
|
(princ "\nTEST_DEMATIC_ARVATO geladen. Aufruf: TEST_DEMATIC_ARVATO")
|
|
(princ)
|