# Linkage geometry

Closed-loop kinematics: a four-bar, a slider-crank and a block and tackle, plus the helpers that lift an elevation drawing into world space. No React, no dependencies, and no dynamics.

> 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/linkage-geometry.json
```

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

## Notes

- Pure geometry. No mass, torque, inertia, friction, rope stretch or sheave efficiency is modelled anywhere in the file.
- The elevation helpers that turn a drawing into world-space solids — `elevationDraft`, `elevationSolid`, `elevationDisc`, `fitTransform` — live in `robot-style`, since every machine projects the same way.

## Usage

```tsx
import { solveFourBar, solveSliderCrank, tacklePosition } from "@/lib/robocn/linkage"

const pose = solveFourBar(48, { ground: -56, rise: 76, crank: 14, coupler: 78, rocker: 56 }, { branch: "down" })
const piston = solveSliderCrank(120, { crank: 15, rod: 62 })
const block = tacklePosition(3, { lines: 8, drumRadius: 11, topHeight: 204, floorHeight: 72 })
```

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `solveFourBar` | `(crankAngle: number, geometry: FourBarGeometry, options?) => FourBarPose` | — | Closes the loop as a circle intersection, so both link lengths are exact. `branch` picks the assembly; `assembled` is false where the loop cannot close and the pose is stretched rather than NaN. |
| `rigidPoint` | `(origin: Vec2, angle: number, along: number, offset?: number) => Vec2` | — | A point rigidly attached to a link: along its direction, then to its left. |
| `solveSliderCrank` | `(crankAngle: number, geometry: SliderCrankGeometry) => SliderCrankPose` | — | The degenerate four-bar. Reports the wrist pin, the rod angle, and the analytic stroke between the two dead centres. |
| `tacklePosition` | `(drumTurns: number, geometry: TackleGeometry) => TacklePosition` | — | Shares the drum's payout between the strung lines: block travel is payout ÷ lines and the advantage is the line count. |
| `tackleReeving` | `(crown: Vec2, block: Vec2, lines: number, spacing: number) => Vec2[]` | — | The rope itself, zig-zagging between the crown and block sheaves, with exactly `lines` falls. |

## Source

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