A potential bug for vtkPolyData

I create a vtkPolyData, and I can display it. The code is:

import vtkmodules.all as vtk
import time
def point(x, y, z):

    polyData = vtk.vtkPolyData()
    polyData.SetPoints(vtk.vtkPoints())
    polyData.SetVerts(vtk.vtkCellArray())

    polyData.GetPoints().InsertNextPoint(x, y, z)
    polyData.GetVerts().InsertNextCell(1)
    polyData.GetVerts().InsertCellPoint(0)

    return polyData

if __name__ == '__main__':

    polyData1 = point(0, 0, 0)
    actor1 = vtk.vtkFollower()
    mapper1 = vtk.vtkPolyDataMapper()
    mapper1.SetInputData(polyData1)
    actor1.SetMapper(mapper1)
    actor1.GetProperty().RenderPointsAsSpheresOn()
    actor1.GetProperty().SetRepresentationToPoints()
    actor1.GetProperty().SetPointSize(10)

    polyData2 = point(10, 0, 0)
    actor2 = vtk.vtkFollower()
    mapper2 = vtk.vtkPolyDataMapper()
    mapper2.SetInputData(polyData2)
    actor2.SetMapper(mapper2)
    actor2.GetProperty().RenderPointsAsSpheresOn()
    actor2.GetProperty().SetRepresentationToPoints()
    actor2.GetProperty().SetPointSize(10)

    ren = vtk.vtkRenderer()
    ren.AddActor(actor1)
    ren.AddActor(actor2)
    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren)
    renWin.Render()

    for i in range(2, 10):
        polyData2.GetPoints().SetPoint(0, i, 0, 0)
        polyData2.Modified()
        mapper2.SetInputData(polyData2)
        mapper2.Update()
        actor2.Modified()
        renWin.Render()
        time.sleep(0.5)

We can see that the point is not updated. The reason is that the verts has not been updated.

The for loop should be modified as:

    for i in range(2, 10):
        polyData2.GetPoints().SetPoint(0, i, 0, 0)
        polyData2.Modified()
        polyData2.GetVerts().Modified()   #####################  modified
        polyData2.GetPoints().Modified()  #####################  modified
        mapper2.SetInputData(polyData2)
        mapper2.Update()
        actor2.Modified()
        renWin.Render()
        time.sleep(0.5)

Then, the points is updated as I expected.

However, I think that polyData2.Modified() should automatically update the time for verts and points.
I think the solution should be that overwrite the modified method in vtkPolyData:

void vtkPolyData::Modified()
{
    vtkPointSet::Modified();
    if(this->Verts != nullptr)
    {
       this->Verts->Modified();
    }
    if(this->Lines!= nullptr)
    {
       this->Lines->Modified();
    }
    if(this->Polys!= nullptr)
    {
       this->Polys->Modified();
    }
    if(this->Strips!= nullptr)
    {
       this->Strips->Modified();
    }
    if(this->GetPoints()!= nullptr)
    {
       this->GetPoints()->Modified();
    }
}

This is handled my GetMTime()

//------------------------------------------------------------------------------
vtkMTimeType vtkPolyData::GetMTime()
{
  vtkMTimeType time = this->Superclass::GetMTime();
  if (this->Verts)
  {
    time = vtkMath::Max(this->Verts->GetMTime(), time);
  }
  if (this->Lines)
  {
    time = vtkMath::Max(this->Lines->GetMTime(), time);
  }
  if (this->Polys)
  {
    time = vtkMath::Max(this->Polys->GetMTime(), time);
  }
  if (this->Strips)
  {
    time = vtkMath::Max(this->Strips->GetMTime(), time);
  }
  return time;
}

vtkPolyData::GetMTime() will compare the MTime for verts, lines, polys, strips in vtkPolyData, but vtkPolyData::Modified do not update the MTime for verts, lines, polys, strips.

Having vtkPolyData::Modified modify its verts, lines, polys, and strips could cause insidious side effects. It is possible, due to VTK’s shallow copying / reference counting, that doing so would indirectly cause a completely different polydata (which referenced one of the modified verts, lines, polys, or strips) to become “modified” which could cause unexpected filter execution etc.

@will.schroeder Thank you for your kindly reply.

It really cost me much time to fix this bug: I need to manually update time for points, verts event I update time for polydata.

As @will.schroeder and I explained. This is not a bug. This is how polydata is designed. You may have another related issue but your suggested fix is not correct.

You should not need to do that.

@mwestphal If I don’t manually update time by:

        polyData2.GetVerts().Modified()   #####################  modified
        polyData2.GetPoints().Modified()  #####################  modified

How can I make the code correct?

1 Like