Pegmatite Pegmatite

The language reference

Every command.

The syntax, the parameters, the possibilities.
Keep this open while you build.

.pegm

Solids. Sweeps. Profiles. Placement. Scripts.
One small, readable language.

Find a command

01 / Create geometry

Solid primitives

Primitives produce placeable volumes. By default, each ordinary solid stacks on the previous one. Its own frame is centered on X and Y, with its base at Z = 0. To build a solid from a 2D profile, use a solid from a shape.

Four primitive solids
Four primitive solids rendered from the script above

cube#

An equal-sided box, centered on X and Y with its base at Z = 0.

cube size
Argument / optionMeaning & constraints
size

Side length on all three axes; zero or greater.

Examplecube 20

block#

A rectangular solid with independently sized axes.

block width depth height
Argument / optionMeaning & constraints
width / depth / height

Lengths of zero or more along local X, Y, and Z, respectively.

Exampleblock 40 30 10

cylinder#

A circular cylinder standing on its base.

cylinder diameter height
Argument / optionMeaning & constraints
diameter

Full width across the circular base; zero or greater.

height

Length along Z; zero or greater.

Examplecylinder 20 30

sphere#

A sphere resting on the ground plane. Standard face references touch its outer bounds.

sphere diameter
Argument / optionMeaning & constraints
diameter

Full width of the sphere; zero or greater.

Examplesphere 24

cone#

A right circular cone standing on its base.

cone diameter height
Argument / optionMeaning & constraints
diameter / height

Base diameter and Z height; both zero or greater.

Examplecone 24 30

pyramid#

A regular pyramid with a base face pointing front. The base is measured through its corners unless a measure word says otherwise.

pyramid sides [diameter | edge | across] size height
Argument / optionMeaning & constraints
sides

Whole number of base sides, at least 3.

diameter / edge / across

Optional measure word. Measure the base through its corners (the default), along one side, or between two parallel sides (even sides only).

size / height

Base size and Z height; both zero or greater.

Examplepyramid 4 edge 24 30

prism#

A regular prism with one upright face pointing front, measured like a pyramid. Its slot uses the bounds of the actual polygon.

prism sides [diameter | edge | across] size height
Argument / optionMeaning & constraints
sides

Whole number of upright faces, at least 3.

diameter / edge / across

Optional measure word. Measure the base through its corners (the default), along one side, or between two parallel sides (even sides only).

size / height

Base size and Z height; both zero or greater.

Exampleprism 6 across 24 20

starprism#

A star raised into a solid. Its first spike points along +X.

starprism spikes outer-diameter inner-diameter height
Argument / optionMeaning & constraints
spikes

Whole number of spikes, at least 3.

outer-diameter / inner-diameter

Diameters through the spikes and notches; inner must be smaller than outer, unless both are zero.

height

Extrusion height; zero or greater.

Examplestarprism 5 40 20 10

Polygonal bases and star profiles
Polygonal bases and star profiles rendered from the script above

torus#

A ring lying in the XY plane. Dimensions describe the outside and the hole, not the tube thickness.

torus outer-diameter inner-diameter
Argument / optionMeaning & constraints
outer-diameter / inner-diameter

Overall and hole diameters; the hole is greater than zero and no larger than the outside.

Exampletorus 30 18

tube#

An upright hollow cylinder, open at both ends.

tube outer-diameter inner-diameter height
Argument / optionMeaning & constraints
outer-diameter / inner-diameter

Outside and bore diameters; the bore is greater than zero and no larger than the outside.

height

Z height; zero or greater.

Exampletube 30 18 20

tetrahedron#

A regular polyhedron with 4 triangular faces, standing on one face. Numbered references identify its actual planar faces.

tetrahedron [diameter | edge] size
Argument / optionMeaning & constraints
size

Size of zero or more, measured along an edge by default, unless diameter is specified.

edge / diameter / across

Optional measure word: along an edge (the default), or the diameter of the sphere through the vertices. A tetrahedron has no opposite faces to measure across.

Exampletetrahedron 12

octahedron#

A regular polyhedron with 8 triangular faces, standing on one face. Numbered references identify its actual planar faces.

octahedron [diameter | edge | across] size
Argument / optionMeaning & constraints
size

Size of zero or more, measured along an edge by default, unless diameter or across is specified.

edge / diameter / across

Optional measure word: along an edge (the default), the diameter of the sphere through the vertices, or between two opposite faces - the height it stands.

Exampleoctahedron 12

dodecahedron#

A regular polyhedron with 12 pentagonal faces, standing on one face. Numbered references identify its actual planar faces.

dodecahedron [diameter | edge | across] size
Argument / optionMeaning & constraints
size

Size of zero or more, measured along an edge by default, unless diameter or across is specified.

edge / diameter / across

Optional measure word: along an edge (the default), the diameter of the sphere through the vertices, or between two opposite faces - the height it stands.

Exampledodecahedron 12

icosahedron#

A regular polyhedron with 20 triangular faces, standing on one face. Numbered references identify its actual planar faces.

icosahedron [diameter | edge | across] size
Argument / optionMeaning & constraints
size

Size of zero or more, measured along an edge by default, unless diameter or across is specified.

edge / diameter / across

Optional measure word: along an edge (the default), the diameter of the sphere through the vertices, or between two opposite faces - the height it stands.

Exampleicosahedron 12

The four polyhedral primitives
The four polyhedral primitives rendered from the script above

mesh#

A solid written out as its corners and the flat faces between them. Faces are named #f1, #f2, … in the order they are written.

mesh vertices [x y z]… faces [i j k …]…
Argument / optionMeaning & constraints
vertices

Four or more corners, each [x y z]. They are numbered from 0 in the order written. The solid is placed by its box, so only their relative positions matter.

faces

Four or more faces, each listing three or more corner indices in order around it. Each face must be flat, and every edge must be shared by exactly two faces. Winding does not matter.

Examplemesh vertices [0 0 0] [10 0 0] [0 10 0] [0 0 10] faces [0 1 2] [0 1 3] [0 2 3] [1 2 3]

A pyramid written corner by corner
A pyramid written corner by corner rendered from the script above

02 / Give a profile volume

Solids from shapes

Turn a 2D profile into a placeable solid by raising it, turning it around an axis, or carrying it along a route. The profile comes first and the sweep follows it after |: steps before the sweep's word treat the shape, steps after it the solid. All four accept the same shapes and 2D operations.

extrude#

Raise a 2D profile into a solid. A filled profile is the default; wall gives its outline a thickness instead, twist and size turn and resize it as it rises, apex runs the sides towards a point, and to runs them to another shape.

profile | extrude height [wall thickness [inside | outside]] [twist degrees] [size factor] [apex [x y [z]] | to top]
Argument / optionMeaning & constraints
height

Zero or greater; extrusion distance along local Z.

wall thickness

Optional wall thickness, zero or greater. Centered on the outline by default.

inside / outside

Keep the wall on one side of a closed outline. Open paths only support a centered wall.

twist

