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