1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkExtractCells.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 /*----------------------------------------------------------------------------
16 Copyright (c) Sandia Corporation
17 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
18 ----------------------------------------------------------------------------*/
19
20 #include "vtkExtractCells.h"
21
22 #include "vtkCell.h"
23 #include "vtkCellArray.h"
24 #include "vtkCellArrayIterator.h"
25 #include "vtkCellData.h"
26 #include "vtkDoubleArray.h"
27 #include "vtkIdTypeArray.h"
28 #include "vtkInformation.h"
29 #include "vtkNew.h"
30 #include "vtkObjectFactory.h"
31 #include "vtkPointData.h"
32 #include "vtkPointSet.h"
33 #include "vtkPoints.h"
34 #include "vtkSMPThreadLocalObject.h"
35 #include "vtkSMPTools.h"
36 #include "vtkTimeStamp.h"
37 #include "vtkUnsignedCharArray.h"
38 #include "vtkUnstructuredGrid.h"
39
40 #include <algorithm>
41 #include <iterator>
42 #include <numeric>
43 #include <vector>
44
45 namespace
46 {
47
48 struct ExtractedCellsT
49 {
50 vtkSmartPointer<vtkCellArray> Connectivity;
51 vtkSmartPointer<vtkUnsignedCharArray> CellTypes;
52 vtkSmartPointer<vtkIdTypeArray> Faces;
53 vtkSmartPointer<vtkIdTypeArray> FaceLocations;
54 };
55
56 //=============================================================================
57 /*
58 * These work types help us reuse the same code for extracting elements
59 * when a smaller subset is being extracted or everything is being extracted
60 * with ease.
61 */
62 struct AllElementsWork
63 {
64 vtkIdType NumberOfPoints;
65 vtkIdType NumberOfCells;
66
67 // PointWork API
GetNumberOfPoints__anon984874830111::AllElementsWork68 inline vtkIdType GetNumberOfPoints() const { return this->NumberOfPoints; }
GetPointId__anon984874830111::AllElementsWork69 inline vtkIdType GetPointId(vtkIdType index) const { return index; }
70
71 // CellWork API
GetNumberOfCells__anon984874830111::AllElementsWork72 inline vtkIdType GetNumberOfCells() const { return this->NumberOfCells; }
GetCellId__anon984874830111::AllElementsWork73 inline vtkIdType GetCellId(vtkIdType index) const { return index; }
MapPointIds__anon984874830111::AllElementsWork74 inline void MapPointIds(vtkIdList*) const {};
75 };
76
77 struct SubsetCellsWork
78 {
79 const std::vector<vtkIdType>::const_iterator Begin;
80 const std::vector<vtkIdType>::const_iterator End;
81 const std::vector<vtkIdType>& PointMap;
82 vtkIdType NumberOfCells;
83
GetNumberOfCells__anon984874830111::SubsetCellsWork84 inline vtkIdType GetNumberOfCells() const { return this->NumberOfCells; }
GetCellId__anon984874830111::SubsetCellsWork85 inline vtkIdType GetCellId(vtkIdType index) const { return *std::next(this->Begin, index); }
MapPointId__anon984874830111::SubsetCellsWork86 inline vtkIdType MapPointId(vtkIdType id) const
87 {
88 assert(id >= 0 && id < static_cast<vtkIdType>(this->PointMap.size()));
89 return this->PointMap[id];
90 }
MapPointIds__anon984874830111::SubsetCellsWork91 inline void MapPointIds(vtkIdList* ids) const
92 {
93 for (vtkIdType ptid = 0, max = ids->GetNumberOfIds(); ptid < max; ++ptid)
94 {
95 ids->SetId(ptid, this->MapPointId(ids->GetId(ptid)));
96 }
97 };
98 };
99
100 struct SubsetPointsWork
101 {
102 const vtkSmartPointer<vtkIdList>& PointIdsToExtract;
GetNumberOfPoints__anon984874830111::SubsetPointsWork103 inline vtkIdType GetNumberOfPoints() const { return this->PointIdsToExtract->GetNumberOfIds(); }
GetPointId__anon984874830111::SubsetPointsWork104 inline vtkIdType GetPointId(vtkIdType index) const
105 {
106 return this->PointIdsToExtract->GetId(index);
107 }
108 };
109 //=============================================================================
110
111 //------------------------------------------------------------------------------
112 /* This function returns a new vtkPoints extracted from the `input`.
113 * The points to extract are identified by the `PointWork`:
114 * `PointWork::GetNumberOfPoints`: total number of points to extract
115 * `PointWork::GetPointId(idx)`: original pt id for extracted point at the `idx`
116 */
117 template <typename PointWorkT>
DoExtractPoints(vtkDataSet * input,const PointWorkT & work)118 static vtkSmartPointer<vtkPoints> DoExtractPoints(vtkDataSet* input, const PointWorkT& work)
119 {
120 vtkNew<vtkPoints> pts;
121 pts->SetDataTypeToDouble();
122 pts->SetNumberOfPoints(work.GetNumberOfPoints());
123 auto array = vtkDoubleArray::SafeDownCast(pts->GetData());
124
125 vtkSMPTools::For(
126 0, work.GetNumberOfPoints(), [&work, &array, &input](vtkIdType first, vtkIdType last) {
127 double coords[3];
128 for (vtkIdType cc = first; cc < last; ++cc)
129 {
130 input->GetPoint(work.GetPointId(cc), coords);
131 array->SetTypedTuple(cc, coords);
132 }
133 });
134 return pts;
135 }
136
137 //------------------------------------------------------------------------------
138 /**
139 * Adds `vtkOriginalCellIds` array, if not already present in `outCD`.
140 * `CellWorkT::GetNumberOfCells`: total number of cells being extracted.
141 * `CellWorkT::GetCellId(idx)`: original cell id for extracted cell at index `idx`.
142 */
143 template <typename CellWorkT>
AddOriginalCellIds(vtkCellData * outCD,const CellWorkT & work)144 static void AddOriginalCellIds(vtkCellData* outCD, const CellWorkT& work)
145 {
146 // add vtkOriginalCellIds array, if needed.
147 if (outCD->GetArray("vtkOriginalCellIds") == nullptr)
148 {
149 const auto numCells = work.GetNumberOfCells();
150 vtkNew<vtkIdTypeArray> ids;
151 ids->SetName("vtkOriginalCellIds");
152 ids->SetNumberOfTuples(numCells);
153 vtkSMPTools::For(0, numCells, [&ids, &work](vtkIdType start, vtkIdType end) {
154 for (vtkIdType cc = start; cc < end; ++cc)
155 {
156 ids->SetTypedComponent(cc, 0, work.GetCellId(cc));
157 }
158 });
159 outCD->AddArray(ids);
160 }
161 }
162
163 //------------------------------------------------------------------------------
164 /* Extracts cells identified by `work` from the input.
165 * Returns ExtractedCellsT with connectivity and cell-types array set.
166 */
167 template <typename CellWorkT>
DoExtractCells(vtkDataSet * input,const CellWorkT & work)168 static ExtractedCellsT DoExtractCells(vtkDataSet* input, const CellWorkT& work)
169 {
170 const auto numCells = work.GetNumberOfCells();
171
172 ExtractedCellsT result;
173 result.Connectivity.TakeReference(vtkCellArray::New());
174 result.Connectivity->AllocateEstimate(numCells, input->GetMaxCellSize());
175 result.CellTypes.TakeReference(vtkUnsignedCharArray::New());
176 result.CellTypes->Allocate(numCells);
177
178 vtkNew<vtkIdList> ptIds;
179 for (vtkIdType cc = 0; cc < numCells; ++cc)
180 {
181 const auto in_cellid = work.GetCellId(cc);
182 input->GetCellPoints(in_cellid, ptIds);
183 work.MapPointIds(ptIds);
184 result.Connectivity->InsertNextCell(ptIds);
185 result.CellTypes->InsertNextValue(input->GetCellType(in_cellid));
186 }
187 result.Connectivity->Squeeze();
188 result.CellTypes->Squeeze();
189 return result;
190 }
191
192 //------------------------------------------------------------------------------
193 /**
194 * Extract polyhedral cell-face information form input. Adds `Faces` and
195 * `FaceLocations` to `result`.
196 */
197 template <typename CellWorkT>
DoExtractPolyhedralFaces(ExtractedCellsT & result,vtkUnstructuredGrid * input,const CellWorkT & work)198 static void DoExtractPolyhedralFaces(
199 ExtractedCellsT& result, vtkUnstructuredGrid* input, const CellWorkT& work)
200 {
201 const auto numCells = work.GetNumberOfCells();
202 auto inFaceLocations = input->GetFaceLocations();
203 auto inFaces = input->GetFaces();
204
205 result.FaceLocations.TakeReference(vtkIdTypeArray::New());
206 result.FaceLocations->SetNumberOfTuples(numCells);
207
208 vtkIdType outFacesSize = 0;
209 for (vtkIdType cc = 0; cc < numCells; ++cc)
210 {
211 const auto loc = inFaceLocations->GetValue(work.GetCellId(cc));
212 if (loc == -1)
213 {
214 // not a polyhedral cell
215 result.FaceLocations->SetTypedComponent(cc, 0, -1);
216 }
217 else
218 {
219 result.FaceLocations->SetTypedComponent(cc, 0, outFacesSize);
220 vtkIdType* pfaces_start = inFaces->GetPointer(loc);
221 vtkIdType* pfaces = pfaces_start;
222 const auto nfaces = (*pfaces++);
223 for (vtkIdType face = 0; face < nfaces; ++face)
224 {
225 const auto npts = (*pfaces++);
226 pfaces += npts;
227 }
228 outFacesSize += static_cast<vtkIdType>(std::distance(pfaces_start, pfaces));
229 }
230 }
231
232 // Now copy polyhedron Faces.
233 result.Faces.TakeReference(vtkIdTypeArray::New());
234 result.Faces->SetNumberOfTuples(outFacesSize);
235
236 vtkSMPTools::For(0, numCells, [&](vtkIdType start, vtkIdType end) {
237 for (vtkIdType cc = start; cc < end; ++cc)
238 {
239 const auto inLoc = inFaceLocations->GetValue(work.GetCellId(cc));
240 if (inLoc == -1)
241 {
242 continue;
243 }
244 const auto outLoc = result.FaceLocations->GetValue(cc);
245
246 auto iptr = inFaces->GetPointer(inLoc);
247 auto optr = result.Faces->GetPointer(outLoc);
248 const auto nfaces = *iptr++;
249 *optr++ = nfaces;
250 for (vtkIdType face = 0; face < nfaces; ++face)
251 {
252 const auto npts = (*iptr++);
253 *optr++ = npts;
254 std::transform(
255 iptr, iptr + npts, optr, [&work](vtkIdType id) { return work.MapPointId(id); });
256 optr += npts;
257 iptr += npts;
258 }
259 }
260 });
261 }
262
263 //------------------------------------------------------------------------------
264 template <typename IteratorType>
FlagChosenPoints(vtkDataSet * input,const IteratorType & start,const IteratorType & end)265 static std::vector<vtkIdType> FlagChosenPoints(
266 vtkDataSet* input, const IteratorType& start, const IteratorType& end)
267 {
268 std::vector<vtkIdType> chosen_points(input->GetNumberOfPoints(), 0);
269 const vtkIdType num_cells = static_cast<vtkIdType>(std::distance(start, end));
270
271 vtkSMPThreadLocalObject<vtkIdList> ptIds;
272
273 // make input API threadsafe by calling it once in a single thread.
274 input->GetCellType(0);
275 input->GetCellPoints(0, ptIds.Local());
276
277 // flag each point used by all of the selected cells.
278 vtkSMPTools::For(0, num_cells, [&](vtkIdType first, vtkIdType last) {
279 auto& lptIds = ptIds.Local();
280 auto celliditer = std::next(start, first);
281 for (vtkIdType cc = first; cc < last; ++cc, ++celliditer)
282 {
283 const auto id = *(celliditer);
284 input->GetCellPoints(id, lptIds);
285 for (vtkIdType i = 0, max = lptIds->GetNumberOfIds(); i < max; ++i)
286 {
287 chosen_points[lptIds->GetId(i)] = 1;
288 }
289 }
290 });
291 return chosen_points;
292 }
293
294 //------------------------------------------------------------------------------
295 // Faster overload for vtkUnstructuredGrid
296 template <typename IteratorType>
FlagChosenPoints(vtkUnstructuredGrid * input,const IteratorType & start,const IteratorType & end)297 static std::vector<vtkIdType> FlagChosenPoints(
298 vtkUnstructuredGrid* input, const IteratorType& start, const IteratorType& end)
299 {
300 std::vector<vtkIdType> chosen_points(input->GetNumberOfPoints(), 0);
301 const vtkIdType num_cells = static_cast<vtkIdType>(std::distance(start, end));
302 auto cellArray = input->GetCells();
303
304 // flag each point used by all of the selected cells.
305 vtkSMPThreadLocal<vtkSmartPointer<vtkCellArrayIterator>> storage;
306
307 vtkSMPTools::For(0, num_cells, [&](vtkIdType first, vtkIdType last) {
308 auto celliditer = std::next(start, first);
309 auto& caIter = storage.Local();
310 if (caIter.GetPointer() == nullptr)
311 {
312 caIter.TakeReference(cellArray->NewIterator());
313 }
314 vtkIdType npts;
315 const vtkIdType* ptids;
316 for (vtkIdType cc = first; cc < last; ++cc, ++celliditer)
317 {
318 const auto id = *(celliditer);
319 caIter->GetCellAtId(id, npts, ptids);
320 for (vtkIdType i = 0; i < npts; ++i)
321 {
322 chosen_points[ptids[i]] = 1;
323 }
324 }
325 });
326 return chosen_points;
327 }
328
329 //------------------------------------------------------------------------------
330 template <typename IteratorType>
GeneratePointMap(vtkDataSet * input,const IteratorType & start,const IteratorType & end,vtkIdType & outNumPoints)331 static std::vector<vtkIdType> GeneratePointMap(
332 vtkDataSet* input, const IteratorType& start, const IteratorType& end, vtkIdType& outNumPoints)
333 {
334 auto ugInput = vtkUnstructuredGrid::SafeDownCast(input);
335 std::vector<vtkIdType> chosen_points = ugInput != nullptr ? FlagChosenPoints(ugInput, start, end)
336 : FlagChosenPoints(input, start, end);
337 // convert flags to map where index is old id, value is new id and -1 means
338 // the point is to be discarded.
339 vtkIdType nextid = 0;
340 for (auto& pt : chosen_points)
341 {
342 pt = pt ? nextid++ : -1;
343 }
344 outNumPoints = nextid;
345 return chosen_points;
346 }
347
348 //------------------------------------------------------------------------------
349 template <typename CellWorkT>
CopyCellData(vtkCellData * input,vtkCellData * output,const CellWorkT & work)350 static void CopyCellData(vtkCellData* input, vtkCellData* output, const CellWorkT& work)
351 {
352 const auto numValues = work.GetNumberOfCells();
353 output->CopyAllocate(input, numValues);
354
355 vtkNew<vtkIdList> srcIds;
356 srcIds->SetNumberOfIds(numValues);
357
358 vtkIdType next = 0;
359 std::generate_n(
360 srcIds->GetPointer(0), numValues, [&work, &next]() { return work.GetCellId(next++); });
361
362 vtkNew<vtkIdList> dstIds;
363 dstIds->SetNumberOfIds(numValues);
364 std::iota(dstIds->GetPointer(0), dstIds->GetPointer(numValues), 0);
365
366 output->CopyData(input, srcIds, dstIds);
367 }
368
369 //------------------------------------------------------------------------------
CopyPointData(vtkPointData * inPD,vtkPointData * outPD,vtkIdList * srcIds)370 void CopyPointData(vtkPointData* inPD, vtkPointData* outPD, vtkIdList* srcIds)
371 {
372 const auto numValues = srcIds->GetNumberOfIds();
373 outPD->CopyAllocate(inPD, numValues);
374 vtkNew<vtkIdList> dstIds;
375 dstIds->SetNumberOfIds(numValues);
376 std::iota(dstIds->GetPointer(0), dstIds->GetPointer(numValues), 0);
377 outPD->CopyData(inPD, srcIds, dstIds);
378 }
379
380 //------------------------------------------------------------------------------
ConvertToPointIdsToExtract(const std::vector<vtkIdType> & pointMap,const vtkIdType numValues)381 vtkSmartPointer<vtkIdList> ConvertToPointIdsToExtract(
382 const std::vector<vtkIdType>& pointMap, const vtkIdType numValues)
383 {
384 vtkNew<vtkIdList> srcIds;
385 srcIds->Allocate(numValues);
386 for (vtkIdType cc = 0; cc < static_cast<vtkIdType>(pointMap.size()); ++cc)
387 {
388 if (pointMap[cc] != -1)
389 {
390 srcIds->InsertNextId(cc);
391 }
392 }
393 srcIds->Squeeze();
394 assert(numValues == srcIds->GetNumberOfIds());
395 return srcIds;
396 }
397
398 } // end anonymous namespace
399
400 //=============================================================================
401 class vtkExtractCellsSTLCloak
402 {
403 vtkTimeStamp SortTime;
404
405 public:
406 std::vector<vtkIdType> CellIds;
407 std::pair<typename std::vector<vtkIdType>::const_iterator,
408 typename std::vector<vtkIdType>::const_iterator>
409 CellIdsRange;
410
Prepare(vtkIdType numInputCells,vtkExtractCells * self)411 vtkIdType Prepare(vtkIdType numInputCells, vtkExtractCells* self)
412 {
413 assert(numInputCells > 0);
414
415 if (self->GetAssumeSortedAndUniqueIds() == false && (self->GetMTime() > this->SortTime))
416 {
417 vtkSMPTools::Sort(this->CellIds.begin(), this->CellIds.end());
418 auto last = std::unique(this->CellIds.begin(), this->CellIds.end());
419 this->CellIds.erase(last, this->CellIds.end());
420 this->SortTime.Modified();
421 }
422
423 this->CellIdsRange =
424 std::make_pair(std::lower_bound(this->CellIds.begin(), this->CellIds.end(), 0),
425 std::upper_bound(this->CellIds.begin(), this->CellIds.end(), (numInputCells - 1)));
426 return static_cast<vtkIdType>(
427 std::distance(this->CellIdsRange.first, this->CellIdsRange.second));
428 }
429 };
430
431 vtkStandardNewMacro(vtkExtractCells);
432 //------------------------------------------------------------------------------
vtkExtractCells()433 vtkExtractCells::vtkExtractCells()
434 {
435 this->CellList = new vtkExtractCellsSTLCloak;
436 }
437
438 //------------------------------------------------------------------------------
~vtkExtractCells()439 vtkExtractCells::~vtkExtractCells()
440 {
441 delete this->CellList;
442 }
443
444 //------------------------------------------------------------------------------
SetCellList(vtkIdList * l)445 void vtkExtractCells::SetCellList(vtkIdList* l)
446 {
447 delete this->CellList;
448 this->CellList = new vtkExtractCellsSTLCloak;
449 if (l != nullptr)
450 {
451 this->AddCellList(l);
452 }
453 this->Modified();
454 }
455
456 //------------------------------------------------------------------------------
AddCellList(vtkIdList * l)457 void vtkExtractCells::AddCellList(vtkIdList* l)
458 {
459 const vtkIdType inputSize = l ? l->GetNumberOfIds() : 0;
460 if (inputSize == 0)
461 {
462 return;
463 }
464
465 auto& cellIds = this->CellList->CellIds;
466 const vtkIdType* inputBegin = l->GetPointer(0);
467 const vtkIdType* inputEnd = inputBegin + inputSize;
468 std::copy(inputBegin, inputEnd, std::back_inserter(cellIds));
469 this->Modified();
470 }
471
472 //------------------------------------------------------------------------------
SetCellIds(const vtkIdType * ptr,vtkIdType numValues)473 void vtkExtractCells::SetCellIds(const vtkIdType* ptr, vtkIdType numValues)
474 {
475 delete this->CellList;
476 this->CellList = new vtkExtractCellsSTLCloak;
477 if (ptr != nullptr && numValues > 0)
478 {
479 this->AddCellIds(ptr, numValues);
480 }
481 this->Modified();
482 }
483
484 //------------------------------------------------------------------------------
AddCellIds(const vtkIdType * ptr,vtkIdType numValues)485 void vtkExtractCells::AddCellIds(const vtkIdType* ptr, vtkIdType numValues)
486 {
487 auto& cellIds = this->CellList->CellIds;
488 std::copy(ptr, ptr + numValues, std::back_inserter(cellIds));
489 this->Modified();
490 }
491
492 //------------------------------------------------------------------------------
AddCellRange(vtkIdType from,vtkIdType to)493 void vtkExtractCells::AddCellRange(vtkIdType from, vtkIdType to)
494 {
495 if (to < from || to < 0)
496 {
497 vtkWarningMacro("Bad cell range: (" << to << "," << from << ")");
498 return;
499 }
500
501 // This range specification is inconsistent with C++. Left for backward
502 // compatibility reasons. Add 1 to `to` to make it consistent.
503 ++to;
504
505 auto& cellIds = this->CellList->CellIds;
506 std::generate_n(std::back_inserter(cellIds), (to - from), [&from]() { return from++; });
507 this->Modified();
508 }
509
510 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)511 int vtkExtractCells::RequestData(vtkInformation* vtkNotUsed(request),
512 vtkInformationVector** inputVector, vtkInformationVector* outputVector)
513 {
514 // get the input and output
515 vtkDataSet* input = vtkDataSet::GetData(inputVector[0]);
516 vtkUnstructuredGrid* output = vtkUnstructuredGrid::GetData(outputVector);
517
518 auto inPD = input->GetPointData();
519 auto inCD = input->GetCellData();
520 auto outPD = output->GetPointData();
521 auto outCD = output->GetCellData();
522
523 // copy all arrays, including global ids etc.
524 outPD->CopyAllOn();
525 outCD->CopyAllOn();
526
527 const vtkIdType numCellsInput = input->GetNumberOfCells();
528 const vtkIdType numCells =
529 this->ExtractAllCells ? numCellsInput : this->CellList->Prepare(numCellsInput, this);
530
531 // Handle simple cases, first.
532 // Check if no cells are to be extracted
533 if (numCells == 0)
534 {
535 // set up a ugrid with same data arrays as input, but
536 // no points, cells or data.
537 output->Allocate(1);
538 outPD->CopyAllocate(inPD, 1);
539 outCD->CopyAllocate(inCD, 1);
540 vtkNew<vtkPoints> pts;
541 pts->SetNumberOfPoints(0);
542 output->SetPoints(pts);
543 return 1;
544 }
545 else if (numCellsInput == numCells)
546 {
547 // Check if all cells are to be extracted.
548 // `Copy` will ShallowCopy input if input is vtkUnstructuredGrid, else
549 // convert it to an unstructured grid.
550 return this->Copy(input, output) ? 1 : 0;
551 }
552
553 // Build point map for selected cells.
554 const auto& cellids_range = this->CellList->CellIdsRange;
555 assert(cellids_range.first != cellids_range.second);
556
557 vtkIdType numPoints;
558 const auto pointMap =
559 ::GeneratePointMap(input, cellids_range.first, cellids_range.second, numPoints);
560 auto chosenPtIds = ::ConvertToPointIdsToExtract(pointMap, numPoints);
561 this->UpdateProgress(0.25);
562
563 const SubsetCellsWork work{ cellids_range.first, cellids_range.second, pointMap, numCells };
564
565 // Copy cell and point data first, since that's easy enough.
566 ::CopyCellData(inCD, outCD, work);
567 ::AddOriginalCellIds(outCD, work);
568 ::CopyPointData(inPD, outPD, chosenPtIds);
569 this->UpdateProgress(0.5);
570
571 // Get new points
572 auto pts = ::DoExtractPoints(input, SubsetPointsWork{ chosenPtIds });
573 output->SetPoints(pts);
574 this->UpdateProgress(0.75);
575
576 // Extract cells
577 auto cells = ::DoExtractCells(input, work);
578 this->UpdateProgress(0.85);
579
580 // Handle polyhedral cells
581 auto inputUG = vtkUnstructuredGrid::SafeDownCast(input);
582 if (inputUG && inputUG->GetFaces() && inputUG->GetFaceLocations() &&
583 inputUG->GetFaceLocations()->GetRange(0)[1] != -1)
584 {
585 ::DoExtractPolyhedralFaces(cells, inputUG, work);
586 }
587 output->SetCells(cells.CellTypes, cells.Connectivity, cells.FaceLocations, cells.Faces);
588 return 1;
589 }
590
591 //------------------------------------------------------------------------------
Copy(vtkDataSet * input,vtkUnstructuredGrid * output)592 bool vtkExtractCells::Copy(vtkDataSet* input, vtkUnstructuredGrid* output)
593 {
594 if (vtkUnstructuredGrid::SafeDownCast(input))
595 {
596 output->ShallowCopy(input);
597 return true;
598 }
599
600 if (vtkPointSet::SafeDownCast(input))
601 {
602 // pass points along.
603 output->vtkPointSet::ShallowCopy(input);
604 }
605 else
606 {
607 // copy points manually.
608 const vtkIdType numPoints = input->GetNumberOfPoints();
609 auto pts = ::DoExtractPoints(input, AllElementsWork{ numPoints, 0 });
610 output->SetPoints(pts);
611 }
612
613 const auto numCells = input->GetNumberOfCells();
614 auto cells = ::DoExtractCells(input, AllElementsWork{ 0, numCells });
615 output->SetCells(cells.CellTypes, cells.Connectivity, nullptr, nullptr);
616
617 // copy cell/point arrays.
618 output->GetPointData()->ShallowCopy(input->GetPointData());
619 output->GetCellData()->ShallowCopy(input->GetCellData());
620 ::AddOriginalCellIds(output->GetCellData(), AllElementsWork{ 0, numCells });
621 return true;
622 }
623
624 //------------------------------------------------------------------------------
FillInputPortInformation(int,vtkInformation * info)625 int vtkExtractCells::FillInputPortInformation(int, vtkInformation* info)
626 {
627 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
628 return 1;
629 }
630
631 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)632 void vtkExtractCells::PrintSelf(ostream& os, vtkIndent indent)
633 {
634 this->Superclass::PrintSelf(os, indent);
635 os << indent << "ExtractAllCells: " << this->ExtractAllCells << endl;
636 os << indent << "AssumeSortedAndUniqueIds: " << this->AssumeSortedAndUniqueIds << endl;
637 }
638