1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //  This software is distributed WITHOUT ANY WARRANTY; without even
6 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 //  PURPOSE.  See the above copyright notice for more information.
8 //
9 //  Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 //  Copyright 2015 UT-Battelle, LLC.
11 //  Copyright 2015 Los Alamos National Security.
12 //
13 //  Under the terms of Contract DE-NA0003525 with NTESS,
14 //  the U.S. Government retains certain rights in this software.
15 //
16 //  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
17 //  Laboratory (LANL), the U.S. Government retains certain rights in
18 //  this software.
19 //============================================================================
20 
21 #ifndef vtk_m_worklet_TriangulateExplicit_h
22 #define vtk_m_worklet_TriangulateExplicit_h
23 
24 #include <vtkm/cont/ArrayHandle.h>
25 #include <vtkm/cont/ArrayHandleGroupVec.h>
26 #include <vtkm/cont/CellSetExplicit.h>
27 #include <vtkm/cont/DataSet.h>
28 #include <vtkm/cont/DeviceAdapter.h>
29 #include <vtkm/cont/DynamicArrayHandle.h>
30 #include <vtkm/cont/Field.h>
31 
32 #include <vtkm/worklet/DispatcherMapField.h>
33 #include <vtkm/worklet/DispatcherMapTopology.h>
34 #include <vtkm/worklet/ScatterCounting.h>
35 #include <vtkm/worklet/WorkletMapField.h>
36 #include <vtkm/worklet/WorkletMapTopology.h>
37 
38 #include <vtkm/worklet/internal/TriangulateTables.h>
39 
40 namespace vtkm
41 {
42 namespace worklet
43 {
44 
45 /// \brief Compute the triangulate cells for an explicit grid data set
46 class TriangulateExplicit
47 {
48 public:
TriangulateExplicit()49   TriangulateExplicit() {}
50 
51   //
52   // Worklet to count the number of triangles generated per cell
53   //
54   class TrianglesPerCell : public vtkm::worklet::WorkletMapField
55   {
56   public:
57     using ControlSignature = void(FieldIn<> shapes,
58                                   FieldIn<> numPoints,
59                                   ExecObject tables,
60                                   FieldOut<> triangleCount);
61     using ExecutionSignature = _4(_1, _2, _3);
62     using InputDomain = _1;
63 
64     VTKM_CONT
TrianglesPerCell()65     TrianglesPerCell() {}
66 
67     template <typename DeviceAdapter>
operator()68     VTKM_EXEC vtkm::IdComponent operator()(
69       vtkm::UInt8 shape,
70       vtkm::IdComponent numPoints,
71       const vtkm::worklet::internal::TriangulateTablesExecutionObject<DeviceAdapter>& tables) const
72     {
73       return tables.GetCount(vtkm::CellShapeTagGeneric(shape), numPoints);
74     }
75   };
76 
77   //
78   // Worklet to turn cells into triangles
79   // Vertices remain the same and each cell is processed with needing topology
80   //
81   class TriangulateCell : public vtkm::worklet::WorkletMapPointToCell
82   {
83   public:
84     using ControlSignature = void(CellSetIn cellset,
85                                   ExecObject tables,
86                                   FieldOutCell<> connectivityOut);
87     using ExecutionSignature = void(CellShape, PointIndices, _2, _3, VisitIndex);
88     using InputDomain = _1;
89 
90     using ScatterType = vtkm::worklet::ScatterCounting;
91 
92     template <typename CountArrayType>
MakeScatter(const CountArrayType & countArray)93     VTKM_CONT static ScatterType MakeScatter(const CountArrayType& countArray)
94     {
95       return ScatterType(countArray);
96     }
97 
98     // Each cell produces triangles and write result at the offset
99     template <typename CellShapeTag,
100               typename ConnectivityInVec,
101               typename ConnectivityOutVec,
102               typename DeviceAdapter>
operator()103     VTKM_EXEC void operator()(
104       CellShapeTag shape,
105       const ConnectivityInVec& connectivityIn,
106       const vtkm::worklet::internal::TriangulateTablesExecutionObject<DeviceAdapter>& tables,
107       ConnectivityOutVec& connectivityOut,
108       vtkm::IdComponent visitIndex) const
109     {
110       vtkm::Vec<vtkm::IdComponent, 3> triIndices = tables.GetIndices(shape, visitIndex);
111       connectivityOut[0] = connectivityIn[triIndices[0]];
112       connectivityOut[1] = connectivityIn[triIndices[1]];
113       connectivityOut[2] = connectivityIn[triIndices[2]];
114     }
115   };
116 
117   template <typename CellSetType>
Run(const CellSetType & cellSet,vtkm::cont::ArrayHandle<vtkm::IdComponent> & outCellsPerCell,vtkm::cont::DeviceAdapterId device)118   vtkm::cont::CellSetSingleType<> Run(const CellSetType& cellSet,
119                                       vtkm::cont::ArrayHandle<vtkm::IdComponent>& outCellsPerCell,
120                                       vtkm::cont::DeviceAdapterId device)
121   {
122     vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
123 
124     // Input topology
125     auto inShapes =
126       cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
127     auto inNumIndices =
128       cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
129 
130     // Output topology
131     vtkm::cont::ArrayHandle<vtkm::Id> outConnectivity;
132 
133     vtkm::worklet::internal::TriangulateTables tables;
134 
135     // Determine the number of output cells each input cell will generate
136     vtkm::worklet::DispatcherMapField<TrianglesPerCell> triPerCellDispatcher;
137     triPerCellDispatcher.SetDevice(device);
138     triPerCellDispatcher.Invoke(inShapes, inNumIndices, tables.PrepareForInput(), outCellsPerCell);
139 
140     // Build new cells
141     vtkm::worklet::DispatcherMapTopology<TriangulateCell> triangulateDispatcher(
142       TriangulateCell::MakeScatter(outCellsPerCell));
143     triangulateDispatcher.SetDevice(device);
144     triangulateDispatcher.Invoke(
145       cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<3>(outConnectivity));
146 
147     // Add cells to output cellset
148     outCellSet.Fill(
149       cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTriangle::Id, 3, outConnectivity);
150     return outCellSet;
151   }
152 };
153 }
154 } // namespace vtkm::worklet
155 
156 #endif // vtk_m_worklet_TriangulateExplicit_h
157