Alex_Miller Posted June 11 Posted June 11 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? Quote
CyberAngel Posted June 11 Posted June 11 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. 1 Quote
Lee Mac Posted June 11 Posted June 11 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. 1 Quote
Alex_Miller Posted June 13 Author Posted June 13 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? Quote
lrm Posted June 14 Posted June 14 "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) 1 1 Quote
Alex_Miller Posted June 26 Author Posted June 26 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. Quote
Recommended Posts
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.