This page is meant to give a quick tour of the different API layers; there are more examples of Scheme-based designs in the Github repository.

## Scheme (high-level)

The `(libfive)` module for Guile Scheme has a few sets of high-level functions:

• `(libfive shapes)`: Basic 2D and 3D shapes
• `(libfive transforms)`: Geometric transforms (e.g. rotate / scale / twist)
• `(libfive csg)`: Constructive solid geometry (e.g. union / intersection / difference)
• `(libfive text)`: A distance-field based font and text layout tools

All of these modules (and their documentation!) are imported into the Studio editor by default, for a seamless experience.

This CSG solid is defined by the following code:

``````(difference (sphere 1 [0 0 0])
(sphere 0.6 [0 0 0])
(cylinder-z 0.6 2 [0 0 -1])
(reflect-xz (cylinder-z 0.6 2 [0 0 -1]))
(reflect-yz (cylinder-z 0.6 2 [0 0 -1])))
``````

The `[x y z]` notation is custom syntax for 3D vectors (in this case, the sphere center and cylinder base position).

## Scheme (low-level)

The `(libfive kernel)` module includes a set of functions and macros to directly manipulate functional representations of solids. Here's a low-level definition of a cube:

``````(define-shape (cube x y z)
(max (- x 1) (- -1 x)
(- y 1) (- -1 y)
(- z 1) (- -1 z)))
``````

Functional representations excel at coordinate transforms. Here's a transform that applies a twist to the original cube:

``````(remap-shape (cube x y z)
(+ (* (cos z) x) (* (sin z) y))
(- (* (cos z) y) (* (sin z) x))
z)
``````

Certain expressions are easier to represent as operations on vectors. Here's a function that generates a sphere given a center and radius, using `norm` to find the length of a 3D vector:

``````(define (sphere r center)
(lambda-shape (x y z)
(- (norm (- center [x y z])) r)))
``````

It's also possible to build custom CSG functions from scratch:

``````(define (blend a b m)
(min a b (+ (sqrt (abs a))
(sqrt (abs b))
(- m)) ))

(blend
(blend (sphere 1 [0 -1 -1])
(sphere 1 [0  1 -1]) 0.75)
(blend (sphere 1 [0 -1  1])
(sphere 1 [0  1  1]) 0.75)
0.75)
``````

## C

The C bindings are not intended for use directly; they're meant as a target for higher-level languages with a C FFI (e.g. most of them).

Still, here's an example showing a circle being constructed and saved as an SVG:

``````// All of these trees are manually managed and must be freed
// In higher-level languages, freeing can be attached to the object's
// destructor and run during garbage collection.
libfive_tree x = libfive_tree_x();
libfive_tree y = libfive_tree_y();

libfive_tree x2 = libfive_tree_unary(libfive_opcode_enum("square"), x);
libfive_tree y2 = libfive_tree_unary(libfive_opcode_enum("square"), y);
libfive_tree s = libfive_tree_binary(libfive_opcode_enum("add"), x2, y2);

libfive_tree one = libfive_tree_const(1);
libfive_tree out = libfive_tree_binary(libfive_opcode_enum("sub"), s, one);

// Select a 2D region to export, then write an SVG
libfive_region2 R;
R.X.lower = -2;
R.X.upper =  2;
R.Y.lower = -2;
R.Y.upper =  2;
libfive_tree_save_slice(out, libfive_region2 R, 0, 10, "circle.svg");

// Finally, clean up all of the intermediate trees
libfive_tree_free(x);
libfive_tree_free(y);
libfive_tree_free(x2);
libfive_tree_free(y2);
libfive_tree_free(s);
libfive_tree_free(one);
libfive_tree_free(out);
``````

## C++

Here at the bottom of the stack, the full power of `libfive` is unleashed!

There are many functions that haven't been wrapped as C or Scheme, either because they're too low-level or because no one has needed them yet; here at the C++ level, everything is on the table.

If you're building `libfive` into a larger C++-based application, you'll be spending a lot of time here. For example, Studio uses the C++ API extensively.

Here's a sphere; compare against the circle example above:

``````// Unlike the C bindings, the C++ interface manages memory automatically
// through flyweight handles and RAII.  These objects will be freed
// when they go out of scope
auto x = Kernel::Tree::X();
auto y = Kernel::Tree::Y();
auto z = Kernel::Tree::Z();

// Arithemetic is overloaded for the Kernel::Tree type
auto out = (x * x) + (y * y) + (z * z) - 1;

// Pick the target region to render
auto bounds = Region<3>({-2, -2, -2}, {2, 2, 2});

// Mesh::render returns a unique_ptr, so it cleans up automatically
Mesh::render(out, bounds)->saveSTL("sphere.stl");
``````

The C++ API uses C++11 features to automatically manage memory, and borrows a few ideas from Rust to enforce ownership semantics (e.g. returning `unique_ptr` rather than bare pointers).