B1.Brick tessellation pattern

Create a 2D brick tessellation pattern from a given quad mesh funicular shell

Objectives

We will compute a 2D brick pattern tessellation mesh from a given quad mesh funicular shell

Procedure

a1.select quad mesh

The end result of the form found geometry is a quad mesh, hence we will begin with a shell structure input as a quad mesh geometry

# ==============================================================================
#Select inputs
# ==============================================================================
guid = compas_rhino.select_mesh()
quad_mesh = RhinoMesh.from_guid(guid).to_compas()

a2.find boundary edges

# ==============================================================================
#Helper functions
# ==============================================================================
def find_boundary(mesh):
    """
    identifies the start vertex,  its respective edge and its continuous edge loop
    Param
    -----
    mesh: compas quad mesh

    return
    ------
    list of corner vertex key, start edge tuple, list of start edge continuous loop
    """
    corners = list(mesh.vertices_where({'vertex_degree':2}))
    corner = corners[1]

    corner_edges = mesh.vertex_neighbors(corner)
    start_edge = (corner, corner_edges[0])
    print("start_edge", start_edge)

    start_loop = mesh.edge_loop(start_edge)
    print("start_loop", start_loop)

    return corner, start_edge, start_loop

# ==============================================================================
#Create vertices of the Brick Pattern
# ==============================================================================
#Step_1 identify the start vertex, edge and start edge loop
corner, start_edge, start_loop = find_boundary(quad_mesh)

a3. create brick tessellation pattern vertices

#initiate new mesh datastructure
brick_tess_mesh = Mesh()

# ==============================================================================
#Helper functions
# ==============================================================================
def find_boundary(mesh):
    """
    identifies the start vertex,  its respective edge and its continuous edge loop
    Param
    -----
    mesh: compas quad mesh

    return
    ------
    list of corner vertex key, start edge tuple, list of start edge continuous loop
    """
    corners = list(mesh.vertices_where({'vertex_degree':2}))
    corner = corners[1]
    corner_edges = mesh.vertex_neighbors(corner)
    start_edge = (corner, corner_edges[0])
    start_loop = mesh.edge_loop(start_edge)

    return corner, start_edge, start_loop

def loop_edges_for_v_coordinates(start_edges, mesh):
    """
    finds the edges loops and add the vertex coordinates in
    a sequence to a list
    Param
    -----
    start_edges: list of Tuples
    edge identifies

    mesh: dict
    COMPAS mesh
    """
    vertices_coordinates = []
    number_of_vertices_in_each_loop = None
    for edge in start_edges:
        edge_loop = mesh.edge_loop(edge)
        number_of_vertices_in_each_loop = (len(edge_loop)+1)
        for i,e_key in enumerate(edge_loop):
            if i==0:
                for v_key in e_key:
                    vertex_coordinates = quad_mesh.vertex_coordinates(v_key, axes='xyz')
                    vertices_coordinates.append(vertex_coordinates)
            else:
                for i,v_key in enumerate(e_key):
                    if i==1:
                        vertex_coordinates = quad_mesh.vertex_coordinates(v_key, axes='xyz')
                        vertices_coordinates.append(vertex_coordinates)

    return vertices_coordinates, number_of_vertices_in_each_loop

def add_vertices(vertices):
    """
    adds vertices to the new mesh in a sequence
    Param
    -----
    vertices: list of lists
    XYZ coordinates of the mesh
    """
    for xyz in vertices:
        v = brick_tess_mesh.add_vertex(x=xyz[0],y=xyz[1],z=xyz[2])

def chunks(items, n):
    items = iter(items)
    for first in items:
        chunk = chain((first), islice(items, n-1))
        yield chunk
        deque(chunk, 0)
        
# ==============================================================================
#Create vertices of the Brick Pattern
# ==============================================================================
#Step_1 identify the start vertex, edge and start edge loop
corner, start_edge, start_loop = find_boundary(quad_mesh)

#Step_2 get all the parallel edge loops
parallel_edges = [edge for edge in quad_mesh.edge_strip(start_edge)]

#Step_3 get all the vertex coorinates of the quad mesh
# and the number of vertices in each edge loop
vertices_coordinates, number_of_vertices_in_each_loop = loop_edges_for_v_coordinates(parallel_edges, quad_mesh)

#Step_4 add all the vertex coordinates to the newly create brick tessellation mesh
create_vertices = add_vertices(vertices_coordinates)

a4. create faces

Create faces for odd,even course bricks and half bricks

# ==============================================================================
#Build faces
# ==============================================================================
#create poly face (make diagram for this)
v_key = [vkey for vkey in brick_tess_mesh.vertices()]

#group v_keys - here we make a nested list of vertices in each edge loop
v_key_chunks = []
for chunk in map(list,chunks(v_key, number_of_vertices_in_each_loop) ):
    v_key_chunks.append(chunk)

#split groups as even and odd course points
even_course_vertices = []
odd_course_vertices = []
for i, chunk in enumerate(v_key_chunks):
    if i%2 == 0:
        even_course_vertices.append(chunk)
    else:
        odd_course_vertices.append(chunk)

#identify start vertex for each face loop in even and odd courses (make diagram for this)
even_course_start_points = []
for chunk in even_course_vertices:
    for j in chunk:
        if j%2 == 0 and j != chunk[-1]:
            even_course_start_points.append(j)

odd_course_start_points = []
half_brick_start_points = []
for chunk in (odd_course_vertices[:-1]):
    for i,j in enumerate(chunk):
        if i==0 or i==(len(chunk)-2):
            half_brick_start_points.append(j)

        elif i>0 and j%2 == 0 and j != chunk[-2]:
            odd_course_start_points.append(j)

# build poly face / full brick
num = number_of_vertices_in_each_loop
for v_key in (even_course_start_points + odd_course_start_points):
    face = [v_key, v_key+1, v_key+2, v_key+num+2, v_key+num+1, v_key+num]
    brick_tess_mesh.add_face(face)

#build hald brick
for v_key in half_brick_start_points:
    face = [v_key, v_key+1, v_key+num+1, v_key+num]
    brick_tess_mesh.add_face(face)

O. Output

# ==============================================================================
#Export JSON
# ==============================================================================
HERE = os.path.dirname(__file__)
FILE_O = os.path.join(HERE, 'data', 'brick_pattern_data.json')

brick_tess_mesh.to_json(FILE_O)

below is an overview of the steps as a flowchart

Last updated