[vtkusers] Major problem with vtkPolyData and vtkCellData

Sander Niemeijer niemeijer at science-and-technology.nl
Fri Jan 23 15:27:52 EST 2004


Hi all,

I'm using VTK-4.2.4 on Linux and am trying to build my own 
vtkPolyDataToPolyDataFilter for a project we are working on. Things 
were going pretty well until I got to the point where I wanted to pass 
the vtkCellData from my input to my output. Within my filter I am 
modifying both vertices, lines, and polygons (the filter supports 
vtkPolyData input with any mix of vertices, lines, and polygons). 
Within a vtkPolyData object,  Verts, Lines, Polys, and Strips each have 
their own vtkCellArray (with their individual cell index range). Next 
to these individual cell arrays, the vtkPolyData class also supports a 
'temporary' cell array containing the total set of cells.
The vtkPolyData objects I am passing through my filter contains both 
lines and polys and each line and polygon needs to have a scalar value 
associated with it that can be used for coloring. I specified these 
scalar attributes within the vtkCellData attribute of the vtkPolyData 
object. I was under the impression that the cell ids I used in the 
vtkCellData attribute would correspond with the 'temporary' cell array 
and that I could use the cell ids returned by 
vtkPolyData::InsertNextCell would provide me with the proper cell id to 
use for the vtkCellData object. However, it seems that this is not the 
case and things are going horribly wrong.

To illustrate this I have added an example python file with this e-mail.
What this example does is show you a polydata object containing 2 
polygons (a triangle and a bar) and 1 line. Each of these 3 cells has 
been given its own scalar value, that is mapped to the colors red, 
green, and blue via a lookup table. The renderwindow is split up, 
showing a 3D (vtkPolyDataMapper) rendering of the polydata on the left 
side and a 2D (vtkPolyDataMapper2D) rendering of the same polydata on 
the right side. Besides the polyActor showing the polydata there is 
also a refpolyActor showing a vtkPolyData with three lines (i.e. a 
vtkPolyData with only one type of cells!) using the same color 
attributes as the polydata.

If you run the example, what should be happening is that you should see 
a red triangle, a greed line, and a blue bar. What you get however is:
  - for the vtkPolyDataMapper   : a green triangle, a red line, and a 
blue bar
  - for the vtkPolyDataMapper2D : a red triangle, a blue line, and a 
green bar
So not only is the coloring wrong, but it depends on the type of mapper 
you use how wrong it will be!!!

Unfortunately it seems that in order to fix this problem properly the 
whole design of how vtkPolyData and vtkCellData interacts should be 
revised. The 'temporary' cell array in vtkPolyData doesn't have a fixed 
ordering; when adding cells they are put at the end (no matter which 
type of cell it is), but when rebuilding the cell array the array is 
build up starting with Verts, then Lines, then Polys, and finally 
Strips. Not having a fixed ordering, means not having a fixed cell id 
for a specific cell in a vtkPolyData object, which makes it impossible 
to use it as index for a vtkCellData object.
Furthermore the fact that the different polydata mappers try to support 
vtkCellData information for vtkPolyData objects with different cell 
types in a different (and all wrong!) manner doesn't make life more 
easy either.

Since we are on a tight deadline for our project, I will have to come 
up with a workaround for this problem soon. My current idea is to 
restrict my vtkPolyDataToPolyDataFilter to vtkPolyData objects with 
only one cell type and split my previous vtkPolyData objects into 
separate vtkPolyData objects (one for lines, and one for polys). 
However, this will require duplicates of the vtkPoints objects. If 
anyone knows a better approach, please let me know.

Regards,
Sander Niemeijer
Science [&] Technology Corp.

-----------------------------------------
python example:
-----------------------------------------
import vtk

VTK_LINE = 3
VTK_POLYGON = 7

# initialize polydata object
polydata = vtk.vtkPolyData()
polydata.SetLines(vtk.vtkCellArray())
polydata.SetPolys(vtk.vtkCellArray())

points = vtk.vtkPoints()
# points for poly 1 (triangle)
points.InsertNextPoint(0.2, 0.3, 0)
points.InsertNextPoint(0.4, 0.55, 0)
points.InsertNextPoint(0.2, 0.8, 0)
# points for line 1 (line)
points.InsertNextPoint(0.5, 0.3, 0)
points.InsertNextPoint(0.5, 0.8, 0)
# points for poly 2 (bar)
points.InsertNextPoint(0.6, 0.3, 0)
points.InsertNextPoint(0.8, 0.3, 0)
points.InsertNextPoint(0.8, 0.8, 0)
points.InsertNextPoint(0.6, 0.8, 0)
polydata.SetPoints(points)

# set scalar cell data
colors = vtk.vtkFloatArray()
polydata.GetCellData().SetScalars(colors)

