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

Operators

Convex-λ is built on a rich operator system that often behaves differently depending on the types of the operands (Polymorphism). This allows for concise and expressive geometric logic.

This chapter details every operator with extensive examples.

Mathematical Operators

Addition +

Used for arithmetic addition, vector translation, and array concatenation.

1. Number + Number Standard addition.

sum = 10 + 5  // 15
assert(sum == 15, "Add Num")

2. Vector + Vector Component-wise addition.

v1 = Vector(1, 0, 0)
v2 = Vector(0, 1, 0)
v3 = v1 + v2  // Vector(1, 1, 0)
assert(v3 == Vector(1, 1, 0), "Add Vec")

3. Point + Vector Translates a point by a vector.

p = Point(0, 0, 0)
v = Vector(0, 0, 5)
p_new = p + v  // Point(0, 0, 5)
assert(p_new == Point(0, 0, 5), "Point Translate")

4. Array + Array Concatenates two arrays.

arr1 = [1, 2]
arr2 = [3, 4]
arr3 = arr1 + arr2  // [1, 2, 3, 4]
assert(arr3.length == 4, "Array Concat")

5. Array + Scalar (Broadcast) Adds the scalar to every element of the array.

nums = [10, 20, 30]
result = nums + 5  // [15, 25, 35]
assert(result[0] == 15, "Array Broadcast +")

Subtraction -

Used for arithmetic subtraction, vector difference, and unary negation.

1. Number - Number

diff = 10 - 3  // 7
assert(diff == 7, "Sub Num")

2. Vector - Vector

v1 = Vector(1, 1, 1)
v2 = Vector(0, 0, 1)
v3 = v1 - v2  // Vector(1, 1, 0)
assert(v3 == Vector(1, 1, 0), "Sub Vec")

3. Unary Negation Negates numbers or vectors.

n = -10
v = -Vector(1, 0, 0)  // Vector(-1, 0, 0)
assert(v.x == -1, "Negate Vec")

4. Array Subtraction (Broadcast)

arr = [10, 20, 30]
res = arr - 5  // [5, 15, 25]
assert(res[0] == 5, "Array Broadcast -")

Multiplication *

Used for scaling, dot products, symmetry composition, and intersection.

1. Number * Number

prod = 6 * 7  // 42
assert(prod == 42, "Mul Num")

2. Vector * Number Scales the vector.

v = Vector(1, 0, 0)
scaled = v * 5  // Vector(5, 0, 0)
assert(scaled.x == 5, "Scale Vec")

3. Plane * Plane (Intersection) Returns the Line where two planes intersect.

pl1 = Plane(Vector(1,0,0), 0) // YZ plane
pl2 = Plane(Vector(0,1,0), 0) // XZ plane
line = pl1 * pl2  // Line along Z axis
assert(line.dir.z == 1 || line.dir.z == -1, "Plane Intersect")

4. Line * Plane (Intersection) Returns the Point where a line hits a plane.

line = Line(Point(0,0,10), Vector(0,0,-1))
plane = Plane(Vector(0,0,1), 0)
hit = line * plane  // Point(0,0,0)
assert(hit == Point(0,0,0), "Line Plane Hit")

5. Symmetry Group Composition Combines two symmetry operations.

// Rotate * Mirror composition
g = Rotate(Vector(0,0,1), 4) // * Mirror(...)

Division /

Used for arithmetic division and scaling.

1. Number / Number

quo = 10 / 2  // 5
assert(quo == 5, "Div Num")

2. Vector / Number Scales the vector by 1/N.

v = Vector(10, 0, 0)
scaled = v / 2  // Vector(5, 0, 0)
assert(scaled.x == 5, "Div Vec")

3. Point / Number Scales the point's coordinates (relative to origin).

p = Point(10, 10, 10)
scaled = p / 2  // Point(5, 5, 5)
assert(scaled.x == 5, "Div Point")

4. Array / Number (Broadcast)

arr = [10, 20, 30]
res = arr / 10  // [1, 2, 3]
assert(res[0] == 1, "Div Array")

5. Midpoint Calculation Combining + and / to find a midpoint.

p1 = Point(0, 0, 0)
p2 = Point(10, 10, 10)
mid = (p1 + p2) / 2  // Point(5, 5, 5)
assert(mid.x == 5, "Midpoint")

Modulo / Cross Product %

