1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkUnstructuredGrid.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 // Hide VTK_DEPRECATED_IN_9_0_0() warnings for this class.
17 #define VTK_DEPRECATION_LEVEL 0
18
19 #include "vtkUnstructuredGrid.h"
20
21 #include "vtkArrayDispatch.h"
22 #include "vtkBezierCurve.h"
23 #include "vtkBezierHexahedron.h"
24 #include "vtkBezierQuadrilateral.h"
25 #include "vtkBezierTetra.h"
26 #include "vtkBezierTriangle.h"
27 #include "vtkBezierWedge.h"
28 #include "vtkBiQuadraticQuad.h"
29 #include "vtkBiQuadraticQuadraticHexahedron.h"
30 #include "vtkBiQuadraticQuadraticWedge.h"
31 #include "vtkBiQuadraticTriangle.h"
32 #include "vtkCellArray.h"
33 #include "vtkCellArrayIterator.h"
34 #include "vtkCellData.h"
35 #include "vtkCellLinks.h"
36 #include "vtkCellTypes.h"
37 #include "vtkConvexPointSet.h"
38 #include "vtkCubicLine.h"
39 #include "vtkDataArrayRange.h"
40 #include "vtkDoubleArray.h"
41 #include "vtkEmptyCell.h"
42 #include "vtkGenericCell.h"
43 #include "vtkHexagonalPrism.h"
44 #include "vtkHexahedron.h"
45 #include "vtkInformation.h"
46 #include "vtkInformationVector.h"
47 #include "vtkLagrangeCurve.h"
48 #include "vtkLagrangeHexahedron.h"
49 #include "vtkLagrangeQuadrilateral.h"
50 #include "vtkLagrangeTetra.h"
51 #include "vtkLagrangeTriangle.h"
52 #include "vtkLagrangeWedge.h"
53 #include "vtkLine.h"
54 #include "vtkNew.h"
55 #include "vtkObjectFactory.h"
56 #include "vtkPentagonalPrism.h"
57 #include "vtkPixel.h"
58 #include "vtkPointData.h"
59 #include "vtkPolyLine.h"
60 #include "vtkPolyVertex.h"
61 #include "vtkPolygon.h"
62 #include "vtkPolyhedron.h"
63 #include "vtkPyramid.h"
64 #include "vtkQuad.h"
65 #include "vtkQuadraticEdge.h"
66 #include "vtkQuadraticHexahedron.h"
67 #include "vtkQuadraticLinearQuad.h"
68 #include "vtkQuadraticLinearWedge.h"
69 #include "vtkQuadraticPolygon.h"
70 #include "vtkQuadraticPyramid.h"
71 #include "vtkQuadraticQuad.h"
72 #include "vtkQuadraticTetra.h"
73 #include "vtkQuadraticTriangle.h"
74 #include "vtkQuadraticWedge.h"
75 #include "vtkSMPTools.h"
76 #include "vtkStaticCellLinks.h"
77 #include "vtkTetra.h"
78 #include "vtkTriQuadraticHexahedron.h"
79 #include "vtkTriQuadraticPyramid.h"
80 #include "vtkTriangle.h"
81 #include "vtkTriangleStrip.h"
82 #include "vtkUnsignedCharArray.h"
83 #include "vtkUnstructuredGridCellIterator.h"
84 #include "vtkVertex.h"
85 #include "vtkVoxel.h"
86 #include "vtkWedge.h"
87
88 #include <algorithm>
89 #include <set>
90
91 vtkStandardNewMacro(vtkUnstructuredGrid);
92 vtkStandardExtendedNewMacro(vtkUnstructuredGrid);
93
94 //------------------------------------------------------------------------------
GetCellLocationsArray()95 vtkIdTypeArray* vtkUnstructuredGrid::GetCellLocationsArray()
96 {
97 if (!this->CellLocations)
98 {
99 this->CellLocations = vtkSmartPointer<vtkIdTypeArray>::New();
100 }
101 this->CellLocations->DeepCopy(this->Connectivity->GetOffsetsArray());
102 this->CellLocations->SetNumberOfValues(this->GetNumberOfCells());
103
104 return this->CellLocations;
105 }
106
107 //------------------------------------------------------------------------------
SetCells(vtkUnsignedCharArray * cellTypes,vtkIdTypeArray *,vtkCellArray * cells)108 void vtkUnstructuredGrid::SetCells(
109 vtkUnsignedCharArray* cellTypes, vtkIdTypeArray*, vtkCellArray* cells)
110 {
111 this->SetCells(cellTypes, cells);
112 }
113
114 //------------------------------------------------------------------------------
SetCells(vtkUnsignedCharArray * cellTypes,vtkIdTypeArray *,vtkCellArray * cells,vtkIdTypeArray * faceLocations,vtkIdTypeArray * faces)115 void vtkUnstructuredGrid::SetCells(vtkUnsignedCharArray* cellTypes, vtkIdTypeArray*,
116 vtkCellArray* cells, vtkIdTypeArray* faceLocations, vtkIdTypeArray* faces)
117 {
118 this->SetCells(cellTypes, cells, faceLocations, faces);
119 }
120
121 //------------------------------------------------------------------------------
vtkUnstructuredGrid()122 vtkUnstructuredGrid::vtkUnstructuredGrid()
123 {
124 this->Vertex = nullptr;
125 this->PolyVertex = nullptr;
126 this->BezierCurve = nullptr;
127 this->BezierQuadrilateral = nullptr;
128 this->BezierHexahedron = nullptr;
129 this->BezierTriangle = nullptr;
130 this->BezierTetra = nullptr;
131 this->BezierWedge = nullptr;
132 this->LagrangeCurve = nullptr;
133 this->LagrangeQuadrilateral = nullptr;
134 this->LagrangeHexahedron = nullptr;
135 this->LagrangeTriangle = nullptr;
136 this->LagrangeTetra = nullptr;
137 this->LagrangeWedge = nullptr;
138 this->Line = nullptr;
139 this->PolyLine = nullptr;
140 this->Triangle = nullptr;
141 this->TriangleStrip = nullptr;
142 this->Pixel = nullptr;
143 this->Quad = nullptr;
144 this->Polygon = nullptr;
145 this->Tetra = nullptr;
146 this->Voxel = nullptr;
147 this->Hexahedron = nullptr;
148 this->Wedge = nullptr;
149 this->Pyramid = nullptr;
150 this->PentagonalPrism = nullptr;
151 this->HexagonalPrism = nullptr;
152 this->QuadraticEdge = nullptr;
153 this->QuadraticTriangle = nullptr;
154 this->QuadraticQuad = nullptr;
155 this->QuadraticPolygon = nullptr;
156 this->QuadraticTetra = nullptr;
157 this->QuadraticHexahedron = nullptr;
158 this->QuadraticWedge = nullptr;
159 this->QuadraticPyramid = nullptr;
160 this->QuadraticLinearQuad = nullptr;
161 this->BiQuadraticQuad = nullptr;
162 this->TriQuadraticHexahedron = nullptr;
163 this->TriQuadraticPyramid = nullptr;
164 this->QuadraticLinearWedge = nullptr;
165 this->BiQuadraticQuadraticWedge = nullptr;
166 this->BiQuadraticQuadraticHexahedron = nullptr;
167 this->BiQuadraticTriangle = nullptr;
168 this->CubicLine = nullptr;
169
170 this->ConvexPointSet = nullptr;
171 this->Polyhedron = nullptr;
172 this->EmptyCell = nullptr;
173
174 this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_PIECES_EXTENT);
175 this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1);
176 this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 1);
177 this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0);
178
179 this->DistinctCellTypesUpdateMTime = 0;
180
181 this->AllocateExact(1024, 1024);
182 }
183
184 //------------------------------------------------------------------------------
~vtkUnstructuredGrid()185 vtkUnstructuredGrid::~vtkUnstructuredGrid()
186 {
187 if (this->Vertex)
188 {
189 this->Vertex->Delete();
190 }
191 if (this->PolyVertex)
192 {
193 this->PolyVertex->Delete();
194 }
195 if (this->BezierCurve)
196 {
197 this->BezierCurve->Delete();
198 }
199 if (this->BezierQuadrilateral)
200 {
201 this->BezierQuadrilateral->Delete();
202 }
203 if (this->BezierHexahedron)
204 {
205 this->BezierHexahedron->Delete();
206 }
207 if (this->BezierTriangle)
208 {
209 this->BezierTriangle->Delete();
210 }
211 if (this->BezierTetra)
212 {
213 this->BezierTetra->Delete();
214 }
215 if (this->BezierWedge)
216 {
217 this->BezierWedge->Delete();
218 }
219 if (this->LagrangeCurve)
220 {
221 this->LagrangeCurve->Delete();
222 }
223 if (this->LagrangeQuadrilateral)
224 {
225 this->LagrangeQuadrilateral->Delete();
226 }
227 if (this->LagrangeHexahedron)
228 {
229 this->LagrangeHexahedron->Delete();
230 }
231 if (this->LagrangeTriangle)
232 {
233 this->LagrangeTriangle->Delete();
234 }
235 if (this->LagrangeTetra)
236 {
237 this->LagrangeTetra->Delete();
238 }
239 if (this->LagrangeWedge)
240 {
241 this->LagrangeWedge->Delete();
242 }
243 if (this->Line)
244 {
245 this->Line->Delete();
246 }
247 if (this->PolyLine)
248 {
249 this->PolyLine->Delete();
250 }
251 if (this->Triangle)
252 {
253 this->Triangle->Delete();
254 }
255 if (this->TriangleStrip)
256 {
257 this->TriangleStrip->Delete();
258 }
259 if (this->Pixel)
260 {
261 this->Pixel->Delete();
262 }
263 if (this->Quad)
264 {
265 this->Quad->Delete();
266 }
267 if (this->Polygon)
268 {
269 this->Polygon->Delete();
270 }
271 if (this->Tetra)
272 {
273 this->Tetra->Delete();
274 }
275 if (this->Voxel)
276 {
277 this->Voxel->Delete();
278 }
279 if (this->Hexahedron)
280 {
281 this->Hexahedron->Delete();
282 }
283 if (this->Wedge)
284 {
285 this->Wedge->Delete();
286 }
287 if (this->Pyramid)
288 {
289 this->Pyramid->Delete();
290 }
291 if (this->PentagonalPrism)
292 {
293 this->PentagonalPrism->Delete();
294 }
295 if (this->HexagonalPrism)
296 {
297 this->HexagonalPrism->Delete();
298 }
299 if (this->QuadraticEdge)
300 {
301 this->QuadraticEdge->Delete();
302 }
303 if (this->QuadraticTriangle)
304 {
305 this->QuadraticTriangle->Delete();
306 }
307 if (this->QuadraticQuad)
308 {
309 this->QuadraticQuad->Delete();
310 }
311 if (this->QuadraticPolygon)
312 {
313 this->QuadraticPolygon->Delete();
314 }
315 if (this->QuadraticTetra)
316 {
317 this->QuadraticTetra->Delete();
318 }
319 if (this->QuadraticHexahedron)
320 {
321 this->QuadraticHexahedron->Delete();
322 }
323 if (this->QuadraticWedge)
324 {
325 this->QuadraticWedge->Delete();
326 }
327 if (this->QuadraticPyramid)
328 {
329 this->QuadraticPyramid->Delete();
330 }
331 if (this->QuadraticLinearQuad)
332 {
333 this->QuadraticLinearQuad->Delete();
334 }
335 if (this->BiQuadraticQuad)
336 {
337 this->BiQuadraticQuad->Delete();
338 }
339 if (this->TriQuadraticHexahedron)
340 {
341 this->TriQuadraticHexahedron->Delete();
342 }
343 if (this->TriQuadraticPyramid)
344 {
345 this->TriQuadraticPyramid->Delete();
346 }
347 if (this->QuadraticLinearWedge)
348 {
349 this->QuadraticLinearWedge->Delete();
350 }
351 if (this->BiQuadraticQuadraticWedge)
352 {
353 this->BiQuadraticQuadraticWedge->Delete();
354 }
355 if (this->BiQuadraticQuadraticHexahedron)
356 {
357 this->BiQuadraticQuadraticHexahedron->Delete();
358 }
359 if (this->BiQuadraticTriangle)
360 {
361 this->BiQuadraticTriangle->Delete();
362 }
363 if (this->CubicLine)
364 {
365 this->CubicLine->Delete();
366 }
367
368 if (this->ConvexPointSet)
369 {
370 this->ConvexPointSet->Delete();
371 }
372 if (this->Polyhedron)
373 {
374 this->Polyhedron->Delete();
375 }
376 if (this->EmptyCell)
377 {
378 this->EmptyCell->Delete();
379 }
380 }
381
382 //------------------------------------------------------------------------------
GetPiece()383 int vtkUnstructuredGrid::GetPiece()
384 {
385 return this->Information->Get(vtkDataObject::DATA_PIECE_NUMBER());
386 }
387
388 //------------------------------------------------------------------------------
GetNumberOfPieces()389 int vtkUnstructuredGrid::GetNumberOfPieces()
390 {
391 return this->Information->Get(vtkDataObject::DATA_NUMBER_OF_PIECES());
392 }
393
394 //------------------------------------------------------------------------------
GetGhostLevel()395 int vtkUnstructuredGrid::GetGhostLevel()
396 {
397 return this->Information->Get(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS());
398 }
399
400 //------------------------------------------------------------------------------
401 // Copy the geometric and topological structure of an input unstructured grid.
CopyStructure(vtkDataSet * ds)402 void vtkUnstructuredGrid::CopyStructure(vtkDataSet* ds)
403 {
404 // If ds is a vtkUnstructuredGrid, do a shallow copy of the cell data.
405 if (vtkUnstructuredGrid* ug = vtkUnstructuredGrid::SafeDownCast(ds))
406 {
407 this->Connectivity = ug->Connectivity;
408 this->Links = ug->Links;
409 this->Types = ug->Types;
410 this->DistinctCellTypes = nullptr;
411 this->DistinctCellTypesUpdateMTime = 0;
412 this->Faces = ug->Faces;
413 this->FaceLocations = ug->FaceLocations;
414 }
415
416 this->Superclass::CopyStructure(ds);
417 }
418
419 //------------------------------------------------------------------------------
Cleanup()420 void vtkUnstructuredGrid::Cleanup()
421 {
422 this->Connectivity = nullptr;
423 this->Links = nullptr;
424 this->Types = nullptr;
425 this->DistinctCellTypes = nullptr;
426 this->DistinctCellTypesUpdateMTime = 0;
427 this->Faces = nullptr;
428 this->FaceLocations = nullptr;
429 }
430
431 //------------------------------------------------------------------------------
Initialize()432 void vtkUnstructuredGrid::Initialize()
433 {
434 vtkPointSet::Initialize();
435
436 this->Cleanup();
437
438 if (this->Information)
439 {
440 this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1);
441 this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 0);
442 this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0);
443 }
444 }
445
446 //------------------------------------------------------------------------------
GetCellType(vtkIdType cellId)447 int vtkUnstructuredGrid::GetCellType(vtkIdType cellId)
448 {
449 vtkDebugMacro(<< "Returning cell type " << static_cast<int>(this->Types->GetValue(cellId)));
450 return static_cast<int>(this->Types->GetValue(cellId));
451 }
452
453 //------------------------------------------------------------------------------
GetCell(vtkIdType cellId)454 vtkCell* vtkUnstructuredGrid::GetCell(vtkIdType cellId)
455 {
456 vtkIdType numPts;
457 const vtkIdType* pts;
458 this->Connectivity->GetCellAtId(cellId, numPts, pts);
459
460 vtkCell* cell = nullptr;
461 switch (this->Types->GetValue(cellId))
462 {
463 case VTK_VERTEX:
464 if (!this->Vertex)
465 {
466 this->Vertex = vtkVertex::New();
467 }
468 cell = this->Vertex;
469 break;
470
471 case VTK_POLY_VERTEX:
472 if (!this->PolyVertex)
473 {
474 this->PolyVertex = vtkPolyVertex::New();
475 }
476 cell = this->PolyVertex;
477 break;
478
479 case VTK_LINE:
480 if (!this->Line)
481 {
482 this->Line = vtkLine::New();
483 }
484 cell = this->Line;
485 break;
486
487 case VTK_LAGRANGE_CURVE:
488 if (!this->LagrangeCurve)
489 {
490 this->LagrangeCurve = vtkLagrangeCurve::New();
491 }
492 cell = this->LagrangeCurve;
493 break;
494
495 case VTK_LAGRANGE_QUADRILATERAL:
496 {
497 if (!this->LagrangeQuadrilateral)
498 {
499 this->LagrangeQuadrilateral = vtkLagrangeQuadrilateral::New();
500 }
501 vtkDataArray* v = GetCellData()->GetHigherOrderDegrees();
502 if (v)
503 {
504 double degs[3];
505 v->GetTuple(cellId, degs);
506 this->LagrangeQuadrilateral->SetOrder(degs[0], degs[1]);
507 }
508 else
509 {
510 this->LagrangeQuadrilateral->SetUniformOrderFromNumPoints(numPts);
511 }
512 cell = this->LagrangeQuadrilateral;
513 break;
514 }
515
516 case VTK_LAGRANGE_HEXAHEDRON:
517 {
518 if (!this->LagrangeHexahedron)
519 {
520 this->LagrangeHexahedron = vtkLagrangeHexahedron::New();
521 }
522 vtkDataArray* v = GetCellData()->GetHigherOrderDegrees();
523 if (v)
524 {
525 double degs[3];
526 v->GetTuple(cellId, degs);
527 this->LagrangeHexahedron->SetOrder(degs[0], degs[1], degs[2]);
528 }
529 else
530 {
531 this->LagrangeHexahedron->SetUniformOrderFromNumPoints(numPts);
532 }
533 cell = this->LagrangeHexahedron;
534 break;
535 }
536
537 case VTK_LAGRANGE_TRIANGLE:
538 if (!this->LagrangeTriangle)
539 {
540 this->LagrangeTriangle = vtkLagrangeTriangle::New();
541 }
542 cell = this->LagrangeTriangle;
543 break;
544
545 case VTK_LAGRANGE_TETRAHEDRON:
546 if (!this->LagrangeTetra)
547 {
548 this->LagrangeTetra = vtkLagrangeTetra::New();
549 }
550 cell = this->LagrangeTetra;
551 break;
552
553 case VTK_LAGRANGE_WEDGE:
554 {
555 if (!this->LagrangeWedge)
556 {
557 this->LagrangeWedge = vtkLagrangeWedge::New();
558 }
559 vtkDataArray* v = GetCellData()->GetHigherOrderDegrees();
560 if (v)
561 {
562 double degs[3];
563 v->GetTuple(cellId, degs);
564 this->LagrangeWedge->SetOrder(degs[0], degs[1], degs[2], numPts);
565 }
566 else
567 {
568 this->LagrangeWedge->SetUniformOrderFromNumPoints(numPts);
569 }
570 cell = this->LagrangeWedge;
571 break;
572 }
573
574 case VTK_BEZIER_CURVE:
575 {
576 if (!this->BezierCurve)
577 {
578 this->BezierCurve = vtkBezierCurve::New();
579 }
580 vtkDataArray* wts = GetPointData()->GetRationalWeights();
581 if (wts)
582 {
583 this->BezierCurve->GetRationalWeights()->SetNumberOfTuples(numPts);
584 for (int i = 0; i < numPts; i++)
585 {
586 this->BezierCurve->GetRationalWeights()->SetValue(i, wts->GetTuple1(pts[i]));
587 }
588 }
589 else
590 this->BezierCurve->GetRationalWeights()->Reset();
591 cell = this->BezierCurve;
592 break;
593 }
594
595 case VTK_BEZIER_QUADRILATERAL:
596 {
597 if (!this->BezierQuadrilateral)
598 {
599 this->BezierQuadrilateral = vtkBezierQuadrilateral::New();
600 }
601 vtkDataArray* v = GetCellData()->GetHigherOrderDegrees();
602 if (v)
603 {
604 double degs[3];
605 v->GetTuple(cellId, degs);
606 this->BezierQuadrilateral->SetOrder(degs[0], degs[1]);
607 }
608 else
609 {
610 this->BezierQuadrilateral->SetUniformOrderFromNumPoints(numPts);
611 }
612 vtkDataArray* wts = GetPointData()->GetRationalWeights();
613 if (wts)
614 {
615 this->BezierQuadrilateral->GetRationalWeights()->SetNumberOfTuples(numPts);
616 for (int i = 0; i < numPts; i++)
617 {
618 this->BezierQuadrilateral->GetRationalWeights()->SetValue(i, wts->GetTuple1(pts[i]));
619 }
620 }
621 else
622 this->BezierQuadrilateral->GetRationalWeights()->Reset();
623 cell = this->BezierQuadrilateral;
624 break;
625 }
626
627 case VTK_BEZIER_HEXAHEDRON:
628 {
629 if (!this->BezierHexahedron)
630 {
631 this->BezierHexahedron = vtkBezierHexahedron::New();
632 }
633 vtkDataArray* v = GetCellData()->GetHigherOrderDegrees();
634 if (v)
635 {
636 double degs[3];
637 v->GetTuple(cellId, degs);
638 this->BezierHexahedron->SetOrder(degs[0], degs[1], degs[2]);
639 }
640 else
641 {
642 this->BezierHexahedron->SetUniformOrderFromNumPoints(numPts);
643 }
644 vtkDataArray* wts = GetPointData()->GetRationalWeights();
645 if (wts)
646 {
647 this->BezierHexahedron->GetRationalWeights()->SetNumberOfTuples(numPts);
648 for (int i = 0; i < numPts; i++)
649 {
650 this->BezierHexahedron->GetRationalWeights()->SetValue(i, wts->GetTuple1(pts[i]));
651 }
652 }
653 else
654 this->BezierHexahedron->GetRationalWeights()->Reset();
655 cell = this->BezierHexahedron;
656 break;
657 }
658
659 case VTK_BEZIER_TRIANGLE:
660 {
661 if (!this->BezierTriangle)
662 {
663 this->BezierTriangle = vtkBezierTriangle::New();
664 }
665 vtkDataArray* wts = GetPointData()->GetRationalWeights();
666 if (wts)
667 {
668 this->BezierTriangle->GetRationalWeights()->SetNumberOfTuples(numPts);
669 for (int i = 0; i < numPts; i++)
670 {
671 this->BezierTriangle->GetRationalWeights()->SetValue(i, wts->GetTuple1(pts[i]));
672 }
673 }
674 else
675 this->BezierTriangle->GetRationalWeights()->Reset();
676 cell = this->BezierTriangle;
677 break;
678 }
679
680 case VTK_BEZIER_TETRAHEDRON:
681 {
682 if (!this->BezierTetra)
683 {
684 this->BezierTetra = vtkBezierTetra::New();
685 }
686 vtkDataArray* wts = GetPointData()->GetRationalWeights();
687 if (wts)
688 {
689 this->BezierTetra->GetRationalWeights()->SetNumberOfTuples(numPts);
690 for (int i = 0; i < numPts; i++)
691 {
692 this->BezierTetra->GetRationalWeights()->SetValue(i, wts->GetTuple1(pts[i]));
693 }
694 }
695 else
696 this->BezierTetra->GetRationalWeights()->Reset();
697 cell = this->BezierTetra;
698 break;
699 }
700
701 case VTK_BEZIER_WEDGE:
702 {
703 if (!this->BezierWedge)
704 {
705 this->BezierWedge = vtkBezierWedge::New();
706 }
707 vtkDataArray* v = GetCellData()->GetHigherOrderDegrees();
708 if (v)
709 {
710 double degs[3];
711 v->GetTuple(cellId, degs);
712 this->BezierWedge->SetOrder(degs[0], degs[1], degs[2], numPts);
713 }
714 else
715 {
716 this->BezierWedge->SetUniformOrderFromNumPoints(numPts);
717 }
718 vtkDataArray* wts = GetPointData()->GetRationalWeights();
719 if (wts)
720 {
721 this->BezierWedge->GetRationalWeights()->SetNumberOfTuples(numPts);
722 for (int i = 0; i < numPts; i++)
723 {
724 this->BezierWedge->GetRationalWeights()->SetValue(i, wts->GetTuple1(pts[i]));
725 }
726 }
727 else
728 this->BezierWedge->GetRationalWeights()->Reset();
729 cell = this->BezierWedge;
730 break;
731 }
732
733 case VTK_POLY_LINE:
734 if (!this->PolyLine)
735 {
736 this->PolyLine = vtkPolyLine::New();
737 }
738 cell = this->PolyLine;
739 break;
740
741 case VTK_TRIANGLE:
742 if (!this->Triangle)
743 {
744 this->Triangle = vtkTriangle::New();
745 }
746 cell = this->Triangle;
747 break;
748
749 case VTK_TRIANGLE_STRIP:
750 if (!this->TriangleStrip)
751 {
752 this->TriangleStrip = vtkTriangleStrip::New();
753 }
754 cell = this->TriangleStrip;
755 break;
756
757 case VTK_PIXEL:
758 if (!this->Pixel)
759 {
760 this->Pixel = vtkPixel::New();
761 }
762 cell = this->Pixel;
763 break;
764
765 case VTK_QUAD:
766 if (!this->Quad)
767 {
768 this->Quad = vtkQuad::New();
769 }
770 cell = this->Quad;
771 break;
772
773 case VTK_POLYGON:
774 if (!this->Polygon)
775 {
776 this->Polygon = vtkPolygon::New();
777 }
778 cell = this->Polygon;
779 break;
780
781 case VTK_TETRA:
782 if (!this->Tetra)
783 {
784 this->Tetra = vtkTetra::New();
785 }
786 cell = this->Tetra;
787 break;
788
789 case VTK_VOXEL:
790 if (!this->Voxel)
791 {
792 this->Voxel = vtkVoxel::New();
793 }
794 cell = this->Voxel;
795 break;
796
797 case VTK_HEXAHEDRON:
798 if (!this->Hexahedron)
799 {
800 this->Hexahedron = vtkHexahedron::New();
801 }
802 cell = this->Hexahedron;
803 break;
804
805 case VTK_WEDGE:
806 if (!this->Wedge)
807 {
808 this->Wedge = vtkWedge::New();
809 }
810 cell = this->Wedge;
811 break;
812
813 case VTK_PYRAMID:
814 if (!this->Pyramid)
815 {
816 this->Pyramid = vtkPyramid::New();
817 }
818 cell = this->Pyramid;
819 break;
820
821 case VTK_PENTAGONAL_PRISM:
822 if (!this->PentagonalPrism)
823 {
824 this->PentagonalPrism = vtkPentagonalPrism::New();
825 }
826 cell = this->PentagonalPrism;
827 break;
828
829 case VTK_HEXAGONAL_PRISM:
830 if (!this->HexagonalPrism)
831 {
832 this->HexagonalPrism = vtkHexagonalPrism::New();
833 }
834 cell = this->HexagonalPrism;
835 break;
836
837 case VTK_QUADRATIC_EDGE:
838 if (!this->QuadraticEdge)
839 {
840 this->QuadraticEdge = vtkQuadraticEdge::New();
841 }
842 cell = this->QuadraticEdge;
843 break;
844
845 case VTK_QUADRATIC_TRIANGLE:
846 if (!this->QuadraticTriangle)
847 {
848 this->QuadraticTriangle = vtkQuadraticTriangle::New();
849 }
850 cell = this->QuadraticTriangle;
851 break;
852
853 case VTK_QUADRATIC_QUAD:
854 if (!this->QuadraticQuad)
855 {
856 this->QuadraticQuad = vtkQuadraticQuad::New();
857 }
858 cell = this->QuadraticQuad;
859 break;
860
861 case VTK_QUADRATIC_POLYGON:
862 if (!this->QuadraticPolygon)
863 {
864 this->QuadraticPolygon = vtkQuadraticPolygon::New();
865 }
866 cell = this->QuadraticPolygon;
867 break;
868
869 case VTK_QUADRATIC_TETRA:
870 if (!this->QuadraticTetra)
871 {
872 this->QuadraticTetra = vtkQuadraticTetra::New();
873 }
874 cell = this->QuadraticTetra;
875 break;
876
877 case VTK_QUADRATIC_HEXAHEDRON:
878 if (!this->QuadraticHexahedron)
879 {
880 this->QuadraticHexahedron = vtkQuadraticHexahedron::New();
881 }
882 cell = this->QuadraticHexahedron;
883 break;
884
885 case VTK_QUADRATIC_WEDGE:
886 if (!this->QuadraticWedge)
887 {
888 this->QuadraticWedge = vtkQuadraticWedge::New();
889 }
890 cell = this->QuadraticWedge;
891 break;
892
893 case VTK_QUADRATIC_PYRAMID:
894 if (!this->QuadraticPyramid)
895 {
896 this->QuadraticPyramid = vtkQuadraticPyramid::New();
897 }
898 cell = this->QuadraticPyramid;
899 break;
900
901 case VTK_QUADRATIC_LINEAR_QUAD:
902 if (!this->QuadraticLinearQuad)
903 {
904 this->QuadraticLinearQuad = vtkQuadraticLinearQuad::New();
905 }
906 cell = this->QuadraticLinearQuad;
907 break;
908
909 case VTK_BIQUADRATIC_QUAD:
910 if (!this->BiQuadraticQuad)
911 {
912 this->BiQuadraticQuad = vtkBiQuadraticQuad::New();
913 }
914 cell = this->BiQuadraticQuad;
915 break;
916
917 case VTK_TRIQUADRATIC_HEXAHEDRON:
918 if (!this->TriQuadraticHexahedron)
919 {
920 this->TriQuadraticHexahedron = vtkTriQuadraticHexahedron::New();
921 }
922 cell = this->TriQuadraticHexahedron;
923 break;
924
925 case VTK_TRIQUADRATIC_PYRAMID:
926 if (!this->TriQuadraticPyramid)
927 {
928 this->TriQuadraticPyramid = vtkTriQuadraticPyramid::New();
929 }
930 cell = this->TriQuadraticPyramid;
931 break;
932
933 case VTK_QUADRATIC_LINEAR_WEDGE:
934 if (!this->QuadraticLinearWedge)
935 {
936 this->QuadraticLinearWedge = vtkQuadraticLinearWedge::New();
937 }
938 cell = this->QuadraticLinearWedge;
939 break;
940
941 case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
942 if (!this->BiQuadraticQuadraticWedge)
943 {
944 this->BiQuadraticQuadraticWedge = vtkBiQuadraticQuadraticWedge::New();
945 }
946 cell = this->BiQuadraticQuadraticWedge;
947 break;
948
949 case VTK_BIQUADRATIC_QUADRATIC_HEXAHEDRON:
950 if (!this->BiQuadraticQuadraticHexahedron)
951 {
952 this->BiQuadraticQuadraticHexahedron = vtkBiQuadraticQuadraticHexahedron::New();
953 }
954 cell = this->BiQuadraticQuadraticHexahedron;
955 break;
956
957 case VTK_BIQUADRATIC_TRIANGLE:
958 if (!this->BiQuadraticTriangle)
959 {
960 this->BiQuadraticTriangle = vtkBiQuadraticTriangle::New();
961 }
962 cell = this->BiQuadraticTriangle;
963 break;
964
965 case VTK_CUBIC_LINE:
966 if (!this->CubicLine)
967 {
968 this->CubicLine = vtkCubicLine::New();
969 }
970 cell = this->CubicLine;
971 break;
972
973 case VTK_CONVEX_POINT_SET:
974 if (!this->ConvexPointSet)
975 {
976 this->ConvexPointSet = vtkConvexPointSet::New();
977 }
978 cell = this->ConvexPointSet;
979 break;
980
981 case VTK_POLYHEDRON:
982 if (!this->Polyhedron)
983 {
984 this->Polyhedron = vtkPolyhedron::New();
985 }
986 this->Polyhedron->SetFaces(this->GetFaces(cellId));
987 cell = this->Polyhedron;
988 break;
989
990 case VTK_EMPTY_CELL:
991 if (!this->EmptyCell)
992 {
993 this->EmptyCell = vtkEmptyCell::New();
994 }
995 cell = this->EmptyCell;
996 break;
997 }
998
999 if (!cell)
1000 {
1001 return nullptr;
1002 }
1003
1004 // Copy the points over to the cell.
1005 cell->PointIds->SetNumberOfIds(numPts);
1006 cell->Points->SetNumberOfPoints(numPts);
1007 for (vtkIdType i = 0; i < numPts; i++)
1008 {
1009 cell->PointIds->SetId(i, pts[i]);
1010 cell->Points->SetPoint(i, this->Points->GetPoint(pts[i]));
1011 }
1012
1013 // Some cells require special initialization to build data structures
1014 // and such.
1015 if (cell->RequiresInitialization())
1016 {
1017 cell->Initialize();
1018 }
1019
1020 return cell;
1021 }
1022
1023 //------------------------------------------------------------------------------
GetCell(vtkIdType cellId,vtkGenericCell * cell)1024 void vtkUnstructuredGrid::GetCell(vtkIdType cellId, vtkGenericCell* cell)
1025 {
1026
1027 int cellType = static_cast<int>(this->Types->GetValue(cellId));
1028 cell->SetCellType(cellType);
1029
1030 this->Connectivity->GetCellAtId(cellId, cell->PointIds);
1031 this->Points->GetPoints(cell->PointIds, cell->Points);
1032
1033 // Explicit face representation
1034 if (cell->RequiresExplicitFaceRepresentation())
1035 {
1036 cell->SetFaces(this->GetFaces(cellId));
1037 }
1038
1039 // Some cells require special initialization to build data structures
1040 // and such.
1041 if (cell->RequiresInitialization())
1042 {
1043 cell->Initialize();
1044 }
1045 this->SetCellOrderAndRationalWeights(cellId, cell);
1046 }
1047
1048 //------------------------------------------------------------------------------
1049 // Support GetCellBounds()
1050 namespace
1051 { // anonymous
1052 struct ComputeCellBoundsWorker
1053 {
1054 struct Visitor
1055 {
1056 // vtkCellArray::Visit entry point:
1057 template <typename CellStateT, typename PointArrayT>
operator ()__anon5f8c9a0d0111::ComputeCellBoundsWorker::Visitor1058 void operator()(
1059 CellStateT& state, PointArrayT* ptArray, vtkIdType cellId, double bounds[6]) const
1060 {
1061 using IdType = typename CellStateT::ValueType;
1062
1063 const auto ptIds = state.GetCellRange(cellId);
1064 if (ptIds.size() == 0)
1065 {
1066 vtkMath::UninitializeBounds(bounds);
1067 return;
1068 }
1069
1070 const auto points = vtk::DataArrayTupleRange<3>(ptArray);
1071
1072 // Initialize bounds to first point:
1073 {
1074 const auto pt = points[ptIds[0]];
1075
1076 // Explicitly reusing a local will improve performance when virtual
1077 // calls are involved in the iterator read:
1078 const double x = static_cast<double>(pt[0]);
1079 const double y = static_cast<double>(pt[1]);
1080 const double z = static_cast<double>(pt[2]);
1081
1082 bounds[0] = x;
1083 bounds[1] = x;
1084 bounds[2] = y;
1085 bounds[3] = y;
1086 bounds[4] = z;
1087 bounds[5] = z;
1088 }
1089
1090 // Reduce bounds with the rest of the ids:
1091 for (const IdType ptId : ptIds.GetSubRange(1))
1092 {
1093 const auto pt = points[ptId];
1094
1095 // Explicitly reusing a local will improve performance when virtual
1096 // calls are involved in the iterator read:
1097 const double x = static_cast<double>(pt[0]);
1098 const double y = static_cast<double>(pt[1]);
1099 const double z = static_cast<double>(pt[2]);
1100
1101 bounds[0] = std::min(bounds[0], x);
1102 bounds[1] = std::max(bounds[1], x);
1103 bounds[2] = std::min(bounds[2], y);
1104 bounds[3] = std::max(bounds[3], y);
1105 bounds[4] = std::min(bounds[4], z);
1106 bounds[5] = std::max(bounds[5], z);
1107 }
1108 }
1109 };
1110
1111 // vtkArrayDispatch entry point:
1112 template <typename PointArrayT>
operator ()__anon5f8c9a0d0111::ComputeCellBoundsWorker1113 void operator()(
1114 PointArrayT* ptArray, vtkCellArray* conn, vtkIdType cellId, double bounds[6]) const
1115 {
1116 conn->Visit(Visitor{}, ptArray, cellId, bounds);
1117 }
1118 };
1119
1120 } // anonymous
1121
1122 //------------------------------------------------------------------------------
1123 // Faster implementation of GetCellBounds(). Bounds are calculated without
1124 // constructing a cell.
GetCellBounds(vtkIdType cellId,double bounds[6])1125 void vtkUnstructuredGrid::GetCellBounds(vtkIdType cellId, double bounds[6])
1126 {
1127 // Fast path for float/double:
1128 using vtkArrayDispatch::Reals;
1129 using Dispatcher = vtkArrayDispatch::DispatchByValueType<Reals>;
1130 ComputeCellBoundsWorker worker;
1131
1132 vtkDataArray* ptArray = this->Points->GetData();
1133 if (!Dispatcher::Execute(ptArray, worker, this->Connectivity, cellId, bounds))
1134 { // fallback for weird types:
1135 worker(ptArray, this->Connectivity, cellId, bounds);
1136 }
1137 }
1138
1139 //------------------------------------------------------------------------------
1140 // Return the number of points from the cell defined by the maximum number of
1141 // points/
GetMaxCellSize()1142 int vtkUnstructuredGrid::GetMaxCellSize()
1143 {
1144 if (this->Connectivity)
1145 { // The internal implementation is threaded.
1146 return this->Connectivity->GetMaxCellSize();
1147 }
1148 else
1149 {
1150 return 0;
1151 }
1152 }
1153
1154 //------------------------------------------------------------------------------
GetNumberOfCells()1155 vtkIdType vtkUnstructuredGrid::GetNumberOfCells()
1156 {
1157 vtkDebugMacro(<< "NUMBER OF CELLS = "
1158 << (this->Connectivity ? this->Connectivity->GetNumberOfCells() : 0));
1159 return (this->Connectivity ? this->Connectivity->GetNumberOfCells() : 0);
1160 }
1161
1162 //------------------------------------------------------------------------------
1163 // Insert/create cell in object by type and list of point ids defining
1164 // cell topology. Using a special input format, this function also support
1165 // polyhedron cells.
InternalInsertNextCell(int type,vtkIdList * ptIds)1166 vtkIdType vtkUnstructuredGrid::InternalInsertNextCell(int type, vtkIdList* ptIds)
1167 {
1168 if (type == VTK_POLYHEDRON)
1169 {
1170 // For polyhedron cell, input ptIds is of format:
1171 // (numCellFaces, numFace0Pts, id1, id2, id3, numFace1Pts,id1, id2, id3, ...)
1172 vtkIdType* dataPtr = ptIds->GetPointer(0);
1173 return this->InsertNextCell(type, dataPtr[0], dataPtr + 1);
1174 }
1175
1176 this->Connectivity->InsertNextCell(ptIds);
1177
1178 // If faces have been created, we need to pad them (we are not creating
1179 // a polyhedral cell in this method)
1180 if (this->FaceLocations)
1181 {
1182 this->FaceLocations->InsertNextValue(-1);
1183 }
1184
1185 // insert cell type
1186 return this->Types->InsertNextValue(static_cast<unsigned char>(type));
1187 }
1188
1189 //------------------------------------------------------------------------------
1190 // Insert/create cell in object by type and list of point ids defining
1191 // cell topology. Using a special input format, this function also support
1192 // polyhedron cells.
InternalInsertNextCell(int type,vtkIdType npts,const vtkIdType ptIds[])1193 vtkIdType vtkUnstructuredGrid::InternalInsertNextCell(
1194 int type, vtkIdType npts, const vtkIdType ptIds[])
1195 {
1196 if (type != VTK_POLYHEDRON)
1197 {
1198 // insert connectivity
1199 this->Connectivity->InsertNextCell(npts, ptIds);
1200
1201 // If faces have been created, we need to pad them (we are not creating
1202 // a polyhedral cell in this method)
1203 if (this->FaceLocations)
1204 {
1205 this->FaceLocations->InsertNextValue(-1);
1206 }
1207 }
1208 else
1209 {
1210 // For polyhedron, npts is actually number of faces, ptIds is of format:
1211 // (numFace0Pts, id1, id2, id3, numFace1Pts,id1, id2, id3, ...)
1212 vtkIdType realnpts;
1213
1214 // We defer allocation for the faces because they are not commonly used and
1215 // we only want to allocate when necessary.
1216 if (!this->Faces)
1217 {
1218 this->Faces = vtkSmartPointer<vtkIdTypeArray>::New();
1219 this->Faces->Allocate(this->Types->GetSize());
1220 this->FaceLocations = vtkSmartPointer<vtkIdTypeArray>::New();
1221 this->FaceLocations->Allocate(this->Types->GetSize());
1222 // FaceLocations must be padded until the current position
1223 for (vtkIdType i = 0; i <= this->Types->GetMaxId(); i++)
1224 {
1225 this->FaceLocations->InsertNextValue(-1);
1226 }
1227 }
1228
1229 // insert face location
1230 this->FaceLocations->InsertNextValue(this->Faces->GetMaxId() + 1);
1231
1232 // insert cell connectivity and faces stream
1233 vtkUnstructuredGrid::DecomposeAPolyhedronCell(
1234 npts, ptIds, realnpts, this->Connectivity, this->Faces);
1235 }
1236
1237 return this->Types->InsertNextValue(static_cast<unsigned char>(type));
1238 }
1239
1240 //------------------------------------------------------------------------------
1241 // Insert/create cell in object by type and list of point and face ids
1242 // defining cell topology. This method is meant for face-explicit cells (e.g.
1243 // polyhedron).
InternalInsertNextCell(int type,vtkIdType npts,const vtkIdType pts[],vtkIdType nfaces,const vtkIdType faces[])1244 vtkIdType vtkUnstructuredGrid::InternalInsertNextCell(
1245 int type, vtkIdType npts, const vtkIdType pts[], vtkIdType nfaces, const vtkIdType faces[])
1246 {
1247 if (type != VTK_POLYHEDRON)
1248 {
1249 return this->InsertNextCell(type, npts, pts);
1250 }
1251 // Insert connectivity (points that make up polyhedron)
1252 this->Connectivity->InsertNextCell(npts, pts);
1253
1254 // Now insert faces; allocate storage if necessary.
1255 // We defer allocation for the faces because they are not commonly used and
1256 // we only want to allocate when necessary.
1257 if (!this->Faces)
1258 {
1259 this->Faces = vtkSmartPointer<vtkIdTypeArray>::New();
1260 this->Faces->Allocate(this->Types->GetSize());
1261 this->FaceLocations = vtkSmartPointer<vtkIdTypeArray>::New();
1262 this->FaceLocations->Allocate(this->Types->GetSize());
1263 // FaceLocations must be padded until the current position
1264 for (vtkIdType i = 0; i <= this->Types->GetMaxId(); i++)
1265 {
1266 this->FaceLocations->InsertNextValue(-1);
1267 }
1268 }
1269
1270 // Okay the faces go in
1271 this->FaceLocations->InsertNextValue(this->Faces->GetMaxId() + 1);
1272 this->Faces->InsertNextValue(nfaces);
1273
1274 for (int faceNum = 0; faceNum < nfaces; ++faceNum)
1275 {
1276 npts = faces[0];
1277 this->Faces->InsertNextValue(npts);
1278 for (vtkIdType i = 1; i <= npts; ++i)
1279 {
1280 this->Faces->InsertNextValue(faces[i]);
1281 }
1282 faces += npts + 1;
1283 } // for all faces
1284
1285 return this->Types->InsertNextValue(static_cast<unsigned char>(type));
1286 }
1287
1288 //------------------------------------------------------------------------------
InitializeFacesRepresentation(vtkIdType numPrevCells)1289 int vtkUnstructuredGrid::InitializeFacesRepresentation(vtkIdType numPrevCells)
1290 {
1291 if (this->Faces || this->FaceLocations)
1292 {
1293 vtkErrorMacro("Face information already exist for this unstuructured grid. "
1294 "InitializeFacesRepresentation returned without execution.");
1295 return 0;
1296 }
1297
1298 this->Faces = vtkSmartPointer<vtkIdTypeArray>::New();
1299 this->Faces->Allocate(this->Types->GetSize());
1300
1301 this->FaceLocations = vtkSmartPointer<vtkIdTypeArray>::New();
1302 this->FaceLocations->Allocate(this->Types->GetSize());
1303 // FaceLocations must be padded until the current position
1304 for (vtkIdType i = 0; i < numPrevCells; i++)
1305 {
1306 this->FaceLocations->InsertNextValue(-1);
1307 }
1308
1309 return 1;
1310 }
1311
1312 //------------------------------------------------------------------------------
GetMeshMTime()1313 vtkMTimeType vtkUnstructuredGrid::GetMeshMTime()
1314 {
1315 return vtkMath::Max(this->Points ? this->Points->GetMTime() : 0,
1316 this->Connectivity ? this->Connectivity->GetMTime() : 0);
1317 }
1318
1319 //------------------------------------------------------------------------------
1320 // Return faces for a polyhedral cell (or face-explicit cell).
GetFaces(vtkIdType cellId)1321 vtkIdType* vtkUnstructuredGrid::GetFaces(vtkIdType cellId)
1322 {
1323 // Get the locations of the face
1324 vtkIdType loc;
1325 if (!this->Faces || cellId < 0 || cellId > this->FaceLocations->GetMaxId() ||
1326 (loc = this->FaceLocations->GetValue(cellId)) == -1)
1327 {
1328 return nullptr;
1329 }
1330
1331 return this->Faces->GetPointer(loc);
1332 }
1333
1334 //------------------------------------------------------------------------------
GetFaces()1335 vtkIdTypeArray* vtkUnstructuredGrid::GetFaces()
1336 {
1337 return this->Faces;
1338 }
1339
1340 //------------------------------------------------------------------------------
GetFaceLocations()1341 vtkIdTypeArray* vtkUnstructuredGrid::GetFaceLocations()
1342 {
1343 return this->FaceLocations;
1344 }
1345
1346 //------------------------------------------------------------------------------
SetCells(int type,vtkCellArray * cells)1347 void vtkUnstructuredGrid::SetCells(int type, vtkCellArray* cells)
1348 {
1349 vtkNew<vtkUnsignedCharArray> types;
1350 types->SetNumberOfComponents(1);
1351 types->SetNumberOfValues(cells->GetNumberOfCells());
1352 types->FillValue(static_cast<unsigned char>(type));
1353
1354 this->SetCells(types, cells);
1355 }
1356
1357 //------------------------------------------------------------------------------
SetCells(int * types,vtkCellArray * cells)1358 void vtkUnstructuredGrid::SetCells(int* types, vtkCellArray* cells)
1359 {
1360 const vtkIdType ncells = cells->GetNumberOfCells();
1361
1362 // Convert the types into a vtkUnsignedCharArray:
1363 vtkNew<vtkUnsignedCharArray> cellTypes;
1364 cellTypes->SetNumberOfTuples(ncells);
1365 auto typeRange = vtk::DataArrayValueRange<1>(cellTypes);
1366 std::transform(types, types + ncells, typeRange.begin(),
1367 [](int t) -> unsigned char { return static_cast<unsigned char>(t); });
1368
1369 this->SetCells(cellTypes, cells);
1370 }
1371
1372 //------------------------------------------------------------------------------
SetCells(vtkUnsignedCharArray * cellTypes,vtkCellArray * cells)1373 void vtkUnstructuredGrid::SetCells(vtkUnsignedCharArray* cellTypes, vtkCellArray* cells)
1374 {
1375 // check if cells contain any polyhedron cell
1376 const vtkIdType ncells = cells->GetNumberOfCells();
1377 const auto typeRange = vtk::DataArrayValueRange<1>(cellTypes);
1378 const bool containPolyhedron =
1379 std::find(typeRange.cbegin(), typeRange.cend(), VTK_POLYHEDRON) != typeRange.cend();
1380
1381 if (!containPolyhedron)
1382 {
1383 this->SetCells(cellTypes, cells, nullptr, nullptr);
1384 return;
1385 }
1386
1387 // If a polyhedron cell exists, its input cellArray is of special format.
1388 // [nCell0Faces, nFace0Pts, i, j, k, nFace1Pts, i, j, k, ...]
1389 // We need to convert it into new cell connectivities of standard format,
1390 // update cellLocations as well as create faces and facelocations.
1391 vtkNew<vtkCellArray> newCells;
1392 newCells->AllocateExact(ncells, cells->GetNumberOfConnectivityIds());
1393
1394 vtkNew<vtkIdTypeArray> faces;
1395 faces->Allocate(ncells + cells->GetNumberOfConnectivityIds());
1396
1397 vtkNew<vtkIdTypeArray> faceLocations;
1398 faceLocations->Allocate(ncells);
1399
1400 auto cellIter = vtkSmartPointer<vtkCellArrayIterator>::Take(cells->NewIterator());
1401
1402 for (cellIter->GoToFirstCell(); !cellIter->IsDoneWithTraversal(); cellIter->GoToNextCell())
1403 {
1404 vtkIdType npts;
1405 const vtkIdType* pts;
1406 cellIter->GetCurrentCell(npts, pts);
1407 const vtkIdType cellId = cellIter->GetCurrentCellId();
1408
1409 if (cellTypes->GetValue(cellId) != VTK_POLYHEDRON)
1410 {
1411 newCells->InsertNextCell(npts, pts);
1412 faceLocations->InsertNextValue(-1);
1413 }
1414 else
1415 {
1416 vtkIdType realnpts;
1417 vtkIdType nfaces;
1418 faceLocations->InsertNextValue(faces->GetMaxId() + 1);
1419 vtkUnstructuredGrid::DecomposeAPolyhedronCell(pts, realnpts, nfaces, newCells, faces);
1420 }
1421 }
1422
1423 this->SetCells(cellTypes, newCells, faceLocations, faces);
1424 }
1425
1426 //------------------------------------------------------------------------------
SetCells(vtkUnsignedCharArray * cellTypes,vtkCellArray * cells,vtkIdTypeArray * faceLocations,vtkIdTypeArray * faces)1427 void vtkUnstructuredGrid::SetCells(vtkUnsignedCharArray* cellTypes, vtkCellArray* cells,
1428 vtkIdTypeArray* faceLocations, vtkIdTypeArray* faces)
1429 {
1430 this->Connectivity = cells;
1431 this->Types = cellTypes;
1432 this->DistinctCellTypes = nullptr;
1433 this->DistinctCellTypesUpdateMTime = 0;
1434 this->Faces = faces;
1435 this->FaceLocations = faceLocations;
1436 }
1437
1438 //------------------------------------------------------------------------------
BuildLinks()1439 void vtkUnstructuredGrid::BuildLinks()
1440 {
1441 // Create appropriate locator. Currently it's either a vtkCellLocator (when
1442 // the dataset is editable) or vtkStaticCellLocator (when the dataset is
1443 // not editable).
1444 vtkIdType numPts = this->GetNumberOfPoints();
1445 if (!this->Editable)
1446 {
1447 this->Links = vtkSmartPointer<vtkStaticCellLinks>::New();
1448 }
1449 else
1450 {
1451 vtkNew<vtkCellLinks> links;
1452 links->Allocate(numPts);
1453 this->Links = links;
1454 }
1455
1456 this->Links->BuildLinks(this);
1457 }
1458
1459 //------------------------------------------------------------------------------
GetCellLinks()1460 vtkAbstractCellLinks* vtkUnstructuredGrid::GetCellLinks()
1461 {
1462 return this->Links;
1463 }
1464
1465 //------------------------------------------------------------------------------
GetPointCells(vtkIdType ptId,vtkIdType & ncells,vtkIdType * & cells)1466 void vtkUnstructuredGrid::GetPointCells(vtkIdType ptId, vtkIdType& ncells, vtkIdType*& cells)
1467 {
1468 if (!this->Editable)
1469 {
1470 vtkStaticCellLinks* links = static_cast<vtkStaticCellLinks*>(this->Links.Get());
1471
1472 ncells = links->GetNcells(ptId);
1473 cells = links->GetCells(ptId);
1474 }
1475 else
1476 {
1477 vtkCellLinks* links = static_cast<vtkCellLinks*>(this->Links.Get());
1478
1479 ncells = links->GetNcells(ptId);
1480 cells = links->GetCells(ptId);
1481 }
1482 }
1483
1484 //------------------------------------------------------------------------------
GetPointCells(vtkIdType ptId,unsigned short & ncells,vtkIdType * & cells)1485 void vtkUnstructuredGrid::GetPointCells(vtkIdType ptId, unsigned short& ncells, vtkIdType*& cells)
1486 {
1487 VTK_LEGACY_BODY(vtkUnstructuredGrid::GetPointCells, "VTK 9.0");
1488 vtkIdType nc;
1489 this->GetPointCells(ptId, nc, cells);
1490 ncells = static_cast<unsigned short>(nc);
1491 }
1492
1493 //------------------------------------------------------------------------------
GetCellPoints(vtkIdType cellId,vtkIdList * ptIds)1494 void vtkUnstructuredGrid::GetCellPoints(vtkIdType cellId, vtkIdList* ptIds)
1495 {
1496 this->Connectivity->GetCellAtId(cellId, ptIds);
1497 }
1498
1499 namespace
1500 {
1501 class DistinctCellTypesWorker
1502 {
1503 public:
DistinctCellTypesWorker(vtkUnstructuredGrid * grid)1504 DistinctCellTypesWorker(vtkUnstructuredGrid* grid)
1505 : Grid(grid)
1506 {
1507 }
1508
1509 vtkUnstructuredGrid* Grid;
1510 std::set<unsigned char> DistinctCellTypes;
1511
1512 // Thread-local storage
1513 vtkSMPThreadLocal<std::set<unsigned char>> LocalDistinctCellTypes;
1514
Initialize()1515 void Initialize() {}
1516
operator ()(vtkIdType begin,vtkIdType end)1517 void operator()(vtkIdType begin, vtkIdType end)
1518 {
1519 if (!this->Grid)
1520 {
1521 return;
1522 }
1523
1524 for (vtkIdType idx = begin; idx < end; ++idx)
1525 {
1526 unsigned char cellType = static_cast<unsigned char>(this->Grid->GetCellType(idx));
1527 this->LocalDistinctCellTypes.Local().insert(cellType);
1528 }
1529 }
1530
Reduce()1531 void Reduce()
1532 {
1533 this->DistinctCellTypes.clear();
1534 for (vtkSMPThreadLocal<std::set<unsigned char>>::iterator iter =
1535 this->LocalDistinctCellTypes.begin();
1536 iter != this->LocalDistinctCellTypes.end(); ++iter)
1537 {
1538 this->DistinctCellTypes.insert(iter->begin(), iter->end());
1539 }
1540 }
1541 };
1542 }
1543
1544 //------------------------------------------------------------------------------
GetCellTypes(vtkCellTypes * types)1545 void vtkUnstructuredGrid::GetCellTypes(vtkCellTypes* types)
1546 {
1547 if (this->Types == nullptr)
1548 {
1549 // No cell types
1550 return;
1551 }
1552
1553 if (this->DistinctCellTypes == nullptr ||
1554 this->Types->GetMTime() > this->DistinctCellTypesUpdateMTime)
1555 {
1556 // Update the list of cell types
1557 DistinctCellTypesWorker cellTypesWorker(this);
1558 vtkSMPTools::For(0, this->GetNumberOfCells(), cellTypesWorker);
1559
1560 if (this->DistinctCellTypes)
1561 {
1562 this->DistinctCellTypes->Reset();
1563 }
1564 else
1565 {
1566 this->DistinctCellTypes = vtkSmartPointer<vtkCellTypes>::New();
1567 this->DistinctCellTypes->Register(this);
1568 this->DistinctCellTypes->Delete();
1569 }
1570 this->DistinctCellTypes->Allocate(static_cast<int>(cellTypesWorker.DistinctCellTypes.size()));
1571
1572 for (auto cellType : cellTypesWorker.DistinctCellTypes)
1573 {
1574 this->DistinctCellTypes->InsertNextType(cellType);
1575 }
1576
1577 this->DistinctCellTypesUpdateMTime = this->Types->GetMTime();
1578 }
1579
1580 types->DeepCopy(this->DistinctCellTypes);
1581 }
1582
1583 //------------------------------------------------------------------------------
GetCellTypesArray()1584 vtkUnsignedCharArray* vtkUnstructuredGrid::GetCellTypesArray()
1585 {
1586 return this->Types;
1587 }
1588
1589 //------------------------------------------------------------------------------
GetFaceStream(vtkIdType cellId,vtkIdList * ptIds)1590 void vtkUnstructuredGrid::GetFaceStream(vtkIdType cellId, vtkIdList* ptIds)
1591 {
1592 if (this->GetCellType(cellId) != VTK_POLYHEDRON)
1593 {
1594 this->GetCellPoints(cellId, ptIds);
1595 return;
1596 }
1597
1598 ptIds->Reset();
1599
1600 if (!this->Faces || !this->FaceLocations)
1601 {
1602 return;
1603 }
1604
1605 vtkIdType loc = this->FaceLocations->GetValue(cellId);
1606 vtkIdType* facePtr = this->Faces->GetPointer(loc);
1607
1608 vtkIdType nfaces = *facePtr++;
1609 ptIds->InsertNextId(nfaces);
1610 for (vtkIdType i = 0; i < nfaces; i++)
1611 {
1612 vtkIdType npts = *facePtr++;
1613 ptIds->InsertNextId(npts);
1614 for (vtkIdType j = 0; j < npts; j++)
1615 {
1616 ptIds->InsertNextId(*facePtr++);
1617 }
1618 }
1619 }
1620
1621 //------------------------------------------------------------------------------
GetFaceStream(vtkIdType cellId,vtkIdType & nfaces,vtkIdType const * & ptIds)1622 void vtkUnstructuredGrid::GetFaceStream(
1623 vtkIdType cellId, vtkIdType& nfaces, vtkIdType const*& ptIds)
1624 {
1625 if (this->GetCellType(cellId) != VTK_POLYHEDRON)
1626 {
1627 this->GetCellPoints(cellId, nfaces, ptIds);
1628 return;
1629 }
1630
1631 if (!this->Faces || !this->FaceLocations)
1632 {
1633 return;
1634 }
1635
1636 vtkIdType loc = this->FaceLocations->GetValue(cellId);
1637 const vtkIdType* facePtr = this->Faces->GetPointer(loc);
1638
1639 nfaces = *facePtr;
1640 ptIds = facePtr + 1;
1641 }
1642
1643 //------------------------------------------------------------------------------
GetPointCells(vtkIdType ptId,vtkIdList * cellIds)1644 void vtkUnstructuredGrid::GetPointCells(vtkIdType ptId, vtkIdList* cellIds)
1645 {
1646 if (!this->Links)
1647 {
1648 this->BuildLinks();
1649 }
1650 cellIds->Reset();
1651
1652 vtkIdType numCells, *cells;
1653 if (!this->Editable)
1654 {
1655 vtkStaticCellLinks* links = static_cast<vtkStaticCellLinks*>(this->Links.Get());
1656 numCells = links->GetNcells(ptId);
1657 cells = links->GetCells(ptId);
1658 }
1659 else
1660 {
1661 vtkCellLinks* links = static_cast<vtkCellLinks*>(this->Links.Get());
1662 numCells = links->GetNcells(ptId);
1663 cells = links->GetCells(ptId);
1664 }
1665
1666 cellIds->SetNumberOfIds(numCells);
1667 for (auto i = 0; i < numCells; i++)
1668 {
1669 cellIds->SetId(i, cells[i]);
1670 }
1671 }
1672
1673 //------------------------------------------------------------------------------
NewCellIterator()1674 vtkCellIterator* vtkUnstructuredGrid::NewCellIterator()
1675 {
1676 vtkUnstructuredGridCellIterator* iter(vtkUnstructuredGridCellIterator::New());
1677 iter->SetUnstructuredGrid(this);
1678 return iter;
1679 }
1680
1681 //------------------------------------------------------------------------------
Reset()1682 void vtkUnstructuredGrid::Reset()
1683 {
1684 if (this->Connectivity)
1685 {
1686 this->Connectivity->Reset();
1687 }
1688 if (this->Links)
1689 {
1690 this->Links->Reset();
1691 }
1692 if (this->Types)
1693 {
1694 this->Types->Reset();
1695 }
1696 if (this->DistinctCellTypes)
1697 {
1698 this->DistinctCellTypes->Reset();
1699 }
1700 if (this->Faces)
1701 {
1702 this->Faces->Reset();
1703 }
1704 if (this->FaceLocations)
1705 {
1706 this->FaceLocations->Reset();
1707 }
1708 }
1709
1710 //------------------------------------------------------------------------------
Squeeze()1711 void vtkUnstructuredGrid::Squeeze()
1712 {
1713 if (this->Connectivity)
1714 {
1715 this->Connectivity->Squeeze();
1716 }
1717 if (this->Links)
1718 {
1719 this->Links->Squeeze();
1720 }
1721 if (this->Types)
1722 {
1723 this->Types->Squeeze();
1724 }
1725 if (this->Faces)
1726 {
1727 this->Faces->Squeeze();
1728 }
1729 if (this->FaceLocations)
1730 {
1731 this->FaceLocations->Squeeze();
1732 }
1733
1734 vtkPointSet::Squeeze();
1735 }
1736
1737 //------------------------------------------------------------------------------
1738 // Remove a reference to a cell in a particular point's link list. You may
1739 // also consider using RemoveCellReference() to remove the references from
1740 // all the cell's points to the cell. This operator does not reallocate
1741 // memory; use the operator ResizeCellList() to do this if necessary. Note that
1742 // dataset should be set to "Editable".
RemoveReferenceToCell(vtkIdType ptId,vtkIdType cellId)1743 void vtkUnstructuredGrid::RemoveReferenceToCell(vtkIdType ptId, vtkIdType cellId)
1744 {
1745 static_cast<vtkCellLinks*>(this->Links.Get())->RemoveCellReference(cellId, ptId);
1746 }
1747
1748 //------------------------------------------------------------------------------
1749 // Add a reference to a cell in a particular point's link list. (You may also
1750 // consider using AddCellReference() to add the references from all the
1751 // cell's points to the cell.) This operator does not realloc memory; use the
1752 // operator ResizeCellList() to do this if necessary. Note that dataset
1753 // should be set to "Editable".
AddReferenceToCell(vtkIdType ptId,vtkIdType cellId)1754 void vtkUnstructuredGrid::AddReferenceToCell(vtkIdType ptId, vtkIdType cellId)
1755 {
1756 static_cast<vtkCellLinks*>(this->Links.Get())->AddCellReference(cellId, ptId);
1757 }
1758
1759 //------------------------------------------------------------------------------
1760 // Resize the list of cells using a particular point. (This operator assumes
1761 // that BuildLinks() has been called.) Note that dataset should be set to
1762 // "Editable".
ResizeCellList(vtkIdType ptId,int size)1763 void vtkUnstructuredGrid::ResizeCellList(vtkIdType ptId, int size)
1764 {
1765 static_cast<vtkCellLinks*>(this->Links.Get())->ResizeCellList(ptId, size);
1766 }
1767
1768 //------------------------------------------------------------------------------
1769 // Replace the points defining cell "cellId" with a new set of points. This
1770 // operator is (typically) used when links from points to cells have not been
1771 // built (i.e., BuildLinks() has not been executed). Use the operator
1772 // ReplaceLinkedCell() to replace a cell when cell structure has been built.
InternalReplaceCell(vtkIdType cellId,int npts,const vtkIdType pts[])1773 void vtkUnstructuredGrid::InternalReplaceCell(vtkIdType cellId, int npts, const vtkIdType pts[])
1774 {
1775 this->Connectivity->ReplaceCellAtId(cellId, npts, pts);
1776 }
1777
1778 //------------------------------------------------------------------------------
1779 // Add a new cell to the cell data structure (after cell links have been
1780 // built). This method adds the cell and then updates the links from the points
1781 // to the cells. (Memory is allocated as necessary.) Note that the dataset must
1782 // be in "Editable" mode.
InsertNextLinkedCell(int type,int npts,const vtkIdType pts[])1783 vtkIdType vtkUnstructuredGrid::InsertNextLinkedCell(int type, int npts, const vtkIdType pts[])
1784 {
1785 vtkIdType i, id;
1786
1787 id = this->InsertNextCell(type, npts, pts);
1788
1789 vtkCellLinks* clinks = static_cast<vtkCellLinks*>(this->Links.Get());
1790 for (i = 0; i < npts; i++)
1791 {
1792 clinks->ResizeCellList(pts[i], 1);
1793 clinks->AddCellReference(id, pts[i]);
1794 }
1795
1796 return id;
1797 }
1798
1799 //------------------------------------------------------------------------------
GetActualMemorySize()1800 unsigned long vtkUnstructuredGrid::GetActualMemorySize()
1801 {
1802 unsigned long size = this->vtkPointSet::GetActualMemorySize();
1803 if (this->Connectivity)
1804 {
1805 size += this->Connectivity->GetActualMemorySize();
1806 }
1807
1808 if (this->Links)
1809 {
1810 size += this->Links->GetActualMemorySize();
1811 }
1812
1813 if (this->Types)
1814 {
1815 size += this->Types->GetActualMemorySize();
1816 }
1817
1818 if (this->Faces)
1819 {
1820 size += this->Faces->GetActualMemorySize();
1821 }
1822
1823 if (this->FaceLocations)
1824 {
1825 size += this->FaceLocations->GetActualMemorySize();
1826 }
1827
1828 return size;
1829 }
1830
1831 //------------------------------------------------------------------------------
ShallowCopy(vtkDataObject * dataObject)1832 void vtkUnstructuredGrid::ShallowCopy(vtkDataObject* dataObject)
1833 {
1834 if (vtkUnstructuredGrid* grid = vtkUnstructuredGrid::SafeDownCast(dataObject))
1835 {
1836 // I do not know if this is correct but.
1837 // ^ I really hope this comment lives for another 20 years.
1838
1839 this->Connectivity = grid->Connectivity;
1840 this->Links = grid->Links;
1841 this->Types = grid->Types;
1842 this->DistinctCellTypes = nullptr;
1843 this->DistinctCellTypesUpdateMTime = 0;
1844 this->Faces = grid->Faces;
1845 this->FaceLocations = grid->FaceLocations;
1846 }
1847 else if (vtkUnstructuredGridBase* ugb = vtkUnstructuredGridBase::SafeDownCast(dataObject))
1848 {
1849 // The source object has vtkUnstructuredGrid topology, but a different
1850 // cell implementation. Deep copy the cells, and shallow copy the rest:
1851 vtkSmartPointer<vtkCellIterator> cellIter =
1852 vtkSmartPointer<vtkCellIterator>::Take(ugb->NewCellIterator());
1853 for (cellIter->InitTraversal(); !cellIter->IsDoneWithTraversal(); cellIter->GoToNextCell())
1854 {
1855 this->InsertNextCell(cellIter->GetCellType(), cellIter->GetNumberOfPoints(),
1856 cellIter->GetPointIds()->GetPointer(0), cellIter->GetNumberOfFaces(),
1857 cellIter->GetFaces()->GetPointer(1));
1858 }
1859 }
1860
1861 this->Superclass::ShallowCopy(dataObject);
1862 }
1863
1864 //------------------------------------------------------------------------------
DeepCopy(vtkDataObject * dataObject)1865 void vtkUnstructuredGrid::DeepCopy(vtkDataObject* dataObject)
1866 {
1867 auto mkhold = vtkMemkindRAII(this->GetIsInMemkind());
1868 vtkUnstructuredGrid* grid = vtkUnstructuredGrid::SafeDownCast(dataObject);
1869
1870 if (grid != nullptr)
1871 {
1872 if (grid->Connectivity)
1873 {
1874 this->Connectivity = vtkSmartPointer<vtkCellArray>::New();
1875 this->Connectivity->DeepCopy(grid->Connectivity);
1876 }
1877 else
1878 {
1879 this->Connectivity = nullptr;
1880 }
1881
1882 if (grid->Types)
1883 {
1884 this->Types = vtkSmartPointer<vtkUnsignedCharArray>::New();
1885 this->Types->DeepCopy(grid->Types);
1886 }
1887 else
1888 {
1889 this->Types = nullptr;
1890 }
1891
1892 if (grid->DistinctCellTypes)
1893 {
1894 this->DistinctCellTypes = vtkSmartPointer<vtkCellTypes>::New();
1895 this->DistinctCellTypes->DeepCopy(grid->DistinctCellTypes);
1896 }
1897 else
1898 {
1899 this->DistinctCellTypes = nullptr;
1900 }
1901
1902 if (grid->Faces)
1903 {
1904 this->Faces = vtkSmartPointer<vtkIdTypeArray>::New();
1905 this->Faces->DeepCopy(grid->Faces);
1906 }
1907 else
1908 {
1909 this->Faces = nullptr;
1910 }
1911
1912 if (grid->FaceLocations)
1913 {
1914 this->FaceLocations = vtkSmartPointer<vtkIdTypeArray>::New();
1915 this->FaceLocations->DeepCopy(grid->FaceLocations);
1916 }
1917 else
1918 {
1919 this->FaceLocations = nullptr;
1920 }
1921
1922 // Skip the unstructured grid base implementation, as it uses a less
1923 // efficient method of copying cell data.
1924 // NOLINTNEXTLINE(bugprone-parent-virtual-call)
1925 this->vtkUnstructuredGridBase::Superclass::DeepCopy(grid);
1926 }
1927 else
1928 {
1929 // Use the vtkUnstructuredGridBase deep copy implementation.
1930 this->Superclass::DeepCopy(dataObject);
1931 }
1932
1933 // Finally Build Links if we need to
1934 if (grid && grid->Links)
1935 {
1936 this->BuildLinks();
1937 }
1938 }
1939
1940 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1941 void vtkUnstructuredGrid::PrintSelf(ostream& os, vtkIndent indent)
1942 {
1943 this->Superclass::PrintSelf(os, indent);
1944
1945 os << indent << "Number Of Pieces: " << this->GetNumberOfPieces() << endl;
1946 os << indent << "Piece: " << this->GetPiece() << endl;
1947 os << indent << "Ghost Level: " << this->GetGhostLevel() << endl;
1948 }
1949
1950 //------------------------------------------------------------------------------
AllocateExact(vtkIdType numCells,vtkIdType connectivitySize)1951 bool vtkUnstructuredGrid::AllocateExact(vtkIdType numCells, vtkIdType connectivitySize)
1952 {
1953 if (numCells < 1)
1954 {
1955 numCells = 1024;
1956 }
1957 if (connectivitySize < 1)
1958 {
1959 connectivitySize = 1024;
1960 }
1961
1962 this->DistinctCellTypesUpdateMTime = 0;
1963 this->DistinctCellTypes = vtkSmartPointer<vtkCellTypes>::New();
1964 this->Types = vtkSmartPointer<vtkUnsignedCharArray>::New();
1965 this->Connectivity = vtkSmartPointer<vtkCellArray>::New();
1966
1967 bool result = this->Connectivity->AllocateExact(numCells, connectivitySize);
1968 if (result)
1969 {
1970 result = this->Types->Allocate(numCells) != 0;
1971 }
1972 if (result)
1973 {
1974 result = this->DistinctCellTypes->Allocate(VTK_NUMBER_OF_CELL_TYPES) != 0;
1975 }
1976
1977 return result;
1978 }
1979
1980 //----------------------------------------------------------------------------
1981 // Supporting implementation functions for IsCellBoundary() and
1982 // GetCellNeighbors(). Basically these methods are an intersection of N sets
1983 // (e.g., each set is a list of cells using each point, the cell links). To
1984 // perform this intersection, the cell links associated with each point are
1985 // combined and then sorted. This will produce contiguous runs, the length
1986 // of which indicates how many times n a cell is represented in the N sets.
1987 // If n == N, then the cell is present in each of the cell links, and if
1988 // the cell != cellId, then this boundary defined by pts[] is an interior
1989 // face.
1990 namespace
1991 { // anonymous
1992
1993 // Determine whether the points provided define a boundary entity (i.e., used
1994 // by only one cell), or whether the points define an interior entity (used
1995 // by more than one cell).
1996 template <class TLinks>
IsCellBoundaryImp(TLinks * links,vtkIdType cellId,vtkIdType npts,const vtkIdType * pts)1997 inline bool IsCellBoundaryImp(TLinks* links, vtkIdType cellId, vtkIdType npts, const vtkIdType* pts)
1998 {
1999 std::vector<vtkIdType> cellSet;
2000 cellSet.reserve(256); // avoid reallocs if possible
2001
2002 // Combine all of the cell lists, and then sort them.
2003 for (auto i = 0; i < npts; ++i)
2004 {
2005 vtkIdType numCells = links->GetNcells(pts[i]);
2006 const vtkIdType* cells = links->GetCells(pts[i]);
2007 cellSet.insert(cellSet.end(), cells, cells + numCells);
2008 }
2009 std::sort(cellSet.begin(), cellSet.end());
2010
2011 // Sorting will have grouped the cells into contiguous runs. Determine the
2012 // length of the runs - if equal to npts, then a cell is present in all
2013 // sets, and if this cell is not the user-provided cellId, then there is a
2014 // cell common to all sets, hence this is not a boundary cell.
2015 auto itr = cellSet.begin();
2016 while (itr != cellSet.end())
2017 {
2018 auto start = itr;
2019 vtkIdType currentCell = *itr;
2020 while (itr != cellSet.end() && *itr == currentCell)
2021 ++itr; // advance across this contiguous run
2022
2023 // What is the size of the contiguous run? If equal to
2024 // the number of sets, then this is an interior boundary.
2025 if (((itr - start) >= npts) && (currentCell != cellId))
2026 {
2027 return false;
2028 }
2029 } // while over the cell set
2030
2031 return true;
2032 }
2033
2034 // Identify the neighbors to the specified cell, where the neighbors
2035 // use all the points in the points list (pts).
2036 template <class TLinks>
GetCellNeighborsImp(TLinks * links,vtkIdType cellId,vtkIdType npts,const vtkIdType * pts,vtkIdList * cellIds)2037 inline void GetCellNeighborsImp(
2038 TLinks* links, vtkIdType cellId, vtkIdType npts, const vtkIdType* pts, vtkIdList* cellIds)
2039 {
2040 std::vector<vtkIdType> cellSet;
2041 cellSet.reserve(256); // avoid reallocs if possible
2042
2043 // Combine all of the cell lists, and then sort them.
2044 for (auto i = 0; i < npts; ++i)
2045 {
2046 vtkIdType numCells = links->GetNcells(pts[i]);
2047 const vtkIdType* cells = links->GetCells(pts[i]);
2048 cellSet.insert(cellSet.end(), cells, cells + numCells);
2049 }
2050 std::sort(cellSet.begin(), cellSet.end());
2051
2052 // Sorting will have grouped the cells into contiguous runs. Determine the
2053 // length of the runs - if equal to npts, then a cell is present in all
2054 // sets, and if this cell is not the user-provided cellId, then this is a
2055 // cell common to all sets, hence it is a neighboring cell.
2056 auto itr = cellSet.begin();
2057 while (itr != cellSet.end())
2058 {
2059 auto start = itr;
2060 vtkIdType currentCell = *itr;
2061 while (itr != cellSet.end() && *itr == currentCell)
2062 ++itr; // advance across this contiguous run
2063
2064 // What is the size of the contiguous run? If equal to
2065 // the number of sets, then this is a neighboring cell.
2066 if (((itr - start) >= npts) && (currentCell != cellId))
2067 {
2068 cellIds->InsertNextId(currentCell);
2069 }
2070 } // while over the cell set
2071 }
2072
2073 } // end anonymous namespace
2074
2075 //----------------------------------------------------------------------------
IsCellBoundary(vtkIdType cellId,vtkIdType npts,const vtkIdType * pts)2076 bool vtkUnstructuredGrid::IsCellBoundary(vtkIdType cellId, vtkIdType npts, const vtkIdType* pts)
2077 {
2078 // Ensure that a valid neighborhood request is made.
2079 if (npts <= 0)
2080 {
2081 return false;
2082 }
2083
2084 // Ensure that cell links are available.
2085 if (!this->Links)
2086 {
2087 this->BuildLinks();
2088 }
2089
2090 // Get the links (cells that use each point) depending on the editable
2091 // state of this object.
2092 if (!this->Editable)
2093 {
2094 vtkStaticCellLinks* links = static_cast<vtkStaticCellLinks*>(this->Links.Get());
2095 return IsCellBoundaryImp<vtkStaticCellLinks>(links, cellId, npts, pts);
2096 }
2097 else
2098 {
2099 vtkCellLinks* links = static_cast<vtkCellLinks*>(this->Links.Get());
2100 return IsCellBoundaryImp<vtkCellLinks>(links, cellId, npts, pts);
2101 }
2102 }
2103
2104 //----------------------------------------------------------------------------
2105 // Return the cells that use all of the ptIds provided. This is a set
2106 // (intersection) operation - it can have significant performance impacts on
2107 // certain filters like vtkGeometryFilter.
GetCellNeighbors(vtkIdType cellId,vtkIdType npts,const vtkIdType * pts,vtkIdList * cellIds)2108 void vtkUnstructuredGrid::GetCellNeighbors(
2109 vtkIdType cellId, vtkIdType npts, const vtkIdType* pts, vtkIdList* cellIds)
2110 {
2111 // Empty the list
2112 cellIds->Reset();
2113
2114 // Ensure that a proper neighborhood request is made.
2115 if (npts <= 0)
2116 {
2117 return;
2118 }
2119
2120 // Ensure that links are built.
2121 if (!this->Links)
2122 {
2123 this->BuildLinks();
2124 }
2125
2126 // Get the cell links based on the current state.
2127 if (!this->Editable)
2128 {
2129 vtkStaticCellLinks* links = static_cast<vtkStaticCellLinks*>(this->Links.Get());
2130 return GetCellNeighborsImp<vtkStaticCellLinks>(links, cellId, npts, pts, cellIds);
2131 }
2132 else
2133 {
2134 vtkCellLinks* links = static_cast<vtkCellLinks*>(this->Links.Get());
2135 return GetCellNeighborsImp<vtkCellLinks>(links, cellId, npts, pts, cellIds);
2136 }
2137 }
2138
2139 //------------------------------------------------------------------------------
IsHomogeneous()2140 int vtkUnstructuredGrid::IsHomogeneous()
2141 {
2142 unsigned char type;
2143 if (this->Types && this->Types->GetMaxId() >= 0)
2144 {
2145 type = Types->GetValue(0);
2146 vtkIdType numCells = this->GetNumberOfCells();
2147 for (vtkIdType cellId = 0; cellId < numCells; ++cellId)
2148 {
2149 if (this->Types->GetValue(cellId) != type)
2150 {
2151 return 0;
2152 }
2153 }
2154 return 1;
2155 }
2156 return 0;
2157 }
2158
2159 //------------------------------------------------------------------------------
2160 // Fill container with indices of cells which match given type.
GetIdsOfCellsOfType(int type,vtkIdTypeArray * array)2161 void vtkUnstructuredGrid::GetIdsOfCellsOfType(int type, vtkIdTypeArray* array)
2162 {
2163 for (int cellId = 0; cellId < this->GetNumberOfCells(); cellId++)
2164 {
2165 if (static_cast<int>(Types->GetValue(cellId)) == type)
2166 {
2167 array->InsertNextValue(cellId);
2168 }
2169 }
2170 }
2171
2172 //------------------------------------------------------------------------------
RemoveGhostCells()2173 void vtkUnstructuredGrid::RemoveGhostCells()
2174 {
2175 vtkUnstructuredGrid* newGrid = vtkUnstructuredGrid::New();
2176 vtkUnsignedCharArray* temp;
2177 unsigned char* cellGhosts;
2178
2179 vtkIdType cellId, newCellId;
2180 vtkIdList *cellPts, *pointMap;
2181 vtkIdList* newCellPts;
2182 vtkCell* cell;
2183 vtkPoints* newPoints;
2184 vtkIdType i, ptId, newId, numPts;
2185 vtkIdType numCellPts;
2186 double* x;
2187 vtkPointData* pd = this->GetPointData();
2188 vtkPointData* outPD = newGrid->GetPointData();
2189 vtkCellData* cd = this->GetCellData();
2190 vtkCellData* outCD = newGrid->GetCellData();
2191
2192 // Get a pointer to the cell ghost array.
2193 temp = this->GetCellGhostArray();
2194 if (temp == nullptr)
2195 {
2196 vtkDebugMacro("Could not find cell ghost array.");
2197 newGrid->Delete();
2198 return;
2199 }
2200 if ((temp->GetNumberOfComponents() != 1) ||
2201 (temp->GetNumberOfTuples() < this->GetNumberOfCells()))
2202 {
2203 vtkErrorMacro("Poorly formed ghost array.");
2204 newGrid->Delete();
2205 return;
2206 }
2207 cellGhosts = temp->GetPointer(0);
2208
2209 // Now threshold based on the cell ghost array.
2210
2211 // ensure that all attributes are copied over, including global ids.
2212 outPD->CopyAllOn(vtkDataSetAttributes::COPYTUPLE);
2213 outCD->CopyAllOn(vtkDataSetAttributes::COPYTUPLE);
2214
2215 outPD->CopyAllocate(pd);
2216 outCD->CopyAllocate(cd);
2217
2218 numPts = this->GetNumberOfPoints();
2219 newGrid->Allocate(this->GetNumberOfCells());
2220 newPoints = vtkPoints::New();
2221 newPoints->SetDataType(this->GetPoints()->GetDataType());
2222 newPoints->Allocate(numPts);
2223
2224 pointMap = vtkIdList::New(); // maps old point ids into new
2225 pointMap->SetNumberOfIds(numPts);
2226 pointMap->Fill(-1);
2227
2228 newCellPts = vtkIdList::New();
2229
2230 // Check that the scalars of each cell satisfy the threshold criterion
2231 for (cellId = 0; cellId < this->GetNumberOfCells(); cellId++)
2232 {
2233 cell = this->GetCell(cellId);
2234 cellPts = cell->GetPointIds();
2235 numCellPts = cell->GetNumberOfPoints();
2236
2237 if ((cellGhosts[cellId] &
2238 (vtkDataSetAttributes::DUPLICATECELL | vtkDataSetAttributes::HIDDENCELL)) ==
2239 0) // Keep the cell.
2240 {
2241 for (i = 0; i < numCellPts; i++)
2242 {
2243 ptId = cellPts->GetId(i);
2244 if ((newId = pointMap->GetId(ptId)) < 0)
2245 {
2246 x = this->GetPoint(ptId);
2247 newId = newPoints->InsertNextPoint(x);
2248 pointMap->SetId(ptId, newId);
2249 outPD->CopyData(pd, ptId, newId);
2250 }
2251 newCellPts->InsertId(i, newId);
2252 }
2253 newCellId = newGrid->InsertNextCell(cell->GetCellType(), newCellPts);
2254 outCD->CopyData(cd, cellId, newCellId);
2255 newCellPts->Reset();
2256 } // satisfied thresholding
2257 } // for all cells
2258
2259 // now clean up / update ourselves
2260 pointMap->Delete();
2261 newCellPts->Delete();
2262
2263 newGrid->SetPoints(newPoints);
2264 newPoints->Delete();
2265
2266 this->CopyStructure(newGrid);
2267 this->GetPointData()->ShallowCopy(newGrid->GetPointData());
2268 this->GetCellData()->ShallowCopy(newGrid->GetCellData());
2269 newGrid->Delete();
2270 newGrid = nullptr;
2271
2272 this->Squeeze();
2273 }
2274
2275 //------------------------------------------------------------------------------
DecomposeAPolyhedronCell(vtkCellArray * polyhedronCell,vtkIdType & numCellPts,vtkIdType & nCellfaces,vtkCellArray * cellArray,vtkIdTypeArray * faces)2276 void vtkUnstructuredGrid::DecomposeAPolyhedronCell(vtkCellArray* polyhedronCell,
2277 vtkIdType& numCellPts, vtkIdType& nCellfaces, vtkCellArray* cellArray, vtkIdTypeArray* faces)
2278 {
2279 const vtkIdType* cellStream = nullptr;
2280 vtkIdType cellLength = 0;
2281
2282 polyhedronCell->InitTraversal();
2283 polyhedronCell->GetNextCell(cellLength, cellStream);
2284
2285 vtkUnstructuredGrid::DecomposeAPolyhedronCell(
2286 cellStream, numCellPts, nCellfaces, cellArray, faces);
2287 }
2288
2289 //------------------------------------------------------------------------------
DecomposeAPolyhedronCell(const vtkIdType * cellStream,vtkIdType & numCellPts,vtkIdType & nCellFaces,vtkCellArray * cellArray,vtkIdTypeArray * faces)2290 void vtkUnstructuredGrid::DecomposeAPolyhedronCell(const vtkIdType* cellStream,
2291 vtkIdType& numCellPts, vtkIdType& nCellFaces, vtkCellArray* cellArray, vtkIdTypeArray* faces)
2292 {
2293 nCellFaces = cellStream[0];
2294 if (nCellFaces <= 0)
2295 {
2296 return;
2297 }
2298
2299 vtkUnstructuredGrid::DecomposeAPolyhedronCell(
2300 nCellFaces, cellStream + 1, numCellPts, cellArray, faces);
2301 }
2302
2303 //------------------------------------------------------------------------------
DecomposeAPolyhedronCell(vtkIdType nCellFaces,const vtkIdType cellStream[],vtkIdType & numCellPts,vtkCellArray * cellArray,vtkIdTypeArray * faces)2304 void vtkUnstructuredGrid::DecomposeAPolyhedronCell(vtkIdType nCellFaces,
2305 const vtkIdType cellStream[], vtkIdType& numCellPts, vtkCellArray* cellArray,
2306 vtkIdTypeArray* faces)
2307 {
2308 std::set<vtkIdType> cellPointSet;
2309 std::set<vtkIdType>::iterator it;
2310
2311 // insert number of faces into the face array
2312 faces->InsertNextValue(nCellFaces);
2313
2314 // for each face
2315 for (vtkIdType fid = 0; fid < nCellFaces; fid++)
2316 {
2317 // extract all points on the same face, store them into a set
2318 vtkIdType npts = *cellStream++;
2319 faces->InsertNextValue(npts);
2320 for (vtkIdType i = 0; i < npts; i++)
2321 {
2322 vtkIdType pid = *cellStream++;
2323 faces->InsertNextValue(pid);
2324 cellPointSet.insert(pid);
2325 }
2326 }
2327
2328 // standard cell connectivity array that stores the number of points plus
2329 // a list of point ids.
2330 cellArray->InsertNextCell(static_cast<int>(cellPointSet.size()));
2331 for (it = cellPointSet.begin(); it != cellPointSet.end(); ++it)
2332 {
2333 cellArray->InsertCellPoint(*it);
2334 }
2335
2336 // the real number of points in the polyhedron cell.
2337 numCellPts = static_cast<vtkIdType>(cellPointSet.size());
2338 }
2339
2340 //------------------------------------------------------------------------------
ConvertFaceStreamPointIds(vtkIdList * faceStream,vtkIdType * idMap)2341 void vtkUnstructuredGrid::ConvertFaceStreamPointIds(vtkIdList* faceStream, vtkIdType* idMap)
2342 {
2343 vtkIdType* idPtr = faceStream->GetPointer(0);
2344 vtkIdType nfaces = *idPtr++;
2345 for (vtkIdType i = 0; i < nfaces; i++)
2346 {
2347 vtkIdType npts = *idPtr++;
2348 for (vtkIdType j = 0; j < npts; j++)
2349 {
2350 *idPtr = idMap[*idPtr];
2351 idPtr++;
2352 }
2353 }
2354 }
2355
2356 //------------------------------------------------------------------------------
ConvertFaceStreamPointIds(vtkIdType nfaces,vtkIdType * faceStream,vtkIdType * idMap)2357 void vtkUnstructuredGrid::ConvertFaceStreamPointIds(
2358 vtkIdType nfaces, vtkIdType* faceStream, vtkIdType* idMap)
2359 {
2360 vtkIdType* idPtr = faceStream;
2361 for (vtkIdType i = 0; i < nfaces; i++)
2362 {
2363 vtkIdType npts = *idPtr++;
2364 for (vtkIdType j = 0; j < npts; j++)
2365 {
2366 *idPtr = idMap[*idPtr];
2367 idPtr++;
2368 }
2369 }
2370 }
2371
2372 //------------------------------------------------------------------------------
GetData(vtkInformation * info)2373 vtkUnstructuredGrid* vtkUnstructuredGrid::GetData(vtkInformation* info)
2374 {
2375 return info ? vtkUnstructuredGrid::SafeDownCast(info->Get(DATA_OBJECT())) : nullptr;
2376 }
2377
2378 //------------------------------------------------------------------------------
GetData(vtkInformationVector * v,int i)2379 vtkUnstructuredGrid* vtkUnstructuredGrid::GetData(vtkInformationVector* v, int i)
2380 {
2381 return vtkUnstructuredGrid::GetData(v->GetInformationObject(i));
2382 }
2383