add observer on cell and point array

Hello, I have a polydata and I would like to run some callback function when the polydata in general, its cells or its points are modified. I attach the following test code as an example.

# define points
x = [0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0]
y = [1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
z = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

# create emtpy VTK arrays and polydata
my_points = vtk.vtkPoints()
my_cells = vtk.vtkCellArray()
my_pd = vtk.vtkPolyData()

# connect callback functions to VTK events
# (I use lambda function to keep it concise, but with standard functions defined with "def" it is the same
my_points.AddObserver("AnyEvent", lambda object, event: print("lambda my_points_any - event: ", event))
my_cells.AddObserver("AnyEvent", lambda object, event: print("lambda my_pd_cells_any - event: ", event))
my_pd .AddObserver("AnyEvent", lambda object, event: print("lambda my_pd_any - event: ", event))

# add points to point array
for idx in range(8):
    my_points.InsertPoint(idx, x[idx], y[idx], z[idx])

# add cells to cell array
for idx in range(6):
    triangle = vtk.vtkTriangle()
    triangle.GetPointIds().SetId(0, idx)
    triangle.GetPointIds().SetId(1, idx+1)
    triangle.GetPointIds().SetId(2, idx+2)

# set points
my_pd .SetPoints(my_points)

# set cells
my_pd .SetPolys(my_cells)

I suppose I should read some message from the callback functions:

  • every time a point is added to the point array
  • every time a cell is added to the cell array
  • when points and cells are added to the polydata

However I only get messages from the polydata events. This is the only output I get:

>>>lambda my_pd_any - event:  ModifiedEvent
>>>lambda my_pd_ any - event:  ModifiedEvent

I am using AnyEvent to capture all possible events for testing purpose, and I also tried with ModifiedEvent and other events.

Could someone help me with this?

Thanks very much!

To allow bulk updates, VTK does not immediately invoke ModifiedEvent event after you modify something. Instead, you do all the modifications you want, and then when you are done, you call Modified() on each modified object. Calling Modified() on the top-level vtkPolyData may not enough, you need to call it on all arrays that you changed.

Hello, and thanks very much!

So, if I understand, if I modify a PointArray that has already been set as a PolyData’s Points, then a ModifiedEvent will be emitted by the PointArray only when the PolyData will be e.g. called by an Actor to be shown in some Canvas. Correct?

This is a bit of a problem for me since I’m writing an interactive application and I’like the Actor to be redrawn in the Canvas when the PointArray is modified… exactly the opposite logic!

At the moment I have solved this using Qt signals (it is a Qt application) emitted by all functions that modify the PointArray (or CellArray etc.), but this is not so elegant and implies replicating a lot of code. Any better ideas?

Thanks very much!

Kind regards

VTK is very commonly used in Qt applications and it works well. All you need to do is call Modified() after you finished with modifying a data set (it is not possible for VTK to know when you are done with your modifications) and trigger re-rendering.

I usually use ctkVTKRenderView for rendering VTK views in Qt applications, as it compresses rendering request events: I can call scheduleRender whenever anything is changed in my application and actual rendering happens only once for each batch of changes.