# create poly 1
ids = vtk.vtkIdList()
ids.InsertNextId(0)
ids.InsertNextId(1)
ids.InsertNextId(2)
cell = polydata.InsertNextCell(VTK_POLYGON, ids)
# poly 1 should get the first color (red)
colors.InsertTuple1(cell, 0.0)

# create line 1
ids.Reset()
ids.InsertNextId(3)
ids.InsertNextId(4)
cell = polydata.InsertNextCell(VTK_LINE, ids)
# line 1 should get the second color (green)
colors.InsertTuple1(cell, 1.0)

# create poly 2
ids.Reset()
ids.InsertNextId(5)
ids.InsertNextId(6)
ids.InsertNextId(7)
ids.InsertNextId(8)
cell = polydata.InsertNextCell(VTK_POLYGON, ids)
# poly 2 should get the third color (blue)
colors.InsertTuple1(cell, 2.0)

# create reference poly with colors as they should be
refpoly = vtk.vtkPolyData()
refpoly.SetLines(vtk.vtkCellArray())
refpoly.GetCellData().SetScalars(colors)
scalars = refpoly.GetCellData().GetScalars()
print scalars.GetNumberOfTuples()
refpoints = vtk.vtkPoints()
refpoints.InsertNextPoint(0.2, 0.2, 0)
refpoints.InsertNextPoint(0.4, 0.2, 0)
refpoints.InsertNextPoint(0.6, 0.2, 0)
refpoints.InsertNextPoint(0.8, 0.2, 0)
refpoly.SetPoints(refpoints)
ids.Reset()
ids.InsertNextId(0)
ids.InsertNextId(1)
cell = refpoly.InsertNextCell(VTK_LINE, ids)
ids.Reset()
ids.InsertNextId(1)
ids.InsertNextId(2)
cell = refpoly.InsertNextCell(VTK_LINE, ids)
ids.Reset()
ids.InsertNextId(2)
ids.InsertNextId(3)
cell = refpoly.InsertNextCell(VTK_LINE, ids)

# define colors
lut = vtk.vtkLookupTable()
lut.SetNumberOfTableValues(3)
lut.SetTableRange(0, 2)
lut.SetTableValue(0, 1.0, 0.0, 0.0, 1.0) # red
lut.SetTableValue(1, 0.0, 1.0, 0.0, 1.0) # green
lut.SetTableValue(2, 0.0, 0.0, 1.0, 1.0) # blue
lut.Build()

# create mapper and assign colortable
polyMapper = vtk.vtkPolyDataMapper()
polyMapper.SetInput(polydata)
polyMapper.SetScalarModeToUseCellData()
polyMapper.UseLookupTableScalarRangeOn()
polyMapper.SetLookupTable(lut)
coordinate = vtk.vtkCoordinate()
coordinate.SetCoordinateSystemToNormalizedViewport()
polyMapper2D = vtk.vtkPolyDataMapper2D()
polyMapper2D.SetTransformCoordinate(coordinate)
polyMapper2D.SetInput(polydata)
polyMapper2D.SetScalarModeToUseCellData()
polyMapper2D.UseLookupTableScalarRangeOn()
polyMapper2D.SetLookupTable(lut)

# same for the refpoly
refpolyMapper = vtk.vtkPolyDataMapper()
refpolyMapper.SetInput(refpoly)
refpolyMapper.SetScalarModeToUseCellData()
refpolyMapper.UseLookupTableScalarRangeOn()
refpolyMapper.SetLookupTable(lut)
refpolyMapper2D = vtk.vtkPolyDataMapper2D()
refpolyMapper2D.SetTransformCoordinate(coordinate)
refpolyMapper2D.SetInput(refpoly)
refpolyMapper2D.SetScalarModeToUseCellData()
refpolyMapper2D.UseLookupTableScalarRangeOn()
refpolyMapper.SetLookupTable(lut)
refpolyMapper2D.SetLookupTable(lut)

# create actors
polyActor = vtk.vtkActor()
polyActor.SetMapper(polyMapper)
polyActor2D = vtk.vtkActor2D()
polyActor2D.SetMapper(polyMapper2D)
refpolyActor = vtk.vtkActor()
refpolyActor.SetMapper(refpolyMapper)
refpolyActor2D = vtk.vtkActor2D()
refpolyActor2D.SetMapper(refpolyMapper2D)

# create renderers
renderer = vtk.vtkRenderer()
renderer.SetViewport(0, 0, 0.5, 1.0)
renderer.AddActor(polyActor)
renderer.AddActor(refpolyActor)
renderer2D = vtk.vtkRenderer()
renderer2D.SetViewport(0.5, 0.0, 1.0, 1.0)
renderer2D.AddActor(polyActor2D)
renderer2D.AddActor(refpolyActor2D)

# render it
renderWindow = vtk.vtkRenderWindow()
renderWindow.SetSize(600,300)
renderWindow.AddRenderer(renderer)
renderWindow.AddRenderer(renderer2D)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renderWindow)
renderWindow.Render()
iren.Start()




More information about the vtkusers mailing list