def make_sphere(radius, slices, segments): profile = [V3.zero() for _ in range(segments)] dtheta = pi / (segments - 1) for i in range(segments): theta = dtheta * i R = Q.Ru(theta, V3.k()) profile[i] = Q.rotate(R, V3.make(0.0, -radius, 0.0)) return profile_sweep(profile, slices)
def make_capsule(radius, height, slices, segments): profile = [V3.zero() for _ in range(segments)] dtheta = pi / (segments - 1) for i in range(segments): theta = dtheta * i R = Q.Ru(theta, V3.k()) dh = -height / 2.0 if i < (segments / 2) else height / 2.0 profile[i] = Q.rotate(R, V3.make(0.0, -radius, 0.0)) + V3.make( 0.0, dh, 0.0) return profile_sweep(profile, slices)
def concat(B, A): """ Concatenate transformations.. First A then B, Hence, C = B*A :param B: :param A: :return: """ C = CoordSys() C.q = Q.unit(Q.prod(B.q, A.q)) C.r = Q.rotate(B.q, A.r) + B.r return C
def make_coordsys_from_to(A, B): """ Assumes that 'A' maps from bf_1 to wcs, and 'B' maps from bf_2 to wcs. Now compute the transform that maps from bf_1 to bf_2 :param A: :param B: :return: """ A2B = CoordSys() A2B.q = Q.unit(Q.prod(Q.conjugate(B.q), A.q)) A2B.r = Q.rotate(Q.conjugate(B.q), A.r - B.r) return A2B
def rotate(mesh, q): for vh in mesh.vertices(): p = Q.rotate(q, get_vertex_coords(mesh, vh)) mesh.set_point(vh, OM.TriMesh.Point(p[0], p[1], p[2])) return mesh
def inverse(X): C = CoordSys() C.q = Q.conjugate(X.q) C.r = Q.rotate(C.q, -X.r) return C
def xform_vector(X, v): return Q.rotate(X.q, v)
def xform_point(X, p): return Q.rotate(X.q, p) + X.r
def profile_sweep(profile, slices): mesh = OM.TriMesh() N = len(profile) J = slices if N <= 2: raise RuntimeError( 'profile_sweep(): Profile must have at least 3 points') if J <= 2: raise RuntimeError( 'profile_sweep(): Sweep must have at least 3 slices to be a proper volume.' ) K = (N - 2) * J + 2 # Total number of vertices bottom = K - 1 # Index to bottom vertex top = K - 2 # Index to top vertex H = N - 2 # Number of latitude circles #F = 2*J*(N-1) # Total number of triangle faces vhandles = [] # Make a 2D grid of vertices by sweeping profile around y-axis dtheta = 2.0 * pi / J # The angle of each slice for j in range(J): theta = j * dtheta R = Q.Ru(theta, V3.j()) for i in range(H): p = Q.rotate(R, profile[i + 1]) vh = mesh.add_vertex(OM.TriMesh.Point(p[0], p[1], p[2])) vhandles.append(vh) # Now fill in top and bottom vertices vh = mesh.add_vertex( OM.TriMesh.Point(profile[N - 1][0], profile[N - 1][1], profile[N - 1][2])) vhandles.append(vh) vh = mesh.add_vertex( OM.TriMesh.Point(profile[0][0], profile[0][1], profile[0][2])) vhandles.append(vh) # Make faces for bottom-ring for j in range(J): # # V = {c1} {c2} ... {cJ} b t # # b c1.0 c2.0 | b c2.0 c3.0| ... | b cJ.0 c1.0 # b 0 (N-2) | b (N-2) 2*(N-2) # left = j right = ((j + 1) % J) vi = vhandles[bottom] vj = vhandles[H * right] vk = vhandles[H * left] mesh.add_face(vi, vj, vk) # Make faces for middle-rings for i in range(H - 1): # ring number for j in range(J): # slice number left = j right = (j + 1) % J up = i + 1 down = i vi = vhandles[left * H + down] vj = vhandles[right * H + down] vk = vhandles[right * H + up] vm = vhandles[left * H + up] mesh.add_face(vi, vj, vk) mesh.add_face(vi, vk, vm) # Make faces for top - ring for j in range(J): offset = (N - 3) left = j right = (j + 1) % J vi = vhandles[top] vj = vhandles[left * H + offset] vk = vhandles[right * H + offset] mesh.add_face(vi, vj, vk) mesh.request_face_normals() mesh.update_face_normals() return mesh