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.

No comments:

Post a Comment

So, what did you think?