<jupyter_start><jupyter_text>Computational Structural Design II - Mesh Datastructure I Learning Goal: - Understand Mesh Datastructure- How to Construct a Mesh- Mesh Vertices, Faces, Edges Content:- [A. Mesh Introduction](MeshIntro)- [B. Mesh Vertex, Edge, Face](MeshB)- [C. Mesh Normals](MeshC)- [D. Exercise: Geodesic Dome](MeshD)---<jupyter_code># ! pip install compas_notebook<jupyter_output><empty_output><jupyter_text>A1. Mesh in Form FindingForm finding a cable-net or generating a compression-only vault usually starts with a **2D mesh**, which represents the horizontal projection of the eventual structure. The line segments of this mesh is called **Pattern**. The following picture shows you an existing structure and its corresponding pattern. The form-found **Thrust** is also a mesh, but in 3D space. ![img](https://files.gitbook.com/v0/b/gitbook-legacy-files/o/assets%2F-M730QpQnbAMvz44bqhc%2F-MOff3g181Ib3KNlmKgc%2F-MOfhAWYJRaSfNZucLzL%2Fimage.png?alt=media&token=<PASSWORD>)Nave Vault of the Sherborne Abbey, Dorset, UK (photo by Lawrence Lew)  A2. Generate Polygon - Geometry and TopologyFirstly, let's create 4 polygons using `compas.geometry.Polygon` and visualize them in different colors. Make sure that the winding order (point order) of the polygons are either all clockwise or all counter-clockwise.  A2_a. Generate Polygon from Points<jupyter_code>from compas.geometry import Polygon
from compas_plotters import Plotter

# create polygons
polygon_1 = Polygon() # add your code here
polygon_2 = Polygon() # add your code here
polygon_3 = Polygon() # add your code here
polygon_4 = Polygon() # add your code here

# visualize the Point
plotter = Plotter(show_axes=True)
plotter.add(polygon_1, facecolor=(1.0, 0, 0))
plotter.add(polygon_2, facecolor=(0, 0, 1.0))
plotter.add(polygon_3, facecolor=(0, 1.0, 0))
plotter.add(polygon_4, facecolor=(1.0, 1.0, 0))
plotter.zoom_extents()
plotter.show()<jupyter_output><empty_output><jupyter_text>A2_b. Generate Polygon Using Connectivity | Point Index | xyz || :---: | :---: || 0 | (0, 0, 0) || 1 | (2.5, 0, 0) || 2 | (4, 0, 0) || 3 | (0, 2, 0) || 4 | (1.5, 2, 0) || 5 | (4, 2, 0) || 6 | (0, 4, 0) || 7 | (2.5, 4, 0) || 8 | (4, 4, 0) |<jupyter_code>from compas.geometry import Polygon
from compas_plotters import Plotter

# create polygons
points = [] # add your code here
polygon_1 = Polygon() # add your code here
polygon_2 = Polygon() # add your code here
polygon_3 = Polygon() # add your code here
polygon_4 = Polygon() # add your code here

# visualize the Point
plotter = Plotter(show_axes=True)
plotter.add(polygon_1, facecolor=(1.0, 0, 0))
plotter.add(polygon_2, facecolor=(0, 0, 1.0))
plotter.add(polygon_3, facecolor=(0, 1.0, 0))
plotter.add(polygon_4, facecolor=(1.0, 1.0, 0))
plotter.zoom_extents()
plotter.show()<jupyter_output><empty_output><jupyter_text>A3. Mesh and COMPAS MeshA mesh is a collection of polygons arranged in a way that it can not only conserve geometric information but also topological information. Here is the API reference of COMPAS mesh: https://compas.dev/compas/latest/api/generated/compas.datastructures.Mesh.htmlcompas.datastructures.Mesh  A3_a. COMPAS Mesh<jupyter_code># add your code here<jupyter_output><empty_output><jupyter_text>A3_b. Build a COMPAS MeshMeshes can be built from scratch by adding vertices and faces.<jupyter_code>from compas.datastructures import Mesh
from compas_plotters import Plotter

mesh = Mesh()

# add vertices
# add your code here

# add faces
# add your code here

# visualize the mesh
plotter = Plotter(show_axes=True)
plotter.add(mesh, sizepolicy='absolute')
plotter.zoom_extents()
plotter.show()<jupyter_output><empty_output><jupyter_text>A3_c. `Mesh.from_vertices_and_faces``Mesh.from_vertices_and_faces` construct a mesh object from a list of vertices and faces. API reference: https://compas.dev/compas/1.5.0/api/generated/compas.datastructures.Mesh.from_vertices_and_faces.htmlcompas.datastructures.Mesh.from_vertices_and_facesSource code: https://github.com/compas-dev/compas/blob/81606f4580b5d4139e56b592f05354f965954388/src/compas/datastructures/mesh/mesh.pyL440<jupyter_code>from compas.datastructures import Mesh
from compas_plotters import Plotter
vertices = [[0, 0, 0], [2.5, 0, 0], [4, 0, 0],
         [0, 2, 0], [1.5, 2, 0], [4, 2, 0],
         [0, 4, 0], [2.5, 4, 0], [4, 4, 0]]

