IsoSurface Rendering of an AR Representation

rlaramee
Class Cube

java.lang.Object
  |
  +--rlaramee.Cube

public class Cube
extends java.lang.Object

Description A Cube is the basic storage object for volume data. A cube represents a geometric structure that is a topological and geometrical regular array of points.

Each [cube|vertex] is labeled using the convention from page 87 of Applications of Spacial Data Structures by H. Samet.
Note it is only the labeling convention taken from H. Sanet, not the numbering. Samet uses a different numbering convention. The vertices are numbered using the convention from page 233 of the Visualization Toolkit (first edition) Figure 8-11


             P3______e2_____P2   This is the cube representation
             /|            /|    for Bob's cube's.  It is the
          e10 |         e11 |    same as the VTK's.
   y     P7______e6____P6/  |    
   ^      |  e3         |   e1    
   |      |   |         |   |    
   |     e7   |        e5   |
   |--->  | P0|____e0___|___|P1
  /    x  |  /          |  /
 /        |e8           | e9
z         |_____e4______|/
         P4             P5
 Vertex #   Location
 --------   -----------
 0          LDB -left, down, back
 1          RDB  
 2          RUB
 3          LUB
 4          LUF
 5          RUF
 6          RUF -right, up, front (furthest away from vertex 0)
 7          LUF
 

start date Tue 27 April 1999

Version:
2.0
Author:
Robert S Laramee
See Also:
Vertex

Field Summary
private  CubeVertex cubeVertex0
           
private  CubeVertex cubeVertex1
           
private  CubeVertex cubeVertex2
           
private  CubeVertex cubeVertex3
           
private  CubeVertex cubeVertex4
           
private  CubeVertex cubeVertex5
           
private  CubeVertex cubeVertex6
           
private  CubeVertex cubeVertex7
           
private  byte level
           
 
Constructor Summary
Cube(short resolution)
          cube constructor
 
Method Summary
 boolean ASCIIprint(java.text.DecimalFormat decimalFormat)
          To print out a Cube identicle to MR output.
private  float[] computeInterpolatedValues()
          This method is called from Cube.subDivide()
It computes the 19 interpolated data values needed to construct the 8 child cubes.
 float computeMaximum()
           
private  float computeMaximum(float[] data)
           
 float computeMinimum()
           
private  float computeMinimum(float[] data)
           
 int[] computeParentCoords()
           computeParentCoords() returns the x,y,z coordinates (in block space) of its parent cube's vertex 0th.
 float[] computeVertex0coords(int childOctant)
          This method is called from OctreeNode.createChild() and Cube.initializeCube()
It computes the x,y,z coordinates of a child cube as a function of which child it is (octants 0 - 7)
private  Cube createArtificialCube(int x, int y, int z)
          Called from the main() method, used for testing purposes.
 void errorCheck(Cube parentCube)
          The purpose of this function is look for errors in the cube It's called from OctreeNode.errorCheck()
 void freeMemory()
          This method attempts to free up all the resources a cube takes up in order to help out the gargbage collector.
 byte getLevel()
           
 short getResolution()
           
 CubeVertex getVertex(byte i)
           
 CubeVertex[] getVertices()
           
private  Cube initializeChildCube(CubeVertex cubeVertex, float[] data, byte octant)
          This method is called from Cube.subDivide()
It initializes a cube object given it's vertex 0 coordinates and 8 scalar values
 boolean isValid()
          This method looks for an invalid cube.
private  boolean isWithin(byte vertexNumber, Vertex vertex, Cube cube)
          This method checks to see if a vertex is within the spacial bounds of a cube
 boolean isWithin(Cube parentCube)
          This function checks to see if this cube is within the spacial bounds of it's parent cube (as part of the error check) It's called from OctreeNode.errorCheck()
static void main(java.lang.String[] args)
          a main() method used for testing
private  void printError(byte vertex, int axis, Cube cube)
          This method is used to print out error messages from the error check method(s)
private  int resolutionScale(short resolution)
           
 void setCoordinates(float x, float y, float z, float offset)
          We are given the x,y,z coordinates of vertex 0.
 void setCoordinates(int x, int y, int z)
          We are given the x,y,z index, in block space, of the leftmost, downmost, front vertex.
 void setLevel(byte newLevel)
           
 void setResolution(short res)
           
 void setVertex(byte index, float newVal)
           
 void setVertexError(byte index, float newErrVal)
           
 Cube[] subDivide(float[] fineInterpolatedVals, float[] fineCornerVals, byte fromFineToCoarseDirection)
           P3_____e2______P2 This is the cube representation /| /| used write the subdivide() method.
 java.lang.String toString()
          To print out a Cube
