This example demonstrates mesh healing: repairing meshes that are not supersolid, e.g. with holes, missing faces, or non-manifold edges where an odd number of faces meet.
The pipeline shows how to import bad input, apply Operation::heal, and optionally clean up inner structures with Operation::selfUnion.
It also demonstrates exporting indexed triangles to preserve shared vertices and connectivity.
Note:
This C++ example uses
ExampleFramework.hh for POD geometry types and utilities.
Result

CMake setup
To use the C++ 17 API from CMake, add the Solidean C++ 17 language target and link it to your project:
# Add the Solidean C++ 17 API to your project
add_subdirectory(path/to/solidean/lang/cpp17)
# Link against the Solidean C++ 17 API
target_link_libraries(YourProject PRIVATE Solidean::Cpp17)
Code
#include <cstring>
#include <iostream>
#include <vector>
#include <solidean.hh>
#include "ExampleFramework.hh"
int main()
{
std::unique_ptr<solidean::Context> ctx = solidean::Context::create();
std::unique_ptr<solidean::ExactArithmetic> arithmetic = ctx->createExactArithmetic(10.f);
// create two overlapping cubes
auto const cubeA = example::createCube();
auto const cubeB = example::createCube({0.5, 0.5, 0.5});
/*
// schematic of the input projected to a plane
_________
| |
| ____|____
| | | |
|____|____| |
| |
|_________|
*/
// create a concatenation of all triangles
auto cubeConcat = cubeA;
for (auto const& t : cubeB)
cubeConcat.push_back(t);
// remove one triangle to create a hole
cubeConcat.pop_back();
// Some stats of the input mesh
std::cout << "Initial mesh contains of " << cubeConcat.size() << " unrolled triangles, i.e. " << cubeConcat.size() * 3 << " vertices." << std::endl;
std::unique_ptr<solidean::TypedBlob> blob = ctx->execute( //
*arithmetic,
[&](solidean::Operation& op)
{
// reinterpret our examplary triangle data type as solidean type
auto const triSpan = solidean::as_triangle3_span(cubeConcat);
// heal the mesh to fill the hole (missing triangle)
auto healed = op.heal(op.importFromTrianglesF32(triSpan, solidean::MeshType::NonSupersolid));
// create a self union to remove all inner structures
// (the intersection volume of the two original cubes)
auto selfUnioned = op.selfUnion(healed);
// export the mesh including topology (i.e. shared vertices)
return op.exportToIndexedTrianglesF32(selfUnioned);
});
auto const vertexSpan = blob->getPositionsF32<example::pos3>();
auto const indexSpan = blob->getTrianglesIndexed<example::tri_idx>();
auto const vertices = std::vector<example::pos3>(vertexSpan.begin(), vertexSpan.end());
auto const indices = std::vector<example::tri_idx>(indexSpan.begin(), indexSpan.end());
/*
// schematic of the output projected to a plane
_________
| |
| |____
| |
|____ |
| |
|_________|
*/
auto const [areaResult, volumeResult] = example::computeAreaAndVolume(vertices, indices);
// Some stats of the result mesh
std::cout << "Result mesh consists of " << indices.size() << " triangles and " << vertices.size() << " (potentially shared) vertices." << std::endl;
std::cout << "Result mesh has an area of " << areaResult << " and a volume of " << volumeResult << "." << std::endl;
return EXIT_SUCCESS;
}
Notes
-
Input mesh:
- The input is built from two overlapping cubes with one triangle removed to create a hole.
- Imported as
MeshType::NonSupersolid, since it contains holes and overlaps.
-
Healing step:
Operation::healrepairs the input to a supersolid mesh.- Healing always succeeds; every input is mapped to a valid supersolid, though exact semantics may vary.
-
Self-union step:
Operation::selfUnionremoves redundant inner structures, leaving a clean solid.
-
Export:
- Exported via
Operation::exportToIndexedTrianglesF32to produce indexed output with shared vertices. - This format is efficient for downstream rendering and analysis.
- Exported via
-
Result statistics:
- Final area and volume are computed from the healed, self-unioned mesh.
- Demonstrates how Solidean guarantees robust results even from broken geometry.
-
Practical use case:
- Mesh healing is critical when handling user-generated or imported geometry that cannot be assumed clean.
- This step is often combined with a self-union before further Booleans or queries.