Exemple #1
0
def offset(mesh,offset=1,doclose=True):
    newMesh=Mesh()
    # calculate vertex normals
    for vertex in mesh.vertices:
        vertex.vertex = Vertex(0,0,0)
        vertex.nfaces = 0
    for face in mesh.faces:
        normal = utils_face.face_normal(face)
        for vertex in face.vertices:
            vertex.vertex.add(normal)
            vertex.nfaces += 1
    for vertex in mesh.vertices:
        vertex.vertex.scale(offset / vertex.nfaces)
        vertex.vertex.add(vertex)
    # create faces
    for face in mesh.faces:
        offsetVertices = []
        for vertex in face.vertices:
            offsetVertices.append(vertex.vertex)
        offsetVertices.reverse()
        newFace = Face(offsetVertices)
        newMesh.faces.append(newFace)
        newMesh.faces.append(face)
    # create sides
    if doclose:
        for edge in mesh.edges:
            if edge.face1 == None or edge.face2 == None:
                offsetVertices = [edge.v1, edge.v2, edge.v2.vertex, edge.v1.vertex]
                if edge.face2 == None:
                    offsetVertices.reverse()
                newFace = Face(offsetVertices)
                newMesh.faces.append(newFace)
    newMesh.update_topology()
    return newMesh
Exemple #2
0
def construct_cone(z1,
                   z2,
                   radius1,
                   radius2,
                   nSegments,
                   capBottom=True,
                   capTop=True):
    """
    Creates and returns a conic cylinder.

    Arguments:
    ----------
    z1, z2 : float<br>
        The bottom and top z-level.<br>
    radius1, radius2 : float<br>
        The radii at the bottom and at the top respectively<br>
    nSegments : int<br>
        The number of segments along the circumference<br>
    capBottom, capTop : bool<br>
        Toggle whether or not to close the cylinder at the bottom and the top
    """
    delaAngle = math.radians(360.0 / nSegments)
    angle = 0
    verticesBottom = []
    verticesTop = []
    for i in range(nSegments):
        x1 = radius1 * math.cos(angle)
        y1 = radius1 * math.sin(angle)
        verticesBottom.append(Vertex(x1, y1, z1))
        x2 = radius2 * math.cos(angle)
        y2 = radius2 * math.sin(angle)
        verticesTop.append(Vertex(x2, y2, z2))
        angle += delaAngle

    mesh = Mesh()
    mesh.vertices.extend(verticesBottom)
    mesh.vertices.extend(verticesTop)
    for i in range(nSegments):
        i2 = (i + 1) % nSegments
        mesh.faces.append(
            Face([
                verticesBottom[i], verticesBottom[i2], verticesTop[i2],
                verticesTop[i]
            ]))
    if capBottom:
        # centerBottom = Vertex(0, 0, z1)
        # mesh.vertices.append(centerBottom)
        # for i in range(nSegments):
        #     i2=(i+1)%nSegments
        #     mesh.faces.append(Face([verticesBottom[i2],verticesBottom[i],centerBottom]))
        mesh.faces.append(Face(list(reversed(verticesBottom))))
    if capTop:
        # centerTop=Vertex(0,0,z2)
        # mesh.vertices.append(centerTop)
        # for i in range(nSegments):
        #     i2=(i+1)%nSegments
        #     mesh.faces.append(Face([verticesTop[i],verticesTop[i2],centerTop]))
        mesh.faces.append(Face(verticesTop))
    mesh.update_topology()
    return mesh