private  float[] updateInterpolatedValues(float[] coarseInterpolatedValues, float[] fineInterpolatedValues, byte fromFineToCoarseDirection)
           
 boolean writeInBinary(FileHandler fileHandler)
          This method writes a cube to a binary file 1 float/int at a time, just like the ASCIIprint() method except in binary.
 
Methods inherited from class java.lang.Object
, clone, equals, finalize, getClass, hashCode, notify, notifyAll, registerNatives, wait, wait, wait
 

Field Detail

level

private byte level

cubeVertex0

private CubeVertex cubeVertex0

cubeVertex1

private CubeVertex cubeVertex1

cubeVertex2

private CubeVertex cubeVertex2

cubeVertex3

private CubeVertex cubeVertex3

cubeVertex4

private CubeVertex cubeVertex4

cubeVertex5

private CubeVertex cubeVertex5

cubeVertex6

private CubeVertex cubeVertex6

cubeVertex7

private CubeVertex cubeVertex7
Constructor Detail

Cube

public Cube(short resolution)
cube constructor

Parameters:
resolution - this cubes resolution
Method Detail

getLevel

public byte getLevel()
Returns:
level -this cube's level in the octree

setLevel

public void setLevel(byte newLevel)
Parameters:
newLevel - this cube's level in the octree

getResolution

public short getResolution()
Returns:
the resolution of this octree node

setResolution

public void setResolution(short res)
Parameters:
the - resolution of this octree node

getVertices

public CubeVertex[] getVertices()
Returns:
this cubes set of 8 vertices

getVertex

public CubeVertex getVertex(byte i)
Parameters:
i - a vertex index
Returns:
the ith

setVertex

public void setVertex(byte index,
                      float newVal)
Parameters:
index - a vertex index e.g. 0-7
newVal - that vertice's new scalar value

setVertexError

public void setVertexError(byte index,
                           float newErrVal)
Parameters:
index - a vertex index e.g. 0-7
newErrVal - that vertice's new Err value

subDivide

public Cube[] subDivide(float[] fineInterpolatedVals,
                        float[] fineCornerVals,
                        byte fromFineToCoarseDirection)
             P3_____e2______P2   This is the cube representation
             /|            /|    used write the subdivide() method.
           e10|          e11|    It is the same as the VTK's except 
   y     P7______e6____P6/  |    for the orientation of the 
   ^      |   e3        |   e1   y,z axes.
   |      |   |         |   |    
   |      e7  |         e5  |
   |--->  | P0|_____e0__|___|P1
  /    x  |  /          |  /
 /        | e8          | e9
z         |/_____e4_____|/
         P4             P5
 

A cube is subdivided in two phases of interpolation. The first round of interpolated values mirrors the edge labeling.
i = interpolated value

                             i2
                P3___________*___________P2
                /|                      /| 
               / |                     / | 
              /  |                    /  |
          i10*   |                i11*   |
            /    |                  /    |
           /     *i3  i6           /     * i1
   y     P7___________*_________P6/      | 
   ^      |      |                |      | 
   |      |      |                |      |    
   |      |      |           i0   |      |
   |--->  |    P0|___________*____|______|P1
  /    x  *i7   /                 * i5  /
 /        |    /                  |    /
z         |   *i8                 |   *i9
          |  /                    |  /
          | /                     | /
          |___________*___________|/
         P4           i4          P5
 
The second round of interpolation completes the job:
                 _____________*____________
                /|           /|           /| 
               / |          / |          / | 
              *  |      i18*  |         *  |
             /|  |        /   |        /|  |
            / |  |       /    *i12    / |  |
           /  |  *      /    /|      /  |  *
   y      /____________*____________/   |  | 
   ^      |i15*  |     |   *i17     |   *i13 
   |      |   |  |     |  /   |     |   |  |    
   |      |   |  |     | /    |     |   |  |
   |--->  |   |  |_____|/_____*_____|___|__|
  /    x  *   | /      *i14  /      *   | /
 /        |   |/       |    /       |   |/
