From e473cb4bbc294a16efaadde4a9b8365f8641e765 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Wed, 10 Jul 2019 08:35:45 -0600 Subject: [PATCH 1/2] Fix PointLocatorUniformGrid for points on boundary When creating the search structures in PointLocatorUniformGrid, a point outside the boundary would be given an invalid bin id. These points could never be found. Generally, this is not a big deal for points outside of the boundary, but it could be a problem for points on the boundary. A point on the boundary could be taken as outside the boundary. Since the boundary is chosen from limits of the points, some will almost always be on the boundary. Fix this problem by clamping all points to the nearest valid bin. This could cause a problem if the user has selected a boundary excluding a lot of points. All those points could be grouped to the same edge bins, but that is probably not a great idea anyway. --- vtkm/cont/PointLocatorUniformGrid.cxx | 2 ++ .../testing/TestingPointLocatorUniformGrid.h | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/vtkm/cont/PointLocatorUniformGrid.cxx b/vtkm/cont/PointLocatorUniformGrid.cxx index 7070e6b74..524f5e63c 100644 --- a/vtkm/cont/PointLocatorUniformGrid.cxx +++ b/vtkm/cont/PointLocatorUniformGrid.cxx @@ -48,6 +48,8 @@ public: VTKM_EXEC void operator()(const CoordVecType& coord, IdType& label) const { vtkm::Vec ijk = (coord - Min) / Dxdydz; + ijk = vtkm::Max(ijk, vtkm::Id3(0)); + ijk = vtkm::Min(ijk, this->Dims - vtkm::Id3(1)); label = ijk[0] + ijk[1] * Dims[0] + ijk[2] * Dims[0] * Dims[1]; } diff --git a/vtkm/cont/testing/TestingPointLocatorUniformGrid.h b/vtkm/cont/testing/TestingPointLocatorUniformGrid.h index 284a2ab1e..7a647c9e4 100644 --- a/vtkm/cont/testing/TestingPointLocatorUniformGrid.h +++ b/vtkm/cont/testing/TestingPointLocatorUniformGrid.h @@ -108,6 +108,16 @@ public: { coordi.push_back(vtkm::make_Vec(dr(dre), dr(dre), dr(dre))); } + // Add a point to each corner to test the case where points might slip out + // of the range by epsilon + coordi.push_back(vtkm::make_Vec(00.0f, 00.0f, 00.0f)); + coordi.push_back(vtkm::make_Vec(00.0f, 10.0f, 00.0f)); + coordi.push_back(vtkm::make_Vec(10.0f, 00.0f, 00.0f)); + coordi.push_back(vtkm::make_Vec(10.0f, 10.0f, 00.0f)); + coordi.push_back(vtkm::make_Vec(00.0f, 00.0f, 10.0f)); + coordi.push_back(vtkm::make_Vec(00.0f, 10.0f, 10.0f)); + coordi.push_back(vtkm::make_Vec(10.0f, 00.0f, 10.0f)); + coordi.push_back(vtkm::make_Vec(10.0f, 10.0f, 10.0f)); auto coordi_Handle = vtkm::cont::make_ArrayHandle(coordi); vtkm::cont::CoordinateSystem coord("points", coordi_Handle); @@ -126,6 +136,15 @@ public: { qcVec.push_back(vtkm::make_Vec(dr(dre), dr(dre), dr(dre))); } + // Test near each corner to make sure that corner gets included + qcVec.push_back(vtkm::make_Vec(0.01f, 0.01f, 0.01f)); + qcVec.push_back(vtkm::make_Vec(0.01f, 9.99f, 0.01f)); + qcVec.push_back(vtkm::make_Vec(9.99f, 0.01f, 0.01f)); + qcVec.push_back(vtkm::make_Vec(9.99f, 9.99f, 0.01f)); + qcVec.push_back(vtkm::make_Vec(0.01f, 0.01f, 9.991f)); + qcVec.push_back(vtkm::make_Vec(0.01f, 9.99f, 9.99f)); + qcVec.push_back(vtkm::make_Vec(9.99f, 0.01f, 9.99f)); + qcVec.push_back(vtkm::make_Vec(9.99f, 9.99f, 9.99f)); auto qc_Handle = vtkm::cont::make_ArrayHandle(qcVec); vtkm::cont::ArrayHandle nnId_Handle; From 461f87dbc8608ba18ddf0d5399fecf942da561db Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Wed, 10 Jul 2019 09:52:49 -0600 Subject: [PATCH 2/2] Fix issues with PointLocatorUniformGrid not finding all points There was a known issue where PointLocatorUniformGrid would quickly quit once it found a point. Instead, look at one more level of bins just in case there is a closer one near the boundary. (Still not guaranteed, but likely.) Also, fix a typo that caused some bins in the y and z direction to not be searched. --- vtkm/exec/PointLocatorUniformGrid.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/vtkm/exec/PointLocatorUniformGrid.h b/vtkm/exec/PointLocatorUniformGrid.h index 05c746f9f..ec28d3568 100644 --- a/vtkm/exec/PointLocatorUniformGrid.h +++ b/vtkm/exec/PointLocatorUniformGrid.h @@ -80,10 +80,16 @@ public: // TODO: This might stop looking before the absolute nearest neighbor is found. vtkm::Id maxLevel = vtkm::Max(vtkm::Max(this->Dims[0], this->Dims[1]), this->Dims[2]); - for (vtkm::Id level = 1; (nearestNeighborId < 0) && (level < maxLevel); ++level) + vtkm::Id level; + for (level = 1; (nearestNeighborId < 0) && (level < maxLevel); ++level) { this->FindInBox(queryPoint, ijk, level, nearestNeighborId, distance2); } + + // Search one more level out. This is still not guaranteed to find the closest point + // in all cases (past level 2), but it will catch most cases where the closest point + // is just on the other side of a cell boundary. + this->FindInBox(queryPoint, ijk, level, nearestNeighborId, distance2); } private: @@ -143,7 +149,7 @@ private: if ((boxCenter[1] + level) < this->Dims[1]) { this->FindInYPlane( - queryPoint, boxCenter - vtkm::Id3(0, level, 0), level, nearestNeighborId, nearestDistance2); + queryPoint, boxCenter + vtkm::Id3(0, level, 0), level, nearestNeighborId, nearestDistance2); } if ((boxCenter[2] - level) >= 0) @@ -154,7 +160,7 @@ private: if ((boxCenter[2] + level) < this->Dims[2]) { this->FindInZPlane( - queryPoint, boxCenter - vtkm::Id3(0, 0, level), level, nearestNeighborId, nearestDistance2); + queryPoint, boxCenter + vtkm::Id3(0, 0, level), level, nearestNeighborId, nearestDistance2); } }