//============================================================================ // 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_RemoveUnusedPoints_h #define vtk_m_worklet_RemoveUnusedPoints_h #include #include #include #include #include #include #include #include #include #include namespace vtkm { namespace worklet { /// A collection of worklets used to identify which points are used by at least /// one cell and then remove the points that are not used by any cells. The /// class containing these worklets can be used to manage running these /// worklets, building new cell sets, and redefine field arrays. /// class RemoveUnusedPoints { public: /// A worklet that creates a mask of used points (the first step in removing /// unused points). Given an array of point indices (taken from the /// connectivity of a CellSetExplicit) and an array mask initialized to 0, /// writes a 1 at the index of every point referenced by a cell. /// struct GeneratePointMask : public vtkm::worklet::WorkletMapField { using ControlSignature = void(FieldIn pointIndices, WholeArrayInOut pointMask); using ExecutionSignature = void(_1, _2); template VTKM_EXEC void operator()(vtkm::Id pointIndex, const PointMaskPortalType& pointMask) const { pointMask.Set(pointIndex, 1); } }; /// A worklet that takes an array of point indices (taken from the /// connectivity of a CellSetExplicit) and an array that functions as a map /// from the original indices to new indices, creates a new array with the /// new mapped indices. /// struct TransformPointIndices : public vtkm::worklet::WorkletMapField { using ControlSignature = void(FieldIn pointIndex, WholeArrayIn indexMap, FieldOut mappedPoints); using ExecutionSignature = _3(_1, _2); template VTKM_EXEC vtkm::Id operator()(vtkm::Id pointIndex, const IndexMapPortalType& indexPortal) const { return indexPortal.Get(pointIndex); } }; public: VTKM_CONT RemoveUnusedPoints() {} template VTKM_CONT RemoveUnusedPoints( const vtkm::cont::CellSetExplicit& inCellSet) { this->FindPointsStart(); this->FindPoints(inCellSet); this->FindPointsEnd(); } /// Get this class ready for identifying the points used by cell sets. /// VTKM_CONT void FindPointsStart() { this->MaskArray.ReleaseResources(); } /// Analyze the given cell set to find all points that are used. Unused /// points are those that are not found in any cell sets passed to this /// method. /// template VTKM_CONT void FindPoints( const vtkm::cont::CellSetExplicit& inCellSet) { if (this->MaskArray.GetNumberOfValues() < 1) { // Initialize mask array to 0. vtkm::cont::ArrayCopy( vtkm::cont::ArrayHandleConstant(0, inCellSet.GetNumberOfPoints()), this->MaskArray); } VTKM_ASSERT(this->MaskArray.GetNumberOfValues() == inCellSet.GetNumberOfPoints()); vtkm::worklet::DispatcherMapField dispatcher; dispatcher.Invoke(inCellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()), this->MaskArray); } /// Compile the information collected from calls to \c FindPointsInCellSet to /// ready this class for mapping cell sets and fields. /// VTKM_CONT void FindPointsEnd() { this->PointScatter.reset(new vtkm::worklet::ScatterCounting(this->MaskArray, true)); this->MaskArray.ReleaseResources(); } /// \brief Map cell indices /// /// Given a cell set (typically the same one passed to the constructor) /// returns a new cell set with cell points transformed to use the indices of /// the new reduced point arrays. /// template VTKM_CONT vtkm::cont::CellSetExplicit MapCellSet(const vtkm::cont::CellSetExplicit& inCellSet) const { VTKM_ASSERT(this->PointScatter); return MapCellSet(inCellSet, this->PointScatter->GetInputToOutputMap(), this->PointScatter->GetOutputToInputMap().GetNumberOfValues()); } /// \brief Map cell indices /// /// Given a cell set (typically the same one passed to the constructor) and /// an array that maps point indices from an old set of indices to a new set, /// returns a new cell set with cell points transformed to use the indices of /// the new reduced point arrays. /// /// This helper method can be used by external items that do similar operations /// that remove points or otherwise rearange points in a cell set. If points /// were removed by calling \c FindPoints, then you should use the other form /// of \c MapCellSet. /// template VTKM_CONT static vtkm::cont::CellSetExplicit MapCellSet( const vtkm::cont::CellSetExplicit& inCellSet, const vtkm::cont::ArrayHandle& inputToOutputPointMap, vtkm::Id numberOfPoints) { using VisitTopology = vtkm::TopologyElementTagCell; using IncidentTopology = vtkm::TopologyElementTagPoint; using NewConnectivityStorage = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG; vtkm::cont::ArrayHandle newConnectivityArray; vtkm::worklet::DispatcherMapField dispatcher; dispatcher.Invoke(inCellSet.GetConnectivityArray(VisitTopology(), IncidentTopology()), inputToOutputPointMap, newConnectivityArray); vtkm::cont::CellSetExplicit outCellSet; outCellSet.Fill(numberOfPoints, inCellSet.GetShapesArray(VisitTopology(), IncidentTopology()), newConnectivityArray, inCellSet.GetOffsetsArray(VisitTopology(), IncidentTopology())); return outCellSet; } /// \brief Maps a point field from the original points to the new reduced points /// /// Given an array handle that holds the values for a point field of the /// original data set, returns a new array handle containing field values /// rearranged to the new indices of the reduced point set. /// /// This version of point mapping performs a shallow copy by using a /// permutation array. /// template VTKM_CONT vtkm::cont::ArrayHandlePermutation, InArrayHandle> MapPointFieldShallow(const InArrayHandle& inArray) const { VTKM_IS_ARRAY_HANDLE(InArrayHandle); VTKM_ASSERT(this->PointScatter); return vtkm::cont::make_ArrayHandlePermutation(this->PointScatter->GetOutputToInputMap(), inArray); } private: struct MapPointFieldDeepFunctor { template VTKM_CONT void operator()(const vtkm::cont::ArrayHandle& inArray, vtkm::cont::ArrayHandle& outArray, const RemoveUnusedPoints& self) const { self.MapPointFieldDeep(inArray, outArray); } template VTKM_CONT void operator()(const vtkm::cont::ArrayHandle& inArray, vtkm::cont::UnknownArrayHandle& outHolder, const RemoveUnusedPoints& self) const { vtkm::cont::ArrayHandle outArray; (*this)(inArray, outArray, self); outHolder = vtkm::cont::UnknownArrayHandle{ outArray }; } VTKM_DEPRECATED_SUPPRESS_BEGIN template VTKM_CONT void operator()(const vtkm::cont::ArrayHandle& inArray, vtkm::cont::VariantArrayHandleCommon& outHolder, const RemoveUnusedPoints& self) const { vtkm::cont::ArrayHandle outArray; (*this)(inArray, outArray, self); outHolder = vtkm::cont::VariantArrayHandleCommon{ outArray }; } VTKM_DEPRECATED_SUPPRESS_END }; public: ///@{ /// \brief Maps a point field from the original points to the new reduced points /// /// Given an array handle that holds the values for a point field of the /// original data set, returns a new array handle containing field values /// rearranged to the new indices of the reduced point set. /// /// This version of point mapping performs a deep copy into the destination /// array provided. /// template VTKM_CONT void MapPointFieldDeep(const vtkm::cont::ArrayHandle& inArray, vtkm::cont::ArrayHandle& outArray) const { vtkm::cont::ArrayCopy(this->MapPointFieldShallow(inArray), outArray); } template VTKM_CONT vtkm::cont::ArrayHandle MapPointFieldDeep( const vtkm::cont::ArrayHandle& inArray) const { vtkm::cont::ArrayHandle outArray; this->MapPointFieldDeep(inArray, outArray); return outArray; } template VTKM_CONT void MapPointFieldDeep( const vtkm::cont::UncertainArrayHandle& inArray, OutArrayHandle& outArray) const { vtkm::cont::CastAndCall(inArray, MapPointFieldDeepFunctor{}, outArray, *this); } template VTKM_CONT vtkm::cont::UncertainArrayHandle MapPointFieldDeep( const vtkm::cont::UncertainArrayHandle& inArray) const { vtkm::cont::UncertainArrayHandle outArray; vtkm::cont::CastAndCall(inArray, MapPointFieldDeepFunctor{}, outArray, *this); return outArray; } VTKM_DEPRECATED_SUPPRESS_BEGIN template VTKM_CONT void MapPointFieldDeep(const vtkm::cont::VariantArrayHandleBase& inArray, OutArrayHandle& outArray) const { vtkm::cont::CastAndCall(inArray, MapPointFieldDeepFunctor{}, outArray, *this); } template VTKM_CONT vtkm::cont::VariantArrayHandleBase MapPointFieldDeep( const vtkm::cont::VariantArrayHandleBase& inArray) const { vtkm::cont::VariantArrayHandleBase outArray; vtkm::cont::CastAndCall(inArray, MapPointFieldDeepFunctor{}, outArray, *this); return outArray; } VTKM_DEPRECATED_SUPPRESS_END ///@} const vtkm::worklet::ScatterCounting& GetPointScatter() const { return *this->PointScatter.get(); } private: vtkm::cont::ArrayHandle MaskArray; /// Manages how the original point indices map to the new point indices. /// std::shared_ptr PointScatter; }; } } // namespace vtkm::worklet #endif //vtk_m_worklet_RemoveUnusedPoints_h