# StrokeModel

Import it from `@grafloria/engine`.

Also has every member of `DiagramEntity`, listed on its own entry.

A freehand ink stroke: an ordered point list, a style, and an identity.

A first-class `DiagramEntity`, which is not a formality — it is what makes every
other gate in this wave close for free:
  • `trackChange()` → `markDirty()` → the GLOBAL MUTATION EPOCH, which is the thing
    both frame gates read (`svg-renderer.ts:795`, `create-diagram.ts:369`). A stroke
    that were a plain object would mutate the picture without moving the epoch, and
    both gates would skip the frame: you would draw and see nothing.
  • `on('change')` → `OpCapture` picks it up through the same funnel as everything
    else. No parallel bookkeeping to drift out of step.
  • `serialize()`/`dispose()`/`version` → the document contracts.

```ts
class StrokeModel extends DiagramEntity
```

**Methods**

- `constructor( points: readonly StrokePoint[] = [], style: StrokeStyle = DEFAULT_STROKE_STYLE, options: { id?: string; uuid?: string; label?: string } = {} )`
- `getPoints(): readonly StrokePoint[]`
- `setPoints(points: readonly StrokePoint[]): void` — Replace the geometry.
- `get pointCount(): number`
- `getBounds(): Rectangle` — Axis-aligned bounds, INFLATED by the stroke's own half-width (ink has girth).
- `hitTest(x: number, y: number, tolerance = 0): boolean` — Is `(x, y)` on the ink, within `tolerance` world units of it?
- `intersectsSegment(a: Point, b: Point, tolerance = 0): boolean` — Did a pointer travelling `a`→`b` sweep across this ink? THE ERASER'S QUESTION. Segment-vs-segment, not point-vs-segment — see {@link segmentDistance}.
- `getStyle(): Readonly<StrokeStyle>`
- `setStyle(style: Partial<StrokeStyle>): void`
- `replaceStyle(style: Partial<StrokeStyle>): void` — REPLACE the whole style object — the write `setStyle` cannot express, and the collab reducer's write path.
- `override getLabel(): string | undefined` — The accessible name, when the author gave one. See the a11y note on the ink layer. Overrides the DiagramEntity canon (metadata.label): a stroke's label lives in its own serialized `label` property, not the metadata bag.
- `override setLabel(label: string | undefined): void` — CANONICAL label write. Writes `metadata.label` (tracked → dirty → repaint) and mirrors into the legacy `data['label']` slot when the entity has a data bag, so any reader still on the old field sees the same value. The mirror is a shadow: metadata is authoritative on every read path.
- `serialize(): SerializedStroke` — Serialize entity to JSON
- `static fromJSON(data: SerializedStroke): StrokeModel` (static)
- `static fromRawPoints( raw: readonly StrokePoint[], style: StrokeStyle = DEFAULT_STROKE_STYLE, options: { id?: string; label?: string; epsilon?: number } = {} ): StrokeModel` (static) — Build a stroke from a RAW POINTER TRACE. This is the only constructor the draw tool uses, and the simplification is not optional decoration.
