Description of _surface module

The _surface module is for displaying surfaces in Chimera. It was developed for displaying isosurfaces of volume data. Chimera has other ways of displaying surfaces, MSMS models (molecular surfaces) and VRML models, that are independent of this module.

The _surface module defines Surface_Model and Surface_Group objects in file surfmodel.h that are available from Python. There is a program testgeom.py that can be imported using the Chimera Python shell (IDLE) that demonstrates the use of this module.

Surface Specification

A surface is described as a set of triangles or quadrilaterals. The triangles or quadrilaterals are defined in two arrays. One array contains the vertex xyz positions. If there are N vertices the array is of size N by 3. The second array gives 3 indices for each triangle or 4 indices for each quadrilateral. These are indices into the vertex xyz position array. This method of representing the surface saves some space since each vertex is used in about 6 triangles in typical triangulated surfaces.

Here is an example that makes surface model with 2 triangles.

import _surface
m = _surface.Surface_Model()

# Xyz positions must be 32-bit floating point values.
import Numeric
v = Numeric.array(((0.,0,0), (1,0,0), (0,1,0), (0,0,1)), Numeric.Float32)  # xyz vertex positions
vi = ((0, 1, 2), (3, 0, 2))		   # define two triangles.
rgba = (1,0,0,.5)			   # partially transparent red.

m.add_group(v, vi, rgba)

import chimera
chimera.openModels.add([m])

The vertex position array must contain floating point values. The index array must contain integer values. The arrays can be nested tuples, or lists, or Numeric Python arrays can be used.

Surface Groups

A surface model can display several sets of triangles or quadrilaterals. The sets are called surface groups. The Surface_Model.add_group() method creates a Surface_Group. Surface groups can be individually added and removed from a Surface_Model. They do not share vertex xyz arrays or any other properties. Their original purpose was for showing multiple isosurfaces of volume data in a single Chimera model.

Surface Group Features

A Surface_Group has methods from controlling its display.

Caution. When defining a triangulated surface it is important to specify the 3 triangle vertices in a consistent order, so that the normal vectors all point towards the same side of the surface. Otherwise the shading produced by lighting will be messed up. Surface normals are calculated for each vertex by adding up the normals of the triangles that share that vertex, then scaling to make the sum have unit length. The orientation of the triangle normals is based on the ordering of the 3 vertices that make up a triangle, and the normal orientation surface group attribute.

Example

import _surface
m = _surface.Surface_Model()
import chimera
chimera.openModels.add([m])

import Numeric
v = Numeric.array(((0.,0,0), (1,0,0), (0,1,0), (0,0,1)), Numeric.Float32)  # xyz vertex positions.
vi = ((0, 1, 2), (3, 0, 2))		   # define two triangles.
rgba = (1,0,0,.5)			   # partially transparent red.

g = m.add_group(v, vi, rgba)		# This returns a Surface_Group

g.display = 0				# hide the group
g.display = 1				# show the group

g.set_display_style(g.Mesh)
g.set_display_style(g.Solid)		# default

g.set_color(0,0,1,1)			# change color to blue

#
# Set the 4 vertices to be red, green, blue and white.
# These values must be floating point.
# This overrides the previous setting of the group to blue.
#	
g.set_vertex_colors( [(1.,0,0,1),(0,1,0,1),(0,0,1,1),(1,1,1,1)] )

#
# Clear the vertex colors.  Group will be blue again.
#
g.set_vertex_colors(None)

g.set_use_lighting(0)		# Lighting off
g.set_use_lighting(1)		# Lighting on (default)

g.set_two_sided_lighting(0)	# Light one side
g.set_two_sided_lighting(1)	# Light both sides (default)

g.set_normal_orientation(g.Righthanded)		# default Righthanded
g.set_normal_orientation(g.Lefthanded)

v2 = Numeric.array(((1.,0,0), (2,0,0), (0,3,0), (0,0,4)), Numeric.Float32)
vi2 = ((0, 1, 2), (3, 1, 0))
g.set_geometry(v2, vi2)		# Change the surface for this group

v3 = Numeric.array(((0.,1,2), (0,2,3), (0,5,0), (1,1,0)), Numeric.Float32)
vi3 = ((1, 0, 2), (3, 2, 0))
rgba3 = (1,0,1,1)
g3 = m.add_group(v3, vi3, rgba3)	# Make another group