points not showing after aplying rotation/translation

Hello!

I am trying to rotate some points in space, but when I try plotting them, they do not show. I am not sure why as I put markers in my code before and after the displaying line and it looks like the program executes the line, but for some reason it is not showing…

My code is as follows (similar to https://lorensen.github.io/VTKExamples/site/Python/Filtering/AppendFilter/)

points = vtk.vtkPoints()

points.InsertNextPoint(…)
points.InsertNextPoint(…)
points.InsertNextPoint(…)

ug = vtk.vtkUnstructuredGrid()
ug.SetPoints(points)

appendFilter = vtk.vtkAppendFilter()
appendFilter.AddInputData(ug)
appendFilter.Update()

mapper = vtk.vtkDataSetMapper()
mapper.SetInputConnection(appendFilter.GetOutputPort())

actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(0.0, 0.0, 1.0)
actor.GetProperty().SetPointSize(10)

ren.AddActor(actor)

I have also tried the following: which it works, but the moment I apply a rotation to them, they disappear and I am not sure why either…

points = vtk.vtkPoints()

points.InsertNextPoint(.....)
points.InsertNextPoint(.....)
points.InsertNextPoint(.....)    

pointsPolyData = vtk.vtkPolyData()
pointsPolyData.SetPoints(points)

vertexFilter = vtk.vtkVertexGlyphFilter()
vertexFilter.SetInputData(pointsPolyData)
vertexFilter.Update() 
     
mapper= vtk.vtkPolyDataMapper()
mapper.SetInputData(vertexFilter.GetOutput())
  
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(0.0, 0.0, 1.0)
actor.GetProperty().SetPointSize(10)

ren.AddActor(actor)

For rotating/translating I can apply the vtkTransformPolyDataFilter() and set its input to the vertex/append Filters’s output. Or at least this is how I see what I should do. But the problem is, once I do this, they stop displaying altogether. I tried printing messages during the execution to see if it stops somewhere but as far as that goes, everything goes well. So I am not sure where it stops working.

Any help is appreciated!

-Diana

Hi

You didn’t assign a transform to vtkTransformPolyDataFilter(), so you see nothing in the output.

From the code you posted:

  1. No usage of vtkTransformPolyDataFilter().
  2. Neither a vtkAbstractTransform derived object like vtkTransform is initialized.
  3. Nor is there a call to SetTransform on the transformation filter.

Are you sure you did not see any error messages? A lack of vtkAbstractTransform should print this error message in the logs, since Transform is nullptr

Yes, sorry. I only posted the first part of the code because in my first code the points would not even show so I thought maybe the problem is there.

This is the rest of the code. (I only posted the part after the calculation of the rotation matrix)

        rot_obj = vtk.vtkTransform()
        rot_obj.Identity()

        tr_obj = vtk.vtkMatrix4x4()
        for i in range(0,4):
            for j in range(0,4):
                tr_obj.SetElement(i,j,Total_Transform[i][j])
                
        rot_obj.SetMatrix(tr_obj)

        transformFilter=vtk.vtkTransformPolyDataFilter()
        transformFilter.SetInputConnection(obj.GetOutputPort())
        transformFilter.SetTransform(rot_obj)
        transformFilter.Update()
        
        NewMapper = vtk.vtkPolyDataMapper()
        NewMapper.SetInputConnection(transformFilter.GetOutputPort())
        
        actorRotated = vtk.vtkActor()
        actorRotated.SetMapper(NewMapper)
        
        actorRotated.GetProperty().SetOpacity(0.4)
        ren.AddActor(actorRotated)

with obj being the object being passed in the function, in my case the vertexFilter or appendFilter.

Yes, I have checked many times and I have no errors…

The pipeline looks alright.

Is anything rendered when you avoid this section of code?

        rot_obj.Identity()

        tr_obj = vtk.vtkMatrix4x4()
        for i in range(0,4):
            for j in range(0,4):
                tr_obj.SetElement(i,j,Total_Transform[i][j])
                
        rot_obj.SetMatrix(tr_obj)

If you see stuff rendered, then the problem lies in Total_Transform and not in the pipeline.

Did you try this instead of directly changing the underlying matrix?

Yes, the render shows my objects with the position before the rotation matrix is applied.

I am not sure why there would be a problem with the transformation matrix because, if I just pass it an actor (random object) it rotates and translates it as it should, but the moment I pass it the points, then they don’t get displayed.

I need to apply this transformation to both points and objects, and it works perfect for objects, but not with points. Is there a difference between a transformation matrix between an object and a point? In my opinion they should be the same, but I might be wrong. I used the Euler-Rodrigues rotation matrix and pre multiplied with the translation matrix and post multiply with the inverse of the translation matrix, so it should be ok.

vtkTransformPolyDataFilter directly copies over any Verts present in its input. So does the generic vtkTransformFilter. The transform filters work only on points and do not change the cells.

Is transformFilter.GetOutput().GetNumberOfPoints() > 0 after the update? Also, is obj.GetOutput().GetNumberOfCells() > 0 after the update?

Edit: fix GetNumberOfPoints()

Just to clarify, the appendFilter does not display anything, and the vertexFilter displays the points. I have wrote wrong before (my apologies), they do display, but not rotated/translated in any way.

For the transformFilter.GetNumberOfPoints() I have the following error: AttributeError: 'vtkmodules.vtkFiltersGeneral.vtkTransformPolyDataF' object has no attribute 'GetNumberOfPoints'.
And for the obj.GetOutput().GetNumberOfCells(), yes both the object and points are > 0.

Edited previous reply to fix error

Yes, they are both > 0

Can you post the full code with the input point set?

yes of course!

ap1 = [np.array([-37.2736, -159.66, -810.009]),
              np.array([-32.5138, -164.127, -809.214]),
              np.array([-23.6534, -167.229, -808.477])]
ap2 = [np.array([14.8481, -143.84, -831.03]),
           np.array([12.861, -146.207, -832.029]),
           np.array([17.2145, -139.715, -831.64])] 

lig_points = vtk.vtkPoints()

points.InsertNextPoint(ap1[0][0], ap1[0][1], ap1[0][2])
points.InsertNextPoint(ap1[1][0], ap1[1][1], ap1[1][2])
points.InsertNextPoint(ap1[2][0], ap1[2][1], ap1[2][2])
points.InsertNextPoint(ap2[0][0], ap2[0][1], ap2[0][2])
points.InsertNextPoint(ap2[1][0], ap2[1][1], ap2[1][2])
points.InsertNextPoint(ap2[2][0], ap2[2][1], ap2[2][2])

pointsPolyData = vtk.vtkPolyData()
pointsPolyData.SetPoints(points)

vertexFilter = vtk.vtkVertexGlyphFilter()
vertexFilter.SetInputData(pointsPolyData)
vertexFilter.Update() 
     
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(vertexFilter.GetOutput())
  
actor = vtk.vtkActor()
actor.SetMapper(mapper_ligaments)
actor.GetProperty().SetColor(0.0, 0.0, 1.0)
actor.GetProperty().SetPointSize(10)

ren.AddActor(actor)

    def rotate(angle, axis, axis_point, obj):
        """Rotate around an arbitrary `axis` passing through `axis_point`."""
        axis = axis/np.linalg.norm(axis)
        anglerad = np.deg2rad(angle)  # transform angle to radians
        
        a = np.cos(anglerad / 2)
        b = -axis[0] * np.sin(anglerad / 2)
        c = -axis[1] * np.sin(anglerad / 2)
        d = -axis[2] * np.sin(anglerad / 2)
        
        size = (a**2 + b**2 + c**2 + d**2)**0.5
        print("size: ", size)
        a, b, c, d = a/size, b/size, c/size, d/size
        aa, bb, cc, dd = a * a, b * b, c * c, d * d
        bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
        
        Transform_R = np.array(
            [
                [aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac),0],
                [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab),0],
                [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc,0],
                [0,0,0,1]
            ]
        )
        Transform_Neg_Translation = np.array(
            [
                [1, 0, 0,-axis_point[0]],
                [0, 1, 0,-axis_point[1]],
                [0, 0, 1,-axis_point[2]],
                [0,0,0,1]
            ]
        )
        Transform_Pos_Translation = np.array(
            [
                [1, 0, 0,axis_point[0]],
                [0, 1, 0,axis_point[1]],
                [0, 0, 1,axis_point[2]],
                [0,0,0,1]
            ]
        )
        Total_Transform = np.matmul(Transform_Pos_Translation,np.matmul(Transform_R,Transform_Neg_Translation))

        rot_obj = vtk.vtkTransform()
        rot_obj.Identity()

        tr_obj = vtk.vtkMatrix4x4()
        for i in range(0,4):
            for j in range(0,4):
                tr_obj.SetElement(i,j,Total_Transform[i][j])
                
        rot_obj.SetMatrix(tr_obj)

        transformFilter=vtk.vtkTransformPolyDataFilter()
        transformFilter.SetInputConnection(obj.GetOutputPort())
        transformFilter.SetTransform(rot_obj)
        transformFilter.Update()
        print("Transform get number of points = ", transformFilter.GetOutput().GetNumberOfPoints())
        print("Object get number of cells = ", obj.GetOutput().GetNumberOfCells())
        
        NewMapper = vtk.vtkPolyDataMapper()
        NewMapper.SetInputConnection(transformFilter.GetOutputPort())
        
        actorRotated = vtk.vtkActor()
        actorRotated.SetMapper(NewMapper)
        
        ren.AddActor(actorRotated)


                
