... you could probably find some rotation matrix stuff somewhere on here, or google it..
This is some code that I was working on for an article on the site a couple of years ago and ended up dropping it before it was complete. It's in terrible shape and nearly impossible to follow, but
*maybe* you can glean something useful out of it
I left off just before I got to the part of having the ghosted objects follow the cursor. From a high level perspective, what you'll have to do is capture the cursor position, compare it to the previous position, and transform the objects from the old to the new position. I have yet to do this in LISP, but I have done it in .NET. You can see that code over in the .NET list,
http://www.theswamp.org/forum/index.php?topic=8195.0 and
http://www.theswamp.org/forum/index.php?topic=8198.0This is the main function
Type "DrawShape" to start the command.
(defun c:drawShape (/ basePt rotation grInput grRetVal sFac
dragPnt vector matrix pMatrix Color
pColor ptLst shape *error*
)
(defun *error* (msg)
(if (not
(member
Msg
'("console break"
"Function cancelled"
"quit / exit abort"
)
)
)
(progn
(princ (strcat "\nError #" (itoa (getvar "ERRNO")) ": " Msg)
)
(setvar "ERRNO" 0)
)
)
;;erase last vectors
(if pMatrix
(grDrClosedShape pColor ptLst pMatrix)
)
(princ)
)
(initget "Rectangle1 rEctangle2")
(setq shape (getkword "\nShape to draw [Rectangle1/rEctangle2] <Rectangle1>")
shape
(cond
((equal shape "rEctangle2") 'rectangle2)
(t 'rectangle1)
)
basePt (getpoint "\nSelect point: ")
)
(if basePt
(progn
(setq sFac (/ (car (getvar "SCREENSIZE")) 1000)
vector (mapcar '- basePt)
ptLst ((eval shape) basePt)
grInput 5
)
;;---------------------------
;;Loop while user moves mouse
;;---------------------------
(while (= grInput 5)
;;-------------------------
;;get data from GRREAD
;;-------------------------
(setq grRetVal (grread t 5 0)
grInput (car grRetVal)
dragPnt (cadr grRetVal)
rotation (angle basePt dragPnt)
color 300
;;-------------------------------------
;;Build Transformation matrix from data
;;-------------------------------------
matrix (bldTformMatrix
(list
(TranslateMatrix basePt)
(ScaleMatrix (/ (distance basePt dragpnt) sFac))
(TranslateMatrix Vector)
(TranslateMatrix basePt)
(RotateZMatrix rotation)
(TranslateMatrix Vector)
)
)
)
;;erase previous vectors
(if pMatrix
(grDrClosedShape pColor ptLst pMatrix)
)
;;Draw vectors
(grDrClosedShape Color ptLst Matrix)
;;Save current grvecs information
(setq pMatrix matrix
pColor Color
)
)
;;erase last vectors
(grDrClosedShape Color ptLst Matrix)
(command "_.pline")
(foreach pt (transPts ptLst Matrix)
(command pt)
)
(command "_C")
)
(princ)
)
)
This helper function will grdraw a closed shape
;;;Draw closed shape with GRVECS
;;;(grDrClosedShape 7 '((1 1) (2 1) (2 2) (1 2)) myMatrix)
(defun grDrClosedShape (color ptLst matrix)
(grvecs
(append
(list color)
(cdr
(apply
'append
(mapcar
'(lambda (pt)
(list pt pt)
)
ptlst
)
)
)
(list (car ptLst))
)
matrix
)
)
These functions define a couple of closed rectangles. You can create others and pass them to the grDrClosedShape() function. They do not have to be rectangles.
;;;Define the shape of the vectors to draw
;;;via a list of points as they relate to a supplied
;;;base point. This is a rectangle with the
;;;base point being the lower left corner.
(defun Rectangle1 (pt / x y xVect yVect)
(mapcar '(lambda (val var) (set var (/ val 1000.0)))
(getvar "SCREENSIZE")
'(xVect yVect)
)
(setq x (car pt)
y (cadr pt)
)
(list
pt ;LL
(list (+ x xVect) y) ;LR
(list (+ x xVect) (+ y yVect)) ;UR
(list x (+ y yVect)) ;UL
)
)
;;;This is a rectangle with the base point being the
;;;center of the rectangle.
(defun Rectangle2 (pt / x y hxVect hyVect)
(mapcar '(lambda (val var) (set var (/ val 1000.0)))
(getvar "SCREENSIZE")
'(xVect yVect)
)
(setq x (car pt)
y (cadr pt)
hxVect (* 0.5 xVect)
hyVect (* 0.5 yVect)
)
(list
(list (- x hxVect) (- y hyVect)) ;LL
(list (+ x hxVect) (- y hyVect)) ;LR
(list (+ x hxVect) (+ y hyVect)) ;UR
(list (- x hxVect) (+ y hyVect)) ;UL
)
)
These are the Matrix helper functions
;;;Special thanks to Vladimir Nesterovsky
;;;for these four matrix manipulation routines
;;;a dot product of the two vectors, u & v
(defun dotprod (u v)
(apply '+ (mapcar '* u v))
)
;;;transpose a matrix
;;;code by doug Wilson
(defun transpose (m)
(apply 'mapcar (cons 'list m))
)
;;;Apply a transformation matrix to a vector
(defun mxv (m v)
(mapcar '(lambda (row) (dotprod row v))
m
)
)
;;;Multiply two matrices
(defun mxm (m q)
(setq q (transpose q))
(mapcar '(lambda (row) (mxv q row))
m
)
)
;;;Scale matrix
;;;We add error handling to this matrix to
;;;ensure that we never have a zero scale factor.
;;;It accepts a single scale factor for the
;;;X, Y, & Z or a list of factors in the order
;;;of '(X Y Z).
;;;(ScaleMatrix 3.5)
;;;(ScaleMatrix '(3 2 1))
(defun ScaleMatrix (Scale / ScaleX ScaleY ScaleZ)
(mapcar
'(lambda (var scl)
(if (zerop scl)
(set var 1)
(set var scl)
)
)
'(ScaleX ScaleY ScaleZ)
(if (listp scale)
Scale
(list Scale Scale Scale)
)
)
(list (list ScaleX 0 0 0)
(list 0 ScaleY 0 0)
(list 0 0 ScaleZ 0)
(list 0 0 0 1)
)
)
;;;Rotate about Z axis
;;;Rotation to be supplied in radians
;;;(RotateZMatrix (* pi 3.33))
(defun RotateZMatrix (Rot)
(list (list (cos Rot) (- (sin Rot)) 0 0)
(list (sin Rot) (cos Rot) 0 0)
(list 0 0 1 0)
(list 0 0 0 1)
)
)
;;;Translate Matrix
;;;Vector is a list of values
;;;in the order of '(X Y Z) to
;;;move a point
;;;(TranslateMatrix '(3 4 0))
(defun TranslateMatrix (Vector)
(list (list 1 0 0 (car Vector))
(list 0 1 0 (cadr Vector))
(list 0 0 1 (caddr Vector))
(list 0 0 0 1)
)
)
;;;Apply a 3d Transformation matrix
;;;to a list of points. Points can
;;;be 2d or 3d points.
;;;(TransPts '((1 1 0) (2 3 0) (1 3 0)) (ScaleMatrix 2))
(defun TransPts (ptLst Matrix)
(mapcar
'(lambda (pt / ptDim)
(setq ptDim (length pt)
pt
(if (= ptDim 3)
(reverse (cons 1 (reverse pt)))
(reverse (cons 1 (cons 0 (reverse pt))))
)
)
(reverse
(apply
(if (= ptDim 3)
'cdr
'cddr
)
(list
(reverse
(mxv Matrix pt)
)
)
)
)
)
ptLst
)
)
;;;Combines multiple Matrices into a single matrix
;;;(bldTformMatrix (list (ScaleMatrix 2) (TranslateMatrix '(2 2 0))))
(defun bldTformMatrix (matrixLst / TformMatrix)
(foreach matrix matrixLst
(setq TformMatrix
(if TformMatrix
(mxm TformMatrix matrix)
matrix
)
)
)
)
Here is another example using some of the same helper functions. This one allows you to create a selection set by defining a rectangular area that you can scale and rotate by moving the cursor.
Type "CS" at the command line to start it.
;;;Crazy Select!
(defun c:cs ()
(ax:cs rectangle1)
)
(defun ax:cs (shape / basePt rotation grInput
grRetVal sFac dragPnt vector matrix
pMatrix sMethod Color pColor ptLst
ss *error*
)
(defun *error* (msg)
(if (not
(member
Msg
'("console break"
"Function cancelled"
"quit / exit abort"
)
)
)
(progn
(princ (strcat "\nError #" (itoa (getvar "ERRNO")) ": " Msg))
(setvar "ERRNO" 0)
)
)
;;erase last vectors
(if pMatrix
(grDrClosedShape pColor ptLst pMatrix)
)
(princ)
)
(if (setq basePt (getpoint "\nSelect point: "))
(progn
(setq sFac (/ (car (getvar "SCREENSIZE")) 1000)
vector (mapcar '- basePt)
ptLst (shape basePt)
grInput 5
)
;;Loop while user moves mouse
(while (= grInput 5)
(setq grRetVal (grread t 5 1)
grInput (car grRetVal)
dragPnt (cadr grRetVal)
rotation (angle basePt dragPnt)
sMethod (cond
((< (* 0.5 pi) rotation (* 1.5 pi))
"_CP"
)
(t "_WP")
)
color (if (equal sMethod "_WP") 300 -300)
matrix (bldTformMatrix
(list
(TranslateMatrix basePt)
(ScaleMatrix (/ (distance basePt dragpnt) sFac))
(TranslateMatrix Vector)
(TranslateMatrix basePt)
(RotateZMatrix rotation)
(TranslateMatrix Vector)
)
)
)
;;erase previous vectors
(if pMatrix
(grDrClosedShape pColor ptLst pMatrix)
)
;;Draw vectors
(grDrClosedShape Color ptLst Matrix)
;;Save current grvecs information
(setq pMatrix matrix
pColor Color
)
)
;;erase last vectors
(grDrClosedShape Color ptLst Matrix)
;;Transform points according to last matrix
(setq ss (ssget sMethod (transPts ptLst Matrix)))
)
(princ)
)
)