VTK-m  2.0
TriangleWinding.h
Go to the documentation of this file.
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 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 // Copyright 2019 UT-Battelle, LLC.
11 // Copyright 2019 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 vtkm_m_worklet_TriangleWinding_h
22 #define vtkm_m_worklet_TriangleWinding_h
23 
24 #include <vtkm/cont/Algorithm.h>
25 #include <vtkm/cont/ArrayHandle.h>
36 #include <vtkm/cont/Invoker.h>
38 
42 
43 #include <vtkm/Types.h>
44 #include <vtkm/VectorAnalysis.h>
45 
46 namespace vtkm
47 {
48 namespace worklet
49 {
50 
59 {
60 public:
61  // Used by Explicit and SingleType specializations
63  {
64  using ControlSignature = void(FieldIn cellNormals, FieldInOut cellPoints, WholeArrayIn coords);
65  using ExecutionSignature = void(_1 cellNormal, _2 cellPoints, _3 coords);
66 
67  template <typename NormalCompType, typename CellPointsType, typename CoordsPortal>
69  CellPointsType& cellPoints,
70  const CoordsPortal& coords) const
71  {
72  // We only care about triangles:
73  if (cellPoints.GetNumberOfComponents() != 3)
74  {
75  return;
76  }
77 
78  using NormalType = vtkm::Vec<NormalCompType, 3>;
79 
80  const NormalType p0 = coords.Get(cellPoints[0]);
81  const NormalType p1 = coords.Get(cellPoints[1]);
82  const NormalType p2 = coords.Get(cellPoints[2]);
83  const NormalType v01 = p1 - p0;
84  const NormalType v02 = p2 - p0;
85  const NormalType triangleNormal = vtkm::Cross(v01, v02);
86  if (vtkm::Dot(cellNormal, triangleNormal) < 0)
87  {
88  // Can't just use std::swap from exec function:
89  const vtkm::Id tmp = cellPoints[1];
90  cellPoints[1] = cellPoints[2];
91  cellPoints[2] = tmp;
92  }
93  }
94  };
95 
96  // Used by generic implementations:
98  {
99  using ControlSignature = void(CellSetIn cells, FieldOutCell shapes, FieldOutCell sizes);
100  using ExecutionSignature = void(CellShape, PointCount, _2, _3);
101 
102  template <typename CellShapeTag>
103  VTKM_EXEC void operator()(const CellShapeTag cellShapeIn,
104  const vtkm::IdComponent cellSizeIn,
105  vtkm::UInt8& cellShapeOut,
106  vtkm::IdComponent& cellSizeOut) const
107  {
108  cellSizeOut = cellSizeIn;
109  cellShapeOut = cellShapeIn.Id;
110  }
111  };
112 
114  {
115  using ControlSignature = void(CellSetIn cellsIn,
116  WholeArrayIn coords,
117  FieldInCell cellNormals,
118  FieldOutCell cellsOut);
119  using ExecutionSignature = void(PointIndices, _2, _3, _4);
120 
121  template <typename InputIds, typename Coords, typename Normal, typename OutputIds>
122  VTKM_EXEC void operator()(const InputIds& inputIds,
123  const Coords& coords,
124  const Normal& normal,
125  OutputIds& outputIds) const
126  {
127  VTKM_ASSERT(inputIds.GetNumberOfComponents() == outputIds.GetNumberOfComponents());
128 
129  // We only care about triangles:
130  if (inputIds.GetNumberOfComponents() != 3)
131  {
132  // Just passthrough non-triangles
133  // Cannot just assign here, must do a manual component-wise copy to
134  // support VecFromPortal:
135  for (vtkm::IdComponent i = 0; i < inputIds.GetNumberOfComponents(); ++i)
136  {
137  outputIds[i] = inputIds[i];
138  }
139  return;
140  }
141 
142  const Normal p0 = coords.Get(inputIds[0]);
143  const Normal p1 = coords.Get(inputIds[1]);
144  const Normal p2 = coords.Get(inputIds[2]);
145  const Normal v01 = p1 - p0;
146  const Normal v02 = p2 - p0;
147  const Normal triangleNormal = vtkm::Cross(v01, v02);
148  if (vtkm::Dot(normal, triangleNormal) < 0)
149  { // Reorder triangle:
150  outputIds[0] = inputIds[0];
151  outputIds[1] = inputIds[2];
152  outputIds[2] = inputIds[1];
153  }
154  else
155  { // passthrough:
156  outputIds[0] = inputIds[0];
157  outputIds[1] = inputIds[1];
158  outputIds[2] = inputIds[2];
159  }
160  }
161  };
162 
163  struct Launcher
164  {
166 
167  // Generic handler:
168  template <typename CellSetType, typename CoordsType, typename CellNormalsType>
169  VTKM_CONT void operator()(const CellSetType& cellSet,
170  const CoordsType& coords,
171  const CellNormalsType& cellNormals,
172  ...)
173  {
174  const auto numCells = cellSet.GetNumberOfCells();
175  if (numCells == 0)
176  {
177  this->Result = cellSet;
178  return;
179  }
180 
181  vtkm::cont::Invoker invoker;
182 
183  // Get each cell's size:
186  {
188  invoker(worklet, cellSet, cellShapes, numIndices);
189  }
190 
191  // Check to see if we can use CellSetSingleType:
192  vtkm::IdComponent cellSize = 0; // 0 if heterogeneous, >0 if homogeneous
193  vtkm::UInt8 cellShape = 0; // only valid if homogeneous
194  {
195  auto rangeHandleSizes = vtkm::cont::ArrayRangeCompute(numIndices);
196  auto rangeHandleShapes = vtkm::cont::ArrayRangeCompute(cellShapes);
197 
198  cellShapes.ReleaseResourcesExecution();
199 
200  auto rangeSizes = rangeHandleSizes.ReadPortal().Get(0);
201  auto rangeShapes = rangeHandleShapes.ReadPortal().Get(0);
202 
203  const bool sameSize = vtkm::Abs(rangeSizes.Max - rangeSizes.Min) < 0.5;
204  const bool sameShape = vtkm::Abs(rangeShapes.Max - rangeShapes.Min) < 0.5;
205 
206  if (sameSize && sameShape)
207  {
208  cellSize = static_cast<vtkm::IdComponent>(rangeSizes.Min + 0.5);
209  cellShape = static_cast<vtkm::UInt8>(rangeShapes.Min + 0.5);
210  }
211  }
212 
213  if (cellSize > 0)
214  { // Single cell type:
215  // don't need these anymore:
216  numIndices.ReleaseResources();
217  cellShapes.ReleaseResources();
218 
220  conn.Allocate(cellSize * numCells);
221 
222  auto offsets = vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, cellSize, numCells);
223  auto connGroupVec = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
224 
226  invoker(worklet, cellSet, coords, cellNormals, connGroupVec);
227 
229  outCells.Fill(cellSet.GetNumberOfPoints(), cellShape, cellSize, conn);
230  this->Result = outCells;
231  }
232  else
233  { // Multiple cell types:
235  vtkm::Id connSize;
236  vtkm::cont::ConvertNumComponentsToOffsets(numIndices, offsets, connSize);
237  numIndices.ReleaseResourcesExecution();
238 
240  conn.Allocate(connSize);
241 
242  // Trim the last value off for the group vec array:
243  auto connGroupVec = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
244 
246  invoker(worklet, cellSet, coords, cellNormals, connGroupVec);
247 
249  outCells.Fill(cellSet.GetNumberOfPoints(), cellShapes, conn, offsets);
250  this->Result = outCells;
251  }
252  }
253 
254  // Specialization for CellSetExplicit
255  template <typename S, typename C, typename O, typename CoordsType, typename CellNormalsType>
257  const CoordsType& coords,
258  const CellNormalsType& cellNormals,
259  int)
260  {
262 
263  const auto numCells = cellSet.GetNumberOfCells();
264  if (numCells == 0)
265  {
266  this->Result = cellSet;
267  return;
268  }
269 
271  {
272  const auto& connIn = cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{},
274  vtkm::cont::Algorithm::Copy(connIn, conn);
275  }
276 
277  const auto& offsets =
279  auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
280 
281  WindToCellNormals dispatcher;
282  dispatcher.Invoke(cellNormals, cells, coords);
283 
284  const auto& shapes =
287  newCells.Fill(cellSet.GetNumberOfPoints(), shapes, conn, offsets);
288 
289  this->Result = newCells;
290  }
291 
292  // Specialization for CellSetSingleType
293  template <typename C, typename CoordsType, typename CellNormalsType>
295  const CoordsType& coords,
296  const CellNormalsType& cellNormals,
297  int)
298  {
300 
301  const auto numCells = cellSet.GetNumberOfCells();
302  if (numCells == 0)
303  {
304  this->Result = cellSet;
305  return;
306  }
307 
309  {
310  const auto& connIn = cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{},
312  vtkm::cont::Algorithm::Copy(connIn, conn);
313  }
314 
315  const auto& offsets =
316  cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
317  auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
318 
319  WindToCellNormals dispatcher;
320  dispatcher.Invoke(cellNormals, cells, coords);
321 
323  newCells.Fill(cellSet.GetNumberOfPoints(),
324  cellSet.GetCellShape(0),
325  cellSet.GetNumberOfPointsInCell(0),
326  conn);
327 
328  this->Result = newCells;
329  }
330  };
331 
332  template <typename CellSetType, typename CoordsType, typename CellNormalsType>
333  VTKM_CONT static vtkm::cont::UnknownCellSet Run(const CellSetType& cellSet,
334  const CoordsType& coords,
335  const CellNormalsType& cellNormals)
336  {
337  Launcher launcher;
338  // The last arg is just to help with overload resolution on the templated
339  // Launcher::operator() method, so that the more specialized impls are
340  // preferred over the generic one.
341  vtkm::cont::CastAndCall(cellSet, launcher, coords, cellNormals, 0);
342  return launcher.Result;
343  }
344 };
345 }
346 } // end namespace vtkm::worklet
347 
348 #endif // vtkm_m_worklet_TriangleWinding_h
vtkm::TopologyElementTagPoint
A tag used to identify the point elements in a topology.
Definition: TopologyElementTag.h:34
vtkm::cont::ArrayHandle< vtkm::IdComponent >
ArrayHandle.h
vtkm::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric::ControlSignature
void(CellSetIn cellsIn, WholeArrayIn coords, FieldInCell cellNormals, FieldOutCell cellsOut) ControlSignature
Definition: TriangleWinding.h:118
vtkm::worklet::TriangleWinding::WorkletGetCellShapesAndSizes::ControlSignature
void(CellSetIn cells, FieldOutCell shapes, FieldOutCell sizes) ControlSignature
Definition: TriangleWinding.h:99
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
ArrayRangeCompute.h
vtkm::worklet::TriangleWinding::Launcher::operator()
VTKM_CONT void operator()(const CellSetType &cellSet, const CoordsType &coords, const CellNormalsType &cellNormals,...)
Definition: TriangleWinding.h:169
ArrayHandleCast.h
Types.h
WorkletMapField.h
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
CellSetExplicit.h
vtkm::cont::ArrayHandle::Allocate
VTKM_CONT void Allocate(vtkm::Id numberOfValues, vtkm::CopyFlag preserve, vtkm::cont::Token &token) const
Allocates an array large enough to hold the given number of values.
Definition: ArrayHandle.h:465
vtkm::worklet::TriangleWinding::Run
static VTKM_CONT vtkm::cont::UnknownCellSet Run(const CellSetType &cellSet, const CoordsType &coords, const CellNormalsType &cellNormals)
Definition: TriangleWinding.h:333
UnknownCellSet.h
vtkm::worklet::WorkletVisitCellsWithPoints::PointCount
IncidentElementCount PointCount
Definition: WorkletMapTopology.h:267
vtkm::IdComponent
vtkm::Int32 IdComponent
Represents a component ID (index of component in a vector).
Definition: Types.h:168
vtkm::cont::CellSetSingleType
Definition: CastAndCall.h:34
vtkm::cont::ArrayHandle::ReleaseResourcesExecution
VTKM_CONT void ReleaseResourcesExecution() const
Releases any resources being used in the execution environment (that are not being shared by the cont...
Definition: ArrayHandle.h:552
ArrayHandleConstant.h
vtkm::cont::Algorithm::Copy
static VTKM_CONT bool Copy(vtkm::cont::DeviceAdapterId devId, const vtkm::cont::ArrayHandle< T, CIn > &input, vtkm::cont::ArrayHandle< U, COut > &output)
Definition: Algorithm.h:410
Invoker.h
vtkm::cont::UnknownCellSet
A CellSet of an unknown type.
Definition: UnknownCellSet.h:48
ArrayHandleView.h
vtkm::cont::CastAndCall
void CastAndCall(const DynamicObject &dynamicObject, Functor &&f, Args &&... args)
A Generic interface to CastAndCall.
Definition: CastAndCall.h:47
vtkm::worklet::WorkletVisitCellsWithPoints::PointIndices
IncidentElementIndices PointIndices
Definition: WorkletMapTopology.h:269
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::cont::CellSetSingleType::GetCellShape
VTKM_DEPRECATED_SUPPRESS_BEGIN VTKM_CONT vtkm::UInt8 GetCellShape(vtkm::Id vtkmNotUsed(cellIndex)) const override
Definition: CellSetSingleType.h:215
VectorAnalysis.h
MaskIndices.h
vtkm::worklet::TriangleWinding::WorkletWindToCellNormals
Definition: TriangleWinding.h:62
vtkm::worklet::TriangleWinding::WorkletGetCellShapesAndSizes
Definition: TriangleWinding.h:97
vtkm::cont::CellSetExplicit::GetOffsetsArray
const VTKM_CONT ConnectivityChooser< VisitTopology, IncidentTopology >::OffsetsArrayType & GetOffsetsArray(VisitTopology, IncidentTopology) const
vtkm::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric::operator()
VTKM_EXEC void operator()(const InputIds &inputIds, const Coords &coords, const Normal &normal, OutputIds &outputIds) const
Definition: TriangleWinding.h:122
vtkm::worklet::DispatcherMapField
Dispatcher for worklets that inherit from WorkletMapField.
Definition: DispatcherMapField.h:25
vtkm::worklet::TriangleWinding::Launcher::operator()
VTKM_CONT void operator()(const vtkm::cont::CellSetExplicit< S, C, O > &cellSet, const CoordsType &coords, const CellNormalsType &cellNormals, int)
Definition: TriangleWinding.h:256
Algorithm.h
vtkm::worklet::Normal
Definition: Normalize.h:22
vtkm::worklet::WorkletMapField::FieldIn
A control signature tag for input fields.
Definition: WorkletMapField.h:49
vtkm::worklet::TriangleWinding::WorkletGetCellShapesAndSizes::ExecutionSignature
void(CellShape, PointCount, _2, _3) ExecutionSignature
Definition: TriangleWinding.h:100
vtkm::Cross
VTKM_EXEC_CONT vtkm::Vec< typename detail::FloatingPointReturnType< T >::Type, 3 > Cross(const vtkm::Vec< T, 3 > &x, const vtkm::Vec< T, 3 > &y)
Find the cross product of two vectors.
Definition: VectorAnalysis.h:177
vtkm::cont::Invoker
Allows launching any worklet without a dispatcher.
Definition: Invoker.h:41
vtkm::worklet::WorkletVisitCellsWithPoints
Base class for worklets that map from Points to Cells.
Definition: WorkletMapTopology.h:255
vtkm::worklet::TriangleWinding::WorkletWindToCellNormals::ExecutionSignature
void(_1 cellNormal, _2 cellPoints, _3 coords) ExecutionSignature
Definition: TriangleWinding.h:65
vtkm::cont::make_ArrayHandleGroupVecVariable
VTKM_CONT vtkm::cont::ArrayHandleGroupVecVariable< ComponentsArrayHandleType, OffsetsArrayHandleType > make_ArrayHandleGroupVecVariable(const ComponentsArrayHandleType &componentsArray, const OffsetsArrayHandleType &offsetsArray)
make_ArrayHandleGroupVecVariable is convenience function to generate an ArrayHandleGroupVecVariable.
Definition: ArrayHandleGroupVecVariable.h:308
vtkm::worklet::TriangleWinding::WorkletWindToCellNormals::operator()
VTKM_EXEC void operator()(const vtkm::Vec< NormalCompType, 3 > &cellNormal, CellPointsType &cellPoints, const CoordsPortal &coords) const
Definition: TriangleWinding.h:68
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::worklet::WorkletMapField::FieldInOut
A control signature tag for input-output (in-place) fields.
Definition: WorkletMapField.h:71
vtkm::cont::CellSetExplicit::Fill
VTKM_CONT void Fill(vtkm::Id numPoints, const vtkm::cont::ArrayHandle< vtkm::UInt8, ShapesStorageTag > &cellTypes, const vtkm::cont::ArrayHandle< vtkm::Id, ConnectivityStorageTag > &connectivity, const vtkm::cont::ArrayHandle< vtkm::Id, OffsetsStorageTag > &offsets)
Second method to add cells – all at once.
vtkm::UInt8
uint8_t UInt8
Definition: Types.h:157
ArrayHandleGroupVec.h
vtkm::worklet::TriangleWinding::Launcher::Result
vtkm::cont::UnknownCellSet Result
Definition: TriangleWinding.h:165
vtkm::worklet::TriangleWinding::Launcher::operator()
VTKM_CONT void operator()(const vtkm::cont::CellSetSingleType< C > &cellSet, const CoordsType &coords, const CellNormalsType &cellNormals, int)
Definition: TriangleWinding.h:294
vtkm::worklet::TriangleWinding::Launcher
Definition: TriangleWinding.h:163
vtkm::cont::CellSetExplicit::GetNumberOfPoints
VTKM_CONT vtkm::Id GetNumberOfPoints() const override
vtkm::Vec
A short fixed-length array.
Definition: Types.h:767
vtkm::cont::ConvertNumComponentsToOffsets
VTKM_CONT_EXPORT void ConvertNumComponentsToOffsets(const vtkm::cont::UnknownArrayHandle &numComponentsArray, vtkm::cont::ArrayHandle< vtkm::Id > &offsetsArray, vtkm::Id &componentsArraySize, vtkm::cont::DeviceAdapterId device=vtkm::cont::DeviceAdapterTagAny{})
vtkm::worklet::TriangleWinding::WorkletWindToCellNormals::ControlSignature
void(FieldIn cellNormals, FieldInOut cellPoints, WholeArrayIn coords) ControlSignature
Definition: TriangleWinding.h:64
vtkm::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric
Definition: TriangleWinding.h:113
vtkm::cont::CellSetExplicit::GetShapesArray
const VTKM_CONT ConnectivityChooser< VisitTopology, IncidentTopology >::ShapesArrayType & GetShapesArray(VisitTopology, IncidentTopology) const
ConvertNumComponentsToOffsets.h
vtkm::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric::ExecutionSignature
void(PointIndices, _2, _3, _4) ExecutionSignature
Definition: TriangleWinding.h:119
vtkm::cont::CellSetExplicit
Definition: CastAndCall.h:36
vtkm::worklet::TriangleWinding::WorkletGetCellShapesAndSizes::operator()
VTKM_EXEC void operator()(const CellShapeTag cellShapeIn, const vtkm::IdComponent cellSizeIn, vtkm::UInt8 &cellShapeOut, vtkm::IdComponent &cellSizeOut) const
Definition: TriangleWinding.h:103
ArrayHandleCounting.h
ArrayHandleGroupVecVariable.h
vtkm::TopologyElementTagCell
A tag used to identify the cell elements in a topology.
Definition: TopologyElementTag.h:24
vtkm::cont::ArrayRangeCompute
VTKM_CONT_EXPORT vtkm::cont::ArrayHandle< vtkm::Range > ArrayRangeCompute(const vtkm::cont::UnknownArrayHandle &array, vtkm::cont::DeviceAdapterId device=vtkm::cont::DeviceAdapterTagAny{})
Compute the range of the data in an array handle.
vtkm::cont::CellSetSingleType::Fill
VTKM_CONT void Fill(vtkm::Id numPoints, vtkm::UInt8 shapeId, vtkm::IdComponent numberOfPointsPerCell, const vtkm::cont::ArrayHandle< vtkm::Id, ConnectivityStorageTag > &connectivity)
Definition: CellSetSingleType.h:186
CellSetSingleType.h
WorkletMapTopology.h
vtkm::cont::CellSetExplicit::GetNumberOfCells
VTKM_CONT vtkm::Id GetNumberOfCells() const override
vtkm::cont::ArrayHandle::ReleaseResources
VTKM_CONT void ReleaseResources() const
Releases all resources in both the control and execution environments.
Definition: ArrayHandle.h:559
vtkm::cont::CellSetExplicit::GetConnectivityArray
const VTKM_CONT ConnectivityChooser< VisitTopology, IncidentTopology >::ConnectivityArrayType & GetConnectivityArray(VisitTopology, IncidentTopology) const
vtkm::worklet::TriangleWinding
This worklet ensures that triangle windings are consistent with provided cell normals.
Definition: TriangleWinding.h:58
vtkm::worklet::WorkletVisitCellsWithPoints::FieldInCell
FieldInVisit FieldInCell
Definition: WorkletMapTopology.h:261
vtkm::worklet::WorkletMapField
Base class for worklets that do a simple mapping of field arrays.
Definition: WorkletMapField.h:38
vtkm::worklet::WorkletVisitCellsWithPoints::FieldOutCell
FieldOut FieldOutCell
Definition: WorkletMapTopology.h:263