Basic C++ 17 API

Using the Solidean C++ 17 API: create a context, run a boolean, and export triangles.

This example demonstrates the minimal flow using the C++ 17 API:
Create a context → set up arithmetic → define an operation → import meshes → run a boolean → export results.

Result

A cube subtracted from a cube

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()
{
    // Create the solidean context which manages operations and data, throws an exception if unsuccessful
    // Note that (like most methods of the solidean c++ API), return type is a unique_ptr which automatically destroys the object at the end of the scope
    std::unique_ptr<solidean::Context> ctx = solidean::Context::create();

    // The exact arithmetic describes the uniform volume in which all operations take place
    // It must be large enough to at least contain all input mesh extents
    // Note that the provided value describes the extent in all three axes, positive and negative
    std::unique_ptr<solidean::ExactArithmetic> arithmetic = ctx->createExactArithmetic(10.f); // uniform cube of 20 units side length, centered at the origin


    // Create two simple cube meshes

    // Vertices consist of 3 consecutive floats
    std::vector<solidean::pos3> vertsA;
    std::vector<solidean::pos3> vertsB;
    // Triangles consist of 3 consecutive ints
    std::vector<solidean::idxtri> trisA;
    std::vector<solidean::idxtri> trisB;

    // Define the indices for the cube
    trisA = trisB = {
        {0, 1, 2}, // front face
        {0, 2, 3}, //
        {4, 6, 5}, // back face
        {4, 7, 6}, //
        {1, 5, 6}, // right face
        {1, 6, 2}, //
        {0, 7, 4}, // left face
        {0, 3, 7}, //
        {3, 2, 6}, // top face
        {3, 6, 7}, //
        {0, 5, 1}, // bottom face
        {0, 4, 5},
    };

    // Define the vertices for the cube
    vertsA = vertsB = {
        {-0.5f, 0.5f, -0.5f},  // vertex 0
        {0.5f, 0.5f, -0.5f},   // vertex 1
        {0.5f, -0.5f, -0.5f},  // vertex 2
        {-0.5f, -0.5f, -0.5f}, // vertex 3
        {-0.5f, 0.5f, 0.5f},   // vertex 4
        {0.5f, 0.5f, 0.5f},    // vertex 5
        {0.5f, -0.5f, 0.5f},   // vertex 6
        {-0.5f, -0.5f, 0.5f}   // vertex 7
    };

    // Offset the vertices of the second cube so that there is only partial overlap
    for (auto& v : vertsB)
    {
        v.x += 0.25f;
        v.y += 0.25f;
        v.z += 0.25f;
    }

    // Execute some operations via a lambda function and return the result of an export function
    std::unique_ptr<solidean::TypedBlob> blob = //
        ctx->execute(                           //
            *arithmetic,
            [&](solidean::Operation& op)
            {
                // Import meshes from the previously defined vertices/indices
                auto meshA = op.importFromIndexedTrianglesF32(vertsA, trisA);
                auto meshB = op.importFromIndexedTrianglesF32(vertsB, trisB);

                // Compute A - B and export (unrolled) float triangles
                return op.exportToTrianglesF32(op.difference(meshA, meshB));
            });


    // The data blob contains (immutable) unrolled triangle data
    auto const triangleSpan = blob->getTrianglesF32<example::triangle>();

    // Copy the triangle data to a vector for further processing
    auto const triangles = std::vector<example::triangle>(triangleSpan.begin(), triangleSpan.end());

    // Compute area and volume
    auto [area, volume] = example::computeAreaAndVolume(triangles);
    std::cout << "The result consists of " << triangles.size() << " triangles. Area is " << area << ". Volume is " << volume << "." << std::endl;

    return EXIT_SUCCESS;
}

Notes

  • This example is written in a slightly more verbose style:

    • Explicit types instead of relying on auto where it helps readability.
    • Useful as a first exposure to the API before moving on to more compact code.
  • The C++17 API is a thin wrapper over the abstract API you see in the reference:

    • For example, Context::execute here uses a helper function that accepts a lambda.
      This makes it possible to group multiple operations, import meshes, and return the result of an export in a single call.
    • The underlying abstract API exposes operations more directly and requires explicit sequencing.
  • All Solidean objects are returned as std::unique_ptr for automatic lifetime management.

    • This ensures proper cleanup when objects leave scope.
    • You can easily upgrade to std::shared_ptr if shared ownership across components is needed.
  • The code uses ExampleFramework.hh for convenience:

    • Provides simple types (triangle, pos3, idxtri) to keep examples self-contained.
  • The example demonstrates how to:

    • Define input geometry in plain vectors.
    • Perform an exact Boolean difference (A - B).
    • Export the result as float32 triangles.
    • External "validation" with a simple framework via surface area and volume.