# GetNthControlPointOrientationMatrix : How should we consider it?

**URL:** <https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131>\
**Category:** Support\
**Created:** [December 18, 2021, 6:26pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131 "2021-12-18T18:26:58Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)\
**Post date:** [December 18, 2021, 6:26pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/1 "2021-12-18T18:26:58Z")

</div>

A markups fiducial node has this function : GetNthControlPointOrientationMatrix.

While tinkering with it, it does not get modified if a transform is applied to the fiducial node, nor if it is placed in a reformatted slice view. If we modify this matrix with SetNthControlPointOrientationMatrix, the applied matrix is always retrieved unaltered.

Is it only a storage place intended for developers ?  
Would the markups internals require/modifiy it ? In what circumstances?

Thanks for any input.

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [December 18, 2021, 6:45pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/2 "2021-12-18T18:45:28Z")

</div>

Please try this:

```auto
orientationMatrix = vtk.vtkMatrix3x3()
getNode('F').GetNthControlPointOrientationMatrix(0,matrix)
#should be the identity
print(matrix)

matrix.SetElement(1,1,-1)
matrix.SetElement(2,2,-1)
#matrix has changed
print(matrix)

#change the orientationMatrix by our changed matrix
getNode('F').SetNthControlPointOrientationMatrix(0,matrix)

#read the new orientationMatrix value, it should not be the identity
matrix2 = vtk.vtkMatrix3x3()
getNode('F').GetNthControlPointOrientationMatrix(0,matrix2)
print(matrix2)

#It's okey

```

---

<div class="post-metadata">

**Author:** ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)\
**Post date:** [December 18, 2021, 7:10pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/3 "2021-12-18T19:10:51Z")

</div>

It’s very clear, thank you.

But is it only a storage place ? If we modify it, how would it affect the fiducial node or a slice node ? I mean, does Slicer rely on it to do something ? Can we just store here an orientation matrix parameter that we would be needing later ?

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [December 18, 2021, 7:17pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/4 "2021-12-18T19:17:12Z")

</div>

> [@chir.set](#):
>
> But is it only a storage place ? If we modify it, how would it affect the fiducial node or a slice node ? I mean, does Slicer rely on it to do something ? Can we just store here an orientation matrix parameter that we would be needing later ?

I think it should work as storage for markups for what I have seen on a fast search through the C++ code. I don’t know about sliceNodes.

Yes I think you can save here an orientationMatrix that you would be needing later

---

<div class="post-metadata">

**Author:** ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)\
**Post date:** [December 18, 2021, 7:20pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/5 "2021-12-18T19:20:33Z")

</div>

> [@mau\_igna\_06](#):
>
> Yes I think you can save here an orientationMatrix that you would be needing later

That would simplify things a lot, thank you.

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [December 18, 2021, 7:27pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/6 "2021-12-18T19:27:17Z")

</div>

Fiducial orientations are a holdover from the original implementation in slicer2 - many of the coolest features of Delphine’s original work have never been ported to later slicer versions.

[http://dspace.mit.edu/handle/1721.1/87240](http://dspace.mit.edu/handle/1721.1/87240)

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 19, 2021, 3:09pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/7 "2021-12-19T15:09:40Z")

</div>

> [@chir.set](#):
>
> While tinkering with it, it does not get modified if a transform is applied to the fiducial node, nor if it is placed in a reformatted slice view. If we modify this matrix with SetNthControlPointOrientationMatrix, the applied matrix is always retrieved unaltered.

In general all node properties are set and retrieved in the node’s coordinate system. You can apply the node’s parent transform to the positions, orientations, etc. to get that in world coordinate system. If you only have linear parent transforms then this is a simple matrix multiplication.

There are convenience functions with “World” or “RAS” suffix in their name that get/set information in world coordinate system. See for example here:

> <https://github.com/Slicer/Slicer/blob/7b8eaec72a9563613caab7b0fb044a6b6d7b3d4b/Modules/Loadable/Markups/MRML/vtkMRMLMarkupsNode.cxx#L762>

---

<div class="post-metadata">

**Author:** ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)\
**Post date:** [December 19, 2021, 7:57pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/8 "2021-12-19T19:57:09Z")

</div>

> [@lassoan](#):
>
> There are convenience functions with “World” or “RAS” suffix in their name that get/set information in world coordinate system.

Yes, I noticed that, and tend to use the ‘World’ suffixed functions every time.

---

<div class="post-metadata">

**Author:** ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)\
**Post date:** [December 19, 2021, 8:59pm UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/9 "2021-12-19T20:59:36Z")

</div>

> [@lassoan](#):
>
> There are convenience functions with “World” or “RAS” suffix in their name that get/set information in world coordinate system.

I noticed strange results with the World variants here :

```auto
matrix = vtk.vtkMatrix3x3()
f = slicer.util.getNode("F")
f.GetNthControlPointOrientationMatrixWorld(0, matrix)
# matrix is identity

matrix.SetElement(0, 1, 2.0)
matrix.SetElement(1, 2, -2.0)
print(matrix)

f.SetNthControlPointOrientationMatrixWorld(0, matrix)

matrix2 = vtk.vtkMatrix3x3()
f.GetNthControlPointOrientationMatrixWorld(0, matrix2)
print(matrix2)
# matrix2 : all 9 values are 0

seq = GetNthControlPointOrientationMatrixWorld(0)
# ValueError: cannot create object of unknown type "vtkVector_IdLi9EE"

```

I guess no one is relying on this, but it’s worth reporting.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [December 20, 2021, 2:57am UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/10 "2021-12-20T02:57:00Z")

</div>

Setting orientation of a control point in a non-transformed markup node using the `SetNthControlPointOrientationMatrixWorld` method indeed did not work correctly. It is [fixed](https://github.com/Slicer/Slicer/commit/f01d58a2d6760a9e41b4a195f7f18cf92f1fa04e) now. Since control point orientation is not used for anything else than recording it and storing it, it is not tested very widely and thoroughly and so the bug remain unnoticed.

What do you plan to use the control point orientation for?

---

<div class="post-metadata">

**Author:** ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)\
**Post date:** [December 20, 2021, 7:38am UTC](https://discourse.slicer.org/t/getnthcontrolpointorientationmatrix-how-should-we-consider-it/21131/11 "2021-12-20T07:38:21Z")

</div>

> [@lassoan](#):
>
> What do you plan to use the control point orientation for?

In a self-contained tool, I need to record the orientation part of the SliceToRAS matrix. It will be different at each fiducial control point. This Get/Set facility seems to be available but not used in Slicer itself. So it gets in very handy.

As a side note, this orientation matrix is not saved with the markups node. Attaching this data to the control points will therefore be volatile, scene-wide only. It’s yet welcome.

> [@lassoan](#):
>
> It is [fixed](https://github.com/Slicer/Slicer/commit/f01d58a2d6760a9e41b4a195f7f18cf92f1fa04e) now.

Thank you.
