Expressions
Note: Most designs never touch custom expressions. Skip this page unless you are building CAM outline functions or a highly specialized cut that needs custom math.
Expressions are the pieces that fit inside statements: numbers, point helpers, comparisons, and function calls.
Numbers, booleans, and strings
- Numbers accept integers and decimals (
42,0.18). - Booleans are just
trueandfalse. - Strings live inside double quotes and support escapes like
\"and\n. You will mostly see them inname =or function bodies.
Optimizable numbers use a +/- hint—41.8 +/- 2.0 or 1.76 +/- 5%—to record a starting value and a search radius for the optimizer.
String Methods
Strings act like primitive values but support several methods:
str.length: Property returning the length of the string.str.concat(other): Returns a new string withotherappended.str.toUpperCase(): Returns a new string in uppercase.str.toLowerCase(): Returns a new string in lowercase.str.includes(substring): Returns true if the string contains the substring.str.startsWith(prefix): Returns true if the string starts with the prefix.str.endsWith(suffix): Returns true if the string ends with the suffix.
Arrays and indexing
Square brackets ([ and ]) create an array literal that captures a list of numeric expressions evaluated right away. Example: tiers = [ 41.8, 32.5, 28.0 +/- 0.5 ]. Arrays are zero-based, so tiers[0] returns the first entry, tiers[1] the next, and so on. Every access is bounds-checked—tiers[3] would halt the interpreter if the array only stored three items—so you get fast feedback when a loop walks too far.
Array Methods
Arrays come with methods to process data efficiently. Note that mutation methods (push, pop, etc.) are pure and return a new array.
arr.length: Property returning the number of elements.arr.push(val, ...): Returns a new array with items added to the end.arr.pop(): Returns a new array with the last item removed.arr.unshift(val, ...): Returns a new array with items added to the start.arr.shift(): Returns a new array with the first item removed.arr.concat(other): Returns a new array combining this array with another array or value.arr.map(callback): Transforms the array.nums.map(x => x * 2)arr.filter(callback): Selects items.nums.filter(x => x > 10)arr.reduce(callback, initial): Folds the array into a single value.arr.forEach(callback): Iterates over the array (returns null).arr.find(callback): Returns the first item where callback returns true, or null.arr.includes(val): Returns true if the array contains the value.arr.some(callback): Returns true if any item matches the callback.arr.every(callback): Returns true if all items match the callback.arr.average(): Returns the average of numbers or the centroid of points/vectors.arr.sum(): Returns the sum of all numbers in the array.arr.min(): Returns the minimum number.arr.max(): Returns the maximum number.
Handy functions
Standard math functions are available under the Math namespace.
concat(args...): Concatenates strings or arrays. Example:concat("Gem", 1)produces"Gem1".Math.range(start, end, step): Creates an array of numbers. Example:Math.range(0, 10, 2)produces[0, 2, 4, 6, 8].Math.clamp(val, min, max): Clamps a value between min and max.Math.lerp(a, b, t): Linearly interpolates between a and b.Math.sin(x),Math.cos(x),Math.tan(x)Math.asin(x),Math.acos(x),Math.atan(x),Math.atan2(y, x)Math.pow(base, exp),Math.log(n)(natural log)Math.toRadians(deg),Math.toDegrees(rad)Math.sqrt(x),Math.abs(x),Math.floor(x),Math.ceil(x),Math.round(x),Math.min(a, b, ...),Math.max(a, b, ...)Math.sign(x),Math.trunc(x),Math.cbrt(x),Math.hypot(x, y, ...)
Geometry Properties
The global stone() function returns an object containing geometric properties of the stone as it currently exists. These are useful for optimization targets or conditional logic.
stone().crownHeight: Returns the crown height as a percentage of total depth.stone().pavilionDepth: Returns the pavilion depth as a percentage of total depth.stone().girdleThickness: Returns the average girdle thickness as a percentage of width.stone().lengthWidthRatio: Returns the length-to-width ratio of the stone.stone().facetCount: Returns the total number of facets cut so far.stone().tablePercentage: Returns the table width as a percentage of the stone width.stone().depthPercentage: Returns the total depth as a percentage of width.
Geometry Methods
Vectors and points (created by Vector() or point helpers) support several built-in methods:
v.length(): Returns the length of the vector.v.normalize(): Returns a unit vector (length 1).v.dot(other): Returns the dot product with another vector (scalar).v.cross(other): Returns the cross product with another vector (new vector).v.distance(other): Returns the Euclidean distance to another point or vector.v.angle(other): Returns the angle in radians between two vectors.v.angleSigned(other, axis): Returns the signed angle in radians betweenvandotheraroundaxis.v.lerp(other, t): Linearly interpolates betweenvandotherby factort(0.0 to 1.0). Works on Vectors, Points, and Normals.v.slerp(other, t): Spherical linear interpolation betweenvandother. Smoothly interpolates direction along the shortest arc.v.reflect(normal): Reflects a vector against a normal. Points can also reflect against aPlaneor anotherPoint.v.rotate(axis, angle): Rotates the vector (or point) around anaxisvector byangleradians.v.rotateAround(pivot, axis, angle): Rotates a point around apivotpoint usingaxisvector andangleradians. (Only for Points).v.project(other): Projects vectorvontoother.v.midpoint(other): Returns the midpoint betweenvandother.v.lengthSquared(): Returns the squared length of the vector.v.clampLength(max): Returns a vector in the same direction but with magnitude limited tomax.v.toArray(): Returns the components as[x, y, z].
v1 = Vector(1, 0, 0)
v2 = Vector(0, 1, 0)
angle = v1.angle(v2) // 1.5707... (Math.PI/2)
dist = v1.distance(v2) // 1.414... (Math.sqrt(2))
mid = v1.midpoint(v2) // Vector(0.5, 0.5, 0)
rot = v1.rotate(Vector(0, 0, 1), Math.PI/2) // Vector(0, 1, 0)
proj = Vector(1,1,0).project(Vector(1,0,0)) // Vector(1,0,0)
arr = v1.toArray() // [1, 0, 0]
print("Angle:", angle)
print("Distance:", dist)
print("Midpoint:", mid)
print("Rotated:", rot)
print("Projected:", proj)
print("Array:", arr)
Plane Methods
Planes created via Plane(origin, normal) or Plane(p1, p2, p3) have properties and methods:
p.origin: The origin point of the plane.p.normal: The normal vector of the plane.p.distance(point): Returns the signed distance from the plane to a point. Positive if on the side of the normal.p.project(point): Projects a point onto the plane, returning the closest point on the surface.p.intersect(origin, direction): Returns the intersection point of a ray (defined byoriginpoint anddirectionvector) with the plane. Returnsnullif parallel.
floor = Plane(Point(0,0,0), Vector(0,0,1))
p = Point(10, 10, 5)
h = floor.distance(p) // 5.0
shadow = floor.project(p) // Point(10, 10, 0)
print("Distance to floor:", h)
print("Shadow point:", shadow)
Conditionals (Ternary Operator)
Use the ternary operator ? : to select between two values based on a condition.
// Ternary operator example
angle = 45.0
// Condition ? Value if true : Value if false
description = angle > 40 ? "steep" : "shallow"
print(description)
// Chained ternary
grade = 85
result = grade >= 90 ? "A"
: grade >= 80 ? "B"
: "C"
print(result)
Point helpers
Point helpers return locations in space and slot neatly into facet commands or variables. Store them with point = mp(P1, G1) and reuse as often as you like. The edge(...) helper returns an array of two points representing the ends of the edge between two facets. You can pass this directly to ep() or access points by index. When you need deeper explanations or syntax variations, head to the dedicated Point Helper Reference for cp(), gp(), mp(), ep(), Point(), and edge().
Everything in motion
Paste this snippet into the studio to see several expression types working together:
name = "Expression Tour"
gear = 96
P1 0 @ 41.8 : cp() x8
P3 1 @ (43 - 1.2) : cp() // parentheses clarify the expression
G1 0 @ Math.toDegrees(Math.atan2(1, 0)) : size x16
C1 0 @ Math.toDegrees(Math.toRadians(32.0) + 0.1) : mp(P1, G1) + girdle
C2 0 @ 28.0 : ep(edge(C1:0, C1:6), 0.5)
shoulder = mp(P1, P3, G1)
show(shoulder, "green")