[vtkusers] VTK24 vs. 312, quality and performance

Tom G. Smith (B75826) smitty at kcc.com
Thu Mar 22 16:12:31 EST 2001


Some time ago I posted a message about a significant difference in rendering
quality and speed, VTK 2.4 versus VTK 3.1.2.  I didn't do a very good job
of describing the problem then, and I'm going to try again.  I have two
environments:

	1.	SGI Dual Processor Octane, 1G memory, IRIX 6.5,
		VTK 2.4 compiled w/OpenGL.

	2.	Compaq Proliant, 2 450Mhz processors, 320M memory,
		RedHat Linux 7.0,
		VTK 3.1.2 compiled w/Mesa.

The hardware difference isn't really significant.  I'm doing all my
rendering from both systems using HCL/eXceed under Windows 95 on an
old Toshiba 510 with 32M memory, with no graphics accelerator card.
That sort of levels the playing field :-)

Prior to upgrading to RH7 and VTK 3.1.2, the renderings from the
Linux box were comparable to those from the SGI system, and I only
noticed a significant degradation in performance and rendering
quality after the upgrade.  I don't have another Linux system still
running vtk 2.4, so I was forced to use the SGI for the comparison.

The scripts I used to make the performance and rendering comparisons
are identical on both hosts.  I picked a really simple Tcl/Tk script
that renders a five-pointed star.  That script and the stuff it
sources are attached.  Here's the two commands I used on both systems:

	vtk star.tcl -- -c yellow
	vtk star.tcl -- -c yellow -w

The first brings up the Interactor, and the second generates an animated
gif file, showing the star rotating 360 degrees about its vertical axis.
Here's the sizes of the two gif files, and as you can see, the one from
VTK 3.1.2 is over 12 times the size of the gif from VTK 2.4:

	-rw-r--r-- 1 smitty mst   65589 Mar 22 14:06 star24.gif
	-rw-r--r-- 1 smitty mst  805580 Mar 22 13:29 star312.gif

To give some measure of the difference in performance, using the
Interactor, I left-clicked and dragged from the center to the edge
of the rendering window, which of course causes the image to rotate.
Then I timed the rotation through 360 degrees.  The rendering from
VTK 2.4 takes 16 seconds, and that from vtk312 72 seconds, 4.5
times longer.

I can't attach the gif files, because it'd make this posting too
big to get onto Kitware's list server, so you'll just have to take
my word that the one from VTK 3.1.2 looks very bad compared to that
from VTK 2.4.

star.tcl:
...........................................................................
#!/usr/bin/tcl
#-----------------------------------------------------------------------
# Description:  Generates an n-pointed 3D star.
# Syntax: vtk star.tcl [-- [-c <color>] [-s <size>] [-w] [-x] [-y] [-z]]
#-----------------------------------------------------------------------
# Changelog:
# 000323 Smitty created.
#-----------------------------------------------------------------------
#set Debug 1

# ---------------------------------------------------------------
# Initialize constants.
if {![regexp {^(.*/)([^/]+$)} $argv0 dummy dirname basename]} {
	# dirname is the path to this executable, e.g. /home/smitty/vtkstuff/,
	# and basename will be "star.tcl".
	set dirname ./
	set basename $argv0
}
set dirname "$dirname/common"
source "$dirname/startup.tcl" ;# Initialize vtk.
source "$dirname/colors.tcl" ;# Define colors
source "$dirname/getopts.tcl"; # Get the getopts and defaultopts routines.

set Pi [expr acos(-1)] ;# Approx. 3.14159265359
set Pitwice [expr $Pi*2.0] ;# Radians of full circumference.
set tips 5 ;# Five pointed star.
set height 2 ;# Diameter at star tips.
set depth [expr $height/4.0] ;# Depth of star, front-to-back.
set radius [expr $height/2.0] ;# Radius of circle at star tips.
set inner_radius $depth ;# Radius of circle where star tip edges intersect.
set c cornflower ;# Default color
set w 0 ;# Default is not to produce animation.
set s 300 ;# Default size of image.
set x 0
set y 0
set z 0

# ---------------------------------------------------------------
# Mainline starts here.
getopts {c:s:wxyz}; # Get command line arguments.

# Now build vtkPoints object.
set pointcount [expr $tips*2+2]
cmd [list "vtkPoints points"]
cmd [list "points SetNumberOfPoints $pointcount"]
cmd [list "points InsertPoint 0 [expr $depth/2] 0 0"] ;# Front center point.
set a 0 ;# Angle of first star tip.
set aincr [expr $Pitwice/$tips] ;# Angle between star tips.
set bincr [expr $aincr/2] ;# Angle increment to intersection of star tip edges.
set n 1 ;# Point index, relative 0.
set xp 0 ;# Plane bisecting star.
while {$a < $Pitwice} {
	foreach r [list $radius $inner_radius] {
		set yp [expr cos($a)*$r]
		set zp [expr sin($a)*$r]
		cmd [list "points InsertPoint $n $xp $yp $zp"]
		incr n
		set a [expr $a+$bincr] ;# Bump to angle of next defining point.
	}
}
cmd [list "points InsertPoint $n [expr -$depth/2] 0 0"] ;# Back center point.

