Basic Mesh Healing

Fix a broken mesh with missing faces and overlapping geometry using the C++17 API.

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

A simple non-supersolid cube duo after repair

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::heal repairs 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:

  • Export:

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