Exemple #3
0
def subdivide_face_split_rel_multiple(face, direction, splits):
    sA = []
    sA.append(face.vertices[direction])
    lA = face.vertices[direction + 1]
    sB = []
    sB.append(face.vertices[direction + 3])
    lB = face.vertices[(direction + 2) % len(face.vertices)]

    for i in range(len(splits)):
        sA.append(utils_vertex.vertex_between_rel(sA[0], lA,splits[i]))
        sB.append(utils_vertex.vertex_between_rel(sB[0], lB,splits[i]))
    sA.append(lA)
    sB.append(lB)

    result = []
    for i in range(len(splits) + 1):
        if(dir == 1):
            f = Face([sB[i], sA[i], sA[i+1], sB[i+1]])
            utils_face.face_copy_properties(face, f)
            result.append(f)
        else:
            f = Face([sB[i], sB[i+1], sA[i+1], sA[i]])
            utils_face.face_copy_properties(face, f)
            result.append(f)
    return result
Exemple #4
0
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
Exemple #5
0
def construct_octahedron(edgeLen=1, cx=0, cy=0, cz=0):
    mesh = Mesh()
    #make vertices
    mesh.vertices = [
        Vertex(0, 0, edgeLen / 2),
        Vertex(-edgeLen / 2, 0, 0),
        Vertex(0, -edgeLen / 2, 0),
        Vertex(edgeLen / 2, 0, 0),
        Vertex(0, edgeLen / 2, 0),
        Vertex(0, 0, -edgeLen / 2)
    ]

    #move center to desired coordinates
    center = Vertex(cx, cy, cz)
    for v in mesh.vertices:
        v.add(center)

    #construct triangular faces
    f1 = Face([mesh.vertices[0], mesh.vertices[1], mesh.vertices[2]])
    f2 = Face([mesh.vertices[0], mesh.vertices[2], mesh.vertices[3]])
    f3 = Face([mesh.vertices[0], mesh.vertices[3], mesh.vertices[4]])
    f4 = Face([mesh.vertices[0], mesh.vertices[4], mesh.vertices[1]])
    f5 = Face([mesh.vertices[5], mesh.vertices[2], mesh.vertices[1]])
    f6 = Face([mesh.vertices[5], mesh.vertices[3], mesh.vertices[2]])
    f7 = Face([mesh.vertices[5], mesh.vertices[4], mesh.vertices[3]])
    f8 = Face([mesh.vertices[5], mesh.vertices[1], mesh.vertices[4]])

    mesh.faces = [f1, f2, f3, f4, f5, f6, f7, f8]
    mesh.update_topology()
    return mesh
Exemple #6
0
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
Exemple #7
0
def subdivide_face_split_grid(face,nU,nV):
    """
    splits a triangle, quad or a rectangle into a regular grid
    """
    if len(face.vertices) > 4:
        print('too many vertices')
        return face

    if len(face.vertices) == 4:
        vsU1 = _vertices_between(face.vertices[0], face.vertices[1], nU)
        vsU2 = _vertices_between(face.vertices[3], face.vertices[2], nU)
        gridVertices = []
        for u in range(len(vsU1)):
            gridVertices.append(_vertices_between(vsU1[u], vsU2[u], nV))
        faces = []
        for u in range(len(vsU1) - 1):
            vs1 = gridVertices[u]
            vs2 = gridVertices[u + 1]
            for v in range(len(vs1) - 1):
                #f = Face([vs1[v], vs1[v + 1], vs2[v + 1], vs2[v]])
                f = Face([vs1[v], vs2[v], vs2[v + 1], vs1[v + 1]])
                utils_face.face_copy_properties(face, f)
                faces.append(f)
        return faces

    if len(face.vertices) == 3:
        vsU1 = _vertices_between(face.vertices[0], face.vertices[1], nU)
        vsU2 = _vertices_between(face.vertices[0], face.vertices[2], nU)
        gridVertices = []
        for u in range(1, len(vsU1)):
            gridVertices.append(_vertices_between(vsU1[u], vsU2[u], nV))
        faces = []
        # triangles
        v0 = face.vertices[0]
        vs1 = gridVertices[0]
        for v in range(len(vs1) - 1):
            f = Face([v0,vs1[v],vs1[v + 1]])
            utils_face.face_copy_properties(face, f)
            faces.append(f)
        for u in range(len(gridVertices) - 1):
            vs1 = gridVertices[u]
            vs2 = gridVertices[u + 1]
            for v in range(len(vs1) - 1):
                f = Face([vs1[v],vs1[v + 1], vs2[v + 1], vs2[v]])
                utils_face.face_copy_properties(face, f)
                faces.append(f)
        return faces