# strips will contain two cells, one for each triangle strip, front and back.
cmd [list "vtkCellArray strips"]
foreach k [list 0 [expr $pointcount-1]] {
	cmd [list "strips InsertNextCell [expr $tips*3+2]"]
	set p 0
	while {$p < $tips*2} {
		cmd [list "strips InsertCellPoint $k"] ;# Front/Back Center
		cmd [list "strips InsertCellPoint [expr $p+1]"] ;# Star tip
		cmd [list "strips InsertCellPoint [expr $p+2]"] ;# intersection.
		incr p 2
	}
	cmd [list "strips InsertCellPoint $k"] ;# Front/Back Center
	cmd [list "strips InsertCellPoint 1"]
}

cmd [list\
	"vtkPolyData polydata"\
	"polydata SetPoints points"\
	"polydata SetStrips strips"\
	"vtkPolyDataMapper map"\
	"map SetInput polydata"\
	"vtkActor actor"\
	"actor SetMapper map"]
cmd [list\
	"eval {[actor GetProperty] SetColor } $colors($c)"\
	"[actor GetProperty] BackfaceCullingOff"\
	"ren1 AddActor actor"\
	"actor RotateY 90"\
	"ren1 SetBackground 1 1 1"]
if {$w} {
	source "$dirname/whirl.tcl" ;# Generate images for animation.
	if {![expr $x+$y+$z]} { set y 1; }
	whirl $s $s  whirl 10 $x $y $z
} else {
	go $s $s ;# start the Interactor and display the image.
}
...........................................................................

common/cmd.tcl:
...........................................................................
#!/usr/bin/tcl
#-----------------------------------------------------------------------
# Description:  This Tcl script can be sourced to get the typical
# code to run vtk commands, and optionally print them on stderr.
#-----------------------------------------------------------------------
# Changelog:
# 000323 Smitty created.
#-----------------------------------------------------------------------
set cmd_include 1 ;# Indicates this file already included.
if {![info exists Debug]} { set Debug 0; }
proc cmd {cmds} {
# ---------------------------------------------------------------
# Called to run a list of vtk commands.
# ---------------------------------------------------------------
	global Debug
	foreach cmd $cmds {
		if {$Debug} { puts stderr $cmd; }
		eval $cmd
	}
} ;# End cmd.
...........................................................................

common/colors.tcl:
...........................................................................
#-----------------------------------------------------------------------
# Description:  This Tcl script can be sourced to build an array of
# RGB color values.  It's a copy of /opt/vtk/examplesTcl/colors.tcl,
# with a lot of changes.
#-----------------------------------------------------------------------
# Changelog:
# 991020 Smitty created.
#-----------------------------------------------------------------------

#  Whites
set colors(antique_white)  "0.9804 0.9216 0.8431"
set colors(azure)  "0.9412 1.0000 1.0000"
set colors(bisque)  "1.0000 0.8941 0.7686"
set colors(blanched_almond)  "1.0000 0.9216 0.8039"
set colors(cornsilk)  "1.0000 0.9725 0.8627"
set colors(eggshell)  "0.9900 0.9000 0.7900"
set colors(floral_white)  "1.0000 0.9804 0.9412"
set colors(gainsboro)  "0.8627 0.8627 0.8627"
set colors(ghost_white)  "0.9725 0.9725 1.0000"
set colors(honeydew)  "0.9412 1.0000 0.9412"
set colors(ivory)  "1.0000 1.0000 0.9412"
set colors(lavender)  "0.9020 0.9020 0.9804"
set colors(lavender_blush)  "1.0000 0.9412 0.9608"
set colors(lemon_chiffon)  "1.0000 0.9804 0.8039"
set colors(linen)  "0.9804 0.9412 0.9020"
set colors(mint_cream)  "0.9608 1.0000 0.9804"
set colors(misty_rose)  "1.0000 0.8941 0.8824"
set colors(moccasin)  "1.0000 0.8941 0.7098"
set colors(navajo_white)  "1.0000 0.8706 0.6784"
set colors(old_lace)  "0.9922 0.9608 0.9020"
set colors(papaya_whip)  "1.0000 0.9373 0.8353"
set colors(peach_puff)  "1.0000 0.8549 0.7255"
set colors(seashell)  "1.0000 0.9608 0.9333"
set colors(snow)  "1.0000 0.9804 0.9804"
set colors(thistle)  "0.8471 0.7490 0.8471"
set colors(titanium_white)  "0.9900 1.0000 0.9400"
set colors(wheat)  "0.9608 0.8706 0.7020"
set colors(white)  "1.0000 1.0000 1.0000"
set colors(white_smoke)  "0.9608 0.9608 0.9608"
set colors(zinc_white)  "0.9900 0.9700 1.0000"

