## 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’s`PositionMatrix`

; more specifically, the VPMInstance `PositionMatrix`

.

### Instance Position Vs Occurrence Position

A Physical Product`Reference`

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: EKL, Linear Algebra, Physical Product
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

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.