refactor: Kettenfoerderer als Seitenansicht mit Beschriftung und Hoehenmass, Draufsicht als eigener Hilfsblock KF2D_n

- Hauptblock KF_n: flache, ungedrehte Seitenansicht mit Beschriftung und Hoehenmass; nur er wird exportiert
- Draufsicht KF_2D als getrennter Hilfsblock KF2D_n (projizierte Laenge, frei verschiebbar, per KF_EDIT regenerierbar), Verknuepfung ueber XDATA-Schluessel
- L_KF_mm = waagerechte Laenge, Sivas-Zeile ohne Laenge, Export nur KF_<Ziffern>
- ensure-block-loaded: Block ohne ILS-Datei (KF_2D) nicht mehr als fehlend melden
- Layer kettenfoerderer_beschriftung, Dispatcher-Zweig KF2D_*, Sprachdateien und Unit-Tests angepasst

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-30 15:42:58 +01:00
parent d9043ebca5
commit 503b02a005
10 changed files with 469 additions and 337 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+357 -258
View File
@@ -26,6 +26,14 @@
;; insert-block-by-ks/insert-block-ks-skaliert, die Rz*Ry-Primitiven des ;; insert-block-by-ks/insert-block-ks-skaliert, die Rz*Ry-Primitiven des
;; VarioFoerderers werden hier nicht gebraucht. ;; VarioFoerderers werden hier nicht gebraucht.
;; ;;
;; HAUPT- UND HILFSBLOCK: KF_<n> ist die Seitenansicht (ungedreht, Einfuege-
;; punkt = KS_EIN der Umlenkung) mit Beschriftung und Hoehenmass; nur dieser
;; Block wird exportiert. Die Draufsicht KF_2D ist ein getrennter Hilfsblock
;; KF2D_<n> (zum Anschliessen von Schienen), der aus der projizierten Laenge
;; entsteht, beim ersten Mal 1000 mm unter dem Hauptblock liegt, frei
;; verschiebbar und loeschbar ist und per Doppelklick auf KF_<n> neu erzeugt
;; wird. Beide tragen denselben Schluessel in der XDATA (SSG_KF_EDIT).
;;
;; Die Einbauhoehe H (Abstand KS_EIN der Umlenkung bis KS_AUS des Antriebs auf ;; Die Einbauhoehe H (Abstand KS_EIN der Umlenkung bis KS_AUS des Antriebs auf
;; der Y-Achse) bestimmt die Laenge des Zwischenstuecks ueber die ;; der Y-Achse) bestimmt die Laenge des Zwischenstuecks ueber die
;; Hoehenbilanz, siehe kf-laenge-berechnen. ;; Hoehenbilanz, siehe kf-laenge-berechnen.
@@ -223,7 +231,8 @@
;; STANDARD_STEUERUNG - Merkmal 361, "1"/"0" ueber Transform ja_nein. ;; STANDARD_STEUERUNG - Merkmal 361, "1"/"0" ueber Transform ja_nein.
;; Steht direkt hinter WINKEL, wie im Merkmalstamm. ;; Steht direkt hinter WINKEL, wie im Merkmalstamm.
;; H_EINBAUHOEHE_mm - Merkmal 360 ;; H_EINBAUHOEHE_mm - Merkmal 360
;; L_KF_mm - Laenge des skalierten Zwischenstuecks, CSV-Spalte ;; L_KF_mm - WAAGERECHTE Laenge des ganzen Foerderers (der Draufsicht
;; KF_2D), CSV-Spalte "Laenge"
;; FARBE - Merkmal 354 ;; FARBE - Merkmal 354
;; ANTRIEBSMOTOR - Merkmal 355 (eigenes Merkmal, nicht Teil von 354) ;; ANTRIEBSMOTOR - Merkmal 355 (eigenes Merkmal, nicht Teil von 354)
;; ANTRIEBSART - Merkmal 357, FEST "1.1 kW" (Wert aus der JSON, ;; ANTRIEBSART - Merkmal 357, FEST "1.1 kW" (Wert aus der JSON,
@@ -327,27 +336,6 @@
(if (and (null treffer) (findfile k)) (setq treffer (findfile k)))) (if (and (null treffer) (findfile k)) (setq treffer (findfile k))))
treffer) 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 ;; GEOMETRIE EINER VARIANTE MESSEN
;; ============================================================ ;; ============================================================
@@ -433,156 +421,261 @@
(list laenge skala nil))))))) (list laenge skala nil)))))))
;; ============================================================ ;; ============================================================
;; KETTE BAUEN (aufgerichtet, 3D) ;; KETTE BAUEN (Seitenansicht)
;; ============================================================ ;; ============================================================
;; Fuegt die drei Bausteine ab startpunkt verkettet ein - AUFGERICHTET, die ;; Fuegt die drei Bausteine ab startpunkt verkettet ein. Die Kette ist eine
;; Hoehe laeuft also in Z (siehe kf-matrix-aufrecht). basis-hz dreht die ;; SEITENANSICHT: sie liegt flach in der XY-Ebene (X = Fahrtrichtung,
;; fertige Baugruppe in der Draufsicht. ;; Y = Hoehe), so wie die Bausteine gezeichnet sind. Es wird nichts
;; aufgerichtet und nichts gedreht; jeder Baustein bekommt nur den aus den KS
;; gemessenen Verkettungswinkel (kf-hz-folge).
;; (Zwischenzeitlich wurde die Kette aufgerichtet in Z eingebaut - nach
;; Abstimmung wieder zurueckgenommen; die Draufsicht ist jetzt ein EIGENER
;; Hilfsblock, siehe kf-hilfsblock-bauen.)
;; Rueckgabe: Weltpunkt des KS_AUS der Antriebsstation (Kettenende). ;; Rueckgabe: Weltpunkt des KS_AUS der Antriebsstation (Kettenende).
(defun kf-kette-bauen (variante geo skala startpunkt basis-hz / pt) (defun kf-kette-bauen (variante geo skala startpunkt / pt)
(setq pt startpunkt) (setq pt startpunkt)
(setq pt (insert-block-ks-matrix (setq pt (insert-block-by-ks
(ssg-json-get variante "block_umlenkung") (ssg-json-get variante "block_umlenkung") pt
pt (cdr (assoc "hz-um" geo))))
(kf-matrix-aufrecht basis-hz (cdr (assoc "hz-um" geo))) (setq pt (insert-block-ks-skaliert
1.0)) (ssg-json-get variante "block_laenge") pt
(setq pt (insert-block-ks-matrix (cdr (assoc "hz-l" geo)) skala))
(ssg-json-get variante "block_laenge") (setq pt (insert-block-by-ks
pt (ssg-json-get variante "block_antrieb") pt
(kf-matrix-aufrecht basis-hz (cdr (assoc "hz-l" geo))) (cdr (assoc "hz-an" 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) pt)
;; ------------------------------------------------------------ ;; ------------------------------------------------------------
;; DRAUFSICHT (KF_2D) - deckungsgleich mit der Kette ;; MASSE AUS START- UND ENDPUNKT (reine Rechenkerne)
;; ------------------------------------------------------------ ;; ------------------------------------------------------------
;; KF_2D gehoert in DIESELBE Lage wie die Kette, nicht daneben: sein KS_EIN ;; Horizontalanteil von p1 nach p2, auf die Kettenrichtung (basis-hz, Grad)
;; faellt mit KS_EIN der Umlenkung zusammen, sein KS_AUS mit KS_AUS des ;; projiziert und nicht die blosse X-Differenz - sonst stimmt es bei einem von
;; Antriebs. Dadurch ist die Baugruppe EIN Koerper - von oben sieht man die ;; Hand gedrehten Block nicht. Die Hoehe (Y) geht NICHT ein.
;; Draufsicht, von der Seite die Kette. (defun kf-horiz-projektion (p1 p2 basis-hz / rad dx dy)
;;
;; 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 rad (* (float basis-hz) (/ pi 180.0)))
(setq dx (- (car p2) (car p1)) (setq dx (- (car p2) (car p1))
dy (- (cadr p2) (cadr p1)) dy (- (cadr p2) (cadr p1)))
dz (- (cond ((caddr p2)) (0.0)) (cond ((caddr p1)) (0.0)))) (+ (* dx (cos rad)) (* dy (sin rad))))
;; 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. ;; WAAGERECHTE (projizierte) Laenge der Kette = Laenge der Draufsicht KF_2D.
;; kette-start/kette-ende = KS_EIN der Umlenkung bzw. KS_AUS des Antriebs. ;; Das ist der Wert im Attribut L_KF_mm. Immer positiv.
;; Rueckgabe: die verwendete Schraeglaenge (mm), sonst nil. (defun kf-waagerecht-laenge (p1 p2 basis-hz)
(defun kf-ansicht-2d-bauen (daten kette-start kette-ende basis-hz / (abs (kf-horiz-projektion p1 p2 basis-hz)))
cfg bname masse laenge winkel ks ein-dx skala R)
;; Neigungswinkel der Variante als nackte Ganzzahl ("26"/"30"), bewusst ueber
;; itoa/fix statt rtos: rtos haengt an DIMZIN/LUPREC/LUNITS der Zeichnung. Der
;; Wert steht im Attribut WINKEL und ist Schluessel der Tabelle
;; [kf_typ_anzeige] im Sivas-Export - er muss profilunabhaengig sein.
(defun kf-winkel-text (variante)
(itoa (fix (+ 0.5 (cond ((kf-zahl (ssg-json-get variante "winkel"))) (0.0))))))
;; Punkt um versatz-y in Y verschoben (Z bleibt, fehlendes Z = 0).
(defun kf-versatzpunkt (p versatz-y)
(list (car p) (+ (cadr p) (float versatz-y)) (cond ((caddr p)) (0.0))))
;; Versatz des Hilfsblocks (Draufsicht) gegen den Hauptblock beim ERSTEN
;; Einfuegen, in mm (Y). Steht in der JSON, nicht im Code; Vorgabe -1000.
;; (Pruefung ueber if, nicht ueber and/or: and liefert T statt der Zahl.)
(defun kf-hilfsblock-versatz (daten / cfg wert)
(setq cfg (ssg-json-get daten "ansicht_2d")) (setq cfg (ssg-json-get daten "ansicht_2d"))
(setq bname (if cfg (ssg-json-get cfg "block"))) (setq wert (if cfg (kf-zahl (ssg-json-get cfg "versatz_y"))))
(if (or (null bname) (= bname "")) (cond (wert) (-1000.0)))
nil
;; ------------------------------------------------------------
;; BESCHRIFTUNG UND HOEHENMASS
;; ------------------------------------------------------------
;; Beschriftung wie bei VF_/GF_ (gf-make-label): ein TEXT, Hoehe 100, auf
;; einem eigenen Layer aus cfg/layer.cfg. Haupt- und Hilfsblock tragen
;; dieselbe Zeile: "KF_1 26 Grad-Zeichen H=1500mm L_horizontal=4951mm".
(defun kf-label-text (nummer winkel-str hoehe waagerecht)
(strcat "KF_" (itoa nummer) " " winkel-str (chr 176)
" H=" (itoa (fix (+ 0.5 (float hoehe)))) "mm"
" L_horizontal=" (itoa (fix (+ 0.5 (float waagerecht)))) "mm"))
;; Layer der Beschriftung (Baugruppe "kettenfoerderer_beschriftung" in
;; cfg/layer.cfg), sonst Hartwert - wie bei GF_/VF_.
(defun kf-beschriftungs-layer ( / lay)
(setq lay (ssg-layer-anlegen "kettenfoerderer_beschriftung" nil))
(if (null lay)
(progn (progn
(setq masse (kf-neigung-aus-punkten kette-start kette-ende basis-hz)) (setq lay "KF_Beschriftung")
(if (null masse) (ssg-make-layer lay "7" nil)))
(progn (princ (ssg-text "kf-2d-laenge-null")) nil) lay)
(progn
(setq laenge (car masse) winkel (cadr masse)) (defun kf-label-zeichnen (txt pt lay)
(if (null (kf-block-laden bname)) (entmake
(progn (princ (ssg-textf "kf-fehler-block-datei" (list bname))) nil) (list '(0 . "TEXT")
(progn (cons 10 pt)
(setq ks (ks-block-messen bname)) (cons 11 pt)
(setq ein-dx (car (cond ((ks-versatz ks)) ('(0.0 0.0 0.0))))) '(40 . 100.0)
(setq skala (kf-skala-berechnen laenge ein-dx)) (cons 1 txt)
(if (null skala) '(7 . "Standard")
(progn (princ (ssg-textf "kf-2d-ks-fehlt" (list bname))) nil) (cons 8 lay)
(progn '(72 . 1)
;; Ry(-winkel) hebt die flache Scheibe um die Steigung an; '(73 . 2)))
;; das Vorzeichen folgt der Rechte-Hand-Regel (positives dz (princ))
;; = Drehung gegen den Uhrzeigersinn um die Y-Achse).
(setq R (mat3-mul-mat3 (ks-rot-z basis-hz) ;; Senkrechtes Hoehenmass zwischen p-unten und p-oben, rechts neben dem
(ks-rot-y (- winkel)))) ;; Kettenende. Echtes DIMENSION-Objekt per ActiveX (AddDimRotated, 90 Grad) -
(insert-block-ks-matrix bname kette-start R skala) ;; kein Befehlsaufruf, der bei einem Fehler im Befehl haengen bleiben koennte.
(princ (ssg-textf "kf-2d-gebaut" ;; Jeder Schritt laeuft unter vl-catch-all-apply: scheitert das Mass, geht der
(list bname (rtos laenge 2 0) (rtos winkel 2 1)))) ;; Bau OHNE Mass weiter und meldet es (Hinweis, kein Abbruch). Textgroesse und
laenge))))))))) ;; Pfeile werden gesetzt, damit das Mass neben der 100-mm-Beschriftung lesbar
;; ist; fehlt eine Eigenschaft, bleibt der Wert der Bemassungsvariablen.
(defun kf-hoehenmass-zeichnen (p-unten p-oben lay / obj)
(setq obj (vl-catch-all-apply 'vla-AddDimRotated
(list modelspace
(vlax-3d-point p-unten)
(vlax-3d-point p-oben)
(vlax-3d-point (list (+ (car p-oben) 400.0)
(/ (+ (cadr p-unten) (cadr p-oben)) 2.0)
(caddr p-oben)))
(/ pi 2.0))))
(if (vl-catch-all-error-p obj)
(progn (princ (ssg-text "kf-bemassung-fehlt")) nil)
(progn
(foreach prop (list (list 'vla-put-TextHeight 100.0)
(list 'vla-put-ArrowheadSize 50.0)
(list 'vla-put-PrimaryUnitsPrecision 0)
(list 'vla-put-Layer lay))
(vl-catch-all-apply (car prop) (cons obj (cdr prop))))
T)))
;; Alles seit last-ent Entstandene als Auswahlsatz (fuer _.-BLOCK).
(defun kf-sammeln (last-ent / ss ent)
(setq ss (ssadd))
(setq ent (if last-ent (entnext last-ent) (entnext)))
(while ent
(ssadd ent ss)
(setq ent (entnext ent)))
ss)
;; Referenz um rot-rad (Bogenmass) um ihren Einfuegepunkt drehen. Der Block
;; wird immer ungedreht gebaut (ssg-block-wrap-welt fuegt mit Drehung 0 ein);
;; eine von Hand vorgenommene Drehung wird so beim Neuaufbau wieder aufgesetzt.
(defun kf-rotation-setzen (ent rot-rad / ed)
(if (and ent rot-rad (/= rot-rad 0.0))
(progn
(setq ed (entget ent))
(if (assoc 50 ed)
(entmod (subst (cons 50 rot-rad) (assoc 50 ed) ed)))))
ent)
;; ============================================================ ;; ============================================================
;; DREHWINKEL DES BLOCKS (XDATA) ;; SCHLUESSEL ZWISCHEN HAUPT- UND HILFSBLOCK (XDATA)
;; ============================================================ ;; ============================================================
;; Der Drehwinkel der Baugruppe wird beim Bau in die GEOMETRIE eingerechnet ;; Haupt- (KF_<n>) und Hilfsblock (KF2D_<n>) tragen denselben Schluessel als
;; (kf-matrix-aufrecht), nicht ueber die Drehung der Blockreferenz: ;; XDATA. Der Name taugt dafuer nicht: die Nummer wechselt bei JEDEM Neuaufbau
;; ssg-block-wrap-welt fuegt den fertigen Block immer mit Drehung 0 ein. Die ;; (KF_EDIT vergibt eine neue). Mit dem Schluessel findet KF_EDIT den
;; Referenz traegt damit nirgends mehr, wie die Kette gedreht wurde - KF_EDIT ;; Hilfsblock auch dann, wenn der Benutzer ihn verschoben hat, und erzeugt ihn
;; wuerde sie beim Neuaufbau ungedreht neu bauen. Darum steht der Winkel als ;; an seiner jetzigen Stelle neu (Projektregel: Editierdaten gehoeren in
;; XDATA am Block (Projektregel: Editierdaten gehoeren in XDATA, nicht in ;; XDATA, nicht in .dbg).
;; .dbg). Eine spaetere Drehung der Referenz von Hand kommt ueber
;; Gruppencode 50 hinzu und wird addiert.
(setq *kf-xdata-app* "SSG_KF_EDIT") (setq *kf-xdata-app* "SSG_KF_EDIT")
;; Gesamtdrehung = gebauter Winkel (XDATA, Grad) + Drehung der Referenz (defun kf-neuer-key () (ssg-timestamp))
;; (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) (defun kf-xdata-schreiben (ent key / eintrag)
(regapp *kf-xdata-app*) (regapp *kf-xdata-app*)
(setq eintrag (list *kf-xdata-app* (setq eintrag (list *kf-xdata-app*
(cons 1000 "kf-edit") (cons 1000 "kf-edit")
(cons 1040 (float drehung-grad)))) (cons 1000 key)))
(entmod (append (entget ent) (list (list -3 eintrag)))) (entmod (append (entget ent) (list (list -3 eintrag))))
ent) ent)
;; Gebauter Drehwinkel (Grad) aus der XDATA, nil wenn keine vorhanden ist. ;; Schluessel aus einer entget-Liste mit XDATA (reiner Kern, testbar): das
(defun kf-xdata-lesen (ent / xd daten paar) ;; ZWEITE 1000-Feld; nil bei fehlender oder Altbestands-XDATA (nur Marker).
(setq xd (entget ent (list *kf-xdata-app*))) (defun kf-key-aus-xdata (xd / daten teile)
(setq daten (cdr (assoc -3 xd))) (setq daten (cdr (assoc -3 xd)) teile '())
(if daten (if daten
(foreach p (cdr (car daten))
(if (= (car p) 1000) (setq teile (append teile (list (cdr p)))))))
(if (>= (length teile) 2) (cadr teile) nil))
(defun kf-xdata-key (ent)
(kf-key-aus-xdata (entget ent (list *kf-xdata-app*))))
;; Hilfsblock (KF2D_*) mit diesem Schluessel suchen; nil, wenn es keinen gibt
;; (nie gebaut oder vom Benutzer geloescht).
(defun kf-hilfsblock-finden (key / ss i e treffer)
(setq treffer nil)
(if key
(progn (progn
(setq paar (assoc 1040 (cdr (car daten)))) (regapp *kf-xdata-app*)
(if paar (cdr paar) nil)) (setq ss (ssget "X" (list '(0 . "INSERT") '(2 . "KF2D_*")
nil)) (list -3 (list *kf-xdata-app*)))))
(if ss
(progn
(setq i 0)
(while (and (null treffer) (< i (sslength ss)))
(setq e (ssname ss i))
(if (equal (kf-xdata-key e) key) (setq treffer e))
(setq i (1+ i)))))))
treffer)
;; ============================================================
;; HILFSBLOCK KF2D_<n> (Draufsicht)
;; ============================================================
;; Die Draufsicht KF_2D ist KEIN Teil des Foerderers, sondern ein
;; Hilfsblock, an dem der Benutzer Schienen anschliesst. Darum:
;; - eigener Block KF2D_<n> (nicht KF_*): die Export-Muster erfassen ihn nicht,
;; exportiert wird nur der Hauptblock KF_<n>
;; - flach in der XY-Ebene, auf die PROJIZIERTE Laenge des Foerderers skaliert
;; - unabhaengig verschiebbar; loescht der Benutzer ihn, bleibt der Hauptblock
;; unberuehrt, und KF_EDIT erzeugt ihn bei Bedarf neu
;; - traegt dieselbe Beschriftung wie der Hauptblock
;; Rueckgabe: die Referenz, sonst nil.
(defun kf-hilfsblock-bauen (daten nummer key winkel-str hoehe waagerecht
einfuegepunkt rot-rad /
cfg bname ks ein-dx skala last-ent lay hname ss ins)
(setq cfg (ssg-json-get daten "ansicht_2d"))
(setq bname (if cfg (ssg-json-get cfg "block")))
(cond
((or (null bname) (= bname "")) nil)
((null (kf-block-laden bname))
(princ (ssg-textf "kf-fehler-block-datei" (list bname)))
nil)
(t
(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 waagerecht ein-dx))
(if (null skala)
(progn (princ (ssg-textf "kf-2d-ks-fehlt" (list bname))) nil)
(progn
(setq hname (strcat "KF2D_" (itoa nummer)))
(setq last-ent (ssg-lastent-ohne-attribute))
(insert-block-ks-skaliert bname einfuegepunkt 0.0 skala)
(setq lay (kf-beschriftungs-layer))
(kf-label-zeichnen
(kf-label-text nummer winkel-str hoehe waagerecht)
(list (+ (car einfuegepunkt) (/ waagerecht 2.0))
(+ (cadr einfuegepunkt) 250.0)
(cond ((caddr einfuegepunkt)) (0.0)))
lay)
(setq ss (kf-sammeln last-ent))
(ssg-block-wrap-welt hname einfuegepunkt ss)
(setq ins (entlast))
(ssg-layer-setzen ins (cond ((ssg-json-get daten "layer")) ("kettenfoerderer")))
(kf-rotation-setzen ins rot-rad)
(kf-xdata-schreiben ins key)
(princ (ssg-textf "kf-2d-gebaut" (list hname (rtos waagerecht 2 0))))
ins)))))
;; ============================================================ ;; ============================================================
;; BLOCK ABSCHLIESSEN ;; BLOCK ABSCHLIESSEN
;; ============================================================ ;; ============================================================
;; Sammelt alle seit last-ent erzeugten Objekte, legt die ATTDEFs an, fasst ;; Beschriftung und Hoehenmass zeichnen, alle seit last-ent erzeugten Objekte
;; alles zu KF_<n> zusammen und beschriftet den fertigen Block. ;; sammeln, ATTDEFs anlegen und alles zu KF_<n> zusammenfassen. Vorbild:
;; Vorbild: gf-block-erstellen (Gefaellestrecke.lsp). ;; gf-block-erstellen (Gefaellestrecke.lsp).
(defun kf-block-erstellen (variante geo hoehe laenge verbindung ;; waagerecht = projizierte Laenge (Attribut L_KF_mm), key = Schluessel zum
startpunkt last-ent kf-nummer ;; Hilfsblock, rot-rad = von Hand gesetzte Drehung der Referenz (0 beim ersten
farbe antriebsmotor movimot steuerung drehung / ;; Einfuegen).
kf-bname kf-ss ent kf-insert winkel-str) (defun kf-block-erstellen (variante geo hoehe waagerecht verbindung
startpunkt endpunkt last-ent kf-nummer
farbe antriebsmotor movimot steuerung key rot-rad /
kf-bname kf-ss kf-insert winkel-str lay z)
(setq kf-bname (strcat "KF_" (itoa kf-nummer))) (setq kf-bname (strcat "KF_" (itoa kf-nummer)))
;; Winkel als nackte Ganzzahl ("26"/"30") - bewusst ueber itoa/fix statt (setq winkel-str (kf-winkel-text variante))
;; rtos: rtos haengt an DIMZIN/LUPREC/LUNITS der Zeichnung und liefert je (setq z (cond ((caddr startpunkt)) (0.0)))
;; 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 ;; ATTDEFs (unsichtbar, am Startpunkt) nach dem KF-Schema
(foreach def (kf-attrib-defs) (foreach def (kf-attrib-defs)
(entmake (entmake
@@ -596,18 +689,20 @@
'(70 . 1) '(70 . 1)
'(72 . 0) '(72 . 0)
'(74 . 0)))) '(74 . 0))))
;; Alle Entities seit last-ent einsammeln ;; Beschriftung unter der Kette, Hoehenmass rechts neben dem Kettenende
(setq kf-ss (ssadd)) (setq lay (kf-beschriftungs-layer))
(setq ent (if last-ent (entnext last-ent) (entnext))) (kf-label-zeichnen
(while ent (kf-label-text kf-nummer winkel-str hoehe waagerecht)
(ssadd ent kf-ss) (list (/ (+ (car startpunkt) (car endpunkt)) 2.0) (- (cadr startpunkt) 300.0) z)
(setq ent (entnext ent))) lay)
(kf-hoehenmass-zeichnen (list (car endpunkt) (cadr startpunkt) z)
(list (car endpunkt) (cadr endpunkt) z)
lay)
(setq kf-ss (kf-sammeln last-ent))
;; Block definieren und einfuegen (OSMODE/ELEVATION/BKS werden dabei sauber ;; Block definieren und einfuegen (OSMODE/ELEVATION/BKS werden dabei sauber
;; abgeschaltet, siehe ssg-block-wrap-welt) ;; abgeschaltet, siehe ssg-block-wrap-welt)
(ssg-block-wrap-welt kf-bname startpunkt kf-ss) (ssg-block-wrap-welt kf-bname startpunkt kf-ss)
(setq kf-insert (entlast)) (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-layer-setzen kf-insert (cond ((ssg-json-get variante "layer"))
((ssg-json-get (kf-daten) "layer")) ((ssg-json-get (kf-daten) "layer"))
("kettenfoerderer"))) ("kettenfoerderer")))
@@ -620,7 +715,9 @@
("Schraegfoerderer Stahl"))) ("Schraegfoerderer Stahl")))
(cons "WINKEL" winkel-str) (cons "WINKEL" winkel-str)
(cons "H_EINBAUHOEHE_mm" (itoa (fix (+ 0.5 (float hoehe))))) (cons "H_EINBAUHOEHE_mm" (itoa (fix (+ 0.5 (float hoehe)))))
(cons "L_KF_mm" (itoa (fix (+ 0.5 (float laenge))))) ;; WAAGERECHTE (projizierte) Laenge des ganzen Foerderers, nicht die
;; Laenge des schraegen Mittelstuecks
(cons "L_KF_mm" (itoa (fix (+ 0.5 (float waagerecht)))))
(cons "FARBE" (cond (farbe) ("RAL 7035"))) (cons "FARBE" (cond (farbe) ("RAL 7035")))
(cons "ANTRIEBSMOTOR" (cond (antriebsmotor) ("Europa 50 Hz"))) (cons "ANTRIEBSMOTOR" (cond (antriebsmotor) ("Europa 50 Hz")))
(cons "ANTRIEBSART" (kf-antriebsart (kf-daten))) (cons "ANTRIEBSART" (kf-antriebsart (kf-daten)))
@@ -629,6 +726,9 @@
(cons "VERBINDUNGSELEMENTE" (cond (verbindung) ("Nein"))) (cons "VERBINDUNGSELEMENTE" (cond (verbindung) ("Nein")))
(cons "ARTINR" (cond ((ssg-json-get variante "sivas_id")) (""))))) (cons "ARTINR" (cond ((ssg-json-get variante "sivas_id")) ("")))))
(ssg-id-generate kf-insert) (ssg-id-generate kf-insert)
;; Reihenfolge: erst Drehung (entmod der Referenz), ZULETZT die XDATA
(kf-rotation-setzen kf-insert rot-rad)
(kf-xdata-schreiben kf-insert key)
kf-insert) kf-insert)
;; Naechste freie KF-Nummer in der Zeichnung. ;; Naechste freie KF-Nummer in der Zeichnung.
@@ -655,9 +755,10 @@
(while (apply belegt-p (list n)) (setq n (1+ n))) (while (apply belegt-p (list n)) (setq n (1+ n)))
n) n)
;; Ist die Block-DEFINITION KF_<n> in der Zeichnung vorhanden? ;; Ist die Block-DEFINITION KF_<n> ODER KF2D_<n> in der Zeichnung vorhanden?
(defun kf-nummer-belegt-p (n) (defun kf-nummer-belegt-p (n)
(not (null (tblsearch "BLOCK" (strcat "KF_" (itoa n)))))) (not (null (or (tblsearch "BLOCK" (strcat "KF_" (itoa n)))
(tblsearch "BLOCK" (strcat "KF2D_" (itoa n)))))))
;; Naechste freie KF-Nummer. Bewusst NICHT nur ueber die Referenzen im Modell: ;; Naechste freie KF-Nummer. Bewusst NICHT nur ueber die Referenzen im Modell:
;; loescht man einen Foerderer (oder baut KF_EDIT ihn neu auf), lebt seine ;; loescht man einen Foerderer (oder baut KF_EDIT ihn neu auf), lebt seine
@@ -756,8 +857,8 @@
;; zwei Punkte in der Zeichnung gewaehlt (z.B. Oberkante Zufuehrung und ;; zwei Punkte in der Zeichnung gewaehlt (z.B. Oberkante Zufuehrung und
;; Oberkante Abgabe) und ihr Hoehenunterschied uebernommen. ;; Oberkante Abgabe) und ihr Hoehenunterschied uebernommen.
;; ;;
;; Gemessen wird die Differenz in Z: die Baugruppe steht aufgerichtet im Modell ;; Gemessen wird die Differenz in Z (die Hoehe der Punkte in der Zeichnung); die
;; (siehe kf-matrix-aufrecht), ihre Hoehe ist also die Hoehe der Zeichnung. ;; Differenz in Y wird nur mit ausgegeben.
;; Damit nachvollziehbar bleibt, was gemessen wurde, nennt die Meldung BEIDE ;; Damit nachvollziehbar bleibt, was gemessen wurde, nennt die Meldung BEIDE
;; Differenzen (dZ und dY): wer in einer DRAUFSICHT pickt, sieht sofort, dass ;; Differenzen (dZ und dY): wer in einer DRAUFSICHT pickt, sieht sofort, dass
;; dort dZ = 0 ist, und kann es melden. ;; dort dZ = 0 ist, und kann es melden.
@@ -981,72 +1082,91 @@
(kf-auswahl-wert movimots *kf-dlg-movimot* "0") (kf-auswahl-wert movimots *kf-dlg-movimot* "0")
(kf-auswahl-wert steuerungen *kf-dlg-steuerung* "0"))) (kf-auswahl-wert steuerungen *kf-dlg-steuerung* "0")))
;; ============================================================
;; KF_BAUEN - gemeinsamer Bau fuer Befehl und Edit
;; ============================================================
;; Baut Hauptblock KF_<n> (Seitenansicht mit Beschriftung + Hoehenmass) und
;; danach den Hilfsblock KF2D_<n> (Draufsicht). Beide Bloecke werden ungedreht
;; gebaut; eine Drehung (Edit eines von Hand gedrehten Blocks) setzt
;; kf-rotation-setzen danach wieder auf.
;; eingabe = Ergebnis von kf-dialog/kf-konsole (Variante, Hoehe, ...)
;; startpunkt = KS_EIN der Umlenkstation (Einfuegepunkt Hauptblock)
;; rot-rad = Drehung des Hauptblocks, hilfs-pt/hilfs-rot = Lage des Hilfsblocks
;; key = Schluessel Haupt <-> Hilfsblock (nil -> neuer)
;; Rueckgabe: Liste (Blockname Hoehe Laenge) bei Erfolg, sonst nil (die
;; Fehlermeldung ist dann schon ausgegeben, die Zeichnung unveraendert).
(defun kf-bauen (daten eingabe startpunkt rot-rad hilfs-pt hilfs-rot key
loeschen /
variante hoehe verbindung farbe antriebsmotor movimot steuerung
geo erg laenge skala lmin lmax endpunkt waagerecht
last-ent kf-nummer winkel-str)
(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 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 geo (kf-geometrie-messen variante))
(setq erg (kf-laenge-fuer-hoehe geo hoehe lmin lmax))
(cond
((caddr erg)
(if (ssg-gui-p) (alert (ssg-text (caddr erg))))
(princ (ssg-text (caddr erg)))
nil)
(t
(setq laenge (car erg) skala (cadr erg))
(ssg-start "Kettenfoerderer" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
(setvar "OSMODE" 0)
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
;; Edit: alte Bloecke (Liste von Enames) erst jetzt loeschen
(foreach e loeschen (if e (entdel e)))
(if (null key) (setq key (kf-neuer-key)))
(setq last-ent (ssg-lastent-ohne-attribute))
(setq kf-nummer (kf-naechste-nummer))
(setq winkel-str (kf-winkel-text variante))
(setq endpunkt (kf-kette-bauen variante geo skala startpunkt))
(setq waagerecht (kf-waagerecht-laenge startpunkt endpunkt 0.0))
(kf-block-erstellen variante geo hoehe waagerecht verbindung
startpunkt endpunkt last-ent kf-nummer
farbe antriebsmotor movimot steuerung key rot-rad)
(kf-hilfsblock-bauen daten kf-nummer key winkel-str hoehe waagerecht
hilfs-pt hilfs-rot)
(ssg-end)
(list (strcat "KF_" (itoa kf-nummer)) hoehe laenge))))
;; ============================================================ ;; ============================================================
;; C:KETTENFOERDERER - Hauptbefehl ;; C:KETTENFOERDERER - Hauptbefehl
;; ============================================================ ;; ============================================================
(defun c:KETTENFOERDERER ( / daten eingabe variante hoehe verbindung (defun c:KETTENFOERDERER ( / daten eingabe startpunkt erg t0)
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 ;; Laufzeit des Dialogaufbaus protokollieren (Schalter "kf-zeit", siehe
;; ssg_dbg.lsp). Hintergrund: der Dialog erschien beim ersten Menueklick ;; ssg_dbg.lsp): unterscheidet Lazy-Laden, JSON-Lesen und Dialogaufbau.
;; 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 t0 (getvar "MILLISECS"))
(setq daten (kf-daten)) (setq daten (kf-daten))
(kf-zeit "Daten geladen" t0) (kf-zeit "Daten geladen" t0)
(if (null daten) (if (null daten)
(princ (ssg-text "kf-fehler-daten-leer")) (princ (ssg-text "kf-fehler-daten-leer"))
(progn (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) (kf-zeit "vor Dialog" t0)
(setq eingabe (if (ssg-gui-p) (kf-dialog daten) (kf-konsole daten))) (setq eingabe (if (ssg-gui-p) (kf-dialog daten) (kf-konsole daten)))
(if (null eingabe) (if (null eingabe)
(princ (ssg-text "kf-abgebrochen")) (princ (ssg-text "kf-abgebrochen"))
(progn (progn
(setq variante (nth 0 eingabe) (setq startpunkt (getpoint (ssg-text "kf-prompt-startpunkt")))
hoehe (nth 1 eingabe) (if (null startpunkt)
verbindung (nth 2 eingabe) (princ (ssg-text "kf-abgebrochen"))
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 (progn
(if (ssg-gui-p) (alert (ssg-text (caddr erg)))) ;; Hilfsblock beim ersten Mal 1000 mm unter dem Hauptblock
(princ (ssg-text (caddr erg)))) (setq erg (kf-bauen daten eingabe startpunkt 0.0
(progn (kf-versatzpunkt startpunkt (kf-hilfsblock-versatz daten))
(setq laenge (car erg) skala (cadr erg)) 0.0 nil nil))
(setq startpunkt (getpoint (ssg-text "kf-prompt-startpunkt"))) (if erg
(if (null startpunkt) (princ (ssg-textf "kf-fertig"
(princ (ssg-text "kf-abgebrochen")) (list (car erg) (rtos (float (cadr erg)) 2 0)
(progn (rtos (caddr erg) 2 0)))))))))))
(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)) (princ))
;; ============================================================ ;; ============================================================
@@ -1056,10 +1176,11 @@
;; an SEINER Stelle neu auf. Vorbild: GEFAELLESTRECKE_EDIT. ;; an SEINER Stelle neu auf. Vorbild: GEFAELLESTRECKE_EDIT.
;; ;;
;; Einfuegepunkt und Drehung kommen aus dem Block selbst (Gruppencode 10 und ;; Einfuegepunkt und Drehung kommen aus dem Block selbst (Gruppencode 10 und
;; 50), nicht aus XDATA: der Kettenfoerderer hat keine Aufbau-Historie, die ;; 50), alles Uebrige steht in den Attributen. Ein von Hand verschobener oder
;; ueber diese beiden Werte hinausgeht - alles Uebrige steht in den ;; gedrehter Block wird dadurch an seiner NEUEN Lage neu gebaut. Die XDATA
;; Attributen. Ein von Hand verschobener oder gedrehter Block wird dadurch ;; traegt nur den Schluessel zum Hilfsblock KF2D_<n>: er wird mit dem Hauptblock
;; korrekt an seiner NEUEN Lage neu gebaut. ;; neu erzeugt (auch wenn der Benutzer ihn geloescht hatte) und behaelt die
;; Lage, an die der Benutzer ihn zuletzt gelegt hat.
;; ;;
;; Der alte Block wird erst geloescht, wenn der Benutzer den Dialog mit OK ;; Der alte Block wird erst geloescht, wenn der Benutzer den Dialog mit OK
;; bestaetigt hat - ein Abbruch laesst die Zeichnung unveraendert. ;; bestaetigt hat - ein Abbruch laesst die Zeichnung unveraendert.
@@ -1115,13 +1236,10 @@
(setq i (1+ i))) (setq i (1+ i)))
(cond (treffer) (0))) (cond (treffer) (0)))
(defun c:KF_EDIT ( / ss ent ed bname attribs daten eingabe variante hoehe (defun c:KF_EDIT ( / ss ent ed bname attribs daten eingabe startpunkt
verbindung farbe antriebsmotor movimot steuerung rot-rad key hilfs hilfs-pt hilfs-rot erg)
geo erg laenge skala lmin lmax startpunkt drehung
last-ent kf-nummer endpunkt)
;; Erst die VORGEWAEHLTE Auswahl (Doppelklick setzt sie), nur ohne sie per ;; Erst die VORGEWAEHLTE Auswahl (Doppelklick setzt sie), nur ohne sie per
;; Klick nachfragen - wie GEFAELLESTRECKE_EDIT/KreiselEdit. Vorher fragte ;; Klick nachfragen - wie GEFAELLESTRECKE_EDIT/KreiselEdit.
;; KF_EDIT auch nach einem Doppelklick noch einmal nach einer Auswahl.
(setq ss (ssget "I")) (setq ss (ssget "I"))
(setq ent (if (and ss (= (sslength ss) 1)) (setq ent (if (and ss (= (sslength ss) 1))
(ssname ss 0) (ssname ss 0)
@@ -1132,8 +1250,7 @@
(setq ed (entget ent)) (setq ed (entget ent))
(setq bname (cdr (assoc 2 ed))) (setq bname (cdr (assoc 2 ed)))
;; Nur echte Foerderer "KF_<n>": die Bausteine (KF_UM_26, KF_2D, ...) ;; Nur echte Foerderer "KF_<n>": die Bausteine (KF_UM_26, KF_2D, ...)
;; tragen ebenfalls das Praefix KF_, haben aber keine Attribute - ein ;; tragen ebenfalls das Praefix KF_, haben aber keine Attribute.
;; Neuaufbau aus ihnen waere sinnlos und wuerde sie loeschen.
(if (or (/= (cdr (assoc 0 ed)) "INSERT") (null (kf-nummer-aus-name bname))) (if (or (/= (cdr (assoc 0 ed)) "INSERT") (null (kf-nummer-aus-name bname)))
(alert (ssg-text "kf-edit-kein-kf")) (alert (ssg-text "kf-edit-kein-kf"))
(progn (progn
@@ -1141,53 +1258,35 @@
(if (null daten) (if (null daten)
(princ (ssg-text "kf-fehler-daten-leer")) (princ (ssg-text "kf-fehler-daten-leer"))
(progn (progn
(setq attribs (ssg-attrib-read ent)) (setq attribs (ssg-attrib-read ent))
(setq startpunkt (cdr (assoc 10 ed))) (setq startpunkt (cdr (assoc 10 ed)))
;; Der gebaute Winkel steckt in der XDATA, eine nachtraegliche (setq rot-rad (cond ((cdr (assoc 50 ed))) (0.0)))
;; Drehung der Referenz in Gruppencode 50 - beides zaehlt. ;; Schluessel zum Hilfsblock; Altbestand ohne Schluessel -> nil,
(setq drehung (kf-drehung-gesamt (kf-xdata-lesen ent) ;; dann gibt es keinen auffindbaren Hilfsblock und ein neuer
(cdr (assoc 50 ed)))) ;; entsteht an der Standardposition.
(setq key (kf-xdata-key ent))
(setq hilfs (kf-hilfsblock-finden key))
(if hilfs
(setq hilfs-pt (cdr (assoc 10 (entget hilfs)))
hilfs-rot (cond ((cdr (assoc 50 (entget hilfs)))) (0.0)))
(setq hilfs-pt (kf-versatzpunkt startpunkt
(kf-hilfsblock-versatz daten))
hilfs-rot 0.0))
(kf-dlg-aus-attributen daten attribs) (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))) (setq eingabe (if (ssg-gui-p) (kf-dialog daten) (kf-konsole daten)))
(if (null eingabe) (if (null eingabe)
(princ (ssg-text "kf-abgebrochen")) (princ (ssg-text "kf-abgebrochen"))
(progn (progn
(setq variante (nth 0 eingabe) ;; Der Hilfsblock wird bei JEDEM Edit neu erzeugt, damit er
hoehe (nth 1 eingabe) ;; zur neuen Hoehe/Laenge passt - an der Stelle, an der der
verbindung (nth 2 eingabe) ;; Benutzer ihn zuletzt hingelegt hat.
farbe (nth 3 eingabe) (setq erg
antriebsmotor (nth 4 eingabe) (kf-bauen daten eingabe startpunkt rot-rad hilfs-pt hilfs-rot
movimot (nth 5 eingabe) (cond (key) (kf-neuer-key))
steuerung (nth 6 eingabe)) (list ent hilfs)))
(setq geo (kf-geometrie-messen variante)) (if erg
(setq erg (kf-laenge-fuer-hoehe geo hoehe lmin lmax)) (princ (ssg-textf "kf-edit-fertig"
(if (caddr erg) (list bname (car 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)) (princ))
;; ============================================================ ;; ============================================================
+6
View File
@@ -462,6 +462,12 @@
) )
) )
;; Hilfsblock (Draufsicht) des Kettenfoerderers: kein eigener Edit - er wird
;; mit dem Hauptblock KF_<n> neu erzeugt (Doppelklick dort).
((wcmatch bname "KF2D_*")
(princ (ssg-text "cmd-kf2d-hilfsblock"))
)
;; Omniflo-Bloecke -> OMNI_EDIT ;; Omniflo-Bloecke -> OMNI_EDIT
;; Erkennung: TEILEART-Attribut vorhanden, AP110-Blockname oder rein numerisch ;; Erkennung: TEILEART-Attribut vorhanden, AP110-Blockname oder rein numerisch
((progn ((progn
+16 -4
View File
@@ -85,10 +85,21 @@
;; Realer Fehler, den das behebt: die KS-Messung eines KF-Bausteins lief ins ;; Realer Fehler, den das behebt: die KS-Messung eines KF-Bausteins lief ins
;; Leere und meldete "KS_EIN/KS_AUS fehlt", obwohl beide KS im Block vorhanden ;; Leere und meldete "KS_EIN/KS_AUS fehlt", obwohl beide KS im Block vorhanden
;; waren - gesucht wurde nur ein Blockname, den es nicht gibt. ;; waren - gesucht wurde nur ein Blockname, den es nicht gibt.
;;
;; Zweiter Sonderfall - Namen, die SELBST auf _2D/_3D enden (z.B. die
;; Kettenfoerderer-Draufsicht "KF_2D"): ssg-ils-blockname laesst solche Namen
;; unveraendert (eff = blockname), die Bedingung "eff existiert nicht" kann
;; dann nie zutreffen, und der Block ging in den ILS-Ladepfad. Der suchte
;; data/ils/KF_2D.dwg und meldete "Block-Datei nicht gefunden", obwohl der
;; Block in der Zeichnung vorhanden war. Massgeblich ist darum, ob es fuer den
;; Namen ueberhaupt eine ILS-Datei gibt: ohne Datei ist es kein ILS-Block und
;; die vorhandene Definition wird genommen. Echte ILS-Bloecke haben eine Datei
;; und laufen unveraendert durch den Ladepfad (Aktualisierung aus der Datei).
(defun ensure-block-loaded (blockname / eff) (defun ensure-block-loaded (blockname / eff)
(setq eff (ssg-ils-blockname blockname)) (setq eff (ssg-ils-blockname blockname))
(if (and (not (tblsearch "BLOCK" eff)) (if (and (tblsearch "BLOCK" blockname)
(tblsearch "BLOCK" blockname)) (or (= eff blockname) (not (tblsearch "BLOCK" eff)))
(null (ssg-ils-block-datei blockname)))
blockname blockname
(progn (progn
(if (not (ssg-ils-block-laden blockname)) (if (not (ssg-ils-block-laden blockname))
@@ -558,8 +569,9 @@
;; Bewusst matrixbasiert statt mit einem weiteren Winkelparameter: die ;; Bewusst matrixbasiert statt mit einem weiteren Winkelparameter: die
;; Aufrichtung ist nur EIN Anwendungsfall, und jeder weitere haette eine ;; Aufrichtung ist nur EIN Anwendungsfall, und jeder weitere haette eine
;; weitere Spezialfunktion gebraucht. Den Aufrufern bleibt freigestellt, ;; weitere Spezialfunktion gebraucht. Den Aufrufern bleibt freigestellt,
;; welche Drehungen sie kombinieren (beim Kettenfoerderer ;; welche Drehungen sie kombinieren. (Der Kettenfoerderer hat sie kurz fuer
;; Rz(basis) * Rx(90) * Rz(eigen), siehe kf-matrix-aufrecht). ;; Rz(basis) * Rx(90) * Rz(eigen) genutzt, ist inzwischen aber wieder eine flache
;; Seitenansicht - aktuell ohne Aufrufer.)
;; Elementare Rotationsmatrizen (3x3, Winkel in GRAD). ;; Elementare Rotationsmatrizen (3x3, Winkel in GRAD).
(defun ks-rot-x (grad / r c s) (defun ks-rot-x (grad / r c s)
+2
View File
@@ -174,6 +174,8 @@ planquadrate = ZZ_Planquadrate, 8
# ZUSAMMENGEBAUTE Baugruppe ohne eigene Blockdatei, der Layer muss darum hier # ZUSAMMENGEBAUTE Baugruppe ohne eigene Blockdatei, der Layer muss darum hier
# stehen. Die drei Bausteine darin behalten ihre eigenen Layer. # stehen. Die drei Bausteine darin behalten ihre eigenen Layer.
kettenfoerderer = Omni_Kettenfoerderer, 4 kettenfoerderer = Omni_Kettenfoerderer, 4
; Beschriftung (KF_n ... H=, L projiziert=) und Hoehenmass, auf Haupt- und Hilfsblock
kettenfoerderer_beschriftung = KF_Beschriftung, 7
# ============================================================ # ============================================================
+2 -2
View File
@@ -9,8 +9,8 @@
"einbauhoehe": { "vorgabe": 1500, "min": 300, "max": 8000 }, "einbauhoehe": { "vorgabe": 1500, "min": 300, "max": 8000 },
"laenge": { "min": 100, "max": 20000 }, "laenge": { "min": 100, "max": 20000 },
"_hinweis_ansicht": "KF_2D liegt DECKUNGSGLEICH mit der Kette (KS_EIN auf KS_EIN der Umlenkung, KS_AUS auf KS_AUS des Antriebs) - die Baugruppe ist EIN Koerper. Den frueheren Versatz (versatz_y) gibt es nicht mehr, seit die Kette aufgerichtet eingebaut wird.", "_hinweis_ansicht": "KF_2D ist ein eigener Hilfsblock KF2D_<n> (Draufsicht zum Anschliessen von Schienen), kein Teil des Foerderers. Er wird auf die projizierte Laenge skaliert und beim ERSTEN Einfuegen versatz_y mm (Y) gegen den Hauptblock versetzt; danach liegt er, wo der Benutzer ihn hinlegt.",
"ansicht_2d": { "block": "KF_2D" }, "ansicht_2d": { "block": "KF_2D", "versatz_y": -1000 },
"_hinweis_antriebsart": "Merkmal 357 ist beim Kettenfoerderer FEST: die Liste hat genau EINEN Eintrag, der im Dialog als Dropdown erscheint und zwingend gewaehlt ist. Weitere Antriebsarten (z.B. 0.55 kW) waeren einfach eine weitere Zeile.", "_hinweis_antriebsart": "Merkmal 357 ist beim Kettenfoerderer FEST: die Liste hat genau EINEN Eintrag, der im Dialog als Dropdown erscheint und zwingend gewaehlt ist. Weitere Antriebsarten (z.B. 0.55 kW) waeren einfach eine weitere Zeile.",
"antriebsart": [ "antriebsart": [
+4 -4
View File
@@ -1300,11 +1300,11 @@
"kf-prompt-messpunkt-2": "\nZweiten Messpunkt waehlen (Hoehenbezug oben): ", "kf-prompt-messpunkt-2": "\nZweiten Messpunkt waehlen (Hoehenbezug oben): ",
"kf-messung-ergebnis": "\n>>> Gemessen: Hoehendifferenz dZ = %1 mm (zur Kontrolle dY = %2 mm).", "kf-messung-ergebnis": "\n>>> Gemessen: Hoehendifferenz dZ = %1 mm (zur Kontrolle dY = %2 mm).",
"kf-konsole-hoehe-hinweis": "\n(0 eingeben, um die Hoehe aus zwei Punkten zu messen)", "kf-konsole-hoehe-hinweis": "\n(0 eingeben, um die Hoehe aus zwei Punkten zu messen)",
"kf-2d-gebaut": "\n>>> Draufsicht %1 eingefuegt: Schraeglaenge %2 mm, Neigung %3 Grad.", "kf-2d-gebaut": "\n>>> Hilfsblock %1 (Draufsicht) eingefuegt: KF waagerechte Laenge %2 mm.",
"kf-2d-laenge-null": "\nDraufsicht uebersprungen: die Kette hat keine messbare Grundrisslaenge.", "kf-bemassung-fehlt": "\nHinweis: Das Hoehenmass konnte nicht gezeichnet werden - der Foerderer wurde trotzdem gebaut.",
"cmd-kf2d-hilfsblock": "\nHilfsblock (Draufsicht): kein eigener Dialog - Doppelklick auf den Hauptblock KF_<n> erzeugt ihn neu.",
"kf-2d-ks-fehlt": "\nDraufsicht uebersprungen: %1 hat kein messbares KS_EIN/KS_AUS.", "kf-2d-ks-fehlt": "\nDraufsicht uebersprungen: %1 hat kein messbares KS_EIN/KS_AUS.",
"kf-prompt-startpunkt": "\nEinfuegepunkt waehlen (KS_EIN der Draufsicht; die Seitenansicht entsteht darueber): ", "kf-prompt-startpunkt": "\nEinfuegepunkt waehlen (KS_EIN der Umlenkstation): ",
"kf-prompt-drehung": "\nDrehwinkel der Kette: ",
"kf-abgebrochen": "\nAbgebrochen.", "kf-abgebrochen": "\nAbgebrochen.",
"kf-fertig": "\n>>> %1 erstellt: Einbauhoehe %2 mm, Zwischenstueck %3 mm.", "kf-fertig": "\n>>> %1 erstellt: Einbauhoehe %2 mm, Zwischenstueck %3 mm.",
"kf-konsole-variante-header": "\n\nSchraegfoerderer Stahl Typ waehlen:", "kf-konsole-variante-header": "\n\nSchraegfoerderer Stahl Typ waehlen:",
+4 -4
View File
@@ -1300,11 +1300,11 @@
"kf-prompt-messpunkt-2": "\nSelect second measuring point (upper reference): ", "kf-prompt-messpunkt-2": "\nSelect second measuring point (upper reference): ",
"kf-messung-ergebnis": "\n>>> Measured: height difference dZ = %1 mm (for reference dY = %2 mm).", "kf-messung-ergebnis": "\n>>> Measured: height difference dZ = %1 mm (for reference dY = %2 mm).",
"kf-konsole-hoehe-hinweis": "\n(enter 0 to measure the height from two points)", "kf-konsole-hoehe-hinweis": "\n(enter 0 to measure the height from two points)",
"kf-2d-gebaut": "\n>>> Plan view %1 inserted: slope length %2 mm, inclination %3 deg.", "kf-2d-gebaut": "\n>>> Helper block %1 (plan view) inserted: KF horizontal length %2 mm.",
"kf-2d-laenge-null": "\nPlan view skipped: the chain has no measurable plan length.", "kf-bemassung-fehlt": "\nNote: the height dimension could not be drawn - the conveyor was built anyway.",
"cmd-kf2d-hilfsblock": "\nHelper block (plan view): no dialog of its own - double-click the main block KF_<n> to regenerate it.",
"kf-2d-ks-fehlt": "\nPlan view skipped: %1 has no measurable KS_EIN/KS_AUS.", "kf-2d-ks-fehlt": "\nPlan view skipped: %1 has no measurable KS_EIN/KS_AUS.",
"kf-prompt-startpunkt": "\nSelect insertion point (KS_EIN of the plan view; the side view is built above it): ", "kf-prompt-startpunkt": "\nSelect insertion point (KS_EIN of the return station): ",
"kf-prompt-drehung": "\nRotation angle of the chain: ",
"kf-abgebrochen": "\nCancelled.", "kf-abgebrochen": "\nCancelled.",
"kf-fertig": "\n>>> %1 created: installation height %2 mm, intermediate section %3 mm.", "kf-fertig": "\n>>> %1 created: installation height %2 mm, intermediate section %3 mm.",
"kf-konsole-variante-header": "\n\nSelect inclined steel conveyor type:", "kf-konsole-variante-header": "\n\nSelect inclined steel conveyor type:",
+12 -4
View File
@@ -313,8 +313,8 @@ def kettenfoerderer_signature(block):
Merkmale wuerden schon hier dieselbe Gruppe ergeben. Sonst wuerde dort Merkmale wuerden schon hier dieselbe Gruppe ergeben. Sonst wuerde dort
"anzahl" addiert, waehrend 353 unveraendert stehen bliebe. "anzahl" addiert, waehrend 353 unveraendert stehen bliebe.
Die Laenge des Zwischenstuecks (L_KF_mm) ist eine FOLGE der Einbauhoehe und Die waagerechte Laenge (L_KF_mm) ist eine FOLGE der Einbauhoehe (und des
steht darum nicht eigens im Schluessel. Winkels) und steht darum nicht eigens im Schluessel.
""" """
attribs = block.get("attribs", {}) attribs = block.get("attribs", {})
return ( return (
@@ -702,7 +702,11 @@ def process_blocks(blocks, anzahl_weichen_ils=0):
# 359/360/391) gingen dabei verloren. Anders als das Geruest werden # 359/360/391) gingen dabei verloren. Anders als das Geruest werden
# BAUGLEICHE Foerderer zu einer Zeile zusammengefasst, weil Merkmal # BAUGLEICHE Foerderer zu einer Zeile zusammengefasst, weil Merkmal
# 353 genau diese Stueckzahl verlangt. # 353 genau diese Stueckzahl verlangt.
if matches_any(bname, BLOCKPATTERNS.get("pattern_kettenfoerderer", [])): # Nur echte Foerderer "KF_<n>": das Muster KF_* erfasst sonst auch
# lose Bausteine (KF_UM_26, KF_2D). Der Hilfsblock KF2D_<n> passt nicht
# aufs Muster und wird nie exportiert.
if (matches_any(bname, BLOCKPATTERNS.get("pattern_kettenfoerderer", []))
and re.fullmatch(r"KF_\d+", bname, re.IGNORECASE)):
sig = kettenfoerderer_signature(block) sig = kettenfoerderer_signature(block)
if sig not in kettenfoerderer_groups: if sig not in kettenfoerderer_groups:
kettenfoerderer_groups[sig] = {"block": block, "ids": [], "anzahl": 0} kettenfoerderer_groups[sig] = {"block": block, "ids": [], "anzahl": 0}
@@ -996,7 +1000,11 @@ def process_blocks(blocks, anzahl_weichen_ils=0):
"bezeichnung": attribs.get("Bezeichnung", ""), "bezeichnung": attribs.get("Bezeichnung", ""),
"dispgruppe": 20, "dispgruppe": 20,
"anzahl": gruppe["anzahl"], "anzahl": gruppe["anzahl"],
"laenge_mm": attribs.get("L_KF_mm", ""), # Bewusst LEER: Sivas berechnet ZL, EL und die Kettenlaenge selbst, aus
# dem Kettenfoerderer wird nur die Hoehe (360) uebernommen. L_KF_mm
# (waagerechte Laenge des Foerderers) steht als Attribut am Block,
# geht aber nicht in die Sivas-Zeile.
"laenge_mm": "",
"ids": gruppe["ids"], "ids": gruppe["ids"],
"details": build_kettenfoerderer_details(block, gruppe["anzahl"]), "details": build_kettenfoerderer_details(block, gruppe["anzahl"]),
}) })
+65 -60
View File
@@ -2892,66 +2892,71 @@
(tu-eq "kf-frei/Start-mitten" 5 (tu-eq "kf-frei/Start-mitten" 5
(kf-freie-nummer 3 '(lambda (n) (member n '(3 4))))) (kf-freie-nummer 3 '(lambda (n) (member n '(3 4)))))
;; --- kf-drehung-gesamt: Drehwinkel fuer KF_EDIT --- ;; --- kf-label-text: Beschriftung von Haupt- UND Hilfsblock ---
;; Regression: der Drehwinkel wird beim Bau in die Geometrie eingerechnet, ;; Eine Zeile wie bei VF_/GF_: Nummer, Winkel mit Gradzeichen, Hoehe,
;; die Blockreferenz selbst hat IMMER Drehung 0 (ssg-block-wrap-welt). ;; projizierte Laenge (ganze mm)
;; KF_EDIT las nur Gruppencode 50 und baute eine mit 90 Grad gebaute (tu-eq "kf-label/normal"
;; Kette ungedreht neu. Der gebaute Winkel steht jetzt als XDATA. (strcat "KF_1 26" (chr 176) " H=1500mm L_horizontal=4951mm")
(tu-eqf "kf-drehung/nur-xdata" 90.0 (kf-drehung-gesamt 90.0 0.0)) (kf-label-text 1 "26" 1500.0 4951.4))
;; Referenz nachtraeglich von Hand um 90 Grad gedreht (Gruppencode 50 in ;; rundet kaufmaennisch auf ganze mm, nimmt auch Ganzzahlen
;; Bogenmass) -> beides addiert sich (tu-eq "kf-label/rundet-auf"
(tu-eqf "kf-drehung/xdata-plus-referenz" 180.0 (strcat "KF_12 30" (chr 176) " H=2000mm L_horizontal=3001mm")
(kf-drehung-gesamt 90.0 (/ pi 2.0))) (kf-label-text 12 "30" 2000 3000.5))
;; Altbestand ohne XDATA: nur die Referenzdrehung (bisheriges Verhalten)
(tu-eqf "kf-drehung/ohne-xdata" 45.0 (kf-drehung-gesamt nil (/ pi 4.0)))
;; nichts bekannt -> 0, kein Absturz und kein nil
(tu-eqf "kf-drehung/nichts" 0.0 (kf-drehung-gesamt nil nil))
(tu-true "kf-drehung/ist-zahl" (numberp (kf-drehung-gesamt nil nil)))
;; Summe ueber 180 Grad wird auf -180..180 gefaltet (270 = -90)
(tu-eqf "kf-drehung/normalisiert" -90.0
(kf-drehung-gesamt 180.0 (/ pi 2.0)))
;; ganze Zahl aus der XDATA (nicht real) darf nicht abstuerzen
(tu-eqf "kf-drehung/ganzzahl" 30.0 (kf-drehung-gesamt 30 0.0))
;; --- kf-neigung-aus-punkten: Kern der 3D-Aufrichtung --- ;; --- kf-winkel-text: Neigung als nackte Ganzzahl (Attribut WINKEL) ---
;; Liefert (Schraeglaenge Neigungswinkel) aus Ketten-Start und -Ende. (tu-eq "kf-winkel-text/real" "26" (kf-winkel-text '(("winkel" . 26.0))))
;; Die Kette wird AUFGERICHTET eingebaut, die Hoehe laeuft also in Z. (tu-eq "kf-winkel-text/string" "30" (kf-winkel-text '(("winkel" . "30"))))
;; 3-4-5-Dreieck: 3000 waagerecht, 4000 hoch -> 5000 schraeg (tu-eq "kf-winkel-text/fehlt" "0" (kf-winkel-text '(("name" . "x"))))
(tu-eqf "kf-neigung/3-4-5-laenge" 5000.0
(car (kf-neigung-aus-punkten '(0.0 0.0 0.0) '(3000.0 0.0 4000.0) 0.0)))
;; 45 Grad: gleiche Betraege waagerecht und hoch
(tu-eqf "kf-neigung/45-grad" 45.0
(cadr (kf-neigung-aus-punkten '(0.0 0.0 0.0) '(1000.0 0.0 1000.0) 0.0)))
;; waagerecht -> Winkel 0, Laenge = Horizontalabstand
(tu-eqf "kf-neigung/waagerecht" '(2000.0 0.0)
(kf-neigung-aus-punkten '(0.0 0.0 0.0) '(2000.0 0.0 0.0) 0.0))
;; Der Horizontalanteil wird auf die KETTENRICHTUNG projiziert, nicht
;; auf die Welt-X-Achse: bei 90 Grad Basisdrehung laeuft die Kette in Y.
;; Ohne Projektion kaeme hier 0 heraus und der Winkel waere 90 statt 45.
(tu-eqf "kf-neigung/gedreht-90" '(1414.213562 45.0)
(kf-neigung-aus-punkten '(0.0 0.0 0.0) '(0.0 1000.0 1000.0) 90.0))
;; fallende Kette -> negativer Winkel
(tu-eqf "kf-neigung/fallend" -45.0
(cadr (kf-neigung-aus-punkten '(0.0 0.0 1000.0) '(1000.0 0.0 0.0) 0.0)))
;; Start = Ende -> nil statt Division durch 0
(tu-nil "kf-neigung/nulllaenge"
(kf-neigung-aus-punkten '(5.0 5.0 5.0) '(5.0 5.0 5.0) 0.0))
;; --- kf-matrix-aufrecht: Y_lokal wird zu Z_welt --- ;; --- kf-versatzpunkt: Hilfsblock beim ersten Einfuegen unter dem Hauptblock ---
;; Das ist die Kernaussage der Aufrichtung. Geprueft wird sie an den (tu-eqf "kf-versatzpunkt/minus-1000" '(100.0 -980.0 5.0)
;; Bildern der Einheitsvektoren, nicht an den Matrixeintraegen - so (kf-versatzpunkt '(100.0 20.0 5.0) -1000))
;; bleibt der Test lesbar und unabhaengig von der Schreibweise. ;; 2D-Punkt ohne Z -> Z = 0, kein Absturz
(tu-eqf "kf-matrix/Y-lokal-wird-Z-welt" '(0.0 0.0 1.0) (tu-eqf "kf-versatzpunkt/ohne-z" '(0.0 -1000.0 0.0)
(mat3-mul-vec3 (kf-matrix-aufrecht 0.0 0.0) '(0.0 1.0 0.0))) (kf-versatzpunkt '(0.0 0.0) -1000.0))
;; Die Fahrtrichtung (X) bleibt bei Basisdrehung 0 die Welt-X-Achse
(tu-eqf "kf-matrix/X-bleibt-X" '(1.0 0.0 0.0) ;; --- kf-hilfsblock-versatz: Wert steht in der JSON, Vorgabe -1000 ---
(mat3-mul-vec3 (kf-matrix-aufrecht 0.0 0.0) '(1.0 0.0 0.0))) (tu-eqf "kf-versatz/aus-daten" -500.0
;; Basisdrehung 90 Grad dreht die Fahrtrichtung in die Welt-Y-Achse, (kf-hilfsblock-versatz '(("ansicht_2d" ("block" . "KF_2D") ("versatz_y" . -500)))))
;; die Hoehe bleibt dabei in Z (tu-eqf "kf-versatz/ohne-feld" -1000.0
(tu-eqf "kf-matrix/basis-90-dreht-X-nach-Y" '(0.0 1.0 0.0) (kf-hilfsblock-versatz '(("ansicht_2d" ("block" . "KF_2D")))))
(mat3-mul-vec3 (kf-matrix-aufrecht 90.0 0.0) '(1.0 0.0 0.0))) (tu-eqf "kf-versatz/ohne-ansicht" -1000.0
(tu-eqf "kf-matrix/basis-90-haelt-Z" '(0.0 0.0 1.0) (kf-hilfsblock-versatz '(("id" . "x"))))
(mat3-mul-vec3 (kf-matrix-aufrecht 90.0 0.0) '(0.0 1.0 0.0))) ;; Zahl, nicht T (and/or-Typfalle)
(tu-true "kf-versatz/ist-zahl"
(numberp (kf-hilfsblock-versatz '(("id" . "x")))))
;; --- kf-key-aus-xdata: Schluessel Haupt- <-> Hilfsblock ---
(tu-eq "kf-key/aus-xdata" "20261030120000"
(kf-key-aus-xdata
'((-3 ("SSG_KF_EDIT" (1000 . "kf-edit") (1000 . "20261030120000"))))))
;; Altbestand: nur der Marker, kein Schluessel -> nil (-> neuer Schluessel)
(tu-nil "kf-key/nur-marker"
(kf-key-aus-xdata '((-3 ("SSG_KF_EDIT" (1000 . "kf-edit"))))))
(tu-nil "kf-key/keine-xdata" (kf-key-aus-xdata '((0 . "INSERT"))))
(tu-nil "kf-key/nil" (kf-key-aus-xdata nil))
;; --- kf-waagerecht-laenge: Wert des Attributs L_KF_mm ---
;; Waagerechte Laenge des GANZEN Foerderers (der Draufsicht KF_2D), also
;; ohne die Steigung - nicht die Laenge des schraegen Mittelstuecks.
;; 3-4-5: 3000 waagerecht, 4000 hoch -> waagerecht bleibt 3000 (nicht 5000)
(tu-eqf "kf-waagerecht/ohne-steigung" 3000.0
(kf-waagerecht-laenge '(0.0 0.0 0.0) '(3000.0 0.0 4000.0) 0.0))
;; nur Hoehe, keine waagerechte Strecke -> 0
(tu-eqf "kf-waagerecht/nur-hoehe" 0.0
(kf-waagerecht-laenge '(0.0 0.0 0.0) '(0.0 0.0 1500.0) 0.0))
;; auf die KETTENRICHTUNG projiziert: bei 90 Grad Basisdrehung laeuft die
;; Kette in Y, die Welt-X-Differenz waere 0
(tu-eqf "kf-waagerecht/gedreht-90" 1000.0
(kf-waagerecht-laenge '(0.0 0.0 0.0) '(0.0 1000.0 1000.0) 90.0))
(tu-eqf "kf-waagerecht/gedreht-45" 1000.0
(kf-waagerecht-laenge '(0.0 0.0 0.0) '(707.10678 707.10678 500.0) 45.0))
;; fallende Kette / Ende "hinter" dem Start: Betrag, nie negativ
(tu-eqf "kf-waagerecht/immer-positiv" 2000.0
(kf-waagerecht-laenge '(2000.0 0.0 0.0) '(0.0 0.0 800.0) 0.0))
;; muss eine Zahl sein (Typfalle: nie T/nil)
(tu-true "kf-waagerecht/ist-zahl"
(numberp (kf-waagerecht-laenge '(0.0 0.0 0.0) '(10.0 0.0 0.0) 0.0)))
;; --- Standard-Variante: steht in den DATEN, nicht im Code --- ;; --- Standard-Variante: steht in den DATEN, nicht im Code ---
(tu-true "kf-variante-standard-p/markiert" (tu-true "kf-variante-standard-p/markiert"
@@ -2970,8 +2975,8 @@
(kf-standard-index '((("winkel" . 26)) (("winkel" . 30))))) (kf-standard-index '((("winkel" . 26)) (("winkel" . 30)))))
;; --- kf-punkt-differenzen: zweite Hoehen-Eingabeart (2 Punkte) --- ;; --- kf-punkt-differenzen: zweite Hoehen-Eingabeart (2 Punkte) ---
;; Gemessen wird die Differenz in Z - die Baugruppe steht aufgerichtet im ;; Gemessen wird die Differenz in Z (Hoehe der gepickten Punkte).
;; Modell. Zurueckgegeben wird (dz dy): die HOEHE zuerst, dY nur zur ;; Zurueckgegeben wird (dz dy): die HOEHE zuerst, dY nur zur
;; Kontrolle (wer in einer Draufsicht pickt, sieht dz = 0). ;; Kontrolle (wer in einer Draufsicht pickt, sieht dz = 0).
(tu-eqf "kf-punkt-diff/dz" '(1500.0 0.0) (tu-eqf "kf-punkt-diff/dz" '(1500.0 0.0)
(kf-punkt-differenzen '(0.0 0.0 0.0) '(2000.0 0.0 1500.0))) (kf-punkt-differenzen '(0.0 0.0 0.0) '(2000.0 0.0 1500.0)))