How to update adjacent vtkPolyData instances after a transformation

(map support) #1

Hi VTK users,

Initially I thought applying a transformation to one cell of a vtkPolyData would propagate positional changes to other vtkPolyData’s sharing the same points, but I am mistaken.

In the example below there are 6 points and two vtkPolygon objects, of which points 1 and 2 are shared between polygon1 and polygon2. The two objects are initially connected, but when I apply a rotation to polygon1, the two objects are then split at the middle because polygon2 is not updated with positional changes to two shared points.

Could I ask if anyone is familiar on how to update multiple polygons, such that if the points in one object is transformed, other objects sharing the same points are also updated? I initially thought vtkPolygon() held a reference to vtkPoints(), and updates were communicated throughout.

The example below is a proof of concept I’m building off, but eventually it will help me with creating an unstructured mesh with 100’s of panels and animation. End use case is to model beam deformations (in case there’s a better way to represent the solution).

import vtk

# Allocations
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()

points = vtk.vtkPoints()
polygon1 = vtk.vtkPolygon()
cell1 = vtk.vtkCellArray()
data1 = vtk.vtkPolyData()
transform1 = vtk.vtkTransform()
polyTransform1 = vtk.vtkTransformPolyDataFilter()
mapper1 = vtk.vtkPolyDataMapper()
actor1 = vtk.vtkActor()

polygon2 = vtk.vtkPolygon()
cell2 = vtk.vtkCellArray()
data2 = vtk.vtkPolyData()
transform2 = vtk.vtkTransform()
polyTransform2 = vtk.vtkTransformPolyDataFilter()
mapper2 = vtk.vtkPolyDataMapper()
actor2 = vtk.vtkActor()

# define points
points.InsertNextPoint(0.0, 0.0, 0.0) # 0
points.InsertNextPoint(2.0, 0.0, 0.0) # 1
points.InsertNextPoint(2.0, 1.0, 0.0) # 2
points.InsertNextPoint(0.0, 1.0, 0.0) # 3
points.InsertNextPoint(4.0, 0.0, 0.0) # 4 
points.InsertNextPoint(4.0, 1.0, 0.0) # 5 

# Create polygons
polygon1.GetPointIds().SetNumberOfIds(4) 
polygon1.GetPointIds().SetId(0, 0) 
polygon1.GetPointIds().SetId(1, 1)
polygon1.GetPointIds().SetId(2, 2)
polygon1.GetPointIds().SetId(3, 3)
cell1.InsertNextCell(polygon1)

polygon2.GetPointIds().SetNumberOfIds(4) 
polygon2.GetPointIds().SetId(0, 1)
polygon2.GetPointIds().SetId(1, 4)
polygon2.GetPointIds().SetId(2, 5)
polygon2.GetPointIds().SetId(3, 2)
cell2.InsertNextCell(polygon2)

data1.SetPoints(points)
data2.SetPoints(points)

data1.SetPolys(cell1)
data2.SetPolys(cell2)

polyTransform1.SetInputData(data1)
polyTransform1.SetTransform(transform1)

polyTransform2.SetInputData(data2)
polyTransform2.SetTransform(transform2)

mapper1.SetInputData(polyTransform1.GetOutput()) 
mapper2.SetInputData(polyTransform2.GetOutput())

actor1.SetMapper(mapper1)
actor2.SetMapper(mapper2)

# apply rotation to cell1
transform1.RotateY(30.0)

polyTransform1.Update()
polyTransform2.Update()

renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderer.AddActor(actor1)
renderer.AddActor(actor2)
renderWindow.Render()
renderWindowInteractor.Initialize()
renderWindowInteractor.Start()
(Andras Lasso) #2

You can share points between multiple polydata and all updates happen in sync as you would expect. The mistake in the code above is that the pipeline execution is broken because SetInputData is used instead of SetInputConnection.

(map support) #3

Thank you for your help Andras. I still find myself stuck and missing a key piece of information. Could you please correct me where I am mistaken? From this link:

https://vtk.org/Wiki/VTK/VTK_6_Migration/Removal_of_GetProducerPort

I take it this chunk should remains unchanged:

polyTransform2.SetInputData(data1)

polyTransform2.SetInputData(data2)

Then, I’m left with the following modification on the two times SetInputData() is called on the mappers:

mapper1.SetInputConnection(polyTransform1.GetOutputPort()) 
mapper2.SetInputConnection(polyTransform2.GetOutputPort())

However, the transformation only updates points on the one vtkPolyData object is it associated with. Are there other ideas/examples I should look into?

(Andras Lasso) #4

Keeping this would break the pipeline. As I wrote above, if you need automatic update of outputs on any input change then you must use ...SetInputConnection(...GetOutputPort()).

(map support) #5

I see. Then the part I’m struggling with, then, is the method GetOutputPort() does not exist for a vtkPolyData(). I found plenty of good examples on connecting a cone, sphere, and plane source (which all inherit vtkAlgorithm) to a transform filter, but I’m still lost on where to go next with vtkPolyData . I also see SetInputConnection() requires a vtkAlgorithm, so I guess my question is how does one get a vtkAlgorithmOutput from a vtkPolyData?

(Andras Lasso) #6

I see now, OK, if the transform filter’s input is the original polydata then setting the input is fine. It should all work then.

If something is off then probably Modified() calls are missed. After you make a modification in a polydata, you need to call Modified() at that level and maybe at higher levels, too (for example, if you change a point coordinates you need to call Modified() when you are done with the changes, for vtkPoints and maybe also for vtkPolyData object).

Also note that if you want the objects to move together then you need to apply the same transform on them. However, it seems that you apply to independent transforms (transform1 and transform2), so if you move one object, the other will not move. You can make the objects move together by building a transformation pipeline using vtkTransform::Concatenate (e.g., a common parent transform concatenated with two additional transforms).

What is your project about? What would you like to achieve?

(map support) #7

Thanks Andras. I appreciate all your help on this. I’ll start off with the last two lines since I haven’t fully digested the first part yet (and also to define the problem in case the route I’m proceeding in is not right).

I’d like to add visualization and animation to an open source project to simulates under water cables and buoys. The buoys themselves have articulating panels (similar to a hinge).

Internally, the buoy is modeled using a few nodes that move relative to one another, similar to a robotic actuator. Each node has position vector and orientation, and I would like to wrap a vtkPolyData representing one part of the buoy over each node to map the node orientation/position of the component. Some edges of the vtkPolyData component will share common points with with neighbors.

In the original problem definition I had two adjacent panels with a common edge in an effort to model the ‘hinge’ part of the buoy, hoping to condense the problem down to something simpler. I hope my description adds a little perspectives on where I’d like to take this.