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_Piece 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 that 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. 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 vertex positions.
v = [(0,0,0), (1.5,0,0), (0,1.2,0), (0,0,2.3)]

# Define two triangles each defined by 3 indices into vertex list.
vi = [(0,1,2), (3,0,2)]

# Color specified as red, green, blue, opacity (0-1), partially transparent red.
rgba = (1,0,0,.5)

m.add_piece(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 Pieces

A surface model can display several sets of triangles. The sets are called surface pieces. The Surface_Model.add_piece() method creates a Surface_Piece. Surface pieces 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 Piece Features

A Surface_Piece 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 piece attribute.

Example

import _surface
m = _surface.Surface_Model()

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

# For minimum memory use and maximum speed use NumPy arrays for vertices
# and triangles.
from numpy import array, single as floatc, intc

# For Chimera versions 1.2318 and older use Numeric instead of NumPy.
# from Numeric import array, Float32 as floatc, Int32 as intc

# Xyz vertex positions.
v = array(((0,0,0), (1.5,0,0), (0,1.2,0), (0,0,2.3)), floatc)

# Define two triangles each defined by 3 indices into vertex list.
vi = array(((0,1,2), (3,0,2)), intc)

# Color specified as red, green, blue, opacity (0-1), partially transparent red.
rgba = (1,0,0,.5)

g = m.add_piece(v, vi, rgba)		# This returns a Surface_Piece

g.display = False			# hide the piece
g.display = True			# show the piece

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 piece 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.  Piece will be blue again.
g.set_vertex_colors(None)

g.set_use_lighting(False)		# Lighting off
g.set_use_lighting(True)		# Lighting on (default)

g.set_two_sided_lighting(False) 	# Light one side
g.set_two_sided_lighting(True)  	# Light both sides (default)

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

v2 = array(((1.,0,0), (2,0,0), (0,3,0), (0,0,4)), floatc)
vi2 = array(((0,1,2), (3,1,0)), intc)
g.set_geometry(v2, vi2)		# Change the surface for this piece

v3 = array(((0.,1,2), (0,2,3), (0,5,0), (1,1,0)), floatc)
vi3 = array(((1,0,2), (3,2,0)), intc)
rgba3 = (1,0,1,1)
g3 = m.add_piece(v3, vi3, rgba3)	# Make another piece