##### data of the line and point the translation is needed
    lineStart = [16.8879, -106.476, -782.449]       
    lineFinish = [-17.827, -92.2757, lineStart[2]]
    lineMiddle = [(lineStart[0]+lineFinish[0])/2, (lineStart[1]+lineFinish[1])/2, lineStartPosterior[2]]
    
    line = (np.array(lineFinish) - np.array(lineStart))

    rotate(-45, line, lineMiddle, vertexFilter)

Also, I forgot to answer your question (sorry!) about me trying this. I did try at first with that, but it would rotate about the global coordinate system and not the local one, so that is why I applied the transformation matrix.

Ahh, to fix that, call rot_obj.PostMultiply(), by default it is set to PreMultiply

Also, you’re not setting up a pipeline here. So changes to vertexFilter's output do not make it to the actor. Use SetInputConnection in place of SetInputData and GetOutputPort in place of GetOutput to establish a pipeline.

mapper.SetInputData(vertexFilter.GetOutput())

1 Like

Oh, sorry. I did not realize that!

I did make the changes, but it is the same result…

I still do not understand why the points are showing but then they are not shifting when called in the function, but the object is shifting :thinking:

{EDIT} IT FINALLY WORKED!!! It was as you said in the previous answer. I did not set-up the pipeline properly. The reason I was not seeing them shifting was that I did not give a colour and size so the points appeared shifted, but really small and the same colour as my object, so they were basically belnding in perfectly… I only realized this when I turned off the display for my object.

Thank you so much for your help!!! I highly appreciate it!

Glad you got it to work. :+1: