From 1d71ce34735a59408450c88702a498315d774acd Mon Sep 17 00:00:00 2001 From: Vamsi-2581 <245859299+Vamsi-2581@users.noreply.github.com> Date: Fri, 23 Oct 2026 10:19:50 +0530 Subject: [PATCH 1/2] fix(spatial): normalize rounded SE2 period boundary --- src/pgraph/PGraph.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pgraph/PGraph.py b/src/pgraph/PGraph.py index e0fa4de0..72e1c5ac 100644 --- a/src/pgraph/PGraph.py +++ b/src/pgraph/PGraph.py @@ -2058,14 +2058,17 @@ def prepare(q: NDArray) -> NDArray | None: # noqa: F811 return None # far outside the data: let the caller do it if weight == 0: return xy - return np.r_[xy, np.mod(weight * q[2], period)] + angle = np.mod(weight * q[2], period) + if angle >= period: + angle = 0.0 + return np.r_[xy, angle] if weight == 0: tree = spatial.cKDTree(points[:, :2] - shift, boxsize=[size, size]) else: - data = np.column_stack( - [points[:, :2] - shift, np.mod(weight * points[:, 2], period)] - ) + angle = np.mod(weight * points[:, 2], period) + angle[angle >= period] = 0.0 + data = np.column_stack([points[:, :2] - shift, angle]) tree = spatial.cKDTree(data, boxsize=[size, size, period]) self._kdtree = _KDTree(tree, index, p, prepare) From ddf1d07110204f06107d6272a66dc1c0bc92f34e Mon Sep 17 00:00:00 2001 From: Vamsi-2581 <245859299+Vamsi-2581@users.noreply.github.com> Date: Fri, 23 Oct 2026 10:20:40 +0530 Subject: [PATCH 2/2] test(spatial): cover SE2 period rounding boundary --- tests/test_spatial_index.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_spatial_index.py b/tests/test_spatial_index.py index b4d98167..8d2bf281 100644 --- a/tests/test_spatial_index.py +++ b/tests/test_spatial_index.py @@ -168,6 +168,22 @@ def test_a_query_across_the_angle_wrap(self): self.assertEqual(v.name, "a") self.assertAlmostEqual(d, 0.2) + def test_a_negative_angle_that_rounds_to_the_period(self): + for metric in ("SE2", SE2Metric(0.3)): + with self.subTest(metric=metric): + for angle_is_in_graph in (True, False): + with self.subTest(angle_is_in_graph=angle_is_in_graph): + g = UGraph(dim=3, metric=metric) + boundary_angle = -1e-17 if angle_is_in_graph else 0.0 + g.add_vertex([0.0, 0.0, boundary_angle], name="boundary") + g.add_vertex([0.0, 0.0, 0.25], name="other") + g.build_kdtree() + + query_angle = 0.0 if angle_is_in_graph else -1e-17 + query = [0.0, 0.0, query_angle] + self.assertEqual(g.closest(query)[0].name, "boundary") + self.assertEqual(g.near(query, 1e-12)[0][0].name, "boundary") + def test_a_query_far_outside_is_still_right(self): g, P = points_graph(UGraph, dim=3, metric=SE2Metric(1.0)) g.build_kdtree()