comac_desk_app/ThirdpartyLibs/Libs/windows-x86_64/vtk/include/vtkSurfaceNets2D.h

340 lines
14 KiB
C
Raw Permalink Normal View History

2024-11-21 11:50:43 +08:00
/*=========================================================================
Program: Visualization Toolkit
Module: vtkSurfaceNets2D.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 vtkSurfaceNets2D
* @brief generate smoothed constours from segmented 2D image data (i.e., "label maps")
*
* vtkSurfaceNets2D creates boundary/isocontour lines from a label map (e.g.,
* a segmented image) using a threaded, 2D version of the multiple
* regions/labels surface nets algorithm. The input is a 2D image where each
* pixel is labeled (integer labels are preferred to real values), and the
* output data is polygonal data separating labeled regions via line
* segments. (Note that on output each region [corresponding to a different
* segmented object] will share points/edges on a common boundary, i.e., two
* objects next to each other will share the boundary that separates them.)
*
* While this filter is similar to a contouring operation, classic contouring
* methods assume a continuous scalar field. In comparision, label maps are
* not continuous in scalar function value, meaning that usual data
* interpolation (e.g., along edges) is not possible. Instead, when the edge
* endpoint pixels are labeled in differing regions, the edge is split and
* transected by a line segment that connects the center points of the squares
* on either side of the edge. Later, using a energy minimization smoothing
* process, these split edges will be adjusted to produce a smoother
* result. (Constraints on smoothing displacements may be specified to
* prevent excessive shrinkage and/or object distortion.)
*
* The smoothing process is controlled by setting a convergence measure, the
* number of smoothing iterations, the step size, and the allowed
* (constraint) distance that points may move. These can be adjusted to
* provide the desired result. This class provides a method to access an
* internal instance of vtkConstrainedSmoothingFilter, through which these
* smoothing parameters may be specified, and which actually performs the
* smoothing operation. (Note: it is possible to skip the smoothing process
* altogether by disabling smoothing (e.g., invoking SmoothingOff()) or
* setting the number of smoothing iterations to zero. This can
* be useful when using a different smoothing filter like
* vtkWindowedSincPolyDataFilter; or if an unsmoothed, aliased output is
* desired. The reason the smoothing is built in to this filter is to remain
* faithful to the published literature describing the surface nets
* algorithm.)
*
* The SurfaceNets algorithm was first proposed by Sarah Frisken. Two
* important papers include the description of surface nets for binary
* objects (i.e., extracting just one segmented object from a volume) and
* multi-label (multiple object extraction).
*
* S. Frisken (Gibson), Constrained Elastic SurfaceNets: Generating Smooth
* Surfaces from Binary Segmented Data, Proc. MICCAI, 1998, pp. 888-898.
*
* S. Frisken, SurfaceNets for Multi-Label Segmentations with Preservation
* of Sharp Boundaries, J. Computer Graphics Techniques, 2022.
*
* Note that one nice feature of this filter is that algorithm execution
* occurs only once no matter the number of object labels / contour
* values. In many contouring-like algorithms, each separate contour value
* requires an additional algorithm execution with a new contour value. So in
* this filter large numbers of contour values do not significantly affect
* overall speed. The user can specify which objects (i.e., labels) are to be
* output to the filter. (Unspecified labels are treated as background and
* not output.)
*
* The filter can optionally output a two-component, cell data array
* indicating the labels/regions on either side of the line segments
* composing the output vtkPolyData. This can be used for advanced operations
* like extracting shared/contacting boundaries between two objects. The name
* of this cell data array is "BoundaryLabels".
*
* Implementation note: For performance reasons, this filter is internally
* implemented quite differently than described in the literature. The main
* difference is that concepts from the Flying Edges parallel isocontouring
* algorithm are used. Namely, parallel, edge-by-edge processing is used to
* define cell cases, generate smoothing stencils, and produce points and
* output lines. The smoothing process is also threaded using a
* double-buffering approach.
*
* @warning
* This filter is specialized to 2D images.
*
* @warning
* Subtle differences in the output may result when the number of objects /
* labels changes. This is because the smoothing operation operates on all of
* the boundaries simultaneously. If the boundaries change due to a
* difference in the number of regions / labels, then the smoothing operation
* can produce different results.
*
* @warning
* The filters vtkDiscreteMarchingCubes, vtkDiscreteFlyingEdges2D,
* vtkDiscreteFlyingEdges3D, and vtkDiscreteFlyingEdgesClipper2D also
* perform isocontour extraction. However these filters produce output
* that may not share common boundary cells, and may produce "gaps"
* between segmented regions. For example, vtkDiscreteMarchingCubes will
* share points between adjacent regions, but not triangle cells (which
* will be conincident). Also, no center point is inserted into voxels,
* meaning that intermittent gaps may form between regions.
*
* @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.
*
* @sa
* vtkSurfaceNets3D vtkDiscreteFlyingEdges2D vtkDiscreteFlyingEdgesClipper2D
* vtkConstrainedSmoothingFilter vtkFlyingEdges2D vtkFlyingEdges3D
* vtkWindowedSincPolyDataFilter
*/
#ifndef vtkSurfaceNets2D_h
#define vtkSurfaceNets2D_h
#include "vtkConstrainedSmoothingFilter.h" // Perform mesh smoothing
#include "vtkContourValues.h" // Needed for direct access to ContourValues
#include "vtkFiltersCoreModule.h" // For export macro
#include "vtkPolyData.h" // To support data caching
#include "vtkPolyDataAlgorithm.h"
class vtkImageData;
class VTKFILTERSCORE_EXPORT vtkSurfaceNets2D : public vtkPolyDataAlgorithm
{
public:
///@{
/**
* Standard methods for instantiation, printing, and type information.
*/
static vtkSurfaceNets2D* New();
vtkTypeMacro(vtkSurfaceNets2D, vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent) override;
///@}
/**
* The modified time is also a function of the label values and
* the smoothing filter.
*/
vtkMTimeType GetMTime() override;
///@{
/**
* Set a particular label value at label number i. The index i ranges
* between 0 <= i <NumberOfLabels. (Note: while labels values are expressed
* as doubles, the underlying scalar data may be a different type. During
* execution the label values are cast to the type of the scalar data.)
* Note the use of "Value" and "Label" when specifying regions to
* extract. The use of "Value" is continuous with other VTK
* continuous-scalar field isocontouring algorithms; however the term
* "Label" is more consistent with label maps.
*/
void SetValue(int i, double value) { this->Labels->SetValue(i, value); }
void SetLabel(int i, double value) { this->Labels->SetValue(i, value); }
///@}
///@{
/**
* Get the ith label value.
*/
double GetValue(int i) { return this->Labels->GetValue(i); }
double GetLabel(int i) { return this->Labels->GetValue(i); }
///@}
///@{
/**
* Get a pointer to an array of labels. There will be
* GetNumberOfLabels() values in the list.
*/
double* GetValues() { return this->Labels->GetValues(); }
double* GetLabels() { return this->Labels->GetValues(); }
///@}
///@{
/**
* Fill a supplied list with label values. There will be
* GetNumberOfLabels() values in the list. Make sure you allocate enough
* memory to hold the list.
*/
void GetValues(double* contourValues) { this->Labels->GetValues(contourValues); }
void GetLabels(double* contourValues) { this->Labels->GetValues(contourValues); }
///@}
///@{
/**
* Set the number of labels to place into the list. You only really need to
* use this method to reduce list size. The method SetValue() will
* automatically increase list size as needed. Note that for consistency
* with other isocountoring-related algorithms, some methods use
* "Labels" and "Contours" interchangeably.
*/
void SetNumberOfLabels(int number) { this->Labels->SetNumberOfContours(number); }
void SetNumberOfContours(int number) { this->Labels->SetNumberOfContours(number); }
///@}
///@{
/**
* Get the number of labels in the list of label values.
*/
vtkIdType GetNumberOfLabels() { return this->Labels->GetNumberOfContours(); }
vtkIdType GetNumberOfContours() { return this->Labels->GetNumberOfContours(); }
///@}
///@{
/**
* Generate numLabels equally spaced labels between the specified
* range. The labels will include the min/max range values.
*/
void GenerateLabels(int numLabels, double range[2])
{
this->Labels->GenerateValues(numLabels, range);
}
void GenerateValues(int numContours, double range[2])
{
this->Labels->GenerateValues(numContours, range);
}
void GenerateLabels(int numLabels, double rangeStart, double rangeEnd)
{
this->Labels->GenerateValues(numLabels, rangeStart, rangeEnd);
}
void GenerateValues(int numContours, double rangeStart, double rangeEnd)
{
this->Labels->GenerateValues(numContours, rangeStart, rangeEnd);
}
///@}
///@{
/**
* Enable/disable an option to generate cell scalars in the output. The
* cell scalars are a two-tuple that indicates which labels (i.e.,
* segmented regions) are on either side of each (line) cell (l0,l1) with
* l0<l1. If an object is one-sided (meaning the background is on one side
* of the line) then l1=(OutsideLabel). The name of the output cell scalars is
* "BoundaryLabels". By default this flag is on.
*/
vtkSetMacro(ComputeScalars, bool);
vtkGetMacro(ComputeScalars, bool);
vtkBooleanMacro(ComputeScalars, bool);
///@}
///@{
/**
* If computing cell scalars, specify the label to use when referencing a
* labeled region outside any of the specified regions (i.e., when
* referencing the background region). By default this value is zero. Be
* very careful of the value being used here, it should not overlap an
* extracted label value, and because it is the same type as the input
* image scalars, make sure the value can be properly represented (i.e., if
* the input scalars are an unsigned type, then BackgroundLabel should not
* be negative).
*/
vtkSetMacro(BackgroundLabel, double);
vtkGetMacro(BackgroundLabel, double);
///@}
///@{
/**
* Set/get which component of a input multi-component scalar array to
* contour with; defaults to component 0.
*/
vtkSetMacro(ArrayComponent, int);
vtkGetMacro(ArrayComponent, int);
///@}
///@{
/**
* Indicate whether smoothing should be enabled. By default, after the
* isoline is extracted, smoothing occurs using the built-in smoother.
* To disable smoothing, invoke SmoothingOff().
*/
vtkSetMacro(Smoothing, bool);
vtkGetMacro(Smoothing, bool);
vtkBooleanMacro(Smoothing, bool);
///@}
///@{
/**
* Get the instance of vtkConstrainedSmoothingFilter used to smooth the
* extracted surface net. To control smoothing, access this instance and
* specify its parameters such as number of smoothing iterations and
* constraint distance. If you wish to disable smoothing, set
* SmoothingOff().
*/
vtkGetSmartPointerMacro(Smoother, vtkConstrainedSmoothingFilter);
///@}
///@{
/**
* Enable caching of intermediate data. A common workflow using this filter
* requires extracting object boundaries, and then repeatedly rerunning the
* smoothing process with different parameters. To improve performance by
* avoiding repeated extraction of the boundary, the filter can cache
* intermediate data prior to the smoothing process. In this way, the
* boundary is only extracted once, and as long as only the internal
* constrained smoothing filter is modified, then boundary extraction will
* not be reexecuted. By default this is enabled.
*/
vtkSetMacro(DataCaching, bool);
vtkGetMacro(DataCaching, bool);
vtkBooleanMacro(DataCaching, bool);
///@}
protected:
vtkSurfaceNets2D();
~vtkSurfaceNets2D() override = default;
int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
int FillInputPortInformation(int port, vtkInformation* info) override;
vtkSmartPointer<vtkContourValues> Labels;
bool ComputeScalars;
double BackgroundLabel;
int ArrayComponent;
bool Smoothing;
vtkSmartPointer<vtkConstrainedSmoothingFilter> Smoother;
// Support data caching of the extracted surface nets. This is used to
// avoid repeated surface extraction when only smoothing filter
// parameters are modified.
bool DataCaching;
vtkSmartPointer<vtkPolyData> GeometryCache;
vtkSmartPointer<vtkCellArray> StencilsCache;
vtkTimeStamp SmoothingTime;
bool IsCacheEmpty();
void CacheData(vtkPolyData* pd, vtkCellArray* ca);
private:
vtkSurfaceNets2D(const vtkSurfaceNets2D&) = delete;
void operator=(const vtkSurfaceNets2D&) = delete;
};
#endif