This guide is a Swiss-army repair pass: take any triangle soup and produce a solid, watertight, manifold result with clean indexed topology.
We assume you already have ctx (solidean::Context*), arithmetic (ExactArithmetic&), and std::vector<example::triangle> triangles.
Referenced API:
MeshType::NonSupersolid,
Operation::heal,
Operation::selfUnion,
Operation::exportMesh,
ExportFormat::IndexedTriangles,
ExportOption::Manifold,
ExportOption::RemoveSpuriousVertices.
Repair → Solid → Manifold (indexed)
#include <vector>
#include <solidean.hh>
#include "ExampleFramework.hh" // triangle, pos3, tri_idx
// Inputs assumed to exist:
// solidean::Context* ctx;
// std::unique_ptr<solidean::ExactArithmetic> arithmetic;
// std::vector<example::triangle> triangles;
auto blob = ctx->execute(*arithmetic, [&](solidean::Operation& op)
{
// 1) Import as *NonSupersolid* to declare: “this soup may have holes / open borders / non-manifold bits”
auto in = op.importFromTrianglesF32(
solidean::as_triangle3_span(triangles),
solidean::MeshType::NonSupersolid);
// 2) Heal → make it supersolid (fills holes / resolves inconsistencies best-effort)
auto healed = op.heal(in);
// 3) Self-union → remove internal self-overlaps and nested structure → strictly *solid*
auto solid = op.selfUnion(healed);
// 4) Export: indexed triangles + guarantees
// - Manifold: topologically manifold decomposition (duplicates a few indices where necessary)
// - RemoveSpuriousVertices: cleans edge-midpoint artifacts on coplanar, same-ID regions
auto options = solidean::ExportOption::VertexPositionF32
| solidean::ExportOption::Manifold
| solidean::ExportOption::RemoveSpuriousVertices;
return op.exportMesh(solid, solidean::ExportFormat::IndexedTriangles, options);
});
// Access indexed topology
auto pos = blob->getPositionsF32<example::pos3>();
auto tris = blob->getTrianglesIndexed<example::tri_idx>();
auto positions = std::vector<example::pos3>(pos.begin(), pos.end());
auto indices = std::vector<example::tri_idx>(tris.begin(), tris.end());
// `positions` + `indices` now form a clean, watertight, manifold surface.
Optional: export with explicit half-edges
If you need rich adjacency (e.g., robust editing / analysis), export a half-edge structure instead:
auto options = solidean::ExportOption::VertexPositionF32
| solidean::ExportOption::Manifold
| solidean::ExportOption::RemoveSpuriousVertices
| solidean::ExportOption::HalfedgeToVertex
| solidean::ExportOption::HalfedgeToNextHalfedge
| solidean::ExportOption::HalfedgeToOppositeHalfedge;
auto heBlob = ctx->execute(*arithmetic, [&](solidean::Operation& op)
{
auto in = op.importFromTrianglesF32(solidean::as_triangle3_span(triangles),
solidean::MeshType::NonSupersolid);
auto solid = op.selfUnion(op.heal(in));
return op.exportMesh(solid, solidean::ExportFormat::HalfedgeExplicit, options);
});
// Then read PositionsF32, HalfedgeToVertex, HalfedgeToNextHalfedge, HalfedgeToOppositeHalfedge, etc.
Notes
- When to use this recipe: whenever input is unknown quality or known to be “bad” (holes, open borders, self-intersections, non-manifold).
- Why
healthenselfUnion:Operation::healconverts arbitrary soup into a supersolid mesh (closed in the “winding-number” sense).Operation::selfUnioncollapses internal overlaps/duplicates to produce a strictly solid boundary.
- Manifold guarantee:
ExportOption::Manifoldensures a manifold decomposition of the output without inventing geometry (it may duplicate vertex indices to separate sheets).
UseExportOption::PreferLargerManifoldsif you want the largest possible manifolds when ambiguous. - Spurious vertices:
RemoveSpuriousVerticesremoves mid-edge artifacts that can appear on coplanar, same-provenance regions. - Positions: example uses
VertexPositionF32. For exact or plane-based positions, seeExportOption::VertexPositionExactandVertexPositionPlanes. - Performance: this is a do-it-all pass; for trusted data, you can skip
healorselfUnionas appropriate.