Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Solid Modeling

In Convex-λ, a "Solid" or "Stone" is defined as the intersection of half-spaces defined by planes. You "cut" a stone by adding planes.

5 Ways to Make a Cube

Here are five different ways to define a Cube of size 2 (extending from -1 to 1).

1. The Built-in Function

The simplest way.

c1 = Cube(2)
_ := c1
assert(c1.length == 6, "Builtin Cube")

2. Explicit Planes

Defining all 6 faces manually.

planes = [
    Plane(Vector( 1, 0, 0), 1), // Right
    Plane(Vector(-1, 0, 0), 1), // Left
    Plane(Vector( 0, 1, 0), 1), // Front
    Plane(Vector( 0,-1, 0), 1), // Back
    Plane(Vector( 0, 0, 1), 1), // Top
    Plane(Vector( 0, 0,-1), 1)  // Bottom
]
_ := planes
assert(planes.length == 6, "Explicit Planes")

3. Convex Hull of Points

Defining the 8 vertices and letting the Hull function calculate the planes.

// Helper to make code shorter
pm = [-1, 1]

// Generate all 8 points using functional mapping
points = pm |> (x) =>
    pm |> (y) =>
        pm |> (z) => Point(x, y, z)

// Note: This produces a nested array [[[Point...]]]
// but Hull flattens it automatically.
cube_hull = Hull(points)
_ := cube_hull
assert(cube_hull.length == 6, "Hull Cube")

4. Symmetry (Rotation)

Define one side face and rotate it 4 times, then add Top and Bottom.

// Side face (Right)
side = Plane(Vector(1,0,0), 1)

// Symmetry group: 4-fold rotation around Z
rotZ = Rotate(Vector(0,0,1), 4)

// Apply rotation
walls = side |> rotZ

// Add caps
caps = [
    Plane(Vector(0,0,1), 1),
    Plane(Vector(0,0,-1), 1)
]

full = walls + caps
_ := full
assert(full.length == 6, "Symm Cube")

5. Intersection of Slabs

A cube is the intersection of 3 perpendicular "slabs" (infinite strips).

// Function to make a slab (pair of parallel planes)
make_slab = (normal, width) => [
    Plane(normal, width/2),
    Plane(-normal, width/2)
]

slab_x = make_slab(Vector(1,0,0), 2)
slab_y = make_slab(Vector(0,1,0), 2)
slab_z = make_slab(Vector(0,0,1), 2)

slab_cube = slab_x + slab_y + slab_z
_ := slab_cube
assert(slab_cube.length == 6, "Slab Cube")

Platonic Solids

Tetrahedron

Using Hull of 4 points.

s = sqrt(2)
tetra_pts = [
    Point(1, 0, -1/s),
    Point(-1, 0, -1/s),
    Point(0, 1, 1/s),
    Point(0, -1, 1/s)
]
tetra = Hull(tetra_pts)
_ := tetra
assert(tetra.length == 4, "Tetrahedron")

Octahedron

Using the built-in or symmetry.

// Built-in
oct1 = Octahedron(2)
_ := oct1
assert(oct1.length == 8, "Octahedron Builtin")

// Or Intersecting Pyramids
pyramid_top = Plane(Vector(1,0,1), 1) |> Rotate(Vector(0,0,1), 4)
pyramid_bot = Plane(Vector(1,0,-1), 1) |> Rotate(Vector(0,0,1), 4)
oct2 = pyramid_top + pyramid_bot
_ := oct2
assert(oct2.length == 8, "Octahedron Symm")

Dodecahedron

Defined by 12 planes.

phi = (1 + sqrt(5)) / 2

// 1. A plane perpendicular to a vertex of a cube
p1 = Plane(Vector(0, 1, phi), 1)

// 2. Rotate it to cover all variations
// This requires complex icosahedral symmetry groups
// which we can simulate by permuting coordinates manually or using Hull.

Note: For complex solids like Dodecahedron and Icosahedron, calculating the Hull of their vertices is often easier.

Archimedean Solids

Truncated Cube

Start with a Cube, then cut off the corners.

// 1. Make the Cube
_ := Cube(2)

// 2. Cut corners
// A corner is at (1,1,1). The normal pointing at it is Vector(1,1,1).
corner_cut = Plane(Vector(1,1,1), 1.5)

// Apply 4-fold symmetry around Z, then Mirror Z
// Combine symmetry groups first
group = Rotate(Vector(0,0,1), 4) * Mirror(Plane(Vector(0,0,1), 0))
cuts = corner_cut |> group

_ := cuts
assert(cuts.length == 8, "Truncated Corners")