Exemple #8
0
def _collect_new_faces(mesh):
    newMesh=Mesh()
    for face in mesh.faces:
        v1 = face.vertices[-2]
        v2 = face.vertices[-1]
        for v3 in face.vertices:
            edge1 = mesh.edge_adjacent_to_vertices(v1,v2)
            edge2 = mesh.edge_adjacent_to_vertices(v2,v3)
            if (edge1 != None) and (edge2!= None):
                newFace = Face([edge1.vertex, v2.vertex, edge2.vertex, face.vertex])
                newFace.color = face.color
                newFace.group = face.group
                newMesh.faces.append(newFace)
            v1 = v2
            v2 = v3
    newMesh.update_topology()
    return newMesh
def marching_cubes(nX,nY,nZ,values,iso, scale_to_canvas=False):
    mesh =  Mesh()
    nYZ = nY * nZ
    index = 0
    n =[0]*8
    switcher = {
        0:lambda: Vertex(x + _v(n[0], n[1], iso), y + 1, z),
        1:lambda: Vertex(x + 1, y + _v(n[2], n[1], iso), z),
        2:lambda: Vertex(x + _v(n[3], n[2], iso), y, z),
        3:lambda: Vertex(x, y + _v(n[3], n[0], iso), z),
        4:lambda: Vertex(x + _v(n[4], n[5], iso), y + 1, z + 1),
        5:lambda: Vertex(x + 1, y + _v(n[6], n[5], iso), z + 1),
        6:lambda: Vertex(x + _v(n[7], n[6], iso), y, z + 1),
        7:lambda: Vertex(x, y + _v(n[7], n[4], iso), z + 1),
        8:lambda: Vertex(x, y + 1, z + _v(n[0], n[4], iso)),
        9:lambda: Vertex(x + 1, y + 1, z + _v(n[1], n[5], iso)),
        10:lambda: Vertex(x, y, z + _v(n[3], n[7], iso)),
        11:lambda: Vertex(x + 1, y, z + _v(n[2], n[6], iso))
    }
    for x in range(nX - 1):
        for y in range(nY - 1):
            for z in range(nZ - 1):
                caseNumber = 0
                index = z + y * nZ + x * nYZ
                # collecting the values
                n[0] = values[index + nZ]# 0,1,0
                n[1] = values[index + nYZ + nZ]#1,1,0
                n[2] = values[index + nYZ]# 1,0,0
                n[3] = values[index]# 0,0,0
                n[4] = values[index + nZ + 1]# 0,1,1
                n[5] = values[index + nYZ + nZ + 1]# 1,1,1
                n[6] = values[index + nYZ + 1]# 1,0,1
                n[7] = values[index + 1]# 0,0,1
                for i in range(7,-1,-1):
                    if n[i] > iso:
                        caseNumber+=1
                    if i > 0:
                        caseNumber = caseNumber << 1
                # collecting the faces
                offset = caseNumber * 15
                for i in range(offset,offset + 15,3):
                    if _faces[i] > -1:
                        vs=[]
                        for j in range(i,i+3):
                            v = switcher[_faces[j]]()
                            mesh.vertices.append(v)
                            vs.append(v)
                            if len(vs) == 3:
                                mesh.faces.append(Face(vs))

    mesh.update_topology()
    if(scale_to_canvas):
        mesh.translate(-nX/2.0,-nY/2.0,-nZ/2.0)
        sc = 20.0/max(nX,nY)
        mesh.scale(sc,sc,sc)

    return mesh