Degrees the outline turns about its own origin by the top, counter-clockwise seen from above. A list, twist [0 30 120], gives the turn at evenly spaced levels from the base to the top, joined by a smooth curve that never overshoots them. Not with apex or to.

size

The size of the top as a share of the profile, about its own origin; written and listed as twist is. Zero or greater, and zero only at the base or the top, where the solid closes to a point. A wall keeps its thickness at every level.

apex

The point the sides run towards, in the profile's own coordinates. z defaults to the height, closing to a point; above it the top is cut short, below the base the sides spread. z between 0 and the height is an error. A wall keeps its thickness all the way up.

to

The shape the top is, in the profile's own coordinates. The side runs straight, corner to corner when both outlines have as many corners, otherwise between points the same share of the way round both, with the top started where the side twists least. Each must be a single outline without holes. Takes no modifiers unless written in a group, to { circle 20 | round 2 }. Cannot be combined with apex.

profile

circle, rect, ellipse, star, polygon, a face, path, text, a tiling or a group, written before the sweep.

A filled profile and an open wall
A filled profile and an open wall rendered from the script above

A filled path closes its subpaths. With wall, open paths stay open. A wall has no bottom; use shell for a vessel with a floor.

Face references as profiles
Face references as profiles rendered from the script above

Face references such as #top can be used as profiles.

A point, a leaning point, and a frustum
A point, a leaning point, and a frustum rendered from the script above

The apex is a point in the profile's own frame, so apex [0 0] stands the point over a circle's centre or a path's origin. Where the outline shrinks below the wall's thickness, the wall closes over into solid; a long outline that does so all along its length, such as text walled to a point, is refused.

Turned, narrowed, and a vase that swells
Turned, narrowed, and a vase that swells rendered from the script above

twist and size work about the profile's own origin, as a | rotate or | scale of the shape would. One value is the top's, reached evenly; a list is the value at each of several evenly spaced levels.

Square to round, a funnel, and a leaning top
Square to round, a funnel, and a leaning top rendered from the script above

With to, every corner of either outline is a corner of both, so the base keeps its corners and the top its curve. A wall is its thickness at the base and at the top and runs straight between, open at both ends.

revolve#

Sweep a profile around an axis. The optional diameter is the circular path of the profile's origin, not the outside diameter of the finished solid.

profile | revolve [diameter] [angle degrees] [start degrees] [about axis] [shrink]
Argument / optionMeaning & constraints
diameter

Zero or greater. Default 0: use the profile's own coordinates without a radial offset.

angle

Greater than 0 and at most 360. Default 360 degrees.

start

Starting angle; default 0, at +X for a Z-axis sweep.

about

x, y, or z. Default z.

shrink

Use material bounds for placement. Partial sweeps otherwise keep bounds mirrored about the axis.

profile

Any 2D profile. Only its outline is swept; profile holes are ignored.

A quarter-turn with capped ends
A quarter-turn with capped ends rendered from the script above

A path profile's Y grows downwards, so the top of the drawing is the top of the solid.

A profile crossing the axis is clipped to the half it sweeps. For example, circle 20 | revolve makes a sphere of diameter 20.

helix#

Sweep a profile around an axis while rising. A second diameter tapers the sweep from its starting circle to its ending circle.

profile | helix diameter [end-diameter] [pitch distance] [turns count | height distance]
      [start degrees] [about axis] [shrink]
Argument / optionMeaning & constraints
diameter / end-diameter

Nonnegative path diameters. End diameter defaults to the starting diameter.

pitch

Nonnegative rise per turn; default 0.

turns

Greater than 0 and at most 100; fractional turns are allowed. Default 1. With no pitch and no end diameter, more than one turn is a warning and builds one.

height

Positive path rise, as an alternative to turns. Requires positive pitch; cannot be combined with turns.

start / about

Starting angle (default 0) and sweep axis (default z).

shrink

For a sweep of less than one turn, use material bounds instead of mirrored bounds.

profile

Any 2D profile, which must not cross the sweep axis.

A tapered spring
A tapered spring rendered from the script above

Height measures the path's rise, so material can extend beyond it by the profile's size. Choose enough pitch to prevent adjacent coils from intersecting.

The slot includes that overshoot: height 60 with a profile 2 tall is 62 tall, and so is a compound around the rod and its thread. To end a thread flush with its rod, run it a pitch past both ends and trim it with on a labelled part and &revolve instead of wrapping it in a compound. That hides the helix's capped ends and lets a chamfer taper the ridge out.

A bolt, its thread trimmed flush and chamfered
A bolt, its thread trimmed flush and chamfered rendered from the script above

sweep#

Sweep a profile along the outline of another 2D shape. The trajectory lies in the build plane, where an extruded shape lies.

profile | sweep along trajectory [about axis] [round]
Argument / optionMeaning & constraints
profile

Any 2D shape with an area. X runs to the right of an open path's travel or outside a closed outline; Y stands off the plane.

along trajectory

Any 2D shape, read as a wall reads it: an open path stays open and is capped at both ends, a closed outline makes a ring. Every outline is swept and the results are joined. Takes no modifiers unless written in a group.

about

x, y, or z: the axis the trajectory's plane faces. Default z.

round

Round the outside of each sharp corner. Corners are mitred by default.

A channel cut along a route on a plate
A channel cut along a route on a plate rendered from the script above

The profile's origin rides the route, and the plane never turns, so the profile never twists. rect 2 10 | sweep along path P is path P | extrude 10 wall 2, and circle 20 | sweep along circle 40 is torus 60 20.

A groove set in from the rim, following a face
A groove set in from the rim, following a face rendered from the script above

A face follows its real outline. On a closed outline the profile's X points outward, so a profile drawn left of its origin lies inside the rim.

A handle stood upright with about y
A handle stood upright with about y rendered from the script above

about turns the plane as it turns a revolve's axis: the trajectory's X lies on the axis after the named one in the x → y → z cycle, and its Y on the one after that. Corners are mitred like a wall's, and cut off square when sharper; round rounds their outside. A profile wider than the inside of a bend has room for is refused, naming the bend. A single outline that crosses itself is swept as drawn.

varying profiles#

A profile drawn anew at every point of its sweep: a shape macro called with every argument but its last, which the sweep gives as it goes, from 0 at its start to 1 at its end. Written in place, % and one parameter stand for the macro.

shape-macro [argument …] | sweep | % $parameter profile | sweep
Argument / optionMeaning & constraints
last argument

Runs over the height of an extrude, the turn of a revolve, the turns of a helix, and each outline of a sweep along.

% $parameter

A varying profile written in place. Everything up to the sweep is its shape, modifiers included.

outlines

Each pairs from the point it is drawn from. As many outlines and holes all the way; sizes, corners and turns may change.

closed sweeps

A whole revolve or a sweep along a closed outline has to end on the shape it starts from.

extrude

Takes twist, size and wall on top of the profile; not apex or to.

A softening square, a horn, and a thinning handle
A softening square, a horn, and a thinning handle rendered from the script above

