# Produce geometry

Solids of revolution with a real profile: the surface, a golden-angle lattice spaced by equal area, half shells that reassemble, a hinge about any line, and blades that keep their length.

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

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

## Notes

- Pure functions over plain objects. No React, no camera, no dependencies — the components own the projection and the paint.
- No crop, growth, ripeness or material model of any kind. These are shapes and the mechanisms that move them.
- The normals come from the unlobed surface of revolution: the furrows are shallow enough that a stud still stands off its own skin, and saying so is cheaper than a normal nobody can see the difference in.

## Usage

```tsx
import { revolveProfile, goldenLattice, halfShell, hingeRotate, bladeRing } from "@/lib/robocn/produce"

const profile = (t: number) => ({ height: 96 * t, radius: 30 * Math.sin(Math.PI * t) })
const skin = revolveProfile(profile, { rings: 12, meridians: 24 })
const studs = goldenLattice(profile, 26, { from: 0.08, to: 0.9 })
const half = halfShell(profile, "right", { rings: 12, meridians: 16 })
const open = hingeRotate(half, { origin: { x: 0, y: 8, z: 0 }, axis: { x: 0, y: 0, z: 1 } }, -30)
const calyx = bladeRing(6, { radius: 28, height: 86, length: 19, width: 19, pitch: -40 })
```

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `revolveProfile` | `(profile, options?) => Vec3[]` | — | The surface as points, rings by meridians. Every sample sits at the profile's own radius and height, lobed or not. |
| `profilePoint` | `(profile, t, azimuth?, options?) => Vec3` | — | One point on that surface. `lobes` and `lobeDepth` modulate the radius in azimuth, so a furrowed fruit is furrowed rather than striped. |
| `latitudeRing` | `(profile, t, options?, steps?) => Vec3[]` | — | The closed ring at one station — a belt, a ripening front, a seat for a blade ring. |
| `meridianLine` | `(profile, azimuth, options?, steps?) => Vec3[]` | — | The line up one azimuth — a furrow, or a seam. |
| `surfaceNormal` | `(profile, t, azimuth?) => Vec3` | — | The outward normal in the meridian plane, turned to the azimuth: the direction a stud extends along, and the vector that says whether it faces the camera. |
| `goldenLattice` | `(profile, count, options?) => ProduceLatticeSite[]` | — | Sites by the golden angle, spaced by equal lateral surface area — the cumulative area is integrated and stepped through evenly, so the sites do not crowd where the profile is steep. |
| `halfShell` | `(profile, side?, options?) => Vec3[]` | — | Half the surface. `left` is `right` mirrored in the x = 0 plane point for point, so the two halves reassemble into exactly the surface `revolveProfile` draws. |
| `hingeRotate` | `(points, hinge, degrees) => Vec3[]` | — | Points turned about an arbitrary line — a vertical post behind a machine, a rod along the floor under it, a knuckle in a stem. Distance to the line is preserved and zero degrees is the identity. |
| `bladeRing` | `(count, options) => ProduceBlade[]` | — | Blades hinged on a ring, evenly spaced, with the blade's length exact at every pitch and its outline as four corners in space. |
| `lateralArea` | `(profile, from?, to?, steps?) => number` | — | Surface area of a band, which is what the lattice is spaced by. |
| `widestSection` | `(profile, steps?) => ProduceSection & { t }` | — | The belt: the widest station, for anything that has to clear it or decide what a camera above can see. |

## Source

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