#  Greys
set colors(cold_grey)  "0.5000 0.5400 0.5300"
set colors(dim_grey)  "0.4118 0.4118 0.4118"
set colors(grey)  "0.7529 0.7529 0.7529"
set colors(light_grey)  "0.8275 0.8275 0.8275"
set colors(slate_grey)  "0.4392 0.5020 0.5647"
set colors(slate_grey_dark)  "0.1843 0.3098 0.3098"
set colors(slate_grey_light)  "0.4667 0.5333 0.6000"
set colors(warm_grey)  "0.5000 0.5000 0.4100"

#  Blacks
set colors(black)  "0.0000 0.0000 0.0000"
set colors(ivory_black)  "0.1600 0.1400 0.1300"
set colors(lamp_black)  "0.1800 0.2800 0.2300"

#  Reds
set colors(alizarin_crimson)  "0.8900 0.1500 0.2100"
set colors(brick)  "0.6100 0.4000 0.1200"
set colors(cadmium_red_deep)  "0.8900 0.0900 0.0500"
set colors(coral)  "1.0000 0.4980 0.3137"
set colors(coral_light)  "0.9412 0.5020 0.5020"
set colors(deep_pink)  "1.0000 0.0784 0.5765"
set colors(english_red)  "0.8300 0.2400 0.1000"
set colors(firebrick)  "0.6980 0.1333 0.1333"
set colors(geranium_lake)  "0.8900 0.0700 0.1900"
set colors(hot_pink)  "1.0000 0.4118 0.7059"
set colors(indian_red)  "0.6900 0.0900 0.1200"
set colors(light_salmon)  "1.0000 0.6275 0.4784"
set colors(madder_lake_deep)  "0.8900 0.1800 0.1900"
set colors(maroon)  "0.6902 0.1882 0.3765"
set colors(pink)  "1.0000 0.7529 0.7961"
set colors(pink_light)  "1.0000 0.7137 0.7569"
set colors(raspberry)  "0.5300 0.1500 0.3400"
set colors(red)  "1.0000 0.0000 0.0000"
set colors(rose_madder)  "0.8900 0.2100 0.2200"
set colors(salmon)  "0.9804 0.5020 0.4471"
set colors(tomato)  "1.0000 0.3882 0.2784"
set colors(venetian_red)  "0.8300 0.1000 0.1200"

#  Browns
set colors(beige)  "0.6400 0.5800 0.5000"
set colors(brown)  "0.5000 0.1647 0.1647"
set colors(brown_madder)  "0.8600 0.1600 0.1600"
set colors(brown_ochre)  "0.5300 0.2600 0.1200"
set colors(burlywood)  "0.8706 0.7216 0.5294"
set colors(burnt_sienna)  "0.5400 0.2100 0.0600"
set colors(burnt_umber)  "0.5400 0.2000 0.1400"
set colors(chocolate)  "0.8235 0.4118 0.1176"
set colors(deep_ochre)  "0.4500 0.2400 0.1000"
set colors(flesh)  "1.0000 0.4900 0.2500"
set colors(flesh_ochre)  "1.0000 0.3400 0.1300"
set colors(gold_ochre)  "0.7800 0.4700 0.1500"
set colors(greenish_umber)  "1.0000 0.2400 0.0500"
set colors(khaki)  "0.9412 0.9020 0.5490"
set colors(khaki_dark)  "0.7412 0.7176 0.4196"
set colors(light_beige)  "0.9608 0.9608 0.8627"
set colors(peru)  "0.8039 0.5216 0.2471"
set colors(rosy_brown)  "0.7373 0.5608 0.5608"
set colors(raw_sienna)  "0.7800 0.3800 0.0800"
set colors(raw_umber)  "0.4500 0.2900 0.0700"
set colors(sepia)  "0.3700 0.1500 0.0700"
set colors(sienna)  "0.6275 0.3216 0.1765"
set colors(saddle_brown)  "0.5451 0.2706 0.0745"
set colors(sandy_brown)  "0.9569 0.6431 0.3765"
set colors(tan)  "0.8235 0.7059 0.5490"
set colors(van_dyke_brown)  "0.3700 0.1500 0.0200"

#  Oranges
set colors(cadmium_orange)  "1.0000 0.3800 0.0100"
set colors(cadmium_red_light)  "1.0000 0.0100 0.0500"
set colors(carrot)  "0.9300 0.5700 0.1300"
set colors(dark_orange)  "1.0000 0.5490 0.0000"
set colors(mars_orange)  "0.5900 0.2700 0.0800"
set colors(mars_yellow)  "0.8900 0.4400 0.1000"
set colors(orange)  "1.0000 0.5000 0.0000"
set colors(orange_red)  "1.0000 0.2706 0.0000"
set colors(yellow_ochre)  "0.8900 0.5100 0.0900"

