# Parts

A part is a parametric document: named parameters (expressions with units), an ordered history of features, and the solid bodies the features build. The history rebuilds from the parameters, so a part you build stays editable by hand: build it the way a careful engineer would, with parameters for the sizes that matter and features in a sensible order.

On a part use `inspect_document`, `get_feature`, `get_sketch`, `query_geometry`, `measure` and `get_selection`. Read [Working with plans](working.md) first.

## Parameters

- `parameter.create` with a name and an expression: `{"type":"parameter.create","id":"$t","name":"wallThickness","expression":"5 mm"}`. Names are identifiers; expressions use units (mm, cm, m, in, ft, deg, rad), other parameters, `pi` and the functions `sqrt`, `abs`, `min`, `max`, `floor`, `ceil`, `round`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan` and `atan2`.
- `parameter.update` changes an expression by id. Every feature that reads the parameter follows.
- Sizes several documents share come from the project's table as `project.<name>` (see [Project parameters](project-parameters.md)); never repeat a number another document owns.

## Features

`feature.create` adds a feature after the rollback marker: `{"type":"feature.create","id":"$f","featureType":"core.extrude","name":"Base","params":{...}}`. Read a feature type with `describe_commands` before its first use; `feature.update` replaces all params, so send the complete object from `get_feature` with your changes.

| Feature                                  | What it does                                                                                                                                                                                         |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `core.sketch`                            | A 2D sketch on a plane; see [Sketches](sketches.md). Prefer the `sketch.template` plan helper.                                                                                                       |
| `core.extrude`                           | Extrudes a sketch's closed regions: operation `new` (with a new `body` id), `join`, `cut` or `intersect` (with `targets`); direction `normal`, `reversed` or `symmetric`; extent `through` for cuts. |
| `core.revolve`                           | Revolves a sketch about a construction line of it, an origin axis or an edge; angle `"360 deg"` for a full turn.                                                                                     |
| `core.hole`                              | Holes at a sketch's points: simple, counterbore or countersink, through or to a depth, tapped with `thread`.                                                                                         |
| `core.fillet`, `core.chamfer`            | Rounds or bevels edges of one body by name.                                                                                                                                                          |
| `core.shell`                             | Hollows a body with open faces and a wall thickness.                                                                                                                                                 |
| `core.draft`                             | Tilts faces by an angle about a neutral plane, for molded parts.                                                                                                                                     |
| `core.sweep`, `core.loft`                | A profile along a path; a solid through profiles.                                                                                                                                                    |
| `core.pattern`                           | Repeats features linearly or around an axis.                                                                                                                                                         |
| `core.mirror`                            | Copies features or bodies across a plane.                                                                                                                                                            |
| `core.combine`                           | Join, cut or intersect bodies.                                                                                                                                                                       |
| `core.plane`                             | A construction plane, offset from a plane or a face.                                                                                                                                                 |
| `core.thread`, `core.coil`, `core.knurl` | Threads on round faces, springs and coils, knurls.                                                                                                                                                   |
| `core.import`                            | Solids of a STEP file, made by people only.                                                                                                                                                          |

`feature.delete`, `feature.rename`, `feature.suppress` and `feature.move` (`{"type":"feature.move","id":<feature>,"after":<feature>}`, `"after":"start"` for first) change the history; `timeline.setMarker` rolls it back for a look. A feature cannot move before what it uses.

## Names of faces and edges

Faces and edges are referenced by topological names (`{"kind":"face","name":"f(...)"}`, `{"kind":"edge","name":"e(...)"}`) that survive rebuilds: they name the feature and the sketch curve that made each face, not a number. Get them from `query_geometry` (filter by type, size, position or the feature that made them), `measure` or `get_selection`.

In the same plan you can name faces of features you create from their placeholders, in these forms:

- an extrude's start and end faces: `f($base:start)`, `f($base:end)`; a side face from a sketch line: `f($base:side:<line id>)` (the template answer lists line ids);
- an edge between two faces: `e(<face>|<face>)`, the two names sorted.

Never invent any other name or edit one.

## Building a part

1. Name it (`document.rename`) and set its material (`document.setMaterial`, for mass) in the first plan.
2. Create the parameters, then the base solid, then the features that cut and add, then the finishing touches (fillets, chamfers) last: a fillet before a cut is often cut away.
3. Put the origin where the part meets others: the face that sits on the base at Z = 0, a shaft's axis on Z. Assemblies and drawings are easier for it.
4. Check sizes with `measure` and add checks to the plan for what the user stated.

```json plan:mounting-plate
{
  "summary": "Mounting plate 100 x 60 x 8 with four M5 clearance holes",
  "steps": [
    {
      "label": "Name, material and parameters",
      "commands": [
        { "type": "document.rename", "name": "Mounting plate" },
        { "type": "document.setMaterial", "material": "aluminum-6061" },
        {
          "type": "parameter.create",
          "id": "$width",
          "name": "width",
          "expression": "100 mm"
        },
        {
          "type": "parameter.create",
          "id": "$depth",
          "name": "depth",
          "expression": "60 mm"
        },
        {
          "type": "parameter.create",
          "id": "$thickness",
          "name": "thickness",
          "expression": "8 mm"
        },
        {
          "type": "parameter.create",
          "id": "$inset",
          "name": "holeInset",
          "expression": "10 mm"
        }
      ]
    },
    {
      "label": "Plate, its top face at Z = 0",
      "commands": [
        {
          "type": "sketch.template",
          "id": "$outline",
          "name": "Outline",
          "template": {
            "kind": "rectangle",
            "width": "width",
            "depth": "depth",
            "plane": { "kind": "origin", "plane": "XY" }
          }
        },
        {
          "type": "feature.create",
          "id": "$base",
          "featureType": "core.extrude",
          "name": "Plate",
          "params": {
            "sketch": "$outline",
            "operation": "new",
            "body": "$plate",
            "distance": "thickness",
            "direction": "reversed"
          }
        }
      ]
    },
    {
      "label": "Four holes 10 mm in from the edges",
      "commands": [
        {
          "type": "sketch.template",
          "id": "$corners",
          "name": "Hole centers",
          "template": {
            "kind": "points",
            "points": [
              {
                "x": "-(width / 2 - holeInset)",
                "y": "-(depth / 2 - holeInset)"
              },
              { "x": "width / 2 - holeInset", "y": "-(depth / 2 - holeInset)" },
              { "x": "width / 2 - holeInset", "y": "depth / 2 - holeInset" },
              { "x": "-(width / 2 - holeInset)", "y": "depth / 2 - holeInset" }
            ],
            "plane": { "kind": "origin", "plane": "XY" }
          }
        },
        {
          "type": "feature.create",
          "id": "$holes",
          "featureType": "core.hole",
          "name": "Mounting holes",
          "params": {
            "sketch": "$corners",
            "targets": ["$plate"],
            "type": "simple",
            "diameter": "5.5 mm",
            "extent": "through"
          }
        }
      ]
    }
  ],
  "checks": [
    {
      "label": "Plate volume",
      "quantity": "volume",
      "a": { "kind": "body", "body": "$plate" },
      "min": 47200,
      "max": 47280
    }
  ]
}
```

A turned part is a profile revolved about its axis. Draw half of its outline on the XZ plane with the axis on Z:

```json plan:stepped-shaft
{
  "summary": "Shaft Ø20 x 60 stepping down to Ø15 x 40",
  "steps": [
    {
      "label": "Shaft",
      "commands": [
        { "type": "document.rename", "name": "Stepped shaft" },
        { "type": "document.setMaterial", "material": "steel" },
        {
          "type": "sketch.template",
          "id": "$half",
          "name": "Half profile",
          "template": {
            "kind": "profile",
            "corners": [
              { "x": "0 mm", "y": "0 mm" },
              { "x": "10 mm", "y": "0 mm" },
              { "x": "10 mm", "y": "60 mm" },
              { "x": "7.5 mm", "y": "60 mm" },
              { "x": "7.5 mm", "y": "100 mm" },
              { "x": "0 mm", "y": "100 mm" }
            ],
            "plane": { "kind": "origin", "plane": "XZ" }
          }
        },
        {
          "type": "feature.create",
          "id": "$turn",
          "featureType": "core.revolve",
          "name": "Shaft",
          "params": {
            "sketch": "$half",
            "axis": { "kind": "axis", "axis": "Z" },
            "angle": "360 deg",
            "direction": "normal",
            "operation": "new",
            "body": "$shaft"
          }
        }
      ]
    }
  ]
}
```

## Holes

A hole drills against its sketch plane's normal from the sketch's points: from XY down (-Z), from XZ toward +Y, from YZ toward -X, from a face into the body. Sketch the points on the face the hole starts from (`"plane":{"kind":"face","ref":{"kind":"face","name":<name>}}`), any face of any orientation, and the hole goes into the body; no offset plane is needed. From a plane outside the body facing away from it, set `"flip": true`. A hole that reaches no body fails with `HOLE_MISSES_BODY`.

- Clearance holes for screws: M3 3.4 mm, M4 4.5 mm, M5 5.5 mm, M6 6.6 mm, M8 9 mm (medium fit).
- Tapped holes: `"thread":{"standard":"iso-coarse","size":"M4"}` drills the tap drill (3.3 mm for M4) and puts a cosmetic thread on the wall; give a depth a little longer than the screw's engagement. A lead screw's nut: `{"standard":"iso-trapezoidal","size":"Tr12x3"}` (drilled to 9 mm), with `starts` and `leftHanded` as the screw has them. Bought trapezoidal nuts (DIN 103 hex, the T8 flanged nut) are in `find_standard_part`.
- Counterbores and countersinks take their diameter and depth or angle (`countersinkDiameter`, `countersinkAngle`).
- Patterns of holes: the points of one sketch, or `core.pattern` over the hole feature.

## Fillets, chamfers and finishing

- `core.fillet` and `core.chamfer` take edges of one body by name: find them with `query_geometry` (for example the edges of the top face, or the edges of a given length) and pass `{"kind":"edge","name":<name>}` for each.
- Fillet and chamfer last. A shell fails when the wall is as thick as a fillet radius or more (`SHELL_THICKER_THAN_FILLET`): shell before filleting, or keep the wall thinner.
- Mirror copies extrudes, revolves and holes across a plane, and the copies follow the originals (mode features); fillets and chamfers alone cannot be mirrored (`MIRROR_EMPTY`): mirror the feature they sit on, then fillet the copy. Mode bodies mirrors whole bodies.

## Shell, draft, sweep and loft

- **Shell** hollows a body: pick the faces to open (none for a closed hollow body) and a wall thickness, inside by default. The inner walls are named `f(<shell>:shell:<outer face>)`.
- **Draft** tilts faces (usually the sides) by an angle about a neutral plane, so a molded part comes out along the pull; faces keep their names. Draft before fillets and shell.
- **Sweep** moves a closed profile of one sketch along a path: curves of another sketch (lines, arcs and splines joined end to end, drawn so the path starts at the profile) and/or model edges. Sharp corners are mitred; a profile with holes needs a path without sharp corners. A broken path fails with `PATH_NOT_CONNECTED` naming the gap.
- **Loft** builds a solid through two or more profiles in order: one closed region per sketch (sketches on construction planes at different heights) or flat faces of bodies; smooth or ruled. Profiles cannot have holes.

## Threads, coils and knurls

- `core.thread` goes on a cylindrical face: standard `iso-coarse`, `iso-fine`, `unc` or `unf`, or for lead screws and their nuts `iso-trapezoidal` (`Tr12x3`) or `acme` (`1/2-10`); the size follows the face unless given (`pitch` picks among sizes of one diameter: Tr16x4 or Tr16x2); the full face or a length. `"starts":"4"` makes a multi-start thread (lead = starts x pitch: a 3D printer's Tr8x8(P2) is `Tr8x2` with 4 starts) and `"leftHanded":true` a left-hand one; a screw and its nut must agree on both to stay out of interference. A Tr or ACME nut is drilled to d - P (a tapped hole's `thread` does it). Cosmetic by default (no geometry change, shown on the face, named in STEP, and a library screw in a tapped hole stays out of interference); `"modeled": true` cuts the helical groove and is slow. `side` (`internal` for a nut or tapped bore, `external` for a screw) follows the face, so set it only to overrule it. `class` names the tolerance class and defaults to the usual one: `6g`/`6H` for ISO metric, `2A`/`2B` for UNC and UNF, `7e`/`7H` for Tr, `2G` for ACME.
- `core.coil` winds a circle, square or triangle around a sketch circle's axis: turns and pitch, height and turns, or height and pitch; taper; ground ends. Springs are coils.
- `core.knurl` puts straight or diamond grooves on round faces, cosmetic or modeled (`KNURL_HEAVY` above 2000 faces).

## Configurations

Configurations are named variants of one part (sizes, lengths, features built or suppressed): a table whose columns are parameters and features and whose first row is the default; an empty cell takes the default's value. Build the part once with parameters, then add rows instead of copying the part:

1. `configuration.create` with the columns (`{"kind":"parameter","id":<parameter>}`, `{"kind":"feature","id":<feature>}`) starts the table with a default row of the current values.
2. `configuration.addRow` adds a named row with the cells that differ (`{"values":{<column id>:"10 mm"}}`; placeholders of the same plan work as keys).
3. The part always is its active row: `parameter.update` and `feature.suppress` on a configured column change that row; `configuration.activate` switches rows.

Export (STEP, STL) builds the active row. For a file of each variant the user exports, switches the row (Part properties > Configuration) and exports again; you can switch it with `configuration.activate` when the user asks. In an assembly every component has its own row, so switching the part's changes no assembly.

Name rows as the maker or the standard names the sizes (`M3 x 8`, `MGN12H`). `inspect_document` lists the table.

## Material and appearance

- `document.setMaterial` sets every body's material (mass, density); `body.setMaterial` one body's. Materials: `generic`, `steel`, `stainless-steel`, `aluminum-6061`, `cast-aluminum`, `cast-iron`, `brass`, `bronze`, `copper`, `titanium`, `epoxy-granite`, `abs`, `pla`, `petg`, `nylon`, `acetal`, `oak`, `nbr` (`describe_commands` on `document.setMaterial` has the current list).
- Appearance is not geometry and never rebuilds: `document.setAppearance` for the whole part, `body.setAppearance` for a body, `body.setFaceAppearance` for faces by name; the finest one set wins, and without any each body shows its material's default. Set a material for mass and an appearance for looks.

## Pictures

`get_view_image` returns a picture of the open document when the user has turned on Send viewport images to AI; otherwise it says so, and you tell the user where to turn it on if a picture would help. Use it to compare the model with a photo or a sketch the user describes, never instead of measuring.

## Imported solids

`core.import` steps are made by people (you cannot upload files): imported bodies have no history, their faces are named `i(<step>:<surface>:...)` from their geometry and work like any other reference (sketch on them, cut, fillet, shell). Never change an Import step's file or solids; `IMPORT_FILE_MISSING`, `IMPORT_UNREADABLE`, `IMPORT_NOT_SOLID` and `IMPORT_PARTIAL` are for the user to fix by choosing the file again.
