Transformation Matrix

I am trying to wrap my head around the transformation matrix in Rhino Python, and was wondering if there was something out there that listed what each item in the matrix controls. For instance scale, rotation, position. Looking through the help this is as close as I got to the structure,but don’t know what each value controls.

Thanks

Hi DJNelson,

I never got my head around matices, yet I know Rajaa has a full chapter about matrices and transformations. Find and download it here:

screenshot:

HTH
-Willem

2 Likes

Thanks. Looking through it right now. More specially my question is really about finding out what transformations have been done to a block.

What type are you specifically looking for is I may ask?

-Willem

Ultimate Goal: I want to click on a block and find out what transformations have been done to it so I can set them to different values if needed.

So through some basic messing I think I figured out where the scale and position entries are. Now I just need to figure out what the rest of the boxes(entries) corollate to. I assume a rotation vector is in there somewhere, but could be wrong. Also not sure what the last row is for.

@rajaa any insight you have would be helpful.

The Rhino SDK does not contain functions that will decompose a transformation matrix into it’s individual components (e.g. scale, rotation, translation). If you Google the topic, you will probably find lots if information on the subject. Just keep in mind that there is no perfect solution for this, as you will find in your research.

Thanks @dale, just so I understand when I insert a block into Rhino with postion(x,y,z) a scale(x,y,z) and a rotation angle there is no way for me to retrieve it later on???

I guess I need read up on transformation matrix, but I assume it just a matrix that was storing these values and that I could extract a value like position x, and enter a new value for it.

As it seems like the examples I have seen for transformation matrix is say you have matrix of all the points on a cube and you want to move the cube, you could multiple the matrix of the points with the move vector matrix and get the resulting new points for the cube. So I not sure how that equates to properties needed to input a block into Rhino.

There is no perfect way. For example, certain scale operations rotation operations can cause the scale and rotation components of the transform will become mixed.

Here are a couple of sample routines I wrote some time ago. They are fairly rudimentary. If you know that your transform only has particular types of component transforms inside it and if you’re willing to accept the fact that you won’t get an exact version of those transforms back after decomposition, they might work for you.

Thanks I will take a look.

Blockquote[quote=“dale, post:8, topic:3446”]
certain scale operations rotation operations can cause the scale and rotation components of the transform will become mixed.
[/quote]

I see that now after reading up on affine transformations.

I came across the source code in Three.js.
In theri Matrix4 Object, they have a function to compose and decompose a matrix from translation, rotation and scale.

.compose ( translation, quaternion, scale ) this
Sets this matrix to the transformation composed of translation, quaternion and scale.

.decompose ( translation, quaternion, scale )
Decomposes this matrix into the translation, quaternion and scale components.

I’ll paste it here since it’s not too long:

decompose: function () {

		var vector, matrix;

		return function ( position, quaternion, scale ) {

			if ( vector === undefined ) vector = new THREE.Vector3();
			if ( matrix === undefined ) matrix = new THREE.Matrix4();

			var te = this.elements;

			var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
			var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
			var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();

			// if determine is negative, we need to invert one scale
			var det = this.determinant();
			if ( det < 0 ) {

				sx = - sx;

			}

			position.x = te[ 12 ];
			position.y = te[ 13 ];
			position.z = te[ 14 ];

			// scale the rotation part

			matrix.elements.set( this.elements ); // at this point matrix is incomplete so we can't use .copy()

			var invSX = 1 / sx;
			var invSY = 1 / sy;
			var invSZ = 1 / sz;

			matrix.elements[ 0 ] *= invSX;
			matrix.elements[ 1 ] *= invSX;
			matrix.elements[ 2 ] *= invSX;

			matrix.elements[ 4 ] *= invSY;
			matrix.elements[ 5 ] *= invSY;
			matrix.elements[ 6 ] *= invSY;

			matrix.elements[ 8 ] *= invSZ;
			matrix.elements[ 9 ] *= invSZ;
			matrix.elements[ 10 ] *= invSZ;

			quaternion.setFromRotationMatrix( matrix );

			scale.x = sx;
			scale.y = sy;
			scale.z = sz;

			return this;

		};

	}(),
1 Like

I’m new to scripting and I’ve found myself in the deep end.

I am trying to find the size of a block. If I use bounding box, the size is incorrect because of its rotation and location in 3Dspace. So my new approach is to use the Transformation Matrix to decompose the Block so that it is back at F4 (where the original block instance started). Then I was hoping to use Bounding Box to get an accurate size.

I am very thankful to find Dales script. When I run the script I am prompted to pick the block. In an attempt to bypass the command line I altered the script to select the block by Object Type. But I get an error (I think because it picks all the blocks in the file instead of one).

Next, I’m unsure whether I can directly use the resulting coordinates to move/scale/rotate back into place. Or do I need to export the coordinates to an excel then call to them to move,scale,rotate.

Im attaching the altered script attempt.

J

MatrixTransformationQuestion.txt (5.8 KB)

J,

you may try a simpler approach:

  • get block xform matrix by GetBlockInstanceXform
  • use PlaneTransform with Rhino.WorldXY source plane and above matrix
  • Use Rhino.BoundingBox with arrPlane (above transformed plane) as you boundingbox plane.

the bbox dimensions should be aligned to your block plane.

hth,

–jarek

1 Like

Simple is better! Thanks.

I’m really new to scripting. I tried to follow your instructions, but I appear to be putting the bbox on the block in 3d space as opposed to using the rhino.worldXY source. Here is the edit i made. Can you advise what I’m doing wrong?

       If Rhino.IsBlockInstance(strObject) Then
			arrMatrix = Rhino.BlockInstanceXform(strObject)
			
			If IsArray(arrMatrix) Then
			
				arrBlockPlane = Rhino.PlaneTransform(Rhino.WorldXYPlane(), arrMatrix)
			
				If IsArray(arrBlockPlane) Then
				
					Dim box
					box = rhino.BoundingBox(strObject)

					Dim distX, distY, distZ
					distX = rhino.Distance(box(0), box(1))
					distY = rhino.Distance(box(0), box(3))
					distZ = rhino.Distance(box(0), box(4))
		
					xlApp.Cells(intCount + 2, 10).Value = round(distX, 2)
					xlApp.Cells(intCount + 2, 11).Value = round(distY, 2)
					xlApp.Cells(intCount + 2, 12).Value = round(distZ, 2)
				
				End If
				
				
			End If
			
			
		End If

Can’t test the script now but seems like the problem is you need to feed the xformed plane to bbox method:

box = rhino.BoundingBox(strObject, arrBlockPlane)

hth,

jarek

Totally worked. Thanks so much!

J

Hi Willem

Sent me a high quality image for this…

-Sarath

Hi @Sarath_Kithiyon,

You can download the guide, in PDF form, from here.

– Dale

There’s also this later edition:

http://www.rhino3d.com/download/Rhino/5.0/EssentialMathematicsThirdEdition