z         |   *        |   *i16     |   * 
          |  /         |  /         |  /
          | /          | /          | /
          |____________*____________|/
 
That leaves us 8 cubes:
 cube in     composed of original and 
 octant #    interpolated scalar values
 ----------  --------------------------------------------
       0    P0  i0  i12 i3    i8  i16 i17 i15
       1    i0  P1  i1  i12   i16 i9  i13 i17
       2    i12 i1  P2  i2    i17 i13 i11 i18
       3    i3  i12 i2  P3    i15 i17 i18 i10
       4    i8  i16 i17 i15   P4  i4  i14 i7
       5    i16 i9  i13 i17   i4  P5  i5  i14
       6    i17 i13 i5  i18   i14 i5  P6  i6
       7    i15 i17 i18 i7    i7  i14 i6  P7
 

"this" is the parent cube (the cube being subdivided)

This naive implementation of subdivision can cause discontinuities because it can result in a two vertices with the same spacial location having different scalar values.

Parameters:
fineInterpolatedValues - an array of 18 shared neighboring vertex scalar values. This cube shares a face with a finer resolution neighbor. We are going to use the scalar values of the finer resolution vertices on that shared face rather than using the interpolated scalar values. Using the interpolated scalar values results in two vertices with the same spacial location having different scalar values.
fineCornerVals - an array of 8 shared neighboring vertex scalar values at each corner of the shared face between the 4 adjacent finer resolution cubes and this cube -the one being subdivided.
fromFineToCoarseDirection - the direction from the 4 adjacent finer resolution cubes to this coarser cube -the one being subdivided.
Returns:
an array of 8 ordered-by-octant, child cubes 0-7

updateInterpolatedValues

private float[] updateInterpolatedValues(float[] coarseInterpolatedValues,
                                         float[] fineInterpolatedValues,
                                         byte fromFineToCoarseDirection)
Parameters:
fineInterpolatedValues - an array of 18 interpolated values computed in the computeInterpolatedValues method.
fineInterpolatedValues - an array of 18 shared neighboring vertex scalar values. This cube shares a face with a finer resolution neighbor. We are going to use the scalar values of the finer resolution vertices on that shared face rather than using the interpolated scalar values. Using the interpolated scalar values results in two vertices with the same spacial location having different scalar values.
fromFineToCoarseDirection - the direction from the 4 adjacent finer resolution cubes to this coarser cube -the one being subdivided.
Returns:
an array of 19 interpolated scalar values needed to construct 8 child cubes

initializeChildCube

private Cube initializeChildCube(CubeVertex cubeVertex,
                                 float[] data,
                                 byte octant)
This method is called from Cube.subDivide()
It initializes a cube object given it's vertex 0 coordinates and 8 scalar values

Parameters:
cubeVertex0 - a cube's vertex 0
data - a cubes 8 scalar values of its 8 vertices respectively
octant - the octant the new cube is in
Returns:
the new child cube

computeInterpolatedValues

private float[] computeInterpolatedValues()
This method is called from Cube.subDivide()
It computes the 19 interpolated data values needed to construct the 8 child cubes.

The interpolation must be done in the proper order.

Returns:
an array of 19 interpolated scalar values needed to construct 8 child cubes

computeVertex0coords

public float[] computeVertex0coords(int childOctant)
This method is called from OctreeNode.createChild() and Cube.initializeCube()
It computes the x,y,z coordinates of a child cube as a function of which child it is (octants 0 - 7)

Parameters:
childOctant - a number from 0 to 7 identifying which child we are computing
Returns:
the x,y,z coordinates of this child's 0th vertex and an offset value for the other 7 vertex coordinates

computeMinimum

private float computeMinimum(float[] data)
Parameters:
data[] - an array of 8 scalar vertex values
Returns:
the minimum of the 8 given values

computeMinimum

public float computeMinimum()
Returns:
the minimum of this Cube's scalar vertex values

computeMaximum

private float computeMaximum(float[] data)
Parameters:
data[] - an array of 8 scalar vertex values
Returns:
the maximum of the 8 given values

computeMaximum

public float computeMaximum()
Returns:
the maximum of this Cube's 8 scalar vertex values

setCoordinates

public void setCoordinates(int x,
                           int y,
                           int z)
