Skip to content

Commit 4d6ac33

Browse files
committed
using half-open intervals for GridCell boundary checks
1 parent 77f5a19 commit 4d6ac33

2 files changed

Lines changed: 12 additions & 5 deletions

File tree

src/graphomotor/core/models.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ def contains_points(self, points: pd.DataFrame) -> bool:
167167
"""Check if a stroke belongs to this cell based on its centroid.
168168
169169
Computes the centroid (mean x, mean y) of the provided points and checks
170-
whether it falls within the cell boundaries (inclusive).
170+
whether it falls within the cell boundaries. Uses half-open intervals
171+
[min, max) to prevent double-assignment on shared grid edges.
171172
172173
Args:
173174
points: DataFrame with 'x' and 'y' columns representing a stroke.
@@ -178,8 +179,8 @@ def contains_points(self, points: pd.DataFrame) -> bool:
178179
centroid_x = points["x"].mean()
179180
centroid_y = points["y"].mean()
180181
return (
181-
self.x_min <= centroid_x <= self.x_max
182-
and self.y_min <= centroid_y <= self.y_max
182+
self.x_min <= centroid_x < self.x_max
183+
and self.y_min <= centroid_y < self.y_max
183184
)
184185

185186

tests/unit/test_grid_cell.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,18 @@ def test_stroke_centroid_outside_cell(cell: models.GridCell) -> None:
4747
assert not cell.contains_points(stroke_points)
4848

4949

50-
def test_stroke_centroid_on_boundary(cell: models.GridCell) -> None:
51-
"""Stroke whose centroid lands exactly on the cell boundary should be contained."""
50+
def test_stroke_centroid_on_lower_boundary(cell: models.GridCell) -> None:
51+
"""Stroke whose centroid lands on the lower/left boundary (min) is included."""
5252
stroke_points = pd.DataFrame({"x": [10.0, 10.0], "y": [88.0, 89.0]})
5353
assert cell.contains_points(stroke_points)
5454

5555

56+
def test_stroke_centroid_on_upper_boundary(cell: models.GridCell) -> None:
57+
"""Stroke whose centroid lands on the upper/right boundary (max) is excluded."""
58+
stroke_points = pd.DataFrame({"x": [17.0, 18.0], "y": [97.0, 97.0]})
59+
assert not cell.contains_points(stroke_points)
60+
61+
5662
def test_stroke_points_span_outside_but_centroid_inside(
5763
cell: models.GridCell,
5864
) -> None:

0 commit comments

Comments
 (0)