Exemple #10
0
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
Exemple #11
0
def subdivide_face_split_rel_free_quad(face, indexEdge, split1, split2):
    """
    Splits a quad in two new quads through the points specified
    by relative position along the edge.

    Arguments:
    ----------
    face : mola.core.Face
        The face to be extruded
    indexEdge : int
        direction of split, 0: 0->2, 1: 1->3
    split1, split2 : float
        relative position of split on each edge (0..1)
    """
    # only works with quads, therefore return original face if triangular
    if len(face.vertices) != 4:
        return face

    # constrain indexEdge to be either 0 or 1
    indexEdge = indexEdge % 2

    indexEdge1 = (indexEdge + 1) % len(face.vertices)
    indexEdge2 = (indexEdge + 2) % len(face.vertices)
    indexEdge3 = (indexEdge + 3) % len(face.vertices)
    p1 = utils_vertex.vertex_between_rel(face.vertices[indexEdge],
                                         face.vertices[indexEdge1], split1)
    p2 = utils_vertex.vertex_between_rel(face.vertices[indexEdge2],
                                         face.vertices[indexEdge3], split2)
    faces = []
    if indexEdge == 0:
        f1 = Face([face.vertices[0], p1, p2, face.vertices[3]])
        f2 = Face([p1, face.vertices[1], face.vertices[2], p2])
        utils_face.face_copy_properties(face, f1)
        utils_face.face_copy_properties(face, f2)
        faces.extend([f1, f2])
    elif indexEdge == 1:
        f1 = Face([face.vertices[0], face.vertices[1], p1, p2])
        f2 = Face([p2, p1, face.vertices[2], face.vertices[3]])
        utils_face.face_copy_properties(face, f1)
        utils_face.face_copy_properties(face, f2)
        faces.extend([f1, f2])
    return faces
Exemple #12
0
def subdivide_face_split_frame(face, w):
    """
    Creates an offset frame with quad corners. Works only with convex shapes.

    Arguments:
    ----------
    face : mola.core.Face
        The face to be split
    w : float
        The width of the offset frame
    """
    faces = []
    innerVertices = []
    for i in range(len(face.vertices)):
        if (i == 0):
            vp = face.vertices[len(face.vertices) - 1]
        else:
            vp = face.vertices[i - 1]
        v = face.vertices[i]
        vn = face.vertices[(i + 1) % len(face.vertices)]
        vnn = face.vertices[(i + 2) % len(face.vertices)]

        th1 = utils_vertex.vertex_angle_triangle(vp, v, vn)
        th2 = utils_vertex.vertex_angle_triangle(v, vn, vnn)

        w1 = w / math.sin(th1)
        w2 = w / math.sin(th2)

        vs1 = _vertices_frame(v, vn, w1, w2)
        vs2 = _vertices_frame(
            _vertices_frame(vp, v, w1, w1)[2],
            _vertices_frame(vn, vnn, w2, w2)[1], w1, w2)
        innerVertices.append(vs2[1])
        f1 = Face([vs1[0], vs2[0], vs2[1], vs1[1]])
        utils_face.face_copy_properties(face, f1)
        f2 = Face([vs1[1], vs2[1], vs2[2], vs1[2]])
        utils_face.face_copy_properties(face, f2)
        faces.extend([f1, f2])
    fInner = Face(innerVertices)
    utils_face.face_copy_properties(face, fInner)
    faces.append(fInner)
    return faces
Exemple #13
0
def mesh_from_rhino_mesh(obj):
    mesh = Mesh()
    vertices = rs.MeshVertices(obj)
    for v in vertices:
        mesh.vertices.append(Vertex(v[0], v[1], v[2]))
    faceVerts = rs.MeshFaceVertices(obj)
    for face in faceVerts:
        if face[2] == face[3]:
            mesh.faces.append(
                Face([
                    mesh.vertices[face[0]], mesh.vertices[face[1]],
                    mesh.vertices[face[2]]
                ]))
        else:
            mesh.faces.append(
                Face([
                    mesh.vertices[face[0]], mesh.vertices[face[1]],
                    mesh.vertices[face[2]], mesh.vertices[face[3]]
                ]))
    return mesh