A varying profile is drawn wherever it changes most: eight times, and again between two wherever the shape strays from the straight way between them. Written alone, it is a sketch of its start. curve(20, 44, 16, $t) gives a size that passes through each value on the way.

03 / Define a profile

2D profiles

A profile becomes a solid when a sweep follows it: extrude, revolve, helix or sweep. Written on its own it is a sketch: placed where the swept solid would stand and drawn flat there, building nothing, taking no slot and leaving the reference where it was. The script still builds, with a warning. 2D modifiers written between a profile and its sweep treat its outline before it is swept.

circle#

A circular profile centered on its own origin.

circle diameter
Argument / optionMeaning & constraints
diameter

Positive full width across the circle.

Examplecircle 20 | extrude 4

rect#

A rectangular profile centered on its own origin.

rect width height
Argument / optionMeaning & constraints
width / height

Positive lengths across local X and Y. Extrusion supplies the Z dimension.

Examplerect 30 20 | extrude 4

ellipse#

An elliptical profile centered on its own origin.

ellipse diameter-x diameter-y
Argument / optionMeaning & constraints
diameter-x / diameter-y

Positive full widths along local X and Y.

Exampleellipse 30 20 | extrude 4

star#

The outline of a starprism, centered on its own origin with its first spike along +X. Extruded, `star 5 40 20` is `starprism 5 40 20` of that height.

star spikes outer-diameter inner-diameter
Argument / optionMeaning & constraints
spikes

Whole number of spikes, at least 3.

outer-diameter / inner-diameter

Positive diameters through the spikes and notches; inner must be smaller than outer.

Examplestar 4 20 10 | extrude 5

polygon#

A polygon of corners written out in the shape's own coordinates, Y up and not re-centered, or the regular polygon of a prism's base, centered on its own origin. Extruded, `polygon 6 20` is `prism 6 20` of that height.

polygon sides [diameter | edge | across] size
polygon points [x y]…
Argument / optionMeaning & constraints
points [x y]...

Three or more corners in order around the outline. The outline closes itself; one that crosses, touches or folds back on itself is an error.

sides

Whole number of corners of a regular polygon, at least 3.

diameter / edge / across

Optional measure word, as for prism: through the corners (the default), along one side, or between two parallel sides (even sides only).

size

Positive size along the measure.

Examplepolygon points [0 0] [30 0] [20 15] [0 10] | extrude 4

#face#

The outline of a face of a built solid, drawn in the face's own frame. A bare face also builds the solid on that face, covering it exactly, unless an on says otherwise.

#face
label #face
Argument / optionMeaning & constraints
#face

Any face reference: #top, #f2, #bounds.front. A bare face is read off the volume the next solid is built against, the one on would read it from.

label

Optional. Reads the face of that labelled volume instead, as its statement built it: booleans written after the label do not reach the outline.

outline

The surface the solid has on the face, so the #top of a cylinder is a circle. A direction must name a flat side the solid has; every #bounds face is its whole extent. The shape claims the whole face as its slot.

A plate swept from the slanted face it stands on
A plate swept from the slanted face it stands on rendered from the script above

A face shape is most useful as the area of a tiling, which fits a pattern to a face without measuring it.

path#

A profile drawn with an SVG path string. SVG's downward Y axis is flipped so the shape stands as drawn.

path "svg-path"
path $variable
Argument / optionMeaning & constraints
svg-path

M, L, H, V, Z, C, S, Q, T, A and their lowercase forms. Use ordinary decimal coordinates; literals reject + signs and exponent notation.

$variable

A string value containing the SVG path.

Extrude a custom outline
Extrude a custom outline rendered from the script above

Because Y is flipped, a larger Y is lower. For revolve and helix, where Y becomes height, draw the profile top first, as it looks on screen.

The points of an SVG <polygon> paste between M and Z, since the pairs after a move are lines: path "M20,0 40,20 30,20 30,40 10,40 10,20 0,20 Z".

Filled extrusion closes every subpath. extrude … wall preserves open subpaths as open walls. A path literal takes no escapes.

text#

A line of text in the current font and font-size. Give it depth with a sweep operation.

text "string"
text $variable
Argument / optionMeaning & constraints
string / $variable

Double-quoted text or a string variable. A string may span lines, each starting below the last, aligned left. Escapes: \n line break, \" quote, \\ backslash, \u{B0} a Unicode character by hex code point.

Raised lettering on a base
Raised lettering on a base rendered from the script above

font-size#

Set the height of a capital letter in a text profile, independently of the extrusion height.

[!]font-size size
[!]font-size unset
Argument / optionMeaning & constraints
size

Positive height in model units. Default 10.

! / unset

Persist the setting or restore the default, following the same rules as color.

font-size 12 text "Hello" | extrude 2

font#

Set the font of a text profile: a Google Fonts family name, the https URL of a font file, or a font file path for the command-line tool.

[!]font "family" [weight]
[!]font unset
Argument / optionMeaning & constraints
family

A Google Fonts name such as "Roboto", a font file URL, or a local path such as "fonts/Logo.otf" relative to the script. Local paths are supported only by the CLI. The value must be written as a literal, not a variable, because the font is loaded before the script runs.

weight

100 (thin) to 900 (black). Default 400 for a family name. For a file, it picks the weight of a variable font and is otherwise left out.

! / unset

Persist the setting or return to the built-in font, following the same rules as color.

Bold lettering in a Google font
Bold lettering in a Google font rendered from the script above

font-size stays the height of a capital letter in every font. The built-in font covers Latin-1 and Greek. A character the font has no glyph for, built-in or not, is left out, with a warning.

A font file, by URL or on disk, is TTF, OTF, WOFF, or WOFF2, up to 10 MB; a TTC collection gives its first font. The format is read from the content, so a URL needs no extension. A path ends in .ttf, .otf, .woff, .woff2, or .ttc, and only the command-line tool reads it.

04 / Treat a profile

2D operations

2D modifiers follow a profile after | and treat its flat outline before it is swept. They come before the solid's own modifiers, in the same left-to-right pipeline, and work on every profile, tilings and faces included. Braces combine profiles into one, placed and signed the way solids are. A shape in braces, and a profile before its sweep, can also be turned, mirrored and resized.

offset#

Grow the outline of a profile by a signed distance, or shrink it by a negative one. Corners stay sharp, as a wall's do.

| offset distance [round]
Argument / optionMeaning & constraints
distance

Any number. Holes move the other way, narrowing as the outline grows. A shrink that leaves nothing is an error.

round

Optional. Keeps the new outline the same distance from the old one, rounding the corners it moves away from.

A lid whose lip fits the box with 0.2 to spare
A lid whose lip fits the box with 0.2 to spare rendered from the script above

2D modifiers come right after the shape and before its sweep, in one pipeline with the solid's own modifiers: rect 40 30 | offset 2 | extrude 10 | fillet 1. A modifier treats the innermost shape before it, so after a tiling it treats the area; put the tiling in braces to treat its cells. The shape stays in the frame it is drawn in.

