Skip to content

Builders

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 :

cpp
// Let's have a TriangulatedSurface3D& called mesh
auto mesh_builder = TriangulatedSurfaceBuilder3D::create( mesh );
...
// Let's have a BRep& called brep
BRepBuilder brep_builder( brep );
// Let's have a TriangulatedSurface3D& called mesh
auto mesh_builder = TriangulatedSurfaceBuilder3D::create( mesh );
...
// Let's have a BRep& called 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 :

cpp
// Let's have a TriangulatedSurface3D& called mesh
auto mesh_builder = SurfaceMeshBuilder3D::create( mesh );
// 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.

Builders

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.

cpp
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();
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.

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

Builders 1

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

cpp
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
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

Builders 2

Note: Deletion methods can change the indices of 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 :

Builders 3

cpp
Section section;
SectionBuilder builder( section );
Section section;
SectionBuilder builder( section );

Create the components

cpp
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 );
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

cpp
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 );
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.

cpp
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
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.

Geode-solutions' documentation website