Exemple #14
0
def mesh_offset(mesh, offset=1, doclose=True):
    """
    Creates an offset of a mesh.
    If `doclose` is `True`, it will create quad faces
    along the naked edges of an open input mesh.
    """
    newMesh = Mesh()
    # calculate vertex normals
    for vertex in mesh.vertices:
        vertex.vertex = Vertex(0, 0, 0)
        vertex.nfaces = 0
    for face in mesh.faces:
        normal = utils_face.face_normal(face)
        for vertex in face.vertices:
            vertex.vertex.add(normal)
            vertex.nfaces += 1
    for vertex in mesh.vertices:
        vertex.vertex.scale(offset / vertex.nfaces)
        vertex.vertex.add(vertex)
    # create faces
    for face in mesh.faces:
        offsetVertices = []
        for vertex in face.vertices:
            offsetVertices.append(vertex.vertex)
        offsetVertices.reverse()
        newFace = Face(offsetVertices)
        newMesh.faces.append(newFace)
        newMesh.faces.append(face)
    # create sides
    if doclose:
        for edge in mesh.edges:
            if edge.face1 == None or edge.face2 == None:
                offsetVertices = [
                    edge.v1, edge.v2, edge.v2.vertex, edge.v1.vertex
                ]
                if edge.face2 == None:
                    offsetVertices.reverse()
                newFace = Face(offsetVertices)
                newMesh.faces.append(newFace)
    newMesh.update_topology()
    return newMesh
Exemple #15
0
def construct_box(x1, y1, z1, x2, y2, z2):
    """
    Creates and returns a mesh box with six quad faces.

    Arguments:
    ----------
    x1,y1,z1 : float<br>
        The coordinates of the bottom left front corner<br>
    x2,y2,z2 : float<br>
        The coordinates of the top right back corner
    """
    mesh = Mesh()
    v1 = Vertex(x1, y1, z1)
    v2 = Vertex(x1, y2, z1)
    v3 = Vertex(x2, y2, z1)
    v4 = Vertex(x2, y1, z1)
    v5 = Vertex(x1, y1, z2)
    v6 = Vertex(x1, y2, z2)
    v7 = Vertex(x2, y2, z2)
    v8 = Vertex(x2, y1, z2)
    mesh.vertices = [v1, v2, v3, v4, v5, v6, v7, v8]
    f1 = Face([v1, v2, v3, v4])
    f2 = Face([v8, v7, v6, v5])
    f3 = Face([v4, v3, v7, v8])
    f4 = Face([v3, v2, v6, v7])
    f5 = Face([v2, v1, v5, v6])
    f6 = Face([v1, v4, v8, v5])
    mesh.faces = [f1, f2, f3, f4, f5, f6]
    mesh.update_topology()
    return mesh