round#

Round every corner of a profile, those pointing out and those turning in alike.

| round radius
Argument / optionMeaning & constraints
radius

Zero or greater. Parts narrower than twice the radius are lost; a radius that leaves nothing is an error.

Examplepolygon points [0 0] [40 0] [40 10] [10 10] [10 40] [0 40] | round 3 | extrude 4

fill#

Fill the holes of a profile, keeping its outlines. A face of a hollowed solid fills into a lid.

| fill

Examplebox: block 40 30 20 | shell 2 on box #top box #top | fill | extrude 2

{ group }#

One profile made of several: each shape placed against the one before it, centered unless x, y or an anchor says otherwise, and joined, cut, kept or cancelled by its sign.

{ shape … } [| modifier …]
Argument / optionMeaning & constraints
shape

Any profile, with optional x, y, @left / @right / @front / @back, a sign - & ^, and slot before it. A flat shape has no z, @top or @bottom.

first shape

Placed against the origin; with nothing to place it, it keeps its own coordinates, so a group of one shape is that shape.

[ list ]

Builds each item from the shape the list opened after.

!setter

Persists to the end of the group or list it is written in.

The same alignment and offset principles used for 3D solids apply to x and y in a group, including named points, percentages, and reference:shape pairs.

A plate with a slot and a pair of holes
A plate with a slot and a pair of holes rendered from the script above

The counterpart of a compound. The group claims the box of every shape in it that adds, slot ones included and cut ones not, and takes 2D modifiers as a whole, so braces around a tiling let a modifier treat its cells. Braces holding only shape macro calls are a group too.

− / & / ^#

Change how a shape in a group combines with the shapes before it, as the signs do for solids. Without a sign, the shape is added.

{ … -shape }
{ … &shape }
{ … ^shape }
Argument / optionMeaning & constraints
-

Difference: cut the shape from the area before it.

&

Intersection: keep only the overlap.

^

Symmetric difference: keep what belongs to exactly one of the two.

Example{ rect 40 20 @right -rect 10 10 } | extrude 2

The counterpart of the signs on solids. A signed shape cannot be the first in its group. On the axis an anchor names it reaches back into the shape before it, so the example notches the right edge, and it leaves its box as the reference for the next shape.

rotate#

Turn a shape in a group, or a profile before its sweep, about its own origin.

| rotate degrees
Argument / optionMeaning & constraints
degrees

Counter-clockwise; no axis, since a flat shape turns in its own plane.

Example{ rect 40 10 rect 40 10 | rotate 90 } | extrude 2

A shape in a group or a profile before its sweep takes it, as a step of the whole shape after that shape's own 2D modifiers. After the sweep the word belongs to the solid's rotate.

scale#

Resize a shape in a group, or a profile before its sweep, about its own origin, uniformly or per axis.

| scale factor
| scale x-factor y-factor
Argument / optionMeaning & constraints
factor(s)

One for both axes, or one for each; not zero. A negative factor mirrors.

Example{ circle 10 | scale 2 1 } | extrude 2

A shape in a group or a profile before its sweep takes it, as a step of the whole shape after that shape's own 2D modifiers. After the sweep the word belongs to the solid's scale.

flip#

Mirror a shape in a group, or a profile before its sweep, across its own origin.

| flip axis
Argument / optionMeaning & constraints
axis

x or y, the axis negated.

Example{ star 5 20 10 @right star 5 20 10 | flip x } | extrude 2

A shape in a group or a profile before its sweep takes it, as a step of the whole shape after that shape's own 2D modifiers. After the sweep the word belongs to the solid's flip.

05 / Fill an area

Tilings & Voronoi

Tilings are 2D profiles that lay cells over the area of another shape, written last after in. The cells are the holes, so subtracting a tiling perforates a plate, and a rim as wide as the strut stays standing along the outline unless rim says otherwise. Any profile can be the area, including a face.

honeycomb#

Hexagonal cells in columns, each column half a cell off the next, laid over the area of a shape and cut back to it, leaving a rim along its outline. Subtract it to perforate a plate.

honeycomb diameter strut [angle degrees] [rim width] in area
Argument / optionMeaning & constraints
diameter

Positive size of a cell across its corners, as a prism is measured. A flat faces front.

strut

Positive gap between neighbouring cells. At most 10,000 cells.

angle

Optional. Turns the cells counter-clockwise inside the area, which stays where it is.

rim

Optional. Material left standing along the outline of the area; the strut by default, 0 lets the cells run out to the outline.

in shape

Required, and always last. The area the cells fill: any 2D profile, a shape macro, or a face such as #f2. The pattern claims the box of the area as its slot.

A drawn outline perforated with its own honeycomb
A drawn outline perforated with its own honeycomb rendered from the script above

The tiling and the plate share one outline, so the rim follows it all the way round. angle turns the cells inside the area, which stays where it is.

squares#

Square cells in a plain grid, laid over the area of a shape and cut back to it, leaving a rim along its outline. Subtract it to perforate a plate.

squares diameter strut [angle degrees] [rim width] in area
Argument / optionMeaning & constraints
diameter

Positive size of a cell across its corners, as a prism is measured. A flat faces front.

strut

Positive gap between neighbouring cells. At most 10,000 cells.

angle

Optional. Turns the cells counter-clockwise inside the area, which stays where it is.

rim

Optional. Material left standing along the outline of the area; the strut by default, 0 lets the cells run out to the outline.

in shape

Required, and always last. The area the cells fill: any 2D profile, a shape macro, or a face such as #f2. The pattern claims the box of the area as its slot.

Examplerect 70 50 | extrude 3 -squares 8 1.5 rim 5 in rect 70 50 | extrude 3

triangles#

Triangular cells in rows, pointing back and front in turn, laid over the area of a shape and cut back to it, leaving a rim along its outline. Subtract it to perforate a plate.

triangles diameter strut [angle degrees] [rim width] in area
Argument / optionMeaning & constraints
diameter

Positive size of a cell across its corners, as a prism is measured. A flat faces front.

strut

Positive gap between neighbouring cells. At most 10,000 cells.

angle

Optional. Turns the cells counter-clockwise inside the area, which stays where it is.

rim

Optional. Material left standing along the outline of the area; the strut by default, 0 lets the cells run out to the outline.

in shape

Required, and always last. The area the cells fill: any 2D profile, a shape macro, or a face such as #f2. The pattern claims the box of the area as its slot.

Examplerect 70 50 | extrude 3 -triangles 8 1.5 rim 5 in rect 70 50 | extrude 3

stripes#

Parallel stripes running left to right, laid over the area of a shape and cut back to it, leaving a rim along its outline. Subtract it to cut slots into a plate.

stripes width strut [angle degrees] [rim width] in area
Argument / optionMeaning & constraints
width

Positive width across a stripe. One stripe runs through the middle of the area.

strut

Positive gap between neighbouring stripes. At most 10,000 stripes.

angle

