//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. // // Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS). // Copyright 2017 UT-Battelle, LLC. // Copyright 2017 Los Alamos National Security. // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ #ifndef vtk_m_worklet_SurfaceNormals_h #define vtk_m_worklet_SurfaceNormals_h #include #include #include #include #include namespace vtkm { namespace worklet { namespace detail { struct PassThrough { template VTKM_EXEC vtkm::Vec operator()(const vtkm::Vec& in) const { return in; } }; struct Normal { template VTKM_EXEC vtkm::Vec operator()(const vtkm::Vec& in) const { return vtkm::Normal(in); } }; } // detail class FacetedSurfaceNormals { public: template class Worklet : public vtkm::worklet::WorkletMapPointToCell { public: typedef void ControlSignature(CellSetIn cellset, FieldInPoint points, FieldOutCell normals); typedef void ExecutionSignature(CellShape, _2, _3); using InputDomain = _1; template VTKM_EXEC void operator()(CellShapeTag, const PointsVecType& points, vtkm::Vec& normal) const { using CTraits = vtkm::CellTraits; const auto tag = typename CTraits::TopologicalDimensionsTag(); this->Compute(tag, points, normal); } template VTKM_EXEC void Compute(vtkm::CellTopologicalDimensionsTag, const PointsVecType&, vtkm::Vec& normal) const { normal = vtkm::TypeTraits>::ZeroInitialization(); } template VTKM_EXEC void Compute(vtkm::CellTopologicalDimensionsTag<2>, const PointsVecType& points, vtkm::Vec& normal) const { normal = this->Normal(vtkm::Cross(points[2] - points[1], points[0] - points[1])); } template VTKM_EXEC void operator()(vtkm::CellShapeTagGeneric shape, const PointsVecType& points, vtkm::Vec& normal) const { switch (shape.Id) { vtkmGenericCellShapeMacro(this->operator()(CellShapeTag(), points, normal)); default: this->RaiseError("unknown cell type"); break; } } private: NormalFnctr Normal; }; FacetedSurfaceNormals() : Normalize(true) { } /// Set/Get if the results should be normalized void SetNormalize(bool value) { this->Normalize = value; } bool GetNormalize() const { return this->Normalize; } template void Run(const CellSetType& cellset, const vtkm::cont::ArrayHandle, CoordsStorageType>& points, vtkm::cont::ArrayHandle>& normals, DeviceAdapter) { if (this->Normalize) { vtkm::worklet::DispatcherMapTopology, DeviceAdapter> dispatcher; dispatcher.Invoke(cellset, points, normals); } else { vtkm::worklet::DispatcherMapTopology, DeviceAdapter> dispatcher; dispatcher.Invoke(cellset, points, normals); } } template void Run( const CellSetType& cellset, const vtkm::cont::DynamicArrayHandleBase& points, vtkm::cont::ArrayHandle>& normals, DeviceAdapter) { if (this->Normalize) { vtkm::worklet::DispatcherMapTopology, DeviceAdapter> dispatcher; dispatcher.Invoke(cellset, points, normals); } else { vtkm::worklet::DispatcherMapTopology, DeviceAdapter> dispatcher; dispatcher.Invoke(cellset, points, normals); } } private: bool Normalize; }; class SmoothSurfaceNormals { public: class Worklet : public vtkm::worklet::WorkletMapCellToPoint { public: typedef void ControlSignature(CellSetIn cellset, FieldInCell faceNormals, FieldOutPoint pointNormals); typedef void ExecutionSignature(CellCount, _2, _3); using InputDomain = _1; template VTKM_EXEC void operator()(vtkm::IdComponent numCells, const FaceNormalsVecType& faceNormals, vtkm::Vec& pointNormal) const { if (numCells == 0) { pointNormal = vtkm::TypeTraits>::ZeroInitialization(); } else { auto result = faceNormals[0]; for (vtkm::IdComponent i = 1; i < numCells; ++i) { result += faceNormals[i]; } pointNormal = vtkm::Normal(result); } } }; template void Run( const CellSetType& cellset, const vtkm::cont::ArrayHandle, FaceNormalStorageType>& faceNormals, vtkm::cont::ArrayHandle>& pointNormals, DeviceAdapter) { vtkm::worklet::DispatcherMapTopology dispatcher; dispatcher.Invoke(cellset, faceNormals, pointNormals); } template void Run(const CellSetType& cellset, const vtkm::cont::DynamicArrayHandleBase& faceNormals, vtkm::cont::ArrayHandle>& pointNormals, DeviceAdapter) { vtkm::worklet::DispatcherMapTopology dispatcher; dispatcher.Invoke(cellset, faceNormals, pointNormals); } }; } } // vtkm::worklet #endif // vtk_m_worklet_SurfaceNormals_h