Generate generalized tube (i.e. cylinder with an axial hole). Args: p0 (``np.ndarray``): Bottom center. p1 (``np.ndarray``): Top center. r0_out (``float``): Bottom outer radius. r1_out (``float``): Top outer radius. r0_in (``float``): Bottom inner radius
(p0, p1, r0_out, r1_out, r0_in, r1_in, num_segments=16,
with_quad=False)
| 5 | from ..misc import Quaternion |
| 6 | |
| 7 | def generate_tube(p0, p1, r0_out, r1_out, r0_in, r1_in, num_segments=16, |
| 8 | with_quad=False): |
| 9 | """ Generate generalized tube (i.e. cylinder with an axial hole). |
| 10 | |
| 11 | Args: |
| 12 | p0 (``np.ndarray``): Bottom center. |
| 13 | p1 (``np.ndarray``): Top center. |
| 14 | r0_out (``float``): Bottom outer radius. |
| 15 | r1_out (``float``): Top outer radius. |
| 16 | r0_in (``float``): Bottom inner radius. |
| 17 | r1_in (``float``): Top inner radius. |
| 18 | num_segments (``int``): Number of segments to a discrete circle consists. |
| 19 | with_quad (``bool``): Output a quad mesh instead. |
| 20 | |
| 21 | Returns: |
| 22 | A generalized tube :py:class:`Mesh`. |
| 23 | """ |
| 24 | |
| 25 | assert(len(p0) == 3) |
| 26 | assert(len(p1) == 3) |
| 27 | Z = np.array([0, 0, 1], dtype=float) |
| 28 | p0 = np.array(p0, dtype=float) |
| 29 | p1 = np.array(p1, dtype=float) |
| 30 | axis = p1 - p0 |
| 31 | l = norm(axis) |
| 32 | if l <= 1e-12: |
| 33 | axis=Z |
| 34 | N = num_segments |
| 35 | |
| 36 | angles = [2*math.pi*i/float(N) for i in range(N)] |
| 37 | rim = np.array([[math.cos(theta), math.sin(theta), 0.0] |
| 38 | for theta in angles]) |
| 39 | rot = Quaternion.fromData(Z, axis).to_matrix() |
| 40 | |
| 41 | bottom_outer_rim = np.dot(rot, rim.T).T * r0_out + p0 |
| 42 | bottom_inner_rim = np.dot(rot, rim.T).T * r0_in + p0 |
| 43 | top_outer_rim = np.dot(rot, rim.T).T * r1_out + p1 |
| 44 | top_inner_rim = np.dot(rot, rim.T).T * r1_in + p1 |
| 45 | |
| 46 | vertices = np.vstack([ |
| 47 | bottom_outer_rim, |
| 48 | bottom_inner_rim, |
| 49 | top_outer_rim, |
| 50 | top_inner_rim]) |
| 51 | |
| 52 | if with_quad: |
| 53 | top = np.array([ |
| 54 | [2*N+i, 2*N+(i+1)%N, 3*N+(i+1)%N, 3*N+i] |
| 55 | for i in range(N)]) |
| 56 | bottom = np.array([ |
| 57 | [(i+1)%N, i, N+i, N+(i+1)%N] |
| 58 | for i in range(N)]) |
| 59 | inner = np.array([ |
| 60 | [3*N+i, 3*N+(i+1)%N, N+(i+1)%N, N+i] |
| 61 | for i in range(N)]) |
| 62 | outer = np.array([ |
| 63 | [ i, (i+1)%N, 2*N+(i+1)%N, 2*N+i] |
| 64 | for i in range(N)]) |