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).