Description of _surface module

Chimera version 1.2540 (July 9, 2008)

The _surface module is for displaying surfaces in Chimera. It was developed for displaying isosurfaces of volume data. Chimera has a second way to display surfaces: VRML models.

The _surface module defines SurfaceModel and SurfacePiece objects that are available from Python. These objects are defined in the C++ header file surfmodel.h.

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.SurfaceModel()

# 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.addPiece(v, vi, rgba)

import chimera

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 numpy arrays can be used.

Surface Pieces

A surface model can display several sets of triangles. The sets are called surface pieces. The SurfaceModel.addPiece() method creates a SurfacePiece. Surface pieces can be individually added and removed from a SurfaceModel. 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 not look right. For volume surfaces, the data gradient direction is used for lighting normals. In other cases surface normals can be 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.


import _surface
m = _surface.SurfaceModel()

import chimera

# For minimum memory use and maximum speed use NumPy arrays for vertices
# and triangles.
from numpy import array, single as floatc, 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)

p = m.addPiece(v, vi, rgba)		# This returns a Surface_Piece

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

p.displayStyle = p.Mesh
p.displayStyle = p.Solid		# default

p.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.
p.vertexColors = [(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.
p.vertexColors = None

p.useLighting = False		# Lighting off
p.useLighting = True		# Lighting on (default)

p.twoSidedLighting = False 	# Light one side
p.twoSidedLighting = True  	# Light both sides (default)

p.save_in_session = True	# Include when saving sessions

v2 = array(((1.,0,0), (2,0,0), (0,3,0), (0,0,4)), floatc)
vi2 = array(((0,1,2), (3,1,0)), intc)
p.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)
p3 = m.addPiece(v3, vi3, rgba3)	# Make another piece