faces = [] # add your code here

mesh = Mesh.from_vertices_and_faces(vertices, faces)

plotter = Plotter(show_axes=True)
plotter.add(mesh, sizepolicy='absolute')
plotter.zoom_extents()
plotter.show()<jupyter_output><empty_output><jupyter_text>A3_d. `Mesh.from_polygons``Mesh.from_polygons` converts a series of polygons to a mesh. API reference: https://compas.dev/compas/1.5.0/api/generated/compas.datastructures.Mesh.from_polygons.htmlGithub source code: https://github.com/compas-dev/compas/blob/main/src/compas/datastructures/mesh/mesh.py<jupyter_code>from compas.datastructures import Mesh
from compas.geometry import Polygon
from compas_plotters import Plotter

polygon_1 = Polygon([[0, 0, 0], [2.5, 0, 0], [1.5, 2, 0], [0, 2, 0]])
polygon_2 = Polygon([[2.5, 0, 0], [4, 0, 0], [4, 2, 0], [1.5, 2, 0]])
polygon_3 = Polygon([[0, 2, 0], [1.5, 2, 0], [2.5, 4, 0], [0, 4, 0]])
polygon_4 = Polygon([[1.5, 2, 0], [4, 2, 0], [4, 4, 0], [2.5, 4, 0]])

mesh = Mesh.from_polygons() # add your code here

# visualize the mesh
plotter = Plotter(show_axes=True)
plotter.add(mesh, sizepolicy='absolute')
plotter.zoom_extents()
plotter.show()<jupyter_output><empty_output><jupyter_text>A4. Visualize Mesh in 3D ViewerMesh is often used to represent 3D objects. We can use the 3D viewer to visualize the mesh. The following example visualize a thrust diagram that is exported from RhinoVault2.<jupyter_code>from compas.datastructures import Mesh
# from compas_notebook.app import App

mesh = Mesh.from_json("https://raw.githubusercontent.com/BlockResearchGroup/CSD2_2022/main/3_Materialization/Tutorial5/data/simple_dome.json")

# add your code here<jupyter_output><empty_output><jupyter_text>Let's pick up a random vertex in the mesh and move it 1 unit up along the z axis.<jupyter_code>from compas.datastructures import Mesh
from compas_notebook.app import App

mesh = Mesh.from_json("https://raw.githubusercontent.com/BlockResearchGroup/CSD2_2022/main/3_Materialization/Tutorial5/data/simple_dome.json")

# add your code here

viewer = App()
viewer.add(mesh)
viewer.show()<jupyter_output><empty_output><jupyter_text>B. Mesh Vertex, Edge, FaceMesh has three main components: **Vertex**, **edge** and **face**. A vertex is a point in 3D space, represented by the [x, y, z] coordinate. | Vertex Key | Coordinates || :---: | :---: || 0 | (0, 0, 0) || 1 | (2, 0, 0) || 2 | (2, 2, 0) || 3 | (0, 2, 0) || 4 | (1, 1, 2) | An edge connects two vertices together. Meshes are built by adding vertices and faces. Edges cannot be added explicitly, so edges don't have identifiers / edge keys. Instead, they are identified through pairs of vertex keys. | (u, v) || :---: || (0, 1) || (1, 2) || (2, 3) || (0, 3) || (1, 4) || (2, 4) || (3, 4) || (0, 4) | A face is constructed by a sequence of vertices on the face. A 3D geometry can be constructed by connecting faces together. Note that, in a COMPAS mesh, the winding order of face vertices is alwyas **counterclockwise**. | Face Key | Face Vertices || :---: | :---: || 0 | (0, 1, 4) || 1 | (1, 2, 4) || 2 | (2, 3, 4) || 3 | (0, 3, 4) |  B1. Access Mesh Vertices, Faces and Edges`mesh.vertices()`, `mesh.edges(`), `mesh.faces()` access the vertices, edges and faces of the mesh data structure. Note that these methods return generator objects that have to be consumed by iteration.<jupyter_code># generator objects
vertices = [[0, 0, 0], [2, 0, 0], [2, 2, 0],
         [0, 2, 0], [1, 1, 2]]

faces = [[0, 1, 4], [1, 2, 4], [2, 3, 4], [0, 3, 4]]

mesh = Mesh.from_vertices_and_faces(vertices, faces)

# access vertices

# access edges

# access faces
print("Vertices")

print("\nEdges")
        
print("\nFaces")    
print(mesh.vertices())

print(mesh.edges())

print(mesh.faces())<jupyter_output><empty_output><jupyter_text>B2. Visualize the Points<jupyter_code>from compas.datastructures import Mesh
from compas.geometry import Sphere, Point
from compas_notebook.app import App

mesh = Mesh.from_json("https://raw.githubusercontent.com/BlockResearchGroup/CSD2_2022/main/3_Materialization/Tutorial5/data/simple_dome.json")

