File: vtkSelectPolyData.h

package info (click to toggle)
vtk9 9.5.2%2Bdfsg3-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 205,916 kB
  • sloc: cpp: 2,336,565; ansic: 327,116; python: 111,200; yacc: 4,104; java: 3,977; sh: 3,032; xml: 2,771; perl: 2,189; lex: 1,787; makefile: 178; javascript: 165; objc: 153; tcl: 59
file content (304 lines) | stat: -rw-r--r-- 10,930 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
/**
 * @class   vtkSelectPolyData
 * @brief   select portion of polygonal mesh; generate selection scalars
 *
 * vtkSelectPolyData is a filter that selects polygonal data based on
 * defining a "loop" and indicating the region inside of the loop. The
 * mesh within the loop consists of complete cells (the cells are not
 * cut). Alternatively, this filter can be used to generate scalars.
 * These scalar values, which are a distance measure to the loop, can
 * be used to clip, contour. or extract data (i.e., anything that an
 * implicit function can do).
 *
 * The loop is defined by an array of x-y-z point coordinates.
 * (Coordinates should be in the same coordinate space as the input
 * polygonal data.) The loop can be concave and non-planar, but not
 * self-intersecting. The input to the filter is a polygonal mesh
 * (only surface primitives such as triangle strips and polygons); the
 * output is either a) a portion of the original mesh laying within
 * the selection loop (GenerateSelectionScalarsOff); or b) the same
 * polygonal mesh with the addition of scalar values
 * (GenerateSelectionScalarsOn).
 *
 * The algorithm works as follows. For each point coordinate in the
 * loop, the closest point in the mesh is found. The result is a loop
 * of closest point ids from the mesh. Then, the edges in the mesh
 * connecting the closest points (and laying along the lines forming
 * the loop) are found. Edges between the points can be searched using
 * one of these methods:
 * A) Greedy edge tracking.
 * At the current point, the mesh edge oriented in the
 * direction of and whose end point is closest to the line is
 * chosen. The edge is followed to the new end point, and the
 * procedure is repeated. This process continues until the entire loop
 * has been created. This method is simple and fast but heuristic,
 * and edge search can randomly fail ("Can't follow edge" error)
 * even for simple, flawless meshes when edge search arrives to a point
 * from where there is no edge pointing towards the next loop point.
 * B) Dijkstra shortest path. This method guarantees to find the shortest
 * path between the loop points.
 *
 * By default the greedy edge tracking method is used to preserve
 * backward compatibility, but generally the Dijkstra shortest path
 * method is recommended due to its robustness.
 *
 * To determine what portion of the mesh is inside and outside of the
 * loop, three options are possible. 1) the smallest connected region,
 * 2) the largest connected region, and 3) the connected region
 * closest to a user specified point. (Set the ivar SelectionMode.)
 *
 * Once the loop is computed as above, the GenerateSelectionScalars
 * controls the output of the filter. If on, then scalar values are
 * generated based on distance to the loop lines. Otherwise, the cells
 * laying inside the selection loop are output. By default, the mesh
 * laying within the loop is output; however, if InsideOut is on, then
 * the portion of the mesh laying outside of the loop is output.
 *
 * The filter can be configured to generate the unselected portions of
 * the mesh as output by setting GenerateUnselectedOutput. Use the
 * method GetUnselectedOutput to access this output. (Note: this flag
 * is pertinent only when GenerateSelectionScalars is off.)
 *
 * @warning
 * Make sure that the points you pick are on a connected surface. If
 * not, then the filter will generate an empty or partial result. Also,
 * self-intersecting loops will generate unpredictable results.
 *
 * @warning
 * During processing of the data, non-triangular cells are converted to
 * triangles if GenerateSelectionScalars is off.
 *
 * @sa
 * vtkImplicitSelectionLoop
 */

#ifndef vtkSelectPolyData_h
#define vtkSelectPolyData_h

#include "vtkFiltersModelingModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"

#define VTK_INSIDE_SMALLEST_REGION 0
#define VTK_INSIDE_LARGEST_REGION 1
#define VTK_INSIDE_CLOSEST_POINT_REGION 2

#define VTK_GREEDY_EDGE_SEARCH 0
#define VTK_DIJKSTRA_EDGE_SEARCH 1

