You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
7.4 KiB
C

/*=========================================================================
Program: Visualization Toolkit
Module: vtkEncodedGradientEstimator.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 vtkEncodedGradientEstimator
* @brief Superclass for gradient estimation
*
* vtkEncodedGradientEstimator is an abstract superclass for gradient
* estimation. It takes a scalar input of vtkImageData, computes
* a gradient value for every point, and encodes this value into a
* three byte value (2 for direction, 1 for magnitude) using the
* vtkDirectionEncoder. The direction encoder is defaulted to a
* vtkRecursiveSphereDirectionEncoder, but can be overridden with the
* SetDirectionEncoder method. The scale and the bias values for the gradient
* magnitude are used to convert it into a one byte value according to
* v = m*scale + bias where m is the magnitude and v is the resulting
* one byte value.
* @sa
* vtkFiniteDifferenceGradientEstimator vtkDirectionEncoder
*/
#ifndef vtkEncodedGradientEstimator_h
#define vtkEncodedGradientEstimator_h
#include "vtkObject.h"
#include "vtkRenderingVolumeModule.h" // For export macro
class vtkImageData;
class vtkDirectionEncoder;
class vtkMultiThreader;
class VTKRENDERINGVOLUME_EXPORT vtkEncodedGradientEstimator : public vtkObject
{
public:
vtkTypeMacro(vtkEncodedGradientEstimator, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent) override;
//@{
/**
* Set/Get the scalar input for which the normals will be
* calculated. Note that this call does not setup a pipeline
* connection. vtkEncodedGradientEstimator is not an algorithm
* and does not update its input. If you are directly using this
* class, you may need to manually update the algorithm that produces
* this data object.
*/
virtual void SetInputData(vtkImageData*);
vtkGetObjectMacro(InputData, vtkImageData);
//@}
//@{
/**
* Set/Get the scale and bias for the gradient magnitude
*/
vtkSetMacro(GradientMagnitudeScale, float);
vtkGetMacro(GradientMagnitudeScale, float);
vtkSetMacro(GradientMagnitudeBias, float);
vtkGetMacro(GradientMagnitudeBias, float);
//@}
//@{
/**
* Turn on / off the bounding of the normal computation by
* the this->Bounds bounding box
*/
vtkSetClampMacro(BoundsClip, vtkTypeBool, 0, 1);
vtkGetMacro(BoundsClip, vtkTypeBool);
vtkBooleanMacro(BoundsClip, vtkTypeBool);
//@}
//@{
/**
* Set / Get the bounds of the computation (used if
* this->ComputationBounds is 1.) The bounds are specified
* xmin, xmax, ymin, ymax, zmin, zmax.
*/
vtkSetVector6Macro(Bounds, int);
vtkGetVectorMacro(Bounds, int, 6);
//@}
/**
* Recompute the encoded normals and gradient magnitudes.
*/
void Update(void);
/**
* Get the encoded normals.
*/
unsigned short* GetEncodedNormals(void);
//@{
/**
* Get the encoded normal at an x,y,z location in the volume
*/
int GetEncodedNormalIndex(vtkIdType xyz_index);
int GetEncodedNormalIndex(int x_index, int y_index, int z_index);
//@}
/**
* Get the gradient magnitudes
*/
unsigned char* GetGradientMagnitudes(void);
//@{
/**
* Get/Set the number of threads to create when encoding normals
* This defaults to the number of available processors on the machine
*/
vtkSetClampMacro(NumberOfThreads, int, 1, VTK_MAX_THREADS);
vtkGetMacro(NumberOfThreads, int);
//@}
//@{
/**
* Set / Get the direction encoder used to encode normal directions
* to fit within two bytes
*/
void SetDirectionEncoder(vtkDirectionEncoder* direnc);
vtkGetObjectMacro(DirectionEncoder, vtkDirectionEncoder);
//@}
//@{
/**
* If you don't want to compute gradient magnitudes (but you
* do want normals for shading) this can be used. Be careful - if
* if you a non-constant gradient magnitude transfer function and
* you turn this on, it may crash
*/
vtkSetMacro(ComputeGradientMagnitudes, vtkTypeBool);
vtkGetMacro(ComputeGradientMagnitudes, vtkTypeBool);
vtkBooleanMacro(ComputeGradientMagnitudes, vtkTypeBool);
//@}
//@{
/**
* If the data in each slice is only contained within a circle circumscribed
* within the slice, and the slice is square, then don't compute anything
* outside the circle. This circle through the slices forms a cylinder.
*/
vtkSetMacro(CylinderClip, vtkTypeBool);
vtkGetMacro(CylinderClip, vtkTypeBool);
vtkBooleanMacro(CylinderClip, vtkTypeBool);
//@}
//@{
/**
* Get the time required for the last update in seconds or cpu seconds
*/
vtkGetMacro(LastUpdateTimeInSeconds, float);
vtkGetMacro(LastUpdateTimeInCPUSeconds, float);
//@}
vtkGetMacro(UseCylinderClip, int);
int* GetCircleLimits() { return this->CircleLimits; }
//@{
/**
* Set / Get the ZeroNormalThreshold - this defines the minimum magnitude
* of a gradient that is considered sufficient to define a
* direction. Gradients with magnitudes at or less than this value are given
* a "zero normal" index. These are handled specially in the shader,
* and you can set the intensity of light for these zero normals in
* the gradient shader.
*/
void SetZeroNormalThreshold(float v);
vtkGetMacro(ZeroNormalThreshold, float);
//@}
//@{
/**
* Assume that the data value outside the volume is zero when
* computing normals.
*/
vtkSetClampMacro(ZeroPad, vtkTypeBool, 0, 1);
vtkGetMacro(ZeroPad, vtkTypeBool);
vtkBooleanMacro(ZeroPad, vtkTypeBool);
//@}
// These variables should be protected but are being
// made public to be accessible to the templated function.
// We used to have the templated function as a friend, but
// this does not work with all compilers
// The input scalar data on which the normals are computed
vtkImageData* InputData;
// The encoded normals (2 bytes) and the size of the encoded normals
unsigned short* EncodedNormals;
int EncodedNormalsSize[3];
// The magnitude of the gradient array and the size of this array
unsigned char* GradientMagnitudes;
// The time at which the normals were last built
vtkTimeStamp BuildTime;
vtkGetVectorMacro(InputSize, int, 3);
vtkGetVectorMacro(InputAspect, float, 3);
protected:
vtkEncodedGradientEstimator();
~vtkEncodedGradientEstimator() override;
void ReportReferences(vtkGarbageCollector*) override;
// The number of threads to use when encoding normals
int NumberOfThreads;
vtkMultiThreader* Threader;
vtkDirectionEncoder* DirectionEncoder;
virtual void UpdateNormals(void) = 0;
float GradientMagnitudeScale;
float GradientMagnitudeBias;
float LastUpdateTimeInSeconds;
float LastUpdateTimeInCPUSeconds;
float ZeroNormalThreshold;
vtkTypeBool CylinderClip;
int* CircleLimits;
int CircleLimitsSize;
int UseCylinderClip;
void ComputeCircleLimits(int size);
vtkTypeBool BoundsClip;
int Bounds[6];
int InputSize[3];
float InputAspect[3];
vtkTypeBool ComputeGradientMagnitudes;
vtkTypeBool ZeroPad;
private:
vtkEncodedGradientEstimator(const vtkEncodedGradientEstimator&) = delete;
void operator=(const vtkEncodedGradientEstimator&) = delete;
};
#endif