Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

539 lines
17 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkVolumeRayCastMIPFunction.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkVolumeRayCastMIPFunction.h"
#include "vtkVolumeRayCastMapper.h"
#include "vtkVolume.h"
#include "vtkObjectFactory.h"
#include <math.h>
vtkCxxRevisionMacro(vtkVolumeRayCastMIPFunction, "$Revision: 1.1 $");
vtkStandardNewMacro(vtkVolumeRayCastMIPFunction);
// This is the templated function that actually casts a ray and computes
// the maximum value. It is valid for unsigned char and unsigned short,
template <class T>
void vtkCastMaxScalarValueRay( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
float triMax, triValue;
int max = 0;;
float max_opacity;
int loop;
int xinc, yinc, zinc;
int voxel[3], prev_voxel[3];
float ray_position[3];
T A, B, C, D, E, F, G, H;
float t00, t01, t10, t11, t0, t1;
int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc;
float xoff, yoff, zoff;
T *dptr;
int num_steps;
float *ray_increment;
float *grayArray, *RGBArray;
float *scalarArray;
T nnValue, nnMax;
num_steps = dynamicInfo->NumberOfStepsToTake;
ray_increment = dynamicInfo->TransformedIncrement;
grayArray = staticInfo->Volume->GetGrayArray();
RGBArray = staticInfo->Volume->GetRGBArray();
scalarArray = staticInfo->Volume->GetScalarOpacityArray();
xinc = staticInfo->DataIncrement[0];
yinc = staticInfo->DataIncrement[1];
zinc = staticInfo->DataIncrement[2];
// Initialize the ray position and voxel location
memcpy( ray_position, dynamicInfo->TransformedStart, 3*sizeof(float) );
// If we have nearest neighbor interpolation
if ( staticInfo->InterpolationType == VTK_NEAREST_INTERPOLATION )
{
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
// Access the value at this voxel location
nnMax = *(data_ptr + voxel[2] * zinc +
voxel[1] * yinc + voxel[0] );
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
// For each step along the ray
for ( loop = 1; loop < num_steps; loop++ )
{
// Access the value at this voxel location
nnValue = *(data_ptr + voxel[2] * zinc +
voxel[1] * yinc + voxel[0] );
// If this is greater than the max, this is the new max.
if ( nnValue > nnMax )
{
nnMax = nnValue;
}
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
}
max = (int)nnMax;
}
// We are using trilinear interpolation
else if ( staticInfo->InterpolationType == VTK_LINEAR_INTERPOLATION )
{
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
// Compute the increments to get to the other 7 voxel vertices from A
Binc = xinc;
Cinc = yinc;
Dinc = xinc + yinc;
Einc = zinc;
Finc = zinc + xinc;
Ginc = zinc + yinc;
Hinc = zinc + xinc + yinc;
// Set values for the first pass through the loop
dptr = data_ptr + voxel[2] * zinc + voxel[1] * yinc + voxel[0];
A = *(dptr);
B = *(dptr + Binc);
C = *(dptr + Cinc);
D = *(dptr + Dinc);
E = *(dptr + Einc);
F = *(dptr + Finc);
G = *(dptr + Ginc);
H = *(dptr + Hinc);
// Compute our offset in the voxel, and use that to trilinearly
// interpolate a value
xoff = ray_position[0] - (float) voxel[0];
yoff = ray_position[1] - (float) voxel[1];
zoff = ray_position[2] - (float) voxel[2];
vtkTrilinFuncMacro( triMax, xoff, yoff, zoff, A, B, C, D, E, F, G, H );
// Keep the voxel location so that we know when we've moved into a
// new voxel
memcpy( prev_voxel, voxel, 3*sizeof(int) );
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
// For each step along the ray
for ( loop = 1; loop < num_steps; loop++ )
{
// Have we moved into a new voxel? If so we need to recompute A-H
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
dptr = data_ptr + voxel[2] * zinc + voxel[1] * yinc + voxel[0];
A = *(dptr);
B = *(dptr + Binc);
C = *(dptr + Cinc);
D = *(dptr + Dinc);
E = *(dptr + Einc);
F = *(dptr + Finc);
G = *(dptr + Ginc);
H = *(dptr + Hinc);
memcpy( prev_voxel, voxel, 3*sizeof(int) );
}
// Compute our offset in the voxel, and use that to trilinearly
// interpolate a value
xoff = ray_position[0] - (float) voxel[0];
yoff = ray_position[1] - (float) voxel[1];
zoff = ray_position[2] - (float) voxel[2];
vtkTrilinFuncMacro( triValue, xoff, yoff, zoff, A, B, C, D, E, F, G, H );
// If this value is greater than max, it is the new max
if ( triValue > triMax )
{
triMax = triValue;
}
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
max = (int)triMax;
}
if ( max < 0 )
{
max = 0;
}
else if ( max > staticInfo->Volume->GetArraySize() - 1 )
{
max = (int)(staticInfo->Volume->GetArraySize() - 1);
}
dynamicInfo->ScalarValue = max;
max_opacity = scalarArray[max];
// Set the return pixel value.
if( staticInfo->ColorChannels == 1 )
{
dynamicInfo->Color[0] = max_opacity * grayArray[max];
dynamicInfo->Color[1] = max_opacity * grayArray[max];
dynamicInfo->Color[2] = max_opacity * grayArray[max];
dynamicInfo->Color[3] = max_opacity;
}
else if ( staticInfo->ColorChannels == 3 )
{
dynamicInfo->Color[0] = max_opacity * RGBArray[max*3];
dynamicInfo->Color[1] = max_opacity * RGBArray[max*3+1];
dynamicInfo->Color[2] = max_opacity * RGBArray[max*3+2];
dynamicInfo->Color[3] = max_opacity;
}
dynamicInfo->NumberOfStepsTaken = num_steps;
}
// This is the templated function that actually casts a ray and computes
// the maximum value. It is valid for unsigned char and unsigned short,
template <class T>
void vtkCastMaxOpacityRay( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
float max;
float opacity;
float value;
int max_value = 0;
int loop;
int xinc, yinc, zinc;
int voxel[3];
int prev_voxel[3];
float ray_position[3];
T A, B, C, D, E, F, G, H;
float t00, t01, t10, t11, t0, t1;
int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc;
float xoff, yoff, zoff;
T *dptr;
int steps_this_ray = 0;
float *SOTF;
int num_steps;
float *ray_start, *ray_increment;
float *grayArray, *RGBArray;
num_steps = dynamicInfo->NumberOfStepsToTake;
ray_start = dynamicInfo->TransformedStart;
ray_increment = dynamicInfo->TransformedIncrement;
SOTF = staticInfo->Volume->GetScalarOpacityArray();
grayArray = staticInfo->Volume->GetGrayArray();
RGBArray = staticInfo->Volume->GetRGBArray();
// Set the max value. This will not always be correct and should be fixed
max = -999999.0;
xinc = staticInfo->DataIncrement[0];
yinc = staticInfo->DataIncrement[1];
zinc = staticInfo->DataIncrement[2];
// Initialize the ray position and voxel location
ray_position[0] = ray_start[0];
ray_position[1] = ray_start[1];
ray_position[2] = ray_start[2];
// If we have nearest neighbor interpolation
if ( staticInfo->InterpolationType == VTK_NEAREST_INTERPOLATION )
{
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
// For each step along the ray
for ( loop = 0; loop < num_steps; loop++ )
{
// We've taken another step
steps_this_ray++;
// Access the value at this voxel location
value = *(data_ptr + voxel[2] * zinc +
voxel[1] * yinc + voxel[0] );
if ( value < 0 )
{
value = 0;
}
else if ( value > staticInfo->Volume->GetArraySize() - 1 )
{
value = staticInfo->Volume->GetArraySize() - 1;
}
opacity = SOTF[(int)value];
// If this is greater than the max, this is the new max.
if ( opacity > max )
{
max = opacity;
max_value = (int) value;
}
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
}
}
// We are using trilinear interpolation
else if ( staticInfo->InterpolationType == VTK_LINEAR_INTERPOLATION )
{
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
// Compute the increments to get to the other 7 voxel vertices from A
Binc = xinc;
Cinc = yinc;
Dinc = xinc + yinc;
Einc = zinc;
Finc = zinc + xinc;
Ginc = zinc + yinc;
Hinc = zinc + xinc + yinc;
// Set values for the first pass through the loop
dptr = data_ptr + voxel[2] * zinc + voxel[1] * yinc + voxel[0];
A = *(dptr);
B = *(dptr + Binc);
C = *(dptr + Cinc);
D = *(dptr + Dinc);
E = *(dptr + Einc);
F = *(dptr + Finc);
G = *(dptr + Ginc);
H = *(dptr + Hinc);
// Keep the voxel location so that we know when we've moved into a
// new voxel
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
// For each step along the ray
for ( loop = 0; loop < num_steps; loop++ )
{
// We've taken another step
steps_this_ray++;
// Have we moved into a new voxel? If so we need to recompute A-H
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
dptr = data_ptr + voxel[2] * zinc + voxel[1] * yinc + voxel[0];
A = *(dptr);
B = *(dptr + Binc);
C = *(dptr + Cinc);
D = *(dptr + Dinc);
E = *(dptr + Einc);
F = *(dptr + Finc);
G = *(dptr + Ginc);
H = *(dptr + Hinc);
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Compute our offset in the voxel, and use that to trilinearly
// interpolate a value
xoff = ray_position[0] - (float) voxel[0];
yoff = ray_position[1] - (float) voxel[1];
zoff = ray_position[2] - (float) voxel[2];
vtkTrilinFuncMacro( value, xoff, yoff, zoff, A, B, C, D, E, F, G, H );
if ( value < 0 )
{
value = 0;
}
else if ( value > staticInfo->Volume->GetArraySize() - 1 )
{
value = staticInfo->Volume->GetArraySize() - 1;
}
opacity = SOTF[(int)value];
// If this is greater than the max, this is the new max.
if ( opacity > max )
{
max = opacity;
max_value = (int) value;
}
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
}
dynamicInfo->ScalarValue = max;
// Set the return pixel value. The depth value is currently useless and
// should be fixed.
if( staticInfo->ColorChannels == 1 )
{
dynamicInfo->Color[0] = max * grayArray[max_value];
dynamicInfo->Color[1] = max * grayArray[max_value];
dynamicInfo->Color[2] = max * grayArray[max_value];
dynamicInfo->Color[3] = max;
}
else if ( staticInfo->ColorChannels == 3 )
{
dynamicInfo->Color[0] = max * RGBArray[max_value*3];
dynamicInfo->Color[1] = max * RGBArray[max_value*3+1];
dynamicInfo->Color[2] = max * RGBArray[max_value*3+2];
dynamicInfo->Color[3] = max;
}
dynamicInfo->NumberOfStepsTaken = steps_this_ray;
}
// Construct a new vtkVolumeRayCastMIPFunction
vtkVolumeRayCastMIPFunction::vtkVolumeRayCastMIPFunction()
{
this->MaximizeMethod = VTK_MAXIMIZE_SCALAR_VALUE;
}
// Destruct the vtkVolumeRayCastMIPFunction
vtkVolumeRayCastMIPFunction::~vtkVolumeRayCastMIPFunction()
{
}
// This is called from RenderAnImage (in vtkDepthPARCMapper.cxx)
// It uses the integer data type flag that is passed in to
// determine what type of ray needs to be cast (which is handled
// by a templated function.
void vtkVolumeRayCastMIPFunction::CastRay( vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo)
{
void *data_ptr;
data_ptr = staticInfo->ScalarDataPointer;
if ( this->MaximizeMethod == VTK_MAXIMIZE_SCALAR_VALUE )
{
switch ( staticInfo->ScalarDataType )
{
case VTK_UNSIGNED_CHAR:
vtkCastMaxScalarValueRay( (unsigned char *)data_ptr, dynamicInfo,
staticInfo );
break;
case VTK_UNSIGNED_SHORT:
vtkCastMaxScalarValueRay( (unsigned short *)data_ptr, dynamicInfo,
staticInfo );
break;
default:
vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" );
break;
}
}
else
{
switch ( staticInfo->ScalarDataType )
{
case VTK_UNSIGNED_CHAR:
vtkCastMaxOpacityRay( (unsigned char *)data_ptr, dynamicInfo, staticInfo );
break;
case VTK_UNSIGNED_SHORT:
vtkCastMaxOpacityRay( (unsigned short *)data_ptr, dynamicInfo, staticInfo );
break;
default:
vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" );
break;
}
}
}
float vtkVolumeRayCastMIPFunction::GetZeroOpacityThreshold( vtkVolume *vtkNotUsed(vol) )
{
return ( 1.0 );
}
// This is an update method that is called from Render (in
// vtkDepthPARCMapper.cxx). It allows the specific mapper type to
// update any local caster variables. In this case, nothing needs
// to be done here
void vtkVolumeRayCastMIPFunction::SpecificFunctionInitialize(
vtkRenderer *vtkNotUsed(ren),
vtkVolume *vtkNotUsed(vol),
vtkVolumeRayCastStaticInfo *staticInfo,
vtkVolumeRayCastMapper *vtkNotUsed(mapper) )
{
staticInfo->MIPFunction = 1;
staticInfo->MaximizeOpacity = (this->MaximizeMethod == VTK_MAXIMIZE_OPACITY);
}
// Description:
// Return the maximize method as a descriptive character string.
const char *vtkVolumeRayCastMIPFunction::GetMaximizeMethodAsString(void)
{
if( this->MaximizeMethod == VTK_MAXIMIZE_SCALAR_VALUE )
{
return "Maximize Scalar Value";
}
if( this->MaximizeMethod == VTK_MAXIMIZE_OPACITY )
{
return "Maximize Opacity";
}
else
{
return "Unknown";
}
}
// Print method for vtkVolumeRayCastMIPFunction
void vtkVolumeRayCastMIPFunction::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Maximize Method: " << this->GetMaximizeMethodAsString()
<< "\n";
}