I showed earlier how to extract origin-coordinates and rotation-angles from Axis Systems’ components. Atsushi followed with a post on working with vectors and I recently showed how to perform Axis To Axis transformations on geometric features. Today I’ll focus on Physical Product’s
PositionMatrix; more specifically, the VPMInstance
Instance Position Vs Occurrence Position
A Physical Product
Reference can have multiple
Occurrences within an assembly. An
Instance is defined in terms of its Parent
Reference, and an
Occurrence is defined in terms of the assembly root. It is like asking "How many times does a Reference occur under a root?".
Following the notions of
Occurrence, Physical Products have two Position Matrices:
- Instance position defined in terms of its Parent. We get this from the
VPMInstance. This is a read/write matrix–granted you provide a valid matrix. For example, an all-zero matrix isn’t valid.
- Occurrence position defined in terms of the assembly root, globally. We get this from the
ProductOccurrence. This is a read-only matrix.
This is how we can query both positions using EKL:
//inputs: Occurrence: ProductOccurrence //define two matrixes let occurrencePosition, instancePosition (Matrix) //cast the ProductOccurrence as a VPMInstance for global position occurrencePosition =(Occurrence:VPMInstance).PositionMatrix //get the Instance object from the Occurrence and take its Position Matrix instancePosition = (Occurrence.Instance:VPMInstance).PositionMatrix //let's dump each matrix (convert it to a string) and notify it on screen Notify("Global Occurrence Position From Root:|#|" , occurrencePosition.Dump()) Notify("Local Instance Position From Parent:|#|", instancePosition.Dump())
The Position Matrix Components
PositionMatrix of Physical Products is composed of three rows and four columns:
//inputs: instance: VPMInstance let posMatrix(Matrix) posMatrix = instance.PositionMatrix Notify("rows: #," posMatrix.NbLine) Notify("columns: #", posMatrix.NbCol)
The PositionMatrix looks like this:
r11, r12, r13, r14 r21, r22, r23, r24 r31, r32, r33, r34
Columns 1, 2, and 3 hold information relating to rotations.
r11 | r21 | r31 r12 | r22 | r32 r13 | r23 | r33
The last column represents the x,y,z position.
r14 r24 r34
Reading The Instance Position Matrix
Let’s read the position matrix of
Physical Product Instance:
Here is the code:
//inputs: instance: VPMInstance. //get position matrix from the instance let posMatrix(Matrix) posMatrix =instance.PositionMatrix //get the matrix components let r11, r12, r13, r21, r22, r23, r31, r32, r33, r14, r24, r34(Real) r11 = posMatrix.Get(1,1) r12 = posMatrix.Get(1,2) r13 = posMatrix.Get(1,3) r14 = posMatrix.Get(1,4) r21 = posMatrix.Get(2,1) r22 = posMatrix.Get(2,2) r23 = posMatrix.Get(2,3) r24 = posMatrix.Get(2,4) r31 = posMatrix.Get(3,1) r32 = posMatrix.Get(3,2) r33 = posMatrix.Get(3,3) r34 = posMatrix.Get(3,4) //get the rotations let ZRotation(Angle) let XRotation(Angle) let YRotation(Angle) ZRotation = atan( r21/r11 ) YRotation = atan2(-r31, sqrt( r32**2 + r33**2 )) XRotation = atan(r32/r33) //the double asterisk is EKL's syntax for to the power of. So 5**2 is 5 x 5 //get the origin let XPos, YPos, ZPos(Length) XPos =r14*1mm YPos =r24*1mm ZPos =r34*1mm //notify to the screen Notify("X Pos ", XPos) Notify("Y Pos ", YPos) Notify("Z Pos ", ZPos) Notify("X Rotation ", XRotation) Notify("Y Rotation ", YRotation) Notify("Z Rotation ", ZRotation)
The same code, above, can be also used to read a ProductOccurrence’s
PositionMatrix since it is also a 3×4 matrix. You could simply make an custom Function that takes in a Matrix object as input and returns the above measurements.
Here are a few ways we can create Matrices with EKL:
//From String let mat1(Matrix) mat1 =MatrixFromString([1,0,0,0; 0,1,0,0; 0,0,1,0]) Notify( mat1.Dump()) //in line let mat2(Matrix) mat2 = [1,0,0,0; 0,1,0,0; 0,0,1,0] Notify( mat2.Dump()) //using the Matrix constructor //create a matrix of 3 rows, 4 columns, with initial values set to zero (for all components) let mat3(Matrix) mat3 = Matrix(3, 4, 0) Notify( mat3.Dump())
There are EKL other functions that return matrices. For example,
TransformationMatrix. It is also possible to perform arithmetic operations on matrices.
Using The PositionMatrix Information
We can use the above matrix information to determine distances, or differences in rotation angles. Here is an example that measures the distance using two Position Matrices:
Here is the code:
//inputs: FirstInstance: VPMInstance, SecondInstance: VPMInstance let posMatrix1(Matrix) posMatrix1 =FirstInstance.PositionMatrix //the position information is at the 4th column in the matrix let x1, y1, z1(Real) x1 = posMatrix1.Get(1,4) y1 = posMatrix1.Get(2,4) z1 = posMatrix1.Get(3,4) let posMatrix2(Matrix) posMatrix2 =SecondInstance.PositionMatrix let x2, y2, z2(Real) x2 = posMatrix2.Get(1,4) y2 = posMatrix2.Get(2,4) z2 = posMatrix2.Get(3,4) //let's calculate the distance given xyz of each physical product let dist(Length) dist = sqrt( (x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2 )*1mm Notify( "Distance between # and # is #", FirstInstance.Name, SecondInstance.Name, dist)
The above measured distance is defined in terms of Instance Position matrices, which might not be the actual distance globally under an assembly root. For that, we’ll need to use the Occurrence Position.
Setting The Position Matrix
You can set the
PositionMatrix to a matching 3×4 matrix; or a minimum of 3×3, at which case the last column will be 0,0,0. The matrix has to be a valid one. For example, it can’t be all zeros.
Here is an example for setting the Instance
PositionMatrix of a Physical Product to that of another:
We can also set it to an identity matrix:
Here is the code for creating an identity matrix. Here, I used a 3×3, or a 4 x4.
//inputs: instance: VPMInstance Notify("Before |#", instance.PositionMatrix.Dump()) let identity(Matrix) //this is a square matrix. made 3x3. identity = MatrixIdent(3) instance.PositionMatrix =identity Notify("After |#", instance.PositionMatrix.Dump())
Set A Physical Product\’s Position And Rotations
Let’s set the position and rotations of a Physical Product Instance to the following:
- 10 degrees around X axis
- 20 degrees around Y axis
- 30 degrees around Z axis
- 10mm in the X direction
- 20mm in the Y direction
- 30mm in the Z direction
Here is the code used in the above video:
//inputs: instance: VPMInstance let x= 10 let y = 20 let z = 30 //rotation angles: A around X, B around Y, C around Z. let A, B, C(Angle) A = 10deg B = 20deg C = 30deg //rotation matrix for x axis let Rx(Matrix) Rx= Matrix(3,3,0) //first row Rx.Set(1,1, 1) Rx.Set(1,2, 0) Rx.Set(1,3, 0) //second row Rx.Set(2,1, 0) Rx.Set(2,2, cos(A)) Rx.Set(2,3, -sin(A)) //third row Rx.Set(3,1, 0) Rx.Set(3,2, sin(A)) Rx.Set(3,3,cos(A)) //rotation matrix for y axis let Ry(Matrix) Ry= Matrix(3,3,0) //first row Ry.Set(1,1, cos(-B)) Ry.Set(1,2, 0) Ry.Set(1,3, sin(-B)) //second row Ry.Set(2,1, 0) Ry.Set(2,2, 1) Ry.Set(2,3, 0) //third row Ry.Set(3,1, -sin(-B)) Ry.Set(3,2, 0) Ry.Set(3,3, cos(-B)) //rotation matrix for z axis let Rz(Matrix) Rz= Matrix(3,3,0) //first row Rz.Set(1,1, cos(C)) Rz.Set(1,2, -sin(C)) Rz.Set(1,3, 0) //second row Rz.Set(2,1, sin(C)) Rz.Set(2,2, cos(C)) Rz.Set(2,3, 0) //third row Rz.Set(3,1, 0) Rz.Set(3,2, 0) Rz.Set(3,3, 1) //multiple matrices to get the compound rotation in the following sequence let r(Matrix) r =((Rz* Ry.Transpose())*Rx) //compose a new matrix including the above and add the position as a 4th column. let t(Matrix) t = Matrix(3, 4, 0) t.Set(1,1, r.Get(1,1)) t.Set(1,2, r.Get(1,2)) t.Set(1,3, r.Get(1,3)) t.Set(1,4, x) t.Set(2,1, r.Get(2,1)) t.Set(2,2, r.Get(2,2)) t.Set(2,3, r.Get(2,3)) t.Set(2,4, y) t.Set(3,1, r.Get(3,1)) t.Set(3,2, r.Get(3,2)) t.Set(3,3, r.Get(3,3)) t.Set(3,4, z) //set position matrix Instance.PositionMatrix= t
In the next post, I’ll cover examples that take the Occurrence PositionMatrix into consideration.Tags: EKL, Linear Algebra, Physical Product