f8b8a4175b
Der Drehwinkel wird beim Bau in die Geometrie eingerechnet, die Blockreferenz selbst hat immer Drehung 0 (ssg-block-wrap-welt). KF_EDIT las die Drehung nur aus Gruppencode 50 und baute einen mit z.B. 90 Grad gebauten Foerderer beim Bearbeiten daher ungedreht neu. Der gebaute Winkel steht jetzt als XDATA (SSG_KF_EDIT) am Block. KF_EDIT addiert eine spaeter von Hand vorgenommene Drehung der Referenz (Gruppencode 50); Altbestand ohne XDATA verhaelt sich wie bisher. - kf-block-erstellen: neuer Parameter drehung, beide Aufrufer angepasst - reiner Kern kf-drehung-gesamt (auf -180..180 normalisiert) mit Unit-Tests Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
1205 lines
58 KiB
Common Lisp
1205 lines
58 KiB
Common Lisp
;; ============================================================
|
|
;; KETTENFOERDERER.LSP - Schraegfoerderer Stahl (Omniflo)
|
|
;; ============================================================
|
|
;; Baut aus drei vorhandenen Bloecken eine Kette zusammen und fasst sie zu
|
|
;; EINEM Block KF_<n> zusammen - dasselbe Muster wie KREISEL_n/VF_n/GF_n:
|
|
;;
|
|
;; KF_UM_<winkel> (Umlenkstation, unten)
|
|
;; KS_AUS --> KS_EIN
|
|
;; KF_LAENGE (Zwischenstueck, in X SKALIERT - wie die Staustrecke
|
|
;; beim VarioFoerderer)
|
|
;; KS_AUS --> KS_EIN
|
|
;; KF_AN_<winkel> (Antriebsstation, oben)
|
|
;;
|
|
;; GEOMETRIE - wichtigste Entwurfsentscheidung:
|
|
;; Die Neigung (26 bzw. 30 Grad) ist KEIN Rechenparameter. Sie steckt fest in
|
|
;; der Geometrie der Varianten-Bloecke (KF_UM_26 gegen KF_UM_30). Der
|
|
;; Einbauwinkel jedes Folgebausteins wird darum zur Laufzeit aus der RICHTUNG
|
|
;; des KS_AUS seines Vorgaengers gemessen (ks-xy-winkel/ks-block-messen in
|
|
;; ssg_ks_insert.lsp) - es gibt hier keine gepflegte Winkeltabelle, die beim
|
|
;; Austausch einer DWG veralten koennte. Der JSON-Wert "winkel" dient nur der
|
|
;; Variantenwahl, der Anzeige und dem Attribut KF_WINKEL.
|
|
;;
|
|
;; Die Bloecke sind eine 2D-SEITENANSICHT: die Steigung liegt in der
|
|
;; XY-Zeichenebene, die Hoehenachse ist Y (nicht Z wie bei VF/GF). Die
|
|
;; Neigung ist damit eine reine Rz-Drehung - deshalb genuegt
|
|
;; insert-block-by-ks/insert-block-ks-skaliert, die Rz*Ry-Primitiven des
|
|
;; VarioFoerderers werden hier nicht gebraucht.
|
|
;;
|
|
;; Die Einbauhoehe H (Abstand KS_EIN der Umlenkung bis KS_AUS des Antriebs auf
|
|
;; der Y-Achse) bestimmt die Laenge des Zwischenstuecks ueber die
|
|
;; Hoehenbilanz, siehe kf-laenge-berechnen.
|
|
;;
|
|
;; Abhaengigkeiten: ssg_core, ssg_lang, ssg_layer, ssg_id, ssg_ks_insert,
|
|
;; OmniModulInsert (nur fuer omni:omniflo-datei-finden - die KF-DWGs liegen
|
|
;; wie alle Omniflo-Bauteile in data/omniflo/<Dimension>/).
|
|
;; ============================================================
|
|
|
|
(vl-load-com)
|
|
|
|
;; modelspace/doc werden von den KS-Einfuegeprimitiven als GLOBALE Variablen
|
|
;; erwartet (gesetzt von vf_core.lsp bzw. Gefaellestrecke.lsp). Beim isolierten
|
|
;; Laden dieses Moduls - etwa in einem Testskript - ist noch keines davon
|
|
;; geladen, darum hier guarded nachziehen (gleiches Muster wie TEFInsert.lsp).
|
|
(if (null doc) (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))))
|
|
(if (null modelspace) (setq modelspace (vla-get-ModelSpace doc)))
|
|
|
|
;; Einfuegeprimitiven guarded nachladen (die MNL laedt ssg_ks_insert als
|
|
;; Kernmodul, beim isolierten Test-Laden fehlt es aber). Geprueft wird ueber
|
|
;; atoms-family, nicht ueber (null <symbol>) - ein noch nie definiertes
|
|
;; Funktionssymbol ist zwar nil, ein definiertes liefert aber eine USUBR, und
|
|
;; die Abfrage waere damit vom Ladezustand abhaengig statt von der Existenz.
|
|
(if (not (car (atoms-family 1 '("INSERT-BLOCK-KS-SKALIERT"))))
|
|
(if (findfile (ssg-lisp-datei-pfad "ssg_ks_insert.lsp"))
|
|
(load (ssg-lisp-datei-pfad "ssg_ks_insert.lsp"))))
|
|
|
|
;; ------------------------------------------------------------
|
|
;; LAUFZEIT-PROTOKOLL (Schalter "kf-zeit")
|
|
;; ------------------------------------------------------------
|
|
;; Schreibt Zwischenzeiten ueber ssg_dbg (dbgmsg) statt per princ ins
|
|
;; BricsCAD-Fenster - die Zeilen landen damit in einer .dbg-Datei im
|
|
;; DXFM_LOG-Verzeichnis und sind ueber den Schalter abschaltbar, koennen
|
|
;; also dauerhaft im Code bleiben (siehe Debug-Abschnitt in CLAUDE.md).
|
|
;; Einschalten: (dbg-schalter-setzen "kf-zeit" 1), dann KETTENFOERDERER.
|
|
;; Zweck: klaeren, wo die spuerbare Verzoegerung beim ersten Menueklick
|
|
;; entsteht (Lazy-Laden des Moduls / JSON lesen / Dialogaufbau).
|
|
;; Eigener Dateihandle statt dbgmsg: ssg_dbg fuehrt mit *dbg-path* genau EINE
|
|
;; global offene Datei - die Zeilen wuerden sonst stillschweigend in einem
|
|
;; fremden Protokoll landen (gleiche Ueberlegung wie bei ssg-sepliste-dbg).
|
|
(if (not (boundp '*kf-zeit-pfad*)) (setq *kf-zeit-pfad* nil))
|
|
|
|
(defun kf-zeit (was t0 / dir fh)
|
|
(if (and t0
|
|
(car (atoms-family 1 '("DBG-SCHALTER-P")))
|
|
(dbg-schalter-p "kf-zeit"))
|
|
(progn
|
|
(if (null *kf-zeit-pfad*)
|
|
(progn
|
|
(setq dir (getenv "DXFM_LOG"))
|
|
(if (or (null dir) (= dir "")) (setq dir "."))
|
|
(setq *kf-zeit-pfad* (strcat dir "\\kf_zeit.dbg"))))
|
|
(setq fh (open *kf-zeit-pfad* "a"))
|
|
(if fh
|
|
(progn
|
|
(write-line (strcat was ": " (itoa (fix (- (getvar "MILLISECS") t0)))
|
|
" ms seit Befehlsstart") fh)
|
|
(close fh)))))
|
|
(princ))
|
|
|
|
;; ============================================================
|
|
;; DATEN (data/json/kettenfoerderer.json)
|
|
;; ============================================================
|
|
;; Verschachteltes JSON -> ssg-json-laden (rekursiver Parser), NICHT der
|
|
;; zeilenbasierte ssg-load-json: die Datei hat verschachtelte Objekte und
|
|
;; Kommas in den Beschreibungstexten.
|
|
(if (not (boundp '*kf-daten*)) (setq *kf-daten* nil))
|
|
|
|
(defun kf-daten-datei ( / basis)
|
|
(setq basis (getenv "DXFM_DATA"))
|
|
(if (or (null basis) (= basis ""))
|
|
(setq basis (strcat (getenv "DXFMAKRO") "/data")))
|
|
(strcat basis "/json/kettenfoerderer.json"))
|
|
|
|
;; Geladene Daten (Cache). kf-daten-reset erzwingt das Neulesen nach einer
|
|
;; Aenderung an der JSON, ohne BricsCAD neu zu starten.
|
|
(defun kf-daten ( / datei roh)
|
|
(if (null *kf-daten*)
|
|
(progn
|
|
(setq datei (kf-daten-datei))
|
|
(if (findfile datei)
|
|
(progn
|
|
(setq roh (ssg-json-laden datei))
|
|
(setq *kf-daten* (ssg-json-get roh "kettenfoerderer")))
|
|
(princ (ssg-textf "kf-fehler-daten-fehlt" (list datei))))))
|
|
*kf-daten*)
|
|
|
|
(defun kf-daten-reset ( ) (setq *kf-daten* nil) (princ))
|
|
|
|
;; ============================================================
|
|
;; REINE RECHENKERNE (ohne Zeichnung/Datei testbar - tests/test_unit.lsp)
|
|
;; ============================================================
|
|
|
|
;; JSON-Wert als Zahl. Der Parser liefert Zahlen je nach Schreibweise als
|
|
;; REAL/INT oder (bei gequoteten Werten) als String - beides zulassen.
|
|
(defun kf-zahl (v)
|
|
(cond
|
|
((null v) nil)
|
|
((numberp v) (float v))
|
|
((= (type v) 'STR) (atof v))
|
|
(t nil)))
|
|
|
|
;; Laenge des skalierbaren Zwischenstuecks aus der Hoehenbilanz.
|
|
;; H = dy-um + [ L*sin(hz) + dy-nativ*cos(hz) ] + dy-an
|
|
;; aufgeloest nach L. Der Term dy-nativ*cos(hz) faellt weg, wenn das
|
|
;; Zwischenstueck waagerecht gezeichnet ist (Normalfall) - er steht hier,
|
|
;; damit auch ein bereits geneigt gezeichnetes KF_LAENGE richtig gerechnet
|
|
;; wird. dy-nativ skaliert BEWUSST nicht mit: skaliert wird nur in X.
|
|
;; h-soll gewuenschte Einbauhoehe H (mm)
|
|
;; dy-um Y-Versatz der eingebauten Umlenkstation
|
|
;; dy-an Y-Versatz der eingebauten Antriebsstation
|
|
;; dy-nativ Y-Anteil des KS_AUS-KS_EIN-Versatzes von KF_LAENGE (Blockmass)
|
|
;; hz Einbauwinkel des Zwischenstuecks (Grad)
|
|
;; Rueckgabe: Laenge entlang der Blockachse (mm), oder nil wenn die Neigung
|
|
;; keinen Hoehengewinn liefert (sin(hz)=0 - dann ist H nicht erreichbar).
|
|
(defun kf-laenge-berechnen (h-soll dy-um dy-an dy-nativ hz / rad sh ch rest)
|
|
(setq rad (* (float hz) (/ pi 180.0)))
|
|
(setq sh (sin rad) ch (cos rad))
|
|
(if (< (abs sh) 1e-9)
|
|
nil
|
|
(progn
|
|
(setq rest (- (float h-soll) (float dy-um) (float dy-an)
|
|
(* (float dy-nativ) ch)))
|
|
(/ rest sh))))
|
|
|
|
;; X-Massstab fuer KF_LAENGE: gewuenschte Laenge / native Blocklaenge.
|
|
;; nil, wenn der Block keine messbare X-Laenge hat.
|
|
(defun kf-skala-berechnen (laenge dx-nativ)
|
|
(if (or (null laenge) (null dx-nativ) (< (abs dx-nativ) 1e-9))
|
|
nil
|
|
(/ (float laenge) (float dx-nativ))))
|
|
|
|
;; Errechnete Laenge gegen die Grenzen aus der JSON pruefen.
|
|
;; Rueckgabe: nil = in Ordnung, sonst der Sprach-Key der Meldung.
|
|
(defun kf-laenge-pruefen (laenge lmin lmax)
|
|
(cond
|
|
((null laenge) "kf-fehler-winkel-null")
|
|
((<= laenge 0.0) "kf-fehler-hoehe-zu-klein")
|
|
((and lmin (< laenge (float lmin))) "kf-fehler-laenge-unter-min")
|
|
((and lmax (> laenge (float lmax))) "kf-fehler-laenge-ueber-max")
|
|
(t nil)))
|
|
|
|
;; Y-Anteil des KS_AUS-KS_EIN-Versatzes nach Einbau mit Rz(hz) und X-Massstab.
|
|
;; In der 2D-Seitenansicht ist Y die Hoehenachse.
|
|
(defun kf-dy-eingebaut (dx-nativ dy-nativ hz skala / rad)
|
|
(setq rad (* (float hz) (/ pi 180.0)))
|
|
(+ (* (* (float skala) (float dx-nativ)) (sin rad))
|
|
(* (float dy-nativ) (cos rad))))
|
|
|
|
;; Einbauwinkel (Rz, Grad) eines Folgebausteins: sein KS_EIN soll in dieselbe
|
|
;; Richtung zeigen wie das KS_AUS seines Vorgaengers.
|
|
;; hz = Weltrichtung(KS_AUS Vorgaenger) - Eigenrichtung(KS_EIN Folgebaustein)
|
|
;; Fehlt die Eigenrichtung des Folgebausteins, wird er wie sein Vorgaenger
|
|
;; ausgerichtet; fehlt die Vorgaengerrichtung, ist keine Aussage moeglich (nil).
|
|
(defun kf-hz-folge (phi-aus beta-ein)
|
|
(cond
|
|
((null phi-aus) nil)
|
|
((null beta-ein) (ks-winkel-normalisieren phi-aus))
|
|
(t (ks-winkel-normalisieren (- phi-aus beta-ein)))))
|
|
|
|
;; Variante zu einem Winkel suchen. Rueckgabe: Varianten-Objekt oder nil.
|
|
(defun kf-variante-finden (winkel varianten / treffer w)
|
|
(setq treffer nil)
|
|
(foreach v varianten
|
|
(setq w (kf-zahl (ssg-json-get v "winkel")))
|
|
(if (and (null treffer) w (< (abs (- w (float winkel))) 0.01))
|
|
(setq treffer v)))
|
|
treffer)
|
|
|
|
;; ------------------------------------------------------------
|
|
;; ATTRIBUT-SCHEMA
|
|
;; ------------------------------------------------------------
|
|
;; EIGENSTAENDIGE Liste - bewusst NICHT vom Strecken-Schema des
|
|
;; VarioFoerderers (`ssg-strecke-attrib-defs`) abgeleitet. Anfangs war sie
|
|
;; das, was dem Block rund zwei Dutzend geerbte Tags eintrug, die der
|
|
;; Kettenfoerderer gar nicht kennt (SEITE_AS/ES, GF_Bogen_*, ANZAHL_VF,
|
|
;; MOTORSEITE, VF_Bogen_*, ANZAHL_SEPARATOR ...). Sie standen leer am Block,
|
|
;; waren im Attributeditor nur Ballast und haetten im Export Werte
|
|
;; vorgetaeuscht, die es hier nicht gibt. Eine explizite Liste ist zudem
|
|
;; leichter zu lesen als eine Erbung mit Ausnahmeliste.
|
|
;;
|
|
;; Was die Tags bedeuten:
|
|
;; ID - vergibt ssg-id-generate (Voraussetzung fuer den Export)
|
|
;; Bezeichnung - Blockname KF_<n>, CSV-Spalte
|
|
;; ARTINR - Sivas-Artikelnummer, CSV-Spalte "SivasNummer"
|
|
;; FOERDERERTYP - Bauart im Klartext ("Schraegfoerderer Stahl"),
|
|
;; Merkmal 350. Der Wert kommt aus der JSON
|
|
;; (Feld "foerderertyp"), nicht aus dem Code - so
|
|
;; bleibt diese Datei frei von Sonderzeichen und der
|
|
;; Text ist an einer Stelle pflegbar.
|
|
;; WINKEL - Neigungswinkel als nackte Zahl ("26"/"30").
|
|
;; Den Sivas-Klartext mit Gradzeichen erzeugt erst die
|
|
;; Tabelle [kf_typ_anzeige] (cfg/sivas.cfg, Merkmal
|
|
;; 359) - Attributwerte bleiben so ASCII.
|
|
;; STANDARD_STEUERUNG - Merkmal 361, "1"/"0" ueber Transform ja_nein.
|
|
;; Steht direkt hinter WINKEL, wie im Merkmalstamm.
|
|
;; H_EINBAUHOEHE_mm - Merkmal 360
|
|
;; L_KF_mm - Laenge des skalierten Zwischenstuecks, CSV-Spalte
|
|
;; FARBE - Merkmal 354
|
|
;; ANTRIEBSMOTOR - Merkmal 355 (eigenes Merkmal, nicht Teil von 354)
|
|
;; ANTRIEBSART - Merkmal 357, FEST "1.1 kW" (Wert aus der JSON,
|
|
;; im Dialog ein Dropdown mit EINER, zwingend gewaehlten Option)
|
|
;; MOVIMOT - Merkmal 356, "1"/"0" ueber Transform ja_nein
|
|
;; VERBINDUNGSELEMENTE - Merkmal 391
|
|
;; LAYER - Ziel-Layer der Baugruppe
|
|
;;
|
|
;; KEINE TEILEART: sie ist fuer jeden Kettenfoerderer gleich und steht darum
|
|
;; als Festwert im Export (KF_TEILEART in export_sivas.py) statt an jedem
|
|
;; Block. Die Erkennung laeuft ohnehin ueber den Blocknamen (pattern_
|
|
;; kettenfoerderer), nicht ueber TEILEART.
|
|
(setq *kf-attrib-defs-liste*
|
|
'(("ID" "")
|
|
("Bezeichnung" "")
|
|
("ARTINR" "")
|
|
("FOERDERERTYP" "Schraegfoerderer Stahl")
|
|
("WINKEL" "26")
|
|
;; Reihenfolge wie im Sivas-Merkmalstamm: 361 folgt direkt auf den Typ.
|
|
("STANDARD_STEUERUNG" "0")
|
|
("H_EINBAUHOEHE_mm" "0")
|
|
("L_KF_mm" "0")
|
|
("FARBE" "RAL 7035")
|
|
("ANTRIEBSMOTOR" "Europa 50 Hz")
|
|
;; Merkmal 357 - beim Kettenfoerderer fest, im Dialog nur Anzeige.
|
|
("ANTRIEBSART" "1.1 kW")
|
|
("MOVIMOT" "0")
|
|
("VERBINDUNGSELEMENTE" "Nein")
|
|
("LAYER" "F-3")))
|
|
|
|
(defun kf-attrib-defs ( ) *kf-attrib-defs-liste*)
|
|
|
|
;; Antriebsart (Merkmal 357). Beim Kettenfoerderer gibt es genau EINE Option
|
|
;; ("1.1 kW"), die im Dialog zwingend gewaehlt ist. Sie steht als Liste in der
|
|
;; JSON (wie alle anderen Auswahlen), nicht im Code. Rueckgabe: der "wert" des
|
|
;; ERSTEN Eintrags - bei einer Ein-Eintrag-Liste also immer derselbe Wert.
|
|
(defun kf-antriebsart (daten)
|
|
(kf-auswahl-wert (ssg-json-get daten "antriebsart") 0 "1.1 kW"))
|
|
|
|
;; Position eines Tags in einer ATTDEF-Liste (0-basiert), nil wenn nicht
|
|
;; enthalten. Die REIHENFOLGE ist nicht beliebig: sie bestimmt, in welcher
|
|
;; Folge die Attribute im Blockeditor und in den Exportzeilen erscheinen, und
|
|
;; folgt darum dem Sivas-Merkmalstamm. Reiner Kern, in test_unit geprueft.
|
|
(defun kf-tag-index (tag defs / i treffer)
|
|
(setq i 0 treffer nil)
|
|
(foreach d defs
|
|
(if (and (null treffer) (= (car d) tag)) (setq treffer i))
|
|
(setq i (1+ i)))
|
|
treffer)
|
|
|
|
;; ============================================================
|
|
;; BLOCK-DATEIEN (data/omniflo/<Dimension>/)
|
|
;; ============================================================
|
|
;; Die KF-Bloecke liegen - anders als die ILS-Bloecke in data/ils (flach, mit
|
|
;; Dimensionssuffix _2D/_3D) - in den Omniflo-Ordnern ohne Suffix. Die
|
|
;; KS-Primitiven in ssg_ks_insert.lsp suchen ueber ssg-ils-block-laden aber in
|
|
;; data/ils. Darum wird die Blockdefinition HIER vorab aus dem Omniflo-Ordner
|
|
;; in die Zeichnung geladen; ensure-block-loaded findet sie dann per
|
|
;; tblsearch bereits vor und laesst sie unangetastet.
|
|
(defun kf-block-laden (blockname / pfad omniflo-pfad temp-obj)
|
|
(if (tblsearch "BLOCK" blockname)
|
|
blockname
|
|
(progn
|
|
(setq omniflo-pfad (getenv "DXFM_OMNIFLO"))
|
|
(setq pfad
|
|
(if (and omniflo-pfad
|
|
(car (atoms-family 1 '("OMNI:OMNIFLO-DATEI-FINDEN"))))
|
|
(omni:omniflo-datei-finden blockname omniflo-pfad)
|
|
nil))
|
|
;; Rueckfall ohne OmniModulInsert/DXFM_OMNIFLO: direkt im Datenordner
|
|
(if (null pfad)
|
|
(setq pfad (kf-block-datei-direkt blockname)))
|
|
(if pfad
|
|
(progn
|
|
;; vla-InsertBlock mit DATEIPFAD definiert den Block unter seinem
|
|
;; Dateinamen (gleiches Vorgehen wie dinformate-block-laden).
|
|
(setq temp-obj (vla-InsertBlock modelspace
|
|
(vlax-3D-point '(0 0 0)) pfad 1.0 1.0 1.0 0))
|
|
(if (and temp-obj (not (vlax-erased-p temp-obj)))
|
|
(vla-Delete temp-obj))
|
|
(if (tblsearch "BLOCK" blockname) blockname nil))
|
|
(progn
|
|
(princ (ssg-textf "kf-fehler-block-datei" (list blockname)))
|
|
nil)))))
|
|
|
|
;; Blockdatei ohne DXFM_OMNIFLO suchen: data/omniflo/<dim>/ in der aktuellen
|
|
;; Dimension, dann in der anderen (der 3D-Datenbestand ist unvollstaendig).
|
|
(defun kf-block-datei-direkt (blockname / basis dim kandidaten treffer)
|
|
(setq basis (getenv "DXFM_DATA"))
|
|
(if (or (null basis) (= basis ""))
|
|
(setq basis (strcat (getenv "DXFMAKRO") "/data")))
|
|
(setq dim (if (car (atoms-family 1 '("SSG-ILS-DIM-AKTUELL")))
|
|
(ssg-ils-dim-aktuell) "2D"))
|
|
(setq kandidaten
|
|
(list (strcat basis "/omniflo/" dim "/" blockname ".dwg")
|
|
(strcat basis "/omniflo/" dim "/" blockname ".dxf")
|
|
(strcat basis "/omniflo/" (if (= dim "2D") "3D" "2D") "/" blockname ".dwg")
|
|
(strcat basis "/omniflo/" (if (= dim "2D") "3D" "2D") "/" blockname ".dxf")))
|
|
(setq treffer nil)
|
|
(foreach k kandidaten
|
|
(if (and (null treffer) (findfile k)) (setq treffer (findfile k))))
|
|
treffer)
|
|
|
|
;; ============================================================
|
|
;; AUFRICHTUNG: die Baugruppe steht im Modell
|
|
;; ============================================================
|
|
;; Die Bausteine sind in der XY-Ebene gezeichnet (X = Fahrtrichtung,
|
|
;; Y = Hoehe) - eine Seitenansicht. Eingebaut werden sie AUFGERICHTET: um
|
|
;; 90 Grad um die Fahrtrichtungsachse gekippt, sodass die Hoehe nach Z
|
|
;; wandert. Von oben sieht man dann die Draufsicht KF_2D, von der Seite die
|
|
;; Kette; beide bilden EIN Objekt ohne Versatz.
|
|
;;
|
|
;; Gesamtdrehung je Baustein: Rz(basis) * Rx(90) * Rz(eigen)
|
|
;; Rz(eigen) richtet den Baustein in seiner EIGENEN Zeichenebene aus
|
|
;; (der aus den KS gemessene Verkettungswinkel, s. kf-hz-folge)
|
|
;; Rx(90) richtet die Ebene auf - Y_lokal wird zu Z_welt
|
|
;; Rz(basis) dreht die fertige Baugruppe in der Draufsicht
|
|
;; Die Reihenfolge ist nicht beliebig: Rz(eigen) muss VOR dem Aufrichten
|
|
;; wirken (es ist eine Drehung in der Blockebene), Rz(basis) danach (es ist
|
|
;; eine Drehung im Modell).
|
|
(defun kf-matrix-aufrecht (basis-hz eigen-hz)
|
|
(mat3-mul-mat3 (ks-rot-z basis-hz)
|
|
(mat3-mul-mat3 (ks-rot-x 90.0) (ks-rot-z eigen-hz))))
|
|
|
|
;; ============================================================
|
|
;; GEOMETRIE EINER VARIANTE MESSEN
|
|
;; ============================================================
|
|
;; Misst alle drei Bloecke EINMAL und leitet daraus die Einbauwinkel und die
|
|
;; Hoehenbeitraege ab. Ergebnis ist ein Record (Assoc-Liste), den der Dialog
|
|
;; fuer die Laengenvorschau und der Bau fuer die eigentliche Verkettung nutzt -
|
|
;; gemessen wird also genau einmal je Variante.
|
|
;;
|
|
;; Felder: "hz-um" "hz-l" "hz-an" Einbauwinkel (Grad, relativ zur Basisdrehung)
|
|
;; "dy-um" "dy-an" Hoehenbeitrag der beiden Stationen
|
|
;; "dx-l" "dy-l" nativer KS-Versatz von KF_LAENGE
|
|
;; "fehler" Sprach-Key, falls etwas fehlt (sonst nil)
|
|
(defun kf-geometrie-messen (variante / b-um b-l b-an ks-um ks-l ks-an
|
|
v-um v-l v-an beta-aus-um beta-ein-l beta-aus-l
|
|
beta-ein-an hz-um hz-l hz-an dy-um dy-an fehler)
|
|
(setq b-um (ssg-json-get variante "block_umlenkung")
|
|
b-l (ssg-json-get variante "block_laenge")
|
|
b-an (ssg-json-get variante "block_antrieb"))
|
|
(setq fehler nil)
|
|
(if (not (and (kf-block-laden b-um) (kf-block-laden b-l) (kf-block-laden b-an)))
|
|
(setq fehler "kf-fehler-block-datei")
|
|
(progn
|
|
(setq ks-um (ks-block-messen b-um)
|
|
ks-l (ks-block-messen b-l)
|
|
ks-an (ks-block-messen b-an))
|
|
(setq v-um (ks-versatz ks-um)
|
|
v-l (ks-versatz ks-l)
|
|
v-an (ks-versatz ks-an))
|
|
(if (not (and v-um v-l v-an))
|
|
;; Welcher Baustein klemmt, gehoert ins Protokoll: die Meldung allein
|
|
;; ("in mindestens einem Baustein fehlt ein KS") hat bei einem realen
|
|
;; Fehlschlag nicht gereicht, um die Ursache zu finden - sie lag nicht
|
|
;; an den Bloecken, sondern an einem falsch aufgeloesten Blocknamen
|
|
;; (siehe ensure-block-loaded in ssg_ks_insert.lsp).
|
|
(progn
|
|
(foreach paar (list (cons b-um v-um) (cons b-l v-l) (cons b-an v-an))
|
|
(if (null (cdr paar))
|
|
(princ (ssg-textf "kf-pruef-ks-fehlt-kurz" (list (car paar))))))
|
|
(setq fehler "kf-fehler-ks-fehlt"))
|
|
(progn
|
|
;; Eigenrichtungen der KS in Blockkoordinaten
|
|
(setq beta-aus-um (ks-xy-winkel (cadr (assoc "KS_AUS" ks-um)))
|
|
beta-ein-l (ks-xy-winkel (cadr (assoc "KS_EIN" ks-l)))
|
|
beta-aus-l (ks-xy-winkel (cadr (assoc "KS_AUS" ks-l)))
|
|
beta-ein-an (ks-xy-winkel (cadr (assoc "KS_EIN" ks-an))))
|
|
;; Die Umlenkstation gibt die Basisrichtung vor (hz 0); jeder
|
|
;; Folgebaustein richtet sich am KS_AUS seines Vorgaengers aus.
|
|
(setq hz-um 0.0)
|
|
(setq hz-l (cond ((kf-hz-folge (if beta-aus-um (+ beta-aus-um hz-um) nil)
|
|
beta-ein-l)) (0.0)))
|
|
(setq hz-an (cond ((kf-hz-folge (if beta-aus-l (+ beta-aus-l hz-l) nil)
|
|
beta-ein-an)) (hz-l)))
|
|
;; Hoehenbeitrag der beiden Stationen (Massstab 1)
|
|
(setq dy-um (kf-dy-eingebaut (car v-um) (cadr v-um) hz-um 1.0))
|
|
(setq dy-an (kf-dy-eingebaut (car v-an) (cadr v-an) hz-an 1.0))))))
|
|
(list (cons "fehler" fehler)
|
|
(cons "hz-um" (cond (hz-um) (0.0)))
|
|
(cons "hz-l" (cond (hz-l) (0.0)))
|
|
(cons "hz-an" (cond (hz-an) (0.0)))
|
|
(cons "dy-um" (cond (dy-um) (0.0)))
|
|
(cons "dy-an" (cond (dy-an) (0.0)))
|
|
(cons "dx-l" (cond ((car v-l)) (0.0)))
|
|
(cons "dy-l" (cond ((cadr v-l)) (0.0)))))
|
|
|
|
;; Laenge + Massstab fuer eine Hoehe aus einem gemessenen Geometrie-Record.
|
|
;; Rueckgabe: (laenge skala fehler-key) - laenge/skala nil bei Fehler.
|
|
(defun kf-laenge-fuer-hoehe (geo hoehe lmin lmax / laenge skala key)
|
|
(if (cdr (assoc "fehler" geo))
|
|
(list nil nil (cdr (assoc "fehler" geo)))
|
|
(progn
|
|
(setq laenge (kf-laenge-berechnen hoehe
|
|
(cdr (assoc "dy-um" geo))
|
|
(cdr (assoc "dy-an" geo))
|
|
(cdr (assoc "dy-l" geo))
|
|
(cdr (assoc "hz-l" geo))))
|
|
(setq key (kf-laenge-pruefen laenge lmin lmax))
|
|
(if key
|
|
(list nil nil key)
|
|
(progn
|
|
(setq skala (kf-skala-berechnen laenge (cdr (assoc "dx-l" geo))))
|
|
(if (null skala)
|
|
(list nil nil "kf-fehler-ks-fehlt")
|
|
(list laenge skala nil)))))))
|
|
|
|
;; ============================================================
|
|
;; KETTE BAUEN (aufgerichtet, 3D)
|
|
;; ============================================================
|
|
;; Fuegt die drei Bausteine ab startpunkt verkettet ein - AUFGERICHTET, die
|
|
;; Hoehe laeuft also in Z (siehe kf-matrix-aufrecht). basis-hz dreht die
|
|
;; fertige Baugruppe in der Draufsicht.
|
|
;; Rueckgabe: Weltpunkt des KS_AUS der Antriebsstation (Kettenende).
|
|
(defun kf-kette-bauen (variante geo skala startpunkt basis-hz / pt)
|
|
(setq pt startpunkt)
|
|
(setq pt (insert-block-ks-matrix
|
|
(ssg-json-get variante "block_umlenkung")
|
|
pt
|
|
(kf-matrix-aufrecht basis-hz (cdr (assoc "hz-um" geo)))
|
|
1.0))
|
|
(setq pt (insert-block-ks-matrix
|
|
(ssg-json-get variante "block_laenge")
|
|
pt
|
|
(kf-matrix-aufrecht basis-hz (cdr (assoc "hz-l" geo)))
|
|
skala))
|
|
(setq pt (insert-block-ks-matrix
|
|
(ssg-json-get variante "block_antrieb")
|
|
pt
|
|
(kf-matrix-aufrecht basis-hz (cdr (assoc "hz-an" geo)))
|
|
1.0))
|
|
pt)
|
|
|
|
;; ------------------------------------------------------------
|
|
;; DRAUFSICHT (KF_2D) - deckungsgleich mit der Kette
|
|
;; ------------------------------------------------------------
|
|
;; KF_2D gehoert in DIESELBE Lage wie die Kette, nicht daneben: sein KS_EIN
|
|
;; faellt mit KS_EIN der Umlenkung zusammen, sein KS_AUS mit KS_AUS des
|
|
;; Antriebs. Dadurch ist die Baugruppe EIN Koerper - von oben sieht man die
|
|
;; Draufsicht, von der Seite die Kette.
|
|
;;
|
|
;; Zwischenzeitlich lagen beide Ansichten 1000 mm uebereinander (versatz_y).
|
|
;; Das war eine Hilfskonstruktion, solange die Kette flach in der XY-Ebene
|
|
;; lag; seit sie aufgerichtet eingebaut wird, ist sie unnoetig.
|
|
;;
|
|
;; KF_2D ist selbst flach gezeichnet und wird darum NICHT aufgerichtet,
|
|
;; sondern nur um die Steigung GENEIGT (Rz(basis) * Ry(-winkel)) und auf die
|
|
;; SCHRAEGLAENGE skaliert. In der Draufsicht erscheint es dadurch genau mit
|
|
;; der Grundrisslaenge - die Verkuerzung uebernimmt die Projektion, sie muss
|
|
;; nicht gerechnet werden.
|
|
|
|
;; Neigungswinkel und Schraeglaenge aus Start- und Endpunkt der Kette.
|
|
;; Rueckgabe: (schraeglaenge winkel-grad), oder nil bei Laenge 0.
|
|
;; Reiner Rechenkern - der eigentliche Pruefpunkt der 3D-Umstellung.
|
|
(defun kf-neigung-aus-punkten (p1 p2 basis-hz / rad dx dy dz horiz laenge)
|
|
(setq rad (* (float basis-hz) (/ pi 180.0)))
|
|
(setq dx (- (car p2) (car p1))
|
|
dy (- (cadr p2) (cadr p1))
|
|
dz (- (cond ((caddr p2)) (0.0)) (cond ((caddr p1)) (0.0))))
|
|
;; Horizontalanteil auf die Kettenrichtung projiziert (nicht die blosse
|
|
;; X-Differenz) - sonst stimmt es bei gedreht eingefuegter Kette nicht.
|
|
(setq horiz (+ (* dx (cos rad)) (* dy (sin rad))))
|
|
(setq laenge (sqrt (+ (* horiz horiz) (* dz dz))))
|
|
(if (< laenge 1e-6)
|
|
nil
|
|
(list laenge (/ (* 180.0 (atan dz horiz)) pi))))
|
|
|
|
;; Draufsicht einfuegen - deckungsgleich mit der Kette.
|
|
;; kette-start/kette-ende = KS_EIN der Umlenkung bzw. KS_AUS des Antriebs.
|
|
;; Rueckgabe: die verwendete Schraeglaenge (mm), sonst nil.
|
|
(defun kf-ansicht-2d-bauen (daten kette-start kette-ende basis-hz /
|
|
cfg bname masse laenge winkel ks ein-dx skala R)
|
|
(setq cfg (ssg-json-get daten "ansicht_2d"))
|
|
(setq bname (if cfg (ssg-json-get cfg "block")))
|
|
(if (or (null bname) (= bname ""))
|
|
nil
|
|
(progn
|
|
(setq masse (kf-neigung-aus-punkten kette-start kette-ende basis-hz))
|
|
(if (null masse)
|
|
(progn (princ (ssg-text "kf-2d-laenge-null")) nil)
|
|
(progn
|
|
(setq laenge (car masse) winkel (cadr masse))
|
|
(if (null (kf-block-laden bname))
|
|
(progn (princ (ssg-textf "kf-fehler-block-datei" (list bname))) nil)
|
|
(progn
|
|
(setq ks (ks-block-messen bname))
|
|
(setq ein-dx (car (cond ((ks-versatz ks)) ('(0.0 0.0 0.0)))))
|
|
(setq skala (kf-skala-berechnen laenge ein-dx))
|
|
(if (null skala)
|
|
(progn (princ (ssg-textf "kf-2d-ks-fehlt" (list bname))) nil)
|
|
(progn
|
|
;; Ry(-winkel) hebt die flache Scheibe um die Steigung an;
|
|
;; das Vorzeichen folgt der Rechte-Hand-Regel (positives dz
|
|
;; = Drehung gegen den Uhrzeigersinn um die Y-Achse).
|
|
(setq R (mat3-mul-mat3 (ks-rot-z basis-hz)
|
|
(ks-rot-y (- winkel))))
|
|
(insert-block-ks-matrix bname kette-start R skala)
|
|
(princ (ssg-textf "kf-2d-gebaut"
|
|
(list bname (rtos laenge 2 0) (rtos winkel 2 1))))
|
|
laenge)))))))))
|
|
|
|
;; ============================================================
|
|
;; DREHWINKEL DES BLOCKS (XDATA)
|
|
;; ============================================================
|
|
;; Der Drehwinkel der Baugruppe wird beim Bau in die GEOMETRIE eingerechnet
|
|
;; (kf-matrix-aufrecht), nicht ueber die Drehung der Blockreferenz:
|
|
;; ssg-block-wrap-welt fuegt den fertigen Block immer mit Drehung 0 ein. Die
|
|
;; Referenz traegt damit nirgends mehr, wie die Kette gedreht wurde - KF_EDIT
|
|
;; wuerde sie beim Neuaufbau ungedreht neu bauen. Darum steht der Winkel als
|
|
;; XDATA am Block (Projektregel: Editierdaten gehoeren in XDATA, nicht in
|
|
;; .dbg). Eine spaetere Drehung der Referenz von Hand kommt ueber
|
|
;; Gruppencode 50 hinzu und wird addiert.
|
|
(setq *kf-xdata-app* "SSG_KF_EDIT")
|
|
|
|
;; Gesamtdrehung = gebauter Winkel (XDATA, Grad) + Drehung der Referenz
|
|
;; (Gruppencode 50, Bogenmass), auf -180..180 Grad normalisiert. Reiner
|
|
;; Rechenkern; fehlende Werte zaehlen als 0 (Altbestand ohne XDATA).
|
|
(defun kf-drehung-gesamt (xdata-grad dxf50-rad / g r)
|
|
(setq g (cond (xdata-grad (float xdata-grad)) (0.0)))
|
|
(setq r (cond (dxf50-rad (float dxf50-rad)) (0.0)))
|
|
(ks-winkel-normalisieren (+ g (/ (* 180.0 r) pi))))
|
|
|
|
(defun kf-xdata-schreiben (ent drehung-grad / eintrag)
|
|
(regapp *kf-xdata-app*)
|
|
(setq eintrag (list *kf-xdata-app*
|
|
(cons 1000 "kf-edit")
|
|
(cons 1040 (float drehung-grad))))
|
|
(entmod (append (entget ent) (list (list -3 eintrag))))
|
|
ent)
|
|
|
|
;; Gebauter Drehwinkel (Grad) aus der XDATA, nil wenn keine vorhanden ist.
|
|
(defun kf-xdata-lesen (ent / xd daten paar)
|
|
(setq xd (entget ent (list *kf-xdata-app*)))
|
|
(setq daten (cdr (assoc -3 xd)))
|
|
(if daten
|
|
(progn
|
|
(setq paar (assoc 1040 (cdr (car daten))))
|
|
(if paar (cdr paar) nil))
|
|
nil))
|
|
|
|
;; ============================================================
|
|
;; BLOCK ABSCHLIESSEN
|
|
;; ============================================================
|
|
;; Sammelt alle seit last-ent erzeugten Objekte, legt die ATTDEFs an, fasst
|
|
;; alles zu KF_<n> zusammen und beschriftet den fertigen Block.
|
|
;; Vorbild: gf-block-erstellen (Gefaellestrecke.lsp).
|
|
(defun kf-block-erstellen (variante geo hoehe laenge verbindung
|
|
startpunkt last-ent kf-nummer
|
|
farbe antriebsmotor movimot steuerung drehung /
|
|
kf-bname kf-ss ent kf-insert winkel-str)
|
|
(setq kf-bname (strcat "KF_" (itoa kf-nummer)))
|
|
;; Winkel als nackte Ganzzahl ("26"/"30") - bewusst ueber itoa/fix statt
|
|
;; rtos: rtos haengt an DIMZIN/LUPREC/LUNITS der Zeichnung und liefert je
|
|
;; nach Zeichnungsprofil unterschiedliche Schreibweisen. Dieser Wert landet
|
|
;; als Attribut WINKEL am Block und wird vom Sivas-Export als Schluessel der
|
|
;; Tabelle [kf_typ_anzeige] verwendet - er muss profilunabhaengig sein
|
|
;; (gleiche Ueberlegung wie bei ssg-sepliste-fmt-koord).
|
|
(setq winkel-str (itoa (fix (+ 0.5 (kf-zahl (ssg-json-get variante "winkel"))))))
|
|
;; ATTDEFs (unsichtbar, am Startpunkt) nach dem KF-Schema
|
|
(foreach def (kf-attrib-defs)
|
|
(entmake
|
|
(list '(0 . "ATTDEF")
|
|
(cons 10 startpunkt)
|
|
(cons 11 startpunkt)
|
|
'(40 . 50.0)
|
|
(cons 1 (cadr def))
|
|
(cons 2 (car def))
|
|
(cons 3 (car def))
|
|
'(70 . 1)
|
|
'(72 . 0)
|
|
'(74 . 0))))
|
|
;; Alle Entities seit last-ent einsammeln
|
|
(setq kf-ss (ssadd))
|
|
(setq ent (if last-ent (entnext last-ent) (entnext)))
|
|
(while ent
|
|
(ssadd ent kf-ss)
|
|
(setq ent (entnext ent)))
|
|
;; Block definieren und einfuegen (OSMODE/ELEVATION/BKS werden dabei sauber
|
|
;; abgeschaltet, siehe ssg-block-wrap-welt)
|
|
(ssg-block-wrap-welt kf-bname startpunkt kf-ss)
|
|
(setq kf-insert (entlast))
|
|
;; Gebauten Drehwinkel festhalten, damit KF_EDIT ihn wiederfindet
|
|
(kf-xdata-schreiben kf-insert drehung)
|
|
(ssg-layer-setzen kf-insert (cond ((ssg-json-get variante "layer"))
|
|
((ssg-json-get (kf-daten) "layer"))
|
|
("kettenfoerderer")))
|
|
(ssg-attrib-set-on kf-insert
|
|
(list
|
|
(cons "Bezeichnung" kf-bname)
|
|
;; FOERDERERTYP = Bauart im Klartext (aus der JSON, mit Sonderzeichen),
|
|
;; WINKEL = Neigungswinkel als nackte Zahl ("26"/"30")
|
|
(cons "FOERDERERTYP" (cond ((ssg-json-get (kf-daten) "foerderertyp"))
|
|
("Schraegfoerderer Stahl")))
|
|
(cons "WINKEL" winkel-str)
|
|
(cons "H_EINBAUHOEHE_mm" (itoa (fix (+ 0.5 (float hoehe)))))
|
|
(cons "L_KF_mm" (itoa (fix (+ 0.5 (float laenge)))))
|
|
(cons "FARBE" (cond (farbe) ("RAL 7035")))
|
|
(cons "ANTRIEBSMOTOR" (cond (antriebsmotor) ("Europa 50 Hz")))
|
|
(cons "ANTRIEBSART" (kf-antriebsart (kf-daten)))
|
|
(cons "MOVIMOT" (cond (movimot) ("0")))
|
|
(cons "STANDARD_STEUERUNG" (cond (steuerung) ("0")))
|
|
(cons "VERBINDUNGSELEMENTE" (cond (verbindung) ("Nein")))
|
|
(cons "ARTINR" (cond ((ssg-json-get variante "sivas_id")) ("")))))
|
|
(ssg-id-generate kf-insert)
|
|
kf-insert)
|
|
|
|
;; Naechste freie KF-Nummer in der Zeichnung.
|
|
(defun kf-naechste-nummer ( / n ss i nm num)
|
|
(setq n 0)
|
|
(setq ss (ssget "X" '((0 . "INSERT") (2 . "KF_*"))))
|
|
(if ss
|
|
(progn
|
|
(setq i 0)
|
|
(while (< i (sslength ss))
|
|
(setq nm (cdr (assoc 2 (entget (ssname ss i)))))
|
|
(setq num (atoi (substr nm 4)))
|
|
(if (> num n) (setq n num))
|
|
(setq i (1+ i)))))
|
|
(1+ n))
|
|
|
|
;; ============================================================
|
|
;; DIALOG
|
|
;; ============================================================
|
|
;; Zustand zwischen den Aufrufen (Dialogstand bleibt je Sitzung erhalten).
|
|
(if (not (boundp '*kf-dlg-variante*)) (setq *kf-dlg-variante* 0))
|
|
(if (not (boundp '*kf-dlg-variante-gesetzt*)) (setq *kf-dlg-variante-gesetzt* nil))
|
|
(if (not (boundp '*kf-dlg-hoehe*)) (setq *kf-dlg-hoehe* nil))
|
|
(if (not (boundp '*kf-dlg-verbindung*)) (setq *kf-dlg-verbindung* 0))
|
|
(if (not (boundp '*kf-dlg-farbe*)) (setq *kf-dlg-farbe* 0))
|
|
(if (not (boundp '*kf-dlg-antriebsmotor*)) (setq *kf-dlg-antriebsmotor* 0))
|
|
(if (not (boundp '*kf-dlg-movimot*)) (setq *kf-dlg-movimot* 0))
|
|
(if (not (boundp '*kf-dlg-steuerung*)) (setq *kf-dlg-steuerung* 0))
|
|
|
|
;; ------------------------------------------------------------
|
|
;; DCL-VORLAGE: Varianten als Radiobuttons
|
|
;; ------------------------------------------------------------
|
|
;; DCL kann Tiles weder zur Laufzeit erzeugen noch radio_button-Labels per
|
|
;; set_tile aendern - der Varianten-Block wird darum an der Markerzeile
|
|
;; //@VARIANTEN@ eingesetzt (gleiches Vorgehen wie geruest_traeger.dcl).
|
|
;; Radiobuttons statt popup_list, weil es nur zwei Werte gibt und beide ohne
|
|
;; Aufklappen sichtbar sein sollen.
|
|
|
|
(defun kf-radio-key (i) (strcat "v" (itoa i)))
|
|
|
|
(defun kf-radio-index (key)
|
|
(if (and key (> (strlen key) 1)) (atoi (substr key 2)) 0))
|
|
|
|
;; Beschriftung einer Variante im Dialog: NUR der Winkel ("26 °"), nicht der
|
|
;; volle Variantenname - der Gruppenrahmen nennt bereits "Schraegfoerderer
|
|
;; Stahl Typ", der Name waere dort doppelt. Die Regelausfuehrung bekommt den
|
|
;; Zusatz "(Standard)".
|
|
;;
|
|
;; Welche Variante das ist, steht als "standard": true in der JSON und NICHT
|
|
;; im Code - sonst muesste bei einer Umstellung auf 30 Grad der Code
|
|
;; angefasst werden. Das Gradzeichen kommt als (chr 176) ueber einen
|
|
;; Platzhalter, damit die Sprachdatei ASCII bleibt (Projektkonvention).
|
|
(defun kf-variante-standard-p (variante)
|
|
(not (null (ssg-json-get variante "standard"))))
|
|
|
|
(defun kf-variante-label (variante / w)
|
|
(setq w (kf-zahl (ssg-json-get variante "winkel")))
|
|
(if w
|
|
(ssg-textf (if (kf-variante-standard-p variante)
|
|
"kf-variante-label-standard"
|
|
"kf-variante-label")
|
|
(list (itoa (fix (+ 0.5 w))) (chr 176)))
|
|
(cond ((ssg-json-get variante "name")) (""))))
|
|
|
|
;; Index der Standard-Variante (fuer die Vorauswahl beim ersten Aufruf);
|
|
;; 0, wenn keine als Standard markiert ist.
|
|
(defun kf-standard-index (varianten / i treffer)
|
|
(setq i 0 treffer nil)
|
|
(foreach v varianten
|
|
(if (and (null treffer) (kf-variante-standard-p v)) (setq treffer i))
|
|
(setq i (1+ i)))
|
|
(cond (treffer) (0)))
|
|
|
|
(defun kf-dcl-varianten-zeilen (varianten / i erg)
|
|
(setq erg nil i 0)
|
|
(foreach v varianten
|
|
(setq erg (append erg
|
|
(list (strcat " : radio_button { key = \"" (kf-radio-key i)
|
|
"\"; label = \"" (kf-variante-label v) "\"; }"))))
|
|
(setq i (1+ i)))
|
|
erg)
|
|
|
|
;; Rueckgabe: Pfad der gefuellten temporaeren DCL-Datei oder nil.
|
|
(defun kf-dcl-schreiben (varianten)
|
|
(ssg-dcl-vorlage-fuellen (kf-dcl-pfad "kettenfoerderer.dcl") "kettenfoerderer"
|
|
(list (cons "VARIANTEN" (kf-dcl-varianten-zeilen varianten)))))
|
|
|
|
;; ------------------------------------------------------------
|
|
;; EINBAUHOEHE AUS ZWEI GEPICKTEN PUNKTEN
|
|
;; ------------------------------------------------------------
|
|
;; Zweite Eingabeart neben dem Zahlenfeld: statt die Hoehe zu tippen, werden
|
|
;; zwei Punkte in der Zeichnung gewaehlt (z.B. Oberkante Zufuehrung und
|
|
;; Oberkante Abgabe) und ihr Hoehenunterschied uebernommen.
|
|
;;
|
|
;; Gemessen wird die Differenz in Z: die Baugruppe steht aufgerichtet im Modell
|
|
;; (siehe kf-matrix-aufrecht), ihre Hoehe ist also die Hoehe der Zeichnung.
|
|
;; Damit nachvollziehbar bleibt, was gemessen wurde, nennt die Meldung BEIDE
|
|
;; Differenzen (dZ und dY): wer in einer DRAUFSICHT pickt, sieht sofort, dass
|
|
;; dort dZ = 0 ist, und kann es melden.
|
|
;;
|
|
;; Reiner Rechenkern (ohne Zeichnung testbar): nimmt zwei Punkte, liefert
|
|
;; (dz dy) als Betraege - die HOEHE zuerst.
|
|
(defun kf-punkt-differenzen (p1 p2)
|
|
(if (and p1 p2 (listp p1) (listp p2))
|
|
(list (abs (- (cond ((caddr p2)) (0.0)) (cond ((caddr p1)) (0.0))))
|
|
(abs (- (cadr p2) (cadr p1))))
|
|
nil))
|
|
|
|
;; Zwei Punkte abfragen und die Hoehe daraus bestimmen.
|
|
;; Rueckgabe: Hoehe in mm, oder nil bei Abbruch.
|
|
(defun kf-hoehe-aus-punkten ( / p1 p2 d)
|
|
(setq p1 (getpoint (ssg-text "kf-prompt-messpunkt-1")))
|
|
(if (null p1)
|
|
nil
|
|
(progn
|
|
(setq p2 (getpoint p1 (ssg-text "kf-prompt-messpunkt-2")))
|
|
(if (null p2)
|
|
nil
|
|
(progn
|
|
(setq d (kf-punkt-differenzen p1 p2))
|
|
(princ (ssg-textf "kf-messung-ergebnis"
|
|
(list (rtos (car d) 2 1) (rtos (cadr d) 2 1))))
|
|
(car d))))))
|
|
|
|
;; Wert eines Auswahleintrags ("wert", sonst "name", sonst Vorgabe).
|
|
;; Gemeinsam genutzt von Dialog und Konsolen-Rueckfall.
|
|
(defun kf-auswahl-wert (liste idx vorgabe / e)
|
|
(setq e (nth idx liste))
|
|
(cond ((null e) vorgabe)
|
|
((ssg-json-get e "wert"))
|
|
((ssg-json-get e "name"))
|
|
(t vorgabe)))
|
|
|
|
;; Dialog zeigen - SCHLEIFE, bis OK oder Abbruch. Rueckgabe:
|
|
;; (variante hoehe verbindung farbe antriebsmotor movimot)
|
|
;; oder nil bei Abbruch.
|
|
;;
|
|
;; Die Schleife gibt es wegen der zweiten Hoehen-Eingabeart: der Knopf
|
|
;; "Hoehe messen" schliesst den Dialog (done_dialog 2), laesst zwei Punkte in
|
|
;; der Zeichnung waehlen und zeigt ihn mit dem gemessenen Wert erneut. Aus
|
|
;; einem action_tile heraus laesst sich kein getpoint aufrufen - dasselbe
|
|
;; Vorgehen wie beim Speichern/Loeschen im Geruest-Dialog (done_dialog 2/3).
|
|
;;
|
|
;; Die Laengenvorschau unter dem Hoehenfeld gab es zwischenzeitlich; sie ist
|
|
;; auf Nutzerwunsch wieder entfallen. Ein nicht baubarer Wert wird darum erst
|
|
;; nach OK gemeldet (alert in c:KETTENFOERDERER).
|
|
(defun kf-dialog (daten / varianten verbindungen farben motoren movimots
|
|
steuerungen idx ergebnis gemessen)
|
|
(setq varianten (ssg-json-get daten "varianten")
|
|
verbindungen (ssg-json-get daten "verbindungselemente")
|
|
farben (ssg-json-get daten "farbe")
|
|
motoren (ssg-json-get daten "antriebsmotor")
|
|
movimots (ssg-json-get daten "movimot")
|
|
steuerungen (ssg-json-get daten "standard_steuerung"))
|
|
(if (null *kf-dlg-hoehe*)
|
|
(setq *kf-dlg-hoehe*
|
|
(cond ((kf-zahl (ssg-json-get (ssg-json-get daten "einbauhoehe") "vorgabe")))
|
|
(1500.0))))
|
|
;; Beim ERSTEN Aufruf je Sitzung die Regelausfuehrung vorwaehlen; danach
|
|
;; bleibt die zuletzt getroffene Wahl stehen.
|
|
(if (null *kf-dlg-variante-gesetzt*)
|
|
(progn
|
|
(setq *kf-dlg-variante* (kf-standard-index varianten))
|
|
(setq *kf-dlg-variante-gesetzt* T)))
|
|
(setq idx 2)
|
|
(while (= idx 2)
|
|
(setq idx (kf-dialog-zeigen daten varianten verbindungen farben motoren
|
|
movimots steuerungen))
|
|
(if (= idx 2)
|
|
(progn
|
|
(setq gemessen (kf-hoehe-aus-punkten))
|
|
(if gemessen (setq *kf-dlg-hoehe* gemessen))))
|
|
)
|
|
(if (= idx 1)
|
|
(list (nth *kf-dlg-variante* varianten)
|
|
*kf-dlg-hoehe*
|
|
(kf-auswahl-wert verbindungen *kf-dlg-verbindung* "Nein")
|
|
(kf-auswahl-wert farben *kf-dlg-farbe* "RAL 7035")
|
|
(kf-auswahl-wert motoren *kf-dlg-antriebsmotor* "Europa 50 Hz")
|
|
(kf-auswahl-wert movimots *kf-dlg-movimot* "0")
|
|
(kf-auswahl-wert steuerungen *kf-dlg-steuerung* "0"))
|
|
nil))
|
|
|
|
;; Den Dialog EINMAL zeigen. Rueckgabe: 1 = OK, 0 = Abbruch, 2 = "Hoehe
|
|
;; messen" (der Aufrufer pickt dann zwei Punkte und ruft erneut auf).
|
|
(defun kf-dialog-zeigen (daten varianten verbindungen farben motoren movimots
|
|
steuerungen /
|
|
dcl-pfad dcl-id idx vb-namen fa-namen nz-namen mm-namen
|
|
st-namen)
|
|
(setq vb-namen (mapcar '(lambda (v) (cond ((ssg-json-get v "name")) (""))) verbindungen))
|
|
(setq fa-namen (mapcar '(lambda (v) (cond ((ssg-json-get v "name")) (""))) farben))
|
|
(setq nz-namen (mapcar '(lambda (v) (cond ((ssg-json-get v "name")) (""))) motoren))
|
|
(setq mm-namen (mapcar '(lambda (v) (cond ((ssg-json-get v "name")) (""))) movimots))
|
|
(setq st-namen (mapcar '(lambda (v) (cond ((ssg-json-get v "name")) (""))) steuerungen))
|
|
;; Vorlage mit den Varianten-Radiobuttons fuellen (Temp-Datei)
|
|
(setq dcl-pfad (kf-dcl-schreiben varianten))
|
|
(if (not dcl-pfad)
|
|
(progn (alert (ssg-text "kf-fehler-dcl")) 0)
|
|
(progn
|
|
(setq dcl-id (load_dialog dcl-pfad))
|
|
(if (not (new_dialog "kettenfoerderer" dcl-id))
|
|
(progn (unload_dialog dcl-id) (vl-file-delete dcl-pfad)
|
|
(alert (ssg-text "kf-fehler-dcl")) 0)
|
|
(progn
|
|
(start_list "verbindung") (mapcar 'add_list vb-namen) (end_list)
|
|
(start_list "farbe") (mapcar 'add_list fa-namen) (end_list)
|
|
(start_list "antriebsmotor") (mapcar 'add_list nz-namen) (end_list)
|
|
(start_list "movimot") (mapcar 'add_list mm-namen) (end_list)
|
|
(start_list "standard_steuerung") (mapcar 'add_list st-namen) (end_list)
|
|
;; Radiobuttons: der gewaehlte Button wird einzeln gesetzt, nicht
|
|
;; die Gruppe - set_tile auf den Gruppenschluessel waehlt nicht aus.
|
|
(if (>= *kf-dlg-variante* (length varianten)) (setq *kf-dlg-variante* 0))
|
|
(set_tile (kf-radio-key *kf-dlg-variante*) "1")
|
|
(set_tile "verbindung" (itoa *kf-dlg-verbindung*))
|
|
(set_tile "farbe" (itoa *kf-dlg-farbe*))
|
|
(set_tile "antriebsmotor" (itoa *kf-dlg-antriebsmotor*))
|
|
(set_tile "movimot" (itoa *kf-dlg-movimot*))
|
|
(set_tile "standard_steuerung" (itoa *kf-dlg-steuerung*))
|
|
(set_tile "hoehe" (rtos *kf-dlg-hoehe* 2 0))
|
|
;; Merkmal 357: Dropdown mit einer einzigen Option, immer gewaehlt
|
|
(start_list "antriebsart")
|
|
(mapcar 'add_list
|
|
(mapcar '(lambda (v) (cond ((ssg-json-get v "name")) ("")))
|
|
(ssg-json-get daten "antriebsart")))
|
|
(end_list)
|
|
(set_tile "antriebsart" "0")
|
|
;; Die Radiobutton-Gruppe meldet den KEY des gewaehlten Buttons
|
|
;; ("v0"/"v1"), nicht dessen Index - daher kf-radio-index.
|
|
(action_tile "variante" "(setq *kf-dlg-variante* (kf-radio-index $value))")
|
|
(action_tile "hoehe" "(setq *kf-dlg-hoehe* (atof $value))")
|
|
(action_tile "verbindung" "(setq *kf-dlg-verbindung* (atoi $value))")
|
|
(action_tile "farbe" "(setq *kf-dlg-farbe* (atoi $value))")
|
|
(action_tile "antriebsmotor" "(setq *kf-dlg-antriebsmotor* (atoi $value))")
|
|
(action_tile "movimot" "(setq *kf-dlg-movimot* (atoi $value))")
|
|
(action_tile "standard_steuerung" "(setq *kf-dlg-steuerung* (atoi $value))")
|
|
;; Zweite Hoehen-Eingabeart: Dialog schliessen, der Aufrufer laesst
|
|
;; zwei Punkte waehlen und zeigt ihn danach erneut.
|
|
(action_tile "hoehe_messen" "(done_dialog 2)")
|
|
(action_tile "accept" "(done_dialog 1)")
|
|
(action_tile "cancel" "(done_dialog 0)")
|
|
(setq idx (start_dialog))
|
|
(unload_dialog dcl-id)
|
|
(vl-file-delete dcl-pfad)
|
|
idx)))))
|
|
|
|
;; DCL-Pfad aufloesen: DXFM_DCL, sonst dcl/ unter der Projektwurzel.
|
|
;; Gleiches Vorgehen wie geruest-dcl-pfad (GeruestInsert.lsp) - bewusst eine
|
|
;; eigene kurze Funktion statt eines Zugriffs quer ins Geruest-Modul, damit
|
|
;; dieses Modul ohne GeruestInsert ladbar bleibt.
|
|
(defun kf-dcl-pfad (datei / basis)
|
|
(setq basis (cond ((getenv "DXFM_DCL"))
|
|
((strcat (getenv "DXFMAKRO") "/dcl"))))
|
|
(if (and basis (/= basis ""))
|
|
(findfile (strcat basis "/" datei))
|
|
nil))
|
|
|
|
;; ============================================================
|
|
;; KONSOLEN-RUECKFALL (ohne GUI, fuer automatische Tests)
|
|
;; ============================================================
|
|
;; Eine Auswahlliste auf der Konsole abfragen. Rueckgabe: 0-basierter Index
|
|
;; (bei ungueltiger Eingabe bleibt die Vorgabe stehen). Alle vier Auswahlen
|
|
;; laufen hierueber - vorher stand derselbe Block viermal untereinander.
|
|
(defun kf-konsole-wahl (liste header-key prompt-key vorgabe-idx / i v antwort)
|
|
(princ (ssg-text header-key))
|
|
(setq i 1)
|
|
(foreach v liste
|
|
(princ (ssg-textf "kf-konsole-option" (list (itoa i) (ssg-json-get v "name"))))
|
|
(setq i (1+ i)))
|
|
(setq antwort (ssg-in-int (ssg-text prompt-key) (1+ vorgabe-idx)))
|
|
(if (or (null antwort) (< antwort 1) (> antwort (length liste)))
|
|
vorgabe-idx
|
|
(1- antwort)))
|
|
|
|
(defun kf-konsole (daten / varianten verbindungen farben motoren movimots
|
|
steuerungen hoehe)
|
|
(setq varianten (ssg-json-get daten "varianten")
|
|
verbindungen (ssg-json-get daten "verbindungselemente")
|
|
farben (ssg-json-get daten "farbe")
|
|
motoren (ssg-json-get daten "antriebsmotor")
|
|
movimots (ssg-json-get daten "movimot")
|
|
steuerungen (ssg-json-get daten "standard_steuerung"))
|
|
(setq *kf-dlg-variante*
|
|
(kf-konsole-wahl varianten "kf-konsole-variante-header"
|
|
"kf-konsole-variante-prompt" *kf-dlg-variante*))
|
|
;; Hoehe: Zahl tippen ODER 0 eingeben und zwei Punkte messen (zweite
|
|
;; Eingabeart, entspricht dem Knopf im Dialog).
|
|
(princ (ssg-text "kf-konsole-hoehe-hinweis"))
|
|
(setq hoehe (ssg-in-real (ssg-text "kf-konsole-hoehe-prompt")
|
|
(cond (*kf-dlg-hoehe*) (1500.0))))
|
|
(if (and hoehe (<= hoehe 0.0))
|
|
(setq hoehe (kf-hoehe-aus-punkten)))
|
|
(if (null hoehe) (setq hoehe (cond (*kf-dlg-hoehe*) (1500.0))))
|
|
(setq *kf-dlg-hoehe* hoehe)
|
|
;; Reihenfolge wie im Dialog und im Sivas-Merkmalstamm: 361 vor 354.
|
|
(setq *kf-dlg-steuerung*
|
|
(kf-konsole-wahl steuerungen "kf-konsole-steuerung-header"
|
|
"kf-konsole-steuerung-prompt" *kf-dlg-steuerung*))
|
|
(setq *kf-dlg-farbe*
|
|
(kf-konsole-wahl farben "kf-konsole-farbe-header"
|
|
"kf-konsole-farbe-prompt" *kf-dlg-farbe*))
|
|
(setq *kf-dlg-antriebsmotor*
|
|
(kf-konsole-wahl motoren "kf-konsole-antriebsmotor-header"
|
|
"kf-konsole-antriebsmotor-prompt" *kf-dlg-antriebsmotor*))
|
|
(setq *kf-dlg-movimot*
|
|
(kf-konsole-wahl movimots "kf-konsole-movimot-header"
|
|
"kf-konsole-movimot-prompt" *kf-dlg-movimot*))
|
|
(setq *kf-dlg-verbindung*
|
|
(kf-konsole-wahl verbindungen "kf-konsole-verbindung-header"
|
|
"kf-konsole-verbindung-prompt" *kf-dlg-verbindung*))
|
|
(list (nth *kf-dlg-variante* varianten)
|
|
hoehe
|
|
(kf-auswahl-wert verbindungen *kf-dlg-verbindung* "Nein")
|
|
(kf-auswahl-wert farben *kf-dlg-farbe* "RAL 7035")
|
|
(kf-auswahl-wert motoren *kf-dlg-antriebsmotor* "Europa 50 Hz")
|
|
(kf-auswahl-wert movimots *kf-dlg-movimot* "0")
|
|
(kf-auswahl-wert steuerungen *kf-dlg-steuerung* "0")))
|
|
|
|
;; ============================================================
|
|
;; C:KETTENFOERDERER - Hauptbefehl
|
|
;; ============================================================
|
|
(defun c:KETTENFOERDERER ( / daten eingabe variante hoehe verbindung
|
|
farbe antriebsmotor movimot steuerung
|
|
geo erg laenge skala endpunkt
|
|
lmin lmax startpunkt drehung last-ent kf-nummer ent
|
|
t0)
|
|
;; Laufzeit des Dialogaufbaus protokollieren (Schalter "kf-zeit", siehe
|
|
;; ssg_dbg.lsp). Hintergrund: der Dialog erschien beim ersten Menueklick
|
|
;; spuerbar verzoegert. Statt zu raten, wird die Zeit bis zum Dialog
|
|
;; gemessen - so laesst sich unterscheiden, ob das Lazy-Laden des Moduls,
|
|
;; das Lesen der JSON oder der Dialogaufbau selbst die Zeit kostet.
|
|
(setq t0 (getvar "MILLISECS"))
|
|
(setq daten (kf-daten))
|
|
(kf-zeit "Daten geladen" t0)
|
|
(if (null daten)
|
|
(princ (ssg-text "kf-fehler-daten-leer"))
|
|
(progn
|
|
(setq lmin (kf-zahl (ssg-json-get (ssg-json-get daten "laenge") "min"))
|
|
lmax (kf-zahl (ssg-json-get (ssg-json-get daten "laenge") "max")))
|
|
(kf-zeit "vor Dialog" t0)
|
|
(setq eingabe (if (ssg-gui-p) (kf-dialog daten) (kf-konsole daten)))
|
|
(if (null eingabe)
|
|
(princ (ssg-text "kf-abgebrochen"))
|
|
(progn
|
|
(setq variante (nth 0 eingabe)
|
|
hoehe (nth 1 eingabe)
|
|
verbindung (nth 2 eingabe)
|
|
farbe (nth 3 eingabe)
|
|
antriebsmotor (nth 4 eingabe)
|
|
movimot (nth 5 eingabe)
|
|
steuerung (nth 6 eingabe))
|
|
(setq geo (kf-geometrie-messen variante))
|
|
(setq erg (kf-laenge-fuer-hoehe geo hoehe lmin lmax))
|
|
(if (caddr erg)
|
|
(progn
|
|
(if (ssg-gui-p) (alert (ssg-text (caddr erg))))
|
|
(princ (ssg-text (caddr erg))))
|
|
(progn
|
|
(setq laenge (car erg) skala (cadr erg))
|
|
(setq startpunkt (getpoint (ssg-text "kf-prompt-startpunkt")))
|
|
(if (null startpunkt)
|
|
(princ (ssg-text "kf-abgebrochen"))
|
|
(progn
|
|
(setq drehung (getangle startpunkt (ssg-text "kf-prompt-drehung")))
|
|
(setq drehung (if drehung (/ (* 180.0 drehung) pi) 0.0))
|
|
(ssg-start "Kettenfoerderer" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
|
|
(setvar "OSMODE" 0)
|
|
(setvar "ATTREQ" 0)
|
|
(setvar "ATTDIA" 0)
|
|
(setq last-ent (ssg-lastent-ohne-attribute))
|
|
(setq kf-nummer (kf-naechste-nummer))
|
|
;; Kette und Draufsicht liegen DECKUNGSGLEICH - beide
|
|
;; beginnen am gewaehlten Punkt. Die Draufsicht gehoert mit
|
|
;; in dieselbe Baugruppe, darum VOR kf-block-erstellen.
|
|
(setq endpunkt (kf-kette-bauen variante geo skala startpunkt drehung))
|
|
(kf-ansicht-2d-bauen daten startpunkt endpunkt drehung)
|
|
(setq ent (kf-block-erstellen variante geo hoehe laenge verbindung
|
|
startpunkt last-ent kf-nummer farbe antriebsmotor movimot
|
|
steuerung drehung))
|
|
(ssg-end)
|
|
(princ (ssg-textf "kf-fertig"
|
|
(list (strcat "KF_" (itoa kf-nummer))
|
|
(rtos (float hoehe) 2 0)
|
|
(rtos laenge 2 0))))))))))))
|
|
(princ))
|
|
|
|
;; ============================================================
|
|
;; C:KF_EDIT - Doppelklick auf einen KF_n-Block
|
|
;; ============================================================
|
|
;; Zeigt den Dialog mit den Werten des gewaehlten Blocks und baut ihn nach OK
|
|
;; an SEINER Stelle neu auf. Vorbild: GEFAELLESTRECKE_EDIT.
|
|
;;
|
|
;; Einfuegepunkt und Drehung kommen aus dem Block selbst (Gruppencode 10 und
|
|
;; 50), nicht aus XDATA: der Kettenfoerderer hat keine Aufbau-Historie, die
|
|
;; ueber diese beiden Werte hinausgeht - alles Uebrige steht in den
|
|
;; Attributen. Ein von Hand verschobener oder gedrehter Block wird dadurch
|
|
;; korrekt an seiner NEUEN Lage neu gebaut.
|
|
;;
|
|
;; Der alte Block wird erst geloescht, wenn der Benutzer den Dialog mit OK
|
|
;; bestaetigt hat - ein Abbruch laesst die Zeichnung unveraendert.
|
|
|
|
;; Dialogzustand aus den Attributen eines Blocks vorbelegen. Sucht je
|
|
;; Auswahlliste den Index, dessen "wert" zum Attributwert passt; ein
|
|
;; unbekannter Wert (von Hand editiert) laesst die Vorgabe stehen, statt den
|
|
;; Dialog scheitern zu lassen.
|
|
(defun kf-index-fuer-wert (liste wert vorgabe / i treffer)
|
|
(setq i 0 treffer nil)
|
|
(foreach e liste
|
|
(if (and (null treffer) wert
|
|
(equal (ssg-json-get e "wert") wert))
|
|
(setq treffer i))
|
|
(setq i (1+ i)))
|
|
(cond (treffer) (vorgabe)))
|
|
|
|
(defun kf-dlg-aus-attributen (daten attribs / w v)
|
|
(setq w (cdr (assoc "WINKEL" attribs)))
|
|
(if w
|
|
(progn
|
|
(setq v (kf-variante-finden (atof w) (ssg-json-get daten "varianten")))
|
|
(if v
|
|
(setq *kf-dlg-variante*
|
|
(kf-tag-index-liste v (ssg-json-get daten "varianten"))))))
|
|
(setq w (cdr (assoc "H_EINBAUHOEHE_mm" attribs)))
|
|
(if (and w (/= w "")) (setq *kf-dlg-hoehe* (atof w)))
|
|
(setq *kf-dlg-farbe*
|
|
(kf-index-fuer-wert (ssg-json-get daten "farbe")
|
|
(cdr (assoc "FARBE" attribs)) *kf-dlg-farbe*))
|
|
(setq *kf-dlg-antriebsmotor*
|
|
(kf-index-fuer-wert (ssg-json-get daten "antriebsmotor")
|
|
(cdr (assoc "ANTRIEBSMOTOR" attribs)) *kf-dlg-antriebsmotor*))
|
|
(setq *kf-dlg-movimot*
|
|
(kf-index-fuer-wert (ssg-json-get daten "movimot")
|
|
(cdr (assoc "MOVIMOT" attribs)) *kf-dlg-movimot*))
|
|
(setq *kf-dlg-steuerung*
|
|
(kf-index-fuer-wert (ssg-json-get daten "standard_steuerung")
|
|
(cdr (assoc "STANDARD_STEUERUNG" attribs)) *kf-dlg-steuerung*))
|
|
(setq *kf-dlg-verbindung*
|
|
(kf-index-fuer-wert (ssg-json-get daten "verbindungselemente")
|
|
(cdr (assoc "VERBINDUNGSELEMENTE" attribs)) *kf-dlg-verbindung*))
|
|
;; Die Variante wurde eben aus dem Block gesetzt - die Standard-Vorauswahl
|
|
;; darf sie nicht mehr ueberschreiben.
|
|
(setq *kf-dlg-variante-gesetzt* T)
|
|
(princ))
|
|
|
|
;; Position eines Eintrags in einer Liste (0-basiert), 0 wenn nicht gefunden.
|
|
(defun kf-tag-index-liste (eintrag liste / i treffer)
|
|
(setq i 0 treffer nil)
|
|
(foreach e liste
|
|
(if (and (null treffer) (equal e eintrag)) (setq treffer i))
|
|
(setq i (1+ i)))
|
|
(cond (treffer) (0)))
|
|
|
|
(defun c:KF_EDIT ( / ent ed bname attribs daten eingabe variante hoehe
|
|
verbindung farbe antriebsmotor movimot steuerung
|
|
geo erg laenge skala lmin lmax startpunkt drehung
|
|
last-ent kf-nummer endpunkt)
|
|
(setq ent (car (entsel (ssg-text "kf-edit-waehlen"))))
|
|
(if (null ent)
|
|
(princ (ssg-text "kf-abgebrochen"))
|
|
(progn
|
|
(setq ed (entget ent))
|
|
(setq bname (cdr (assoc 2 ed)))
|
|
(if (or (/= (cdr (assoc 0 ed)) "INSERT") (not (wcmatch bname "KF_*")))
|
|
(alert (ssg-text "kf-edit-kein-kf"))
|
|
(progn
|
|
(setq daten (kf-daten))
|
|
(if (null daten)
|
|
(princ (ssg-text "kf-fehler-daten-leer"))
|
|
(progn
|
|
(setq attribs (ssg-attrib-read ent))
|
|
(setq startpunkt (cdr (assoc 10 ed)))
|
|
;; Der gebaute Winkel steckt in der XDATA, eine nachtraegliche
|
|
;; Drehung der Referenz in Gruppencode 50 - beides zaehlt.
|
|
(setq drehung (kf-drehung-gesamt (kf-xdata-lesen ent)
|
|
(cdr (assoc 50 ed))))
|
|
(kf-dlg-aus-attributen daten attribs)
|
|
(setq lmin (kf-zahl (ssg-json-get (ssg-json-get daten "laenge") "min"))
|
|
lmax (kf-zahl (ssg-json-get (ssg-json-get daten "laenge") "max")))
|
|
(setq eingabe (if (ssg-gui-p) (kf-dialog daten) (kf-konsole daten)))
|
|
(if (null eingabe)
|
|
(princ (ssg-text "kf-abgebrochen"))
|
|
(progn
|
|
(setq variante (nth 0 eingabe)
|
|
hoehe (nth 1 eingabe)
|
|
verbindung (nth 2 eingabe)
|
|
farbe (nth 3 eingabe)
|
|
antriebsmotor (nth 4 eingabe)
|
|
movimot (nth 5 eingabe)
|
|
steuerung (nth 6 eingabe))
|
|
(setq geo (kf-geometrie-messen variante))
|
|
(setq erg (kf-laenge-fuer-hoehe geo hoehe lmin lmax))
|
|
(if (caddr erg)
|
|
(progn
|
|
(if (ssg-gui-p) (alert (ssg-text (caddr erg))))
|
|
(princ (ssg-text (caddr erg))))
|
|
(progn
|
|
(setq laenge (car erg) skala (cadr erg))
|
|
(ssg-start "Kettenfoerderer Edit"
|
|
'(("OSMODE") ("ATTREQ") ("ATTDIA")))
|
|
(setvar "OSMODE" 0)
|
|
(setvar "ATTREQ" 0)
|
|
(setvar "ATTDIA" 0)
|
|
;; Erst jetzt loeschen - ein Abbruch oben laesst die
|
|
;; Zeichnung unveraendert.
|
|
(entdel ent)
|
|
(setq last-ent (ssg-lastent-ohne-attribute))
|
|
(setq kf-nummer (kf-naechste-nummer))
|
|
(setq endpunkt (kf-kette-bauen variante geo skala
|
|
startpunkt drehung))
|
|
(kf-ansicht-2d-bauen daten startpunkt endpunkt drehung)
|
|
(kf-block-erstellen variante geo hoehe laenge verbindung
|
|
startpunkt last-ent kf-nummer farbe antriebsmotor
|
|
movimot steuerung drehung)
|
|
(ssg-end)
|
|
(princ (ssg-textf "kf-edit-fertig"
|
|
(list bname (strcat "KF_" (itoa kf-nummer)))))))))))))))
|
|
(princ))
|
|
|
|
;; ============================================================
|
|
;; C:KF_KS_PRUEFEN - Diagnose
|
|
;; ============================================================
|
|
;; Liest fuer jede Variante die KS-Lage aller drei Bloecke aus und gibt sie
|
|
;; aus: Ursprung und Richtung von KS_EIN/KS_AUS, daraus die abgeleiteten
|
|
;; Einbauwinkel und Hoehenbeitraege. Erste Anlaufstelle, wenn eine Kette
|
|
;; nicht zusammenpasst - zeigt sofort, ob ein Block kein KS_EIN/KS_AUS hat
|
|
;; oder ob seine Achsen anders liegen als erwartet.
|
|
(defun c:KF_KS_PRUEFEN ( / daten varianten geo b)
|
|
(setq daten (kf-daten))
|
|
(if (null daten)
|
|
(princ (ssg-text "kf-fehler-daten-leer"))
|
|
(progn
|
|
(setq varianten (ssg-json-get daten "varianten"))
|
|
(princ (ssg-text "kf-pruef-kopf"))
|
|
(foreach v varianten
|
|
(princ (ssg-textf "kf-pruef-variante" (list (ssg-json-get v "name"))))
|
|
(foreach feld '("block_umlenkung" "block_laenge" "block_antrieb")
|
|
(setq b (ssg-json-get v feld))
|
|
(kf-pruef-block b))
|
|
(setq geo (kf-geometrie-messen v))
|
|
(if (cdr (assoc "fehler" geo))
|
|
(princ (ssg-textf "kf-pruef-fehler" (list (ssg-text (cdr (assoc "fehler" geo))))))
|
|
(princ (ssg-textf "kf-pruef-geo"
|
|
(list (rtos (cdr (assoc "hz-um" geo)) 2 2)
|
|
(rtos (cdr (assoc "hz-l" geo)) 2 2)
|
|
(rtos (cdr (assoc "hz-an" geo)) 2 2)
|
|
(rtos (cdr (assoc "dy-um" geo)) 2 2)
|
|
(rtos (cdr (assoc "dy-an" geo)) 2 2)
|
|
(rtos (cdr (assoc "dx-l" geo)) 2 2)
|
|
(rtos (cdr (assoc "dy-l" geo)) 2 2))))))))
|
|
(princ))
|
|
|
|
;; Einen Block vermessen und protokollieren (Helfer von KF_KS_PRUEFEN).
|
|
(defun kf-pruef-block (blockname / ks ein aus)
|
|
(if (null (kf-block-laden blockname))
|
|
(princ (ssg-textf "kf-pruef-block-fehlt" (list blockname)))
|
|
(progn
|
|
(setq ks (ks-block-messen blockname))
|
|
(setq ein (cadr (assoc "KS_EIN" ks))
|
|
aus (cadr (assoc "KS_AUS" ks)))
|
|
(if (not (and ein aus))
|
|
(princ (ssg-textf "kf-pruef-ks-fehlt"
|
|
(list blockname
|
|
(if ein (ssg-text "kf-pruef-ja") (ssg-text "kf-pruef-nein"))
|
|
(if aus (ssg-text "kf-pruef-ja") (ssg-text "kf-pruef-nein")))))
|
|
(princ (ssg-textf "kf-pruef-block"
|
|
(list blockname
|
|
(rtos (car (car ein)) 2 2) (rtos (cadr (car ein)) 2 2)
|
|
(cond ((rtos (ks-xy-winkel ein) 2 2)) ("-"))
|
|
(rtos (car (car aus)) 2 2) (rtos (cadr (car aus)) 2 2)
|
|
(cond ((rtos (ks-xy-winkel aus) 2 2)) ("-")))))))))
|
|
|
|
(setq *ssg-KettenFoerderer-loaded* T)
|
|
(princ "\n>>> KettenFoerderer.lsp geladen (KETTENFOERDERER, KF_KS_PRUEFEN)")
|
|
(princ)
|