# 2D shapes

[Start here](https://pegmatite.dev/guide/start.md). Fetch this topic when a profile needs an exact outline: an ellipse, a star, a polygon, an SVG path, or the outline of an existing face.

## Shapes

A 2D shape becomes a solid with `| extrude`, `| revolve`, `| helix` or `| sweep` ([extrude.md](https://pegmatite.dev/guide/extrude.md), [sweeps.md](https://pegmatite.dev/guide/sweeps.md)). Alter outlines and combine them with [2D operations and groups](https://pegmatite.dev/guide/shape-operations.md); reuse them with [shape macros](https://pegmatite.dev/guide/macros.md). `circle`, `rect`, `ellipse`, `star` and a regular `polygon` are centered on their origin; `polygon points`, `path` and `text` use drawn coordinates. Sizes take variables and expressions, and a size not greater than zero is rejected.

### Sketches

A shape with no sweep after it is a sketch. It is placed exactly as the solid swept from it would be, and the preview draws its outline where that solid's base would lie. It builds nothing: no material, no slot, and the next volume is placed as though it were not there. The script builds with a warning:

```pegm
/* Expected warning: the circle is a sketch, drawn and not built. */
block 40 40 10
circle 20
@right 4 cube 10
```

The cube stands beside the block. A sketch's label and sign wait for its sweep, `-circle 20 | extrude 6`. Braces holding only shapes are a group, and so one sketch; a shape macro called as a statement is a sketch of its shape.

### `circle`

**Syntax:** **`circle`** _diameter_

### `rect`

**Syntax:** **`rect`** _width_ _height_

_width_ runs across X, _height_ across Y, the shape's own axes. An extruded `rect` is a `block`.

### `ellipse`

**Syntax:** **`ellipse`** _diameter-x_ _diameter-y_

Both diameters span the whole shape.

### `star`

**Syntax:** **`star`** _spikes_ _outer-diameter_ _inner-diameter_

The base of a `starprism`: `star n outer inner | extrude h` is `starprism n outer inner h`. Spikes reach the outer circle, notches the inner one; _inner-diameter_ must be smaller than _outer-diameter_, and _spikes_ a whole number of 3 or more. The origin is the center of both circles, the first spike points along +X, so `revolve` turns about that point and `apex [0 0]` stands over the middle:

```pegm
star 5 40 20 | extrude 20 apex [0 0]
```

### `polygon`

**Syntax:** **`polygon points [`**_x_ _y_**`]`**…

**Syntax:** **`polygon`** _sides_ [**`diameter`** | **`edge`** | **`across`**] _size_

With `points`, list at least three corners in outline order, in the shape's own coordinates with Y up. Coordinates take expressions. The outline closes itself; a repeated first point is allowed, and either winding works.

```pegm
set $w 30
polygon points [0 0] [$w 0] [($w / 2) 20] | extrude 4
```

Crossing edges, self-touching outlines and edges that double back are rejected:

```pegm
/* Expected error: the edges of a polygon must not cross. */
polygon points [0 0] [10 10] [10 0] [0 10] | extrude 4
```

With a side count it is a regular polygon sized and oriented like a `prism` base: at least three sides, _size_ the diameter through the corners by default, a flat facing front, the origin at the circumcircle center. These two give the same shape and numbered faces:

```pegm
polygon 6 across 24 | extrude 20
@right 10 prism 6 across 24 20
```

### `path`

**Syntax:** **`path`** _SVG-path_

An SVG path string. SVG Y grows downward, so the path is flipped to stand as drawn: a larger Y is lower. This matters for `revolve` and `helix`, where Y becomes height; draw the profile as it looks on screen. The flange drawn at Y 0 is the top here:

```pegm
path "M0,0 H10 V2 H2 V20 H0 Z" | revolve
```

The `points` of an SVG `<polygon>` paste between `M` and `Z`, since pairs after a move are lines:

```pegm
path "M20,0 40,20 30,20 30,40 10,40 10,20 0,20 Z" | extrude 10
```

A literal accepts the commands `M L H V Z C S Q T A` and their lowercase forms, digits, decimal points, minus signs, commas and whitespace; it rejects `+` and exponents, which a path in a string variable accepts. Use plain decimals in both. A path is filled, so every subpath is closed before it is raised; only `extrude … wall` and a `sweep` trajectory read a subpath as the open line it was drawn as.

## Faces as shapes

**Syntax:** _face_ or _label_ _face_

A [face reference](https://pegmatite.dev/guide/placement.md) where a shape is expected stands for that face's outline, drawn in the face's own frame along the directions `on` places a solid in. A bare face, alone, under outline modifiers or as a tiling's area, also places the solid on that face, so it covers the face edge to edge:

```pegm
rect 40 40 | extrude 50 apex [0 0 -170]
#f2 | extrude 2
```

An `on` written out still decides where the solid goes: `on #top #front | extrude 2` lays the front's outline on the top.

A bare face is read off the volume the next solid is built against, the one `on` would read; after `on base`, that is `base`. Right after `on base`, though, a face belongs to `on`, `on base #top`, so write the profile in a group there: `on base { #top } | extrude 2`. A label in front reads that volume's face wherever the shape is used:

```pegm
base: cylinder 40 10
@right 10 base #top | extrude 2
```

Through a label, the outline is the face as the labelled statement built it, pipeline and all; a later boolean cuts the model, not that outline. So a lid from a hollowed box's top covers the whole box:

```pegm
box: block 40 40 20 [ -block 36 36 18 ]
z 10 box #top | extrude 2
```

To read the surface left after a cut, label a compound holding the cut: `box: { block 40 40 20 -block 36 36 18 }` makes `box #top` the rim. A bare face is always read as the volume stands now.

The outline is the real surface on the face: a cylinder's top is a circle. A direction must name a flat side the solid has: a sphere's `#top` or a cylinder's `#front` is an error. Every face of a bounding box, `#bounds.top`, gives the whole face. A face shape claims the whole face as its slot, so an outline covering part of the face keeps its place within it:

```pegm
{ block 20 20 10 @right block 20 20 5 }
on #top color red #top | extrude 2
```

The red plate stands on the higher block only. A face shape is most useful as the area of a [tiling](https://pegmatite.dev/guide/tilings.md), fitting a pattern to a face without measuring it.