#  Yellows
set colors(aureoline_yellow)  "1.0000 0.6600 0.1400"
set colors(banana)  "0.8900 0.8100 0.3400"
set colors(cadmium_lemon)  "1.0000 0.8900 0.0100"
set colors(cadmium_yellow)  "1.0000 0.6000 0.0700"
set colors(cadmium_yellow_light)  "1.0000 0.6900 0.0600"
set colors(gold)  "1.0000 0.8431 0.0000"
set colors(goldenrod)  "0.8549 0.6471 0.1255"
set colors(goldenrod_dark)  "0.7216 0.5255 0.0431"
set colors(goldenrod_light)  "0.9804 0.9804 0.8235"
set colors(goldenrod_pale)  "0.9333 0.9098 0.6667"
set colors(light_goldenrod)  "0.9333 0.8667 0.5098"
set colors(melon)  "0.8900 0.6600 0.4100"
set colors(naples_yellow_deep)  "1.0000 0.6600 0.0700"
set colors(yellow)  "1.0000 1.0000 0.0000"
set colors(yellow_light)  "1.0000 1.0000 0.8784"

#  Greens
set colors(chartreuse)  "0.4980 1.0000 0.0000"
set colors(chrome_oxide_green)  "0.4000 0.5000 0.0800"
set colors(cinnabar_green)  "0.3800 0.7000 0.1600"
set colors(cobalt_green)  "0.2400 0.5700 0.2500"
set colors(emerald_green)  "0.0000 0.7900 0.3400"
set colors(forest_green)  "0.1333 0.5451 0.1333"
set colors(green)  "0.0000 1.0000 0.0000"
set colors(green_dark)  "0.0000 0.3922 0.0000"
set colors(green_pale)  "0.5961 0.9843 0.5961"
set colors(green_yellow)  "0.6784 1.0000 0.1843"
set colors(lawn_green)  "0.4863 0.9882 0.0000"
set colors(lime_green)  "0.1961 0.8039 0.1961"
set colors(mint)  "0.7400 0.9900 0.7900"
set colors(olive)  "0.2300 0.3700 0.1700"
set colors(olive_drab)  "0.4196 0.5569 0.1373"
set colors(olive_green_dark)  "0.3333 0.4196 0.1843"
set colors(permanent_green)  "0.0400 0.7900 0.1700"
set colors(sap_green)  "0.1900 0.5000 0.0800"
set colors(sea_green)  "0.1804 0.5451 0.3412"
set colors(sea_green_dark)  "0.5608 0.7373 0.5608"
set colors(sea_green_medium)  "0.2353 0.7020 0.4431"
set colors(sea_green_light)  "0.1255 0.6980 0.6667"
set colors(spring_green)  "0.0000 1.0000 0.4980"
set colors(spring_green_medium)  "0.0000 0.9804 0.6039"
set colors(terre_verte)  "0.2200 0.3700 0.0600"
set colors(viridian_light)  "0.4300 1.0000 0.4400"
set colors(yellow_green)  "0.6039 0.8039 0.1961"

#  Cyans
set colors(aquamarine)  "0.4980 1.0000 0.8314"
set colors(aquamarine_medium)  "0.4000 0.8039 0.6667"
set colors(cyan)  "0.0000 1.0000 1.0000"
set colors(cyan_white)  "0.8784 1.0000 1.0000"
set colors(turquoise)  "0.2510 0.8784 0.8157"
set colors(turquoise_dark)  "0.0000 0.8078 0.8196"
set colors(turquoise_medium)  "0.2824 0.8196 0.8000"
set colors(turquoise_pale)  "0.6863 0.9333 0.9333"

#  Blues
set colors(alice_blue)  "0.9412 0.9725 1.0000"
set colors(blue)  "0.0000 0.0000 1.0000"
set colors(blue_light)  "0.6784 0.8471 0.9020"
set colors(blue_medium)  "0.0000 0.0000 0.8039"
set colors(cadet)  "0.3725 0.6196 0.6275"
set colors(cobalt)  "0.2400 0.3500 0.6700"
set colors(cornflower)  "0.3922 0.5843 0.9294"
set colors(cerulean)  "0.0200 0.7200 0.8000"
set colors(dodger_blue)  "0.1176 0.5647 1.0000"
set colors(indigo)  "0.0300 0.1800 0.3300"
set colors(manganese_blue)  "0.0100 0.6600 0.6200"
set colors(midnight_blue)  "0.0980 0.0980 0.4392"
set colors(navy)  "0.0000 0.0000 0.5020"
set colors(peacock)  "0.2000 0.6300 0.7900"
set colors(powder_blue)  "0.6902 0.8784 0.9020"
set colors(royal_blue)  "0.2549 0.4118 0.8824"
set colors(slate_blue)  "0.4157 0.3529 0.8039"
set colors(slate_blue_dark)  "0.2824 0.2392 0.5451"
set colors(slate_blue_light)  "0.5176 0.4392 1.0000"
set colors(slate_blue_medium)  "0.4824 0.4078 0.9333"
set colors(sky_blue)  "0.5294 0.8078 0.9216"
set colors(sky_blue_deep)  "0.0000 0.7490 1.0000"
set colors(sky_blue_light)  "0.5294 0.8078 0.9804"
set colors(steel_blue)  "0.2745 0.5098 0.7059"
set colors(steel_blue_light)  "0.6902 0.7686 0.8706"
set colors(turquoise_blue)  "0.0000 0.7800 0.5500"
set colors(ultramarine)  "0.0700 0.0400 0.5600"

