Author Topic: Transformation matrix vs Acads matrix  (Read 15670 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.