The tcl script march.tcl uses the Visualization Toolkit to generate triangle files from cross-section data using the Marching Cubes algorithm. Make Your Own Visible Woman describes how to use this script. The script is broken into several sections:
This paper describes the script section by section.
Verify Parameters
Certain parameters are required and certain parameters have defaults.
This section makes sure the required NAME, RESOLUTION, STUDY and END_SLICE
parameters are defined. If a required parameter is missing, the script exits
with an error message.
# Set defaults for any parameters not defined
if {[info exists NAME] == 0} {
puts "march.tcl: NAME is not defined"
set OK 0
}
if {[info exists RESOLUTION] == 0} {
puts "march.tcl: RESOLUTION is not defined"
set OK 0
}
if {[info exists STUDY] == 0} {
puts "march.tcl: STUDY is not defined"
set OK 0
}
if {[info exists END_SLICE] == 0} {
puts "march.tcl: END_SLICE is not defined"
set OK 0
}
if {[info exists VALUE] == 0} {
puts "march.tcl: VALUE is not defined"
set OK 0
}
if { $OK == 0 } {
puts "march.tcl: One or more required parameters are missing!"
exit
}
if {[info exists SLICE_ORDER] == 0} {set SLICE_ORDER si}
if {[info exists HEADER_SIZE] == 0} {set HEADER_SIZE 0}
if {[info exists PIXEL_SIZE] == 0} {set PIXEL_SIZE 1}
if {[info exists START_SLICE] == 0} {set START_SLICE 1}
if {[info exists SWAP] == 0} {set SWAP SwapBytesOff}
if {[info exists REDUCTION] == 0} {set REDUCTION 1}
if {[info exists FEATURE_ANGLE] == 0} {set FEATURE_ANGLE 60}
if {[info exists DECIMATE_ANGLE] == 0} {set DECIMATE_ANGLE $FEATURE_ANGLE}
if {[info exists SMOOTH_ANGLE] == 0} {set SMOOTH_ANGLE $DECIMATE_ANGLE}
if {[info exists DECIMATE_ITERATIONS] == 0} {set DECIMATE_ITERATIONS 1}
if {[info exists SMOOTH_ITERATIONS] == 0} {set SMOOTH_ITERATIONS 10}
if {[info exists DECIMATE_REDUCTION] == 0} {set DECIMATE_REDUCTION 1}
if {[info exists DECIMATE_ERROR] == 0} {set DECIMATE_ERROR .0002}
if {[info exists DECIMATE_ERROR_INCREMENT] == 0} {set DECIMATE_ERROR_INCREMENT .0002}
if {[info exists SMOOTH_EXPAND] == 0} {set SMOOTH_EXPAND -.34}
if {[info exists SMOOTH_SHRINK] == 0} {set SMOOTH_SHRINK .33}
if {[info exists VOI] == 0} {
set VOI "0 [expr $RESOLUTION - 1] 0 [expr $RESOLUTION - 1] 0 $ZMAX]"
}
if {[info exists SAMPLE_RATE] == 0} {set SAMPLE_RATE "1 1 1"}
set origin [expr ( $RESOLUTION / 2.0 ) * $PIXEL_SIZE * -1.0]
vtkVolume16Reader reader;
eval reader SetDataDimensions $RESOLUTION $RESOLUTION
eval reader SetFilePrefix $STUDY
eval reader SetDataAspectRatio $PIXEL_SIZE $PIXEL_SIZE $SPACING
eval reader SetDataOrigin $origin $origin [expr $START_SLICE * $SPACING]
eval reader SetImageRange $START_SLICE $END_SLICE
reader SetHeaderSize $HEADER_SIZE
reader SetDataMask 0x7fff;
eval reader $SWAP
[reader GetOutput] GlobalReleaseDataFlagOn;
vtkExtractVOI extractor
extractor SetInput [reader GetOutput]
eval extractor SetVOI $VOI
eval extractor SetSampleRate $SAMPLE_RATE
vtkMarchingCubes mcubes;
mcubes SetInput [extractor GetOutput]
mcubes ComputeScalarsOff
mcubes ComputeGradientsOff
mcubes ComputeNormalsOff
eval mcubes SetValue 0 $VALUE
vtkDecimate decimator
decimator SetInput [mcubes GetOutput]
eval decimator SetInitialFeatureAngle $DECIMATE_ANGLE
eval decimator SetMaximumIterations $DECIMATE_ITERATIONS
decimator SetMaximumSubIterations 0
decimator PreserveEdgesOn
decimator SetMaximumError 1
decimator SetTargetReduction $DECIMATE_REDUCTION
eval decimator SetInitialError $DECIMATE_ERROR
eval decimator SetErrorIncrement $DECIMATE_ERROR_INCREMENT
vtkSmoothPolyFilter smoother
smoother SetInput [decimator GetOutput]
eval smoother SetNumberOfIterations $SMOOTH_ITERATIONS
eval smoother SetExpansionFactor $SMOOTH_EXPAND
eval smoother SetContractionFactor $SMOOTH_SHRINK
eval smoother SetFeatureAngle $SMOOTH_ANGLE
smoother FeatureEdgeSmoothingOff
smoother BoundarySmoothingOff;
smoother SetConvergence 0
vtkTransformPolyFilter transformer
eval transformer SetTransform $SLICE_ORDER
transformer SetInput [smoother GetOutput]
vtkPolyNormals normals
normals SetInput [transformer GetOutput]
eval normals SetFeatureAngle $FEATURE_ANGLE
if { $SLICE_ORDER == "si" || $SLICE_ORDER == "pa" || $SLICE_ORDER == "rl" } {
normals FlipNormalsOn
}
vtkStripper stripper
stripper SetInput [normals GetOutput]
vtkPolyWriter writer
writer SetInput [stripper GetOutput]
eval writer SetFilename $NAME.vtk
writer SetFileType 2
proc readerStart {} {global NAME; puts -nonewline "$NAME read took:\t"; flush stdout};
reader SetStartMethod readerStart
proc extractorStart {} {global NAME; puts -nonewline "$NAME extractor took:\t"; flush stdout};
extractor SetStartMethod extractorStart
proc mcubesStart {} {global NAME; puts -nonewline "$NAME mcubes generated\t"; flush stdout};
proc mcubesEnd {} {
global NAME
puts -nonewline "[[mcubes GetOutput] GetNumberOfPolys]"
puts -nonewline " polygons in "
flush stdout
};
mcubes SetStartMethod mcubesStart
mcubes SetEndMethod mcubesEnd
proc decimatorStart {} {global NAME; puts -nonewline "$NAME decimator generated\t"; flush stdout};
proc decimatorEnd {} {
global NAME
puts -nonewline "[[decimator GetOutput] GetNumberOfPolys]"
puts -nonewline " polygons in "
flush stdout
};
decimator SetStartMethod decimatorStart
decimator SetEndMethod decimatorEnd
proc smootherStart {} {global NAME; puts -nonewline "$NAME smoother took:\t"; flush stdout};
smoother SetStartMethod smootherStart
proc normalsStart {} {global NAME; puts -nonewline "$NAME normals took:\t"; flush stdout};
normals SetStartMethod normalsStart
proc writerStart {} {global NAME; puts -nonewline "$NAME writer took:\t"; flush stdout};
transformer SetStartMethod transformerStart
proc transformerStart {} {global NAME; puts -nonewline "$NAME transformer took:\t"; flush stdout};
stripper SetStartMethod stripperStart
proc stripperStart {} {global NAME; puts -nonewline "$NAME stripper took:\t"; flush stdout};
puts "[expr [lindex [time {reader Update;} 1] 0] / 1000000.0] seconds"
puts "[expr [lindex [time {extractor Update;} 1] 0] / 1000000.0] seconds"
puts "[expr [lindex [time {mcubes Update;} 1] 0] / 1000000.0] seconds"
puts "[expr [lindex [time {decimator Update;} 1] 0] / 1000000.0] seconds"
puts "[expr [lindex [time {smoother Update;} 1] 0] / 1000000.0] seconds"
puts "[expr [lindex [time {transformer Update;} 1] 0] / 1000000.0] seconds"
puts "[expr [lindex [time {normals Update;} 1] 0] / 1000000.0] seconds"
puts "[expr [lindex [time {stripper Update;} 1] 0] / 1000000.0] seconds"
writerStart
puts "[expr [lindex [time {writer Update;} 1] 0] / 1000000.0] seconds"
exit
And that's all there is to it. The models generated by the script can be viewed with renactors.tcl.
GE Home Page | GE Research and Development