Jump to content

4x4 transformation matrix


Alex_Miller

Recommended Posts

Greetings.

The region is drawn in ModelSpace as a rectangle with sides 500 and 300.

(command "_.rectangle" '(100.0 100.0 0.0) '(600.0 400.0 0.0))
(setq entity (entlast))
(command "_.region" entity "")
(setq entity (entlast))

Its position in the WCS will be expressed by two points and a normal vector.
The second point is relative to the first.

(regapp "PositionWCS")

;; some manipulation

;; initial data assigned to region
(-3 ("PositionWCS" (1011 100.0 100.0 0.0) (1012 500.0 0.0 0.0) (1013 0 0 1)))

Now I move and rotate the region with the commands move and rotate.
The region takes a new position in the WCS. Its values in Xdata have changed.

For example:
(-3 ("PositionWCS" (1011 1100.0 1100.0 500.0) (1012 500.0 0.0 0.0) (1013 0 -1 0)))
or:
(-3 ("PositionWCS" (1011 -400.0 100.0 -600.0) (1012 0.0 -500.0 0.0) (1013 1 0 0)))

I would like to create a function that creates a transformation matrix for a region from the original position to the new one.

Command:
_$ (CreateMatrix4x4 
     '(100.0 100.0 0.0) '(500.0 0.0 0.0) '(0 0 1) 
		 '(-400.0 100.0 -600.0) '(0.0 -500.0 0.0) '(1 0 0) )

The result:
((n1 n2 n3 n4) (n5 n6 n7 n8) (n9 n10 n11 n12) (n13 n14 n15 n16))

To be able to apply the method:

(setq obj (vlax-ename->vla-object entity))
(vla-TransformBy obj matrix)

Help me with a solution so I don’t have to sit on this problem for unknown amount of time?

Link to comment
Share on other sites

I may be totally misunderstanding the question, but it sounds like what they do in Blender with matrix algebra. To apply successive transformations, they simply multiply (dot product) each one by the next. The only caveat is to apply them in the correct order.

 

If that doesn't help, please elaborate.

  • Like 1
Link to comment
Share on other sites

Essentially you need to obtain three orthogonal vectors representing the transformation from the first set of points to the second set of points - such vectors will then form the columns of the 3x3 upper-left component of your transformation matrix. You would then apply such matrix to your original point and calculate the difference from the target point - such difference is the translation vector of your 4x4 matrix. Google 'change of basis matrix' for more information on this subject.

  • Like 1
Link to comment
Share on other sites

Still not working as it should, problem with the axes.

(defun CreateMatrix4x4 (wcp wsd normal wcpNew wsdNew normalNew / 
                            dot-product cross-product normalize matrix-multiply Acos
                            translation-vector theta axis x y z cosT sinT R TT M)

  ;; Scalar product.
	(defun dot-product (u v) 
	  (apply '+ (mapcar '* u v)))
  
  ;; Vector product.
  (defun cross-product (v1 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)))))
  
  ;; To normalize a vector.
  (defun normalize (v)
    (setq len (sqrt (dot-product v v)))
    (mapcar '(lambda (x) (/ x len)) v))
  
  (defun matrix-multiply (a b)
    (mapcar
      '(lambda (row)
         (mapcar
           '(lambda (col)
              (apply '+ (mapcar '* row col)))
           (apply 'mapcar (cons 'list b)))) a))

	;; Arccosine of the number.
	(defun Acos (x) 
	  (if (<= -1. x 1.) 
		  (atan (sqrt (- 1. (* x x))) x)))

