def subdivide_face_extrude_tapered(face, height=0.0, fraction=0.5,doCap=True): """ Extrudes the face tapered like a window by creating an offset face and quads between every original edge and the corresponding new edge. Arguments: ---------- face : mola.core.Face The face to be extruded height : float The distance of the new face to the original face, default 0 fraction : float The relative offset distance, 0: original vertex, 1: center point default 0.5 (halfway) """ center_vertex = utils_face.face_center(face) normal = utils_face.face_normal(face) scaled_normal = utils_vertex.vertex_scale(normal, height) # calculate new vertex positions new_vertices = [] for i in range(len(face.vertices)): n1 = face.vertices[i] betw = utils_vertex.vertex_subtract(center_vertex, n1) betw = utils_vertex.vertex_scale(betw, fraction) nn = utils_vertex.vertex_add(n1, betw) nn = utils_vertex.vertex_add(nn, scaled_normal) new_vertices.append(nn) new_faces = [] # create the quads along the edges num = len(face.vertices) for i in range(num): n1 = face.vertices[i] n2 = face.vertices[(i + 1) % num] n3 = new_vertices[(i + 1) % num] n4 = new_vertices[i] new_face = Face([n1,n2,n3,n4]) new_faces.append(new_face) # create the closing cap face if doCap: cap_face = Face(new_vertices) new_faces.append(cap_face) for new_face in new_faces: utils_face.face_copy_properties(face,new_face) return new_faces
def subdivide_catmull_2d(vertices): newNodes = [] for i in range(len(vertices)): a = vertices[i] newNodes.append(Vertex(a.x,a.y,a.z)) b = vertices[(i + 1) % len(vertices)] center = utils_vertex.vertex_add(a, b) newNodes.append(utils_vertex.vertex_scale(center,0.5)) newNodes2 = [] for i in range(len(newNodes)): iPrev = i - 1 if iPrev < 0: iPrev = len(newNodes) - 1 iNext = i + 1 if iNext >= len(newNodes): iNext = 0 a = newNodes[iPrev] b = newNodes[i] c = newNodes[iNext] average = Vertex() # [average.add(v) for v in [a,b,b,c]] average.add(a) average.add(b) average.add(b) average.add(c) average.divide(4.0) # average = utils_vertex.vertex_add(average,a) # average = utils_vertex.vertex_add(average,b) # average = utils_vertex.vertex_add(average,b) # average = utils_vertex.vertex_add(average,c) # average /= 4 # average = utils_vertex.vertex_divide(average,4.0) newNodes2.append(average) return newNodes2
def construct_tetrahedron(size=1, cx=0, cy=0, cz=0): """ Constructs a tetrahedron mesh. Optional Arguments: ---------- side : float<br> The edge length of the tetrahedron<br> cx,cy,cz : float<br> The coordinates of the center point. """ mesh = Mesh() coord = 1 / math.sqrt(2) mesh.vertices = [ Vertex(+1, 0, -coord), Vertex(-1, 0, -coord), Vertex(0, +1, +coord), Vertex(0, -1, +coord) ] for i in range(len(mesh.vertices)): mesh.vertices[i] = utils_vertex.vertex_scale(mesh.vertices[i], size / 2) mesh.vertices[i] = utils_vertex.vertex_add(mesh.vertices[i], Vertex(cx, cy, cz)) f1 = Face([mesh.vertices[0], mesh.vertices[1], mesh.vertices[2]]) f2 = Face([mesh.vertices[1], mesh.vertices[0], mesh.vertices[3]]) f3 = Face([mesh.vertices[2], mesh.vertices[3], mesh.vertices[0]]) f4 = Face([mesh.vertices[3], mesh.vertices[2], mesh.vertices[1]]) mesh.faces = [f1, f2, f3, f4] mesh.update_topology() return mesh
def _vertices_between(v1,v2,n): row = [] deltaV = utils_vertex.vertex_subtract(v2, v1) deltaV = utils_vertex.vertex_divide(deltaV, n) for i in range(n): addV = utils_vertex.vertex_scale(deltaV, i) row.append(utils_vertex.vertex_add(addV, v1)) row.append(v2) return row
def subdivide_face_split_roof(face, height): """ Extrudes a pitched roof Arguments: ---------- face : mola.core.Face The face to be extruded height : mola.core.Vertex Th height of the roof """ faces = [] normal = utils_face.face_normal(face) normal = utils_vertex.vertex_scale(normal,height) if len(face.vertices) == 4: ev1 = utils_vertex.vertex_center(face.vertices[0], face.vertices[1]) ev1 = utils_vertex.vertex_add(ev1, normal) ev2 = utils_vertex.vertex_center(face.vertices[2], face.vertices[3]) ev2 = utils_vertex.vertex_add(ev2, normal) faces.append(Face([face.vertices[0], face.vertices[1], ev1])) faces.append(Face([face.vertices[1], face.vertices[2], ev2, ev1])) faces.append(Face([face.vertices[2], face.vertices[3], ev2])) faces.append(Face([face.vertices[3], face.vertices[0], ev1, ev2])) for f in faces: utils_face.face_copy_properties(face,f) return faces elif len(face.vertices) == 3: ev1 = utils_vertex.vertex_center(face.vertices[0], face.vertices[1]) ev1 = utils_vertex.vertex_add(ev1, normal) ev2 = utils_vertex.vertex_center(face.vertices[1], face.vertices[2]) ev2 = utils_vertex.vertex_add(ev2, normal) faces.append(Face([face.vertices[0], face.vertices[1], ev1])) faces.append(Face([face.vertices[1], ev2, ev1])) faces.append(Face([face.vertices[1], face.vertices[2], ev2])) faces.append(Face([face.vertices[2], face.vertices[0], ev1, ev2])) for f in faces: utils_face.face_copy_properties(face, f) return faces return [face]
def _catmullVertices(mesh): for face in mesh.faces: face.vertex = face.center() for edge in mesh.edges: if edge.face1 == None or edge.face2 == None: edge.v1.fix = True edge.v2.fix = True edge.vertex = edge.center() else: vsum = Vertex() nElements = 2 vsum = utils_vertex.vertex_add(vsum, edge.v1) vsum = utils_vertex.vertex_add(vsum, edge.v2) if edge.face1 != None: vsum = utils_vertex.vertex_add(vsum, edge.face1.vertex) nElements += 1 if edge.face2 != None: vsum = utils_vertex.vertex_add(vsum, edge.face2.vertex) nElements += 1 vsum = utils_vertex.vertex_divide(vsum, nElements) edge.vertex = vsum if edge.v1.fix and edge.v2.fix: edge.vertex.fix = True for vertex in mesh.vertices: if vertex.fix: vertex.vertex = copy.copy(vertex) else: averageFaces = Vertex() averageEdges = Vertex() nEdges = len(vertex.edges) for edge in vertex.edges: face = edge.face1 if edge.v2 is vertex: face = edge.face2 if face != None: averageFaces = utils_vertex.vertex_add( averageFaces, face.vertex) averageEdges = utils_vertex.vertex_add(averageEdges, edge.center()) averageEdges = utils_vertex.vertex_scale(averageEdges, 2.0 / nEdges) averageFaces = utils_vertex.vertex_scale(averageFaces, 1.0 / nEdges) v = Vertex(vertex.x, vertex.y, vertex.z) v = utils_vertex.vertex_scale(v, nEdges - 3) v = utils_vertex.vertex_add(v, averageFaces) v = utils_vertex.vertex_add(v, averageEdges) v = utils_vertex.vertex_scale(v, 1.0 / nEdges) vertex.vertex = v
def construct_dodecahedron(radius=1, cx=0, cy=0, cz=0): """ Constructs a dodecaheron mesh. Optional Arguments: ---------- radius : float<br> The radius of the containing sphere<br> cx,cy,cz : float<br> The coordinates of the center point. """ mesh = Mesh() phi = (1 + 5**0.5) / 2 mesh.vertices = [ Vertex(1, 1, 1), Vertex(1, 1, -1), Vertex(1, -1, 1), Vertex(1, -1, -1), Vertex(-1, 1, 1), Vertex(-1, 1, -1), Vertex(-1, -1, 1), Vertex(-1, -1, -1), Vertex(0, -phi, -1 / phi), Vertex(0, -phi, 1 / phi), Vertex(0, phi, -1 / phi), Vertex(0, phi, 1 / phi), Vertex(-phi, -1 / phi, 0), Vertex(-phi, 1 / phi, 0), Vertex(phi, -1 / phi, 0), Vertex(phi, 1 / phi, 0), Vertex(-1 / phi, 0, -phi), Vertex(1 / phi, 0, -phi), Vertex(-1 / phi, 0, phi), Vertex(1 / phi, 0, phi) ] for i in range(len(mesh.vertices)): mesh.vertices[i] = utils_vertex.vertex_scale(mesh.vertices[i], radius) mesh.vertices[i] = utils_vertex.vertex_add(mesh.vertices[i], Vertex(cx, cy, cz)) indices = [ 2, 9, 6, 18, 19, 4, 11, 0, 19, 18, 18, 6, 12, 13, 4, 19, 0, 15, 14, 2, 4, 13, 5, 10, 11, 14, 15, 1, 17, 3, 1, 15, 0, 11, 10, 3, 17, 16, 7, 8, 2, 14, 3, 8, 9, 6, 9, 8, 7, 12, 1, 10, 5, 16, 17, 12, 7, 16, 5, 13 ] for i in range(0, len(indices), 5): f = Face([ mesh.vertices[indices[i]], mesh.vertices[indices[i + 1]], mesh.vertices[indices[i + 2]], mesh.vertices[indices[i + 3]], mesh.vertices[indices[i + 4]] ]) mesh.faces.append(f) mesh.update_topology() return mesh
def normal_vertex_2d(vprev, v, vnext): vec1 = utils_vertex.vertex_subtract(v, vprev) vec1 = utils_vertex.vertex_unitize(vec1) vec2 = utils_vertex.vertex_subtract(vnext, v) vec2 = utils_vertex.vertex_unitize(vec2) n = utils_vertex.vertex_add(vec1, vec2) n = utils_vertex.vertex_scale(n, 0.5) n = utils_vertex.vertex_rotate_2D_90(n) #t=n.x #n.x=-n.y #n.y=t return n
def construct_icosahedron(radius=1, cx=0, cy=0, cz=0): """ Creates and returns a mesh in the form of an icosahedron. Optional Arguments: ---------- radius : float<br> The radius of the containing sphere.<br> cx,cy,cz : float<br> The coordinates of the center point. """ mesh = Mesh() phi = (1 + 5**0.5) / 2 coordA = 1 / (2 * math.sin(2 * math.pi / 5)) coordB = phi / (2 * math.sin(2 * math.pi / 5)) mesh.vertices = [ Vertex(0, -coordA, coordB), Vertex(coordB, 0, coordA), Vertex(coordB, 0, -coordA), Vertex(-coordB, 0, -coordA), Vertex(-coordB, 0, coordA), Vertex(-coordA, coordB, 0), Vertex(coordA, coordB, 0), Vertex(coordA, -coordB, 0), Vertex(-coordA, -coordB, 0), Vertex(0, -coordA, -coordB), Vertex(0, coordA, -coordB), Vertex(0, coordA, coordB) ] for i in range(len(mesh.vertices)): mesh.vertices[i] = utils_vertex.vertex_scale(mesh.vertices[i], radius) mesh.vertices[i] = utils_vertex.vertex_add(mesh.vertices[i], Vertex(cx, cy, cz)) indices = [ 1, 2, 6, 1, 7, 2, 3, 4, 5, 4, 3, 8, 6, 5, 11, 5, 6, 10, 9, 10, 2, 10, 9, 3, 7, 8, 9, 8, 7, 0, 11, 0, 1, 0, 11, 4, 6, 2, 10, 1, 6, 11, 3, 5, 10, 5, 4, 11, 2, 7, 9, 7, 1, 0, 3, 9, 8, 4, 8, 0 ] faces = [] for i in range(0, len(indices), 3): f = Face([ mesh.vertices[indices[i]], mesh.vertices[indices[i + 1]], mesh.vertices[indices[i + 2]] ]) faces.append(f) mesh.faces = faces mesh.update_topology() return mesh
def subdivide_face_extrude_to_point_center(face, height=0.0): """ Extrudes the face to the center point moved by height normal to the face and creating a triangular face from each edge to the point. Arguments: ---------- face : mola.core.Face The face to be extruded height : float The distance of the new point to the face center, default 0 """ normal = utils_face.face_normal(face) normal = utils_vertex.vertex_scale(normal,height) center = utils_face.face_center(face) center = utils_vertex.vertex_add(center,normal) return subdivide_face_extrude_to_point(face,center)
def subdivide_face_extrude(face, height=0.0, capBottom=False, capTop=True): """ Extrudes the face straight by distance height. Arguments: ---------- face : mola.core.Face The face to be extruded height : float The extrusion distance, default 0 capBottom : bool Toggle if bottom face (original face) should be created, default False capTop : bool Toggle if top face (extrusion face) should be created, default True """ normal=utils_face.face_normal(face) normal=utils_vertex.vertex_scale(normal,height) # calculate vertices new_vertices=[] for i in range(len(face.vertices)): new_vertices.append(utils_vertex.vertex_add(face.vertices[i], normal)) # faces new_faces=[] if capBottom: new_faces.append(face) for i in range(len(face.vertices)): i2=i+1 if i2>=len(face.vertices): i2=0 v0=face.vertices[i] v1=face.vertices[i2] v2=new_vertices[i2] v3=new_vertices[i] new_faces.append(Face([v0,v1,v2,v3])) if capTop: new_faces.append(Face(new_vertices)) for new_face in new_faces: utils_face.face_copy_properties(face,new_face) return new_faces
def subdivide_custom_triface_extrude_tapered_nonU(face, height=0.0, fraction=0.5, doCap=True): """ Extrudes a triangular face tapered like a window by creating an offset face and quads between every original edge and the corresponding new edge. The vertices of the new edge which corresponds to the shortest edge of the triangle are moved closer to the later, while preserving the offset from its other edges Arguments: ---------- face : mola.core.Face The face to be extruded height : float The distance of the new face to the original face, default 0 fraction : float The relative offset distance, 0: original vertex, 1: center point default 0.5 (halfway) """ center_vertex = utils_face.face_center(face) normal = utils_face.face_normal(face) scaled_normal = utils_vertex.vertex_scale(normal, height) minD = 9999999999999999 for i in range(len(face.vertices) - 1): n1 = face.vertices[i] for j in range(i + 1, len(face.vertices)): n2 = face.vertices[j] d = (n2.x - n1.x)**2.0 + (n2.y - n1.y)**2.0 + (n2.z - n1.z)**2.0 if d < minD: minD = d shortF_st = i shortF_end = j other = 3 - shortF_st - shortF_end n_other = face.vertices[other] betw_other = utils_vertex.vertex_subtract(center_vertex, n_other) betw_other = utils_vertex.vertex_scale(betw_other, fraction) nn_other = utils_vertex.vertex_add(n_other, betw_other) nn_other = utils_vertex.vertex_add(nn_other, scaled_normal) # calculate new vertex positions new_vertices = [] for i in range(len(face.vertices)): n1 = face.vertices[i] betw = utils_vertex.vertex_subtract(center_vertex, n1) betw = utils_vertex.vertex_scale(betw, fraction) nn = utils_vertex.vertex_add(n1, betw) nn = utils_vertex.vertex_add(nn, scaled_normal) if i == shortF_st or i == shortF_end: vec = utils_vertex.vertex_subtract(n1, nn_other) vec = utils_vertex.vertex_scale(vec, 0.25) nn = utils_vertex.vertex_add(nn, vec) new_vertices.append(nn) new_faces = [] # create the quads along the edges num = len(face.vertices) for i in range(num): n1 = face.vertices[i] n2 = face.vertices[(i + 1) % num] n3 = new_vertices[(i + 1) % num] n4 = new_vertices[i] new_face = Face([n1, n2, n3, n4]) new_faces.append(new_face) # create the closing cap face if doCap: cap_face = Face(new_vertices) new_faces.append(cap_face) for new_face in new_faces: utils_face.face_copy_properties(face, new_face) return new_faces