In this guide, you will learn fundamental elements to build and modify a mesh and a model in OpenGeode.

What are Builders?

As you may have noticed, OpenGeode Meshes and Models are read-only classes. You cannot modify them directly.

The goal of this design is to:

  1. clearly identify what operations will affect the class storage,
  2. give access to modifying methods on a shorter lifetime.

Every Mesh or Model has its own corresponding Builder, for example:

The builders inheritance diagram is the same as the one for the corresponding meshes and models. Like them, builders can be templated by their dimension. For example, two aliases are defined for TriangulatedSurfaceBuilder: TriangulatedSurfaceBuilder2D and TriangulatedSurfaceBuilder3D.

Create a Builder

First of all, let's create the builder for its corresponding object:

// Let's have a TriangulatedSurface3D& called mesh; auto mesh_builder = TriangulatedSurfaceBuilder3D::create( mesh ); ... BRep brep; BRepBuilder brep_builder( brep );

Using the static function Builder::create() will automatically identify the builder matching the object to modify it accordingly. So if you only need the inherited builder interface, you can do:

// Let's have a TriangulatedSurface3D& called mesh; auto mesh_builder = SurfaceMeshBuilder3D::create( mesh );

Mesh builders

We will use a simple PolygonalSurface (shown in the image below) and its builder and see what we can do.

There are 3 main types of operations on a surface:

  • create, modify or delete a point which is a vertex with coordinates
  • create, modify or delete a polygon (or a triangle)
  • create, modify or delete adjacency between polygons

Let's start with an example of mesh creation.

auto mesh = PolygonalSurface2D::create(); auto mesh_builder = PolygonalSurfaceBuilder2D::create( *mesh ); // Create some points const auto pt0 = mesh_builder->create_point( { {0., 0.} } ); const auto pt1 = mesh_builder->create_point( { {1., 0.} } ); const auto pt2 = mesh_builder->create_point( { {1., 1.} } ); const auto pt3 = mesh_builder->create_point( { {2., 0.} } ); const auto pt4 = mesh_builder->create_point( { {2., 1.} } ); // Create some polygons const auto poly0 = mesh_builder->create_polygon( {0, 1, 2} ); // a triangle const auto poly1 = mesh_builder->create_polygon( {1, 3, 4, 2} ); // a quad // Connect these polygons programmatically mesh_builder->set_polygon_adjacent( {poly0, 1}, poly1 ); // {poly0, 1} is the PolygonEdge to connect mesh_builder->set_polygon_adjacent( {poly1, 3}, poly0 ); // {poly1, 3} is the PolygonEdge to connect // or automatically mesh_builder->compute_polygon_adjacencies();

And now, two examples of deletion. For every element, you have to give which ones to keep and which ones to remove.

Deleting the polygon #0 will remove the polygon and renumber the remaining polygons.

mesh_builder->delete_polygons( {true, false} ); // Only the first polygon is removed

Deleting the vertex #3 will remove the vertex, renumber the remaining vertices and remove the polygons containing this vertex.

mesh_builder->delete_vertices( {false, false, false, true, false} ); // Only the fourth vertex is removed // To remove several vertices at once mesh_builder->delete_vertices( {false, true, false, true, false} ); // The second and fourth vertices are removed

Note: Deletion methods can renumber your entire mesh to keep continuous indexing. To know how the indexing was changed, all deletion methods return a table containing the mapping between the old index and the new index.

Equivalent methods can be found for all other mesh builders.

Model Builders

To build a model, you need to interact with three concepts:

  • add or remove a Component to the model
  • add or remove a relation between two model Components
  • add or remove information in the VertexIdentifier

Create the Components and their relations

There are predefined relations between Component types. We will use the following Section as example and build the following section:

Section section; SectionBuilder builder( section );

Create the components

const auto& corner0_id = builder.add_corner(); // Add a new corner and get its unique identifier const auto& corner0 = section.corner( corner0_id ); // Get the actual corner in the section ... const auto& line0_id = builder.add_line(); const auto& line0 = section.line( line0_id ); ... const auto& surface0_id = builder.add_surface(); const auto& surface0 = section.surface( surface0_id );

Create the relations

builder.add_corner_line_boundary_relationship( corner0, line3 ); builder.add_corner_line_boundary_relationship( corner0, line1 ); builder.add_corner_line_boundary_relationship( corner1, line0 ); builder.add_corner_line_boundary_relationship( corner1, line2 ); ... builder.add_line_surface_boundary_relationship( line0, surface0 ); builder.add_line_surface_boundary_relationship( line1, surface0 ); builder.add_line_surface_boundary_relationship( line2, surface0 ); builder.add_line_surface_boundary_relationship( line3, surface0 );

Complete the unique vertex identification

This unique identification is more complex to fill. You need to identify all the mesh component vertices that represent the same point in the model.

Let's focus only on the unique vertex corresponding to the corner0 in the picture. Then this vertex is representing the corner0, one vertex of line1 (assuming vertex #0) and line3 (assuming vertex #1) and one vertex (assuming vertex #3) of surface0.

const auto vertex_id = builder.create_unique_vertex(); builder.set_unique_vertex( {corner0.component_id(), 0}, vertex_id ); // Link the vertex #0 of corner0 to vertex_id builder.set_unique_vertex( {line1.component_id(), 0}, vertex_id ); // Link the vertex #0 of line1 to vertex_id builder.set_unique_vertex( {line3.component_id(), 1}, vertex_id ); // Link the vertex #1 of line3 to vertex_id builder.set_unique_vertex( {surface0.component_id(), 3}, vertex_id ); // Link the vertex #3 of surface0 to vertex_id

Repeat this process for every unique vertex of the section.