Slice a given 3D mesh N times along certain direciton. Args: mesh (:class:`Mesh`): The mesh to be sliced. direction (:class:`numpy.ndaray`): Direction orthogonal to the slices. N (int): Number of slices. Returns: A list of `N` :class:`Mesh` objects, each re
(mesh, direction, N)
| 7 | from numpy.linalg import norm |
| 8 | |
| 9 | def slice_mesh(mesh, direction, N): |
| 10 | """ Slice a given 3D mesh N times along certain direciton. |
| 11 | |
| 12 | Args: |
| 13 | mesh (:class:`Mesh`): The mesh to be sliced. |
| 14 | direction (:class:`numpy.ndaray`): Direction orthogonal to the slices. |
| 15 | N (int): Number of slices. |
| 16 | |
| 17 | Returns: |
| 18 | A list of `N` :class:`Mesh` objects, each representing a single slice. |
| 19 | """ |
| 20 | if mesh.dim != 3: |
| 21 | raise NotImplementedError("Only slicing 3D mesh is supported.") |
| 22 | |
| 23 | bbox_min, bbox_max = mesh.bbox |
| 24 | center = 0.5 * (bbox_min + bbox_max) |
| 25 | radius = norm(bbox_max - center) |
| 26 | direction = np.array(direction) |
| 27 | direction = direction / norm(direction) |
| 28 | |
| 29 | proj_len = np.dot(mesh.vertices, direction) |
| 30 | min_val = np.amin(proj_len) |
| 31 | max_val = np.amax(proj_len) |
| 32 | mid_val = 0.5 * (min_val + max_val) |
| 33 | intercepts = np.linspace(min_val - mid_val, max_val - mid_val, N+2)[1:-1] |
| 34 | assert(len(intercepts) == N) |
| 35 | if N%2 == 1: |
| 36 | intercepts = np.append(intercepts, intercepts[-1]+radius) |
| 37 | |
| 38 | boxes = [] |
| 39 | for low, high in intercepts.reshape((-1, 2), order="C"): |
| 40 | min_corner = -np.ones(3) * (radius+1) |
| 41 | max_corner = np.ones(3) * (radius+1) |
| 42 | min_corner[2] = low |
| 43 | max_corner[2] = high |
| 44 | box = generate_box_mesh(min_corner, max_corner) |
| 45 | boxes.append(box) |
| 46 | |
| 47 | num_boxes = len(boxes) |
| 48 | boxes = merge_meshes(boxes) |
| 49 | rot = Quaternion.fromData( |
| 50 | np.array([0.0, 0.0, 1.0]), np.array(direction)).to_matrix() |
| 51 | boxes = form_mesh(np.dot(rot, boxes.vertices.T).T + center, boxes.faces) |
| 52 | |
| 53 | slabs = boolean(boxes, mesh, "intersection") |
| 54 | |
| 55 | cross_secs = [] |
| 56 | source = slabs.get_attribute("source").ravel() |
| 57 | selected = source == 1 |
| 58 | cross_section_faces = slabs.faces[selected] |
| 59 | cross_section = form_mesh(slabs.vertices, cross_section_faces) |
| 60 | |
| 61 | intersects = np.dot(slabs.vertices, direction).ravel() - \ |
| 62 | np.dot(center, direction) |
| 63 | eps = (max_val - min_val) / (2 * N) |
| 64 | |
| 65 | for i,val in enumerate(intercepts[:N]): |
| 66 | selected_vertices = np.logical_and( |