erste allgemeine Fassung einer Kreiselroutine für horizontale und vertikale Kreisel. Allgemeine Deklaration aller Definitionen am Anfang des Blocks

This commit is contained in:
2026-05-15 15:07:27 +02:00
parent aa387dbcdd
commit d8283437e8
+284 -230
View File
@@ -1,6 +1,7 @@
;; ModulInsert.lsp
;; Kreisel Modul-Einfügesystem + Smart Connect
;; Version: 4.1 (mit DXFM_BLOCKS Unterstützung)
;; KreiselInsert.lsp
;; Kreisel Modul-Einfuegesystem mit Compound-Block
;; Version: 5.0 (Compound Block + 2-Linien-Connect)
;; Setzt ssg_core.lsp voraus.
;; ============================================
;; ============================================================
@@ -11,298 +12,351 @@
(if (or (null block-pfad) (= block-pfad ""))
(progn
(setq block-pfad "C:/Users/y.wang/Documents/dxfmakros/Blocks/") ;; Fallback oder manuell
(setq block-pfad "C:/Users/y.wang/Documents/dxfmakros/Blocks/")
(alert (strcat "Umgebungsvariable DXFM_BLOCKS nicht gefunden.\nNutze Standardpfad: " block-pfad))
)
(setq block-pfad (strcat (vl-string-right-trim "/" (vl-string-translate "\\" "/" block-pfad)) "/"))
)
(setq *block-path* block-pfad)
(princ (strcat "\nBlock-Pfad aktiv: " block-pfad))
(princ (strcat "\nBlock-Pfad aktiv: " block-pfad))
;; Standardwerte initialisieren
(if (null #Kreisel_Abstand) (setq #Kreisel_Abstand 2300.0))
;; Kreisel-Geometrie-Konstanten
(setq *kreisel-durchmesser* 800.0) ;; Kreisdurchmesser AN8/SP8
(setq *kreisel-pin-abstand* 100.0) ;; Einrueckung PIN-Linie vom Kreisrand
(setq *kreisel-default-laenge* 2300.0) ;; Standard-Tangentenlaenge
;; Standardwerte
(if (null #Kreisel_Typ) (setq #Kreisel_Typ "PIN"))
;; ============================================================
;; TEIL 2: HILFSFUNKTIONEN
;; ============================================================
;; ============================================
;; Haupt-Einfügebefehl (Position manuell angeben)
;; ============================================
(defun c:KreiselInsert ( / pt x y abstand typ abstandStr typNum)
(ssg-start "Kreisel Modul einfuegen" '(("OSMODE") ("CECOLOR")))
(setvar "OSMODE" 0)
(princ "Basispunkt = linke Kreistangente (links Mitte)\n")
;; 1. Einfügepunkt abfragen
(setq pt (getpoint "\nBasispunkt (linke Kreistangente): "))
(if (null pt) (setq pt '(0 0 0)))
(setq x (car pt) y (cadr pt))
;; 2. Abstand abfragen
(princ (strcat "\nAbstand <" (rtos #Kreisel_Abstand 2 0) ">: "))
(setq abstandStr (getstring ""))
(if (= abstandStr "")
(setq abstand #Kreisel_Abstand)
(setq abstand (atof abstandStr))
)
(setq #Kreisel_Abstand abstand)
;; 3. Typ abfragen
;; PIN-Typ abfragen. Rueckgabe: "PIN" oder "OhnePIN"
(defun kreisel-ask-typ ( / typNum typ)
(princ "\n[1] Kreisel mit PIN")
(princ "\n[2] Kreisel ohne PIN")
(princ (strcat "\nBitte wählen <" (if (= #Kreisel_Typ "PIN") "1" "2") ">: "))
(princ (strcat "\nBitte waehlen <" (if (= #Kreisel_Typ "PIN") "1" "2") ">: "))
(setq typNum (getstring ""))
(cond
((= typNum "2") (setq typ "OhnePIN"))
(t (setq typ "PIN"))
)
(setq #Kreisel_Typ typ)
(princ (strcat "\n→ Modus: " typ))
;; Modul zeichnen
(draw-module x y abstand typ)
(princ "\n✅ Kreisel Modul erfolgreich eingefügt")
(ssg-end)
typ
)
;; Punkt auf Gerade projizieren (Fusspunkt der Senkrechten)
;; pt = beliebiger Punkt; lstart/lend = Geradenendpunkte (jeweils 2D)
;; Rueckgabe: 2D-Punkt auf der Geraden
(defun kreisel-project-point (pt lstart lend / dx dy tval)
(setq dx (- (car lend) (car lstart))
dy (- (cadr lend) (cadr lstart)))
(setq tval (/ (+ (* (- (car pt) (car lstart)) dx)
(* (- (cadr pt) (cadr lstart)) dy))
(+ (* dx dx) (* dy dy))))
(list (+ (car lstart) (* tval dx))
(+ (cadr lstart) (* tval dy)))
)
;; Linien-Endpunkte aus LINE-Entity lesen
;; Rueckgabe: ((sx sy) (ex ey))
(defun kreisel-get-line-pts (ent / ed p10 p11)
(setq ed (entget ent))
(setq p10 (cdr (assoc 10 ed))
p11 (cdr (assoc 11 ed)))
(list (list (car p10) (cadr p10))
(list (car p11) (cadr p11)))
)
;; Pruefen ob zwei Richtungsvektoren parallel sind
;; Normiertes Kreuzprodukt < Toleranz
(defun kreisel-parallel-p (d1 d2 / cross len1 len2)
(setq cross (abs (- (* (car d1) (cadr d2)) (* (cadr d1) (car d2))))
len1 (sqrt (+ (* (car d1) (car d1)) (* (cadr d1) (cadr d1))))
len2 (sqrt (+ (* (car d2) (car d2)) (* (cadr d2) (cadr d2)))))
(< (/ cross (* len1 len2)) 0.01)
)
;; ============================================
;; Smart-Connect-Einfügebefehl
;; ============================================
(defun c:KreiselConnect ( / existingObj pickPoint connectionType newX newY abstand typ abstandStr typNum newBasePoint)
;; ============================================================
;; TEIL 3: COMPOUND BLOCK ERZEUGEN UND EINFUEGEN
;; ============================================================
(ssg-start "Kreisel Smart Connect" '(("OSMODE") ("CECOLOR")))
(setvar "OSMODE" 0)
;; 1. Bestehendes Modul auswählen
(setq existingObj (car (entsel "\nBestehendes Modul wählen: ")))
(if (null existingObj) (exit))
;; 2. Verbindungspunkt abfragen (Benutzer-Klickposition)
(setq pickPoint (getpoint "\nVerbindungspunkt wählen (auf Tangente klicken): "))
(if (null pickPoint) (exit))
;; 3. Verbindungspunkt-Typ erkennen
(setq connectionType (identify-connection-point existingObj pickPoint))
(princ (strcat "\n→ Verbindungspunkt: " connectionType))
;; 4. Parameter des neuen Moduls abfragen
(princ (strcat "\nAbstand <" (rtos #Kreisel_Abstand 2 0) ">: "))
(setq abstandStr (getstring ""))
(if (= abstandStr "")
(setq abstand #Kreisel_Abstand)
(setq abstand (atof abstandStr))
)
(princ "\n[1] Kreisel mit PIN")
(princ "\n[2] Kreisel ohne PIN")
(princ (strcat "\nBitte wählen <" (if (= #Kreisel_Typ "PIN") "1" "2") ">: "))
(setq typNum (getstring ""))
(cond
((= typNum "2") (setq typ "OhnePIN"))
(t (setq typ "PIN"))
)
;; 5. Basispunkt des neuen Moduls anhand der Verbindungsregeln berechnen
(setq newBasePoint (calculate-new-basepoint existingObj pickPoint connectionType abstand))
(if newBasePoint
(progn
(princ (strcat "\n→ Neue Basis: (" (rtos (car newBasePoint) 2 0) "," (rtos (cadr newBasePoint) 2 0) ")"))
(draw-module (car newBasePoint) (cadr newBasePoint) abstand typ)
(princ "\n✅ Smart Connect erfolgreich!")
)
(princ "\n❌ Verbindung nicht möglich!")
)
(ssg-end)
)
;; Zeichnet Kreisel-Geometrie bei (0,0), erzeugt Block, fuegt ihn ein.
;;
;; basePoint = Einfuegepunkt (2D-Liste), AN-Seite
;; abstand = Tangentenlaenge zwischen Kreismitten
;; typ = "PIN" oder "OhnePIN"
;; rotation = Einfuegewinkel in Grad (0=rechts, 90=oben, 180=links, 270=unten)
;;
;; Blockgeometrie (bei Rotation 0, horizontal):
;; Basispunkt (0,0) = linke Kreistangente (AN-Seite)
;; AN8 Zentrum bei (radius, 0)
;; SP8 Zentrum bei (radius+abstand, 0)
;; Gesamtbreite = durchmesser + abstand
;;
;; Rueckgabe: Entity-Name des eingefuegten Blocks
(defun draw-module (basePoint abstand typ rotation / lastEnt ss e bname
radius pin-y)
;; ============================================
;; Verbindungspunkt-Typ erkennen
;; ============================================
(defun identify-connection-point (obj pickPoint / x y abstand insertPoint pickX pickY tolerance type)
;; Basispunkt des Moduls ermitteln (aus Einfügepunkt berechnen)
(setq insertPoint (cdr (assoc 10 (entget obj))))
(setq x (car insertPoint) y (cadr insertPoint))
;; Abstand ermitteln (sollte aus Modulattributen gelesen werden, vorerst globale Variable)
(setq abstand #Kreisel_Abstand)
(setq pickX (car pickPoint) pickY (cadr pickPoint))
(setq tolerance 50.0) ;; Toleranz 50mm
;; Verbindungspunkte pruefen
(cond
;; T_O (Mittelpunkt obere Tangente)
((and (<= (abs (- pickX (+ x 400.0 (/ abstand 2.0)))) tolerance)
(<= (abs (- pickY (+ y 400.0))) tolerance))
(setq type "T_O"))
;; Abgeleitete Masse
(setq radius (/ *kreisel-durchmesser* 2.0))
(setq pin-y (- radius *kreisel-pin-abstand*))
;; T_U (Mittelpunkt untere Tangente)
((and (<= (abs (- pickX (+ x 400.0 (/ abstand 2.0)))) tolerance)
(<= (abs (- pickY (- y 400.0))) tolerance))
(setq type "T_U"))
;; Letzte Entity vor dem Zeichnen merken
(setq lastEnt (entlast))
;; M_O (Linker Kreis, oberer Rand)
((and (<= (abs (- pickX (+ x 400.0))) tolerance)
(<= (abs (- pickY (+ y 400.0))) tolerance))
(setq type "M_O"))
;; --- Geometrie bei Ursprung (0,0) zeichnen ---
;; M_U (Linker Kreis, unterer Rand)
((and (<= (abs (- pickX (+ x 400.0))) tolerance)
(<= (abs (- pickY (- y 400.0))) tolerance))
(setq type "M_U"))
;; AN8 Kreis (Antriebsstation) bei (radius, 0)
(command "_.INSERT" (strcat block-pfad "AN8.dwg") (list radius 0.0) 1 1 0)
;; M_L (Linker Kreis, linker Rand)
((and (<= (abs (- pickX x)) tolerance)
(<= (abs (- pickY y)) tolerance))
(setq type "M_L"))
;; SP8 Kreis (Spannstation) bei (radius+abstand, 0)
(command "_.INSERT" (strcat block-pfad "SP8.dwg") (list (+ radius abstand) 0.0) 1 1 0)
;; S_O (Rechter Kreis, oberer Rand)
((and (<= (abs (- pickX (+ x 400.0 abstand))) tolerance)
(<= (abs (- pickY (+ y 400.0))) tolerance))
(setq type "S_O"))
;; S_U (Rechter Kreis, unterer Rand)
((and (<= (abs (- pickX (+ x 400.0 abstand))) tolerance)
(<= (abs (- pickY (- y 400.0))) tolerance))
(setq type "S_U"))
;; S_R (Rechter Kreis, rechter Rand)
((and (<= (abs (- pickX (+ x 800.0 abstand))) tolerance)
(<= (abs (- pickY y)) tolerance))
(setq type "S_R"))
(t (setq type "UNKNOWN"))
)
type
)
;; ============================================
;; Basispunkt des neuen Moduls berechnen
;; ============================================
(defun calculate-new-basepoint (obj pickPoint connectionType abstand / x y newX newY insertPoint)
(setq insertPoint (cdr (assoc 10 (entget obj))))
(setq x (car insertPoint) y (cadr insertPoint))
(cond
;; T_O / T_U / M_O / S_O / M_U / S_U → Verbindung nach oben oder unten, neues Modul mit S_R
((member connectionType '("T_O" "T_U" "M_O" "S_O" "M_U" "S_U"))
(princ "\n→ Richtung: nach oben/unten")
;; Bestimmen ob nach oben oder unten
(if (> (cadr pickPoint) y)
(setq newX x newY (+ y 800.0 abstand)) ;; nach oben
(setq newX x newY (- y 800.0 abstand)) ;; nach unten
)
)
;; M_L → Verbindung nach links, neues Modul mit S_R
((= connectionType "M_L")
(princ "\n→ Richtung: nach links")
(setq newX (- x 800.0 abstand) newY y)
)
;; S_R → Verbindung nach rechts, neues Modul mit M_L
((= connectionType "S_R")
(princ "\n→ Richtung: nach rechts")
(setq newX (+ x 800.0 abstand) newY y)
)
(t (setq newX nil newY nil))
)
(if (and newX newY) (list newX newY) nil)
)
;; ============================================
;; Komplettes Modul zeichnen
;; ============================================
(defun draw-module (x y abstand typ)
;; Linken Kreisblock einfügen
(command "_.INSERT" (strcat block-pfad "AN8.dwg") (list (+ x 400.0) y) 1 1 0)
;; Rechten Kreisblock einfügen
(command "_.INSERT" (strcat block-pfad "SP8.dwg") (list (+ x 400.0 abstand) y) 1 1 0)
;; Tangenten zeichnen
;; Tangenten auf Layer S_LP
(ssg-make-layer "S_LP" "7" T)
(if (= typ "PIN")
(setvar "CECOLOR" "5")
(setvar "CECOLOR" "1")
)
;; Obere Tangente
(command "_.LINE"
(list (+ x 400.0) (+ y 400.0))
(list (+ x 400.0 abstand) (+ y 400.0))
"")
(command "_.LINE" (list radius radius) (list (+ radius abstand) radius) "")
;; Untere Tangente
(command "_.LINE"
(list (+ x 400.0) (- y 400.0))
(list (+ x 400.0 abstand) (- y 400.0))
"")
(command "_.LINE" (list radius (- radius)) (list (+ radius abstand) (- radius)) "")
;; PIN-Linien zeichnen
;; PIN-Linien
(if (= typ "PIN")
(progn
(ssg-make-layer "pinbereich" "3" T)
(command "_LAYER" "_LT" "2punkt" "pinbereich" "")
(setvar "CECOLOR" "3")
;; Obere PIN-Linie
(command "_.LINE"
(list (+ x 800.0) (+ y 300.0))
(list (+ x abstand) (+ y 300.0))
"")
(command "_.LINE" (list *kreisel-durchmesser* pin-y) (list (float abstand) pin-y) "")
;; Untere PIN-Linie
(command "_.LINE"
(list (+ x 800.0) (- y 300.0))
(list (+ x abstand) (- y 300.0))
"")
(command "_.LINE" (list *kreisel-durchmesser* (- pin-y)) (list (float abstand) (- pin-y)) "")
)
)
;; --- Neue Entities einsammeln ---
(setq ss (ssadd))
(setq e (entnext lastEnt))
(while e
(ssadd e ss)
(setq e (entnext e))
)
;; --- Block erzeugen (Entities werden aus Zeichnung entfernt) ---
(setq bname (strcat "KR_" (ssg-make-blockname
(list (car basePoint) (cadr basePoint) 0.0))))
(command "_.-BLOCK" bname (list 0.0 0.0 0.0) ss "")
;; --- Block am Zielpunkt mit Rotation einfuegen ---
(command "_.INSERT" bname basePoint 1 1 rotation)
(entlast)
)
;; ============================================
;; Hilfsbefehle
;; ============================================
;; ============================================================
;; TEIL 4: BEFEHLE
;; ============================================================
(defun c:KreiselQuick ( / pt)
(ssg-start "Kreisel Schnell Einfuegen" '(("OSMODE") ("CECOLOR")))
;; --------------------------------------------
;; KreiselInsert: Manuell Position + Parameter
;; --------------------------------------------
(defun c:KreiselInsert ( / pt abstand typ rotation rotStr)
(ssg-start "Kreisel Modul einfuegen" '(("OSMODE") ("CECOLOR")))
(setvar "OSMODE" 0)
(setq pt (getpoint "\nBasispunkt (linke Kreistangente): "))
(if pt
(draw-module (car pt) (cadr pt) #Kreisel_Abstand #Kreisel_Typ)
;; 1. Einfuegepunkt
(setq pt (getpoint "\nBasispunkt (AN-Seite): "))
(if (null pt) (exit))
;; 2. Abstand (zeigen oder tippen)
(initget 6)
(setq abstand (getdist pt (strcat "\nAbstand (Tangentenlaenge) zeigen oder eingeben <"
(rtos *kreisel-default-laenge* 2 0) ">: ")))
(if (null abstand) (setq abstand *kreisel-default-laenge*))
;; 3. Rotation
(setq rotStr (getstring "\nRotation in Grad <0>: "))
(if (= rotStr "")
(setq rotation 0.0)
(setq rotation (atof rotStr))
)
(princ "\n✅ Schnell Einfügen fertig")
;; 4. Typ
(setq typ (kreisel-ask-typ))
(princ (strcat "\n-> Abstand: " (rtos abstand 2 0)
" Rotation: " (rtos rotation 2 1)
" Typ: " typ))
;; 5. Modul einfuegen
(draw-module (list (car pt) (cadr pt)) abstand typ rotation)
(princ "\nKreisel Modul eingefuegt.")
(ssg-end)
)
;; -----------------------------------------------
;; KreiselConnect: 2 parallele Linien anklicken
;;
;; Ablauf:
;; 1. Erste Linie anklicken -> AN-Position (Antriebsstation)
;; 2. Zweite Linie anklicken -> SP-Seite (Spannstation)
;; 3. Richtung + Abstand werden aus der Geometrie berechnet
;; 4. Nur PIN ja/nein wird abgefragt
;;
;; Beide Linien muessen parallel sein und gleiche Z-Koordinate haben.
;; Horizontale und vertikale Linien werden unterstuetzt.
;; -----------------------------------------------
(defun c:KreiselConnect ( / sel1 ent1 pt1 sel2 ent2 pt2
lpts1 lpts2 s1 e1 s2 e2
dir1 dir2 snap1 foot
dx dy dist abstand rotation typ
ok msg)
(ssg-start "Kreisel Smart Connect" '(("OSMODE") ("CECOLOR")))
(setvar "OSMODE" 0)
(setq ok T msg nil)
(princ "\n--- Kreisel zwischen zwei parallelen Linien ---")
;; 1. Erste Linie anklicken (AN-Seite)
(if ok
(progn
(setq sel1 (entsel "\nErste Linie anklicken (AN-Seite): "))
(cond
((null sel1)
(setq ok nil))
((/= (cdr (assoc 0 (entget (car sel1)))) "LINE")
(setq ok nil msg "Erste Auswahl ist kein LINE-Objekt!"))
)
)
)
;; 2. Zweite Linie anklicken (SP-Seite)
(if ok
(progn
(setq sel2 (entsel "\nZweite Linie anklicken (SP-Seite): "))
(cond
((null sel2)
(setq ok nil))
((/= (cdr (assoc 0 (entget (car sel2)))) "LINE")
(setq ok nil msg "Zweite Auswahl ist kein LINE-Objekt!"))
)
)
)
;; 3. Geometrie auswerten
(if ok
(progn
(setq ent1 (car sel1) pt1 (cadr sel1))
(setq ent2 (car sel2) pt2 (cadr sel2))
;; Linien-Endpunkte lesen
(setq lpts1 (kreisel-get-line-pts ent1)
s1 (car lpts1) e1 (cadr lpts1))
(setq lpts2 (kreisel-get-line-pts ent2)
s2 (car lpts2) e2 (cadr lpts2))
;; Richtungsvektoren
(setq dir1 (list (- (car e1) (car s1)) (- (cadr e1) (cadr s1))))
(setq dir2 (list (- (car e2) (car s2)) (- (cadr e2) (cadr s2))))
;; Parallelitaet pruefen
(if (not (kreisel-parallel-p dir1 dir2))
(setq ok nil msg "Linien sind nicht parallel!")
)
)
)
;; 4. Positionen und Abstand berechnen
(if ok
(progn
;; Klickpunkt exakt auf Linie 1 projizieren
(setq snap1 (kreisel-project-point (list (car pt1) (cadr pt1)) s1 e1))
;; Von snap1 senkrecht auf Linie 2 projizieren
(setq foot (kreisel-project-point snap1 s2 e2))
;; Richtung und Distanz
(setq dx (- (car foot) (car snap1))
dy (- (cadr foot) (cadr snap1)))
(setq dist (sqrt (+ (* dx dx) (* dy dy))))
(setq abstand (- dist *kreisel-durchmesser*))
(if (<= abstand 0.0)
(setq ok nil
msg (strcat "Abstand zwischen Linien zu klein! ("
(rtos dist 2 0) " < " (rtos *kreisel-durchmesser* 2 0) ")"))
)
)
)
;; 5. Rotation berechnen und Modul einfuegen
(if ok
(progn
;; Winkel von AN-Punkt (snap1) zum SP-Fusspunkt (foot)
(setq rotation (* (/ 180.0 pi) (atan dy dx)))
;; Typ abfragen (einzige Benutzer-Eingabe)
(setq typ (kreisel-ask-typ))
(princ (strcat "\n-> Abstand: " (rtos abstand 2 0) " mm"
" Rotation: " (rtos rotation 2 1) " Grad"
" Typ: " typ))
;; Modul als Compound-Block einfuegen
(draw-module snap1 abstand typ rotation)
(princ "\nKreisel Connect erfolgreich!")
)
;; Fehlerfall
(if msg (ssg-emsg msg) (princ "\nAbgebrochen."))
)
(ssg-end)
)
;; --------------------------------------------
;; KreiselQuick: Schnell mit Defaults (horizontal)
;; --------------------------------------------
(defun c:KreiselQuick ( / pt)
(ssg-start "Kreisel Schnell Einfuegen" '(("OSMODE") ("CECOLOR")))
(setvar "OSMODE" 0)
(setq pt (getpoint "\nBasispunkt (AN-Seite): "))
(if pt
(draw-module (list (car pt) (cadr pt)) *kreisel-default-laenge* #Kreisel_Typ 0.0)
)
(princ "\nSchnell Einfuegen fertig.")
(ssg-end)
)
;; --------------------------------------------
;; KreiselParams: Aktuelle Parameter anzeigen
;; --------------------------------------------
(defun c:KreiselParams ()
(princ "\n=== Aktuelle Kreisel Parameter ===")
(princ (strcat "\nAbstand: " (rtos #Kreisel_Abstand 2 0) " mm"))
(princ (strcat "\nTyp: " #Kreisel_Typ))
(princ "\nBasispunkt: linke Kreistangente (links Mitte)")
(princ "\nBasispunkt: AN-Seite (Antriebsstation)")
(princ "\nBlock: Compound (AN8 + SP8 + Tangenten + PIN)")
(princ "\n===================================\n")
(princ)
)
(princ "\nKreiselInsert.lsp geladen (Version 4.2 - SSG-Lib Integration)!")
(princ "\nKreiselInsert.lsp geladen (Version 5.0 - Compound Block)")
(princ "\nBefehle: KreiselInsert, KreiselConnect, KreiselQuick, KreiselParams")
(princ)