Optional. Turns the stripes counter-clockwise inside the area, which stays where it is; 90 runs them front to back.

rim

Optional. Material left standing along the outline of the area; the strut by default, 0 lets the cells run out to the outline.

in shape

Required, and always last. The area the cells fill: any 2D profile, a shape macro, or a face such as #f2. The pattern claims the box of the area as its slot.

A plate cut with diagonal stripes
A plate cut with diagonal stripes rendered from the script above

The stripes are turned inside the area, which stays where it is, and the rim stops every one of them 5 short of the outline.

voronoi#

Cells nearest each of a set of sites, laid over the area of a shape and cut back to it, leaving a rim along its outline. Subtract it to perforate a plate.

voronoi strut [cells count] [seed seed] [points [x y]…] [relax passes] [rim width] in area
Argument / optionMeaning & constraints
strut

Positive gap between neighbouring cells.

cells

Whole number of random sites, at most 10,000, all scattered inside the area.

seed

Whole number choosing the random arrangement; 0 by default. The same seed always gives the same cells.

points

Sites written out as [x y], in the area's own frame centered on its box, instead of cells.

relax

Passes that move each site to the middle of its cell, evening the cells out. 2 for random sites, 0 for points. At most 50; more is a warning and makes 50.

rim

Optional. Material left standing along the outline of the area; the strut by default, 0 lets the cells run out to the outline.

in shape

Required, and always last. The area the cells fill: any 2D profile, a shape macro, or a face such as #f2. The pattern claims the box of the area as its slot.

A vase with a voronoi pattern on every side
A vase with a voronoi pattern on every side rendered from the script above

Each side is its own area, so the pattern follows the trapezoid of the face and the rim keeps the corners standing. The label brings every cut back to the vase.

06 / Shape the result

3D modifiers

Modifiers follow a solid after | and run from left to right before placement. The whole pipeline remains one solid. Every step returns geometry centered on X and Y with its base at Z = 0.

rotate#

Turn a solid around one axis in its own frame. Chain rotations to specify their order.

| rotate angle about axis-or-face
Argument / optionMeaning & constraints
angle

Degrees, counterclockwise as seen from the positive end of the axis.

axis-or-face

x, y, z, or a face normal such as #front.

A face follows its solid through a turn
A face follows its solid through a turn rendered from the script above

Placement uses the transformed bounds. A named face follows the original solid; #bounds.top instead selects the top of the current bounding box.

For a shape inside a 2D group, see 2D rotate.

scale#

Resize uniformly or along all three axes independently. Useful for compounds, macros, and swept solids.

| scale factor
| scale x-factor y-factor z-factor
Argument / optionMeaning & constraints
factor(s)

One or three nonzero numbers. Negative factors also reflect along those axes.

Stretch a sphere along one axis
Stretch a sphere along one axis rendered from the script above

Scaling after a fillet scales its radius too. Scaling before the fillet leaves the subsequently specified radius unchanged.

For a shape inside a 2D group, see 2D scale.

flip#

Reflect across the plane normal to an axis, without changing size.

| flip axis
Argument / optionMeaning & constraints
axis

x, y, or z. flip x has the same geometric effect as scale -1 1 1.

Mirror a custom profile
Mirror a custom profile rendered from the script above

For a shape inside a 2D group, see 2D flip.

shell#

Hollow a finished solid inward, keeping its bottom and opening the flat face that points up where the shell stands in the pipeline, the faces named, or none.

| shell thickness [open face | open [face …] | closed]
Argument / optionMeaning & constraints
thickness

Positive wall thickness that leaves a valid inner cavity.

face

A face to leave open instead of the top, such as #f2, or a list of them.

A vessel with a bottom and a rim
A vessel with a bottom and a rim rendered from the script above

The opening is the solid's flat top face; every other face moves inward and keeps its shape, so sloped walls and narrow necks stay. A solid without a flat top, such as a sphere, needs a cut first. Shell also accepts fused compounds.