Overloaded for remainder and vector cross product.

1. Number % Number Euclidean remainder.

rem = 10 % 3  // 1
assert(rem == 1, "Mod")

2. Negative Modulo Handles negative numbers correctly (Euclidean).

val = -10 % 3  // 2 (not -1)
assert(val == 2, "Euclidean Mod")

3. Array Broadcast

nums = [10, 11, 12]
mods = nums % 2  // [0, 1, 0]
assert(mods[1] == 1, "Mod Array")

Power / Distance ^

Overloaded for exponentiation and distance calculation.

1. Number ^ Number Exponentiation.

sq = 5 ^ 2  // 25
assert(sq == 25, "Pow")

2. Vector ^ Vector (Distance) Euclidean distance between two vectors tips.

v1 = Vector(0, 0, 0)
v2 = Vector(3, 4, 0)
dist = v1 ^ v2  // 5
assert(dist == 5, "Vec Dist")

3. Point ^ Point (Distance) Distance between two points.

p1 = Point(0, 0, 0)
p2 = Point(1, 1, 1)
dist = p1 ^ p2  // sqrt(3) ~ 1.732
assert(abs(dist - 1.732) < 0.001, "Point Dist")

4. Array Broadcast

nums = [1, 2, 3]
squares = nums ^ 2  // [1, 4, 9]
assert(squares[2] == 9, "Pow Array")

Projection >>

Projects a point onto a plane.

1. Point >> Plane Projects the point onto the plane surface along the normal.

pt = Point(0, 0, 10)
pl = Plane(Vector(0,0,1), 0) // XY Plane
// Projects pt onto pl
proj = pt >> pl
assert(proj.z == 0, "Projection")

2. Array >> Plane Projects multiple points.

pts = [Point(0,0,1), Point(0,0,2)]
pl = Plane(Vector(0,0,1), 0)
flat = pts >> pl
assert(flat[0].z == 0, "Array Projection")

Logical Operators

Returns true or false.

Comparison

==, !=, <, >, <=, >=.

1. Number Comparison

check = 10 > 5  // true
assert(check, "GT")

2. Equality Check

is_equal = 5 == 5  // true
assert(is_equal, "EQ")

3. Filtering Logic Used inside filters.

x = 10
assert(x > 0, "Check")

4. Boolean Logic && (AND), || (OR), ! (NOT).

x = 5
valid = (x > 0) && (x < 10)
assert(valid, "Logic")

5. Ternary Operator ? : Conditional value selection.

x = 5
val = (x > 0) ? "Positive" : "Negative"
assert(val == "Positive", "Ternary")

Pipe Operators

Map / Apply |>

Passes the left operand as the first argument to the function on the right.

1. Function Application

x = 16 |> sqrt  // same as sqrt(16) -> 4
assert(x == 4, "Pipe Func")

2. Array Mapping Applies the function to every element.

nums = [1, 4, 9]
roots = nums |> sqrt  // [1, 2, 3]
assert(roots[1] == 2, "Pipe Map")

3. Symmetry Application Applies a symmetry group to geometry.

p = Point(1, 0, 0)
rot = Rotate(Vector(0,0,1), 4)
// Generates 4 points
sym_pts = p |> rot
assert(sym_pts.length == 4, "Symmetry Apply")

4. Chained Operations Reading left-to-right.

val = -16 |> abs |> sqrt
assert(val == 4, "Pipe Chain")

5. Lambda Application

nums = [1, 2, 3]
doubled = nums |> (x) => x * 2  // [2, 4, 6]
assert(doubled[2] == 6, "Pipe Lambda")

Filter ?|

Selects elements from an array that satisfy a condition.

1. Basic Filtering

nums = [1, 2, 3, 4, 5]
odds = nums ?| (x) => x % 2 != 0  // [1, 3, 5]
assert(odds.length == 3, "Filter Basic")

2. Geometric Filtering Find points above the equator.

pts = [Point(0,0,1), Point(0,0,-1)]
upper = pts ?| (p) => p.z > 0
assert(upper.length == 1, "Filter Geo")

3. Type Filtering (Advanced usage with type checks)

4. Range Filtering

nums = 1 .. 10
high = nums ?| (x) => x > 8  // [9, 10]
assert(high.length == 2, "Filter Range")

5. Combined with Map Filter then Map.

