Aug 26, 2009

VTK displaying finite element mesh using vtkunstructuredgrid from data file of coordinates

Hi guys,

Just wanted to show you my current working code. I am displaying a finite element mesh, using a vtkunstructuredgrid. The data consists of data points starting from 1, their coordinates, as well as connectivity info, that is, how the points connect to form cells/ elements.

Here it is below:

#!/usr/bin/env python

# Author: Helvin Lui

# This is a function, which takes a string parameter: file_path. This string is
# the path of the geometry txt file from which vtk will grab and display data.

def displayMesh(file_path):
import vtk
from vtk import vtkTriangle, vtkQuad
VTK_TRIANGLE = vtkTriangle().GetCellType()
VTK_QUAD = vtkQuad().GetCellType()
with open(file_path, 'r') as f:
aMeshGrid = vtk.vtkUnstructuredGrid()
# The numbers in the bracket below does not appear to make a huge difference.
# I read somewhere that its only an estimate of something...
aMeshGrid.Allocate(2, 180)
# Get number of mesh points
no_points = int(f.readline())
# Set number of points
meshPoints = vtk.vtkPoints()
meshPoints.SetNumberOfPoints(no_points)
# Iterate through point data
for i in range(no_points):
# Get coord info for each point
point_info = f.readline().split() # I need to split, before I assign to point_coord
# else the whole thing is split into single numbers
point_ID = (int(point_info[0])-1) # -1 because the IDs need to start with 0.
point_x = float(point_info[1])
point_y = float(point_info[2])
point_z = float(point_info[3])
# Set coord info in mesh
meshPoints.InsertPoint(point_ID, point_x, point_y, point_z)
# Get number of elements
no_elements = int(f.readline())
# Set number of elements
for i in range(no_elements):
element_info = f.readline().split()
element_ID = (int(element_info[0])-1)
element_no_nodes = int(element_info[1])
element_ID_list = vtk.vtkIdList()
for j in range(element_no_nodes):
node_no = int(element_info[j+2])
element_ID_list.InsertNextId(node_no -1)
print j, node_no
if element_no_nodes == 3: # a triangle
cell_type = VTK_TRIANGLE
elif element_no_nodes == 4: # a rectangle/quad
cell_type = VTK_QUAD
aMeshGrid.InsertNextCell(cell_type, element_ID_list)
aMeshGrid.SetPoints(meshPoints)
aMeshMapper = vtk.vtkDataSetMapper()
aMeshMapper.SetInput(aMeshGrid)
aMeshActor = vtk.vtkActor()
aMeshActor.AddPosition(0,0,0)
aMeshActor.SetMapper(aMeshMapper)
aMeshActor.GetProperty().SetDiffuseColor(0, 0.5, 0)
aMeshActor.GetProperty().SetEdgeVisibility(1)
aMeshActor.GetProperty().SetEdgeColor(1, 0, 0)

# Create the usual rendering stuff.
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
renWin.SetSize(300, 300)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
ren.AddActor(aMeshActor)
ren.ResetCamera()
cam1 = ren.GetActiveCamera()
## Render the scene and start interaction.
iren.Initialize()
renWin.Render()
iren.Start()

The data file that you might display could look like this:

7
1 1.000000000 0.000000000 0.000000000
2 3.000000000 0.000000000 0.000000000
3 0.000000000 2.000000000 0.000000000
4 2.000000000 2.000000000 0.000000000
5 4.000000000 2.000000000 0.000000000
6 1.000000000 4.000000000 0.000000000
7 3.000000000 4.000000000 0.000000000
6
1 3 1 4 3
2 3 1 2 4
3 3 2 5 4
4 3 3 4 6
5 3 4 7 6
6 3 4 5 7

It is essentially 'the number of points', then a list of point IDs and their coordinates, then 'the number of elements', then a list of point IDs and their shape (no. of sides; in this case, the elements are triangles), and the coordinates.

Note that I was getting problems with the point IDs, because my data file's IDs started with 1. However, vtk numbering starts with 0. So I needed to '-1' (in red font above) whenever I accessed point numbers. So you will need to be careful if your data points start at 1.

Aug 4, 2009

Actor Color / Colour Change

I am using VTK (Visualization Toolkit) to display a shape, read in from a file called test.vtk
I am coding in Python. I want to be able to change the shape from the default redish to a blue.
According to http://www.vtk.org/VTK/help/examplecode.html, a tried drawing a blue sphere, in python. It worked.

from vtk import *
sphere = vtkSphereSource()
sphere.SetRadius(1.0)
sphere.SetThetaResolution(18)
sphere.SetPhiResolution(18)
map = vtkPolyDataMapper()
map.SetInput(sphere.GetOutput())
aSphere = vtkActor()
aSphere.SetMapper(map)
aSphere.GetProperty().SetColor(0,0,1)
ren1 = vtkRenderer()
renWin = vtkRenderWindow()
renWin.AddRenderer(ren1)
iren = vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
ren1.AddActor(aSphere)
ren1.SetBackground(1,1,1)
renWin.Render()
iren.Start()

Problem:

However, when I changed the code to read in my data file, test.vtk, it did not work. By this, I mean that the shape was still drawn, but it was redish, and not blue. The first few lines of the above were changed to:

from vtk import *
Reader = vtkUnstructuredGridReader()
Reader.SetFileName("test.vtk")
sphere = Reader # cone is an unstructured grid

map = vtkDataSetMapper()
map.SetInput(sphere.GetOutput())
#
aSphere = vtkActor()

etc...as above.


Solution:

Add this line:

map.ScalarVisibilityOff()

at the place where the '#' is positioned above.

Why?

The colour in the actor’s property only takes effect if there is no scalar data available to the actor’s mapper. By default, the mapper’s input scalar data colours the actor, and the actor’s colour is ignored. To ignore the scalar data, use the method ScalarVisibilityOff().

(Taken from the book: The VTK User's Guide; updated for VTK Version 5)