open names the faces to leave open instead, one or a list such as open [#top #front], named as on names them where the shell stands, so a slope such as a pyramid's #f1 can open too. closed opens none, leaving a sealed hollow to subtract from or build into later. An opening other than the top may need the slow general computation.

Open through two faces, and through a slope
Open through two faces, and through a slope rendered from the script above

cut#

Keep only the portion between two levels on the solid's local Z axis. The result gets a new base at Z = 0 and new face names.

| cut lower upper
Argument / optionMeaning & constraints
lower / upper

Heights above the base, or literal percentages such as 25%. Lower must not exceed upper; the result must retain material.

Keep the middle of a sphere
Keep the middle of a sphere rendered from the script above

Percentages measure the solid as the preceding pipeline step left it. Levels outside the solid do not remove additional material.

chamfer#

Bevel selected logical edges of any solid with sharp edges, measured along both faces whatever angle they meet at.

| chamfer distance [distance] [at edge-selector]
Argument / optionMeaning & constraints
distance

Positive and within the faces beside the selected edges: a whole face when its far edge is left alone, half of it when that edge is selected too. Zero is a warning and leaves the edges as they are.

second distance

Cuts unevenly: the first distance lands on the face that looks further up, then further front, then further left, and the second on the other face. Swap the numbers to flip the cut.

edge-selector

A predicate combining faces, axis directions, shared edges, nearest points and coordinate conditions with and / or / not, grown along smooth edges with tangent. See edge selectors below. Every edge when at is left out.

Bevel upright edges, then the top
Bevel upright edges, then the top rendered from the script above
Cut 3 across the top and 1 down the sides
Cut 3 across the top and 1 down the sides rendered from the script above

Edges whose faces meet at any angle are supported. Selectors read the geometry left by the previous step; a selector matching no edges is a warning, and the modifier is left out.

fillet#

Round edges with a surface tangent to their neighboring faces. Uses the same geometry, selectors, and size limits as chamfer.

| fillet radius [at edge-selector]
Argument / optionMeaning & constraints
radius

Positive and within the faces beside the selected edges: a whole face when its far edge is left alone, half of it when that edge is selected too. Zero is a warning and leaves the edges as they are.

edge-selector

The edges to round, every edge when at is left out. Edges already smoothed away cannot be selected again.

Round every edge and corner
Round every edge and corner rendered from the script above

Concave edges gain material; convex edges lose it. Chamfers and fillets can be combined in one pipeline. Apply edge operations before oblique rotations.

Edge selectors#

A predicate that selects whole logical edges for chamfer and fillet, rather than the triangle edges used to draw a surface. Any tests combine with any others.

parallel axis
#face
nearest x y z
axis comparison value
selector or selector
selector and selector
not selector
tangent selector
(selector)
Argument / optionMeaning & constraints
parallel x / y / z

Edges parallel to one local axis.

#face

Boundary edges of an axis-aligned face.

#top and #front

The edge shared by two adjacent faces.

nearest x y z

Edges closest to a point in the solid's local frame. Ties select all equally close edges.

z > 10

Compare x, y, or z using <, <=, >, >=, ==, !=. An edge matches when all of it satisfies the comparison.

#top or parallel z

Combine any selectors with or, and, not. not and tangent bind tightest, then and, then or; parentheses regroup.

tangent parallel z

Add every edge that carries a selected edge on without a corner, such as the arcs an earlier fillet left. Stops at sharp corners, where it adds nothing.

Select the rim inside a bore
Select the rim inside a bore rendered from the script above
Combine a face with a direction
Combine a face with a direction rendered from the script above
Follow the uprights round earlier fillets
Follow the uprights round earlier fillets rendered from the script above

Coordinates are evaluated before placement. On block 40 30 20, X spans −20 to 20, Y spans −15 to 15, and Z spans 0 to 20. z > 10 selects top edges; vertical edges do not satisfy it over their whole length.

Each operand is evaluated over every edge before and, or and not combine the results, so nearest ranks all edges, not only those its neighbours leave. A cylinder's logical edges are its two complete rims, so conditions on Z can select them, while x > 0 cannot select half a rim.

07 / Place and paint

Placement & properties

Build a tree of connected volumes: continue from the previous volume, align to its edges, and use lists to branch from a shared parent. Use labels for later returns and patterns for repeated features. See the modeling guide for an example.

Choose where a solid is built, align it with its reference, reserve empty space with slot, and set its color. Placement and color properties precede the solid they qualify.

@anchors#

Choose the direction from the placement reference and optionally leave a gap. Anchors seed one axis's alignment and offset.

[!]@direction [gap | unset]
Argument / optionMeaning & constraints
direction

left / right on X; front / back on Y; bottom / top on Z. center centers inside the reference when no other alignment is given.

gap

Optional signed distance along the chosen direction.

unset

Clear the gap while keeping the direction. !@right unset closes a spaced row.

Branch along the local axes
Branch along the local axes rendered from the script above

Ordinary solids default to local @top. After a negative volume, ordinary solids default to @bottom; intersection and symmetric difference also default to @bottom. A persistent anchor overrides these defaults.

Anchors keep the current orientation. @bottom cone 12 8 places an upright cone below an unrotated block, with its tip against the block. on #bottom cone 12 8 turns the cone outward, with its base against the block and its tip pointing down.

x / y / z#

Set an axis's alignment, offset, or both. The same forms apply to y and z. Each axis has two independent settings.

[!]x alignment [offset]
[!]x offset
[!]x unset
Argument / optionMeaning & constraints
alignment

One point aligns the same point on the reference and the new volume: x right is short for x right:right and aligns their right edges.

Two points use reference:volume order: x right:left aligns the reference’s right edge with the new volume’s left edge.

Named points: left / center / right on X, front / center / back on Y, and bottom / center / top on Z. Each set corresponds to 0% / 50% / 100% of the box along that axis.

Percentages work in either form: x 25% aligns the 25% point on both boxes; x 100%:25% aligns the reference’s 100% point with the new volume’s 25% point. Names and percentages can be mixed, as in x right:25%. Percentages must be literal numbers followed immediately by %, such as 25%.

offset

Signed distance along the axis, applied after alignment. Positive X always moves right.

unset

Clear both alignment and offset; the anchor or built-in default can apply.

Place against opposite corners
Place against opposite corners rendered from the script above

Axis commands override whichever settings they name, including settings supplied by an anchor.

on#

Select the reference for the next solid. A face also supplies a local frame whose Z axis points outward.

on #face
on label [#face]
on root
on [label] [#face …] statement
Argument / optionMeaning & constraints
#face

#front, #back, #left, #right, #top, #bottom, or an actual planar face such as #f1.

#bounds.face

Select a face of the current bounding box, rather than a face following the original solid through transforms.

label

A volume named with label: before its solid. Any name but root and pi works, even a command's. Optionally follow it with a face.

root

The current context's origin; a compound or macro has its own. Reserve on root for deliberate work from that origin. Repeated on root plus XYZ offsets for individual features is an antipattern; use parent volumes, faces and branching lists.

[#face …]

Build the statement after it on each face in turn, as a list with an on for each face would. Without a label the faces are those of the previous solid.

Build on a slanted, numbered face
Build on a slanted, numbered face rendered from the script above
Drill every side of a hexagon
Drill every side of a hexagon rendered from the script above

A label and one-shot setters may stand before the on of their solid: plate: color red on #front cube 10. A label cannot stand before a face list. Before any volume exists, a face selects the build plane; inside a compound or macro body write it as on root #front. on creates no scope. On a selected face, use x and y for sideways placement; a sideways anchor on the first solid is rejected. A persistent anchor is ignored for that first solid, then resumes.

Face names are local to the solid. After an initial on #front, a new block's #front faces world-down, #back world-up, and #top world-front. The local frame lets the same macro grow outward from any face without rewriting its coordinates. See faces and coordinate frames.

slot#

The room a solid takes, without its material. Use its faces, anchors, and labels just as you would the solid's.

slot solid
Argument / optionMeaning & constraints
solid

Any solid, compound, or macro call, with its modifiers. Its faces, numbered sides included, stay available.

Slots contribute to compound bounds. They cannot be boolean operands. A modifier shapes the room the way it would shape the solid.

A solid with a size of zero is a zero-sized volume: it keeps its room like a slot and builds no material. As a boolean operand it is the empty volume, so cube 5 -cube 0 leaves the cube whole and cube 5 &cube 0 leaves nothing. Transforms turn its room; other modifiers are skipped, and it has no numbered sides. A zero written as a plain number warns; one computed from a variable does not.

Size a part down to nothing
Size a part down to nothing rendered from the script above
Build around an empty space
Build around an empty space rendered from the script above
Build on the side of a missing prism
Build on the side of a missing prism rendered from the script above

color#

Set a solid's color. A plain setter applies once; ! makes it persistent in the current scope. 3MF and STEP export include colors only when the model sets one.

[!]color name-or-hex
[!]color unset
Argument / optionMeaning & constraints
name-or-hex

A CSS color name or six-digit RGB hex color such as #ff0000. Color variables are not supported.

unset

Use the built-in default once. !color unset clears the persistent color.

A persistent color with a one-shot override
A persistent color with a one-shot override rendered from the script above

Persistent appearance settings enter lists, compounds, and macro bodies. Changes within a list, compound, or macro stay inside it.

08 / Compute the numbers

Variables & expressions

Every numeric argument is a number, a $variable, a function call such as sqrt(50), a measure such as base.width, or an expression in parentheses. The parentheses keep the arguments of a command apart, so cube ($a + 2) is one argument where cube $a 2 would be two. A sign alone needs none: x -$inset negates the variable, since no volume begins with a value.

set#

Assign a number or string immediately. Values must exist before use; later reassignment does not change earlier geometry or stored settings.

set $name value
Argument / optionMeaning & constraints
$name

A case-sensitive name beginning with a letter, followed by letters, digits, or underscores.

value

A number, variable, parenthesized numeric expression, or double-quoted string. Strings can supply text and path profiles.

set $size 20
set $label "Hi"
block ($size * 2) $size 4
on #top text $label | extrude 2

A variable is written with its $ wherever a number or a profile string is accepted. Lists share variables; compound assignments stay local. Macro bodies see only parameters and local assignments. A pattern index is local to its pattern.

( expression )#

Combine numbers and numeric variables. Operators of a higher row bind tighter; within a row they apply from left to right, except ** which applies from right to left.

( operand operator operand … )
( test ? value : otherwise )
Argument / optionMeaning & constraints
**

Power: 2 ** 3 is 8, and 2 ** 3 ** 2 is 2 ** 9. Binds tighter than a leading minus, so -2 ** 2 is -4.

- (unary)

Negation: -$size.

* / %

Multiply, divide and remainder. % takes the sign of its divisor, so -1 % 4 is 3 and a == floor(a / b) * b + a % b.

+ -

Add and subtract.

a < b ? x : y

Choice, the loosest of all: x when the test holds, y otherwise. Compares with < <= > >= == !=, as edge selectors do, and == treats numbers within 0.000001 as equal. Only the picked value is worked out; chains nest to the right.

and or not

Join and turn comparisons in a test, not binding tightest and or loosest. The right side is only worked out when it can change the answer.

"text" == $s

A text compares only by == and !=, and never equals a number.

( )

Group any part of an expression; nesting is allowed.

Column and row read from one grid index
Column and row read from one grid index rendered from the script above
A checkerboard chosen by the index
A checkerboard chosen by the index rendered from the script above

Numbers may carry a decimal point, as in 1.5, and never touch a word: 2pi is an error, so write (2 * pi). A division or remainder by zero is an error, and so is a power with no real value, such as (-8) ** 0.5. Percentages such as 25% are literal points on a box, not expressions; inside parentheses % is always the remainder.

functions#

Work out a number from others. A call stands wherever a number does, inside an expression or bare as an argument, and calls nest. The name touches its opening parenthesis; commas part the arguments.

sin(degrees)  cos(degrees)  tan(degrees)
asin(value)  acos(value)  atan(value)  atan2(y, x)
sqrt(value)  exp(value)  log(value)  abs(value)
round(value)  floor(value)  ceil(value)
min(value, …)  max(value, …)  lerp(from, to, t)  curve(value, value, …, t)
pi
Argument / optionMeaning & constraints
sin cos tan

Sine, cosine and tangent of an angle in degrees. A quarter turn is exact, so sin(180) is 0. tan(90) has no value.

asin acos atan

The angle, in degrees, of a sine, cosine or tangent: -90 to 90, 0 to 180, -90 to 90. asin and acos need a value from -1 to 1.

atan2(y, x)

The angle of the point x, y from the +X axis, -180 to 180.

sqrt abs

Square root of a value that is not negative; the value without its sign.

exp log

e raised to the value, so exp(1) is e; the natural logarithm of a value above zero.

round floor ceil

The nearest whole number, with a half rounding away from zero; the nearest at or below; at or above.

min max

The smallest or largest of one or more values.

lerp(from, to, t)

The point t of the way from one value to the other: from at 0, to at 1, and on past either end.

curve(value, value, …, t)

A smooth curve through the values, the first at t 0 and the last at 1, never beyond any of them, holding the ends outside. The curve an extrude size list follows.

pi

The constant π, written bare like a number.

Heights along a sine wave
Heights along a sine wave rendered from the script above

An unknown name, a call with the wrong number of arguments, and a call with no value - the square root of a negative number - are errors.

measures#

Read a size back from a labelled volume: the side of its slot along X, Y or Z, measured in the frame the volume was placed in. A measure stands wherever a number does.

label.width  label.depth  label.height
Argument / optionMeaning & constraints
label

A volume named with label: before its solid, already built and still in scope.

width depth height

The slot along the X, Y and Z of its own frame, the order block takes its sizes in.

A plate sized to its text
A plate sized to its text rendered from the script above

It is the slot that is measured, not the material, since the slot is what every other volume is placed from. The two are the same box for most volumes; a partial revolve, circular pattern or helix measures the whole circle it turns about, and with shrink the arc its material covers. A slot measures a solid without building it, and a labelled macro call measures the part its body built. A solid cannot measure itself.

width( ) height( )#

Measure a 2D shape in its own frame: how far it reaches along x or y, or only at a given y or x. A shape measure stands wherever a number does.

width(2d-shape [, y])  height(2d-shape [, x])
Argument / optionMeaning & constraints
2d-shape

Any 2D shape, modifiers included, written as a profile is. It ends at the comma. A path stands upright, its y running up, as a sweep builds it.

y / x

Where to measure: from the leftmost point at that y to the rightmost, holes and gaps included. Outside the shape it is an error.

A star vase sized by a revolve silhouette
A star vase sized by a revolve silhouette rendered from the script above

A circle is centred, so width(circle 20, 0) is 20 and width(circle 20, 10) is 0. A silhouette drawn for a revolve is half of the solid, so its width is the radius.

09 / Organize the build

Script structure

Branch from a reference, combine solids into a compound, and choose how their material joins. Define reusable parts with def and choose what to build with if.

[ list ]#

Branch every item from the reference saved at the opening bracket. Closing the list restores that reference.

[ statements ]
cube 20 [
  @left color gold cube 8
  @right color coral cube 8
]
@top sphere 10

Settings and labels are local to the list. Variables and boolean operations remain in the surrounding context. A nested list immediately after an item branches from that item's volume. A build plane selected inside the list reaches only the item it leads into.

{ compound }#

Fuse a body into one placeable solid, with its own origin, labels, and boolean operations.

[properties] { statements } [| modifier …]

Touching and overlapping children are joined; disconnected children remain parts of the same solid. The placement box encloses the slots of the children that add material, including empty ones; a - or & child leads the next one but claims no room. Appearance enters the body; placement applies to the finished compound.

color steelblue {
  block 30 30 6
  cylinder 16 20
}

− / & / ^#

Change how a solid combines with existing material in the same construction context. Without a sign, geometry is added.

[properties] -solid
[properties] &solid
[properties] ^solid
Argument / optionMeaning & constraints
-

Difference: remove the operand from earlier material.

&

Intersection: retain only overlap.

^

Symmetric difference: retain material belonging to exactly one of the two.

A pocket cut into a compound
A pocket cut into a compound rendered from the script above

A signed volume cannot be the first volume in its construction context. It reaches inward along its anchor axis. Difference defaults to drilling from the top; intersection and symmetric difference default to base alignment. The operand leaves a placement reference even when its material is removed. A difference that removes no material is a warning.

def#

Define a reusable compound or 2D shape with numeric parameters, then call it like a solid, or where a shape is expected. A definition stands among the statements of the script, never inside braces, a list or a branch; a statement calls the macros defined above it, and a body any macro defined by the time it runs.

def %name $parameter … { statements }
def %name $parameter … statement
def %name $parameter … 2d-shape
%name argument …
Argument / optionMeaning & constraints
%name

A valid identifier after %, written the same in the definition and every call. Any name is free, including one of a built-in command.

$parameter / argument

Any number of numeric parameters, including zero. Call arguments must match the parameter count.

body

A construction context of its own. Sees the variables set above the definition, with their values there, and its parameters; inherits appearance settings, but not the caller's variables or internal placement. Without braces it is one statement.

2d-shape

A shape body makes a shape macro, called inside extrude, revolve, helix, or sweep. Settings such as font-size are read where it is used.

One part, two sizes
One part, two sizes rendered from the script above

Definitions may call other macros and can be written in any order. A call accepts properties, boolean signs, and modifier pipelines.

One outline, swept twice
One outline, swept twice rendered from the script above

A shape macro is a solid nowhere else: calling it as a statement, or a solid macro in place of a shape, is an error.

part#

Begin a part of the model: the material built after it, up to the next part, is exported to 3MF as one named object, to STEP as bodies carrying its name, and shown or hidden as one in the editor. A part stands among the statements of the script, never inside braces, a list, a branch or a macro body.

part name
Argument / optionMeaning & constraints
name

A string written out, spaces and all, such as "Left hinge". It names the part and is no reference; two parts may share a name.

A box and its lid
A box and its lid rendered from the script above

Placement, labels, settings and variables carry on across a part, so the lid is built on the box. Booleans do not: a part is a construction context of its own, and a signed volume reaches only its own part. What comes before the first part is a part with no name, exported as Unnamed. A part with no material warns and is left out of the export.

if#

Build the statement after the test when it holds, and the one after else when it does not. An if stands for the branch it picks; with none picked it is as though nothing were written.

if test statement [else statement]
Argument / optionMeaning & constraints
test

Two arguments compared with < <= > >= == !=, such as $ears == 1 or $style == "flange". A test of more than one comparison goes in parentheses, joined by and, or and not. Arithmetic in a bare test goes in parentheses, as in any argument.

statement

One statement, with any on written before it. A list branches several statements from the same reference; braces are a compound.

else statement

Optional. Built when the test does not hold; else if chains. An else belongs to the nearest if that can still take one.

Mounting ears that a parameter switches on
Mounting ears that a parameter switches on rendered from the script above

An if opens no scope and keeps no slot: what follows is placed against whatever the branch left behind, and with no branch picked against whatever the if itself followed. Setters written before it bind to the branch picked, and to nothing when none is. A macro may call itself behind a test, up to 64 calls deep.

10 / Repeat and arrange

Patterns

Repeat or mirror a body. Each pattern takes one statement as its body, with any on written in front of it; braces make that body a compound, and setters written before the command reach the body.

repeat#

Run a body repeatedly as a continuing sequence. The pattern leaves a combined slot around its iterations.

repeat count [with index $name] body
Argument / optionMeaning & constraints
count

Whole number from 0 to 10,000. Zero builds nothing.

with index $name

Optional zero-based iteration variable. Its previous value is restored afterward.

body

One statement, with any on written before it. Braces are a compound like anywhere else: one volume per iteration, placed by the setters before the brace, with its own variables and settings.

A row driven by its iteration index
A row driven by its iteration index rendered from the script above

One-shot setters before the pattern are consumed by its first solid. A repeat body continues its sequence even when the pattern appears inside a list.

linear#

Space the iterations out along X of the current frame, their centres the distance apart whatever size each iteration is.

linear distance count [with index $name] body
linear inset margin count [with index $name] body
Argument / optionMeaning & constraints
distance

From the centre of one iteration to the centre of the next. Negative runs toward −X.

inset margin

Instead of a distance: the row spans what it is placed against, its end centres the margin in from the ends, the rest spaced evenly. One iteration is centred.

count

Whole number from 0 to 10,000.

with index $name / body

Same index and body forms as repeat. Each iteration starts centred on its own point of the line.

Holes of growing size, evenly spaced
Holes of growing size, evenly spaced rendered from the script above

Unlike repeat, which puts each iteration against the previous one, a linear pattern spaces the centres, so iterations of different sizes stay on an even pitch. Placement setters before the pattern position the row as a whole, and what follows is placed against the box over what it built.

circular#

Place each iteration at its own point around a circle, beginning at +X and sweeping toward +Y in the current frame.

circular diameter count [angle degrees] [start degrees] [shrink]
           [with index $name] body
Argument / optionMeaning & constraints
diameter

Nonnegative diameter of the placement circle.

count

Whole number from 0 to 10,000.

angle / start

Sweep and starting angle. Defaults 360 and 0. Zero and negative sweeps are allowed.

shrink

Use material bounds instead of a slot mirrored about the sweep axis.

with index $name / body

Same index and body forms as repeat. Each iteration starts from its own circle point.

A circular pattern of holes
A circular pattern of holes rendered from the script above

Placement setters before the pattern position the ring as a whole. Appearance setters reach only its first solid unless made persistent. Wrap the pattern in a compound to isolate its booleans.

grid#

Lay the iterations out in cells, columns along X and rows along Y of the current frame. Every cell is the size of the largest iteration.

grid columns rows [gap] [inset margin] [y-margin] [with index $name] body
Argument / optionMeaning & constraints
columns / rows

Whole numbers; their product is at most 10,000. Zero builds nothing.

gap

Distance between neighbouring cells. Default 0, cells touching; negative overlaps them.

inset margin y-margin

Instead of a gap: the grid spans what it is placed against, its outermost centres the margin in from the edges, y-margin along Y if given. grid 2 2 inset 9 puts four corner holes 9 from the edges.

with index $name / body

Same index and body forms as repeat. The index runs along a row first, from the left front cell; each iteration starts centred in its own cell.

A grid of holes
A grid of holes rendered from the script above

Placement setters before the pattern position the grid as a whole, and what follows is placed against the box over all its cells. A grid of negative volumes reaches into what it was placed against, as a single negative volume does.

mirror#

Build the body, then a reflected copy of it beside it, the two standing against a plane between them that faces the axis.

mirror axis [gap] [inset margin] [with index $name] body
Argument / optionMeaning & constraints
axis

x, y, or z of the current frame; the plane is normal to it.

gap

Distance between the halves. Default 0, halves touching; negative overlaps them.

inset margin

Instead of a gap: the pair spans what it is placed against, each centre the margin in from its edge. Not for mirror z.

with index $name / body

Same index and body forms as repeat. The index is 0 for the original, on the negative side, and 1 for the copy.

A bracket written as one half
A bracket written as one half rendered from the script above

Each half is placed by its size, as an iteration of a linear pattern is, whatever offset its body is built at. The copy is a true reflection, so text in it reads backwards, and a hole the body drills into an earlier volume is mirrored too. Placement setters before the pattern position the pair as a whole, by the box over both halves; nest one mirror in another for a part symmetric in two directions.

From reference to model

Make it your own.

Combine a solid, a placement command, and a modifier. The editor provides argument hints as you write.

Open editor Read the learning guide →