Healing Broken Geometry

Repair holes, overlaps, and self-intersections; export a clean, connected mesh.

The goal of this tutorial is to fix a deliberately broken mesh using Solidean’s healing pipeline. We will:

  1. Create a Context and ExactArithmetic
  2. Import a mesh that is not supersolid (holes/overlaps)
  3. Run heal to make it supersolid
  4. Run selfUnion to remove inner structure and ensure solidity
  5. Export indexed triangles (shared vertices, connected output)
  6. Compute area/volume to verify the result

Along the way, you’ll use: Context, ExactArithmetic, Operation::heal, Operation::selfUnion, Operation::exportToIndexedTrianglesF32, and MeshType::NonSupersolid.

Note:
All C++ tutorials/examples use ExampleFramework.hh for tiny POD types (pos3, triangle, tri_idx) and helpers.

1) Project setup (CMake)

Add the C++17 binding and link it:

add_subdirectory(path/to/solidean/lang/cpp17)
target_link_libraries(YourProject PRIVATE Solidean::Cpp17)

Ensure the Solidean dynamic library is discoverable at runtime (same folder as your binary or on your system path).

2) Minimal program

We concatenate two overlapping cubes, delete one triangle to create a hole, then repair the mesh and export an indexed result.

#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.5f, 0.5f, 0.5f});

    // create a concatenation of all triangles
    // NOTE: this is a single mesh that contains intersecting triangles now
    auto cubeConcat = cubeA;
    for (auto const& t : cubeB) cubeConcat.push_back(t);

    // remove one triangle to create a hole
    cubeConcat.pop_back();

    std::cout << "Initial mesh has " << cubeConcat.size() << " triangles (unrolled).\n";

    std::unique_ptr<solidean::TypedBlob> blob =
        ctx->execute(*arithmetic, [&](solidean::Operation& op)
        {
            // reinterpret example triangle type as Solidean triangle
            auto const triSpan = solidean::as_triangle3_span(cubeConcat);

            // 1) Heal: map arbitrary input → supersolid mesh
            auto healed = op.heal(op.importFromTrianglesF32(triSpan, solidean::MeshType::NonSupersolid));

            // 2) Self-union: remove inner structures; ensure a clean solid
            auto solid  = op.selfUnion(healed);

            // 3) Export indexed triangles (shared vertices, connected result)
            return op.exportToIndexedTrianglesF32(solid);
        });

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

    auto const [areaResult, volumeResult] = example::computeAreaAndVolume(vertices, indices);

    std::cout << "Result mesh: " << indices.size() << " triangles, "
              << vertices.size() << " shared vertices.\n";
    std::cout << "Area: " << areaResult << "  Volume: " << volumeResult << "\n";

    return EXIT_SUCCESS;
}

3) What you learned

  • Declare guarantees honestly: broken inputs must be marked as
    MeshType::NonSupersolid (or via builder flags).
  • Healing works on any input mesh:
    Operation::heal upgrades arbitrary geometry to a supersolid.
  • Make it strictly solid:
    Operation::selfUnion removes inner structure, yielding a solid mesh.
  • Export connected results:
    exportToIndexedTrianglesF32 deduplicates vertices and resolves T-junctions.
  • Exactness is preserved: floats are storage; Solidean converts to an exact internal representation on import.

4) Variations to try

Next steps