# Classes

Import these from `@grafloria/renderer`.

## Classes

### `EdgeOptimizer`

```ts
class EdgeOptimizer
```

**Methods**

- `constructor(options: EdgeOptimizerOptions = {})`
- `get stats(): Readonly<OptimizerStats>`
- `update(frame: OptimizerFrame): void` — Run the pass for a frame. Cheap when little changed: a frame whose links and
nodes all carry the same signatures as last time performs zero segment tests
and zero label searches.
- `getJumps(linkId: string): Intersection[]` — The crossings on this link, for the jump-point path builder. Empty when the
link draws no jumps.
- `getLabelOffset(linkId: string, labelId: string, fallback: Point): Point` — The offset this label should actually be drawn at. For a label that did not
opt into `autoOffset` this is exactly the offset the author set.
- `reset(): void` — Drop all state (renderer disposal, or a wholesale diagram swap).

### `JumpPointDetector`

JumpPointDetector detects line-line intersections for jump point rendering.

Features:
- Line segment intersection detection
- Angle calculation between intersecting lines
- Multiple detection modes (all, perpendicular, threshold)
- Performance optimized for many links

Algorithm:
Uses parametric line intersection algorithm with bounds checking.

```ts
class JumpPointDetector
```

**Methods**

- `findIntersection(line1: LineSegment, line2: LineSegment): Intersection | null` — Find intersection between two line segments
- `detectIntersections( targetLink: LinkWithPoints, otherLinks: LinkWithPoints[], mode: DetectionMode = 'all', threshold: number = 45 ): Intersection[]` — Detect all intersections for a link with other links

### `JumpPointRenderer`

JumpPointRenderer modifies link paths to show jump points at intersections.

Supports three visual styles:
- arc: Small arc over intersection
- gap: Break in line
- bridge: Bridge shape over intersection

Algorithm:
1. Parse path to extract points
2. Sort intersections by position
3. Split path at intersections
4. Insert jump point geometry
5. Reconstruct path

```ts
class JumpPointRenderer
```

**Methods**

- `renderWithJumpPoints( pathData: string, intersections: Intersection[], config: JumpPointConfig, originalProps?: Record<string, any> ): VNode` — Render path with jump points at intersections

### `LabelRenderer`

LabelRenderer generates SVG (or HTML) VNodes for link labels.

Features:
- Position labels at any point along path (0-1), or in one of three slots
- Auto-rotation with path or fixed angle
- Text wrapping with maxWidth
- Multiple labels per link
- Rich styling support
- HTML content and author templates

Architecture:
Uses LinkModel utilities (getPointAtPosition, getAngleAt) for positioning. Returns VNode tree compatible with framework-agnostic rendering.

```ts
class LabelRenderer
```

**Methods**

- `renderLabel(label: LinkLabel, link: LinkModel, context: LabelRenderContext = {}): VNode | null` — Render a label on a link
- `labelBox(label: LinkLabel): { width: number; height: number }` — Estimated on-screen box of a label, in LOCAL units (before the path anchor
and offset are applied). The edge optimizer needs a box to test collisions
against; HTML/template labels declare their own, and text labels are
measured with the same estimator the background rect already uses.

### `RouteMemo`

```ts
class RouteMemo
```

**Methods**

- `get stats(): Readonly<RouteMemoStats>`
- `get size(): number`
- `beginFrame(rects: Map<string, Rect>, obstacleEpoch: string): Rect[]` — Start a frame. Diffs this frame's node rectangles against last frame's and
returns the world regions that changed — each moved node contributes BOTH
where it was and where it now is, because a link routed around its old
position is just as stale as one routed through its new one.

`obstacleEpoch` covers obstacle-set changes that are NOT node rects — a
group collapsing hides its members and adds a block, and no node moved. A
change there drops the whole cache, which is the honest thing to do: it is
rare, and reasoning about which links a collapse touched is how you ship a
stale route.
- `lookup(linkId: string, key: string): RoutedPath | undefined` — The route for this link if its inputs are unchanged since we cached it.
- `store(linkId: string, key: string, routed: RoutedPath): void`
- `drop(linkId: string): void` — A route computed but NOT cacheable (e.g. no route found) must not keep a stale entry.
- `invalidate(linkIds: Iterable<string>): void`
- `clear(): void`

### `RouteSolverBridge`

```ts
class RouteSolverBridge
```

**Methods**

- `constructor(options: RouteSolverBridgeOptions = {})`
- `get stats(): Readonly<RouteSolverStats>`
- `hasRoutesFor(version: number): boolean` — True once the solver has an answer for THIS world — i.e. one safe to paint.
- `routeFor(linkId: string, version: number): RoutedPath | undefined`
- `submit(version: number, edges: SolverEdge[], obstacles: Obstacle[]): void` — Ask for this world to be solved. Idempotent per version: submitting the same
world twice does nothing, so calling this every frame is free.

If a solve is already running for an older world, the new one is QUEUED, not
raced — and if a third arrives first, it replaces the queued one. At most one
solve in flight, and the newest world always wins.
- `dispose(): void`
