|
|
|
|
|
import numpy as np |
|
|
|
cimport cython |
|
cimport numpy as np |
|
from libc.math cimport ceil, floor |
|
from libcpp.vector cimport vector |
|
|
|
|
|
cdef class TriangleHash: |
|
cdef vector[vector[int]] spatial_hash |
|
cdef int resolution |
|
|
|
def __cinit__(self, double[:, :, :] triangles, int resolution): |
|
self.spatial_hash.resize(resolution * resolution) |
|
self.resolution = resolution |
|
self._build_hash(triangles) |
|
|
|
@cython.boundscheck(False) |
|
@cython.wraparound(False) |
|
cdef int _build_hash(self, double[:, :, :] triangles): |
|
assert(triangles.shape[1] == 3) |
|
assert(triangles.shape[2] == 2) |
|
|
|
cdef int n_tri = triangles.shape[0] |
|
cdef int bbox_min[2] |
|
cdef int bbox_max[2] |
|
|
|
cdef int i_tri, j, x, y |
|
cdef int spatial_idx |
|
|
|
for i_tri in range(n_tri): |
|
|
|
for j in range(2): |
|
bbox_min[j] = <int> min( |
|
triangles[i_tri, 0, j], triangles[i_tri, 1, j], triangles[i_tri, 2, j] |
|
) |
|
bbox_max[j] = <int> max( |
|
triangles[i_tri, 0, j], triangles[i_tri, 1, j], triangles[i_tri, 2, j] |
|
) |
|
bbox_min[j] = min(max(bbox_min[j], 0), self.resolution - 1) |
|
bbox_max[j] = min(max(bbox_max[j], 0), self.resolution - 1) |
|
|
|
|
|
for x in range(bbox_min[0], bbox_max[0] + 1): |
|
for y in range(bbox_min[1], bbox_max[1] + 1): |
|
spatial_idx = self.resolution * x + y |
|
self.spatial_hash[spatial_idx].push_back(i_tri) |
|
|
|
@cython.boundscheck(False) |
|
@cython.wraparound(False) |
|
cpdef query(self, double[:, :] points): |
|
assert(points.shape[1] == 2) |
|
cdef int n_points = points.shape[0] |
|
|
|
cdef vector[int] points_indices |
|
cdef vector[int] tri_indices |
|
|
|
|
|
|
|
cdef int i_point, k, x, y |
|
cdef int spatial_idx |
|
|
|
for i_point in range(n_points): |
|
x = int(points[i_point, 0]) |
|
y = int(points[i_point, 1]) |
|
if not (0 <= x < self.resolution and 0 <= y < self.resolution): |
|
continue |
|
|
|
spatial_idx = self.resolution * x + y |
|
for i_tri in self.spatial_hash[spatial_idx]: |
|
points_indices.push_back(i_point) |
|
tri_indices.push_back(i_tri) |
|
|
|
points_indices_np = np.zeros(points_indices.size(), dtype=np.int32) |
|
tri_indices_np = np.zeros(tri_indices.size(), dtype=np.int32) |
|
|
|
cdef int[:] points_indices_view = points_indices_np |
|
cdef int[:] tri_indices_view = tri_indices_np |
|
|
|
for k in range(points_indices.size()): |
|
points_indices_view[k] = points_indices[k] |
|
|
|
for k in range(tri_indices.size()): |
|
tri_indices_view[k] = tri_indices[k] |
|
|
|
return points_indices_np, tri_indices_np |
|
|