Viskores  1.0
TriangleWinding.h
Go to the documentation of this file.
1 //============================================================================
2 // The contents of this file are covered by the Viskores license. See
3 // LICENSE.txt for details.
4 //
5 // By contributing to this file, all contributors agree to the Developer
6 // Certificate of Origin Version 1.1 (DCO 1.1) as stated in DCO.txt.
7 //============================================================================
8 
9 //============================================================================
10 // Copyright (c) Kitware, Inc.
11 // All rights reserved.
12 // See LICENSE.txt for details.
13 // This software is distributed WITHOUT ANY WARRANTY; without even
14 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 // PURPOSE. See the above copyright notice for more information.
16 //
17 // Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
18 // Copyright 2019 UT-Battelle, LLC.
19 // Copyright 2019 Los Alamos National Security.
20 //
21 // Under the terms of Contract DE-NA0003525 with NTESS,
22 // the U.S. Government retains certain rights in this software.
23 //
24 // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
25 // Laboratory (LANL), the U.S. Government retains certain rights in
26 // this software.
27 //============================================================================
28 
29 #ifndef viskores_m_worklet_TriangleWinding_h
30 #define viskores_m_worklet_TriangleWinding_h
31 
44 #include <viskores/cont/Invoker.h>
46 
50 
51 #include <viskores/Types.h>
53 
54 namespace viskores
55 {
56 namespace worklet
57 {
58 
67 {
68 public:
69  // Used by Explicit and SingleType specializations
71  {
72  using ControlSignature = void(FieldIn cellNormals, FieldInOut cellPoints, WholeArrayIn coords);
73  using ExecutionSignature = void(_1 cellNormal, _2 cellPoints, _3 coords);
74 
75  template <typename NormalCompType, typename CellPointsType, typename CoordsPortal>
77  CellPointsType& cellPoints,
78  const CoordsPortal& coords) const
79  {
80  // We only care about triangles:
81  if (cellPoints.GetNumberOfComponents() != 3)
82  {
83  return;
84  }
85 
86  using NormalType = viskores::Vec<NormalCompType, 3>;
87 
88  const NormalType p0 = coords.Get(cellPoints[0]);
89  const NormalType p1 = coords.Get(cellPoints[1]);
90  const NormalType p2 = coords.Get(cellPoints[2]);
91  const NormalType v01 = p1 - p0;
92  const NormalType v02 = p2 - p0;
93  const NormalType triangleNormal = viskores::Cross(v01, v02);
94  if (viskores::Dot(cellNormal, triangleNormal) < 0)
95  {
96  // Can't just use std::swap from exec function:
97  const viskores::Id tmp = cellPoints[1];
98  cellPoints[1] = cellPoints[2];
99  cellPoints[2] = tmp;
100  }
101  }
102  };
103 
104  // Used by generic implementations:
106  {
107  using ControlSignature = void(CellSetIn cells, FieldOutCell shapes, FieldOutCell sizes);
108  using ExecutionSignature = void(CellShape, PointCount, _2, _3);
109 
110  template <typename CellShapeTag>
111  VISKORES_EXEC void operator()(const CellShapeTag cellShapeIn,
112  const viskores::IdComponent cellSizeIn,
113  viskores::UInt8& cellShapeOut,
114  viskores::IdComponent& cellSizeOut) const
115  {
116  cellSizeOut = cellSizeIn;
117  cellShapeOut = cellShapeIn.Id;
118  }
119  };
120 
122  {
123  using ControlSignature = void(CellSetIn cellsIn,
124  WholeArrayIn coords,
125  FieldInCell cellNormals,
126  FieldOutCell cellsOut);
127  using ExecutionSignature = void(PointIndices, _2, _3, _4);
128 
129  template <typename InputIds, typename Coords, typename Normal, typename OutputIds>
130  VISKORES_EXEC void operator()(const InputIds& inputIds,
131  const Coords& coords,
132  const Normal& normal,
133  OutputIds& outputIds) const
134  {
135  VISKORES_ASSERT(inputIds.GetNumberOfComponents() == outputIds.GetNumberOfComponents());
136 
137  // We only care about triangles:
138  if (inputIds.GetNumberOfComponents() != 3)
139  {
140  // Just passthrough non-triangles
141  // Cannot just assign here, must do a manual component-wise copy to
142  // support VecFromPortal:
143  for (viskores::IdComponent i = 0; i < inputIds.GetNumberOfComponents(); ++i)
144  {
145  outputIds[i] = inputIds[i];
146  }
147  return;
148  }
149 
150  const Normal p0 = coords.Get(inputIds[0]);
151  const Normal p1 = coords.Get(inputIds[1]);
152  const Normal p2 = coords.Get(inputIds[2]);
153  const Normal v01 = p1 - p0;
154  const Normal v02 = p2 - p0;
155  const Normal triangleNormal = viskores::Cross(v01, v02);
156  if (viskores::Dot(normal, triangleNormal) < 0)
157  { // Reorder triangle:
158  outputIds[0] = inputIds[0];
159  outputIds[1] = inputIds[2];
160  outputIds[2] = inputIds[1];
161  }
162  else
163  { // passthrough:
164  outputIds[0] = inputIds[0];
165  outputIds[1] = inputIds[1];
166  outputIds[2] = inputIds[2];
167  }
168  }
169  };
170 
171  struct Launcher
172  {
174 
175  // Generic handler:
176  template <typename CellSetType, typename CoordsType, typename CellNormalsType>
177  VISKORES_CONT void operator()(const CellSetType& cellSet,
178  const CoordsType& coords,
179  const CellNormalsType& cellNormals,
180  ...)
181  {
182  const auto numCells = cellSet.GetNumberOfCells();
183  if (numCells == 0)
184  {
185  this->Result = cellSet;
186  return;
187  }
188 
189  viskores::cont::Invoker invoker;
190 
191  // Get each cell's size:
194  {
196  invoker(worklet, cellSet, cellShapes, numIndices);
197  }
198 
199  // Check to see if we can use CellSetSingleType:
200  viskores::IdComponent cellSize = 0; // 0 if heterogeneous, >0 if homogeneous
201  viskores::UInt8 cellShape = 0; // only valid if homogeneous
202  {
203  auto rangeHandleSizes = viskores::cont::ArrayRangeCompute(numIndices);
204  auto rangeHandleShapes = viskores::cont::ArrayRangeCompute(cellShapes);
205 
206  cellShapes.ReleaseResourcesExecution();
207 
208  auto rangeSizes = rangeHandleSizes.ReadPortal().Get(0);
209  auto rangeShapes = rangeHandleShapes.ReadPortal().Get(0);
210 
211  const bool sameSize = viskores::Abs(rangeSizes.Max - rangeSizes.Min) < 0.5;
212  const bool sameShape = viskores::Abs(rangeShapes.Max - rangeShapes.Min) < 0.5;
213 
214  if (sameSize && sameShape)
215  {
216  cellSize = static_cast<viskores::IdComponent>(rangeSizes.Min + 0.5);
217  cellShape = static_cast<viskores::UInt8>(rangeShapes.Min + 0.5);
218  }
219  }
220 
221  if (cellSize > 0)
222  { // Single cell type:
223  // don't need these anymore:
224  numIndices.ReleaseResources();
225  cellShapes.ReleaseResources();
226 
228  conn.Allocate(cellSize * numCells);
229 
230  auto offsets =
231  viskores::cont::make_ArrayHandleCounting<viskores::Id>(0, cellSize, numCells);
232  auto connGroupVec = viskores::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
233 
235  invoker(worklet, cellSet, coords, cellNormals, connGroupVec);
236 
238  outCells.Fill(cellSet.GetNumberOfPoints(), cellShape, cellSize, conn);
239  this->Result = outCells;
240  }
241  else
242  { // Multiple cell types:
244  viskores::Id connSize;
245  viskores::cont::ConvertNumComponentsToOffsets(numIndices, offsets, connSize);
246  numIndices.ReleaseResourcesExecution();
247 
249  conn.Allocate(connSize);
250 
251  // Trim the last value off for the group vec array:
252  auto connGroupVec = viskores::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
253 
255  invoker(worklet, cellSet, coords, cellNormals, connGroupVec);
256 
258  outCells.Fill(cellSet.GetNumberOfPoints(), cellShapes, conn, offsets);
259  this->Result = outCells;
260  }
261  }
262 
263  // Specialization for CellSetExplicit
264  template <typename S, typename C, typename O, typename CoordsType, typename CellNormalsType>
266  const CoordsType& coords,
267  const CellNormalsType& cellNormals,
268  int)
269  {
271 
272  const auto numCells = cellSet.GetNumberOfCells();
273  if (numCells == 0)
274  {
275  this->Result = cellSet;
276  return;
277  }
278 
280  {
281  const auto& connIn = cellSet.GetConnectivityArray(viskores::TopologyElementTagCell{},
283  viskores::cont::Algorithm::Copy(connIn, conn);
284  }
285 
286  const auto& offsets = cellSet.GetOffsetsArray(viskores::TopologyElementTagCell{},
288  auto cells = viskores::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
289 
290  WindToCellNormals dispatcher;
291  dispatcher.Invoke(cellNormals, cells, coords);
292 
293  const auto& shapes = cellSet.GetShapesArray(viskores::TopologyElementTagCell{},
296  newCells.Fill(cellSet.GetNumberOfPoints(), shapes, conn, offsets);
297 
298  this->Result = newCells;
299  }
300 
301  // Specialization for CellSetSingleType
302  template <typename C, typename CoordsType, typename CellNormalsType>
304  const CoordsType& coords,
305  const CellNormalsType& cellNormals,
306  int)
307  {
309 
310  const auto numCells = cellSet.GetNumberOfCells();
311  if (numCells == 0)
312  {
313  this->Result = cellSet;
314  return;
315  }
316 
318  {
319  const auto& connIn = cellSet.GetConnectivityArray(viskores::TopologyElementTagCell{},
321  viskores::cont::Algorithm::Copy(connIn, conn);
322  }
323 
324  const auto& offsets = cellSet.GetOffsetsArray(viskores::TopologyElementTagCell{},
326  auto cells = viskores::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
327 
328  WindToCellNormals dispatcher;
329  dispatcher.Invoke(cellNormals, cells, coords);
330 
332  newCells.Fill(cellSet.GetNumberOfPoints(),
333  cellSet.GetCellShape(0),
334  cellSet.GetNumberOfPointsInCell(0),
335  conn);
336 
337  this->Result = newCells;
338  }
339  };
340 
341  template <typename CellSetType, typename CoordsType, typename CellNormalsType>
342  VISKORES_CONT static viskores::cont::UnknownCellSet Run(const CellSetType& cellSet,
343  const CoordsType& coords,
344  const CellNormalsType& cellNormals)
345  {
346  Launcher launcher;
347  // The last arg is just to help with overload resolution on the templated
348  // Launcher::operator() method, so that the more specialized impls are
349  // preferred over the generic one.
350  viskores::cont::CastAndCall(cellSet, launcher, coords, cellNormals, 0);
351  return launcher.Result;
352  }
353 };
354 }
355 } // end namespace viskores::worklet
356 
357 #endif // viskores_m_worklet_TriangleWinding_h
viskores::worklet::TriangleWinding::WorkletWindToCellNormals::ControlSignature
void(FieldIn cellNormals, FieldInOut cellPoints, WholeArrayIn coords) ControlSignature
Definition: TriangleWinding.h:72
viskores::worklet::WorkletVisitCellsWithPoints::FieldInCell
A control signature tag for input fields on the cells of the topology.
Definition: WorkletMapTopology.h:299
ArrayHandle.h
viskores::TopologyElementTagCell
A tag used to identify the cell elements in a topology.
Definition: TopologyElementTag.h:32
ArrayRangeCompute.h
ArrayHandleCast.h
Types.h
WorkletMapField.h
viskores::cont::CastAndCall
void CastAndCall(const DynamicObject &dynamicObject, Functor &&f, Args &&... args)
A Generic interface to CastAndCall.
Definition: CastAndCall.h:55
CellSetExplicit.h
UnknownCellSet.h
viskores::worklet::WorkletVisitCellsWithPoints::CellSetIn
A control signature tag for input connectivity.
Definition: WorkletMapTopology.h:289
viskores::worklet::TriangleWinding::WorkletWindToCellNormals::operator()
void operator()(const viskores::Vec< NormalCompType, 3 > &cellNormal, CellPointsType &cellPoints, const CoordsPortal &coords) const
Definition: TriangleWinding.h:76
viskores::cont::CellSetSingleType::GetCellShape
viskores::UInt8 GetCellShape(viskores::Id) const override
Definition: CellSetSingleType.h:241
viskores::worklet::WorkletMapField::FieldIn
A control signature tag for input fields.
Definition: WorkletMapField.h:68
viskores::worklet::WorkletVisitCellsWithPoints::CellShape
An execution signature tag to get the shape of the visited cell.
Definition: WorkletMapTopology.h:406
viskores::cont::ArrayHandle< viskores::IdComponent >
ArrayHandleConstant.h
viskores::worklet::TriangleWinding::WorkletGetCellShapesAndSizes::ControlSignature
void(CellSetIn cells, FieldOutCell shapes, FieldOutCell sizes) ControlSignature
Definition: TriangleWinding.h:107
Invoker.h
viskores::IdComponent
viskores::Int32 IdComponent
Base type to use to index small lists.
Definition: Types.h:202
ArrayHandleView.h
viskores::worklet::WorkletVisitCellsWithPoints
Base class for worklets that map from Points to Cells.
Definition: WorkletMapTopology.h:265
viskores::worklet::WorkletVisitCellsWithPoints::PointCount
An execution signature tag to get the number of incident points.
Definition: WorkletMapTopology.h:416
viskores::cont::CellSetExplicit::GetOffsetsArray
const ConnectivityChooser< VisitTopology, IncidentTopology >::OffsetsArrayType & GetOffsetsArray(VisitTopology, IncidentTopology) const
Returns the viskores::cont::ArrayHandle containing the offsets into theconnectivity information.
viskores::TopologyElementTagPoint
A tag used to identify the point elements in a topology.
Definition: TopologyElementTag.h:42
viskores::worklet::WorkletVisitCellsWithPoints::PointIndices
An execution signature tag to get the indices of the incident points.
Definition: WorkletMapTopology.h:426
viskores::Cross
viskores::Vec< typename detail::FloatingPointReturnType< T >::Type, 3 > Cross(const viskores::Vec< T, 3 > &x, const viskores::Vec< T, 3 > &y)
Find the cross product of two vectors.
Definition: VectorAnalysis.h:188
viskores::worklet::TriangleWinding::Run
static viskores::cont::UnknownCellSet Run(const CellSetType &cellSet, const CoordsType &coords, const CellNormalsType &cellNormals)
Definition: TriangleWinding.h:342
VectorAnalysis.h
MaskIndices.h
viskores::cont::CellSetExplicit::GetConnectivityArray
const ConnectivityChooser< VisitTopology, IncidentTopology >::ConnectivityArrayType & GetConnectivityArray(VisitTopology, IncidentTopology) const
Returns the viskores::cont::ArrayHandle containing the connectivity information.
viskores::worklet::TriangleWinding::Launcher::operator()
void operator()(const viskores::cont::CellSetExplicit< S, C, O > &cellSet, const CoordsType &coords, const CellNormalsType &cellNormals, int)
Definition: TriangleWinding.h:265
viskores::worklet::TriangleWinding::WorkletWindToCellNormals
Definition: TriangleWinding.h:70
viskores::cont::Algorithm::Copy
static bool Copy(viskores::cont::DeviceAdapterId devId, const viskores::cont::ArrayHandle< T, CIn > &input, viskores::cont::ArrayHandle< U, COut > &output)
Definition: Algorithm.h:422
viskores::Id
viskores::Int64 Id
Base type to use to index arrays.
Definition: Types.h:235
viskores::cont::ArrayHandle::ReleaseResources
void ReleaseResources() const
Releases all resources in both the control and execution environments.
Definition: ArrayHandle.h:600
viskores::worklet::WorkletMapField::FieldInOut
A control signature tag for input-output (in-place) fields.
Definition: WorkletMapField.h:107
VISKORES_CONT
#define VISKORES_CONT
Definition: ExportMacros.h:65
viskores
Groups connected points that have the same field value.
Definition: Atomic.h:27
viskores::worklet::DispatcherMapField
Dispatcher for worklets that inherit from WorkletMapField.
Definition: DispatcherMapField.h:33
Algorithm.h
viskores::worklet::TriangleWinding::WorkletGetCellShapesAndSizes
Definition: TriangleWinding.h:105
viskores::cont::ArrayHandle::Allocate
void Allocate(viskores::Id numberOfValues, viskores::CopyFlag preserve, viskores::cont::Token &token) const
Allocates an array large enough to hold the given number of values.
Definition: ArrayHandle.h:504
viskores::cont::CellSetExplicit
Defines an irregular collection of cells.
Definition: CastAndCall.h:44
viskores::worklet::TriangleWinding::Launcher::operator()
void operator()(const viskores::cont::CellSetSingleType< C > &cellSet, const CoordsType &coords, const CellNormalsType &cellNormals, int)
Definition: TriangleWinding.h:303
viskores::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric::ExecutionSignature
void(PointIndices, _2, _3, _4) ExecutionSignature
Definition: TriangleWinding.h:127
VISKORES_ASSERT
#define VISKORES_ASSERT(condition)
Definition: Assert.h:51
viskores::worklet::TriangleWinding::WorkletGetCellShapesAndSizes::ExecutionSignature
void(CellShape, PointCount, _2, _3) ExecutionSignature
Definition: TriangleWinding.h:108
viskores::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric::ControlSignature
void(CellSetIn cellsIn, WholeArrayIn coords, FieldInCell cellNormals, FieldOutCell cellsOut) ControlSignature
Definition: TriangleWinding.h:126
viskores::worklet::Normal
Definition: Normalize.h:30
viskores::cont::CellSetExplicit::Fill
void Fill(viskores::Id numPoints, const viskores::cont::ArrayHandle< viskores::UInt8, ShapesStorageTag > &cellTypes, const viskores::cont::ArrayHandle< viskores::Id, ConnectivityStorageTag > &connectivity, const viskores::cont::ArrayHandle< viskores::Id, OffsetsStorageTag > &offsets)
Set all the cells of the mesh.
viskores::cont::CellSetExplicit::GetNumberOfCells
viskores::Id GetNumberOfCells() const override
viskores::worklet::TriangleWinding::Launcher::operator()
void operator()(const CellSetType &cellSet, const CoordsType &coords, const CellNormalsType &cellNormals,...)
Definition: TriangleWinding.h:177
viskores::cont::ConvertNumComponentsToOffsets
void ConvertNumComponentsToOffsets(const viskores::cont::UnknownArrayHandle &numComponentsArray, viskores::cont::ArrayHandle< viskores::Id > &offsetsArray, viskores::Id &componentsArraySize, viskores::cont::DeviceAdapterId device=viskores::cont::DeviceAdapterTagAny{})
ConvertNumComponentsToOffsets takes an array of Vec sizes (i.e.
viskores::worklet::TriangleWinding::Launcher
Definition: TriangleWinding.h:171
ArrayHandleGroupVec.h
viskores::worklet::TriangleWinding::WorkletGetCellShapesAndSizes::operator()
void operator()(const CellShapeTag cellShapeIn, const viskores::IdComponent cellSizeIn, viskores::UInt8 &cellShapeOut, viskores::IdComponent &cellSizeOut) const
Definition: TriangleWinding.h:111
viskores::UInt8
uint8_t UInt8
Base type to use for 8-bit unsigned integer numbers.
Definition: Types.h:177
viskores::cont::ArrayHandle::ReleaseResourcesExecution
void ReleaseResourcesExecution() const
Releases any resources being used in the execution environment (that are not being shared by the cont...
Definition: ArrayHandle.h:593
viskores::cont::CellSetExplicit::GetNumberOfPoints
viskores::Id GetNumberOfPoints() const override
viskores::cont::UnknownCellSet
A CellSet of an unknown type.
Definition: UnknownCellSet.h:56
viskores::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric::operator()
void operator()(const InputIds &inputIds, const Coords &coords, const Normal &normal, OutputIds &outputIds) const
Definition: TriangleWinding.h:130
viskores::worklet::WorkletVisitCellsWithPoints::FieldOutCell
A control signature tag for output fields.
Definition: WorkletMapTopology.h:334
ConvertNumComponentsToOffsets.h
viskores::cont::CellSetExplicit::GetShapesArray
const ConnectivityChooser< VisitTopology, IncidentTopology >::ShapesArrayType & GetShapesArray(VisitTopology, IncidentTopology) const
Returns the viskores::cont::ArrayHandle holding the shape information.
ArrayHandleCounting.h
viskores::cont::CellSetSingleType::Fill
void Fill(viskores::Id numPoints, viskores::UInt8 shapeId, viskores::IdComponent numberOfPointsPerCell, const viskores::cont::ArrayHandle< viskores::Id, ConnectivityStorageTag > &connectivity)
Set all the cells of the mesh.
Definition: CellSetSingleType.h:211
viskores::cont::make_ArrayHandleGroupVecVariable
viskores::cont::ArrayHandleGroupVecVariable< ComponentsArrayHandleType, OffsetsArrayHandleType > make_ArrayHandleGroupVecVariable(const ComponentsArrayHandleType &componentsArray, const OffsetsArrayHandleType &offsetsArray)
make_ArrayHandleGroupVecVariable is convenience function to generate an ArrayHandleGroupVecVariable.
Definition: ArrayHandleGroupVecVariable.h:332
viskores::cont::CellSetSingleType
An explicit cell set with all cells of the same shape.
Definition: CastAndCall.h:42
ArrayHandleGroupVecVariable.h
viskores::cont::Invoker
Allows launching any worklet without a dispatcher.
Definition: Invoker.h:49
viskores::worklet::WorkletMapField
Base class for worklets that do a simple mapping of field arrays.
Definition: WorkletMapField.h:47
viskores::worklet::TriangleWinding::Launcher::Result
viskores::cont::UnknownCellSet Result
Definition: TriangleWinding.h:173
CellSetSingleType.h
viskores::worklet::TriangleWinding::WorkletWindToCellNormals::ExecutionSignature
void(_1 cellNormal, _2 cellPoints, _3 coords) ExecutionSignature
Definition: TriangleWinding.h:73
WorkletMapTopology.h
viskores::cont::ArrayRangeCompute
viskores::cont::ArrayHandle< viskores::Range > ArrayRangeCompute(const viskores::cont::UnknownArrayHandle &array, bool computeFiniteRange=false, viskores::cont::DeviceAdapterId device=viskores::cont::DeviceAdapterTagAny{})
Compute the range of the data in an array handle.
viskores::Vec
A short fixed-length array.
Definition: Types.h:365
viskores::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric
Definition: TriangleWinding.h:121
VISKORES_EXEC
#define VISKORES_EXEC
Definition: ExportMacros.h:59
viskores::worklet::TriangleWinding
This worklet ensures that triangle windings are consistent with provided cell normals.
Definition: TriangleWinding.h:66