/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkImplicitModeller.h,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. =========================================================================*/ // .NAME vtkImplicitModeller - compute distance from input geometry on structured point dataset // .SECTION Description // vtkImplicitModeller is a filter that computes the distance from the input // geometry to the points of an output structured point set. This distance // function can then be "contoured" to generate new, offset surfaces from // the original geometry. An important feature of this object is // "capping". If capping is turned on, after the implicit model is created, // the values on the boundary of the structured points dataset are set to // the cap value. This is used to force closure of the resulting contoured // surface. Note, however, that large cap values can generate weird surface // normals in those cells adjacent to the boundary of the dataset. Using // smaller cap value will reduce this effect. //

// Another important ivar is MaximumDistance. This controls how far into the // volume the distance function is computed from the input geometry. Small // values give significant increases in performance. However, there can // strange sampling effects at the extreme range of the MaximumDistance. //

// In order to properly execute and sample the input data, a rectangular // region in space must be defined (this is the ivar ModelBounds). If not // explicitly defined, the model bounds will be computed. Note that to avoid // boundary effects, it is possible to adjust the model bounds (i.e., using // the AdjustBounds and AdjustDistance ivars) to strictly contain the // sampled data. //

// This filter has one other unusual capability: it is possible to append // data in a sequence of operations to generate a single output. This is // useful when you have multiple datasets and want to create a // conglomeration of all the data. However, the user must be careful to // either specify the ModelBounds or specify the first item such that its // bounds completely contain all other items. This is because the // rectangular region of the output can not be changed after the 1st Append. //

// The ProcessMode ivar controls the method used within the Append function // (where the actual work is done regardless if the Append function is // explicitly called) to compute the implicit model. If set to work in voxel // mode, each voxel is visited once. If set to cell mode, each cell is visited // once. Tests have shown once per voxel to be faster when there are a // lot of cells (at least a thousand?); relative performance improvement // increases with addition cells. Primitives should not be stripped for best // performance of the voxel mode. Also, if explicitly using the Append feature // many times, the cell mode will probably be better because each voxel will be // visited each Append. Append the data before input if possible when using // the voxel mode. Do not switch between voxel and cell mode between execution // of StartAppend and EndAppend. //

// Further performance improvement is now possible using the PerVoxel process // mode on multi-processor machines (the mode is now multithreaded). Each // thread processes a different "slab" of the output. Also, if the input is // vtkPolyData, it is appropriately clipped for each thread; that is, each // thread only considers the input which could affect its slab of the output. //

