Spaces:
Running on Zero
Running on Zero
| from dataclasses import dataclass | |
| from numpy import ndarray | |
| from typing import Optional | |
| import numpy as np | |
| class Voxel(): | |
| # coordinates of mesh | |
| coords: ndarray | |
| # origin of the voxel | |
| origin: ndarray | |
| # grid size | |
| voxel_size: float | |
| # a boolen array | |
| _voxel: Optional[ndarray]=None | |
| def voxel(self) -> ndarray: | |
| if self._voxel is None: | |
| max_coords = np.max(self.coords, axis=0) | |
| shape = tuple(max_coords + 1) | |
| voxel = np.zeros(shape, dtype=bool) | |
| voxel[tuple(self.coords.T)] = True | |
| self._voxel = voxel | |
| return self._voxel | |
| def pc(self) -> ndarray: | |
| return self.origin + (self.coords + 0.5) * self.voxel_size | |
| def projection_fill(self, rigid: bool=True): | |
| """ | |
| Fill up holes in the voxel. | |
| """ | |
| grids = np.indices(self.voxel.shape) | |
| x_coord = grids[0, ...] | |
| y_coord = grids[1, ...] | |
| z_coord = grids[2, ...] | |
| INF = 2147483647 | |
| x_tmp = x_coord.copy() | |
| x_tmp[~self.voxel] = INF | |
| x_min = x_tmp.min(axis=0) | |
| x_tmp[~self.voxel] = -1 | |
| x_max = x_tmp.max(axis=0) | |
| y_tmp = y_coord.copy() | |
| y_tmp[~self.voxel] = INF | |
| y_min = y_tmp.min(axis=1) | |
| y_tmp[~self.voxel] = -1 | |
| y_max = y_tmp.max(axis=1) | |
| z_tmp = z_coord.copy() | |
| z_tmp[~self.voxel] = INF | |
| z_min = z_tmp.min(axis=2) | |
| z_tmp[~self.voxel] = -1 | |
| z_max = z_tmp.max(axis=2) | |
| in_x = (x_coord >= x_min[None, :, :]) & (x_coord <= x_max[None, :, :]) | |
| in_y = (y_coord >= y_min[:, None, :]) & (y_coord <= y_max[:, None, :]) | |
| in_z = (z_coord >= z_min[:, :, None]) & (z_coord <= z_max[:, :, None]) | |
| count = in_x.astype(int) + in_y.astype(int) + in_z.astype(int) | |
| fill_mask = count >= (3 if rigid else 2) | |
| self._voxel = self.voxel | fill_mask | |
| x, y, z = np.where(self.voxel) | |
| self.coords = np.stack([x, y, z], axis=1) | |
| def inside(self, points: ndarray) -> ndarray: | |
| if points.ndim == 1: | |
| points = points[None, :] | |
| points = np.asarray(points) | |
| idx = np.floor((points - self.origin) / self.voxel_size).astype(int) | |
| invalid = ( | |
| (idx < 0).any(axis=1) | | |
| (idx >= np.array(self.voxel.shape)).any(axis=1) | |
| ) | |
| result = np.zeros(len(points), dtype=bool) | |
| valid_idx = np.where(~invalid)[0] | |
| valid_voxel_idx = idx[valid_idx] | |
| result[valid_idx] = self.voxel[valid_voxel_idx[:, 0], valid_voxel_idx[:, 1], valid_voxel_idx[:, 2]] | |
| return result |