viewer = App()

# loop through all the vertex keys
for vkey in mesh.vertices():
    # xyz coordinates of the vertex
    
    # create a sphere
    
    # add the sphere in the viewer
    pass

viewer.add(mesh)
viewer.show()<jupyter_output>/Users/duch/opt/anaconda3/envs/csd2/lib/python3.9/site-packages/IPython/core/display.py:724: UserWarning: Consider using IPython.display.IFrame instead
  warnings.warn("Consider using IPython.display.IFrame instead")<jupyter_text>B3. Visualize the Lines<jupyter_code>from compas.datastructures import Mesh
from compas.geometry import Line
from compas_notebook.app import App

mesh = Mesh.from_json("https://raw.githubusercontent.com/BlockResearchGroup/CSD2_2022/main/3_Materialization/Tutorial5/data/simple_dome.json")

viewer = App()

for edge in mesh.edges():
    # find edge coordinates
    
    # create a line
    
    # add line to the viewer
    
    pass

# viewer.add(mesh)
viewer.show()<jupyter_output><empty_output><jupyter_text>B4. Visualize the Faces<jupyter_code>from compas.datastructures import Mesh
from compas.geometry import Polygon
from compas_notebook.app import App

mesh = Mesh.from_json("https://raw.githubusercontent.com/BlockResearchGroup/CSD2_2022/main/3_Materialization/Tutorial5/data/simple_dome.json")

viewer = App()

for fkey in mesh.faces():
    # find vertex keys on the face
    
    # find xyz coordinates of the vertices
    
    # create a polygon
    
    # add polygon to the viewer
    pass

# viewer.add(mesh)
viewer.show()<jupyter_output><empty_output><jupyter_text>--- C. Mesh NormalsThere are two kinds of normals that. Face normals are orthongal vectors to the faces of the mesh. Whereas vertex normals are orthongal to the vertices.  C1. Face NormalsThe face normal is a vector that describes the direction that the face polygon is facing. The winding of the vertices determines the direction of the face normal.<jupyter_code>from compas.datastructures import Mesh
from compas_notebook.app import App

mesh = Mesh.from_json("https://raw.githubusercontent.com/BlockResearchGroup/CSD2_2022/main/3_Materialization/Tutorial5/data/simple_dome.json")

viewer = App()

for fkey in mesh.faces():
    # add your code here
    pass

# viewer.add(mesh)
# viewer.show()<jupyter_output><empty_output><jupyter_text>C2. Vertex NormalsThe vertex normal is the weighted average of the normals of the neighboring faces.<jupyter_code>from compas.datastructures import Mesh
from compas_notebook.app import App

mesh = Mesh.from_json("https://raw.githubusercontent.com/BlockResearchGroup/CSD2_2022/main/3_Materialization/Tutorial5/data/simple_dome.json")

viewer = App()

for vkey in mesh.vertices():
    # add your code here
    pass

# viewer.add(mesh)
# viewer.show()<jupyter_output><empty_output><jupyter_text>--- D. Exercise: Geodesic Dome D1. Load MeshIn the following example, we will try to materialize a geodesic dome. We will use spheres/cylinders, cylinders, polygons to represent joints, bars and facades.<jupyter_code>from compas.datastructures import Mesh
from compas.geometry import Polygon, add_vectors, scale_vector
from compas_notebook.app import App

mesh = Mesh.from_json("https://raw.githubusercontent.com/BlockResearchGroup/CSD2_2022/main/3_Materialization/Tutorial5/data/geodome.json")

viewer = App()
viewer.add(mesh)
viewer.show()<jupyter_output><empty_output><jupyter_text>D2. Draw Joints<jupyter_code>from compas.geometry import Cylinder, Plane, Circle

viewer = App()

for vkey in mesh.vertices():
    # add your code here
    pass

# viewer.add(mesh)
viewer.show()<jupyter_output><empty_output><jupyter_text>D3. Draw Bars<jupyter_code>from compas.geometry import Plane, Vector, Circle, Cylinder
from compas_notebook.app import App

viewer = App()

for (u, v) in mesh.edges():
    # add your code here
    pass

# viewer.add(mesh)
viewer.show()<jupyter_output><empty_output><jupyter_text>D4. Draw Facades<jupyter_code>from compas.geometry import Polygon, Translation, scale_vector
from compas_notebook.app import App

viewer = App()

for fkey in mesh.faces():
    # add your code here
    pass
    
# viewer.add(mesh)
viewer.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12177033492822967, 'fraction_numerical': 0.03253588516746411, 'mean_word_length': 4.969062351261305, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 77, 'https://': 14, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '293532', 'license': 'MIT', 'n_tokens_mistral': 4716, 'n_tokens_neox': 4413, 'n_words': 1253, 'path': '3_Materialization/Tutorial5/week_6_notebook_lecture.ipynb', 'repo_name': 'BlockResearchGroup/CSD2_2022', 'size': '12566'}