Working with datastructures

Network, Mesh, VolMesh

The main library of the COMPAS framework contains three fundamental data structures:

  • Network

  • Mesh

  • VolMesh

These can be used as-is, but they can also be easily extended or combined to form entirely different data structures. For this tutorial, we will use the mesh data structure to demonstrate the general principles and give an overview of the possibilities.

../_images/datastructures.png

Construction

All datastructures come with factory constructors. These are implemented as class methods (using the @classmethod decoreator) and are named using the following pattern .from_xxx.

mesh = Mesh.from_data(...)
mesh = Mesh.from_json(...)
mesh = Mesh.from_obj(...)
mesh = Mesh.from_vertices_and_faces(...)
mesh = Mesh.from_polygons(...)
mesh = Mesh.from_polyhedron(...)
mesh = Mesh.from_points(...)

compas also provides sample data that can be used together with the constructors, for example for debugging or to generate example code.

from __future__ import print_function

import compas
from compas.datastructures import Mesh

mesh = Mesh.from_obj(compas.get('faces.obj'))

print(mesh)

# ================================================================================
# Mesh summary
# ================================================================================
#
# - name: Mesh
# - vertices: 36
# - edges: 60
# - faces: 25
# - vertex degree: 2/4
# - face degree: 2/4
#
# ================================================================================

Printing the mesh produces a summary of the mesh’s properties: the number of vertices, edges and faces and information about vertex and face degree.

Data

All data accessors are iterators; they are meant to be iterated over. Lists of data have to be constructed explicitly.

  • mesh.vertices()

  • mesh.faces()

  • mesh.halfedges()

  • mesh.edges()

from __future__ import print_function

import compas
from compas.datastructures import Mesh

mesh = Mesh.from_obj(compas.get('faces.obj'))

for key in mesh.vertices():
    print(key)

for key, attr in mesh.vertices(True):
    print(key, attr)

print(list(mesh.vertices()))
print(mesh.number_of_vertices())
from __future__ import print_function

import compas
from compas.datastructures import Mesh

mesh = Mesh.from_obj(compas.get('faces.obj'))

for fkey in mesh.faces():
    print(fkey)

for fkey, attr in mesh.faces(True):
    print(fkey, attr)

print(len(list(mesh.faces()))
print(mesh.number_of_faces())

Topology

  • mesh.is_valid()

  • mesh.is_regular()

  • mesh.is_connected()

  • mesh.is_manifold()

  • mesh.is_orientable()

  • mesh.is_trimesh()

  • mesh.is_quadmesh()

  • mesh.vertex_neighbours()

  • mesh.vertex_degree()

  • mesh.vertex_faces()

  • mesh.vertex_neighbourhood()

  • mesh.face_vertices()

  • mesh.face_halfedges()

  • mesh.face_neighbours()

  • mesh.face_neighbourhood()

  • mesh.face_vertex_ancestor()

  • mesh.face_vertex_descendant()

import compas
from compas.datastructures import Mesh
from compas.plotters import MeshPlotter

mesh = Mesh.from_obj(compas.get('faces.obj'))

plotter = MeshPlotter(mesh)

root = 17
nbrs = mesh.vertex_neighbours(root, ordered=True)

text = {nbr: str(i) for i, nbr in enumerate(nbrs)}
text[root] = root

facecolor = {nbr: '#cccccc' for nbr in nbrs}
facecolor[root] = '#ff0000'

plotter.draw_vertices(
    text=text,
    facecolor=facecolor,
    radius=0.15
)
plotter.draw_faces()
plotter.draw_edges()

plotter.show()
../_images/datastructures-1.png

Geometry

  • mesh.vertex_coordinates()

  • mesh.vertex_area()

  • mesh.vertex_centroid()

  • mesh.vertex_normal()

  • mesh.face_coordinates()

  • mesh.face_area()

  • mesh.face_centroid()

  • mesh.face_center()

  • mesh.face_normal()

  • mesh.face_flatness()

  • mesh.edge_coordinates()

  • mesh.edge_vector()

  • mesh.edge_direction()

  • mesh.edge_length()

  • mesh.edge_midpoint()

import compas
from compas.datastructures import Mesh
from compas.plotters import MeshPlotter

mesh = Mesh.from_obj(compas.get('faces.obj'))

plotter = MeshPlotter(mesh)

plotter.draw_vertices()
plotter.draw_faces(text={fkey: '%.1f' % mesh.face_area(fkey) for fkey in mesh.faces()})
plotter.draw_edges()

plotter.show()
../_images/datastructures-2.png