Generate cylinder (or `conical frustum`_ to be precise). Args: p0 (``np.ndarray``): Bottom center. p1 (``np.ndarray``): Top center. r0 (``float``): Bottom radius. r1 (``float``): Top radius. num_segments (``int``): Number of segments of discrete circle.
(p0, p1, r0, r1, num_segments=16)
| 5 | from ..misc import Quaternion |
| 6 | |
| 7 | def generate_cylinder(p0, p1, r0, r1, num_segments=16): |
| 8 | """ Generate cylinder (or `conical frustum`_ to be precise). |
| 9 | |
| 10 | Args: |
| 11 | p0 (``np.ndarray``): Bottom center. |
| 12 | p1 (``np.ndarray``): Top center. |
| 13 | r0 (``float``): Bottom radius. |
| 14 | r1 (``float``): Top radius. |
| 15 | num_segments (``int``): Number of segments of discrete circle. |
| 16 | |
| 17 | Returns: |
| 18 | The cylinder :py:class:`Mesh`. |
| 19 | |
| 20 | .. _conical frustum: http://mathworld.wolfram.com/ConicalFrustum.html |
| 21 | """ |
| 22 | |
| 23 | assert(len(p0) == 3) |
| 24 | assert(len(p1) == 3) |
| 25 | Z = np.array([0, 0, 1], dtype=float) |
| 26 | p0 = np.array(p0, dtype=float) |
| 27 | p1 = np.array(p1, dtype=float) |
| 28 | axis = p1 - p0 |
| 29 | l = norm(axis) |
| 30 | if l <= 1e-12: |
| 31 | axis=Z |
| 32 | |
| 33 | angles = [2*math.pi*i/float(num_segments) for i in range(num_segments)] |
| 34 | rim = np.array([[math.cos(theta), math.sin(theta), 0.0] |
| 35 | for theta in angles]) |
| 36 | rot = Quaternion.fromData(Z, axis).to_matrix() |
| 37 | |
| 38 | bottom_rim = np.dot(rot, rim.T).T * r0 + p0 |
| 39 | top_rim = np.dot(rot, rim.T).T * r1 + p1 |
| 40 | |
| 41 | vertices = np.vstack([ [p0, p1], bottom_rim, top_rim ]) |
| 42 | |
| 43 | bottom_fan = np.array([ |
| 44 | [0, (i+1)%num_segments+2, i+2] |
| 45 | for i in range(num_segments) ], dtype=int) |
| 46 | |
| 47 | top_fan = np.array([ |
| 48 | [1, i+num_segments+2, (i+1)%num_segments+num_segments+2] |
| 49 | for i in range(num_segments) ], dtype=int) |
| 50 | |
| 51 | side = np.array([ |
| 52 | [[2+i, 2+(i+1)%num_segments, 2+i+num_segments], |
| 53 | [2+i+num_segments, 2+(i+1)%num_segments, 2+(i+1)%num_segments+num_segments] ] |
| 54 | for i in range(num_segments) ], dtype=int) |
| 55 | side = side.reshape((-1, 3), order="C") |
| 56 | |
| 57 | faces = np.vstack([bottom_fan, top_fan, side]) |
| 58 | return form_mesh(vertices, faces) |