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

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 true and false.
  • Strings live inside double quotes and support escapes like \" and \n. You will mostly see them in name = 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 with other appended.
  • 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 between v and other around axis.
  • v.lerp(other, t): Linearly interpolates between v and other by factor t (0.0 to 1.0). Works on Vectors, Points, and Normals.
  • v.slerp(other, t): Spherical linear interpolation between v and other. Smoothly interpolates direction along the shortest arc.
  • v.reflect(normal): Reflects a vector against a normal. Points can also reflect against a Plane or another Point.
  • v.rotate(axis, angle): Rotates the vector (or point) around an axis vector by angle radians.
  • v.rotateAround(pivot, axis, angle): Rotates a point around a pivot point using axis vector and angle radians. (Only for Points).
  • v.project(other): Projects vector v onto other.
  • v.midpoint(other): Returns the midpoint between v and other.
  • v.lengthSquared(): Returns the squared length of the vector.
  • v.clampLength(max): Returns a vector in the same direction but with magnitude limited to max.
  • 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 by origin point and direction vector) with the plane. Returns null if 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")