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