We are given the x,y,z index, in block space, of the leftmost, downmost, front vertex.
That is what Mike Gildersleeve and Phil Rhodes build_mr generates. This was deduced partially by trial and error. It was found that no other way worked correctly.

We set all the coordinate values of the other 7 vertices based on these parameters and the cube resolution.
The coordinates are set in cube space at their current resolution

Parameters:
x - x block space coordinate of the LDF vertex
y - y block space coordinate of the LDF vertex
z - z block space coordinate of the LDF vertex

setCoordinates

public void setCoordinates(float x,
                           float y,
                           float z,
                           float offset)
We are given the x,y,z coordinates of vertex 0.

We set all the coordinate values of the other 7 vertices based on these parameters and the cube resolution.

Parameters:
x - x coordinate of the LDF vertex
y - y coordinate of the LDF vertex
z - z coordinate of the LDF vertex

freeMemory

public void freeMemory()
This method attempts to free up all the resources a cube takes up in order to help out the gargbage collector.

Don't override the finalize() method. It will get called everytime the garbage collector runs causing nondeterministic behavior which is very difficult to debug


isValid

public boolean isValid()
This method looks for an invalid cube. It's called from MarchingCubes.processCube()

Returns:
TRUE if this is a valid cube

errorCheck

public void errorCheck(Cube parentCube)
The purpose of this function is look for errors in the cube It's called from OctreeNode.errorCheck()

Parameters:
parentCube - -the parent cube of this cube

isWithin

public boolean isWithin(Cube parentCube)
This function checks to see if this cube is within the spacial bounds of it's parent cube (as part of the error check) It's called from OctreeNode.errorCheck()

Parameters:
parentCube - the parent cube of 'this' cube
Returns:
TRUE if 'this' cube is within it's parent

isWithin

private boolean isWithin(byte vertexNumber,
                         Vertex vertex,
                         Cube cube)
This method checks to see if a vertex is within the spacial bounds of a cube

Parameters:
vertexNumber - 1- 8 for cube vertices, or 1 - 3 for triangle vertices
vertex - 1 of 8 cube vertices, or 1 of 3 triangle vertices
cube - the cube whose volume the vertex should be in
Returns:
TRUE if the vertex is withing the cube's spacial bounds

printError

private void printError(byte vertex,
                        int axis,
                        Cube cube)
This method is used to print out error messages from the error check method(s)

Parameters:
vertex - a vertex outside of the given cube's spatial bounds
axis - 1 of 3 -the X, Y, and Z axes

toString

public java.lang.String toString()
To print out a Cube

Overrides:
toString in class java.lang.Object
Returns:
a string describing a cube

ASCIIprint

public boolean ASCIIprint(java.text.DecimalFormat decimalFormat)
To print out a Cube identicle to MR output. Remember, there's a strange mapping from the VTK cube vertices and Phil's cube vertices. We have to do the reverse mapping done in ASCIICubeParser.parseDataVTK()

Parameters:
decimalFormat - the object used for formatting the numbers
Returns:
TRUE if the print was successful
See Also:
ASCIICubeParser.parseDataVTK()

writeInBinary

public boolean writeInBinary(FileHandler fileHandler)
This method writes a cube to a binary file 1 float/int at a time, just like the ASCIIprint() method except in binary.

Parameters:
fileHandler - the object that manages the outputstream
Returns:
true if the output was successful

computeParentCoords

public int[] computeParentCoords()
computeParentCoords() returns the x,y,z coordinates (in block space) of its parent cube's vertex 0th.

Computing the floor of a coordinate has the affect of truncating the fraction off of the number.

Returns:
the x,y,z coordinate (in block space) of the parent cube's 0th vertex

resolutionScale

private int resolutionScale(short resolution)
Parameters:
resolution - the resolution of the cube
Returns:
how many units in coordinate space 1 block at the given resolution takes up along one of the x, y, z dimensions

main

public static void main(java.lang.String[] args)
a main() method used for testing

createArtificialCube

private Cube createArtificialCube(int x,
                                  int y,
                                  int z)
Called from the main() method, used for testing purposes.

Parameters:
x - the x coordinate (in block space) of the cube's 0th vertex
y - the y coordinate (in block space) of the cube's 0th vertex
z - the z coordinate (in block space) of the cube's 0th vertex
Returns:
a new artificial cube

IsoSurface Rendering of an AR Representation