Author Topic: Matrix question  (Read 2926 times)

0 Members and 1 Guest are viewing this topic.

wizman

  • Bull Frog
  • Posts: 228
Matrix question
« on: March 31, 2009, 10:20:57 AM »
hi guys, im just studying transformation matrix but i was stumped on this vast topic, i understood all the blue items below but the red ones im not able to derive when rotation is not on world x, y z axis, thank you in advance.



Rotation Matrix: 45 degrees about point (5, 5, 0)

0.707107   -0.707107   0.0   5.0
 
0.707107    0.707107   0.0    -2.071068
 
0.0            0.0           1.0    0.0
 
0.0            0.0           0.0     1.0


gile

  • Water Moccasin
  • Posts: 2233
  • Marseille, France
Re: Matrix question
« Reply #1 on: March 31, 2009, 11:27:34 AM »
Hi,

A 4x4 transformation matrix countains :
- the 3x3 upper left matrix (rotations and scalings)
- the 4th column but last item is the translation vector (displacement of origin)
- the 4th row, always 0.0 0.0 0.0 1.0 is to make the matrix square

Example: applying your matrix to a line which start point is (20.0 20.0 0.0) and end point is (80.0 50.0 0.0) in WCS coordinates.
The new coordinates of the rotated line are : (5.0 26.2132 0.0) (26.2132 89.8528 0.0).
Now, if you create a new UCS moving the origin to (5.0 -2.071068 0.0) and rotating 45° on Z axis, the coordinates of the line in this UCS are (20.0 20.0 0.0) and (80.0 50.0 0.0).

When using matrices with AutoLISP, I'd rather first deal with separated rotation (sclaing) 3x3 matrices and translation vectors, and then build the 4x4 matrix (if needed).
To calculate the translation vector about a rotation matrix (for example) and a rotation base point, You can apply the 3x3 matrix to the vector from origin (0,0,0) to the base point.

Example to construct your 4x4 matrix:
Code: [Select]
;; Build the 3x3 rotation matrix
(setq 3x3Matrix (list (list (cos ang) (- (sin ang)) 0.0)
      (list (sin ang) (cos ang) 0.0)
      '(0.0 0.0 1.0)
)
      )

;; Calculate the translation vector
(setq translation (mapcar '- BasePoint (mxv 3x3Matrix BasePoint)))

;; Build the 4x4 matrix
(setq 4x4Matrix (append
  (mapcar '(lambda (v x) (append v (list x)))
  3x3Matrix
  translation
  )
  (list '(0.0 0.0 0.0 1.0))
)
)

The upper example uses the mxv function wich is, IMO, one of the three most usefull routines to play with matrices:
Code: [Select]
;; TRP Transpose a matrix -Doug Wilson-
(defun trp (m)
  (apply 'mapcar (cons 'list m))
)

;; MXV Apply a transformation matrix to a vector -Vladimir Nesterovsky-
(defun mxv (m v)
  (mapcar '(lambda (r) (apply '+ (mapcar '* r v))) m)
)

;; MXM Multiply two matrices -Vladimir Nesterovsky-
(defun mxm (m q)
  (mapcar '(lambda (r) (mxv (trp q) r)) m)
)

« Last Edit: March 31, 2009, 11:30:42 AM by gile »
Speaking English as a French Frog

wizman

  • Bull Frog
  • Posts: 228
Re: Matrix question
« Reply #2 on: March 31, 2009, 03:18:15 PM »
Thank you very much gile for your quick reply, its a big help for me sir, i will study it for today and tomorrow, i'll let you know if i understood it correctly.

wizman

  • Bull Frog
  • Posts: 228
Re: Matrix question
« Reply #3 on: March 31, 2009, 04:56:52 PM »

Code: [Select]
(setq lineobj (vlax-ename->vla-object (car (entsel))))

;; MXV Apply a transformation matrix to a vector -Vladimir Nesterovsky-
(defun mxv (m v)
  (mapcar '(lambda (r) (apply '+ (mapcar '* r v))) m)
)


;; Build the 3x3 rotation matrix
(setq ang (/ pi 4))
(setq 3x3Matrix (list (list (cos ang) (- (sin ang)) 0.0)
      (list (sin ang) (cos ang) 0.0)
      '(0.0 0.0 1.0)
)
      )
;;;;=>
;;;((0.707107 -0.707107 0.0) (0.707107 0.707107 0.0) (0.0 0.0 1.0))


;; Calculate the translation vector
(setq BasePoint '(5. 5. 0.))
(setq translation (mapcar '- BasePoint (mxv 3x3Matrix BasePoint)))
;;;;=>
;;;(5.0 -2.07107 0.0)


;; Build the 4x4 matrix
(setq 4x4Matrix (append
  (mapcar '(lambda (v x) (append v (list x)))
  3x3Matrix
  translation
  )
  (list '(0.0 0.0 0.0 1.0))
)
)
;;;;=>
;;;((0.707107 -0.707107 0.0 5.0) (0.707107 0.707107 0.0 -2.07107) (0.0 0.0 1.0 0.0) (0.0 0.0 0.0 1.0))


;;; Use vlax-tmatrix to convert the list to a variant.

 (setq transmat (vlax-tmatrix 4x4Matrix))

;;; Transform the line using the defined transformation matrix

 (vla-transformby lineObj transMat)


above is working clearly and well thanks to you gile, just one very minor issue, why is it when i replace the 4x4matrix above with the one below im having an error due to non uniform scale:


Code: [Select]
(setq 4x4Matrix '((0.707107 -0.707107 0.0 5.0)(0.707107 0.707107 0.0 -2.07107) (0.0 0.0 1.0 0.0)(0.0 0.0 0.0 1.0 )))

gile

  • Water Moccasin
  • Posts: 2233
  • Marseille, France
Re: Matrix question
« Reply #4 on: April 01, 2009, 03:03:47 AM »
This is due to the fact 0.707107 is a rounded value of (sin (/ pi 4)) or (cos (/ pi 4)), and the vla-transformby function needs much more accuracy.

In an uniform scale matrix, all the row vectors (and column vectors too) of the 3x3 matrix must have the same lengthes.

In your example, the 3x3 last row is (0.0 0.0 1.0), its length is equal to 1.0, if you try to compare distances:

with rounded values:
(= 1.0 (distance '(0.0 0.0 0.0) '(0.707107 0.707107 0.0)))
it returns nil

with calculated values:
(= 1.0 (distance '(0.0 0.0 0.0) (list (sin (/ pi 4)) (cos (/ pi 4)) 0.0)))
it returns T

PS: The vla-TransformBy function certainly use a tolerance when comparing vector lengthes (as the `=' have to do), but as far as the tests I did show it to me, this tolerance seems to be very closed to the one used by the `=' function (around 1e-016).
« Last Edit: April 01, 2009, 04:30:01 AM by gile »
Speaking English as a French Frog

wizman

  • Bull Frog
  • Posts: 228
Re: Matrix question
« Reply #5 on: April 01, 2009, 05:14:19 AM »
Thank you very much for you help sir,much appreciated, i'll continue studying it deeper. More power to you