# Gym geometry

The five mechanisms that stand between a selected weight and a felt load: rope reeving, a variable-radius cam, an inclined rail, a coupler curve, and velocity-squared air drag.

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

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

## Notes

- Pure functions over plain objects: no React, no three.js, no dependencies beyond robot-kinematics and linkage-geometry.
- Unit-agnostic. Lengths are world units and weights are whatever you count in, so a plate is a plate.
- Frictionless throughout: no rope stretch, no sheave efficiency, no rail or roller friction, no bearing loss. The advantages and loads are the ideal ones.
- Nothing here knows about a person, a muscle or a rep. The rowing stroke's handle and seat schedules are chosen ramps; everything downstream of them — speeds, forces, drag factor, counter-travel — is integrated from those ramps.
- Design note: docs/gym-machines.md.

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `reeveStack(draw, geometry?)` | `(draw: number, geometry?: StackGeometry) => StackLift` | — | Where a selectorised stack sits after the handle has been drawn. The rope is inextensible, so the stack rises draw / lines and the handle holds weight / lines: the reeving is the advantage, and nobody sets it. |
| `camRadius(angle, geometry?)` | `(angle: number, geometry?: CamGeometry) => number` | — | The cam's working radius at one lever angle — which is also the moment arm there. |
| `solveCam(angle, geometry?)` | `(angle: number, geometry?: CamGeometry) => CamPose` | — | Moment arm, leverage and cable payout. Payout is the integral of r dθ, so the stack does not rise linearly with the lever. |
| `camProfile(geometry?, steps?)` | `(geometry?: CamGeometry, steps?: number) => Vec2[]` | — | The cam's outline in polar about its pivot, at the radii solveCam works from — so the drawn cam is the resistance curve. |
| `solveSled(stroke, geometry?)` | `(stroke: number, geometry?: SledGeometry) => SledPose` | — | A carriage on inclined rails. Only the component along the rails resists, so the load is weight · sin(angle) and the rail angle is the resistance. |
| `solveTrainer(crankAngle, geometry?)` | `(crankAngle: number, geometry?: TrainerGeometry) => TrainerPose` | — | Crank, coupler and rocker solved as a closed loop, with the footpad rigid on the coupler and the grip carried on up the rocker. |
| `trainerFootPath(geometry?, steps?)` | `(geometry?: TrainerGeometry, steps?: number) => TrainerPath` | — | A whole turn of the crank as the closed path the footpad draws, with the stride and rise that path happens to have. |
| `solveErgCycle(geometry?, steps?)` | `(geometry?: ErgGeometry, steps?: number) => ErgCycle` | — | One steady-state stroke of an air flywheel on a one-way clutch: drag factor, speeds, handle force, and the window where handle and seat travel opposite ways. |
| `ergAt(cycle, phase)` | `(cycle: ErgCycle, phase: number) => ErgSample` | — | One sample of a solved cycle, interpolated, with the phase wrapped — so a component can memoise the cycle and stay a pure function of the clock. |

## Source

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