diff --git a/vtkm/CMakeLists.txt b/vtkm/CMakeLists.txt index 4c53caf3b..9627eaf52 100644 --- a/vtkm/CMakeLists.txt +++ b/vtkm/CMakeLists.txt @@ -35,6 +35,7 @@ set(headers ImplicitFunction.h List.h ListTag.h # Deprecated, replaced by List.h + LocatorGoulash.h LowerBound.h Math.h Matrix.h diff --git a/vtkm/LocatorGoulash.h b/vtkm/LocatorGoulash.h new file mode 100644 index 000000000..6b023769e --- /dev/null +++ b/vtkm/LocatorGoulash.h @@ -0,0 +1,47 @@ +//============================================================================ +// 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_LocatorGoulash_h +#define vtk_m_LocatorGoulash_h + +#include + +namespace vtkm +{ + +//Last cell object for each locator. +struct LastCellUniformGrid +{ +}; + +struct LastCellRectilinearGrid +{ +}; + +struct LastCellTwoLevel +{ + vtkm::Id CellId = -1; + vtkm::Id LeafIdx = -1; +}; + +struct LastCellBoundingHierarchy +{ + vtkm::Id CellId = -1; + vtkm::Id NodeIdx = -1; +}; + +using LastCellType = vtkm::exec::internal::Variant; + +} //namespace vtkm + + +#endif // vtk_m_LocatorGoulash_h diff --git a/vtkm/exec/CellLocatorBoundingIntervalHierarchy.h b/vtkm/exec/CellLocatorBoundingIntervalHierarchy.h index c6031c98f..d4c262d21 100644 --- a/vtkm/exec/CellLocatorBoundingIntervalHierarchy.h +++ b/vtkm/exec/CellLocatorBoundingIntervalHierarchy.h @@ -10,6 +10,7 @@ #ifndef vtk_m_exec_CellLocatorBoundingIntervalHierarchy_h #define vtk_m_exec_CellLocatorBoundingIntervalHierarchy_h +#include #include #include #include @@ -83,11 +84,63 @@ public: { } - VTKM_EXEC vtkm::ErrorCode FindCell(const vtkm::Vec3f& point, vtkm::Id& cellId, vtkm::Vec3f& parametric) const + { + vtkm::LastCellBoundingHierarchy lastCell; + return this->FindCellImpl(point, cellId, parametric, lastCell); + } + + VTKM_EXEC + vtkm::ErrorCode FindCell(const vtkm::Vec3f& point, + vtkm::Id& cellId, + vtkm::Vec3f& parametric, + vtkm::LastCellType& lastCell) const + { + if (lastCell.GetIndex() != lastCell.GetIndexOf()) + lastCell = vtkm::LastCellBoundingHierarchy(); + auto& lastCellBH = lastCell.Get(); + + cellId = -1; + + //Check the last cell. + if (lastCellBH.CellId != -1) + { + if (this->PointInCell(point, lastCellBH.CellId, parametric) == vtkm::ErrorCode::Success) + { + cellId = lastCellBH.CellId; + return vtkm::ErrorCode::Success; + } + } + + //Check the last leaf node. + if (lastCellBH.NodeIdx != -1) + { + const auto& node = this->Nodes.Get(lastCellBH.NodeIdx); + VTKM_ASSERT(node.ChildIndex < 0); //should be a leaf node. + + if (node.ChildIndex < 0) + { + VTKM_RETURN_ON_ERROR(this->FindInLeaf(point, parametric, node, cellId)); + if (cellId != -1) + { + lastCellBH.CellId = cellId; + return vtkm::ErrorCode::Success; + } + } + } + + //No fastpath. Do a full search. + return this->FindCellImpl(point, cellId, parametric, lastCellBH); + } + + VTKM_EXEC + vtkm::ErrorCode FindCellImpl(const vtkm::Vec3f& point, + vtkm::Id& cellId, + vtkm::Vec3f& parametric, + vtkm::LastCellBoundingHierarchy& lastCell) const { cellId = -1; vtkm::Id nodeIndex = 0; @@ -98,7 +151,8 @@ public: switch (state) { case FindCellState::EnterNode: - VTKM_RETURN_ON_ERROR(this->EnterNode(state, point, cellId, nodeIndex, parametric)); + VTKM_RETURN_ON_ERROR( + this->EnterNode(state, point, cellId, nodeIndex, parametric, lastCell)); break; case FindCellState::AscendFromNode: this->AscendFromNode(state, nodeIndex); @@ -141,7 +195,8 @@ private: const vtkm::Vec3f& point, vtkm::Id& cellId, vtkm::Id nodeIndex, - vtkm::Vec3f& parametric) const + vtkm::Vec3f& parametric, + vtkm::LastCellBoundingHierarchy& lastCell) const { VTKM_ASSERT(state == FindCellState::EnterNode); @@ -152,6 +207,11 @@ private: // In a leaf node. Look for a containing cell. VTKM_RETURN_ON_ERROR(this->FindInLeaf(point, parametric, node, cellId)); state = FindCellState::AscendFromNode; + if (cellId != -1) + { + lastCell.CellId = cellId; + lastCell.NodeIdx = nodeIndex; + } } else { @@ -230,26 +290,40 @@ private: const vtkm::exec::CellLocatorBoundingIntervalHierarchyNode& node, vtkm::Id& containingCellId) const { - using IndicesType = typename CellSetPortal::IndicesType; for (vtkm::Id i = node.Leaf.Start; i < node.Leaf.Start + node.Leaf.Size; ++i) { vtkm::Id cellId = this->CellIds.Get(i); - IndicesType cellPointIndices = this->CellSet.GetIndices(cellId); - vtkm::VecFromPortalPermute cellPoints(&cellPointIndices, - this->Coords); - bool found; - VTKM_RETURN_ON_ERROR(this->IsPointInCell( - point, parametric, this->CellSet.GetCellShape(cellId), cellPoints, found)); - if (found) + + if (this->PointInCell(point, cellId, parametric) == vtkm::ErrorCode::Success) { containingCellId = cellId; return vtkm::ErrorCode::Success; } } + containingCellId = -1; return vtkm::ErrorCode::Success; } + // template + VTKM_EXEC vtkm::ErrorCode PointInCell(const vtkm::Vec3f& point, + vtkm::Id& cellId, + vtkm::Vec3f& parametric) const + { + using IndicesType = typename CellSetPortal::IndicesType; + IndicesType cellPointIndices = this->CellSet.GetIndices(cellId); + vtkm::VecFromPortalPermute cellPoints(&cellPointIndices, + this->Coords); + auto cellShape = this->CellSet.GetCellShape(cellId); + bool isInside; + VTKM_RETURN_ON_ERROR(IsPointInCell(point, parametric, cellShape, cellPoints, isInside)); + + if (isInside && vtkm::exec::CellInside(parametric, cellShape)) + return vtkm::ErrorCode::Success; + + return vtkm::ErrorCode::CellNotFound; + } + template VTKM_EXEC static vtkm::ErrorCode IsPointInCell(const vtkm::Vec3f& point, vtkm::Vec3f& parametric, diff --git a/vtkm/exec/CellLocatorMultiplexer.h b/vtkm/exec/CellLocatorMultiplexer.h index d41343640..5dd9885f9 100644 --- a/vtkm/exec/CellLocatorMultiplexer.h +++ b/vtkm/exec/CellLocatorMultiplexer.h @@ -11,6 +11,7 @@ #define vtk_m_exec_CellLocatorMultiplexer_h #include +#include #include #include @@ -33,6 +34,16 @@ struct FindCellFunctor { return locator.FindCell(point, cellId, parametric); } + + template + VTKM_EXEC vtkm::ErrorCode operator()(Locator&& locator, + const vtkm::Vec3f& point, + vtkm::Id& cellId, + vtkm::Vec3f& parametric, + LastCellType& lastCell) const + { + return locator.FindCell(point, cellId, parametric, lastCell); + } }; } // namespace detail @@ -58,6 +69,15 @@ public: return this->Locators.CastAndCall(detail::FindCellFunctor{}, point, cellId, parametric); } + VTKM_EXEC vtkm::ErrorCode FindCell(const vtkm::Vec3f& point, + vtkm::Id& cellId, + vtkm::Vec3f& parametric, + LastCellType& lastCell) const + { + return this->Locators.CastAndCall( + detail::FindCellFunctor{}, point, cellId, parametric, lastCell); + } + VTKM_DEPRECATED(1.6, "Locators are no longer pointers. Use . operator.") VTKM_EXEC CellLocatorMultiplexer* operator->() { return this; } VTKM_DEPRECATED(1.6, "Locators are no longer pointers. Use . operator.") diff --git a/vtkm/exec/CellLocatorRectilinearGrid.h b/vtkm/exec/CellLocatorRectilinearGrid.h index 58bd09e55..ebb3852f9 100644 --- a/vtkm/exec/CellLocatorRectilinearGrid.h +++ b/vtkm/exec/CellLocatorRectilinearGrid.h @@ -11,6 +11,7 @@ #define vtkm_exec_celllocatorrectilineargrid_h #include +#include #include #include #include @@ -87,6 +88,15 @@ public: return inside; } + VTKM_EXEC + vtkm::ErrorCode FindCell(const vtkm::Vec3f& point, + vtkm::Id& cellId, + vtkm::Vec3f& parametric, + vtkm::LastCellType& vtkmNotUsed(lastCell)) const + { + return this->FindCell(point, cellId, parametric); + } + VTKM_EXEC vtkm::ErrorCode FindCell(const vtkm::Vec3f& point, vtkm::Id& cellId, diff --git a/vtkm/exec/CellLocatorTwoLevel.h b/vtkm/exec/CellLocatorTwoLevel.h index c30e4c6e4..5f4dd7f65 100644 --- a/vtkm/exec/CellLocatorTwoLevel.h +++ b/vtkm/exec/CellLocatorTwoLevel.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -155,10 +156,106 @@ public: VTKM_EXEC vtkm::ErrorCode FindCell(const FloatVec3& point, vtkm::Id& cellId, FloatVec3& parametric) const + { + vtkm::LastCellTwoLevel lastCell; + return this->FindCellImpl(point, cellId, parametric, lastCell); + } + + VTKM_EXEC + vtkm::ErrorCode FindCell(const FloatVec3& point, + vtkm::Id& cellId, + FloatVec3& parametric, + vtkm::LastCellType& lastCell) const + { + if (lastCell.GetIndex() != lastCell.GetIndexOf()) + lastCell = vtkm::LastCellTwoLevel(); + + auto& lastCell2L = lastCell.Get(); + + vtkm::Vec3f pc; + //See if point is inside the last cell. + if (lastCell2L.CellId != -1 && + this->PointInCell(point, lastCell2L.CellId, pc) == vtkm::ErrorCode::Success) + { + parametric = pc; + return vtkm::ErrorCode::Success; + } + + //See if it's in the last leaf. + if (lastCell2L.LeafIdx != -1 && + this->PointInLeaf(point, lastCell2L.LeafIdx, cellId, pc) == vtkm::ErrorCode::Success) + { + parametric = pc; + lastCell2L.CellId = cellId; + return vtkm::ErrorCode::Success; + } + + //Call the full point search. + return this->FindCellImpl(point, cellId, parametric, lastCell2L); + } + + VTKM_DEPRECATED(1.6, "Locators are no longer pointers. Use . operator.") + VTKM_EXEC CellLocatorTwoLevel* operator->() { return this; } + VTKM_DEPRECATED(1.6, "Locators are no longer pointers. Use . operator.") + VTKM_EXEC const CellLocatorTwoLevel* operator->() const { return this; } + +private: + VTKM_EXEC + vtkm::ErrorCode PointInCell(const vtkm::Vec3f& point, + const vtkm::Id& cid, + vtkm::Vec3f& parametric) const + { + auto indices = this->CellSet.GetIndices(cid); + auto pts = vtkm::make_VecFromPortalPermute(&indices, this->Coords); + vtkm::Vec3f pc; + bool inside; + auto status = PointInsideCell(point, this->CellSet.GetCellShape(cid), pts, pc, inside); + if (status == vtkm::ErrorCode::Success && inside) + { + parametric = pc; + return vtkm::ErrorCode::Success; + } + + return vtkm::ErrorCode::CellNotFound; + } + + VTKM_EXEC + vtkm::ErrorCode PointInLeaf(const FloatVec3& point, + const vtkm::Id& leafIdx, + vtkm::Id& cellId, + FloatVec3& parametric) const + { + vtkm::Id start = this->CellStartIndex.Get(leafIdx); + vtkm::Id end = start + this->CellCount.Get(leafIdx); + + for (vtkm::Id i = start; i < end; ++i) + { + vtkm::Vec3f pc; + + vtkm::Id cid = this->CellIds.Get(i); + if (this->PointInCell(point, cid, pc) == vtkm::ErrorCode::Success) + { + cellId = cid; + parametric = pc; + return vtkm::ErrorCode::Success; + } + } + + return vtkm::ErrorCode::CellNotFound; + } + + + VTKM_EXEC + vtkm::ErrorCode FindCellImpl(const FloatVec3& point, + vtkm::Id& cellId, + FloatVec3& parametric, + vtkm::LastCellTwoLevel& lastCell) const { using namespace vtkm::internal::cl_uniform_bins; cellId = -1; + lastCell.CellId = -1; + lastCell.LeafIdx = -1; DimVec3 binId3 = static_cast((point - this->TopLevel.Origin) / this->TopLevel.BinSize); if (binId3[0] >= 0 && binId3[0] < this->TopLevel.Dimensions[0] && binId3[1] >= 0 && @@ -180,37 +277,20 @@ public: leafId3 = vtkm::Max(DimVec3(0), vtkm::Min(ldim - DimVec3(1), leafId3)); vtkm::Id leafStart = this->LeafStartIndex.Get(binId); - vtkm::Id leafId = leafStart + ComputeFlatIndex(leafId3, leafGrid.Dimensions); + vtkm::Id leafIdx = leafStart + ComputeFlatIndex(leafId3, leafGrid.Dimensions); - vtkm::Id start = this->CellStartIndex.Get(leafId); - vtkm::Id end = start + this->CellCount.Get(leafId); - for (vtkm::Id i = start; i < end; ++i) + if (this->PointInLeaf(point, leafIdx, cellId, parametric) == vtkm::ErrorCode::Success) { - vtkm::Id cid = this->CellIds.Get(i); - auto indices = this->CellSet.GetIndices(cid); - auto pts = vtkm::make_VecFromPortalPermute(&indices, this->Coords); - FloatVec3 pc; - bool inside; - VTKM_RETURN_ON_ERROR( - PointInsideCell(point, this->CellSet.GetCellShape(cid), pts, pc, inside)); - if (inside) - { - cellId = cid; - parametric = pc; - return vtkm::ErrorCode::Success; - } + lastCell.CellId = cellId; + lastCell.LeafIdx = leafIdx; + + return vtkm::ErrorCode::Success; } } return vtkm::ErrorCode::CellNotFound; } - VTKM_DEPRECATED(1.6, "Locators are no longer pointers. Use . operator.") - VTKM_EXEC CellLocatorTwoLevel* operator->() { return this; } - VTKM_DEPRECATED(1.6, "Locators are no longer pointers. Use . operator.") - VTKM_EXEC const CellLocatorTwoLevel* operator->() const { return this; } - -private: vtkm::internal::cl_uniform_bins::Grid TopLevel; ReadPortal LeafDimensions; diff --git a/vtkm/exec/CellLocatorUniformGrid.h b/vtkm/exec/CellLocatorUniformGrid.h index f78b9fb11..a36677558 100644 --- a/vtkm/exec/CellLocatorUniformGrid.h +++ b/vtkm/exec/CellLocatorUniformGrid.h @@ -11,6 +11,7 @@ #define vtkm_exec_celllocatoruniformgrid_h #include +#include #include #include #include @@ -55,6 +56,15 @@ public: return inside; } + VTKM_EXEC + vtkm::ErrorCode FindCell(const vtkm::Vec3f& point, + vtkm::Id& cellId, + vtkm::Vec3f& parametric, + vtkm::LastCellType& vtkmNotUsed(lastCell)) const + { + return this->FindCell(point, cellId, parametric); + } + VTKM_EXEC vtkm::ErrorCode FindCell(const vtkm::Vec3f& point, vtkm::Id& cellId,