// This filter can now produce output of any type supported by vtkImageData. // However to support this change, additional sqrts must be executed during the // Append step. Previously, the output was initialized to the squared CapValue // in StartAppend, the output was updated with squared distance values during // the Append, and then the sqrt of the distances was computed in EndAppend. // To support different scalar types in the output (largely to reduce memory // requirements as an vtkImageShiftScale and/or vtkImageCast could have // achieved the same result), we can't "afford" to save squared value in the // output, because then we could only represent up to the sqrt of the scalar // max for an integer type in the output; 1 (instead of 255) for an unsigned // char; 11 for a char (instead of 127). Thus this change may result in a // minor performance degradation. Non-float output types can be scaled to the // CapValue by turning ScaleToMaximumDistance On. // // .SECTION See Also // vtkSampleFunction vtkContourFilter #ifndef __vtkImplicitModeller_h #define __vtkImplicitModeller_h #include "vtkImageAlgorithm.h" #define VTK_VOXEL_MODE 0 #define VTK_CELL_MODE 1 class vtkDataArray; class vtkExtractGeometry; class vtkMultiThreader; class VTK_HYBRID_EXPORT vtkImplicitModeller : public vtkImageAlgorithm { public: vtkTypeRevisionMacro(vtkImplicitModeller,vtkImageAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Construct with sample dimensions=(50,50,50), and so that model bounds are // automatically computed from the input. Capping is turned on with CapValue // equal to a large positive number. static vtkImplicitModeller *New(); // Description: // Compute ModelBounds from input geometry. If input is not specified, the // input of the filter will be used. double ComputeModelBounds(vtkDataSet *input = NULL); // Description: // Set/Get the i-j-k dimensions on which to sample distance function. vtkGetVectorMacro(SampleDimensions,int,3); void SetSampleDimensions(int i, int j, int k); void SetSampleDimensions(int dim[3]); // Description: // Set / get the distance away from surface of input geometry to // sample. Smaller values make large increases in performance. vtkSetClampMacro(MaximumDistance,double,0.0,1.0); vtkGetMacro(MaximumDistance,double); // Description: // Set / get the region in space in which to perform the sampling. If // not specified, it will be computed automatically. vtkSetVector6Macro(ModelBounds,double); vtkGetVectorMacro(ModelBounds,double,6); // Description: // Control how the model bounds are computed. If the ivar AdjustBounds // is set, then the bounds specified (or computed automatically) is modified // by the fraction given by AdjustDistance. This means that the model // bounds is expanded in each of the x-y-z directions. vtkSetMacro(AdjustBounds,int); vtkGetMacro(AdjustBounds,int); vtkBooleanMacro(AdjustBounds,int); // Description: // Specify the amount to grow the model bounds (if the ivar AdjustBounds // is set). The value is a fraction of the maximum length of the sides // of the box specified by the model bounds. vtkSetClampMacro(AdjustDistance,double,-1.0,1.0); vtkGetMacro(AdjustDistance,double); // Description: // The outer boundary of the structured point set can be assigned a // particular value. This can be used to close or "cap" all surfaces. vtkSetMacro(Capping,int); vtkGetMacro(Capping,int); vtkBooleanMacro(Capping,int); // Description: // Specify the capping value to use. The CapValue is also used as an // initial distance value at each point in the dataset. void SetCapValue(double value); vtkGetMacro(CapValue,double); // Description: // If a non-floating output type is specified, the output distances can be // scaled to use the entire positive scalar range of the output type // specified (up to the CapValue which is equal to the max for the type // unless modified by the user). For example, if ScaleToMaximumDistance // is On and the OutputScalarType is UnsignedChar the distances saved in the // output would be linearly scaled between 0 (for distances "very close" to // the surface) and 255 (at the specifed maximum distance)... assuming the // CapValue is not changed from 255. vtkSetMacro(ScaleToMaximumDistance, int); vtkGetMacro(ScaleToMaximumDistance, int); vtkBooleanMacro(ScaleToMaximumDistance,int); // Description: // Specify whether to visit each cell once per append or each voxel once // per append. Some tests have shown once per voxel to be faster // when there are a lot of cells (at least a thousand?); relative // performance improvement increases with addition cells. Primitives // should not be stripped for best performance of the voxel mode. vtkSetClampMacro(ProcessMode, int, 0, 1); vtkGetMacro(ProcessMode, int); void SetProcessModeToPerVoxel() {this->SetProcessMode(VTK_VOXEL_MODE);} void SetProcessModeToPerCell() {this->SetProcessMode(VTK_CELL_MODE);} const char *GetProcessModeAsString(void); // Description: // Specify the level of the locator to use when using the per voxel // process mode. vtkSetMacro(LocatorMaxLevel,int); vtkGetMacro(LocatorMaxLevel,int); // Description: // Set / Get the number of threads used during Per-Voxel processing mode vtkSetClampMacro( NumberOfThreads, int, 1, VTK_MAX_THREADS ); vtkGetMacro( NumberOfThreads, int ); // Description: // Set the desired output scalar type. void SetOutputScalarType(int type); vtkGetMacro(OutputScalarType,int); void SetOutputScalarTypeToFloat(){this->SetOutputScalarType(VTK_FLOAT);}; void SetOutputScalarTypeToDouble(){this->SetOutputScalarType(VTK_DOUBLE);}; void SetOutputScalarTypeToInt(){this->SetOutputScalarType(VTK_INT);}; void SetOutputScalarTypeToUnsignedInt() {this->SetOutputScalarType(VTK_UNSIGNED_INT);}; void SetOutputScalarTypeToLong(){this->SetOutputScalarType(VTK_LONG);}; void SetOutputScalarTypeToUnsignedLong() {this->SetOutputScalarType(VTK_UNSIGNED_LONG);}; void SetOutputScalarTypeToShort(){this->SetOutputScalarType(VTK_SHORT);}; void SetOutputScalarTypeToUnsignedShort() {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);}; void SetOutputScalarTypeToUnsignedChar() {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);}; void SetOutputScalarTypeToChar() {this->SetOutputScalarType(VTK_CHAR);}; // Description: // Initialize the filter for appending data. You must invoke the // StartAppend() method before doing successive Appends(). It's also a // good idea to manually specify the model bounds; otherwise the input // bounds for the data will be used. void StartAppend(); // Description: // Append a data set to the existing output. To use this function, // you'll have to invoke the StartAppend() method before doing // successive appends. It's also a good idea to specify the model // bounds; otherwise the input model bounds is used. When you've // finished appending, use the EndAppend() method. void Append(vtkDataSet *input); // Description: // Method completes the append process. void EndAppend(); // See the vtkAlgorithm for a desciption of what these do int ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*); protected: vtkImplicitModeller(); ~vtkImplicitModeller(); double GetScalarTypeMax(int type); virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); virtual int RequestData (vtkInformation *, vtkInformationVector **, vtkInformationVector *); void StartAppend(int internal); void Cap(vtkDataArray *s); vtkMultiThreader *Threader; int NumberOfThreads; int SampleDimensions[3]; double MaximumDistance; double ModelBounds[6]; int Capping; double CapValue; int DataAppended; int AdjustBounds; double AdjustDistance; int ProcessMode; int LocatorMaxLevel; int OutputScalarType; int ScaleToMaximumDistance; // flag to limit to one ComputeModelBounds per StartAppend int BoundsComputed; // the max distance computed during that one call double InternalMaxDistance; virtual int FillInputPortInformation(int, vtkInformation*); private: vtkImplicitModeller(const vtkImplicitModeller&); // Not implemented. void operator=(const vtkImplicitModeller&); // Not implemented. }; #endif