Spaces:
Running
Running
| """Selection / geometry helpers. | |
| This module contains small, backend-agnostic utilities used by selection endpoints | |
| (e.g. lasso selection over 2D embeddings). | |
| """ | |
| from __future__ import annotations | |
| import numpy as np | |
| def points_in_polygon(points_xy: np.ndarray, polygon_xy: np.ndarray) -> np.ndarray: | |
| """Vectorized point-in-polygon (even-odd rule / ray casting). | |
| Args: | |
| points_xy: Array of shape (m, 2) with point coordinates. | |
| polygon_xy: Array of shape (n, 2) with polygon vertices. | |
| Returns: | |
| Boolean mask of length m, True where point lies inside polygon. | |
| Notes: | |
| Boundary points may be classified as outside depending on floating point | |
| ties (common for lasso selection tools). | |
| """ | |
| if polygon_xy.shape[0] < 3: | |
| return np.zeros((points_xy.shape[0],), dtype=bool) | |
| x = points_xy[:, 0] | |
| y = points_xy[:, 1] | |
| poly_x = polygon_xy[:, 0] | |
| poly_y = polygon_xy[:, 1] | |
| inside = np.zeros((points_xy.shape[0],), dtype=bool) | |
| j = polygon_xy.shape[0] - 1 | |
| for i in range(polygon_xy.shape[0]): | |
| xi = poly_x[i] | |
| yi = poly_y[i] | |
| xj = poly_x[j] | |
| yj = poly_y[j] | |
| # Half-open y-interval to avoid double-counting vertices. | |
| intersects = (yi > y) != (yj > y) | |
| denom = yj - yi | |
| # denom == 0 => intersects is always False; add tiny epsilon to avoid warnings. | |
| x_intersect = (xj - xi) * (y - yi) / (denom + 1e-30) + xi | |
| inside ^= intersects & (x < x_intersect) | |
| j = i | |
| return inside | |