result = (1 .. 10) ?| ((x) => x > 5) |> (x) => x * 10
assert(result[0] == 60, "Filter Map")

Geometric Operators

Bind :

Binds a Normal Vector and a Point (or distance) to create a Plane.

1. Normal : Point Creates a plane with normal n passing through point p.

n = Vector(0, 0, 1)
p = Point(0, 0, 5)
pl = n : p  // Plane(0,0,1, dist=5)
assert(pl.distance == 5, "Bind Point")

2. Normal : Distance (Number) Usually done via constructor Plane(n, d), but : works if overloaded (check specific implementation). Typically used with Points.

3. Array : Point Creates multiple planes passing through one point.

normals = [Vector(1,0,0), Vector(0,1,0)]
p = Point(0,0,0)
planes = normals : p
assert(planes.length == 2, "Bind Array Normal")

4. Normal : Array Creates parallel planes.

n = Vector(0,0,1)
pts = [Point(0,0,0), Point(0,0,10)]
planes = n : pts
assert(planes.length == 2, "Bind Array Point")

5. Auto-Centering If the point is the origin (0,0,0), it creates a center-point cut.

pl = Vector(1,1,1) : Point(0,0,0)

Sweep / Auto-Note ->

Similar to Bind, but implies a "cutting" action and often attaches automatic documentation notes (like "Meet A", "Set Girdle").

1. Normal -> Distance Creates a plane at distance d.

pl = Vector(0,0,1) -> 5
assert(pl.distance == 5, "Sweep Dist")

2. Normal -> Point Creates a plane through point p.

pl = Vector(0,0,1) -> Point(0,0,5)
assert(pl.distance == 5, "Sweep Point")

3. Auto-Note: Set Girdle If the cut defines the girdle width, -> detects it.

girdle_pl = Vector(1,0,0) -> 10
// plane.notes is automatically set to "Set stone size" or "Set girdle width"

4. Auto-Note: Meet If the target point was derived from an intersection, -> generates a "Meet ..." note.

pl1 = Plane(Vector(1,0,0), 1)
pl2 = Plane(Vector(0,1,0), 1)
pl3 = Plane(Vector(0,0,1), 1)
meet_pt = pl1 * pl2 * pl3

cut = Vector(1,1,1) -> meet_pt
// plane.notes = "Meet [Plane names...]"

5. Chaining

pl1 = Plane(Vector(1,0,0), 1)
pl2 = Plane(Vector(0,1,0), 1)
pl3 = Plane(Vector(0,0,1), 1)

final_plane = Vector(0,0,1) -> (pl1 * pl2 * pl3)

Contact *>

Finds the "Contact Point" or "Tangent Point". It searches a set of geometry for the point most extreme in the direction of a vector.

*1. Vector > Stone Finds the vertex on the current stone that is furthest in direction v.

_ := Cube(2)
// Find the tip of the stone (highest Z)
tip = Vector(0,0,1) *> Stone
assert(tip.z == 1, "Contact Stone")

*2. Vector > Array Finds the point in the array that maximizes dot product with v.

pts = [Point(0,0,0), Point(10,10,10)]
v = Vector(1,1,1)
best = v *> pts  // Point(10,10,10)
assert(best.x == 10, "Contact Array")

3. Used for Meet-point Faceting "Cut until you touch this vertex".

_ := Cube(2)
target_v = Vector(0,0,1) *> Stone
new_cut = Vector(1,0,1) -> target_v

*4. Vector > Plane (Usually undefined unless bounded, behavior depends on implementation).

5. Finding Girdle Corners

_ := Cube(2)
corner = Vector(1,0,0) *> Stone

Range Operator ..

Creates an array of integers.

1. Basic Range

r = 1 .. 5  // [1, 2, 3, 4, 5]
assert(r.length == 5, "Range Len")

2. Loop Indexing Useful for creating sequences.

angles = 0 .. 3 |> (i) => i * 90
assert(angles[3] == 270, "Range Loop")

3. Creating Grids

x_vals = 0 .. 10
y_vals = 0 .. 10

4. With Filter

evens = (1 .. 10) ?| (x) => x % 2 == 0
assert(evens.length == 5, "Range Filter")

5. Negative Ranges

r = -3 .. 3  // [-3, -2, -1, 0, 1, 2, 3]
assert(r.length == 7, "Neg Range")