VTK_ABI_NAMESPACE_BEGIN
class vtkCharArray;
class vtkPoints;
class vtkIdList;

class VTKFILTERSMODELING_EXPORT vtkSelectPolyData : public vtkPolyDataAlgorithm
{
public:
  /**
   * Instantiate object with InsideOut turned off, and
   * GenerateSelectionScalars turned off. The unselected output
   * is not generated, and the inside mode is the smallest region.
   */
  static vtkSelectPolyData* New();

  vtkTypeMacro(vtkSelectPolyData, vtkPolyDataAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  ///@{
  /**
   * Set/Get the flag to control behavior of the filter. If
   * GenerateSelectionScalars is on, then the output of the filter
   * is the same as the input, except that scalars are generated.
   * If off, the filter outputs the cells laying inside the loop, and
   * does not generate scalars.
   */
  vtkSetMacro(GenerateSelectionScalars, vtkTypeBool);
  vtkGetMacro(GenerateSelectionScalars, vtkTypeBool);
  vtkBooleanMacro(GenerateSelectionScalars, vtkTypeBool);
  ///@}

  ///@{
  /**
   * Name of the Selection Scalars array. Default is "Selection".
   */
  vtkSetStringMacro(SelectionScalarsArrayName);
  vtkGetStringMacro(SelectionScalarsArrayName);
  ///@}

  ///@{
  /**
   * Set/Get the InsideOut flag. When off, the mesh within the loop is
   * extracted. When on, the mesh outside the loop is extracted.
   */
  vtkSetMacro(InsideOut, vtkTypeBool);
  vtkGetMacro(InsideOut, vtkTypeBool);
  vtkBooleanMacro(InsideOut, vtkTypeBool);
  ///@}

  ///@{
  /**
   * Set the edge search mode. VTK_GREEDY_EDGE_SEARCH is simple and fast,
   * VTK_DIJKSTRA_EDGE_SEARCH is more robust and guaranteed to provide
   * shortest path between loop points.
   * If the algorithm fails with "Can't follow edge" error then switch to
   * Dijkstra method.
   * The default is VTK_GREEDY_EDGE_SEARCH for backward compatibility.
   */
  vtkSetClampMacro(EdgeSearchMode, int, VTK_GREEDY_EDGE_SEARCH, VTK_DIJKSTRA_EDGE_SEARCH);
  vtkGetMacro(EdgeSearchMode, int);
  void SetEdgeSearchModeToGreedy() { this->SetEdgeSearchMode(VTK_GREEDY_EDGE_SEARCH); }
  void SetEdgeSearchModeToDijkstra() { this->SetEdgeSearchMode(VTK_DIJKSTRA_EDGE_SEARCH); }
  const char* GetEdgeSearchModeAsString();
  ///@}

  ///@{
  /**
   * Set/Get the array of point coordinates defining the loop. There must
   * be at least three points used to define a loop.
   */
  virtual void SetLoop(vtkPoints*);
  vtkGetObjectMacro(Loop, vtkPoints);
  ///@}

  ///@{
  /**
   * Set/Get the point used in SelectionModeToClosestPointRegion.
   */
  vtkSetVector3Macro(ClosestPoint, double);
  vtkGetVector3Macro(ClosestPoint, double);
  ///@}

  ///@{
  /**
   * Control how inside/outside of loop is defined.
   */
  vtkSetClampMacro(SelectionMode, int, VTK_INSIDE_SMALLEST_REGION, VTK_INSIDE_CLOSEST_POINT_REGION);
  vtkGetMacro(SelectionMode, int);
  void SetSelectionModeToSmallestRegion() { this->SetSelectionMode(VTK_INSIDE_SMALLEST_REGION); }
  void SetSelectionModeToLargestRegion() { this->SetSelectionMode(VTK_INSIDE_LARGEST_REGION); }
  void SetSelectionModeToClosestPointRegion()
  {
    this->SetSelectionMode(VTK_INSIDE_CLOSEST_POINT_REGION);
  }
  const char* GetSelectionModeAsString();
  ///@}

  ///@{
  /**
   * Control whether a second output is generated. The second output
   * contains the polygonal data that's not been selected.
   */
  vtkSetMacro(GenerateUnselectedOutput, vtkTypeBool);
  vtkGetMacro(GenerateUnselectedOutput, vtkTypeBool);
  vtkBooleanMacro(GenerateUnselectedOutput, vtkTypeBool);
  ///@}

  /**
   * Return output that hasn't been selected (if GenreateUnselectedOutput is
   * enabled).
   */
  vtkPolyData* GetUnselectedOutput();

  /**
   * Return output port that hasn't been selected (if GenreateUnselectedOutput is
   * enabled).
   */
  vtkAlgorithmOutput* GetUnselectedOutputPort();

  /**
   * Return the (mesh) edges of the selection region.
   */
  vtkPolyData* GetSelectionEdges();

  // Overload GetMTime() because we depend on Loop
  vtkMTimeType GetMTime() override;

protected:
  vtkSelectPolyData();
  ~vtkSelectPolyData() override;

  int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;

  // Compute point list that forms a continuous loop overy the mesh,
  void GreedyEdgeSearch(vtkPolyData* mesh, vtkIdList* edgeIds);
  void DijkstraEdgeSearch(vtkPolyData* mesh, vtkIdList* edgeIds);

  // Returns maximum front cell ID
  vtkIdType ComputeTopologicalDistance(
    vtkPolyData* mesh, vtkIdList* edgeIds, vtkIntArray* pointMarks, vtkIntArray* cellMarks);

  // Get closest cell to a position that is not at the boundary
  vtkIdType GetClosestCellId(vtkPolyData* mesh, vtkIntArray* pointMarks);

  // Starting from maxFrontCell, without crossing the boundary, set all cell and point marks to -1.
  void FillMarksInRegion(vtkPolyData* mesh, vtkIdList* edgePointIds, vtkIntArray* pointMarks,
    vtkIntArray* cellMarks, vtkIdType cellIdInSelectedRegion);

  void SetClippedResultToOutput(vtkPointData* originalPointData, vtkCellData* originalCellData,
    vtkPolyData* mesh, vtkIntArray* cellMarks, vtkPolyData* output);

  void SetSelectionScalarsToOutput(vtkPointData* originalPointData, vtkCellData* originalCellData,
    vtkPolyData* mesh, vtkIdList* edgeIds, vtkIntArray* pointMarks, vtkPolyData* output);

  vtkTypeBool GenerateSelectionScalars;
  char* SelectionScalarsArrayName;
  vtkTypeBool InsideOut;
  int EdgeSearchMode;
  vtkPoints* Loop;
  int SelectionMode;
  double ClosestPoint[3];
  vtkTypeBool GenerateUnselectedOutput;

private:
  static void GetPointNeighbors(vtkPolyData* mesh, vtkIdType ptId, vtkIdList* nei);

  // Helper function to check if the edge between pointId1 and pointId2 is present in the
  // edgePointIds (as direct neighbors).
  static bool IsBoundaryEdge(vtkIdType pointId1, vtkIdType pointId2, vtkIdList* edgePointIds);

  vtkSelectPolyData(const vtkSelectPolyData&) = delete;
  void operator=(const vtkSelectPolyData&) = delete;
};

/**
 * Return the method of determining in/out of loop as a string.
 */
inline const char* vtkSelectPolyData::GetSelectionModeAsString()
{
  if (this->SelectionMode == VTK_INSIDE_SMALLEST_REGION)
  {
    return "InsideSmallestRegion";
  }
  else if (this->SelectionMode == VTK_INSIDE_LARGEST_REGION)
  {
    return "InsideLargestRegion";
  }
  else
  {
    return "InsideClosestPointRegion";
  }
}

/**
 * Return the edge search mode as a string.
 */
inline const char* vtkSelectPolyData::GetEdgeSearchModeAsString()
{
  if (this->EdgeSearchMode == VTK_GREEDY_EDGE_SEARCH)
  {
    return "GreedyEdgeSearch";
  }
  else if (this->EdgeSearchMode == VTK_DIJKSTRA_EDGE_SEARCH)
  {
    return "DijkstraEdgeSearch";
  }
  else
  {
    // This should never occur
    return "Invalid";
  }
}

VTK_ABI_NAMESPACE_END
#endif