# Sketches

A sketch (`core.sketch`) is a 2D drawing on a plane: points, lines, circles, arcs, splines and text, held in place by constraints and dimensions. Its closed regions become profiles for extrude, revolve, sweep and loft, and its points place holes. Dimensions are expressions, so a sketch follows the part's parameters.

Read [Working with plans](working.md) and [Parts](parts.md) first.

## Sketch templates

Most sketches are a rectangle, circles, hole points, a polygon outline or a slot. The `sketch.template` plan helper writes them fully constrained, with every size an expression:

```json
{
  "type": "sketch.template",
  "id": "$sk",
  "name": "Base",
  "template": {
    "kind": "rectangle",
    "width": "width",
    "depth": "depth",
    "plane": { "kind": "origin", "plane": "XY" }
  }
}
```

| Template                                                                    | Shape                                                                                                                                             |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{"kind":"rectangle","width":..,"depth":..}`                                | Centered on the origin; its lines are bottom, right, top, left.                                                                                   |
| `{"kind":"circles","diameter":"6 mm","centers":[{"x":"0 mm","y":"pitch"}]}` | Circles of one diameter.                                                                                                                          |
| `{"kind":"points","points":[{"x":"-30 mm","y":"0 mm"}]}`                    | Points, for hole centers.                                                                                                                         |
| `{"kind":"profile","corners":[{"x":..,"y":..},..],"axis":[[0,0],[0,10]]}`   | A closed polygon with every corner dimensioned from the origin; the optional axis is a construction line for a revolve.                           |
| `{"kind":"slot","from":{..},"to":{..},"width":"6 mm"}`                      | A slot between two arc centers; its lines are top and bottom, its arcs start and end.                                                             |
| `{"kind":"polygon","center":{..},"sides":6,"diameter":"10 mm"}`             | A regular polygon inscribed in a construction circle, its first side horizontal at the bottom (a hex's flats are `diameter * cos(30 deg)` apart). |

The answer lists the entity ids each template made (`sketches` in the preview), for later plans that constrain, trim or reference them.

## Sketch planes

`plane` is one of:

- `{"kind":"origin","plane":"XY"|"XZ"|"YZ"}`, the default XY. XY: sketch x is the part's X, y its Y, the normal +Z. XZ: x is X, y is Z, the normal -Y. YZ: x is Y, y is Z, the normal +X. Extrudes go along the normal (`reversed` against it), holes against it.
- `{"kind":"face","ref":{"kind":"face","name":<topological name>}}`: a planar face of a body, from `query_geometry` or one of your own placeholders (`f($base:end)`). The sketch follows the face when it moves. Its origin is the part's origin dropped onto the face's plane, sketch x is the part's X laid on the face (the part's Y when the face faces mostly along X), and sketch y is the normal crossed with x, so it depends on which way the face faces:

  | The face faces | Sketch x | Sketch y |
  | -------------- | -------- | -------- |
  | +Z             | X        | Y        |
  | -Z             | X        | -Y       |
  | +Y             | X        | -Z       |
  | -Y             | X        | Z        |
  | +X             | Y        | Z        |
  | -X             | Y        | -Z       |

  So hole centers on the top of a flange that faces +Y take the part's Z with its sign changed as y.

- `{"kind":"plane","feature":<core.plane id>}`: a construction plane, offset from a plane or a face. The offset goes along the base's normal: from XZ toward -Y, so a plane at Y = 20 mm is XZ with offset `-20 mm`.

`sketch.setPlane` moves a sketch to another plane.

## Drawing by hand

For shapes no template makes, create a `core.sketch` with its entities and constraints. Points carry a first guess of their position in mm; the solver moves them to satisfy the constraints. Fix one point (or constrain it to the origin) and dimension the rest until the sketch has no degrees of freedom left (`get_sketch` says how many remain).

```json plan:gusset
{
  "summary": "Triangular gusset 40 x 30, 5 mm thick",
  "steps": [
    {
      "label": "Gusset",
      "commands": [
        { "type": "document.rename", "name": "Gusset" },
        {
          "type": "feature.create",
          "id": "$tri",
          "featureType": "core.sketch",
          "name": "Triangle",
          "params": {
            "plane": { "kind": "origin", "plane": "XY" },
            "entities": [
              { "id": "$p1", "kind": "point", "x": 0, "y": 0, "fixed": true },
              { "id": "$p2", "kind": "point", "x": 40, "y": 0 },
              { "id": "$p3", "kind": "point", "x": 0, "y": 30 },
              { "id": "$bottom", "kind": "line", "start": "$p1", "end": "$p2" },
              { "id": "$side", "kind": "line", "start": "$p1", "end": "$p3" },
              { "id": "$slope", "kind": "line", "start": "$p2", "end": "$p3" }
            ],
            "constraints": [
              { "id": "$h", "kind": "horizontal", "line": "$bottom" },
              { "id": "$v", "kind": "vertical", "line": "$side" },
              {
                "id": "$w",
                "kind": "distance",
                "a": "$p1",
                "b": "$p2",
                "value": "40 mm"
              },
              {
                "id": "$t",
                "kind": "distance",
                "a": "$p1",
                "b": "$p3",
                "value": "30 mm"
              }
            ]
          }
        },
        {
          "type": "feature.create",
          "id": "$plate",
          "featureType": "core.extrude",
          "name": "Gusset",
          "params": {
            "sketch": "$tri",
            "operation": "new",
            "body": "$body",
            "distance": "5 mm",
            "direction": "normal"
          }
        }
      ]
    }
  ]
}
```

Constraints: `coincident`, `horizontal`, `vertical`, `horizontalPoints`, `verticalPoints`, `parallel`, `perpendicular`, `equalLength`, `equalRadius`, `tangent`, `pointOnLine`, `pointOnCircle`, `midpoint`, `symmetric`. Dimensions, with a `value` expression: `distance`, `horizontalDistance`, `verticalDistance`, `pointLineDistance`, `radius`, `diameter`, `angle`, `lineOffset`, `radiusDifference`.

Commands on an existing sketch: `sketch.add` (entities and constraints), `sketch.remove`, `sketch.constrain`, `sketch.setDimension` (a dimension's value), `sketch.move`, `sketch.setConstruction`, `sketch.setFixed`. Construction geometry (`"construction": true`) guides the shape and makes no profile.

## Sketch tools

Commands on a sketch's stored geometry:

- `sketch.trim`: a curve and a point on the piece to remove; it is cut back to the curves that cross it.
- `sketch.extend`: a free end to the next curve.
- `sketch.offset`: curves, a distance expression and its value in mm, side `inside`, `outside` or `both`; linked offsets follow the original. A whole loop is the usual input.
- `sketch.mirror`: curves and a line; the copies stay symmetric.
- `sketch.fillet`: a corner point where two lines meet and a radius; the corner stays as a construction point.
- `sketch.project`: model edges by topological name with their shape on the sketch plane; the rebuild moves them with the edge, and a lost edge leaves `SKETCH_PROJECTION_DANGLING`. Its `ids` go in order, per edge: the projection, then its fixed entities (a line: two points and the line; a circle: center and circle; an arc: center, start, end and arc). With `"ids":["$proj","$c","$circle"]` a later `sketch.offset` in the same plan takes `["$circle"]`.

Slots and regular polygons drawn by hand are lines and arcs added with `sketch.add`, with tangent, equal and point-on-circle constraints.

## Splines

A spline is a sketch entity over ordinary points: by `fit` it passes through them, by `control` it is shaped by them (add construction lines between control points to constrain its tangents). Constraints go on its points, not on the curve. `sketch.setSpline` switches between fit and control. Splines work in profiles and in sweep paths.

## Text

Text is a sketch entity at a point: an expression `height` (of a capital letter) and `angle`, font `noto-sans`, `noto-sans-mono` or `inter`, `bold`, align `left`, `center` or `right`. Its outlines are closed regions: extrude them to emboss, or cut to engrave. `{name}` in the text is a parameter's value and `{project.name}` a project parameter's, so a part number or a size follows the part. `sketch.setText` changes it.

```json plan:name-plate
{
  "summary": "Name plate 60 x 20 x 3 with MOKET engraved 0.5 mm deep",
  "steps": [
    {
      "label": "Plate, its top face at Z = 0",
      "commands": [
        { "type": "document.rename", "name": "Name plate" },
        {
          "type": "sketch.template",
          "id": "$outline",
          "name": "Outline",
          "template": {
            "kind": "rectangle",
            "width": "60 mm",
            "depth": "20 mm"
          }
        },
        {
          "type": "feature.create",
          "id": "$base",
          "featureType": "core.extrude",
          "name": "Plate",
          "params": {
            "sketch": "$outline",
            "operation": "new",
            "body": "$plate",
            "distance": "3 mm",
            "direction": "reversed"
          }
        }
      ]
    },
    {
      "label": "Engraving",
      "commands": [
        {
          "type": "feature.create",
          "id": "$label",
          "featureType": "core.sketch",
          "name": "Label",
          "params": {
            "plane": { "kind": "origin", "plane": "XY" },
            "entities": [
              { "id": "$at", "kind": "point", "x": 0, "y": -4, "fixed": true },
              {
                "id": "$text",
                "kind": "text",
                "text": "MOKET",
                "font": "inter",
                "bold": true,
                "position": "$at",
                "height": "8 mm",
                "angle": "0 deg",
                "align": "center"
              }
            ],
            "constraints": []
          }
        },
        {
          "type": "feature.create",
          "id": "$engrave",
          "featureType": "core.extrude",
          "name": "Engrave",
          "params": {
            "sketch": "$label",
            "operation": "cut",
            "targets": ["$plate"],
            "distance": "0.5 mm",
            "direction": "reversed"
          }
        }
      ]
    }
  ]
}
```
