- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I am working on a LISP program to create tangent lines to two ellipses. The ellipses may be at any orientation in space but must lie on the same plane. Although the ray command, unlike the line command, can be used in conjunction with the tangent OSNAP modifier to create a line from a point tangent to an ellipse, it does not work for creating a line tangent to two ellipses.
The math for computing coordinates and slopes at points on an ellipse is simplified if the coordinate system used is oriented such that the x axis passes through the center of the ellipse and points in the direction of the major axis.
I was hoping to use the trans function to convert WCS coordinates to ellipse object coordinates. I have not had success with this approach. Using UCS OB to set the current ucs to the ellipse yields a coordinate system that does not align the x axis with the major axis.
Alternatively, I have had success by building a homogeneous transformation matrix for the ellipse and then inverting it to translate ellipse world coordinates to "proper" ellipse coordinates. Although this approach works I think it too complex and I was hoping there was a way to use trans or some other VLISP function to convert WCS to the desired coordinate system of the ellipse.
The following work-in-progress code provides two commands, ucs_ob and ucs_matrix that highlight the differences in the two approaches. ucs_matrix yields the correct results whereas ucs_ob does not.
(defun c:ucs_ob (/)
(setq pA (getpoint "\nSpecify point for ellipse"))
(setq ent (entsel "\nSelect ellipse."))
(setq ppA (cadr ent) ; pick point ellpse A
enA (car ent)
edA (entget enA)
cenEllipseA (cdr (assoc 10 edA))
smajorA (cdr (assoc 11 edA))
ratio (cdr (assoc 40 edA))
sminorA (mapcar '*
(list ratio ratio ratio)
(cross '(0 0 1) smajorA)
)
a (distance '(0 0 0) smajorA)
b (distance '(0 0 0) sminorA)
)
; set coordinate system to ellipse
(command "_ucs" "ob" ena)
(setq pAOCS (trans pA 0 1))
(princ "\n\npA = ")
(princ pA)
(princ "\n\npA OCS = ")
(princ pAOCS)
(princ)
)
(defun c:ucs_matrix (/)
(setq pA (getpoint "\nSpecify point for ellipse"))
(princ "\nP = ")
(princ pA)
(setq ent (entsel "\nSelect ellipse."))
(setq ppA (cadr ent) ; pick point ellpse A
enA (car ent)
edA (entget enA)
cenEllipseA (cdr (assoc 10 edA))
smajorA (cdr (assoc 11 edA))
ratio (cdr (assoc 40 edA))
sminorA (mapcar '*
(list ratio ratio ratio)
(cross '(0 0 1) smajorA)
)
a (distance '(0 0 0) smajorA)
b (distance '(0 0 0) sminorA)
)
(setq row1 (append (unitV smajorA) '(0.0))
row2 (append (unitV sminorA) '(0.0))
row3 '(0 0 1 0)
row4 (append cenEllipseA '(1.0))
mA (list row1 row2 row3 row4) ; matrix for ellipse A
)
; translate point from world to ellipse A coordinate system
(setq miA (invm mA))
(setq pAOCS (transform pA miA))
(princ "\n\npA = ")(princ pA)
(princ "\n\npA OCS = ")(princ pAOCS)
(princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun transform (a b / transpt) ;Coordinate transformation via matrix multiplication
; a = point (3 coordinates)
; b = homogeneous transformation matrix (3 x 4)
(setq aH (append a '(1.0))) ; aH = homogeneous point in local coordinates (1 x 4)
(setq transpt
(list
(+ ; transpt = list of x, y, z coordinates
(* (nth 0 aH) (nth 0 (nth 0 b)))
(* (nth 1 aH) (nth 0 (nth 1 b)))
(* (nth 2 aH) (nth 0 (nth 2 b)))
(* (nth 3 aH) (nth 0 (nth 3 b)))
)
(+
(* (nth 0 aH) (nth 1 (nth 0 b)))
(* (nth 1 aH) (nth 1 (nth 1 b)))
(* (nth 2 aH) (nth 1 (nth 2 b)))
(* (nth 3 aH) (nth 1 (nth 3 b)))
)
(+
(* (nth 0 aH) (nth 2 (nth 0 b)))
(* (nth 1 aH) (nth 2 (nth 1 b)))
(* (nth 2 aH) (nth 2 (nth 2 b)))
(* (nth 3 aH) (nth 2 (nth 3 b)))
)
)
)
(setq transpt (list (nth 0 transpt) (nth 1 transpt) (nth 2 transpt) ))
) ;end transform
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;
;; Matrix Inverse - gile & Lee Mac
;; Uses Gauss-Jordan Elimination to return the inverse of a non-singular nxn matrix.
;; Args: m - nxn matrix
(defun invm ( m / c f p r )
(defun f ( p m )
(mapcar '(lambda ( x ) (mapcar '(lambda ( a b ) (- a (* (car x) b))) (cdr x) p)) m)
)
(setq m (mapcar 'append m (imat (length m))))
(while m
(setq c (mapcar '(lambda ( x ) (abs (car x))) m))
(repeat (vl-position (apply 'max c) c)
(setq m (append (cdr m) (list (car m))))
)
(if (equal 0.0 (caar m) 1e-14)
(setq m nil
r nil
)
(setq p (mapcar '(lambda ( x ) (/ (float x) (caar m))) (cdar m))
m (f p (cdr m))
r (cons p (f p r))
)
)
)
(reverse r)
)
;; Identity Matrix - Lee Mac
;; Args: n - matrix dimension
(defun imat ( n / i j l m )
(repeat (setq i n)
(repeat (setq j n)
(setq l (cons (if (= i j) 1.0 0.0) l)
j (1- j)
)
)
(setq m (cons l m)
l nil
i (1- i)
)
)
m
)
;;; Compute the cross product of 2 vectors a and b
(defun cross (a b / crs)
(setq crs (list
(- (* (nth 1 a) (nth 2 b))
(* (nth 1 b) (nth 2 a))
)
(- (* (nth 0 b) (nth 2 a))
(* (nth 0 a) (nth 2 b))
)
(- (* (nth 0 a) (nth 1 b))
(* (nth 0 b) (nth 1 a))
)
) ;end list
) ;end setq c
) ;end cross
Solved! Go to Solution.