#  Magentas
set colors(blue_violet)  "0.5412 0.1686 0.8863"
set colors(cobalt_violet_deep)  "0.5700 0.1300 0.6200"
set colors(magenta)  "1.0000 0.0000 1.0000"
set colors(orchid)  "0.8549 0.4392 0.8392"
set colors(orchid_dark)  "0.6000 0.1961 0.8000"
set colors(orchid_medium)  "0.7294 0.3333 0.8275"
set colors(permanent_red_violet)  "0.8600 0.1500 0.2700"
set colors(plum)  "0.8667 0.6275 0.8667"
set colors(purple)  "0.6275 0.1255 0.9412"
set colors(purple_medium)  "0.5765 0.4392 0.8588"
set colors(ultramarine_violet)  "0.3600 0.1400 0.4300"
set colors(violet)  "0.5600 0.3700 0.6000"
set colors(violet_dark)  "0.5804 0.0000 0.8275"
set colors(violet_red)  "0.8157 0.1255 0.5647"
set colors(violet_red_medium)  "0.7804 0.0824 0.5216"
set colors(violet_red_pale)  "0.8588 0.4392 0.5765"

proc showcolors {} {
#------------------------------------------------------------------
# Called to display all the possible color names.
#------------------------------------------------------------------
	global colors
	
	foreach key [lsort [array names colors]] {
		set value $colors($key)
		puts "$key=$value"
	}
} ;# End showcolors.

proc tablecolors {tablename colornames {count 0}} {
#------------------------------------------------------------------
# Called to build a vtkLookupTable object based on a list of
# color names.  If count is greater than the number of colors in
# colornames, the table will be built with $count entries and the
# colors in colornames will be cycled to fill out the table.
#------------------------------------------------------------------
	global colors

	if {$count < 1} { set count [llength $colornames]; }
	upvar $tablename lut
	vtkLookupTable lut
	lut SetNumberOfColors $count
		# Specify the number of values (i.e., colors) in the lookup
		# table. This method simply allocates memory and prepares the
		# table for use with SetTableValue(). It differs from Build()
		# method in that the allocated memory is not initialized
		# according to HSVA ramps.
	lut SetTableRange 0 [expr $count - 1]
		# Declared as "void SetTableRange(float r[2]);" in
		# vtkLookupTable.h.  I found source for it in 
		# vtkLookupTable.cxx that looks like this, in part:
		#   void  vtkLookupTable::SetTableRange(float min, float max)
		#   { this->TableRange[0] = min; this->TableRange[1] = max; }
	lut Build
		# Build is a virtual function inherited from vtkScalarsToColors
		# class, where it's declared as "virtual void Build() {};".
		# The actual source for it is in vtkLookupTable.cxx.
		# Using pre-established (perhaps default) values for
		# HueRange, SaturationRange, ValueRange, and AlphaRange,
		# it builds the specified set of colors (see SetNumberOfColors
		# and SetTableRange above).
	set ix 0; # Color table index.
	set jx 0; # Color name index.
	while {$ix < $count} {
		set name [lindex $colornames $jx]
		incr jx
		if {$jx == [llength $colornames]} { set jx 0; }
		if {![info exists colors($name)]} {
			puts "ERROR: Color $name is not defined."
			exit 1
		}
		set cmd "lut SetTableValue $ix $colors($name) 1"
		eval $cmd
			# SetTableValue expects 5 arguments:
			# 1.	The index (relative 0) of the colortable entry
			#	to be set.
			# 2.	The red component of the RGB value.
			#	A number from 0 to 1.
			# 3.	The green component of the RGB value.
			#	A number from 0 to 1.
			# 4.	The blue component of the RGB value.
			#	A number from 0 to 1.
			# 5.	The alpha, or transparency, component.
			#	A number from 0 to 1, 1 being totally opaque.
		incr ix
	}
} ;# End tablecolors.
...........................................................................

