Basic Python API

Minimal Python example: create a context, run an exact boolean, export triangles, and write an OBJ.

Setup

To use the Python API, ensure the following:

  • The solidean.py module is available on your PYTHONPATH (e.g. by installing or placing it next to your script).
  • The dynamic library (solidean.dll on Windows, solidean.so on Linux) is discoverable by Python.
    • Either place it in the same folder as your script, or ensure it is on your system library path.

Once both are in place, import solidean should succeed.

Result

A cube subtracted from a cube

Code

import solidean
import array

ctx = solidean.Context.create()
arithmetic = ctx.create_exact_arithmetic(10.0)

tri_indices = [
    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,
]

verts_a = [
    -0.5, 0.5, -0.5,  # vertex 0
    0.5, 0.5, -0.5,   # vertex 1
    0.5, -0.5, -0.5,  # vertex 2
    -0.5, -0.5, -0.5, # vertex 3
    -0.5, 0.5, 0.5,   # vertex 4
    0.5, 0.5, 0.5,    # vertex 5
    0.5, -0.5, 0.5,   # vertex 6
    -0.5, -0.5, 0.5   # vertex 7
]

verts_b = [v + 0.25 for v in verts_a]

op = ctx.create_operation(arithmetic)
mA = op.import_from_indexed_triangles_f32(verts_a, tri_indices)
mB = op.import_from_indexed_triangles_f32(verts_b, tri_indices)
mR = op.difference(mA, mB)
blob = op.export_to_triangles_f32(mR)
r = ctx.execute(op)
assert r == solidean.ExecuteResult.Ok, f"execute error: {r.__doc__}"

tri_data = blob.get_data(solidean.DataSlot.TrianglesF32)
print(f"got {len(tri_data)} bytes result")

tri_data = array.array('f', tri_data)
print(f"equals {len(tri_data)} floats")
print(f"equals {len(tri_data) // 9} tris")

# Open the OBJ file for writing
with open('result.obj', 'w') as obj_file:
    # Write each triangle to the OBJ file
    for i in range(0, len(tri_data), 9):
        # Extract vertices of the triangle
        v1 = tri_data[i:i+3]
        v2 = tri_data[i+3:i+6]
        v3 = tri_data[i+6:i+9]

        # Write vertex lines to the OBJ file
        obj_file.write("v {} {} {}\n".format(*v1))
        obj_file.write("v {} {} {}\n".format(*v2))
        obj_file.write("v {} {} {}\n".format(*v3))
        
        # Write face line to the OBJ file
        j = i // 3
        obj_file.write("f {} {} {}\n".format(j+1, j+2, j+3))

Notes

  • Structure mirrors the abstract API closely:
    You explicitly Context::createOperation with an ExactArithmetic, record steps like Operation::import_from_indexed_triangles_f32, Operation::difference, and Operation::export_to_triangles_f32, then call Context.execute.
    Unlike the C++17 helper that takes a lambda and returns an export directly, Python follows the record-then-execute pattern explicitly for now.

  • Exactness model is identical:
    Context.create_exact_arithmetic defines the absolute bounding box used for internal exact arithmetic. Float inputs are treated as storage and converted to exact; robustness is not impacted.

  • Reading exported data:
    TypedBlob.get_data with DataSlot.TrianglesF32 returns a bytes-like object. Converting via array.array('f', data) gives 32-bit floats (9 floats per triangle: x0 y0 z0 x1 y1 z1 x2 y2 z2).
    The example writes a simple OBJ by unrolling vertices; for connected outputs, consider exporting ExportFormat.IndexedTriangles instead.

  • Result checking:
    Context.execute returns an ExecuteResult. The example asserts Ok; on failures, inspect the code (__doc__ provides a string) and see Troubleshooting for typical causes.

  • Performance considerations:
    The Python API has identical internal performance to the C++ API; all computation runs in the same backend.
    Currently, get_data copies the results into Python-owned memory (and the imports perform a similar copy due to unboxing). We are working on zero-copy integration with NumPy and other array libraries (see the roadmap) to reduce overhead and allow seamless downstream processing.