1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkFlyingEdges3D.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /**
16  * @class   vtkFlyingEdges3D
17  * @brief   generate isosurface from 3D image data (volume)
18  *
19  * vtkFlyingEdges3D is a reference implementation of the 3D version of the
20  * flying edges algorithm. It is designed to be highly scalable (i.e.,
21  * parallelizable) for large data. It implements certain performance
22  * optimizations including computational trimming to rapidly eliminate
23  * processing of data regions, packed bit representation of case table
24  * values, single edge intersection, elimination of point merging, and
25  * elimination of any reallocs (due to dynamic data insertion). Note that
26  * computational trimming is a method to reduce total computational cost in
27  * which partial computational results can be used to eliminate future
28  * computations.
29  *
30  * This is a four-pass algorithm. The first pass processes all x-edges and
31  * builds x-edge case values (which, when the four x-edges defining a voxel
32  * are combined, are equivalent to vertex-based case table except edge-based
33  * approaches are separable in support of parallel computing). Next x-voxel
34  * rows are processed to gather information from yz-edges (basically to count
35  * the number of y-z edge intersections and triangles generated). In the third
36  * pass a prefix sum is used to count and allocate memory for the output
37  * primitives. Finally in the fourth pass output primitives are generated into
38  * pre-allocated arrays. This implementation uses voxel cell axes (a x-y-z
39  * triad located at the voxel origin) to ensure that each edge is intersected
40  * at most one time. Note that this implementation also reuses the VTK
41  * Marching Cubes case table, although the vertex-based MC table is
42  * transformed into an edge-based table on object instantiation.
43  *
44  * See the paper "Flying Edges: A High-Performance Scalable Isocontouring
45  * Algorithm" by Schroeder, Maynard, Geveci. Proc. of LDAV 2015. Chicago, IL.
46  *
47  * @warning
48  * This filter is specialized to 3D volumes. This implementation can produce
49  * degenerate triangles (i.e., zero-area triangles).
50  *
51  * @warning
52  * If you are interested in extracting segmented regions from a label mask,
53  * consider using vtkDiscreteFlyingEdges3D.
54  *
55  * @warning
56  * This class has been threaded with vtkSMPTools. Using TBB or other
57  * non-sequential type (set in the CMake variable
58  * VTK_SMP_IMPLEMENTATION_TYPE) may improve performance significantly.
59  *
60  * @sa
61  * vtkContourFilter vtkFlyingEdges2D vtkSynchronizedTemplates3D
62  * vtkMarchingCubes vtkDiscreteFlyingEdges3D vtkContour3DLinearGrid
63  * vtkFlyingEdgesPlaneCutter
64  */
65 
66 #ifndef vtkFlyingEdges3D_h
67 #define vtkFlyingEdges3D_h
68 
69 #include "vtkContourValues.h"     // Passes calls through
70 #include "vtkFiltersCoreModule.h" // For export macro
71 #include "vtkPolyDataAlgorithm.h"
72 
73 class vtkImageData;
74 
75 class VTKFILTERSCORE_EXPORT vtkFlyingEdges3D : public vtkPolyDataAlgorithm
76 {
77 public:
78   static vtkFlyingEdges3D* New();
79   vtkTypeMacro(vtkFlyingEdges3D, vtkPolyDataAlgorithm);
80   void PrintSelf(ostream& os, vtkIndent indent) override;
81 
82   /**
83    * Because we delegate to vtkContourValues.
84    */
85   vtkMTimeType GetMTime() override;
86 
87   ///@{
88   /**
89    * Set/Get the computation of normals. Normal computation is fairly
90    * expensive in both time and storage. If the output data will be processed
91    * by filters that modify topology or geometry, it may be wise to turn
92    * Normals and Gradients off.
93    */
94   vtkSetMacro(ComputeNormals, vtkTypeBool);
95   vtkGetMacro(ComputeNormals, vtkTypeBool);
96   vtkBooleanMacro(ComputeNormals, vtkTypeBool);
97   ///@}
98 
99   ///@{
100   /**
101    * Set/Get the computation of gradients. Gradient computation is fairly
102    * expensive in both time and storage. Note that if ComputeNormals is on,
103    * gradients will have to be calculated, but will not be stored in the
104    * output dataset. If the output data will be processed by filters that
105    * modify topology or geometry, it may be wise to turn Normals and
106    * Gradients off.
107    */
108   vtkSetMacro(ComputeGradients, vtkTypeBool);
109   vtkGetMacro(ComputeGradients, vtkTypeBool);
110   vtkBooleanMacro(ComputeGradients, vtkTypeBool);
111   ///@}
112 
113   ///@{
114   /**
115    * Set/Get the computation of scalars.
116    */
117   vtkSetMacro(ComputeScalars, vtkTypeBool);
118   vtkGetMacro(ComputeScalars, vtkTypeBool);
119   vtkBooleanMacro(ComputeScalars, vtkTypeBool);
120   ///@}
121 
122   ///@{
123   /**
124    * Indicate whether to interpolate other attribute data. That is, as the
125    * isosurface is generated, interpolate all point attribute data across
126    * the edge. This is independent of scalar interpolation, which is
127    * controlled by the ComputeScalars flag.
128    */
129   vtkSetMacro(InterpolateAttributes, vtkTypeBool);
130   vtkGetMacro(InterpolateAttributes, vtkTypeBool);
131   vtkBooleanMacro(InterpolateAttributes, vtkTypeBool);
132   ///@}
133 
134   /**
135    * Set a particular contour value at contour number i. The index i ranges
136    * between 0<=i<NumberOfContours.
137    */
SetValue(int i,double value)138   void SetValue(int i, double value) { this->ContourValues->SetValue(i, value); }
139 
140   /**
141    * Get the ith contour value.
142    */
GetValue(int i)143   double GetValue(int i) { return this->ContourValues->GetValue(i); }
144 
145   /**
146    * Get a pointer to an array of contour values. There will be
147    * GetNumberOfContours() values in the list.
148    */
GetValues()149   double* GetValues() { return this->ContourValues->GetValues(); }
150 
151   /**
152    * Fill a supplied list with contour values. There will be
153    * GetNumberOfContours() values in the list. Make sure you allocate
154    * enough memory to hold the list.
155    */
GetValues(double * contourValues)156   void GetValues(double* contourValues) { this->ContourValues->GetValues(contourValues); }
157 
158   /**
159    * Set the number of contours to place into the list. You only really
160    * need to use this method to reduce list size. The method SetValue()
161    * will automatically increase list size as needed.
162    */
SetNumberOfContours(int number)163   void SetNumberOfContours(int number) { this->ContourValues->SetNumberOfContours(number); }
164 
165   /**
166    * Get the number of contours in the list of contour values.
167    */
GetNumberOfContours()168   vtkIdType GetNumberOfContours() { return this->ContourValues->GetNumberOfContours(); }
169 
170   /**
171    * Generate numContours equally spaced contour values between specified
172    * range. Contour values will include min/max range values.
173    */
GenerateValues(int numContours,double range[2])174   void GenerateValues(int numContours, double range[2])
175   {
176     this->ContourValues->GenerateValues(numContours, range);
177   }
178 
179   /**
180    * Generate numContours equally spaced contour values between specified
181    * range. Contour values will include min/max range values.
182    */
GenerateValues(int numContours,double rangeStart,double rangeEnd)183   void GenerateValues(int numContours, double rangeStart, double rangeEnd)
184   {
185     this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);
186   }
187 
188   ///@{
189   /**
190    * Set/get which component of the scalar array to contour on; defaults to 0.
191    */
192   vtkSetMacro(ArrayComponent, int);
193   vtkGetMacro(ArrayComponent, int);
194   ///@}
195 
196 protected:
197   vtkFlyingEdges3D();
198   ~vtkFlyingEdges3D() override;
199 
200   vtkTypeBool ComputeNormals;
201   vtkTypeBool ComputeGradients;
202   vtkTypeBool ComputeScalars;
203   vtkTypeBool InterpolateAttributes;
204   int ArrayComponent;
205   vtkContourValues* ContourValues;
206 
207   int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
208   int RequestUpdateExtent(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
209   int FillInputPortInformation(int port, vtkInformation* info) override;
210 
211 private:
212   vtkFlyingEdges3D(const vtkFlyingEdges3D&) = delete;
213   void operator=(const vtkFlyingEdges3D&) = delete;
214 };
215 
216 #endif
217