343 lines
14 KiB
C++
343 lines
14 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkCheckerboardSplatter.h
|
|
|
|
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.
|
|
|
|
=========================================================================*/
|
|
/**
|
|
* @class vtkCheckerboardSplatter
|
|
* @brief splat points into a volume with an elliptical, Gaussian distribution
|
|
*
|
|
* vtkCheckerboardSplatter is a filter that injects input points into a
|
|
* structured points (volume) dataset using a multithreaded 8-way
|
|
* checkerboard approach. It produces a scalar field of a specified type. As
|
|
* each point is injected, it "splats" or distributes values to nearby
|
|
* voxels. Data is distributed using an elliptical, Gaussian distribution
|
|
* function. The distribution function is modified using scalar values
|
|
* (expands distribution) or normals (creates ellipsoidal distribution rather
|
|
* than spherical). This algorithm is designed for scalability through
|
|
* multithreading.
|
|
*
|
|
* In general, the Gaussian distribution function f(x) around a given
|
|
* splat point p is given by
|
|
*
|
|
* f(x) = ScaleFactor * exp( ExponentFactor*((r/Radius)**2) )
|
|
*
|
|
* where x is the current voxel sample point; r is the distance |x-p|
|
|
* ExponentFactor <= 0.0, and ScaleFactor can be multiplied by the scalar
|
|
* value of the point p that is currently being splatted.
|
|
*
|
|
* If point normals are present (and NormalWarping is on), then the splat
|
|
* function becomes elliptical (as compared to the spherical one described
|
|
* by the previous equation). The Gaussian distribution function then
|
|
* becomes:
|
|
*
|
|
* f(x) = ScaleFactor *
|
|
* exp( ExponentFactor*( ((rxy/E)**2 + z**2)/R**2) )
|
|
*
|
|
* where E is a user-defined eccentricity factor that controls the elliptical
|
|
* shape of the splat; z is the distance of the current voxel sample point
|
|
* along normal N; and rxy is the distance of x in the direction
|
|
* prependicular to N.
|
|
*
|
|
* This class is typically used to convert point-valued distributions into
|
|
* a volume representation. The volume is then usually iso-surfaced or
|
|
* volume rendered to generate a visualization. It can be used to create
|
|
* surfaces from point distributions, or to create structure (i.e.,
|
|
* topology) when none exists.
|
|
*
|
|
* This class makes use of vtkSMPTools to implement a parallel, shared-memory
|
|
* implementation. Hence performance will be significantly improved if VTK is
|
|
* built with VTK_SMP_IMPLEMENTATION_TYPE set to something other than
|
|
* "Sequential" (typically TBB). For example, on a standard laptop with four
|
|
* threads it is common to see a >10x speedup as compared to the serial
|
|
* version of vtkGaussianSplatter.
|
|
*
|
|
* In summary, the algorithm operates by dividing the volume into a 3D
|
|
* checkerboard, where the squares of the checkerboard overlay voxels in the
|
|
* volume. The checkerboard overlay is designed as a function of the splat
|
|
* footprint, so that when splatting occurs in a group (or color) of
|
|
* checkerboard squares, the splat operation will not cause write contention
|
|
* as the splatting proceeds in parallel. There are eight colors in this
|
|
* checkerboard (like an octree) and parallel splatting occurs simultaneously
|
|
* in one of the eight colors (e.g., octants). A single splat operation
|
|
* (across the given 3D footprint) may also be parallelized if the splat is
|
|
* large enough.
|
|
*
|
|
* @warning
|
|
* The input to this filter is of type vtkPointSet. Currently only real types
|
|
* (e.g., float, double) are supported as input, but this could easily be
|
|
* extended to other types. The output type is limited to real types as well.
|
|
*
|
|
* @warning
|
|
* Some voxels may never receive a contribution during the splatting process.
|
|
* The final value of these points can be specified with the "NullValue"
|
|
* instance variable. Note that NullValue is also the initial value of the
|
|
* output voxel values and will affect the accumulation process.
|
|
*
|
|
* @warning
|
|
* While this class is very similar to vtkGaussianSplatter, it does produce
|
|
* slightly different output in most cases (due to the way the footprint is
|
|
* computed).
|
|
*
|
|
* @sa
|
|
* vtkShepardMethod vtkGaussianSplatter
|
|
*/
|
|
|
|
#ifndef vtkCheckerboardSplatter_h
|
|
#define vtkCheckerboardSplatter_h
|
|
|
|
#include "vtkImageAlgorithm.h"
|
|
#include "vtkImagingHybridModule.h" // For export macro
|
|
|
|
#define VTK_ACCUMULATION_MODE_MIN 0
|
|
#define VTK_ACCUMULATION_MODE_MAX 1
|
|
#define VTK_ACCUMULATION_MODE_SUM 2
|
|
|
|
class vtkDoubleArray;
|
|
class vtkCompositeDataSet;
|
|
|
|
class VTKIMAGINGHYBRID_EXPORT vtkCheckerboardSplatter : public vtkImageAlgorithm
|
|
{
|
|
public:
|
|
vtkTypeMacro(vtkCheckerboardSplatter, vtkImageAlgorithm);
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
|
|
|
/**
|
|
* Construct object with dimensions=(50,50,50); automatic computation of
|
|
* bounds; a Footprint of 2; a Radius of 0; an exponent factor of -5; and normal and
|
|
* scalar warping enabled; and Capping enabled.
|
|
*/
|
|
static vtkCheckerboardSplatter* New();
|
|
|
|
///@{
|
|
/**
|
|
* Set / get the dimensions of the sampling structured point set. Higher
|
|
* values produce better results but may be much slower.
|
|
*/
|
|
void SetSampleDimensions(int i, int j, int k);
|
|
void SetSampleDimensions(int dim[3]);
|
|
vtkGetVectorMacro(SampleDimensions, int, 3);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Set / get the (xmin,xmax, ymin,ymax, zmin,zmax) bounding box in which
|
|
* the sampling is performed. If any of the (min,max) bounds values are
|
|
* min >= max, then the bounds will be computed automatically from the input
|
|
* data. Otherwise, the user-specified bounds will be used.
|
|
*/
|
|
vtkSetVector6Macro(ModelBounds, double);
|
|
vtkGetVectorMacro(ModelBounds, double, 6);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Control the footprint size of the splat in terms of propagation across a
|
|
* voxel neighborhood. The Footprint value simply indicates the number of
|
|
* neighboring voxels in the i-j-k directions to extend the splat. A value
|
|
* of zero means that only the voxel containing the splat point is
|
|
* affected. A value of one means the immediate neighbors touching the
|
|
* affected voxel are affected as well. Larger numbers increase the splat
|
|
* footprint and significantly increase processing time. Note that the
|
|
* footprint is always 3D rectangular.
|
|
*/
|
|
vtkSetClampMacro(Footprint, int, 0, VTK_INT_MAX);
|
|
vtkGetMacro(Footprint, int);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Set / get the radius variable that controls the Gaussian exponential
|
|
* function (see equation above). If set to zero, it is automatically set
|
|
* to the radius of the circumsphere bounding a single voxel. (By default,
|
|
* the Radius is set to zero and is automatically computed.)
|
|
*/
|
|
vtkSetClampMacro(Radius, double, 0.0, VTK_DOUBLE_MAX);
|
|
vtkGetMacro(Radius, double);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Multiply Gaussian splat distribution by this value. If ScalarWarping
|
|
* is on, then the Scalar value will be multiplied by the ScaleFactor
|
|
* times the Gaussian function.
|
|
*/
|
|
vtkSetClampMacro(ScaleFactor, double, 0.0, VTK_DOUBLE_MAX);
|
|
vtkGetMacro(ScaleFactor, double);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Set / get the sharpness of decay of the splats. This is the exponent
|
|
* constant in the Gaussian equation described above. Normally this is a
|
|
* negative value.
|
|
*/
|
|
vtkSetMacro(ExponentFactor, double);
|
|
vtkGetMacro(ExponentFactor, double);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Turn on/off the scaling of splats by scalar value.
|
|
*/
|
|
vtkSetMacro(ScalarWarping, vtkTypeBool);
|
|
vtkGetMacro(ScalarWarping, vtkTypeBool);
|
|
vtkBooleanMacro(ScalarWarping, vtkTypeBool);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Turn on/off the generation of elliptical splats. If normal warping is
|
|
* on, then the input normals affect the distribution of the splat. This
|
|
* boolean is used in combination with the Eccentricity ivar.
|
|
*/
|
|
vtkSetMacro(NormalWarping, vtkTypeBool);
|
|
vtkGetMacro(NormalWarping, vtkTypeBool);
|
|
vtkBooleanMacro(NormalWarping, vtkTypeBool);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Control the shape of elliptical splatting. Eccentricity is the ratio
|
|
* of the major axis (aligned along normal) to the minor (axes) aligned
|
|
* along other two axes. So Eccentricity > 1 creates needles with the
|
|
* long axis in the direction of the normal; Eccentricity<1 creates
|
|
* pancakes perpendicular to the normal vector.
|
|
*/
|
|
vtkSetClampMacro(Eccentricity, double, 0.001, VTK_DOUBLE_MAX);
|
|
vtkGetMacro(Eccentricity, double);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Specify the scalar accumulation mode. This mode expresses how scalar
|
|
* values are combined when splats overlap one another. The Max mode acts
|
|
* like a set union operation and is the most commonly used; the Min mode
|
|
* acts like a set intersection, and the sum is just weird (and can
|
|
* potentially cause accumulation overflow in extreme cases). Note that the
|
|
* NullValue must be set consistent with the accumulation operation.
|
|
*/
|
|
vtkSetClampMacro(AccumulationMode, int, VTK_ACCUMULATION_MODE_MIN, VTK_ACCUMULATION_MODE_SUM);
|
|
vtkGetMacro(AccumulationMode, int);
|
|
void SetAccumulationModeToMin() { this->SetAccumulationMode(VTK_ACCUMULATION_MODE_MIN); }
|
|
void SetAccumulationModeToMax() { this->SetAccumulationMode(VTK_ACCUMULATION_MODE_MAX); }
|
|
void SetAccumulationModeToSum() { this->SetAccumulationMode(VTK_ACCUMULATION_MODE_SUM); }
|
|
const char* GetAccumulationModeAsString();
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Set what type of scalar data this source should generate. Only double
|
|
* and float types are supported currently due to precision requirements
|
|
* during accumulation. By default, float scalars are produced.
|
|
*/
|
|
vtkSetMacro(OutputScalarType, int);
|
|
vtkGetMacro(OutputScalarType, int);
|
|
void SetOutputScalarTypeToDouble() { this->SetOutputScalarType(VTK_DOUBLE); }
|
|
void SetOutputScalarTypeToFloat() { this->SetOutputScalarType(VTK_FLOAT); }
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Turn on/off the capping of the outer boundary of the volume
|
|
* to a specified cap value. This can be used to close surfaces
|
|
* (after iso-surfacing) and create other effects.
|
|
*/
|
|
vtkSetMacro(Capping, vtkTypeBool);
|
|
vtkGetMacro(Capping, vtkTypeBool);
|
|
vtkBooleanMacro(Capping, vtkTypeBool);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Specify the cap value to use. (This instance variable only has effect
|
|
* if the ivar Capping is on.)
|
|
*/
|
|
vtkSetMacro(CapValue, double);
|
|
vtkGetMacro(CapValue, double);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Set the Null value for output points not receiving a contribution from
|
|
* the input points. (This is the initial value of the voxel samples, by
|
|
* default it is set to zero.) Note that the value should be consistent
|
|
* with the output dataset type. The NullValue also provides the initial
|
|
* value on which the accumulations process operates.
|
|
*/
|
|
vtkSetMacro(NullValue, double);
|
|
vtkGetMacro(NullValue, double);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Set/Get the maximum dimension of the checkerboard (i.e., the number of
|
|
* squares in any of the i, j, or k directions). This number also impacts
|
|
* the granularity of the parallel threading (since each checker square is
|
|
* processed separaely). Because of the internal addressing, the maximum
|
|
* dimension is limited to 255 (maximum value of an unsigned char).
|
|
*/
|
|
vtkSetClampMacro(MaximumDimension, int, 0, 255);
|
|
vtkGetMacro(MaximumDimension, int);
|
|
///@}
|
|
|
|
///@{
|
|
/**
|
|
* Set/get the crossover point expressed in footprint size where the
|
|
* splatting operation is parallelized (through vtkSMPTools). By default
|
|
* the parallel crossover point is for splat footprints of size two or
|
|
* greater (i.e., at footprint=2 then splat is 5x5x5 and parallel splatting
|
|
* occurs). This is really meant for experimental purposes.
|
|
*/
|
|
vtkSetClampMacro(ParallelSplatCrossover, int, 0, 255);
|
|
vtkGetMacro(ParallelSplatCrossover, int);
|
|
///@}
|
|
|
|
/**
|
|
* Compute the size of the sample bounding box automatically from the
|
|
* input data. This is an internal helper function.
|
|
*/
|
|
void ComputeModelBounds(vtkDataSet* input, vtkImageData* output, vtkInformation* outInfo);
|
|
|
|
protected:
|
|
vtkCheckerboardSplatter();
|
|
~vtkCheckerboardSplatter() override = default;
|
|
|
|
int FillInputPortInformation(int port, vtkInformation* info) override;
|
|
int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
|
|
int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
|
|
|
|
int OutputScalarType; // the type of output scalars
|
|
int SampleDimensions[3]; // dimensions of volume to splat into
|
|
double Radius; // Radius factor in the Gaussian exponential function
|
|
int Footprint; // maximum distance splat propagates (in voxels 0->Dim)
|
|
double ExponentFactor; // scale exponent of gaussian function
|
|
double ModelBounds[6]; // bounding box of splatting dimensions
|
|
double Origin[3], Spacing[3]; // output geometry
|
|
vtkTypeBool NormalWarping; // on/off warping of splat via normal
|
|
double Eccentricity; // elliptic distortion due to normals
|
|
vtkTypeBool ScalarWarping; // on/off warping of splat via scalar
|
|
double ScaleFactor; // splat size influenced by scale factor
|
|
vtkTypeBool Capping; // Cap side of volume to close surfaces
|
|
double CapValue; // value to use for capping
|
|
int AccumulationMode; // how to combine scalar values
|
|
double NullValue; // initial value of voxels
|
|
unsigned char MaximumDimension; // max resolution of checkerboard
|
|
int ParallelSplatCrossover; // the point at which parallel splatting occurs
|
|
|
|
private:
|
|
vtkCheckerboardSplatter(const vtkCheckerboardSplatter&) = delete;
|
|
void operator=(const vtkCheckerboardSplatter&) = delete;
|
|
};
|
|
|
|
#endif
|