common/getopts.tcl:
...........................................................................
#!/usr/bin/tcl
#-----------------------------------------------------------------------
# Description:  When sourced in a Tcl script run under vtk, enables
# subroutine getopts that reads the command line arguments and
# sets global variables accordingly, and defaultopt that can be
# invoked to set a default.
#-----------------------------------------------------------------------
# Changelog:
# 991013 Smitty created.
# 991207 Smitty modified to properly handle positional parameters, and to
#	check for duplicate use of keywords.
# 000613 Smitty moved getopts.tcl to /usr/local/bin on random.
#-----------------------------------------------------------------------
if {![info exists Debug]} { set Debug 0; }

if {![info exists getopts_include]} {
set getopts_include 1

proc defaultopt {opt {default 0}} {
#-----------------------------------------------------------------------
# Called to set the default for a command line argument.
#-----------------------------------------------------------------------
	upvar $opt t
	if {![info exists t]} {
		set t $default
	}
} ;# End defaultopt.

proc getopts {optstr} {
#-----------------------------------------------------------------------
# Called to get the command line arguments.
# optstr contains the option letters to be recognized.
# ->	Each option letter may optionally be followed by a slash-delimited
#	name.  If the option letter is found on the command line, the
#	global variable with that name will either be set
#	to the argument (see below), or if there is no argument expected,
#	will be set to 1 to indicate the option letter was found.
#	If not supplied, the name used will be the option letter itself.
# ->	If a letter, and possibly its slash-delimited name (see above) is
#	followed by a colon, the option is expected to
#	have an argument, which should be separated from it by white
#	space on the command line.
# ->	One or more semicolons at the end of optstr each signify
#	positional parameters.  Values for positional parameters will
#	be set to corresponding locations in global list pos.
# Examples:
#-----------------------------------------------------------------------
	global argc argv Debug pos

	if {$Debug} { puts "getopts entered, optstr='$optstr'"; }
	set pos {};# Initialize pos to empty list.
	set a 0 ;# Index to command line arguments.
	while {$a < $argc} {
		set arg [lindex $argv $a];# arg = next command line argument.
		incr a
		if {$Debug} { puts "getopts loop, optstr='$optstr' arg='$arg'"; }
		set len [string length $optstr]
		if {0 == $len} {
			puts "ERROR: More arguments than expected, arg='$arg' pos='$pos'"
			exit 1
		}
		if {0 == [string first ";" $optstr]} {
			if {$Debug} { puts "nothing left but positionals"; }
			# Nothing left but positionals.
			lappend pos $arg;# Add to global positionals
			set optstr [string range $optstr 1 end]
		} else {
			if {0 != [string first - $arg]} {
				if {$Debug} { puts "No preceding hyphen, so m/b positonal = '$arg'"; }
				# No preceding hyphen, so it must be positional.
				set i [string last ";" $optstr]
				if {$i < [expr $len-1]} {
					puts "ERROR: invalid syntax in '$optstr', arg='$arg' i=$i len=$len"
					exit 1
				}
				set optstr [string range $optstr 0 [expr $len-2]]
				lappend pos $arg;# Add to global positionals
			} else {
				set b 1;# Bypass the hyphen.
				if {$Debug} { puts "setting b to 1"; }
				while {$b < [string length $arg]} {
					set letter [string index $arg $b]
					incr b
					set ret [getopts_sub $optstr $letter $a]
					if {$Debug} { puts "letter='$letter' ret='$ret'"; }
					set optstr [lindex $ret 0]
					set a [lindex $ret 1]
				}
			}
		}
	}
	if {-1 < [string last ";" $optstr]} {
		puts "ERROR: Positional arguments expected but not found."
		exit 1
	}
} ;# End getopts.

proc getopts_sub {optstr opt a} {
#-----------------------------------------------------------------------
# Called from getopts to process an option letter (opt) parsed from the
# command line. A two-item list is returned, {optstr a}, where
# optstr is updated to eliminate a keyword, indicating it's been
# used, and a is the index to argv to the next available argument.
# If the option has an argument, its value will be extracted
# from $argv and assigned to the global variable with the keyword name,
# and the index $a+1 will be returned.  Otherwise index $a
# will be returned.
#-----------------------------------------------------------------------
	global argc argv Debug
 
	if {$Debug} { puts "getopts_sub entered, optstr='$optstr' opt='$opt' a=$a"; }
	set match 0; # Indicates letter matched in optstr.
	set state 0; # Looking for option letter in optstr.
	set b 0
	while {$b < [string length $optstr]} {
		set letter [string index $optstr $b]
			# letter is next letter from optstr.
		incr b
		switch -exact -- $state {
			0 { ;# Looking for matching option letter.
				if {0 == [string compare $letter ";"]} break
				if {0 == [string compare $letter $opt]} {
					set match 1;# Indicate keyword found.
					set mix [expr $b-2]; # Save start index.
					set name $letter; # Default name.
					set value 1; # Default value.
				}
				set state 1; # Look for slash.
			  }
			1 { ;# Looking for slash.
				if {0 == [string compare $letter /]} {
					set name {}; # Empty out default name.
					while {$b < [string length $optstr]} {
						set letter [string index $optstr $b]
						incr b
						if {0 == [string compare $letter /]} break; # Found end of name.
						if {$b == [string length $optstr]} {
							puts "ERROR: missing trailing slash"
							exit 1
						}
						set name "$name$letter"
					}
				} else {
					incr b -1; # Back up parse cursor.
				}
				set state 2; # Look for colon.
			  }
			2 { ;# Looking for colon.
				if {0 == [string compare $letter {:}]} {
					if {$match} {
						if {$a == $argc} {
							puts "ERROR: $name has no argument"
							exit 1 
						}
						set value [lindex $argv $a]
						incr a
						break; # All done.
					}
					set state 0; # Look for next option.
				} else {
					incr b -1; # Back up parse cursor.
					if {$match} break
					set state 0; # Look for next option.
				}
			  }
		} ;# End switch.
	}
	if {!$match} {
		puts "ERROR: $letter is an unknown option."
		exit 1
	}
	upvar #0 $name t;# t is a synonym for global keyword name.
	set t $value;# Set keyword argument in global variable of that name.
	if {$mix} {
		# Keyword pattern isn't at front of $optstr.
		set front [string range $optstr 0 $mix]
		#set a [string length $front]
		if {$b==[string length $optstr]} {
			# Keyword pattern is at end of $optstr.
			set optstr $front
		} else {
			# Keyword pattern isn't at end of $optstr.
			set back [string range $optstr $b end]
			set optstr "$front$back"
		}
	} else {
		# Keyword pattern is at front of $optstr.
		if {$b==[string length $optstr]} {
			# Keyword pattern is at end of $optstr.
			set optstr "";# Opstring is empty.
			#set a 1
		} else {
			# Keyword pattern isn't at end of $optstr.
			set optstr [string range $optstr $b end]
			#set a 0
		}
	}
	if {$Debug} { puts "getopts_sub returning, optstr='$optstr' a=$a"; }
	return [list $optstr $a]
} ;# End getopts_sub.

}
...........................................................................

