[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