def subdivideCatmull2D(pts): newNodes = [] for i in range(len(pts)): a = pts[i] newNodes.append(Vertex(a.x, a.y, a.z)) b = pts[(i + 1) % len(pts)] center = vec.add(a, b) newNodes.append(vec.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(0, 0, 0) average = vec.add(average, a) average = vec.add(average, b) average = vec.add(average, b) average = vec.add(average, c) average = vec.divide(average, 4.0) newNodes2.append(average) return newNodes2
def sd_sided_tapered(face, d=0.1): # d should be between 0.01 and 0.49 bottom = vec.subtract(face.vertices[2], face.vertices[1]) top = vec.subtract(face.vertices[3], face.vertices[0]) b_vertices = [] b_vertices.append(face.vertices[1]) pv = vec.add(face.vertices[1], vec.scale(bottom, d)) b_vertices.append(pv) pv = vec.add(face.vertices[1], vec.scale(bottom, 1-d)) b_vertices.append(pv) b_vertices.append(face.vertices[2]) t_vertices = [] t_vertices.append(face.vertices[0]) pv = vec.add(face.vertices[0], vec.scale(top, d)) t_vertices.append(pv) pv = vec.add(face.vertices[0], vec.scale(top, 1-d)) t_vertices.append(pv) t_vertices.append(face.vertices[3]) newFaces = [] for i in range(3): vts = [] vts.append(t_vertices[i]) vts.append(b_vertices[i]) vts.append(b_vertices[i+1]) vts.append(t_vertices[i+1]) newFaces.append(Face(vts)) return newFaces
def extrudeTapered(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 = faceUtils.center(face) normal = faceUtils.normal(face) scaled_normal = vec.scale(normal, height) # calculate new vertex positions new_vertices = [] for i in range(len(face.vertices)): n1 = face.vertices[i] betw = vec.subtract(center_vertex, n1) betw = vec.scale(betw, fraction) nn = vec.add(n1, betw) nn = vec.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: faceUtils.copyProperties(face,new_face) return new_faces
def constructTetrahedron(cx,cy,cz,side): """ Constructs a tetrahedron mesh. Arguments: ---------- cx, cy, cz : float The center point of the tetrahedron side : float The edge length of the tetrahedron """ 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] = vec.scale(mesh.vertices[i], side / 2) mesh.vertices[i] = vec.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] return mesh
def constructDodecahedron(cx,cy,cz,radius): 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] = _vec.scale(mesh.vertices[i],radius) mesh.vertices[i] = _vec.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] faces = [] 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]]]) faces.append(f) # make triangles newfaces = [] for f in faces: v = _faceUtils.center(f) mesh.vertices.append(v) for i,cv in enumerate(f.vertices): nv = f.vertices[(i+1)%len(f.vertices)] newfaces.append(_Face([cv,v,nv])) mesh.faces = newfaces return mesh
def constructDodecahedron(cx,cy,cz,radius): """ Constructs a dodecaheron mesh. Arguments: ---------- cx, cy, cz : float The center point of the dodecaheron radius : float The radius of the containing sphere """ 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] = vec.scale(mesh.vertices[i], radius) mesh.vertices[i] = vec.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) return mesh
def _getVerticesBetween(v1,v2,n): row = [] deltaV = vec.subtract(v2, v1) deltaV = vec.divide(deltaV, n) for i in range(n): addV = vec.scale(deltaV, i) row.append(vec.add(addV, v1)) row.append(v2) return row
def splitRoof(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 = faceUtils.normal(face) normal = vec.scale(normal,height) if len(face.vertices) == 4: ev1 = vec.center(face.vertices[0], face.vertices[1]) ev1 = vec.add(ev1, normal) ev2 = vec.center(face.vertices[2], face.vertices[3]) ev2 = vec.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: faceUtils.copyProperties(face,f) return faces elif len(face.vertices) == 3: ev1 = vec.center(face.vertices[0], face.vertices[1]) ev1 = vec.add(ev1, normal) ev2 = vec.center(face.vertices[1], face.vertices[2]) ev2 = vec.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: faceUtils.copyProperties(face, f) return faces return [face]
def normalVertex2D(vprev, v, vnext): vec1 = vec.subtract(v, vprev) vec1 = vec.unitize(vec1) vec2 = vec.subtract(vnext, v) vec2 = vec.unitize(vec1) n = vec.add(vec1, vec2) n = vec.scale(n, 0.5) t = n.x n.x = -n.y n.y = t return n
def subdivideCatmull(_mesh): for face in _mesh.faces: face.vertex=faceUtils.center(face) for edge in _mesh.edges: if edge.face1==None or edge.face2==None: edge.v1.fix=True edge.v2.fix=True edge.vertex = edge.getCenter() else: vsum=Vertex() nElements=2 vsum=_vec.add(vsum,edge.v1) vsum=_vec.add(vsum,edge.v2) if edge.face1!=None: vsum=_vec.add(vsum,edge.face1.vertex) nElements+=1 if edge.face2!=None: vsum=_vec.add(vsum,edge.face2.vertex) nElements+=1 vsum=_vec.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=_vec.add(averageFaces,face.vertex) averageEdges=_vec.add(averageEdges,edge.getCenter()) averageEdges=_vec.scale(averageEdges,2.0/nEdges) averageFaces=_vec.scale(averageFaces,1.0/nEdges) v=Vertex(vertex.x,vertex.y,vertex.z) v=_vec.scale(v,nEdges-3) v=_vec.add(v,averageFaces) v=_vec.add(v,averageEdges) v=_vec.scale(v,1.0/nEdges) vertex.vertex=v return _collectNewFaces(_mesh)
def constructIcosahedron(cx, cy, cz, radius): """ Creates and returns a mesh in the form of an icosahedron. Arguments: ---------- cx,cy,cz : float The coordinates of the center point radius : float The radius of the containing sphere """ 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] = _vec.scale(mesh.vertices[i], radius) mesh.vertices[i] = _vec.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 return mesh
def createProfileSubdivision(z): global freq_Z vertices = polyUtils.constructCircle(15, 8, z) for i in range(3): newVertices = [] v0 = vertices[-1] for i, v1 in enumerate(vertices): newVertices.append(v0) n = polyUtils.normalEdge2DNonUnified(v0, v1) n = vec.scale(n, math.sin(freq_Z * z / 300)) center = vec.betweenRel(v0, v1, 0.5) newVertices.append(vec.add(center, n)) v0 = v1 vertices = newVertices #vertices=polyUtils.subdivideCatmull2D(vertices) return vertices
def extrudeToPointCenter(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 = faceUtils.normal(face) normal = vec.scale(normal,height) center = faceUtils.center(face) center = vec.add(center,normal) return extrudeToPoint(face,center)
def constructTetrahedron(cx,cy,cz,side): 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] = _vec.scale(mesh.vertices[i],side/2) mesh.vertices[i] = _vec.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] return mesh
def createProfile(z): global freq_Z, amp_Z, phase_Z, freq_P, amp_P, phase_P vertices = polyUtils.constructCircle(15, 128, z) iterations = 4 factor_Z = amp_Z * math.sin(freq_Z * (z / 300) + phase_Z) for i in range(1, iterations, 1): f = freq_P * i * i a = (factor_Z + amp_P) / (i * i) p = phase_P * z / 300 newVertices = [] v0 = vertices[-2] v1 = vertices[-1] for j, v2 in enumerate(vertices): nvec = polyUtils.normalVertex2D(v0, v1, v2) magnitude = a * math.sin(f * j / len(vertices) + p) nvec = vec.scale(nvec, magnitude) newVertices.append(vec.add(v2, nvec)) v0 = v1 v1 = v2 vertices = newVertices return vertices
def 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=faceUtils.normal(face) normal=vec.scale(normal,height) # calculate vertices new_vertices=[] for i in range(len(face.vertices)): new_vertices.append(vec.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: faceUtils.copyProperties(face,new_face) return new_faces