2 Sep, 2019

## The Physical Product PositionMatrix

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’sPositionMatrix; more specifically, the VPMInstance PositionMatrix.

### Instance Position Vs Occurrence Position

A Physical ProductReference can have multiple Instances and 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 Instance and 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

The 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.

### Creating Matrices

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, Determinant and 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:

toMove.PositionMatrix= toMatch.PositionMatrix

Like this:

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: , ,

Maher Elkhaldi is a senior applications engineer at Tesla Motors. He founded the 3DXAutomation blog to help make knowledge of programming CATIA easier to find, and contribute to the open-source community.

## 2 thoughts on “The Physical Product PositionMatrix”

1. Eric says:

To simply view a matrix with Notify you can do

Notify (myMatrix.Dump())

the output will be:

1000
0100
0010

For another view of the matrix you can ask for

SplitString( Regex(“/[|]”)->Replace(“” ,myMatrix.ToString(),-1) , “;”).Apply (“String”, “Notify (ReplaceAll(x,\”,\”,\” , \”))”)

the output will be:

1 , 0 , 0 , 0
0 , 1 , 0 , 0
0 , 0 , 1 , 0

Explanation:

myMatrix.ToString() will return the string “[1,0,0,0;0,1,0,0;0,0,1,0]”

Regex(“/[|]”)->Replace(“” ,myMatrix.ToString(),-1) will remove [ and ] from the string so result = “1,0,0,0;0,1,0,0;0,0,1,0”

SplitString (Regex… , “;” ) will return a list from the string split at ; so result is a list (“1,0,0,0” , “0,1,0,0” , “0,0,1,0” )

Finally the list->Apply (“String”, “Notify (ReplaceAll(x,\”,\”,\” , \”))”) will Notify each String of the list replacing “,” (coma) with ” , ” (space coma space) for visibility

1. Great addition, Eric! I got lazy about formatting the string returned from the Dump() method. This should make the result easier to view for users.

This site uses Akismet to reduce spam. Learn how your comment data is processed.