In the Polygon, the line segments form a continuous cycle, connecting the vertices in order. These directed line segments are called half-edge. If an edge is shared by two faces, it can be decomposed into 2 twin half-edges, which have the opposite directions and each face can have a half-edge. The half-edge adjacencies define the connectivity of faces.
One incident face and one incident vertex are stored in each half-edge. In a face, a vertex always has an outgoing half-edge which starts at this vertex. Starting from the end vertex of the half-edge, the next half-edge could be found, until it comes back to the start vertex and forms a cycle. The ordering of the vertices determines the direction of the face normal according to right-hand rule.
A COMPAS mesh is a polygon mesh, represented using a half-edge data strucutre, where most information is stored in the half-edges - these are the primary objects.
The basic elements of COMPAS mesh are vertices, faces, and half-edges.
vertices stores the xyz coordinates of the vertices.
faces contains all the indices of the vertex key in order that make up the face.
half-edge contains the index of a vertex key, the end vertex key of the outgoing half-edge, and the face key it belongs to.
3. Building a Mesh
3.a: construct mesh from scratch
Meshes can be built from scratch by adding vertex-per-vertex and face per face. Mesh.add_face() would generate half-edges at the same time. As long as one vertex or face is added to the mesh, it could be visualized with a Plotter.
Vertices, faces and edges of the mesh data structure could be accessed using the corresponding methods, which returns generator objects that have to be consumed by iteration. We can print and see what is inside the generator.
# access the vertices, faces and edges of the meshfor vertex in cablenet_mesh.vertices():print("vertex", vertex)# vertex keyfor face in cablenet_mesh.faces():print("face", face)# face keyfor edge in cablenet_mesh.edges():print("edge", edge)# (u, v) of the edge
In CSDII, notation vkey means vertex key, fkey means face key and (u, v) means the vkey pair for edges. With the keys, more relevant information of the mesh could be accessed.
for vkey in cablenet_mesh.vertices():# xyz coordinates of the vertex xyz = cablenet_mesh.vertex_coordinates(vkey)print("vertex:", vkey, "coordinates:", xyz)for fkey in cablenet_mesh.faces():# vertex keys of the face f_vkeys = cablenet_mesh.face_vertices(fkey)print("face:", fkey, "vkyes:", f_vkeys)for (u, v) in cablenet_mesh.edges():print("edge:", (u, v))
6. Topology
Similar to Network, a mesh can answer several topological questions about itself and its components.
# verticesvertex_facecolor ={}vertex_text ={}for vkey in vkeys: vertex_text[vkey]=str(vkey) vertex_facecolor[vkey]= (255,0,0)# faces:face_facecolor ={}for fkey in fkeys:if cablenet_mesh.is_face_on_boundary(fkey)isFalse: face_facecolor[fkey]= (150,255,150)# edges:edgecolor ={}for (u, v) in edges: edgecolor[u, v]= (0,0,255)
7. Attributes
Additional data of the Mesh vertices, faces and edges could be saved with attributes.
7.a: extract attributes
Here are some methods to extract attributes of a specific vertex.
for vkey, attr in cablenet_mesh.vertices(data=True):print(vkey, attr)print(cablenet_mesh.vertex_attributes(vkey))print(cablenet_mesh.vertex_attribute(vkey, 'x'))
The methods to extract attributes can also be used to set attributes.
Move vertex 20 along positive x-axis 1 unit and along positive y-axis 2 unit. Update the mesh.
vkey =20ori_x = cablenet_mesh.vertex_attribute(vkey, "x")# get x attribute of the vertexori_y = cablenet_mesh.vertex_attribute(vkey, "y")# get y attribute of the vertexcablenet_mesh.vertex_attribute(vkey, "x", ori_x +1)# set x attribute of the vertexcablenet_mesh.vertex_attribute(vkey, "y", ori_y +2)# set y attribute of the vertex
7.c: update attributes
UsingMesh.update_default_edge_attributes(), Mesh.update_default_face_attributes() and Mesh.update_default_edge_attributes()could customize the default attributes of the elements. Now create new attributes q(force density) and f(axial force) for all edges and extract them.
cablenet_mesh.update_default_edge_attributes({'q': 1.0, 'f': 0.0})for (u, v), attr in cablenet_mesh.edges(data=True):print((u, v), attr)print(cablenet_mesh.edge_attributes((u, v)))print(cablenet_mesh.edge_attribute((u, v), 'q'))# get attribute of all edgesprint(cablenet_mesh.edges_attributes('qf'))print(cablenet_mesh.edges_attributes('q'))
(0, 6) {'q': 1.0, 'f': 0.0}
7.d: find elements by attributes
Mesh.vertices_where(), Mesh.faces_where() and Mesh.edges_where() can find elements of the mesh under a specific or a set of conditions.
Set a new vertex attribute "fixed", and by default False. Find the vertices in the corners and set the value to True. Fixed these vertices and smooth the mesh by moving every free vertex to the centroid of its neighbors using Mesh.smooth_centroid().