common/go.tcl:
...........................................................................
#!/usr/bin/tcl
#-----------------------------------------------------------------------
# Description:  This Tcl script can be sourced to get the typical
# vtk code to start the interactor, and to display the final image.
#-----------------------------------------------------------------------
# Changelog:
# 991013 Smitty created.
# 000323 Smitty moved interactor code from startup.tcl to here, and
#	made go invocable proc.  go.tcl is now included for you in
#	startup.tcl.
#-----------------------------------------------------------------------

proc go {{hsize 100} {vsize 100}} {
	cmd [list\
	"renWin SetSize $hsize $vsize"\
	"source /opt/vtk/examplesTcl/vtkInt.tcl"\
	"vtkRenderWindowInteractor iren"\
	"iren SetRenderWindow renWin"\
	"iren SetUserMethod {wm deiconify .vtkInteract}"\
	"iren Initialize"\
	"wm withdraw ."]
	# vtkRenderWindowInteractor is a convenience object that provides
	# event bindings to common graphics functions.  Here's a brief
	# summary.  See http://www.kitware.com/vtkhtml/vtkdata/manhtml/
	# vtkRenderWindowInteractor.html for more detail:
	# Mouse bindings:
	# 	camera: Button 1 - rotate
	# 		Button 2 - pan
	# 		Button 3 - zoom
	# 		ctrl-Button 1 - spin
	# 	actor:  Button 1 - rotate
	# 		Button 2 - pan
	# 		Button 3 - uniform scale
	# 		ctrl-Button 1 - spin
	# 		ctrl-Button 2 - dolly.
	# Keyboard bindings (upper or lower case):
	# j - joystick like mouse interactions
	# t - trackball like mouse interactions
	# o - object/actor interaction
	# c - camera interaction
	# r - reset camera view
	# w - turn all actors wireframe
	# s - turn all actors surface
	# u - execute user defined function
	# p - pick actor under mouse pointer (if pickable)
	# 3 - toggle in/out of 3D mode (if supported by renderer)
	# e - exit
	# q - exit
} ;# End go.
...........................................................................

