# Hull geometry

An equal-area tiling of a sphere into armour plates whose areas sum to exactly one, a fracture front and the straight-line travel behind it, a shock ring as a real circle, and a paraboloid dish.

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

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

## Notes

- Pure functions over plain numbers and `{x, y, z}`. No React, no camera, no dependency but `clamp`.
- Courses are cut by equal area rather than by equal angle, which is the reason the sum is exact rather than nearly right: the area of a zone depends only on its height, so stepping `sin(latitude)` uniformly gives every course exactly its share.
- The travel never comes back in, whatever the `focus` blend, because both candidate directions — straight out, and away from the rupture — have a non-negative component along the plate's own normal.
- No structure, no mass, no energy and no collision. Pieces pass through each other's paths because nothing is stopping them, and `progress` runs backwards as happily as forwards.

## Usage

```tsx
import { hullPlates, burst, dish, dishNormal } from "@/lib/robocn/hull"

const plates = hullPlates(9, { perCourse: 12 })
plates.reduce((sum, plate) => sum + plate.area, 0)   // exactly 1: no gaps
burst(plates[7], 0.4, { origin: { x: 0, y: 0, z: -1 }, spread: 1.6 })
```

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `hullPlates(courses, options?)` | `HullPlate[]` | — | The tiling. Courses are cut by equal area and divided into equal longitudes, so the plate areas sum to exactly one sphere at every course and plate count. Plates per course track the cosine of the latitude, so a polar plate is not a sliver. |
| `plateOutline(plate, steps?)` | `{ latitude, longitude }[]` | — | That plate's boundary: along the south parallel, up the east meridian, back along the north, down the west. A parallel is a curve on the body, so each edge is stepped rather than chorded. |
| `plateNormal(plate)` | `Vec3` | — | The unit direction of the plate's centre — where it sits on the intact hull. |
| `burst(plate, progress, options?)` | `PlateBurst` | — | The breakup. A fracture front sweeps out from `origin`, so a plate's `release` is 0 until the front reaches it; after that it travels in a straight line. At progress 0 every plate is back at `plateNormal` exactly, and the distance from the centre never decreases. |
| `shockRing(centre, axis, radius, steps?)` | `Vec3[]` | — | A real circle of that radius in the plane through `centre` square to `axis`. Projected, it is the ellipse — nothing has to draw one. |
| `dish(radius, depth)` | `DishSurface` | — | A paraboloid from its rim and its depth, carrying the focal length `r²/(4d)` measured from the vertex. |
| `dishProfile / dishNormal / dishFocalPoint` | `Vec2` | — | A point on the bowl, its outward normal there, and where the focus sits — all in the bowl's own axial plane. Reflecting an axial ray about that normal at any point on the surface sends it through the focus, which is what lets an emitter array be solved rather than aimed. |
| `direction(latitude, longitude)` | `Vec3` | — | The unit direction at a latitude and longitude, pole on `y` — the same convention `celestial-geometry` uses, so plate geometry hands straight to `surfacePoint`. |

## Source

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