Author Topic: Transformation matrix vs Acads matrix  (Read 15612 times)

0 Members and 1 Guest are viewing this topic.

T.Willey

  • Needs a day job
  • Posts: 5251
Transformation matrix vs Acads matrix
« on: January 30, 2007, 02:15:41 PM »
I have been trying to undrestand transformation matrices and how to use them in Acad.  I have read plenty of articles and think I have a handle of the basics.  I wrote this program to give me a 4x4 matrix when supplied an ename.  It works correctly (for now, but I'm sure I need to improve it), but when I use the matrix returned with the 'transformby' method, it doesn't transform it correctly, but if I use 'vlax-tmatrix' on my matrix and use 'transformby' then it does.

Anybody know why?  Or know how Acad wants their matrices?
Example of a matrix my program returns.  Object inserted at 0,0,0 with now scale and no rotation.
Code: [Select]
(
 (1.0 0.0 0.0 0.0)
 (0.0 1.0 0.0 0.0)
 (0.0 0.0 1.0 0.0)
 (0.0 0.0 0.0 1.0)
)
Another example.  Moved 5,2, and rotated 180.
Code: [Select]
(
 (-1.0 -1.22461e-016 0.0 5.0)
 (1.22461e-016 -1.0 0.0 2.0)
 (0.0 0.0 1.0 0.0)
 (0.0 0.0 0.0 1.0)
)

The difference in use is this
Code: [Select]
(vlax-inivoke Obj 'TransformBy Matrix)and
Code: [Select]
(vla-TransformBy Obj (vlax-tmatrix Matrix))With the later one working only.

Thanks.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #1 on: January 30, 2007, 02:48:39 PM »
Hi,

I don't know if it helps, but what I discovered is that vlax-tmatrix transforms a list in a variant (as vlax-3d-point)

You can try :
Code: [Select]
(setq matrix '(
       (-1.0 0. 0.0 5.0)
       (0.0 -1.0 0.0 2.0)
       (0.0 0.0 1.0 0.0)
       (0.0 0.0 0.0 1.0)
      )
)

(setq test (vlax-make-variant
     (vlax-safearray-fill
       (vlax-make-safearray vlax-vbDouble '(0 . 3) '(0 . 3))
       matrix
     )
   )
)

(vla-transformby obj test)

I suppose vlax-invoke accepts simple lists instead of variants but no matrices.
Speaking English as a French Frog

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #2 on: January 30, 2007, 02:57:05 PM »
Gile,

  That seems to work also.  I guess Acad just doesn't like a list of list to use as a transformation matrix.
Thank you.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #3 on: January 30, 2007, 03:28:35 PM »
Perhaps it's a question of array dimension.
A matrix is a two dimension array.
When passing a list of points to vlax-invoke i.e. (vlax-invoke space addPolyline lst), the list have to be transformed in a "flat" list.
The same type of list becomes a one dimension array to be used with (vla-addPolyline space variant).
Speaking English as a French Frog

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #4 on: January 30, 2007, 03:43:24 PM »
Perhaps it's a question of array dimension.
A matrix is a two dimension array.
So if this is true, which sounds like a good explanation to me, then there is no way to use a list of lists to pass to it.  At least I don't see a way.  In more general terms then, if a ActiveX functions wants a multi-dimension array, then you have to supply it an array, but if it's only a single dimension array, then a flat list will work.  I think I will go with this theory until it is proved wrong.  Thanks for the ideas Gile.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Joe Burke

  • Guest
Re: Transformation matrix vs Acads matrix
« Reply #5 on: January 31, 2007, 10:16:27 AM »
Hi Tim,

As I read your question, it seems you want to create a 4x4 transformation matrix from an object. Presumably from a block.

If so, you probably already have my ObjMatrix functions, which are designed to do exactly that, going either way.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #6 on: January 31, 2007, 11:03:45 AM »
Hi Tim,

As I read your question, it seems you want to create a 4x4 transformation matrix from an object. Presumably from a block.

If so, you probably already have my ObjMatrix functions, which are designed to do exactly that, going either way.
Hey Joe,

  Yea I have yours, and I used yours as a guide.  I wanted to understand it better, so I wrote my own, and when I got stuck I would look at yours.  That is how I saw to use the function 'vlax-tmatrix' because I saw you use it.  I was just trying to get a better understand of why you used it.  :-D  Thanks again for your code.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #7 on: January 31, 2007, 05:25:10 PM »
If you're interested by some matrix routines, I post here some extracted from this thread on the French site CADxp (you have to register to read all replies). You can find another one there and two others to be used with nentsel or nentselp matrices Here in TheSwamp.

EDIT 1 : Last link was wrong, it's right now.

EDIT 2 : Correction in ReverseMatrix.

First some some vector and matrix calculus little routines (Thanks to Doug Wilson and Vladimir Nesterovsky)
Code: [Select]
;; VXV Dot product
;; Arguments : two vectors
;; Return : a real
(defun vxv (v1 v2)
  (apply '+ (mapcar '* v1 v2))
)

;; V^V Cross product
;; Arguments : two vectors
;; Return : a vector, perpendicular with both arguments (respects the "right hand rule")
(defun v^v (v1 v2)
  (if (inters '(0 0 0) v1 '(0 0 0) v2)
    (list (- (* (cadr v1) (caddr v2)) (* (caddr v1) (cadr v2)))
  (- (* (caddr v1) (car v2)) (* (car v1) (caddr v2)))
  (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2)))
    )
  )
)