common/startup.tcl:
...........................................................................
#!/usr/bin/tcl
#-----------------------------------------------------------------------
# Description:  This Tcl script can be sourced to get the typical
# vtk initialization.
#-----------------------------------------------------------------------
# Changelog:
# 991007 Smitty created.
# 000323 Smitty moved interactor code from here to go.tcl.
#-----------------------------------------------------------------------
catch {load vtktcl} ;# Load the shared vtk libraries.
if {![info exists dirname]} {
	if {![regexp {^(.*/)([^/]+$)} $argv0 dummy dirname basename]} {
		# dirname is the path to this executable,
		# e.g. /home/smitty/vtkstuff/,
		# and basename will be e.g. "star.tcl".
		set dirname ./
		set basename $argv0
	}
}
if {![info exists cmd_include]} { source "$dirname/cmd.tcl"; }
cmd [list\
	"vtkRenderer ren1"\
	"vtkRenderWindow renWin"\
	"renWin AddRenderer ren1"]
	# vtkRenderer provides an abstract specification for renderers. A
	# renderer is an object that controls the rendering process for
	# objects. Rendering is the process of converting geometry,
	# a specification for lights, and a camera view into an
	# image. vtkRenderer also performs coordinate transformation
	# between world coordinates, view coordinates (the computer
	# graphics rendering coordinate system), and display coordinates
	# (the actual screen coordinates on the display device). 
	#
	# vtkRenderWindow is an abstract object to specify the behavior
	# of a rendering window. A rendering window is a window
	# in a graphical user interface where renderers draw their
	# images. Methods are provided to synchronize the rendering
	# process, set window size, and control double buffering.
	#
	# Associate renderer ren1 with renWin.

source "$dirname/go.tcl" ;# Go proc starts the Interactor, displays the image.
...........................................................................

common/whirl.sh:
...........................................................................
#!/usr/bin/sh
# -----------------------------------------------------------------
# Description:
# Called by whirl.tcl.  Uses convert from ImageMagick to convert
# ppm files to gif, then invokes whirlgif to create an animation
# from the gif files.  You can see the resulting animation with -
#	animate $1.gif
# -----------------------------------------------------------------
# Changelog:
# 000324 Smitty created.
# -----------------------------------------------------------------
for i in `ls $1*.ppm | cut -d. -f1`
do
	convert $i.ppm $i.gif
	rm $i.ppm
done
whirlgif -loop 999999 -o $1.gif ${1}_[0-9][0-9][0-9].gif
rm ${1}_[0-9][0-9][0-9].gif
...........................................................................

common/whirl.tcl:
...........................................................................
#!/usr/bin/tcl
#-----------------------------------------------------------------------
# Description:  This Tcl script can be sourced to define subroutine whirl,
# which can be invoked to generate a series of ppm files that later can
# be combined to produce an animation.
#-----------------------------------------------------------------------
# Changelog:
# 000323 Smitty created.
# 000921 Smitty added the actors argument
#-----------------------------------------------------------------------

proc whirl {{hsize 100} {vsize 100} {basename whirl} {nsteps 10}
	{x 0} {y 1} {z 0} {actors actor}} {
# ---------------------------------------------------------------
# Generates a series of ppm files, with filenames of the form
# $filename_001.ppm, $filename_002.ppm, etc.  The files contain
# progressive images of the scene, with the camera rotated about
# the z axis a specified increment for each image, for a full
# 360 degrees.  Expects renWin, a vtkRenderWindow object, and
# by default, actor, a vtkActor object, to be predefined.
#
# Arguments -
# basename
#	Filenames will be $basename_001.ppm, $basename_002.ppm, etc.
#	If omitted, the default is "whirl".
# hsize
#	Horizontal size in pels of the images.
#	If omitted, the default is 100.
# vsize
#	Vertical size in pels of the images.
#	If omitted, the default is 100.
# nsteps
#	Number of images to be generated, i.e. 10 would produce
#	10 images, each rotated from the others by 36 degrees about
#	the z axis.
#	If omitted, the default is 10.
# x
#	Set to 1 if rotation is to occur about the x axis.
#	Default is 0.
# y
#	Set to 1 if rotation is to occur about the y axis.
#	Default is 1.
# z
#	Set to 1 if rotation is to occur about the z axis.
#	Default is 0.
#
# actor
#	list of actors in the rendering.  Default is the single
#	actor named "actor".
# ---------------------------------------------------------------
	global dirname

	set delta [expr 360.0/$nsteps]
	set suffix ppm
	set n 0
	cmd [list\
		"renWin SetSize $hsize $vsize"\
		 "wm withdraw ."]
	while {$n < $nsteps} {
		incr n
		set filename "${basename}_[format %03d $n].$suffix"
		cmd [list\
			"renWin Render"\
			"renWin SetFileName $filename"\
			"renWin SaveImageAsPPM"]
		foreach actor $actors {
			if {$x} { cmd [list "$actor RotateX $delta"] }
			if {$y} { cmd [list "$actor RotateY $delta"] }
			if {$z} { cmd [list "$actor RotateZ $delta"] }
		}
	}
	cmd [list "destroy ."]
	catch {exec $dirname/whirl.sh $basename}
} ;# End whirl.
...........................................................................

------------------------------------------------------------------------------
This e-mail is intended for the use of the addressee(s) only and may contain privileged, confidential, or proprietary information that is exempt from disclosure under law.  If you have received this message in error, please inform us promptly by reply e-mail, then delete the e-mail and destroy any printed copy.   Thank you.

==============================================================================




More information about the vtkusers mailing list