# Patterns

[Start here](https://pegmatite.dev/guide/start.md). Fetch this topic when you repeat a statement in a row, ring, grid or mirrored pair, space holes a margin in from the edges, or need what a pattern leaves as the reference.

## Common rules

Every pattern has the form `kind arguments [with index $name] body`. `repeat` continues a sequence; `linear` spaces centers along X; `circular` spaces them around a circle; `grid` fills rows and columns; `mirror` adds a reflected copy.

- A count is a number, variable or expression, a whole number from 0 to 10,000; `0` builds nothing. For `grid`, _columns_ × _rows_ follows the same limit.
- `with index $name` counts iterations from 0. The index is local: it is undefined after the pattern, and an outer variable of the same name keeps its value. Nested patterns name their own index.

```pegm
set $i 5
repeat 3 with index $i cube (10 + $i)   // cubes of 10, 11 and 12
cube $i                                 // 5
```

### The body is one statement

The body is one statement with its setters and pipeline, and may span lines; whatever follows is outside the pattern, whatever the indentation. An `on` in front of the solid belongs to the body: `repeat 3 on #top cube 10` builds a stack.

```pegm
circular 40 4 on #front text "A" | extrude 4
```

Braces make the body a [compound](https://pegmatite.dev/guide/start.md#compounds-and-parts): each iteration is one fused volume, placed by the setters before the brace. A setter on the first solid inside only moves it within the compound, so it warns; a statement built on `root` is the exception. A `set`, a persistent setting or a label inside the braces ends with the iteration, so every iteration starts from the same state; use the index for what changes. A cut inside the braces cuts only the iteration; to drill earlier material with several solids, negate the compound, `-{ … }`.

```pegm
repeat 3 {
  @right 2 cube 10    /* Expected warning: this placement has no effect */
}
```

```pegm
block 60 20 10
on #top
linear 15 4 -{
  cylinder 9 2
  @bottom cylinder 5 8
}
```

Each iteration is a counterbored hole.

### What a pattern leaves

The pattern leaves the **box over everything its iterations built** as the reference; the next statement is placed against it, and `on` names its faces. The iterations are not fused: put the pattern in braces to fuse it or apply a modifier. A pattern that builds nothing leaves nothing, and the next statement follows what came before the pattern.

```pegm
repeat 4 @right cube 10
on #top cube 4      /* centered on top of the whole row */
```

```pegm
cube 10
repeat 0 cube 4
@right cube 4       /* to the right of the cube 10 */
```

For `linear`, `circular`, `grid` and `mirror`, placement setters before the pattern place its combined slot, not single iterations. A pattern of negative volumes reaches into its reference like a negative solid, so a row of holes drills the face it was placed on. Appearance setters reach only the first solid; write them with `!` or inside the body to apply them to every iteration.

### Spanning the reference with `inset`

`linear`, `grid` and `mirror` take `inset` _margin_ in place of their distance or gap. The pattern then spans what it is placed against, the face after `on` or the previous volume: its outermost centers stand the margin in from the edges, and the rest are spaced evenly between, whatever size the iterations are. A single iteration is centered. The slot is the reference's width on the spanned axes, so the pattern lands centered on it; a margin over half the width is an error. This is how holes dimensioned from the edges are written:

```pegm
block 95 60 10
[
  -cylinder 12 10
  grid 2 2 inset 9 -cylinder 5.5 10   // four holes, centers 9 from the edges
]
```

## repeat

**Syntax:** **`repeat`** _count_ [**`with index $`**_name_] _body_

Each iteration is placed against the previous one, so the gaps are even. All one-shot setters before `repeat` go to its first solid.

```pegm
!@right 2
repeat 5 cube 10
```

```pegm
block 60 20 10
on #top
!@right 6
x left 11 repeat 4 -cylinder 5 10
```

`x left 11` places the first hole, which centers the row of four on the block.

## linear

**Syntax:** **`linear`** _distance_ _count_ [**`with index $`**_name_] _body_

**Syntax:** **`linear inset`** _margin_ _count_ [**`with index $`**_name_] _body_

_distance_ runs from one iteration's center to the next; negative runs towards −X, so iteration 0 is at the +X end; `0` puts every iteration in one place. The centers are spaced, not the gaps: an iteration of any size keeps its place on the line.

```pegm
linear 16 5 with index $i cylinder (4 + $i * 2) 6
```

The cylinders grow from 4 to 12 across with centers 16 apart; `!@right 4 repeat 5` would keep the gaps at 4 instead. With `inset`, the count comes after the margin and the row spans its reference: `on #top linear inset 10 4 -cylinder 5 10` drills four holes across a block, the outer two 10 from its ends. Each iteration is centered on its point across the plane, whatever offset its body is built at, and keeps its own height above the lowest of them. Iterations branch from their own point; inside one, statements follow each other as usual.

```pegm
linear 10 4 cube 6
@top block 36 6 2    /* one bar across the whole row */
```

## circular

**Syntax:** **`circular`** _diameter_ _count_ [**`angle`** _degrees_] [**`start`** _degrees_] [**`shrink`**] [**`with index $`**_name_] _body_

| Option            | Default | Rule                                                      |
| ----------------- | ------- | --------------------------------------------------------- |
| _diameter_        |         | zero or greater                                           |
| `angle` _degrees_ | `360`   | sweep shared by the iterations; zero and negative allowed |
| `start` _degrees_ | `0`     | angle of the first iteration, from +X                     |
| `shrink`          | off     | the slot is the box over what was built                   |

`angle` and `start` may come in either order; a repeated one keeps its last value. A full turn is closed, shared out over the iterations; any other sweep is open, with an iteration at each end when there are at least two. One iteration sits at `start`. A negative sweep runs the other way.

```pegm
circular 40 4 cube 4                    /* 0, 90, 180 and 270 degrees */
circular 40 4 angle 90 cube 4           /* 0, 30, 60 and 90 degrees */
circular 40 4 angle 90 start 45 cube 4  /* 45, 75, 105 and 135 degrees */
```

Each iteration stands on its own point of the circle, turned by its share of the sweep, so a solid facing out on the first faces out on every one. Iterations branch from their point; a braced body's statements follow each other. An anchor in the body moves the solid from its point: `@bottom` hangs it under the circle, `@center` sinks it onto the point. This sets the iterations relative to each other; the ring itself goes where its slot goes.

```pegm
cylinder 60 10
on #top circular 40 6 @top -cylinder 6 10   // six holes on a 40 bolt circle
```

The placement frame sets the circle's plane, and the slot its position: `sphere 30` then `@center circular 30 4 sphere 5` rings the equator; without `@center` the ring sits on top of the sphere.

### The slot is the circle

The slot is the generated bounds mirrored about the circle's center. Two opposite arcs of one circle claim the same slot, an odd count is not off-center, and `angle` and `start` move the material without moving the ring:

```pegm
sphere 70 | cut 30 40
[
  @top 1 circular 65 19 angle 154 start 103 sphere 4
  @top 1 circular 65 19 angle 154 start 283 sphere 4
]
```

`shrink` uses the box over what was built instead, placed like any solid. A ring whose iterations cut a volume built before it stays where its circle put it, so a bolt circle drills the face it was placed on.

## grid

**Syntax:** **`grid`** _columns_ _rows_ [_gap_] [**`inset`** _margin_] [_y-margin_] [**`with index $`**_name_] _body_

_columns_ run along X, _rows_ along Y. _gap_ is the distance between cells, `0` by default so cells touch; a negative gap overlaps them, `grid 4 4 -2 sphere 10`. Every cell has the largest width, depth and height of all iterations, and each iteration is centered in its cell on X and Y, so rows stay straight:

```pegm
grid 3 2 2 with index $i cylinder (4 + $i * 2) 6   // cells 14 across
```

The index runs along the first row, then the next: iteration 0 is at the left front, the row runs towards +X, and each new row is further +Y; with 4 columns, iteration 5 is the second of the second row. Iterations branch from their own cell and stand on it as on the ground. The slot encloses all cells, gaps included:

```pegm
block 50 50 6
on #top grid 4 4 4 -cylinder 6 6
```

`inset` replaces the gap and spans the reference on both axes; a second value sets the margin along Y, `grid 3 2 inset 10 8`.

## mirror

**Syntax:** **`mirror`** _axis_ [_gap_] [**`inset`** _margin_] [**`with index $`**_name_] _body_

_axis_ is `x`, `y` or `z`, normal to the plane between the halves: `mirror x` sets them side by side along X. The original is on the negative side, the copy on the positive side, each against the plane or half the _gap_ from it; a negative gap overlaps. A half is placed by its size like a `linear` iteration, so `mirror x x 15 cube 10` is two cubes meeting at the plane; only the gap spaces them. The index is 0 for the original and 1 for the copy, and a label in the body names the original half. The slot encloses both halves with the plane in its middle, even when the halves differ.

```pegm
mirror x {
  block 30 24 4
  [ on #top x 6 -cylinder 8 4 ]
  @top x left block 4 24 20
}
```

A bracket with a hole in each foot, written as one half.

`inset` replaces the gap: the halves span the reference along the axis, each centered the margin in from its edge, `on #top mirror x inset 8 -cylinder 4 6`. `mirror z` takes no inset.

### The copy is reflected

The copy is the reflection, with the opposite handedness: a profile is reversed, a helix turns the other way, text reads backwards. Put lettering that must read correctly outside the pattern. Each volume of the copy is reflected as it is finished, so a hole the body drills into earlier material is mirrored too:

```pegm
block 60 20 4
on #top mirror x 20 -path "M0,0 H10 L10,6 Z" | extrude 4
```

### Two planes

A mirror has one plane; for symmetry in two directions, mirror a mirrored pair:

```pegm
mirror y mirror x cube 10    /* four cubes meeting at the center */
```
