If your internal pipeline is half-edge based and requires strictly manifold meshes, you can directly export Solidean results in a half-edge representation. Solidean guarantees manifoldness at export time if you request it, even when inputs have ambiguous or degenerate structures.
This guide shows how to:
- Import two cubes that touch along a shared edge
- Perform a Boolean union
- Export the result as a half-edge mesh with the
Manifoldflag
Code
// Assumed to exist:
// solidean::Context* ctx;
// solidean::ExactArithmetic* arithmetic;
// Two unit cubes that share a single edge:
// centers at (-0.5, 0, -0.5) and (0.5, 0, 0.5); scale = 1.0
auto cubeA = example::createCube({-0.5f, 0.0f, -0.5f}, 1.0f);
auto cubeB = example::createCube({ 0.5f, 0.0f, 0.5f}, 1.0f);
// Boolean union → export as explicit half-edge with manifold guarantee
auto blob = ctx->execute(*arithmetic, [&](solidean::Operation& op)
{
auto mA = op.importFromTrianglesF32(solidean::as_triangle3_span(cubeA));
auto mB = op.importFromTrianglesF32(solidean::as_triangle3_span(cubeB));
auto mU = op.union_(mA, mB);
auto opts = solidean::ExportOption::VertexPositionF32
| solidean::ExportOption::Manifold
| solidean::ExportOption::HalfedgeToVertex
| solidean::ExportOption::HalfedgeToNextHalfedge
| solidean::ExportOption::HalfedgeToOppositeHalfedge
| solidean::ExportOption::HalfedgeToFace;
return op.exportMesh(mU, solidean::ExportFormat::HalfedgeExplicit, opts);
});
// Read back half-edge topology and positions (names may vary in your SDK; adapt as needed)
auto posSpan = blob->getPositionsF32<example::pos3>();
std::vector<example::pos3> positions(posSpan.begin(), posSpan.end());
// Half-edge relations (int32 indices)
auto he2vSpan = blob->getHalfedgeToVertex();
auto he2nSpan = blob->getHalfedgeToNextHalfedge();
auto he2oSpan = blob->getHalfedgeToOppositeHalfedge();
auto he2fSpan = blob->getHalfedgeToFace();
auto he_to_vertex = std::vector<int32_t>(he2vSpan.begin(), he2vSpan.end());
auto he_to_next = std::vector<int32_t>(he2nSpan.begin(), he2nSpan.end());
auto he_to_opp = std::vector<int32_t>(he2oSpan.begin(), he2oSpan.end());
auto he_to_face = std::vector<int32_t>(he2fSpan.begin(), he2fSpan.end());
std::cout << "Half-edges: " << he_to_vertex.size() << "\n"
<< "Vertices : " << positions.size() << "\n";
// Example: verify manifold export implies valid opposite links for all half-edges
// (Opposite indices are valid; faces/next pointers define per-face cycles.)
bool ok = true;
for (size_t h = 0; h < he_to_vertex.size(); ++h) {
int32_t const o = he_to_opp[h];
if (o < 0 || o >= (int32_t)he_to_vertex.size() || he_to_opp[o] != (int32_t)h) { ok = false; break; }
}
std::cout << "Opposite symmetry check: " << (ok ? "OK" : "FAILED") << "\n";
Notes
-
Halfedge format:
By choosingExportFormat::HalfedgeExplicit, you request explicit halfedge connectivity.
Use [ExportOption::HalfedgeToFace] and [ExportOption::HalfedgeToVertex] to retrieve mappings. -
Manifold guarantee:
TheExportOption::Manifoldflag ensures Solidean will duplicate vertices if necessary, so the resulting mesh is strictly manifold and suitable for half-edge traversal. -
Performance:
Manifold remapping is lightweight and does not change geometry — only the topological representation. -
Alternatives:
If you don’t need manifold guarantees, you can skip the flag. The output may then contain non-manifold edges if the input required them.
ExportFormat::HalfedgeImplicitOpposite (opposite halfedge = h ^ 1) and
ExportFormat::HalfedgeImplicitNext (all halfedges of a polygon stored contiguously) are currently under development.
If these formats would significantly benefit your pipeline, please get in touch — we may be able to fast-track support.