B2. Convex polygon 2D pattern
Create a 2D convex polygon pattern from a given quad mesh funicular shell
Objective
We will learn to compute a convex polygon 2d tessellation pattern for a given quad mesh shell structure.
Procedure
a1. load brick mesh data
# ==============================================================================
#Load data
# ==============================================================================
HERE = os.path.dirname(__file__)
FILE_I = os.path.join(HERE, 'data', 'brick_pattern_data.json')
mesh = Mesh.from_json(FILE_I)
a2. boundary bricks
# ==============================================================================
#Params
# ==============================================================================
offset_value = 0.1
# ==============================================================================
#Helper functions
# ==============================================================================
def check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value):
v_neighbors = mesh.vertex_neighborhood(vkey)
v_descendant = mesh.face_vertex_descendant(fkey,vkey,n=1)
v_ancestor = mesh.face_vertex_ancestor(fkey,vkey,n=1)
g = None
for v in v_neighbors:
if v != v_descendant and v != v_ancestor:
g = v
g_xyz = mesh.vertex_coordinates(g,axes='xyz')
v_xyz = mesh.vertex_coordinates(vkey,axes='xyz')
vector = subtract_vectors(g_xyz, v_xyz)
offset_coordinates = add_vectors(v_xyz, scale_vector(vector,offset_value))
return offset_coordinates
def calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value):
v_xyz = mesh.vertex_coordinates(vkey)
if order =="ancestor":
v_neighbor = mesh.face_vertex_ancestor(fkey,vkey,n=1)
v2_xyz = mesh.vertex_coordinates(v_neighbor,axes='xyz')
elif order =="descendant":
v_neighbor = mesh.face_vertex_descendant(fkey,vkey,n=1)
v2_xyz = mesh.vertex_coordinates(v_neighbor,axes='xyz')
vector = subtract_vectors(v2_xyz, v_xyz)
offset_coordinates = add_vectors(v_xyz, scale_vector(vector,offset_value))
return offset_coordinates
#================================================================
#hexagonal brick pattern
#================================================================
#visually identify face index along south and north boundary. This can be automated, however for this exercise we will do it manually
south_boundary_faces = (0,1,2,3,4,5)
north_boundary_faces = (12,13,14,15,16,17)
#create list to store newly created hexaconal pattern meshes
hexagonal_meshes = []
#South boundary
for fkey in (south_boundary_faces):
tess_mesh = Mesh()
for i,vkey in enumerate(mesh.face_vertices(fkey)):
if i==0:
v_xyz = mesh.vertex_coordinates(vkey)
a = tess_mesh.add_vertex(x=v_xyz[0],y=v_xyz[1],z=v_xyz[2])
elif i==1:
v_xyz = mesh.vertex_coordinates(vkey)
b = tess_mesh.add_vertex(x=v_xyz[0], y=v_xyz[1],z=v_xyz[2])
elif i==2:
v_xyz = mesh.vertex_coordinates(vkey)
c = tess_mesh.add_vertex(x=v_xyz[0], y=v_xyz[1],z=v_xyz[2])
elif i==3:
order = "ancestor"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
d = tess_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
elif i == 4:
offset_xyz = check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value)
e = tess_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
elif i == 5:
order = "descendant"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
f = tess_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
tess_mesh.add_face([0,1,2,3,4,5])
hexagonal_meshes.append(tess_mesh)
#north boundary
for fkey in north_boundary_faces:
tess_mesh = Mesh()
for i,vkey in enumerate(mesh.face_vertices(fkey)):
if i==0:
order = "ancestor"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
a = tess_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
elif i==1:
offset_xyz = check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value)
b = tess_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
elif i==2:
order = "descendant"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
c = tess_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
elif i==3:
v_xyz = mesh.vertex_coordinates(vkey)
d = tess_mesh.add_vertex(x=v_xyz[0], y=v_xyz[1],z=v_xyz[2])
elif i==4:
v_xyz = mesh.vertex_coordinates(vkey)
e = tess_mesh.add_vertex(x=v_xyz[0], y=v_xyz[1],z=v_xyz[2])
elif i==5:
v_xyz = mesh.vertex_coordinates(vkey)
f = tess_mesh.add_vertex(x=v_xyz[0], y=v_xyz[1],z=v_xyz[2])
tess_mesh.add_face([0,1,2,3,4,5])
hexagonal_meshes.append(tess_mesh)
this step is also illustrated as a flowchart below
a3. course bricks
#identify full bricks/middle faces
faces = list(fkey for fkey in mesh.faces())
boundary_faces = south_boundary_faces + north_boundary_faces
middle_faces = set(faces) ^ set(boundary_faces)
for fkey in middle_faces:
if len(mesh.face_vertices(fkey))==6:
middle_mesh = Mesh()
new_vertices = []
for i,vkey in enumerate(mesh.face_vertices(fkey)):
if i==0:
order = "ancestor"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
a = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(a)
elif i==1:
offset_xyz = check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value)
b = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(b)
elif i==2:
order = "descendant"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
c = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(c)
elif i==3:
order = "ancestor"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
d = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(d)
elif i == 4:
offset_xyz = check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value)
e = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(e)
elif i == 5:
order = "descendant"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
f = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(f)
middle_mesh.add_face(new_vertices)
hexagonal_meshes.append(middle_mesh)
a4. half bricks
#half brick right
elif fkey == 28 or fkey == 30:
middle_mesh = Mesh()
new_vertices = []
for i,vkey in enumerate(mesh.face_vertices(fkey)):
if i==0:
offset_xyz = check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value)
a = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
print(a)
new_vertices.append(a)
elif i==1:
order = "descendant"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
b = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(b)
elif i==2:
order = "ancestor"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
c = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(c)
elif i==3:
offset_xyz = check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value)
d = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(d)
middle_mesh.add_face(new_vertices)
hexagonal_meshes.append(middle_mesh)
#half brick left
elif fkey == 31 or fkey == 29:
middle_mesh = Mesh()
new_vertices = []
for i,vkey in enumerate(mesh.face_vertices(fkey)):
if i==0:
order = "ancestor"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
a = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(a)
elif i==1:
offset_xyz = check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value)
b = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(b)
elif i==2:
offset_xyz = check_neighbors_and_offset_vector(mesh,vkey,fkey,offset_value)
c = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(c)
elif i==3:
order = "descendant"
offset_xyz = calc_vector_and_offset_vertex(mesh,vkey,fkey,order,offset_value)
d = middle_mesh.add_vertex(x=offset_xyz[0], y=offset_xyz[1],z=offset_xyz[2])
new_vertices.append(d)
middle_mesh.add_face(new_vertices)
hexagonal_meshes.append(middle_mesh)
Last updated