1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkExtractPolyDataGeometry.cxx
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 #include "vtkExtractPolyDataGeometry.h"
16
17 #include "vtkCellArray.h"
18 #include "vtkCellData.h"
19 #include "vtkFloatArray.h"
20 #include "vtkImplicitFunction.h"
21 #include "vtkInformation.h"
22 #include "vtkInformationVector.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkPointData.h"
25 #include "vtkPolyData.h"
26
27 vtkStandardNewMacro(vtkExtractPolyDataGeometry);
28 vtkCxxSetObjectMacro(vtkExtractPolyDataGeometry, ImplicitFunction, vtkImplicitFunction);
29
30 //------------------------------------------------------------------------------
31 // Construct object with ExtractInside turned on.
vtkExtractPolyDataGeometry(vtkImplicitFunction * f)32 vtkExtractPolyDataGeometry::vtkExtractPolyDataGeometry(vtkImplicitFunction* f)
33 {
34 this->ImplicitFunction = f;
35 if (this->ImplicitFunction)
36 {
37 this->ImplicitFunction->Register(this);
38 }
39
40 this->ExtractInside = 1;
41 this->ExtractBoundaryCells = 0;
42 this->PassPoints = 0;
43 }
44
45 //------------------------------------------------------------------------------
~vtkExtractPolyDataGeometry()46 vtkExtractPolyDataGeometry::~vtkExtractPolyDataGeometry()
47 {
48 this->SetImplicitFunction(nullptr);
49 }
50
51 //------------------------------------------------------------------------------
52 // Overload standard modified time function. If implicit function is modified,
53 // then this object is modified as well.
GetMTime()54 vtkMTimeType vtkExtractPolyDataGeometry::GetMTime()
55 {
56 vtkMTimeType mTime = this->MTime.GetMTime();
57 vtkMTimeType impFuncMTime;
58
59 if (this->ImplicitFunction != nullptr)
60 {
61 impFuncMTime = this->ImplicitFunction->GetMTime();
62 mTime = (impFuncMTime > mTime ? impFuncMTime : mTime);
63 }
64
65 return mTime;
66 }
67
68 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)69 int vtkExtractPolyDataGeometry::RequestData(vtkInformation* vtkNotUsed(request),
70 vtkInformationVector** inputVector, vtkInformationVector* outputVector)
71 {
72 // get the info objects
73 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
74 vtkInformation* outInfo = outputVector->GetInformationObject(0);
75
76 // get the input and output
77 vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
78 vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
79
80 vtkPointData* pd = input->GetPointData();
81 vtkCellData* cd = input->GetCellData();
82 vtkPointData* outputPD = output->GetPointData();
83 vtkCellData* outputCD = output->GetCellData();
84 vtkPoints* inPts = input->GetPoints();
85 vtkIdType numPts, i, cellId = 0, newId, ptId, *pointMap = nullptr;
86 float multiplier;
87 vtkCellArray *inVerts = nullptr, *inLines = nullptr, *inPolys = nullptr, *inStrips = nullptr;
88 vtkCellArray *newVerts = nullptr, *newLines = nullptr, *newPolys = nullptr, *newStrips = nullptr;
89 vtkPoints* newPts = nullptr;
90
91 vtkDebugMacro(<< "Extracting poly data geometry");
92
93 if (!this->ImplicitFunction)
94 {
95 vtkErrorMacro(<< "No implicit function specified");
96 return 1;
97 }
98
99 numPts = input->GetNumberOfPoints();
100
101 if (this->ExtractInside)
102 {
103 multiplier = 1.0;
104 }
105 else
106 {
107 multiplier = -1.0;
108 }
109
110 // Use a templated function to access the points. The points are
111 // passed through, but scalar values are generated.
112 vtkFloatArray* newScalars = vtkFloatArray::New();
113 newScalars->SetNumberOfValues(numPts);
114
115 for (ptId = 0; ptId < numPts; ptId++)
116 {
117 newScalars->SetValue(
118 ptId, this->ImplicitFunction->FunctionValue(inPts->GetPoint(ptId)) * multiplier);
119 }
120
121 // Do different things with the points depending on user directive
122 if (this->PassPoints)
123 {
124 output->SetPoints(inPts);
125 outputPD->PassData(pd);
126 }
127 else
128 {
129 newPts = vtkPoints::New();
130 newPts->Allocate(numPts / 4, numPts);
131 pointMap = new vtkIdType[numPts]; // maps old point ids into new
132 for (ptId = 0; ptId < numPts; ptId++)
133 {
134 if (newScalars->GetValue(ptId) <= 0.0)
135 {
136 newId = this->InsertPointInMap(ptId, inPts, newPts, pointMap);
137 }
138 else
139 {
140 pointMap[ptId] = -1;
141 }
142 }
143 }
144 outputCD->CopyAllocate(cd);
145
146 // Now loop over all cells to see whether they are inside the implicit
147 // function. Copy if they are. Note: there is an awful hack here, that
148 // can result in bugs. The cellId is assumed to be arranged starting
149 // with the verts, then lines, then polys, then strips.
150 //
151 int numIn;
152 vtkIdType npts = 0;
153 const vtkIdType* pts = nullptr;
154 if (input->GetNumberOfVerts())
155 {
156 inVerts = input->GetVerts();
157 newVerts = vtkCellArray::New();
158 newVerts->AllocateCopy(inVerts);
159 }
160 if (input->GetNumberOfLines())
161 {
162 inLines = input->GetLines();
163 newLines = vtkCellArray::New();
164 newLines->AllocateCopy(inLines);
165 }
166 if (input->GetNumberOfPolys())
167 {
168 inPolys = input->GetPolys();
169 newPolys = vtkCellArray::New();
170 newPolys->AllocateCopy(inPolys);
171 }
172 if (input->GetNumberOfStrips())
173 {
174 inStrips = input->GetStrips();
175 newStrips = vtkCellArray::New();
176 newStrips->AllocateCopy(inStrips);
177 }
178
179 // verts
180 if (newVerts && !this->GetAbortExecute())
181 {
182 for (inVerts->InitTraversal(); inVerts->GetNextCell(npts, pts);)
183 {
184 for (numIn = 0, i = 0; i < npts; i++)
185 {
186 if (newScalars->GetValue(pts[i]) <= 0.0)
187 {
188 numIn++;
189 }
190 }
191 if ((numIn == npts) || (this->ExtractBoundaryCells && numIn > 0))
192 {
193 if (this->PassPoints)
194 {
195 newId = newVerts->InsertNextCell(npts, pts);
196 }
197 else
198 {
199 newId = newVerts->InsertNextCell(npts);
200 for (i = 0; i < npts; i++)
201 {
202 if (pointMap[pts[i]] < 0)
203 {
204 ptId = this->InsertPointInMap(pts[i], inPts, newPts, pointMap);
205 }
206 else
207 {
208 ptId = pointMap[pts[i]];
209 }
210 newVerts->InsertCellPoint(ptId);
211 }
212 }
213 outputCD->CopyData(cd, cellId, newId);
214 }
215 cellId++;
216 }
217 }
218 this->UpdateProgress(0.6);
219
220 // lines
221 if (newLines && !this->GetAbortExecute())
222 {
223 for (inLines->InitTraversal(); inLines->GetNextCell(npts, pts);)
224 {
225 for (numIn = 0, i = 0; i < npts; i++)
226 {
227 if (newScalars->GetValue(pts[i]) <= 0.0)
228 {
229 numIn++;
230 }
231 }
232 if ((numIn == npts) || (this->ExtractBoundaryCells && numIn > 0))
233 {
234 if (this->PassPoints)
235 {
236 newId = newLines->InsertNextCell(npts, pts);
237 }
238 else
239 {
240 newId = newLines->InsertNextCell(npts);
241 for (i = 0; i < npts; i++)
242 {
243 if (pointMap[pts[i]] < 0)
244 {
245 ptId = this->InsertPointInMap(pts[i], inPts, newPts, pointMap);
246 }
247 else
248 {
249 ptId = pointMap[pts[i]];
250 }
251 newLines->InsertCellPoint(ptId);
252 }
253 }
254 outputCD->CopyData(cd, cellId, newId);
255 }
256 cellId++;
257 }
258 }
259 this->UpdateProgress(0.75);
260
261 // polys
262 if (newPolys && !this->GetAbortExecute())
263 {
264 for (inPolys->InitTraversal(); inPolys->GetNextCell(npts, pts);)
265 {
266 for (numIn = 0, i = 0; i < npts; i++)
267 {
268 if (newScalars->GetValue(pts[i]) <= 0.0)
269 {
270 numIn++;
271 }
272 }
273 if ((numIn == npts) || (this->ExtractBoundaryCells && numIn > 0))
274 {
275 if (this->PassPoints)
276 {
277 newId = newPolys->InsertNextCell(npts, pts);
278 }
279 else
280 {
281 newId = newPolys->InsertNextCell(npts);
282 for (i = 0; i < npts; i++)
283 {
284 if (pointMap[pts[i]] < 0)
285 {
286 ptId = this->InsertPointInMap(pts[i], inPts, newPts, pointMap);
287 }
288 else
289 {
290 ptId = pointMap[pts[i]];
291 }
292 newPolys->InsertCellPoint(ptId);
293 }
294 }
295 outputCD->CopyData(cd, cellId, newId);
296 }
297 cellId++;
298 }
299 }
300 this->UpdateProgress(0.90);
301
302 // strips
303 if (newStrips && !this->GetAbortExecute())
304 {
305 for (inStrips->InitTraversal(); inStrips->GetNextCell(npts, pts);)
306 {
307 for (numIn = 0, i = 0; i < npts; i++)
308 {
309 if (newScalars->GetValue(pts[i]) <= 0.0)
310 {
311 numIn++;
312 }
313 }
314 if ((numIn == npts) || (this->ExtractBoundaryCells && numIn > 0))
315 {
316 if (this->PassPoints)
317 {
318 newId = newStrips->InsertNextCell(npts, pts);
319 }
320 else
321 {
322 newId = newStrips->InsertNextCell(npts);
323 for (i = 0; i < npts; i++)
324 {
325 if (pointMap[pts[i]] < 0)
326 {
327 ptId = this->InsertPointInMap(pts[i], inPts, newPts, pointMap);
328 }
329 else
330 {
331 ptId = pointMap[pts[i]];
332 }
333 newStrips->InsertCellPoint(ptId);
334 }
335 }
336 outputCD->CopyData(cd, cellId, newId);
337 }
338 cellId++;
339 }
340 }
341 this->UpdateProgress(1.0);
342
343 // Update ourselves and release memory
344 //
345 newScalars->Delete();
346 if (!this->PassPoints)
347 {
348 output->SetPoints(newPts);
349 newPts->Delete();
350 outputPD->CopyAllocate(pd);
351 for (i = 0; i < numPts; i++)
352 {
353 if (pointMap[i] >= 0)
354 {
355 outputPD->CopyData(pd, i, pointMap[i]);
356 }
357 }
358 delete[] pointMap;
359 }
360
361 if (newVerts)
362 {
363 output->SetVerts(newVerts);
364 newVerts->Delete();
365 }
366 if (newLines)
367 {
368 output->SetLines(newLines);
369 newLines->Delete();
370 }
371 if (newPolys)
372 {
373 output->SetPolys(newPolys);
374 newPolys->Delete();
375 }
376 if (newStrips)
377 {
378 output->SetStrips(newStrips);
379 newStrips->Delete();
380 }
381
382 return 1;
383 }
384
385 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)386 void vtkExtractPolyDataGeometry::PrintSelf(ostream& os, vtkIndent indent)
387 {
388 this->Superclass::PrintSelf(os, indent);
389
390 if (this->ImplicitFunction)
391 {
392 os << indent << "Implicit Function: " << static_cast<void*>(this->ImplicitFunction) << "\n";
393 }
394 else
395 {
396 os << indent << "Implicit Function: (null)\n";
397 }
398 os << indent << "Extract Inside: " << (this->ExtractInside ? "On\n" : "Off\n");
399 os << indent << "Extract Boundary Cells: " << (this->ExtractBoundaryCells ? "On\n" : "Off\n");
400 os << indent << "Pass Points: " << (this->PassPoints ? "On\n" : "Off\n");
401 }
402