;; Transpose a matrix Doug Wilson
;; Argument : a matrix
;; Return : the tranposed matrix
(defun trp (m)
  (apply 'mapcar (cons 'list m))
)

;; Apply a transformation matrix to a vector by Vladimir Nesterovsky
;; Arguments: a 3X3 matrix and a vector
;; Return : the vecor transformed by the matrix

(defun mxv (m v)
  (mapcar '(lambda (r) (apply '+ (mapcar '* r v))) m)
)

;; Multiply two matrices by Vladimir Nesterovsky
;; Arguments : two matrices
;; Return : the matrices combination
;; Attention : (mxm mat1 mat1) is not equal to (mxm mat2 mat1)
(defun mxm (m q)
  (mapcar '(lambda (r)
     (mapcar '(lambda (l) (apply '+ (mapcar '* l r)))
     (apply 'mapcar (cons 'list q))
     )
   )
  m
  )
)

The two routines which made me start with matrices (Thanks to Doug Broad)
Code: [Select]
;; Doug C. Broad, Jr.
;; can be used with vla-transformby to
;; transform objects from the UCS to the WCS
(defun UCS2WCSMatrix ()
  (append
    (mapcar
      '(lambda (vector origin)
(append (trans vector 1 0 T) (list origin))
       )
      (list '(1 0 0) '(0 1 0) '(0 0 1))
      (trans '(0 0 0) 0 1)
    )
    (list '(0 0 0 1))
  )
)

;; Doug C. Broad, Jr.
;; can be used with vla-transformby to
;; transform objects from the WCS to the UCS
(defun WCS2UCSMatrix ()
  (append
    (mapcar
      '(lambda (vector origin)
(append (trans vector 0 1 T) (list origin))
       )
      (list '(1 0 0) '(0 1 0) '(0 0 1))
      (trans '(0 0 0) 1 0)
    )
    (list '(0 0 0 1))
  )
)

Some other examples of my own
all the matrices returned by these routines have to be changed in variants with (vlax-TMatrix ...) before being used with (vla-TransformBy ....)
Code: [Select]
;; WCS23ptsMatrix
;; Arguments : 3 points (origin, X direction and Y positive location)
;; Return : the transformation matrix from WCS to a 3 points defined UCS
(defun WCS23ptsMatrix (org xdir ydir / lst zdir)
  (setq lst
(reverse
   (list
     (setq zdir (norm_3pts org xdir ydir))
     (norm_3pts org (mapcar '+ org zdir) xdir)
     (mapcar '(lambda (x y) (/ (- x y) (distance org xdir)))
     xdir
     org
     )
   )
)
  )
  (append
    (mapcar '(lambda (v1 v2) (append v1 (list v2)))
    (trp lst)
    org
    )
    (list '(0 0 0 1))
  )
)

;; 3pts2WCSMatrix
;; Arguments : 3 points (origin, X direction and Y positive location)
;; Return : the transformation matrix from a 3 points defined UCS to WCS
(defun 3pts2WCSMatrix (org xdir ydir / lst zdir)
  (setq lst
(reverse
   (list
     (setq zdir (norm_3pts org xdir ydir))
     (norm_3pts org (mapcar '+ org zdir) xdir)
     (mapcar '(lambda (x y) (/ (- x y) (distance org xdir)))
     xdir
     org
     )
   )
)
  )
  (append
    (mapcar '(lambda (v1 v2) (append v1 (list v2)))
    lst
    (mapcar '- (mxv lst org))
    )
    (list '(0 0 0 1))
  )
)

;; Example of using MXM
;;
;; UCS23pointsMatrix
;; Arguments : 3 points (origin, X direction and Y positive location)
;; Return : the transformation matrix from the current UCS to a 3 points defined UCS
(defun UCS23pointsMatrix (org xdir ydir)
  (mxm (WCS23ptsMatrix org xdir ydir) (UCS2WCSMatrix))
)

;; ScaleMatrix
;; Arguments : base point and scale factor
;; Note : only uniform scales are accepted by vla-TransformBy
(defun ScaleMatrix (base scl)
  (append
    (mapcar
      '(lambda (v1 v2)
(append (mapcar '(lambda (x) (* x scl)) v1)
(list v2)
)
       )
      (list '(1 0 0) '(0 1 0) '(0 0 1))
      (mapcar '(lambda (x) (- x (* x scl))) base)
    )
    (list '(0 0 0 1))
  )
)

;; MoveMatrix
;; Argument : a vector
(defun MoveMatrix (dep)
  (append
    (mapcar
      '(lambda (v1 v2)
(append v1 (list v2))
       )
      (list '(1 0 0) '(0 1 0) '(0 0 1))
      dep
    )
    (list '(0 0 0 1))
  )
)

;; Rotation on Z axis
;; Arguments : base point and angle
(defun ZRotateMatrix (base ang / mat)
  (append
    (mapcar
      '(lambda (v1 v2)
(append v1 (list v2))
       )
      (setq mat (list (list (cos ang) (- (sin ang)) 0)
      (list (sin ang) (cos ang) 0)
      '(0 0 1)
)
      )
      (mapcar '- base (mxv mat base))
    )
    (list '(0 0 0 1))
  )
)

;; Rotation on X axis
;; Arguments : base point and angle
(defun XRotateMatrix (base ang / mat)
  (append
    (mapcar
      '(lambda (v1 v2)
(append v1 (list v2))
       )
      (setq mat (list '(1 0 0)
      (list 0 (cos ang) (- (sin ang)))
      (list 0 (sin ang) (cos ang))
)
      )
      (mapcar '- base (mxv mat base))
    )
    (list '(0 0 0 1))
  )
)

;;; Rotation on Y axis
;; Arguments : base point and angle
(defun YRotateMatrix (base ang / mat)
  (append
    (mapcar
      '(lambda (v1 v2)
(append v1 (list v2))
       )
      (setq mat (list (list (cos ang) 0 (sin ang))
      '(0 1 0)
      (list (- (sin ang)) 0 (cos ang))
)
      )
      (mapcar '- base (mxv mat base))
    )
    (list '(0 0 0 1))
  )
)

;; ReverseMatrix
;; Argument : a transformation matrix
;; Return : the reverse transformation matrix
(defun butlast (lst)
  (reverse (cdr (reverse lst)))
)

(defun ReverseMatrix (mat / sclst rmat)
  (setq sclst (mapcar '(lambda (v) (expt (car (mapcar '/ (vunit v) v)) 2))
      (trp (mapcar 'butlast (butlast mat)))
      )
  )
  (append
    (mapcar '(lambda (v1 v2) (append v1 (list v2)))
    (setq rmat (trp (mxm (mapcar 'butlast (butlast mat))
  (list (list (car sclst) 0.0 0.0)
(list 0.0 (cadr sclst) 0.0)
(list 0.0 0.0 (caddr sclst))
  )
     )
)
    )
    (mapcar '- (mxv rmat (mapcar 'last (butlast mat))))
    )
    (list '(0.0 0.0 0.0 1.0))
  )
)
« Last Edit: February 07, 2007, 09:04:57 AM by gile »
Speaking English as a French Frog

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #8 on: January 31, 2007, 05:32:12 PM »
Thanks again Gile, for the abundance of information.  This is fun learning, but hard at times.  I'm in the process of trying to make a matrix that will work with objects that are rotated in 3d space.  Something fun an challenging.  When (if) I finish I will post it here.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

whdjr

  • Guest
Re: Transformation matrix vs Acads matrix
« Reply #9 on: February 01, 2007, 10:07:57 AM »
I'll speak up for all those out there that have heard of matrices but don't actually know what they are or how you would use them.

What are matrices and how would you use them?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #10 on: February 01, 2007, 11:17:15 AM »
Here is a site to explain it better than I will.

Matrix is a way to transform (move, scale, rotate) an object in 3d space.  Say you want to copy an object from and xref.  You copy it into the drawing, but the xref has been moved, scaled and rotated, so when it copies its in the wrong location.  You would create a matrix off the xref so that you can place your newly copied object where it should be.

I know thats not the best explanation, but that is what I'm using them for.  If someone wants to explain it better, I'm all ears also.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Transformation matrix vs Acads matrix
« Reply #11 on: February 01, 2007, 12:07:34 PM »
Nice link there Tim.
Here is some more matrix stuff.
http://www.theswamp.org/index.php?topic=8251.msg105624#msg105624
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Joe Burke

  • Guest
Re: Transformation matrix vs Acads matrix
« Reply #12 on: February 04, 2007, 11:50:17 AM »
Hi Tim,

As I read your question, it seems you want to create a 4x4 transformation matrix from an object. Presumably from a block.

If so, you probably already have my ObjMatrix functions, which are designed to do exactly that, going either way.
Hey Joe,

  Yea I have yours, and I used yours as a guide.  I wanted to understand it better, so I wrote my own, and when I got stuck I would look at yours.  That is how I saw to use the function 'vlax-tmatrix' because I saw you use it.  I was just trying to get a better understand of why you used it.  :-D  Thanks again for your code.

Hi Tim,

I'm sorry, I sorta forgot about this topic.

Just to be clear, the vlax-tmatrix function is not called within my ObjMatrix v2.lsp set of routines. It's used with the *returned* values of those functions in conjunction with the TransformBy method.

For instance, (ObjMatrix <block reference>) returns exactly the same 4x4 matrix as nentselp assuming a nested object was selected which is only nested one level deep. That matrix allows transformations from OCS to WCS. And when that's passed to vlax-tmatrix it does a conversion which allows the TransformBy method to use it.

The same is true for InverseObjMatrix. But it returns the inverse matrix, which is the hard part, transformations from WCS to OCS. There is no equivalent of this anywhere in out-of-the-box lisp or vlisp that I know of.

But of course, I could be wrong about that. If so, I don't why others smarter than me have looked for a solution to the same problem.

Also note, last time I checked, the TransformBy method cannot deal with matricies derived from non uniformaly scaled blocks. It will error in that case. That's not a limitation of my functions as it is not a limitation of nentselp. Both return the correct transformation matrix with NUS blocks.

You simply have to check for that where appropriate.

Joe

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #13 on: February 05, 2007, 11:28:49 AM »
Thanks Joe.

I still haven't got it working the way I want it to.  I now have a better understand of the 'normal' and I can tell, when looking at the numbers, where it is being looked at from, but I can't seem to code it correctly.  I have spent a couple days, off and on, on it, and still am lost.  This is driving me crazy.  :ugly:
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #14 on: February 05, 2007, 12:11:54 PM »
Just incase anyone wants to try and help me figure this out, here is the code I have so far.
Code: [Select]
(defun MultiplyAxies (Xdir Ydir)
; Call like (MultiplyAxis (getvar "ucsxdir") (getvar "ucsydir"))
;  to get the normal (z value) for the given ucs.

(list
 (- (* (cadr Xdir) (caddr Ydir)) (* (caddr Xdir) (cadr Ydir)))
 (- (* (caddr Xdir) (car Ydir)) (* (car Xdir) (caddr Ydir)))
 (- (* (car Xdir) (cadr Ydir)) (* (cadr Xdir) (car Ydir)))
)
)
;------------------------------------------------------------------------
(defun GetObjectAxisVectors (Norm / Ax)
; Retruns a list of two vectors, firs is the X axis vector,
;  the second is the Y axis vector.

(if
 (and
  (< (abs (car Norm)) (/ 1 64.0))
  (< (abs (cadr Norm)) (/ 1 64.0))
 )
 (setq Ax (MultiplyAxies '(0.0 1.0 0.0) Norm)) ; first vector world Y Axis
 (setq Ax (MultiplyAxies '(0.0 0.0 1.0) Norm)) ; first vector world Z Axis
)
(list Ax (MultiplyAxies Norm Ax))
)
;-----------------------------------------------------------------------------
(defun ArcCos (num)
; Posted by SMadsen @ theswamp.org
  (cond ((<= -1.0 num 1.0)
         (atan (sqrt (- 1.0 (* num num))) num)
        )
  )
)
;-----------------------------------------------------------------------------
(defun AngleOfVectors (v1 v2)
(ArcCos
 (/
  (apply '+ (mapcar '* v1 v2))
  (*
   (sqrt (apply '+ (mapcar '(lambda (x) (* x x)) v1)))
   (sqrt (apply '+ (mapcar '(lambda (x) (* x x)) v2)))
  )
 )
)
)
;-------------------------------------------------------------------------------------
(defun ename->4x4Matrix (ename / entData ptNorm Ang AxisList RotAng OppAng MainRotMatrix RotMatrix OppMatrix ptIns)

(setq entData (entget ename))
(setq MainRotMatrix
 (list
  (list 1.0 0.0 0.0 0.0)
  (list 0.0 1.0 0.0 0.0)
  (list 0.0 0.0 1.0 0.0)
  (list 0.0 0.0 0.0 1.0)
 )
)
(setq ptIns (append (cdr (assoc 10 entData)) '(1.0)))
(setq ptNorm (append (cdr (assoc 210 entData)) '(1.0)))
(setq AxisList (GetObjectAxisVectors ptNorm))
(setq Ang (cdr (assoc 50 entData)))
(if
 (and
  (not (equal (cadr AxisList) '(0.0 1.0 0.0) 0.0000001))
  (setq RotAng (angle (cadr AxisList) '(0.0 1.0 0.0)))
  (setq OppAng (- (* pi 2.0) RotAng))
 )
 (progn
  (setq OppMatrix
   (list
    (list 1.0 0.0 0.0 0.0)
    (list 0.0 (cos OppAng) (- (sin OppAng)) 0.0)
    (list 0.0 (sin OppAng) (cos OppAng) 0.0)
    (list 0.0 0.0 0.0 1.0)
   )
  )
  (setq RotMatrix
   (list
    (list 1.0 0.0 0.0 0.0)
    (list 0.0 (cos RotAng) (- (sin RotAng)) 0.0)
    (list 0.0 (sin RotAng) (cos RotAng) 0.0)
    (list 0.0 0.0 0.0 1.0)
   )
  )
  (setq MainRotMatrix
   (mxm
    MainRotMatrix
    RotMatrix
   )
  )
  (setq ptNorm (mxv OppMatrix ptNorm))
  (setq ptIns (mxv RotMatrix ptIns))
 )
)
(if
 (and
  (not (equal (car AxisList) '(1.0 0.0 0.0) 0.0000001))
  (setq RotAng (angle (car AxisList) '(1.0 0.0 0.0)))
  (setq OppAng (- (* pi 2.0) RotAng))
 )
 (progn
  (setq OppMatrix
   (list
    (list (cos OppAng) 0.0 (sin OppAng) 0.0)
    (list 0.0 1.0 0.0 0.0)
    (list (- (sin OppAng)) 0.0 (cos OppAng) 0.0)
    (list 0.0 0.0 0.0 1.0)
   )
  )
  (setq RotMatrix
   (list
    (list (cos RotAng) 0.0 (sin RotAng) 0.0)
    (list 0.0 1.0 0.0 0.0)
    (list (- (sin RotAng)) 0.0 (cos RotAng) 0.0)
    (list 0.0 0.0 0.0 1.0)
   )
  )
  (setq MainRotMatrix
   (mxm
    MainRotMatrix
    RotMatrix
   )
  )
  (setq ptNorm (mxv OppMatrix ptNorm))
  (setq ptIns (mxv RotMatrix ptIns))
 )
)
(if
 (and
  (equal ptNorm '(0.0 0.0 1.0 1.0) 0.0000001)
  (not (equal Ang 0.0))
 )
 (setq MainRotMatrix
  (mxm
   MainRotMatrix
   (list
    (list (cos Ang) (- (sin Ang)) 0.0 0.0)
    (list (sin Ang) (cos Ang) 0.0 0.0)
    (list 0.0 0.0 1.0 0.0)
    (list 0.0 0.0 0.0 1.0)
   )
  )
 )
)
;(print ptIns)
;(print Matrix)
(mxm
 (list
  (list (cdr (assoc 41 entData)) 0.0 0.0 (car ptIns))
  (list 0.0 (cdr (assoc 42 entData)) 0.0 (cadr ptIns))
  (list 0.0 0.0 (cdr (assoc 43 entData)) (caddr ptIns))
  (list 0.0 0.0 0.0 1.0)
 )
 MainRotMatrix
)
)

;; Apply a transformation matrix to a vector,
;; by Vladimir Nesterovsky
(defun mxv (m v)
  (mapcar '(lambda (row) (apply '+ (mapcar '* row v))) m)
)
;; Multiply two matrices, by Vladimir Nesterovsky.
(defun mxm (m q / qt)
  (setq qt (apply 'mapcar (cons 'list q)))
  (mapcar '(lambda (mrow) (mxv qt mrow)) m)
)

;========================================================================================

(defun c:testCopyObject (/ *error* ActDoc BlkCol dbxApp oVer Sel EntList tempStr tempList cnt DiaRtn Pos ObjCopy
                           NewObj Matrix tempEntData tempEntType tempBlkName tempPos testMatrix)
; Copy objects in place, nested or not.
; Sub's '*error* 'GetCurrentSpace 'ename->4x4Matrix 'SingleSelect

(defun *error* (msg)

(vla-EndUndoMark ActDoc)
(if dbxApp (vl-catch-all-apply 'vlax-release-object (list dbxApp)))
(setq dbxApp nil)
(prompt (strcat "\n Error-->: " msg))
)
;-------------------------------------------------------------
(setq ActDoc (vla-get-ActiveDocument (vlax-get-Acad-Object)))
(vla-EndUndoMark ActDoc)
(vla-StartUndoMark ActDoc)
(setq BlkCol (vla-get-Blocks ActDoc))
(setq dbxApp
 (if (< (atoi (setq oVer (substr (getvar "acadver") 1 2))) 16)
  (vla-GetInterfaceObject (vlax-get-acad-object) "ObjectDBX.AxDbDocument")
  (vla-GetInterfaceObject (vlax-get-acad-object) (strcat "ObjectDBX.AxDbDocument." oVer))
 )
)
(while (setq Sel (nentsel))
 (if (> (length Sel) 2)
  (progn
   (setq EntList (cons (car Sel) (last Sel)))
   (setq tempStr "")
   (setq tempList nil)
   (foreach ename EntList
    (if (not (equal ename (last EntList)))
     (progn
      (setq tempEntData (entget ename))
      (setq tempEntType (cdr (assoc 0 tempEntData)))
      (setq tempList
       (cons
        (strcat
         tempStr
         tempEntType
         (if (= tempEntType "INSERT")
          (progn
           (setq tempBlkName (cdr (assoc 2 tempEntData)))
           (if (setq tempPos (vl-string-search "|" tempBlkName))
            (setq tempBlkName (substr tempBlkname (+ tempPos 2)))
           )
           (strcat "  [ " tempBlkName " ]")
          )
          ""
         )
        )
        tempList
       )
      )
      (if (= tempStr "")
       (setq tempStr "   |-> ")
       (setq tempStr (strcat "   " tempStr))
      )
     )
    )
   )
   (if
    (or
     (and
      (<= (length EntList) 2)
      (setq DiaRtn 0)
      (setq cnt 1)
     )
     (and
      (setq DiaRtn (SingleSelect (reverse tempList) "Select item to copy." nil))
      (setq DiaRtn (car DiaRtn))
      (setq cnt (1+ DiaRtn))
      (< cnt (length EntList))
     )
    )
    (progn
     (setq tempList
      (
       (lambda (lst cnt / nlst ncnt)
        (setq ncnt 0)
        (foreach i lst
         (if (>= ncnt cnt)
          (setq nlst (cons i nlst))
         )
         (setq ncnt (1+ ncnt))
        )
        nlst
       )
       EntList
       cnt
      )
     )
     (if (setq Pos (vl-position :vlax-true (mapcar '(lambda (x) (vla-get-IsXref (vla-Item BlkCol (cdr (assoc 2 (entget x)))))) tempList)))
      (progn
       (if (vl-catch-all-error-p (vl-catch-all-apply 'vla-Open (list dbxApp (findfile (vla-get-Path (vlax-ename->vla-object (nth Pos tempList)))))))
        (exit)
       )
       (setq ObjCopy
        (vlax-invoke
         dbxApp
         'HandleToObject
         (vla-get-Handle
          (vlax-ename->vla-object
           (nth DiaRtn EntList)
          )
         )
        )
       )
      )
      (progn
       (setq dbxApp ActDoc)
       (setq ObjCopy (vlax-ename->vla-object (nth DiaRtn EntList)))
      )
     )
     (setq NewObj (car (vlax-invoke dbxApp 'CopyObjects (list ObjCopy) (GetCurrentSpace ActDoc))))
     (while (< cnt (length EntList))
      (setq Matrix (ename->4x4Matrix (nth cnt EntList)))
;(print Matrix)
;|      (setq testMatrix
       (vlax-make-variant
        (vlax-safearray-fill
         (vlax-make-safearray vlax-vbDouble '(0 . 3) '(0 . 3))
         Matrix
        )
       )
      )
      (vla-TransformBy NewObj testMatrix)
example by Gile @ theswamp works.
|;
      (vla-TransformBy NewObj (vlax-tmatrix Matrix))
      (setq cnt (1+ cnt))
     )
     (vla-Highlight NewObj :vlax-true)
    )
   )
   (prompt "\n Copy successful.")
  )
  (prompt "\n No object copied!")
 )
)
(vla-EndUndoMark ActDoc)
(if dbxApp (vl-catch-all-apply 'vlax-release-object (list dbxApp)))
(setq dbxApp nil)
(princ)
)
The problem is within the function 'ename->4x4Matrix'.  Attached is the drawing I'm testing it with, and my dcl file.
Code: [Select]
(defun SingleSelect (Listof Message Toggle / DiaLoad tmpStr tmpTog tmpList)

(setq DiaLoad (load_dialog "MyDialogs.dcl"))
(if (new_dialog "SingleSelect" DiaLOad)
 (progn
  (start_list "listbox" 3)
  (mapcar 'add_list Listof)
  (end_list)
  (if Message
   (set_tile "text1" Message)
  )
  (if (not Toggle)
   (mode_tile "toggle1" 1)
  )
  (action_tile "listbox"
   "(if (= $reason 4)
    (progn
     (setq tmpStr (get_tile \"listbox\"))
     (if Toggle
      (setq tmpTog (get_tile \"toggle1\"))
     )
     (done_dialog 1)
    )
   )"
  )     
  (action_tile "accept"
   "(progn
    (setq tmpStr (get_tile \"listbox\"))
    (if Toggle
     (setq tmpTog (get_tile \"toggle1\"))
    )
    (done_dialog 1)
   )"
  )
  (action_tile "cancel" "(done_dialog 0)")
  (if (= (start_dialog) 1)
   (progn
    (setq tmpList (read (strcat "(" tmpStr ")")))
    (if (= tmpTog "1")
     (cons T tmpList)
     tmpList
    )
   )
  )
 )
)
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #15 on: February 06, 2007, 02:44:31 AM »
Hi Tim,

I'm not sure to understand what you want to do with 'ename->4x4Matrix', but it seams to be : return the same 4X4 matrix as the one returned by 'nentselp' on a non nested entity in a reference (block or xref).

Here's the way I do it. Note I'd rather deal with 3X3 matrices than 4X4 matrices for scales and rotations, and then add a fourth column (deplacement) and the last row (0.0 0.0 0.0 1.0).

As said Joe, if the reference is non uniformaly scaled, the matrix shouldn't be used with 'vla-TransformBy'.

I purpose also another way to get OCS axis using 'trans'.

(mapcar   '(lambda (v) (trans v ename 0 T))
         '((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
)
returns the same thing as
(SCO (cdr (assoc 210 entData)))

EDIT: I change 'ename' argument to 'norm' in the (trans ...) expression, because it didn't work with nested entities in 'testCopyObject'.

Code: [Select]
;; Multiply two matrices by Vladimir Nesterovsky
;; Arguments : two matrices
;; Return : the matrices combination
;; Attention : (mxm mat1 mat2) is not equal to (mxm mat2 mat1)
(defun mxm (m q)
  (mapcar '(lambda (r)
     (mapcar '(lambda (l) (apply '+ (mapcar '* l r)))
     (apply 'mapcar (cons 'list q))
     )
   )
  m
  )
)


(defun ename->4x4Matrix (ename / entData ang norm mat)
  (setq entData (entget ename))
  (setq ang (- (cdr (assoc 50 entData))))
  (setq norm (cdr (assoc 210 entData)))
 
  ;; a 3X3 matrix as this returned by (butlast (caddr (nentsel)))
  (setq mat (mxm
      ;; scale
      (list (list (cdr (assoc 41 entData)) 0.0 0.0)
    (list 0.0 (cdr (assoc 42 entData)) 0.0)
    (list 0.0 0.0 (cdr (assoc 43 entData)))
      )
      (mxm
;; rotation on Z axis ...
(list (list (cos ang) (- (sin ang)) 0.0)
      (list (sin ang) (cos ang) 0.0)
      '(0.0 0.0 1.0)
)
;; ... of OCS
(mapcar '(lambda (v) (trans v norm 0 T))
'((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
)
      )
    )
  )

  ;; the 4X4 matrix as this returned by (caddr (nentselp))
  (append
    (mapcar
      '(lambda (v1 v2)
(append v1 (list v2))
       )
     (apply 'mapcar (cons 'list mat)) ; transposed 3X3 matrix
      (trans (cdr (assoc 10 entData)) norm 0) ; deplacement
    )
    (list '(0.0 0.0 0.0 1.0))
  )
)
« Last Edit: February 06, 2007, 12:14:20 PM by gile »
Speaking English as a French Frog

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Transformation matrix vs Acads matrix
« Reply #16 on: February 06, 2007, 11:05:45 AM »
Probably so it is better? 

Code: [Select]
;; the 4X4 matrix as this returned by (caddr (nentselp))
(append (mapcar '(lambda (v1 v2) (append v1 (list v2)))
                (apply 'mapcar (cons 'list mat))
                (trans (cdr (assoc 10 entData)) norm 0)
        ) ;_  mapcar
        (list '(0.0 0.0 0.0 1.0))
) ;_  append

;; My variant
(append
 (apply 'mapcar (cons 'list (append mat (list (trans (cdr (assoc 10 entData)) norm 0)))))
 (list '(0.0 0.0 0.0 1.0))
) ;_  append

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #17 on: February 06, 2007, 11:15:27 AM »
Thank you both.  I will look at these when my brain is ready for some real thinking.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #18 on: February 06, 2007, 11:22:27 AM »
Very nice Evgeniy, I keep it handy.
But it's not as easy to read than the other one and make it more difficult to understand how the matrix is built (transposed and appended).
« Last Edit: February 06, 2007, 11:35:43 AM by gile »
Speaking English as a French Frog

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #19 on: February 06, 2007, 11:38:52 AM »
Gile,

  YOURS WORKS PERFECT!! Now to study it and see where I messed up.  I think I know, I think it's the use of the 'trans'.  Thank you very much.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Transformation matrix vs Acads matrix
« Reply #20 on: February 06, 2007, 11:44:23 AM »
Very nice Evgeniy, I keep it handy.
But it's not as easy to read than the other one and make it more difficult to understand how the matrix is built (transposed and appended).

As (defun mxv .... or (defun mxm...  :-)

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #21 on: February 06, 2007, 12:17:41 PM »
You're welcome, Tim. Glad to give you a hand.

Quote
As (defun mxv .... or (defun mxm...
Very nice too, but not mine. Vladimir Nesterovsky wrote them.
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #22 on: February 07, 2007, 04:36:25 AM »
I loosed myself between 'nentsel' and 'nentselp' matrices.

Here's a more direct way to get the 4x4 matrix.

Code: [Select]
(defun Ename->4x4Matrix (ename / entData ang norm)
  (setq entData (entget ename)
ang (cdr (assoc 50 entData))
norm (cdr (assoc 210 entData))
  )
  (append
    (mapcar
      '(lambda (v1 v2)
(append v1 (list v2))
       )
      (mxm
  ;; WCS to OCS 3x3 matrix
  (mapcar '(lambda (v) (trans v 0 norm T))
  '((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
  )
(mxm
  ;; Z axis rotation 3x3 matrix
  (list (list (cos ang) (- (sin ang)) 0.0)
(list (sin ang) (cos ang) 0.0)
'(0.0 0.0 1.0)
  )
;; Scale 3x3 matrix
(list (list (cdr (assoc 41 entData)) 0.0 0.0)
      (list 0.0 (cdr (assoc 42 entData)) 0.0)
      (list 0.0 0.0 (cdr (assoc 43 entData)))
)
)
      )
      ;; Deplacement vector
      (trans (cdr (assoc 10 entData)) norm 0)
    )
    (list '(0.0 0.0 0.0 1.0))
  )
)
« Last Edit: February 07, 2007, 08:13:00 AM by gile »
Speaking English as a French Frog

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Transformation matrix vs Acads matrix
« Reply #23 on: February 07, 2007, 04:52:38 AM »
Excellent work gile!

Code: [Select]
(mxm
 ;; WCS to OCS 3x3 matrix
 (mapcar '(lambda (v) (trans v 0 norm T)) '((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0)))
 ;; Z axis rotation 3x3 matrix
 (list (list (cos ang) (- (sin ang)) 0.0) (list (sin ang) (cos ang) 0.0) '(0.0 0.0 1.0))
) ;_  mxm

I hope will be faster...

Code: [Select]
(append ;; WCS to OCS 3x3 matrix
        (mxm (mapcar '(lambda (v) (trans v 0 norm T)) '((1.0 0.0 0.0) (0.0 1.0 0.0)))
             ;; Z axis rotation 3x3 matrix
             (list (list (cos ang) (- (sin ang))) (list (sin ang) (cos ang)))
        ) ;_  mxm
        (list (trans '(0.0 0.0 1.0) 0 norm T))
) ;_  append

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #24 on: February 07, 2007, 06:45:51 AM »
Hi Evgeniy,

There's something wrong in your code, the result of this expression must be a 3x3 matrix.
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #25 on: February 07, 2007, 08:29:20 AM »
And another one to get the inverse transformation matrix.

This can also be done using 'ReverseMatrix' (the code have been corrected):
(ReverseMatrix (Ename->4x4Matrix ename)) returns the same result as (Ename->4x4ReverseMatrix ename)

Code: [Select]
;; Apply a transformation matrix to a vector by Vladimir Nesterovsky
;; Arguments: a matrix and a vector
;; Return : the vecor transformed by the matrix

(defun mxv (m v)
  (mapcar '(lambda (r) (apply '+ (mapcar '* r v))) m)
)

;; Multiply two matrices by Vladimir Nesterovsky
;; Arguments : two matrices
;; Return : the matrices combination
;; Attention : (mxm mat1 mat1) is not equal to (mxm mat2 mat1)
(defun mxm (m q)
  (mapcar '(lambda (r)
     (mapcar '(lambda (l) (apply '+ (mapcar '* l r)))
     (apply 'mapcar (cons 'list q))
     )
   )
  m
  )
)

(defun Ename->4x4ReverseMatrix (ename / entData ang norm mat)
  (setq entData (entget ename)
ang (- (cdr (assoc 50 entData)))
norm (cdr (assoc 210 entData))
  )
  (append
    (mapcar
      '(lambda (v1 v2)
(append v1 (list v2))
       )
      (setq mat
     (mxm
       ;; Scale 3x3 matrix
       (list (list (/ 1 (cdr (assoc 41 entData))) 0.0 0.0)
     (list 0.0 (/ 1 (cdr (assoc 42 entData))) 0.0)
     (list 0.0 0.0 (/ 1 (cdr (assoc 43 entData))))
       )
       (mxm
;; Z axis rotation 3x3 matrix
(list (list (cos ang) (- (sin ang)) 0.0)
       (list (sin ang) (cos ang) 0.0)
       '(0.0 0.0 1.0)
)
;; OCS to WCS 3x3 matrix
(mapcar '(lambda (v) (trans v norm 0 T))
'((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
)
       )
     )
      )
      ;; Deplacement vector
      (mapcar '-
      (mxv mat (trans (cdr (assoc 10 entData)) norm 0))
      )
    )
    (list '(0.0 0.0 0.0 1.0))
  )
)


Note: I just discover the Joe Burke's 'ObjMatrix V2', the first version worked only in 2D (Normal = 0.0,0.0,1.0).
Good job, Joe :-)
'ObjMatrix' and 'InverseObjMatrix' do the same as 'Ename->4x4Matrix' and 'Ename->4x4ReverseMatrix'.
« Last Edit: February 07, 2007, 10:07:19 AM by gile »
Speaking English as a French Frog

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Transformation matrix vs Acads matrix
« Reply #26 on: February 07, 2007, 10:46:03 AM »
Hi Evgeniy,

There's something wrong in your code, the result of this expression must be a 3x3 matrix.

Yes, my mistake!

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #27 on: February 07, 2007, 11:21:55 AM »
Gile,

 Thanks for all the examples.  I am able to follow them, which is a big surprise to me.  I guess I just don't understand how you knew what to do.  How did you know all you needed was the scale matrix (I know you need this one), and the z-rotation matrix (I know you need this one), but you don't need the y or x rotation matrices?  How did you know that you can just get the plan the object is on (OCS) and multiple that by the z-rotation matrix?  I will do a little more digging to try and understand these questions, and then I think I will be done with it.

Thanks again for all the code posted, I learned a lot! 
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #28 on: February 07, 2007, 03:25:52 PM »
You're welcome, Tim.

I'm going to try to answer you.
As I said, I began learning transformation matrix process with 'UCS2WCSMatrix' and 'WCS2UCSMatrix' from Doug Broad, and saw how they can be used to align objects from the WCS to the current UCS, for example. If the current UCS is rotated about the 3 axis the transformation matrix make the the object rotate about the 3 axis at one time.
I also try to understand more about OCS and 'trans' function. In the example done in this post, I tried to explain what is the rotation of a block reference (50 DXF code) and its OCS defined by its normal (210 DXF code).
So, transforming an object to an OCS with a transformation matrix is equal to make it rotate as the OCS is rotated about WCS X and Y axis, and the rotation (50 DXF code) of the object is only a rotation about the Z axis of the OCS.
Speaking English as a French Frog

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Transformation matrix vs Acads matrix
« Reply #29 on: February 07, 2007, 03:35:55 PM »
Thanks again Gile.  I have been busy with 'real' work, so I haven't had any time to try and find some answers.  I will look at the post you show when I get a moment.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Transformation matrix vs Acads matrix
« Reply #30 on: February 09, 2007, 08:40:25 AM »
To go a little further.

In ObjMatrixV2, Joe Burke gives a 'TransPt' function to transform a point coordinates from (or to) the coordinates system of the reference (block or xref, whatever its nested level) to (or from) the WCS (or UCS).
I made something similar here.

(transpt pt (last (nentselp)) 2 0)
returns the same as
(RCS2WCS pt (caddr (nentselp)))

and

(transpt pt (last (nentselp)) 0 2)
the same as
(WCS2RCS pt (caddr (nentselp)))

But the way to get these results is quite different. Perhaps, comparing the two methods should help to understand the way to work with transformation matrices.
Speaking English as a French Frog

Joe Burke

  • Guest
Re: Transformation matrix vs Acads matrix
« Reply #31 on: February 09, 2007, 10:56:08 AM »
Thanks Joe.

I still haven't got it working the way I want it to.  I now have a better understand of the 'normal' and I can tell, when looking at the numbers, where it is being looked at from, but I can't seem to code it correctly.  I have spent a couple days, off and on, on it, and still am lost.  This is driving me crazy.  :ugly:

Hi Tim,

Forgive me, but I can't find much sympathy for, "I have spent a couple days... and still am lost." :-)

I have no idea how many hours I spent on the ObjMatrix functions, other than I revised them many times over a period of about three years.

Was it worth it? Yes, no question.

And I'm not forgetting you helped me with that puzzle John Uhden posed. The origin of a block definition not at 0,0,0. Which prompted another revsion of the code.

I applaud your effort to understand the nuts and bolts.

I tried to design my code so someone could use it without understanding how it works. But in the end and like anything else, somone who understands the ideas behind it will put it to better use.

Regards