diff --git a/field.py b/field.py index 7c184c4..8099cce 100644 --- a/field.py +++ b/field.py @@ -659,7 +659,6 @@ class Features3d: # Assign basic properties to class variables self.origin = np.array(origin,dtype=np.float) self.spacing = np.array(spacing,dtype=np.float) - self.dimensions = np.array(input.shape,dtype=np.int) self.periodicity = tuple(bool(x) for x in periodicity) # If regions are supposed to be inverted, i.e. the interior consists of values # smaller than the threshold instead of larger, change the sign of the array. @@ -674,6 +673,7 @@ class Features3d: else: pw = tuple((0,1) if x else (0,0) for x in periodicity) self._input = np.pad(sign_invert*input,pw,mode='wrap') + self.dimensions = np.array(self._input.shape,dtype=np.int) # Triangulate self.triangulate(contour_method=contour_method, cellvol_normal_component=cellvol_normal_component, @@ -700,12 +700,13 @@ class Features3d: import pyvista as pv import vtk from scipy import ndimage, spatial + from scipy.spatial import KDTree from time import time # Check if '_input' is available: might have been dropped after initialization assert self._input is not None, "'_input' not available. Initialize object with keep_input=True flag." # Wrap data for VTK using pyvista datavtk = pv.UniformGrid() - datavtk.dimensions = self._input.shape + datavtk.dimensions = self.dimensions datavtk.origin = self.origin datavtk.spacing = self.spacing datavtk.point_arrays['data'] = self._input.ravel('F') @@ -714,6 +715,87 @@ class Features3d: if report: print('[Features3d.triangulate] computing isocontour using {}...'.format(contour_method)) contour = datavtk.contour([self._threshold],method=contour_method,compute_scalars=False,compute_gradients=True) assert contour.is_all_triangles(), "Contouring produced non-triangle cells." + # Compute contour on boundaries: this is necessary for inside/outside checks and proper + # volume computation for overlapping objects + t__ = time() + self._faces_bd = [] + self._points_bd = [] + offset_pts = contour.n_points + print(offset_pts) + for axis in range(3): + # Build a nearest-neighbor search KD-trees for boundary points so that we can connect + # them to the boundary faces when needed + # t__ = time() + pos_bd_lo = self.origin[axis] + pos_bd_hi = self.origin[axis]+self.spacing[axis]*(self.dimensions[axis]-1) + search_dist = 1e-5*self.spacing[axis] + idx_lo = np.flatnonzero(np.abs(contour.points[:,axis]-pos_bd_lo)