1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //
6 //  This software is distributed WITHOUT ANY WARRANTY; without even
7 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 //  PURPOSE.  See the above copyright notice for more information.
9 //============================================================================
10 #ifndef vtk_m_rendering_Quadralizer_h
11 #define vtk_m_rendering_Quadralizer_h
12 
13 #include <typeinfo>
14 #include <vtkm/cont/Algorithm.h>
15 #include <vtkm/cont/ArrayHandleCounting.h>
16 #include <vtkm/cont/CellSetPermutation.h>
17 #include <vtkm/cont/DataSet.h>
18 #include <vtkm/rendering/raytracing/MeshConnectivityBuilder.h>
19 #include <vtkm/worklet/DispatcherMapTopology.h>
20 #include <vtkm/worklet/WorkletMapField.h>
21 #include <vtkm/worklet/WorkletMapTopology.h>
22 
23 
24 #define QUAD_PER_CSS 6
25 
26 namespace vtkm
27 {
28 namespace rendering
29 {
30 
31 class Quadralizer
32 {
33 public:
34   class CountQuads : public vtkm::worklet::WorkletVisitCellsWithPoints
35   {
36   public:
37     VTKM_CONT
CountQuads()38     CountQuads() {}
39     typedef void ControlSignature(CellSetIn cellset, FieldOut);
40     typedef void ExecutionSignature(CellShape, _2);
41 
42     VTKM_EXEC
operator()43     void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& quads) const
44     {
45       if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
46         quads = 1;
47       else if (shapeType.Id == CELL_SHAPE_HEXAHEDRON)
48         quads = 6;
49       else if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
50         quads = 3;
51       else if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
52         quads = 1;
53 
54       else
55         quads = 0;
56     }
57 
58     VTKM_EXEC
operator()59     void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& quads) const
60     {
61       quads = 6;
62     }
63 
64     VTKM_EXEC
operator()65     void operator()(vtkm::CellShapeTagQuad shapeType, vtkm::Id& quads) const
66     {
67       if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
68         quads = 1;
69       else
70         quads = 0;
71     }
72     VTKM_EXEC
operator()73     void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& quads) const
74     {
75       quads = 3;
76     }
77   }; //class CountQuads
78 
79   template <int DIM>
80   class SegmentedStructured : public vtkm::worklet::WorkletVisitCellsWithPoints
81   {
82 
83   public:
84     typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut);
85     typedef void ExecutionSignature(IncidentElementIndices, _2, _3);
86     //typedef _1 InputDomain;
87     VTKM_CONT
SegmentedStructured()88     SegmentedStructured() {}
89 
90 #if defined(VTKM_MSVC)
91 #pragma warning(push)
92 #pragma warning(disable : 4127) //conditional expression is constant
93 #endif
94     template <typename CellNodeVecType, typename OutIndicesPortal>
cell2quad(vtkm::Id4 idx,vtkm::Vec<Id,5> & quad,const vtkm::Id offset,const CellNodeVecType & cellIndices,OutIndicesPortal & outputIndices)95     VTKM_EXEC void cell2quad(vtkm::Id4 idx,
96                              vtkm::Vec<Id, 5>& quad,
97                              const vtkm::Id offset,
98                              const CellNodeVecType& cellIndices,
99                              OutIndicesPortal& outputIndices) const
100     {
101 
102       quad[1] = cellIndices[vtkm::IdComponent(idx[0])];
103       quad[2] = cellIndices[vtkm::IdComponent(idx[1])];
104       quad[3] = cellIndices[vtkm::IdComponent(idx[2])];
105       quad[4] = cellIndices[vtkm::IdComponent(idx[3])];
106       outputIndices.Set(offset, quad);
107     }
108 
109     template <typename CellNodeVecType, typename OutIndicesPortal>
operator()110     VTKM_EXEC void operator()(const CellNodeVecType& cellIndices,
111                               const vtkm::Id& cellIndex,
112                               OutIndicesPortal& outputIndices) const
113     {
114       if (DIM == 2)
115       {
116         outputIndices.Set(
117           cellIndex, { cellIndex, cellIndices[0], cellIndices[1], cellIndices[2], cellIndices[3] });
118       }
119       else if (DIM == 3)
120       {
121         vtkm::Id offset = cellIndex * QUAD_PER_CSS;
122         vtkm::Vec<vtkm::Id, 5> quad;
123         quad[0] = cellIndex;
124         vtkm::Id4 idx;
125         idx[0] = 0;
126         idx[1] = 1;
127         idx[2] = 5;
128         idx[3] = 4;
129         cell2quad(idx, quad, offset, cellIndices, outputIndices);
130 
131         idx[0] = 1;
132         idx[1] = 2;
133         idx[2] = 6;
134         idx[3] = 5;
135         offset++;
136         cell2quad(idx, quad, offset, cellIndices, outputIndices);
137 
138         idx[0] = 3;
139         idx[1] = 7;
140         idx[2] = 6;
141         idx[3] = 2;
142         offset++;
143         cell2quad(idx, quad, offset, cellIndices, outputIndices);
144 
145         idx[0] = 0;
146         idx[1] = 4;
147         idx[2] = 7;
148         idx[3] = 3;
149         offset++;
150         cell2quad(idx, quad, offset, cellIndices, outputIndices);
151 
152         idx[0] = 0;
153         idx[1] = 3;
154         idx[2] = 2;
155         idx[3] = 1;
156         offset++;
157         cell2quad(idx, quad, offset, cellIndices, outputIndices);
158 
159         idx[0] = 4;
160         idx[1] = 5;
161         idx[2] = 6;
162         idx[3] = 7;
163         offset++;
164         cell2quad(idx, quad, offset, cellIndices, outputIndices);
165       }
166     }
167 #if defined(VTKM_MSVC)
168 #pragma warning(pop)
169 #endif
170   };
171 
172 
173   class Quadralize : public vtkm::worklet::WorkletVisitCellsWithPoints
174   {
175 
176   public:
177     VTKM_CONT
Quadralize()178     Quadralize() {}
179     typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut);
180     typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
181 
182     template <typename VecType, typename OutputPortal>
cell2quad(vtkm::Id & offset,const VecType & cellIndices,const vtkm::Id & cellId,const vtkm::Id Id0,const vtkm::Id Id1,const vtkm::Id Id2,const vtkm::Id Id3,OutputPortal & outputIndices)183     VTKM_EXEC void cell2quad(vtkm::Id& offset,
184                              const VecType& cellIndices,
185                              const vtkm::Id& cellId,
186                              const vtkm::Id Id0,
187                              const vtkm::Id Id1,
188                              const vtkm::Id Id2,
189                              const vtkm::Id Id3,
190                              OutputPortal& outputIndices) const
191     {
192       vtkm::Vec<vtkm::Id, 5> quad;
193       quad[0] = cellId;
194       quad[1] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id0)]);
195       quad[2] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id1)]);
196       quad[3] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id2)]);
197       quad[4] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id3)]);
198       outputIndices.Set(offset++, quad);
199     }
200 
201     template <typename VecType, typename OutputPortal>
operator()202     VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
203                               vtkm::CellShapeTagWedge vtkmNotUsed(shapeType),
204                               const VecType& cellIndices,
205                               const vtkm::Id& cellId,
206                               OutputPortal& outputIndices) const
207     {
208       vtkm::Id offset = pointOffset;
209 
210       cell2quad(offset, cellIndices, cellId, 3, 0, 2, 5, outputIndices);
211       cell2quad(offset, cellIndices, cellId, 1, 4, 5, 2, outputIndices);
212       cell2quad(offset, cellIndices, cellId, 0, 3, 4, 1, outputIndices);
213     }
214     template <typename VecType, typename OutputPortal>
operator()215     VTKM_EXEC void operator()(const vtkm::Id& offset,
216                               vtkm::CellShapeTagQuad shapeType,
217                               const VecType& cellIndices,
218                               const vtkm::Id& cellId,
219                               OutputPortal& outputIndices) const
220     {
221       if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
222       {
223         vtkm::Vec<vtkm::Id, 5> quad;
224         quad[0] = cellId;
225         quad[1] = static_cast<vtkm::Id>(cellIndices[0]);
226         quad[2] = static_cast<vtkm::Id>(cellIndices[1]);
227         quad[3] = static_cast<vtkm::Id>(cellIndices[2]);
228         quad[4] = static_cast<vtkm::Id>(cellIndices[3]);
229         outputIndices.Set(offset, quad);
230       }
231     }
232 
233     template <typename VecType, typename OutputPortal>
operator()234     VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
235                               vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),
236                               const VecType& cellIndices,
237                               const vtkm::Id& cellId,
238                               OutputPortal& outputIndices) const
239 
240     {
241       vtkm::Id offset = pointOffset;
242       cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices);
243       cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices);
244       cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices);
245       cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices);
246       cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices);
247       cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices);
248     }
249 
250     template <typename VecType, typename OutputPortal>
operator()251     VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
252                               vtkm::CellShapeTagGeneric shapeType,
253                               const VecType& cellIndices,
254                               const vtkm::Id& cellId,
255                               OutputPortal& outputIndices) const
256     {
257 
258       if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
259       {
260         vtkm::Vec<vtkm::Id, 5> quad;
261         quad[0] = cellId;
262         quad[1] = cellIndices[0];
263         quad[2] = cellIndices[1];
264         quad[3] = cellIndices[2];
265         quad[4] = cellIndices[3];
266         outputIndices.Set(pointOffset, quad);
267       }
268       if (shapeType.Id == vtkm::CELL_SHAPE_HEXAHEDRON)
269       {
270         vtkm::Id offset = pointOffset;
271         cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices);
272         cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices);
273         cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices);
274         cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices);
275         cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices);
276         cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices);
277       }
278       if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
279       {
280         vtkm::Id offset = pointOffset;
281 
282         cell2quad(offset, cellIndices, cellId, 3, 0, 2, 5, outputIndices);
283         cell2quad(offset, cellIndices, cellId, 1, 4, 5, 2, outputIndices);
284         cell2quad(offset, cellIndices, cellId, 0, 3, 4, 1, outputIndices);
285       }
286       if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
287       {
288         vtkm::Id offset = pointOffset;
289 
290         cell2quad(offset, cellIndices, cellId, 3, 2, 1, 0, outputIndices);
291       }
292     }
293 
294   }; //class Quadralize
295 
296 public:
297   VTKM_CONT
Quadralizer()298   Quadralizer() {}
299 
300   VTKM_CONT
Run(const vtkm::cont::DynamicCellSet & cellset,vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id,5>> & outputIndices,vtkm::Id & output)301   void Run(const vtkm::cont::DynamicCellSet& cellset,
302            vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>>& outputIndices,
303            vtkm::Id& output)
304   {
305     vtkm::cont::Invoker invoke;
306 
307     if (cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
308     {
309       vtkm::cont::CellSetStructured<3> cellSetStructured3D =
310         cellset.Cast<vtkm::cont::CellSetStructured<3>>();
311       const vtkm::Id numCells = cellSetStructured3D.GetNumberOfCells();
312 
313       vtkm::cont::ArrayHandleIndex cellIdxs(numCells);
314       outputIndices.Allocate(numCells * QUAD_PER_CSS);
315       invoke(SegmentedStructured<3>{}, cellSetStructured3D, cellIdxs, outputIndices);
316 
317       output = numCells * QUAD_PER_CSS;
318     }
319     else if (cellset.IsSameType(vtkm::cont::CellSetStructured<2>()))
320     {
321       vtkm::cont::CellSetStructured<2> cellSetStructured2D =
322         cellset.Cast<vtkm::cont::CellSetStructured<2>>();
323       const vtkm::Id numCells = cellSetStructured2D.GetNumberOfCells();
324 
325       vtkm::cont::ArrayHandleIndex cellIdxs(numCells);
326       outputIndices.Allocate(numCells);
327       invoke(SegmentedStructured<2>{}, cellSetStructured2D, cellIdxs, outputIndices);
328 
329       output = numCells;
330     }
331     else
332     {
333       auto cellSetUnstructured =
334         cellset.ResetCellSetList(VTKM_DEFAULT_CELL_SET_LIST_UNSTRUCTURED{});
335       vtkm::cont::ArrayHandle<vtkm::Id> quadsPerCell;
336       invoke(CountQuads{}, cellSetUnstructured, quadsPerCell);
337 
338       vtkm::Id total = 0;
339       total = vtkm::cont::Algorithm::Reduce(quadsPerCell, vtkm::Id(0));
340 
341       vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
342       vtkm::cont::Algorithm::ScanExclusive(quadsPerCell, cellOffsets);
343       outputIndices.Allocate(total);
344 
345       invoke(Quadralize{}, cellSetUnstructured, cellOffsets, outputIndices);
346 
347       output = total;
348     }
349   }
350 };
351 }
352 }
353 #endif
354