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.
189 lines
7.4 KiB
C++
189 lines
7.4 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkExtractSurface.h
|
|
|
|
Copyright (c) Kitware, Inc.
|
|
All rights reserved.
|
|
See LICENSE file 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 vtkExtractSurface
|
|
* @brief generate zero-crossing isosurface from
|
|
* truncated signed distance volume
|
|
*
|
|
*
|
|
* This filter extracts the zero-crossing isosurface from a truncated signed
|
|
* distance function TSDF. The TSDF is sampled across a volume, and is
|
|
* extracted using a modified version of the Flying Edges (FE) algorithm for
|
|
* increased speed, and to support multithreading. To use the filter, an
|
|
* input volume should be assigned, which may have special values indicating
|
|
* empty and/or unseen portions of the volume. These values are equal to +/-
|
|
* radius value of the signed distance function, and should be consistent
|
|
* with any filters used to generate the input volume (e.g.,
|
|
* vtkSignedDistance).
|
|
*
|
|
* The Flying Edges algorithm is modified to deal with the nature of the
|
|
* truncated, signed distance function. Being truncated, the distance
|
|
* function typically is not computed throughout the volume, rather the
|
|
* special data values "unseen" and/or "empty" maybe assigned to distant or
|
|
* bordering voxels. The implications of this are that this implementation
|
|
* may produce non-closed, non-manifold surfaces, which is what is required
|
|
* to extract surfaces.
|
|
*
|
|
* More specifically, voxels may exist in one of three states: 1) within the
|
|
* TSDF, which extends +/-Radius from a generating geometry (typically a
|
|
* point cloud); 2) in the empty state, in which it is known that the surface
|
|
* does not exist; and 3) the unseen state, where a surface may exist but not
|
|
* enough information is known to be certain. Such situations arise, for
|
|
* example, when laser scanners generate point clouds, and the propagation of
|
|
* the laser beam "carves" out regions where no geometry exists (thereby
|
|
* defining empty space). Furthermore, areas in which the beam are occluded
|
|
* by geometry are known as "unseen" and the boundary between empty and
|
|
* unseen can be processed to produced a portion of the output isosurface
|
|
* (this is called hole filling).
|
|
*
|
|
* @warning
|
|
* This class has been threaded with vtkSMPTools. Using TBB or other
|
|
* non-sequential type (set in the CMake variable
|
|
* VTK_SMP_IMPLEMENTATION_TYPE) may improve performance significantly.
|
|
*
|
|
* @warning
|
|
* Empty regions are expected to have a data value
|
|
* -(this->Radius+FLT_EPSILON). Unseen regions are expected to have a data
|
|
* value (this->Radius+FLT_EPSILON). Near regions have data values d such that:
|
|
* -(this->Radius+FLT_EPSILON) < d (this->Radius+FLT_EPSILON).
|
|
*
|
|
* @warning
|
|
* <pre>
|
|
* Notes on the implementation:
|
|
* 1. This is a lightly modified version of vtkFlyingEdges3D. Some design goals
|
|
* included minimizing the impact on the FE algorithm, and not adding extra
|
|
* memory requirements.
|
|
* 2. It presumes an isocontour value=0.0 (the zero crossing of a signed
|
|
* distance function).
|
|
* 3. The major modifications are to the edge cases. In Flying Edges, a single
|
|
* byte represents the case of an edge, and within that byte only 2 bits
|
|
* are needed (the extra six bytes are not used). Here, these unused bytes
|
|
* are repurposed to represent the "state" of the edge, whether it is
|
|
* 1) near to the TSDF; 2) in an empty state; or 3) unseen state.
|
|
* 4. Since these now-used bits encode extra state information, masking and
|
|
* related methods are modified from FE to tease apart the edge cases from
|
|
* the edge state.
|
|
* 5. Voxels with edges marked "empty" are not processed, i.e., no output
|
|
* triangle primitives are generated. Depending on whether hole filling is
|
|
* enabled, voxels with edges marked "unseen" may not be processed either.
|
|
* 6. As a result of #1 and #5, and the desire to keep the implementation simple,
|
|
* it is possible to produce output points which are not used by any output
|
|
* triangle.
|
|
*</pre>
|
|
*
|
|
* @warning
|
|
* This algorithm loosely follows the most excellent paper by Curless and
|
|
* Levoy: "A Volumetric Method for Building Complex Models from Range
|
|
* Images."
|
|
*
|
|
* @warning
|
|
* This algorithm differs from the paper cited above in an important way. The
|
|
* Curless & Levoy algorithm is designed to create watertight surfaces, while this
|
|
* modified algorithm may not do so as the generating surface is not assumed to be
|
|
* closed.
|
|
*
|
|
* @sa
|
|
* vtkSignedDistance vtkFlyingEdges3D
|
|
*/
|
|
|
|
#ifndef vtkExtractSurface_h
|
|
#define vtkExtractSurface_h
|
|
|
|
#include "vtkContourValues.h" // Passes calls through
|
|
#include "vtkFiltersPointsModule.h" // For export macro
|
|
#include "vtkPolyDataAlgorithm.h"
|
|
|
|
class vtkImageData;
|
|
|
|
class VTKFILTERSPOINTS_EXPORT vtkExtractSurface : public vtkPolyDataAlgorithm
|
|
{
|
|
public:
|
|
//@{
|
|
/**
|
|
* Standard methods for instantiating the class, providing type information,
|
|
* and printing.
|
|
*/
|
|
static vtkExtractSurface* New();
|
|
vtkTypeMacro(vtkExtractSurface, vtkPolyDataAlgorithm);
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Specify the radius of influence of the signed distance function. Data
|
|
* values (which are distances) that are greater than the radius (i.e., d >
|
|
* Radius) are considered empty voxels; those voxel data values d < -Radius
|
|
* are considered unseen voxels.
|
|
*/
|
|
vtkSetClampMacro(Radius, double, 0.0, VTK_FLOAT_MAX);
|
|
vtkGetMacro(Radius, double);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Enable hole filling. This generates separating surfaces between the
|
|
* empty and unseen portions of the volume.
|
|
*/
|
|
vtkSetMacro(HoleFilling, bool);
|
|
vtkGetMacro(HoleFilling, bool);
|
|
vtkBooleanMacro(HoleFilling, bool);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get the computation of normals. Normal computation is fairly
|
|
* expensive in both time and storage. If the output data will be processed
|
|
* by filters that modify topology or geometry, it may be wise to turn
|
|
* Normals and Gradients off.
|
|
*/
|
|
vtkSetMacro(ComputeNormals, vtkTypeBool);
|
|
vtkGetMacro(ComputeNormals, vtkTypeBool);
|
|
vtkBooleanMacro(ComputeNormals, vtkTypeBool);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get the computation of gradients. Gradient computation is fairly
|
|
* expensive in both time and storage. Note that if ComputeNormals is on,
|
|
* gradients will have to be calculated, but will not be stored in the
|
|
* output dataset. If the output data will be processed by filters that
|
|
* modify topology or geometry, it may be wise to turn Normals and
|
|
* Gradients off.
|
|
*/
|
|
vtkSetMacro(ComputeGradients, vtkTypeBool);
|
|
vtkGetMacro(ComputeGradients, vtkTypeBool);
|
|
vtkBooleanMacro(ComputeGradients, vtkTypeBool);
|
|
//@}
|
|
|
|
protected:
|
|
vtkExtractSurface();
|
|
~vtkExtractSurface() override;
|
|
|
|
double Radius;
|
|
bool HoleFilling;
|
|
vtkTypeBool ComputeNormals;
|
|
vtkTypeBool ComputeGradients;
|
|
|
|
int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
|
|
int RequestUpdateExtent(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
|
|
int FillInputPortInformation(int port, vtkInformation* info) override;
|
|
|
|
private:
|
|
vtkExtractSurface(const vtkExtractSurface&) = delete;
|
|
void operator=(const vtkExtractSurface&) = delete;
|
|
};
|
|
|
|
#endif
|