# vtkCylinderSource() and transformation matrix

**URL:** <https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052>\
**Category:** Support\
**Created:** [September 2, 2022, 12:05pm UTC](https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052 "2022-09-02T12:05:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mosenco](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mosenco/32/16037_2.png) [@mosenco](https://discourse.slicer.org/u/mosenco)\
**Post date:** [September 2, 2022, 12:05pm UTC](https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052/1 "2022-09-02T12:05:35Z")

</div>

I had a problem, back then, with the rotation. I had a cylinder, C1, in space, with its rotation and another one C2, placed at the origin (0,0,0). I wanted to move and rotate C2 like C1, so C2 overlaps C1. I did it with euler angles using the transformation matrix 4x4.

Now i have another problem. I have a model of a brain and many models of cylinders that represent electrodes to capture brain activities and i wanted to detect if a specific cylinder is outside or inside the brain and color it accordingly. I tried with `vtkCollisionDetectionFilter()` and had my problems and i already made a post about it here, but then i found another class `vtkSelectEnclosedPoints()` that works better for my case, because giving an input data, a surface data, then i just use the function `IsInside()` to check if the input data is inside the surface data. But weird enough, the result was all wrong.

Turns out, the transformation matrix is the one that was giving the errors.  
I rewrote the code without the transformation matrix, so both brain and cylinder have the same cartesian system, and the `vtkSelectEnclosedPoints()` works fine. Turns out, that if i rotate with the euler angles, so using the transformation matrix, the brain and the cylinder have different cartesiam system. So for example, the position in space (0,0,0) for the brain is different for the cylinder, because they are refering to different cartesian system.

What can i do?

```auto
### Create a vtk cylinder
cylinderSource = vtk.vtkCylinderSource()
cylinderSource.SetCenter(0,0,0)
cylinderSource.SetHeight(list(models.values())[0][1])
cylinderSource.SetRadius(list(models.values())[0][2])
cylinderSource.SetResolution(100)
cylinderSource.Update()
### Create a model of the cylinder to add to the scene
cylindermodel = slicer.vtkMRMLModelNode()
cylindermodel.SetName(name + "_direction")
cylindermodel.SetAndObservePolyData(cylinderSource.GetOutput())

#Create a Transform node for the model to copy the rotation
cylinderTS = slicer.vtkMRMLTransformNode()

##compute the rotation
#Given the vector (p1,p3) i move it to the origin
vorigin = np.subtract(p1,p3)
#compute rotation matrix
R = self.rotMat(vorigin)
#from 3x3 matrix i transformit in a 4x4 matrix
matrix4 = self.mat3To4(R, float(points[p]), float(points[p + 1]), float(points[p + 2]))
#from 4x4 matrix, generate vtkmatrix4x4 object
rMatrix = self.mat4x4Gen(matrix4)
#add the rotation to the model
cylinderTS.SetAndObserveMatrixTransformToParent(rMatrix)

cylindermodelDisplay = slicer.vtkMRMLModelDisplayNode()
cylindermodelDisplay.SetSliceIntersectionVisibility(True) # Hide in slice view
cylindermodelDisplay.SetVisibility(True) # Show in 3D view
cylindermodelDisplay.SetColor(1, 0, 0)
cylindermodelDisplay.SetLineWidth(2)
cylindermodelDisplay.SetOpacity(0.5)

slicer.mrmlScene.AddNode(cylindermodelDisplay)
cylindermodel.SetAndObserveDisplayNodeID(cylindermodelDisplay.GetID())

slicer.mrmlScene.AddNode(cylinderTS)
cylindermodel.SetAndObserveTransformNodeID(cylinderTS.GetID())

slicer.mrmlScene.AddNode(cylindermodel)

# Check if electrodes are inside or outside the brain
for j in range(0, len(listBrain)):
    select = vtk.vtkSelectEnclosedPoints()
    select.SetInputData(cylindermodel.GetPolyData())
    select.SetSurfaceData(listBrain[j])
    select.SetTolerance(.00001)
    select.Update()
    if select.IsInsideSurface([float(points[p]), float(points[p + 1]), float(points[p + 2])]):
        cylindermodelDisplay.SetColor(1, 1, 1)
        fidNode.SetNthFiducialLabel(a, name + str((p / 3) + 1)+"#")
    del select

```

```auto
def mat4x4Gen(self, m):
    rMatrix = vtk.vtkMatrix4x4()
    for x in range(4):
        for y in range(4):
            rMatrix.SetElement(x, y, m[x][y])
    return rMatrix

def mat3To4(self, m,x,y,z):
    b = np.array([[0, 0, 0]])
    c = np.concatenate((m, b), axis=0)
    d = np.array([[x, y, z, 1]])
    return np.concatenate((c, d.T), axis=1)

  

def rotMat(self, vec2):
    """ Find the rotation matrix that aligns vec1 to vec2
    :param vec1: A 3d "source" vector
    :param vec2: A 3d "destination" vector
    :return mat: A transform matrix (3x3) which when applied to vec1, aligns it with vec2.
    """
    vec1 = [0,1,0]
    a, b = (vec1 / np.linalg.norm(vec1)).reshape(3), (vec2 / np.linalg.norm(vec2)).reshape(3)
    v = np.cross(a, b)
    c = np.dot(a, b)
    s = np.linalg.norm(v)
    kmat = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]], [-v[1], v[0], 0]])
    rotation_matrix = np.eye(3) + kmat + kmat.dot(kmat) * ((1 - c) / (s ** 2))
    return rotation_matrix

```

---

<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:** [September 3, 2022, 2:21pm UTC](https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052/2 "2022-09-03T14:21:11Z")

</div>

If you apply a transform to a model node (using `SetAndObserveTransformNodeID()`) then the polydata in the model node is not changed.

If you want to get a polydata in world coordinate system (what you see on screen) then you can either:

- harden a transform (persistently transform all points of a model, using `HardenTransform()`)
- get the polydata, make a copy, and apply use `vtkTransformPolyDataFilter` to transform the polydata (using the transform provided by `transformNode.GetMatrixTransformToWorld()`).

However, I would to determine what parts of an electrode intersect the brain (or segmented regions of the brain) using “Probe volume with model” module. This modules assigns to each labelpoint the value of the image at that position. It takes care of all transforms (you get what you see in the 3D view). You can get the values as a numpy array by calling `pd = slicer.util.arrayFromModelPointData()` and if you want to know if any points are inside the volume then you can simply check if `pd.max() > 0`.

---

<div class="post-metadata">

**Author:** ![mosenco](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mosenco/32/16037_2.png) [@mosenco](https://discourse.slicer.org/u/mosenco)\
**Post date:** [September 13, 2022, 6:30pm UTC](https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052/3 "2022-09-13T18:30:51Z")

</div>

I tried to use

```auto
pointAt = [0,0,0]
for indexMesh in range(0, cylindermodel.GetPolyData().GetNumberOfPoints()):
    cylindermodel.GetPolyData().GetPoint(indexMesh, pointAt)

```

so at each cycle, pointAt will return a continuous flow of points regarding my single `cylindermodel`. And for each point i create a new `AddControlPoint(pointAt)` so i can see where that point is.

To my surprise they all are at (0,0,0), because as you see in previous code when i declare `cylinderSource` i set the center at (0,0,0). So when i called `cylindermodel.SetAndObservePolyData(cylinderSource.GetOutput())`, my model was just mirroring the `cylinderSource` but the model doesnt have any mesh or poly or anything.

With `cylinderTS = slicer.vtkMRMLTransformNode()` i managed to make a transformation so with `cylindermodel.SetAndObserveDisplayNodeID(cylindermodelDisplay.GetID())` i just rotate and move my model.

The problem is that when i call `cylindermodel.GetPolyData()` it returns me the poly data of `cylinderSource` not the one i see in the 3Dslicer.

I tried to search on the forum but didn’t find anything. Is there any guide to create, for example, a cube using vtk and then put it in the scene? Is there any other way from what i did?

---

<div class="post-metadata">

**Author:** ![mosenco](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mosenco/32/16037_2.png) [@mosenco](https://discourse.slicer.org/u/mosenco)\
**Post date:** [September 13, 2022, 9:07pm UTC](https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052/4 "2022-09-13T21:07:53Z")

</div>

i tried to follow this guide to how use hardentransform [https://python.hotexamples.com/examples/slicer/-/vtkSlicerTransformLogic/python-vtkslicertransformlogic-function-examples.html](https://python.hotexamples.com/examples/slicer/-/vtkSlicerTransformLogic/python-vtkslicertransformlogic-function-examples.html) but i dunno, my cylinder vtk stays at position (0,0,0) even if i hardentransformed. I tried also `cylindermodel.HardenTransform()` but nothing happens.

I used `cylindermodel.GetPolyData().GetPoint(0, pos)` before and after hardentransform and the value of pos doesnt change

---

<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:** [September 13, 2022, 9:47pm UTC](https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052/5 "2022-09-13T21:47:59Z")

</div>

Most likely the issue is something trivial, like you haven’t called `Update()` on cylinder source. Please provide a code snippet that I can copy-paste into the Python console that reproduces the unexpected behavior.

---

<div class="post-metadata">

**Author:** ![mosenco](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mosenco/32/16037_2.png) [@mosenco](https://discourse.slicer.org/u/mosenco)\
**Post date:** [September 14, 2022, 1:07pm UTC](https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052/6 "2022-09-14T13:07:20Z")

</div>

Meanwhile i was writing a test to share it with you, i found out the problem. `cylindermodel.HardenTransform()` must be used after `slicer.mrmlScene.AddNode(cylindermodel)`.

Btw, i didn’t know about the `hardentransform()`, that solved it!

---

<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:** [September 14, 2022, 3:20pm UTC](https://discourse.slicer.org/t/vtkcylindersource-and-transformation-matrix/25052/7 "2022-09-14T15:20:42Z")

</div>

That’s correct. Node references (such as the model node refers to a transform node) only work between nodes that are added to the scene.
