# Helix, sweep and varying profiles

[Start here](https://pegmatite.dev/guide/start.md). Fetch this topic when a part needs a thread, coil or spiral, a profile carried along a route, or a profile that changes along its sweep.

## Helix

**Syntax:** _2d-shape_ **`| helix`** _diameter_ [_end-diameter_] [**`pitch`** _distance_] [**`turns`** _count_] [**`height`** _rise_] [**`start`** _degrees_] [**`shrink`**] [**`about`** _axis_]

| Argument or option | Default           | Rule                                                                          |
| ------------------ | ----------------- | ----------------------------------------------------------------------------- |
| _diameter_         | Required          | Nonnegative diameter of the path of the profile's origin.                     |
| _end-diameter_     | Starting diameter | Nonnegative; written before named options.                                    |
| `pitch` _distance_ | `0`               | Nonnegative rise per turn.                                                    |
| `turns` _count_    | `1`               | Greater than 0, at most 100; fractional turns are allowed.                    |
| `height` _rise_    | Use `turns`       | Positive path rise; requires positive pitch. Cannot be combined with `turns`. |
| `start` _degrees_  | `0`               | Start angle around the axis.                                                  |
| `about` _axis_     | `z`               | `x`, `y`, or `z`.                                                             |
| `shrink`           | Off               | Use the material's bounds for placement.                                      |

```pegm
circle 5 | helix 40 pitch 10 turns 6
```

A helix is a [`revolve`](https://pegmatite.dev/guide/extrude.md) that climbs by _pitch_ every turn: six coils of wire 5 thick on a mean diameter of 40. The profile is read as by revolve, X a radius and Y a height, and stays in the plane through the axis, so it is the section a cut through the axis shows, as a thread form is drawn. Unlike revolve, a helix keeps the side of the axis its profile is drawn on; a profile crossing the axis is refused.

- `height` states the turns as the rise of the **path**, which the pitch divides into turns. The material reaches half a profile past each end, and the [slot](https://pegmatite.dev/guide/booleans.md) holds that overshoot: below, the thread is 62 tall, not 60, sticks out by 1 at both ends of its rod, and anything stacked on it or a compound holding it measures 62.
- _end-diameter_ makes the path climb a cone, growing by an even share each turn. Growing without rising is a flat spiral.
- Neither rising nor growing comes back to the start: one turn is a ring (`circle 5 | helix 40` is `circle 5 | revolve 40`); more turns warn and build one.
- A helix starts at +X and rises toward +Y, a right-handed thread; [`| flip x`](https://pegmatite.dev/guide/modifiers.md) makes it left-handed. `start` and `about` read as on a revolve.
- An open helix is capped with the profile at both ends. A pitch smaller than the profile's height makes coils overlap into a self-crossing surface.
- A turn or more claims the box over the sweep. Less than a turn claims the box mirrored about the axis, as a partial revolve does; `shrink` claims the material's own box.

```pegm
cylinder 20 60
@center path "M0,0 L2,1 L0,2 Z" | helix 20 pitch 4 height 60
```

```pegm
rect 3 1 | helix 10 60 turns 5
@right 10 circle 6 | helix 40 80 pitch 10 turns 4
@right 10 circle 5 | helix 40 about y pitch 10 turns 3 start 45 | flip x
```

### Thread ends

To end a thread flush, build it outside any compound, run it a pitch past each end, and trim it with an [intersection](https://pegmatite.dev/guide/booleans.md) `on` a label at the part's base:

```pegm
head: prism 6 30 10
cylinder 16 30
@center path "M-0.2,-1.2 L0,-1.2 L1.2,-0.3 L1.2,0.3 L0,1.2 L-0.2,1.2 Z"
  | helix 16 pitch 3 height 36
on head &path "M0,0 H8 L9.5,1.5 V30 H16 V40 H0 Z" | revolve
```

The bolt's thread caps lie inside the head and above the tip, where the intersection removes them, and its chamfer tapers the ridge to nothing; a helix stopped at the rod's ends would leave a blunt stub. The profile starts at X `-0.2` so thread and rod overlap rather than touch. The trimming path is drawn top first, since a path's Y grows downward. A nut is the same helix cut from a prism: `@center -{ cylinder … helix … }`, run a pitch past each face.

## Sweep along a path

**Syntax:** _2d-shape_ **`| sweep along`** _trajectory_ [**`about`** _axis_] [**`round`**]

| Argument or option   | Default        | Rule                                                                |
| -------------------- | -------------- | ------------------------------------------------------------------- |
| _2d-shape_           | Required       | Any 2D shape with an area. It must fit round the tightest bend.     |
| `along` _trajectory_ | Required       | Any 2D shape. Its outline is followed, and an open path stays open. |
| `about` _axis_       | `z`            | `x`, `y`, or `z`: the axis the trajectory's plane faces.            |
| `round`              | Mitred corners | Rounds the outside of every corner.                                 |

```pegm
block 80 40 6
on #top -rect 4 3 | sweep along path "M0,0 H30 C40,0 40,20 50,20 H70"
```

The trajectory lies in the build plane, where an extrude's shape lies, so on a face it follows a route drawn on that face: here a channel cut into a plate. Write the options after the trajectory. The result is an ordinary solid placed by the box over its material.

- The profile stands across the route: its X points to the **right** of the way an open path is drawn, its Y up off the plane. Its origin rides the line, so a measured shape is centered on it. The profile never twists.
- On a closed outline the profile's X points **outward**, whichever way it was drawn: a profile right of its origin lies outside the ring, one left of it inside.
- An open path's ends are capped square with the profile; a closed outline needs no caps. A [face](https://pegmatite.dev/guide/shapes.md) is followed along its real outline.
- Every outline of a path with several subpaths, a text or a [tiling](https://pegmatite.dev/guide/tilings.md) is swept on its own and the solids joined. A single outline that crosses itself gives a self-crossing surface; draw it as separate subpaths.
- Sharp corners are **mitred** like a wall's, and one sharper than a wall would mitre is cut off square. `round` turns the profile about the outside of every corner sharper than a circle's facet; the inside stays mitred.
- A profile may reach no further into a bend than its radius; wider is refused. Reaching only outward, it can turn as tightly as it likes.
- `about` names the axis the trajectory's plane faces. The trajectory's X lies on the axis that **follows** it in `x` → `y` → `z` → `x` and its Y on the next: `about x` has X along Y, `about y` has X running up Z.
- `rect 2 10 | sweep along path "M0,0 H30 V20"` equals `path "M0,0 H30 V20" | extrude 10 wall 2`; `circle 20 | sweep along circle 40` equals `torus 60 20`.

```pegm
path "M0,0 H5 V2 H0 Z" | sweep along circle 40
@right 10 path "M-5,0 H0 V2 H-5 Z" | sweep along circle 40
@right 10 rect 4 4 | sweep along rect 40 20 round
```

The first ring is 50 across, the second 40 with a bore of 30.

```pegm
cylinder 40 50
@right -2 color gold circle 6 | sweep along path "M0,0 C0,-30 36,-30 36,0" about y
```

A mug handle: X is the height, Y the distance out.

```pegm
/* Expected error: the profile is too wide for the bend */
circle 10 | sweep along circle 6
```

## Varying profiles

**Syntax:** _shape-macro_ [_argument_ …] **`|`** _sweep_ or **`%`** **`$`**_parameter_ _2d-shape_ **`|`** _sweep_

A varying profile is drawn anew at every point of its sweep. It is a [shape macro](https://pegmatite.dev/guide/macros.md) called with every argument but its last; the sweep supplies the last, from 0 at its start to 1 at its end.

| Sweep         | The last argument runs over |
| ------------- | --------------------------- |
| `extrude`     | the height                  |
| `revolve`     | the turn                    |
| `helix`       | the turns                   |
| `sweep along` | each outline of the route   |

```pegm
!@right 10
def %petal $depth $t star 6 40 (36 - $depth * $t)
%petal 8 | extrude 40
%petal 24 | extrude 40
```

Used once, it is written inline with `%` and its one parameter. Everything up to the sweep's word is the shape, modifiers included. Its own `rotate` may speed up, slow down or turn back, unlike [`twist`](https://pegmatite.dev/guide/extrude.md). A [`curve`](https://pegmatite.dev/guide/expressions.md) passes through given values; a path silhouette gives a size at every height through `width` (see [measures](https://pegmatite.dev/guide/expressions.md)).

```pegm
!@right 10
% $t rect 30 30 | round (1 + 13 * $t) | rotate (45 * $t) | extrude 40
% $t circle curve(20, 44, 16, $t) | extrude 60
% $t circle (8 + 12 * $t) | revolve 50 angle 270
% $t rect 3 (1 + 3 * $t) | helix 40 pitch 8 turns 4
```

- Each outline is joined to itself from one point to the next, starting where it is drawn from, so a turning profile turns the solid. Outlines with equal point counts pair points in order; others are cut at equal shares of the way round, keeping every corner.
- Size, corners and turn may change; the number of outlines and holes may not, and a change is refused naming where along the sweep it happens.
- A sweep that closes, a whole revolve or a sweep along a closed outline, must end on its starting shape or is refused there; a partial turn need not. `% $t circle (16 + 4 * sin($t * 720)) | revolve 60` swells twice and closes.
- Revolve and helix keep the profile to one side of the axis and sweep its outlines, passing over its holes. Extrude adds `twist` and `size` on top, and a `wall` of one thickness at every level; it takes no `apex` or `to`.
- It is drawn 8 times, then again halfway between two drawings wherever the shape strays from the straight way between them. Still straying after 160 extra drawings warns and builds from those.
- Written alone, it is a sketch of its starting shape.
