//============================================================================ // 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. //============================================================================ #ifndef vtk_m_worklet_RemoveDegeneratePolygons_h #define vtk_m_worklet_RemoveDegeneratePolygons_h #include #include #include #include #include #include #include #include namespace vtkm { namespace worklet { struct RemoveDegenerateCells { struct IdentifyDegenerates : vtkm::worklet::WorkletVisitCellsWithPoints { using ControlSignature = void(CellSetIn, FieldOutCell); using ExecutionSignature = _2(CellShape, PointIndices); using InputDomain = _1; template VTKM_EXEC bool CheckForDimensionality(vtkm::CellTopologicalDimensionsTag, CellShapeTag, PointVecType&& pointIds) const { const vtkm::IdComponent numPoints = pointIds.GetNumberOfComponents(); vtkm::IdComponent numUnduplicatedPoints = 0; for (vtkm::IdComponent localPointId = 0; localPointId < numPoints; ++localPointId) { ++numUnduplicatedPoints; if (numUnduplicatedPoints >= dimensionality + 1) { return true; } while (((localPointId < numPoints - 1) && (pointIds[localPointId] == pointIds[localPointId + 1])) || ((localPointId == numPoints - 1) && (pointIds[localPointId] == pointIds[0]))) { // Skip over any repeated points. Assume any repeated points are adjacent. ++localPointId; } } return false; } template VTKM_EXEC bool CheckForDimensionality(vtkm::CellTopologicalDimensionsTag<0>, CellShapeTag, PointVecType&&) { return true; } template VTKM_EXEC bool CheckForDimensionality(vtkm::CellTopologicalDimensionsTag<3>, CellShapeTag shape, PointVecType&& pointIds) { const vtkm::IdComponent numFaces = vtkm::exec::CellFaceNumberOfFaces(shape, *this); vtkm::Id numValidFaces = 0; for (vtkm::IdComponent faceId = 0; faceId < numFaces; ++faceId) { if (this->CheckForDimensionality( vtkm::CellTopologicalDimensionsTag<2>(), vtkm::CellShapeTagPolygon(), pointIds)) { ++numValidFaces; if (numValidFaces > 2) { return true; } } } return false; } template VTKM_EXEC bool operator()(CellShapeTag shape, const PointIdVec& pointIds) const { using Traits = vtkm::CellTraits; return this->CheckForDimensionality( typename Traits::TopologicalDimensionsTag(), shape, pointIds); } template VTKM_EXEC bool operator()(vtkm::CellShapeTagGeneric shape, PointIdVec&& pointIds) const { bool passCell = true; switch (shape.Id) { vtkmGenericCellShapeMacro(passCell = (*this)(CellShapeTag(), pointIds)); default: // Raise an error for unknown cell type? Pass if we don't know. passCell = true; } return passCell; } }; template vtkm::cont::CellSetExplicit<> Run(const CellSetType& cellSet) { vtkm::cont::ArrayHandle passFlags; DispatcherMapTopology dispatcher; dispatcher.Invoke(cellSet, passFlags); vtkm::cont::ArrayHandleCounting indices = vtkm::cont::make_ArrayHandleCounting(vtkm::Id(0), vtkm::Id(1), passFlags.GetNumberOfValues()); vtkm::cont::Algorithm::CopyIf( vtkm::cont::ArrayHandleIndex(passFlags.GetNumberOfValues()), passFlags, this->ValidCellIds); vtkm::cont::CellSetPermutation permutation(this->ValidCellIds, cellSet); vtkm::cont::CellSetExplicit<> output; vtkm::worklet::CellDeepCopy::Run(permutation, output); return output; } struct CallWorklet { template void operator()(const CellSetType& cellSet, RemoveDegenerateCells& self, vtkm::cont::CellSetExplicit<>& output) const { output = self.Run(cellSet); } }; template vtkm::cont::CellSetExplicit<> Run(const vtkm::cont::DynamicCellSetBase& cellSet) { vtkm::cont::CellSetExplicit<> output; cellSet.CastAndCall(CallWorklet(), *this, output); return output; } template vtkm::cont::ArrayHandle ProcessCellField( const vtkm::cont::ArrayHandle in) const { // Use a temporary permutation array to simplify the mapping: auto tmp = vtkm::cont::make_ArrayHandlePermutation(this->ValidCellIds, in); // Copy into an array with default storage: vtkm::cont::ArrayHandle result; vtkm::cont::ArrayCopy(tmp, result); return result; } vtkm::cont::ArrayHandle GetValidCellIds() const { return this->ValidCellIds; } private: vtkm::cont::ArrayHandle ValidCellIds; }; } } #endif //vtk_m_worklet_RemoveDegeneratePolygons_h