# Device geometry

The mechanisms in a machine you carry: a hinge, a book fold whose display keeps its length, a kickstand that has to close, rotary detents that wrap, a band that keeps its length, and a screen on a plane at any attitude.

> For the complete index, see [llms.txt](https://robocn.dev/llms.txt). A Markdown version of any page is available by appending `.md` to its URL or by sending an `Accept: text/markdown` header.

## Install

```bash
bunx --bun shadcn@latest add https://robocn.dev/r/device-geometry.json
```

Registry item: `device-geometry` · [`https://robocn.dev/r/device-geometry.json`](https://robocn.dev/r/device-geometry.json)

## Notes

- Pure functions over plain objects. No React, no dependencies, and no dynamics — no friction in the hinge, no detent force on the crown, no crease memory in the folding display, no material in the band, and no contact between the stand's foot and the desk beyond the requirement that it be there.
- `camera.plane` covers artwork in the horizontal plane and `camera.wall` covers a vertical one. `panelTransform` is for everything in between — a lid, a propped slate, a turned handset — which is where the screens in this family actually live.
- Panel axes follow what a reader of the panel sees rather than the world: a screen facing the front camera runs its own left-to-right from +x to −x, because from nose-on the machine's starboard side is on your left.

## Usage

```tsx
import { hingePose, foldPose, standPose, detent, bandLinks, panelTransform } from "@/lib/robocn/device"

const lid = hingePose(105, 84, 78)          // lid keeps its length; facing says what you see
const book = foldPose(60, 60, 3)            // 2 * run + arc is the sheet, at every angle
const stand = standPose(0.7, 78, 46, 44)    // foot solved onto the desk, or folded
const dial = detent(450, 8, 45)             // -> { index: 2, offset, turns }
const band = bandLinks(7, 6.4, 0.8)         // constant pitch, curvature varies
const panel = panelTransform(camera, corner, along, down, 104, 78)
```

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `hingePose` | `(angle, base, lid, options?) => HingePose` | — | One revolute joint in side elevation. The lid is `lid` long from the pivot in every pose, `facing` says how much of the screen is toward the front, and `overCentre` says when it has passed vertical. |
| `foldPose` | `(angle, leaf, radius, options?) => FoldPose` | — | A book fold: the bend spends `radius × (180 − angle)` of display, the straight run gives it up so the sheet keeps its length, and both leaf faces stay tangent to the bend circle so the leaves roll rather than pivot. Returns `pinched` for a bend too big for the leaves. |
| `standPose` | `(recline, slate, leg, mount, options?) => StandPose` | — | The kickstand triangle: given the tilt, the drop from the hinge to the desk decides the horizontal run. Returns `folded` when the leg cannot reach, instead of stretching it. |
| `detent` | `(rotation, steps, degreesPerStep) => DetentPose` | — | A rotary input divided into steps, wrapping in both directions. The click wheel and the digital crown are the same mechanism at different scales. |
| `wheelSegment` | `(degrees) => "menu" | "next" | "play" | "previous" | null` | — | Which quarter of a ring a thumb at this angle is on. Null for a non-finite angle. |
| `bandLinks` | `(count, pitch, closure, options?) => BandLink[]` | — | A link band as a constant-pitch chain — count and pitch fixed, curvature varying — so opening it cannot make it longer. |
| `listWindow` | `(index, rows, visible) => number[]` | — | The rows a fixed-height list shows with `index` selected, sliding to keep it near the middle and stopping at both ends. |
| `panelTransform` | `(camera, corner, along, down, width, height) => PanelProjection` | — | A flat panel at any attitude, as one affine transform for its artwork plus a `facing` that says whether you are looking at its front, its back, or its edge. |
| `panelPath` | `(camera, corner, along, down) => string` | — | The same panel's outline, projected. |

## Source

- `src/lib/robocn/device.ts`
