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