;;; Routine

  ;; axis of rotation.
	;; TODO: several rotate axis. 
  (setq axis (cross-product (normalize wsd) (normalize wsdNew)))
  (setq x (nth 0 axis)
        y (nth 1 axis)
        z (nth 2 axis))
				
  ;; rotation angle in radians
  (setq theta (acos (dot-product normal normalNew)))
  
  ;; cosine and sine of an angle
  (setq cosT (cos theta)
        sinT (sin theta))
  
  ;; Creating a rotation matrix
  (setq R
    (list
      (list (+ cosT (* (- 1 cosT) (* x x)))
			      (- (* (- 1 cosT) (* x y)) (* sinT z))
						(+ (* (- 1 cosT) (* x z)) (* sinT y))
						0)
      (list (+ (* (- 1 cosT) (* y x)) (* sinT z))
			      (+ cosT (* (- 1 cosT) (* y y)))
						(- (* (- 1 cosT) (* y z)) (* sinT x))
						0)
      (list (- (* (- 1 cosT) (* z x)) (* sinT y))
			      (+ (* (- 1 cosT) (* z y)) (* sinT x))
						(+ cosT (* (- 1 cosT) (* z z)))
						0)
      (list 0 0 0 1)))

  ;; displacement vector
  (setq translation-vector (mapcar '- wcpNew wcp))
  
  ;; Creating a displacement matrix
  (setq TT
    (list
      (list 1 0 0 (nth 0 translation-vector))
      (list 0 1 0 (nth 1 translation-vector))
      (list 0 0 1 (nth 2 translation-vector))
      (list 0 0 0 1)))
  
  ;; Combining the translation and rotation matrices
  (setq M (matrix-multiply TT R))

  ;; matrix result 
  M)
;; Command:
_$ (CreateMatrix4x4 '(0. 0. 0.) '(500. 0. 0.) '(0 0 1) '(1500. 1500. 0.) '(0. -500. 0.) '(-1. 0. 0.))

The call should return the correct matrix, here it is:

(setq matrix '(
( 0.0 0.0 -1.0 1500.0) 
(-1.0 0.0  0.0 1500.0) 
( 0.0 1.0  0.0 0.0) 
( 0.0 0.0  0.0 1.0)
))

Could somebody tell me how to make that part where the axes are?

Link to comment
Share on other sites

 "I would like to create a function that creates a transformation matrix for a region from the original position to the new one."

 

Essentially is this what you have and you want to solve for T?

T_original * T = T_new

 

If so,

 

T = T_new * (inverse T_orignal)

 

  • Like 1
  • Agree 1
Link to comment
Share on other sites

  • 2 weeks later...

Let's consider it solved.
There are several solutions though.

(defun Get1011 (entity)
  (cdr (assoc 1011 (cdadr (assoc -3 (entget entity '("PositionWCS")))))))

(defun Get1012 (entity)
  (cdr (assoc 1012 (cdadr (assoc -3 (entget entity '("PositionWCS")))))))

(defun Get1013 (entity)
  (cdr (assoc 1013 (cdadr (assoc -3 (entget entity '("PositionWCS")))))))

(defun DotProduct (u v) 
  (apply '+ (mapcar '* u v)))
		
(defun Normalize (v / len)
  (setq len (sqrt (DotProduct v v)))
  (mapcar '(lambda (x) (/ x len)) v))

(defun CrossProduct (v1 v2)
  (list
    (- (* (nth 1 v1) (nth 2 v2)) (* (nth 2 v1) (nth 1 v2)))
    (- (* (nth 2 v1) (nth 0 v2)) (* (nth 0 v1) (nth 2 v2)))
    (- (* (nth 0 v1) (nth 1 v2)) (* (nth 1 v1) (nth 0 v2)))))

(defun Transpose (matrix) 
  (apply 'mapcar (cons 'list matrix)))

(setq entity (car (entsel "\nSelect: ")))
	
(setq origin (Get1011 entity))
; (1500.0 1500.0 0.0)

(setq xvector (Normalize (Get1012 entity)))
; (0.0 -1.0 0.0)

(setq yvector (CrossProduct (Get1013 entity) xvector))
; (0.0 0.0 1.0)

(setq zvector (Get1013 entity))
; (-1.0 0.0 0.0)

(setq M (Transpose (list xvector yvector zvector)))

;; Multiply. [simplified]
(setq mlist
  (list 
    (append (nth 0 M) (list (nth 0 origin)))
    (append (nth 1 M) (list (nth 1 origin)))
    (append (nth 2 M) (list (nth 2 origin)))
    '(0. 0. 0. 1.)))

;; achieved
(setq matrix (vlax-tmatrix mlist))

;; Test.
(setq mS (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-acad-object)))
      center (vlax-3d-point 10 10 0)
      radius 100.
      circleObj (vla-AddCircle mS center radius))

(vla-TransformBy circleObj matrix)

The End.

Math.jpg

Math2.jpg

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...