Exemple #16
0
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
Exemple #17
0
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
Exemple #18
0
 def quad_mesh(self, functionIn, functionOut):
     faces = []
     for x in range(self.nx):
         for y in range(self.ny):
             for z in range(self.nz):
                 index = self.get_index(x, y, z)
                 if functionIn(self.values[index]):
                     # (x,y) (x1,y) (x1,y1) (x,y1)
                     if x == self.nx - 1 or functionOut(
                             self.get_value_at_xyz(x + 1, y, z)):
                         v1 = Vertex(x + 1, y, z)
                         v2 = Vertex(x + 1, y + 1, z)
                         v3 = Vertex(x + 1, y + 1, z + 1)
                         v4 = Vertex(x + 1, y, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if x == 0 or functionOut(
                             self.get_value_at_xyz(x - 1, y, z)):
                         v1 = Vertex(x, y + 1, z)
                         v2 = Vertex(x, y, z)
                         v3 = Vertex(x, y, z + 1)
                         v4 = Vertex(x, y + 1, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if y == self.ny - 1 or functionOut(
                             self.get_value_at_xyz(x, y + 1, z)):
                         v1 = Vertex(x + 1, y + 1, z)
                         v2 = Vertex(x, y + 1, z)
                         v3 = Vertex(x, y + 1, z + 1)
                         v4 = Vertex(x + 1, y + 1, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if y == 0 or functionOut(
                             self.get_value_at_xyz(x, y - 1, z)):
                         v1 = Vertex(x, y, z)
                         v2 = Vertex(x + 1, y, z)
                         v3 = Vertex(x + 1, y, z + 1)
                         v4 = Vertex(x, y, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if z == self.nz - 1 or functionOut(
                             self.get_value_at_xyz(x, y, z + 1)):
                         v1 = Vertex(x, y, z + 1)
                         v2 = Vertex(x + 1, y, z + 1)
                         v3 = Vertex(x + 1, y + 1, z + 1)
                         v4 = Vertex(x, y + 1, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if z == 0 or functionOut(
                             self.get_value_at_xyz(x, y, z - 1)):
                         v1 = Vertex(x, y + 1, z)
                         v2 = Vertex(x + 1, y + 1, z)
                         v3 = Vertex(x + 1, y, z)
                         v4 = Vertex(x, y, z)
                         faces.append(Face([v1, v2, v3, v4]))
     mesh = Mesh()
     mesh.faces = faces
     mesh.update_topology()
     if (self.scale_to_canvas):
         mesh.translate(-self.nx / 2.0, -self.ny / 2.0, -self.nz / 2.0)
         sc = 20.0 / max(self.nx, self.ny)
         mesh.scale(sc, sc, sc)
     return mesh
Exemple #19
0
def import_obj(filename):
    """Loads a Wavefront OBJ file. """
    mesh = Mesh()
    group = ""
    for line in open(filename, "r"):
        if line.startswith('#'): continue
        values = line.split()
        if not values: continue
        if values[0] == 'g':
            group=values[1]
        elif values[0] == 'v':
            v = [float(c) for c in values[1 : 4]]
            #v = map(float, values[1:4])
            mesh.vertices.append(Vertex(v[0],v[1],v[2]))
        elif values[0] == 'f':
            face = Face([])
            face.group = group
            for v in values[1:]:
                w = v.split('/')
                vertex = mesh.vertices[int(w[0]) - 1]
                face.vertices.append(vertex)
            mesh.faces.append(face)
    return mesh
Exemple #20
0
def subdivide_face_offset_planar(face,offsets):
    newPts = []
    for i in range(len(face.vertices)):
        iP = i - 1
        if(iP < 0):
            iP = len(face.vertices)-1
        iN = (i + 1) % len(face.vertices)
        v0 = face.vertices[iP]
        v1 = face.vertices[i]
        v2 = face.vertices[iN]
        newPts.append(utils_vertex.vertex_offset_point(v0, v1, v2, offsets[iP], offsets[i]))
    f = Face(newPts)
    utils_face.face_copy_properties(face, f)
    return f
Exemple #21
0
def construct_single_face(vertices):
    """
    Creates and returns a single face mesh from the vertices.

    Arguments:
    ----------
    vertices : list of mola.core.Vertex<br>
        The vertices describing the face
    """
    mesh = Mesh()
    mesh.vertices = vertices
    mesh.faces = [Face(vertices)]
    mesh.update_topology()
    return mesh
Exemple #22
0
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]
Exemple #23
0
def subdivide_face_split_offsets(face,offsets):
    offsetFace = subdivide_face_offset_planar(face,offsets)
    nOffsetFaces = 0
    for o in offsets:
        if(abs(o) > 0):
            nOffsetFaces += 1
    faces = []
    for i in range(len(face.vertices)):
        if(abs(offsets[i]) > 0):
            i2 = (i + 1) % len(face.vertices)
            f = Face([face.vertices[i], face.vertices[i2], offsetFace.vertices[i2], offsetFace.vertices[i]])
            utils_face.face_copy_properties(face, f)
            faces.append(f)
    faces.append(offsetFace)
    for f in faces:
        if(utils_face.face_area(f) < 0):
            f.vertices.reverse()
    return faces
Exemple #24
0
def subdivide_face_extrude_to_point(face, point):
    """
    Extrudes the face to a point by creating a
    triangular face from each edge to the point.

    Arguments:
    ----------
    face : mola.core.Face
        The face to be extruded
    point : mola.core.Vertex
        The point to extrude to
    """
    numV = len(face.vertices)
    faces = []
    for i in range(numV):
        v1 = face.vertices[i]
        v2 = face.vertices[(i + 1) % numV]
        f = Face([v1, v2, point])
        utils_face.face_copy_properties(face, f)
        faces.append(f)
    return faces
Exemple #25
0
 def quad_mesh(self, functionIn, functionOut):
     faces = []
     for x in range(self.nx):
         for y in range(self.ny):
             for z in range(self.nz):
                 index=self.get_index(x,y,z)
                 if functionIn(self.values[index]):
                     # (x,y) (x1,y) (x1,y1) (x,y1)
                     if x == self.nx - 1 or functionOut(self.get_value_at_xyz(x + 1, y, z)):
                         v1 = Vertex(x + 1, y, z)
                         v2 = Vertex(x + 1, y + 1, z)
                         v3 = Vertex(x + 1, y + 1, z + 1)
                         v4 = Vertex(x + 1, y, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if x == 0 or functionOut(self.get_value_at_xyz(x-1,y,z)):
                         v1 = Vertex(x, y + 1, z)
                         v2 = Vertex(x, y, z)
                         v3 = Vertex(x, y, z + 1)
                         v4 = Vertex(x, y + 1, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if y == self.ny - 1 or functionOut(self.get_value_at_xyz(x, y + 1, z)):
                         v1 = Vertex(x + 1, y + 1, z)
                         v2 = Vertex(x, y + 1, z)
                         v3 = Vertex(x, y + 1, z + 1)
                         v4 = Vertex(x + 1, y + 1, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if y == 0 or functionOut(self.get_value_at_xyz(x, y - 1, z)):
                         v1 = Vertex(x, y, z)
                         v2 = Vertex(x + 1, y, z)
                         v3 = Vertex(x + 1, y, z + 1)
                         v4 = Vertex(x, y, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if z==self.nz-1 or functionOut(self.get_value_at_xyz(x, y, z + 1)):
                         v1 = Vertex(x, y, z + 1)
                         v2 = Vertex(x + 1, y, z + 1)
                         v3 = Vertex(x + 1, y + 1, z + 1)
                         v4 = Vertex(x, y + 1, z + 1)
                         faces.append(Face([v1, v2, v3, v4]))
                     if z == 0 or functionOut(self.get_value_at_xyz(x, y, z - 1)):
                         v1 = Vertex(x, y + 1, z)
                         v2 = Vertex(x + 1, y + 1, z)
                         v3 = Vertex(x + 1, y, z)
                         v4 = Vertex(x, y, z)
                         faces.append(Face([v1, v2, v3, v4]))
     mesh = Mesh()
     mesh.faces = faces
     mesh.update_topology()
     return mesh
Exemple #26
0
def construct_torus(ringRadius, tubeRadius, ringN=16, tubeN=16):
    """
    Constructs a torus mesh.

    Arguments:
    ----------
    ringRadius : float<br>
        the big radius of the axis<br>
    tubeRadius : float<br>
        radius of the the tube along the axis<br>

    Optional Arguments:
    ----------
    ringN : int<br>
        resolution along the ring<br>
    tubeN : int<br>
        resolution along the tube
    """
    mesh = Mesh()
    theta = 2 * math.pi / ringN
    phi = 2 * math.pi / tubeN

    for i in range(ringN):
        for j in range(tubeN):
            mesh.vertices.append(
                _torus_vertex(ringRadius, tubeRadius, phi * j, theta * i))

    for i in range(ringN):
        ii = (i + 1) % ringN
        for j in range(tubeN):
            jj = (j + 1) % tubeN
            a = i * tubeN + j
            b = ii * tubeN + j
            c = ii * tubeN + jj
            d = i * tubeN + jj
            f = Face([mesh.vertices[k] for k in [a, b, c, d]])
            mesh.faces.append(f)
    mesh.update_topology()
    return mesh
Exemple #27
0
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
Exemple #28
0
def construct_rhombic_dodecahedron(edge_length=1, cx=0, cy=0, cz=0):
    mesh = Mesh()
    #make vertices
    mesh.vertices = [
        Vertex(0, 0, 2 * edge_length),
        Vertex(-edge_length, edge_length, edge_length),
        Vertex(-edge_length, -edge_length, edge_length),
        Vertex(edge_length, -edge_length, edge_length),
        Vertex(edge_length, edge_length, edge_length),
        Vertex(-2 * edge_length, 0, 0),
        Vertex(0, -2 * edge_length, 0),
        Vertex(2 * edge_length, 0, 0),
        Vertex(0, 2 * edge_length, 0),
        Vertex(-edge_length, edge_length, -edge_length),
        Vertex(-edge_length, -edge_length, -edge_length),
        Vertex(edge_length, -edge_length, -edge_length),
        Vertex(edge_length, edge_length, -edge_length),
        Vertex(0, 0, -2 * edge_length)
    ]

    #move center to desired coordinates
    center = Vertex(cx, cy, cz)
    for v in mesh.vertices:
        v.add(center)

    #construct quad faces
    f1 = Face([
        mesh.vertices[0], mesh.vertices[2], mesh.vertices[5], mesh.vertices[1]
    ])
    f2 = Face([
        mesh.vertices[0], mesh.vertices[3], mesh.vertices[6], mesh.vertices[2]
    ])
    f3 = Face([
        mesh.vertices[0], mesh.vertices[4], mesh.vertices[7], mesh.vertices[3]
    ])
    f4 = Face([
        mesh.vertices[0], mesh.vertices[1], mesh.vertices[8], mesh.vertices[4]
    ])
    f5 = Face([
        mesh.vertices[2], mesh.vertices[6], mesh.vertices[10], mesh.vertices[5]
    ])
    f6 = Face([
        mesh.vertices[3], mesh.vertices[7], mesh.vertices[11], mesh.vertices[6]
    ])
    f7 = Face([
        mesh.vertices[4], mesh.vertices[8], mesh.vertices[12], mesh.vertices[7]
    ])
    f8 = Face([
        mesh.vertices[1], mesh.vertices[5], mesh.vertices[9], mesh.vertices[8]
    ])
    f9 = Face([
        mesh.vertices[10], mesh.vertices[13], mesh.vertices[9],
        mesh.vertices[5]
    ])
    f10 = Face([
        mesh.vertices[11], mesh.vertices[13], mesh.vertices[10],
        mesh.vertices[6]
    ])
    f11 = Face([
        mesh.vertices[12], mesh.vertices[13], mesh.vertices[11],
        mesh.vertices[7]
    ])
    f12 = Face([
        mesh.vertices[9], mesh.vertices[13], mesh.vertices[12],
        mesh.vertices[8]
    ])

    mesh.faces = [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12]
    mesh.update_topology()
    return mesh
Exemple #29
0
 def add_face(self, vertices):
     f = Face(vertices)
     self.faces.append(f)
     return f