@mark1russell7/highways 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["SIDES","turn","dedupe","now","now"],"sources":["../src/geom.ts","../src/grid.ts","../src/model.ts","../src/fixtures.ts","../src/cases.ts","../src/plugs.ts","../src/curves.ts","../src/curves/model.ts","../src/bench/properties.ts","../src/curves/sample.ts","../src/curves/space.ts","../src/curves/arc/index.ts","../src/curves/rounded/index.ts","../src/curves/spline/index.ts","../src/curves/straight/index.ts","../src/curves/index.ts","../src/visibility.ts","../src/ways.ts","../src/segments.ts","../src/sections.ts","../src/routers/corners.ts","../src/routers/plugs.ts","../src/bench/links.ts","../src/levels.ts","../src/routers/sections.ts","../src/routers/shared.ts","../src/routers/straight.ts","../src/routers/trunks.ts","../src/routers/index.ts","../src/room/index.ts","../src/bench/quality.ts","../src/bench/run.ts","../src/bench/curves.ts","../src/bench/room.ts"],"sourcesContent":["/** A point in the plane. */\nexport interface Point {\n readonly x: number;\n readonly y: number;\n}\n\n/** A box with its top-left corner at (`x`, `y`). */\nexport interface Box {\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n}\n\n/** This function gives the distance between two points. */\nexport function dist(a: Point, b: Point): number {\n const dx = a.x - b.x;\n const dy = a.y - b.y;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/** This function gives the center of a box. */\nexport function center(b: Box): Point {\n return { x: b.x + b.w / 2, y: b.y + b.h / 2 };\n}\n\n/** This function gives a box that is larger by `m` on each side. A negative `m` makes the box smaller. */\nexport function inflate(b: Box, m: number): Box {\n return { x: b.x - m, y: b.y - m, w: Math.max(0, b.w + 2 * m), h: Math.max(0, b.h + 2 * m) };\n}\n\n/** This function gives the sum of the lengths of the segments of a polyline. */\nexport function polylineLength(p: readonly Point[]): number {\n let s = 0;\n for (let i = 1; i < p.length; i++) s += dist(p[i - 1]!, p[i]!);\n return s;\n}\n\nconst orient = (a: Point, b: Point, c: Point): number => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n\n/**\n * This function tells if the segments `ab` and `cd` cross at one point inside both of them.\n * Segments that only touch at an end, or that are collinear, do not cross.\n */\nexport function segmentsCross(a: Point, b: Point, c: Point, d: Point): boolean {\n const d1 = orient(c, d, a);\n const d2 = orient(c, d, b);\n const d3 = orient(a, b, c);\n const d4 = orient(a, b, d);\n return d1 * d2 < 0 && d3 * d4 < 0;\n}\n\n/**\n * This function tells if the segment `ab` goes through the inside of the box.\n * The function clips the segment to the box (Liang-Barsky) and asks for a part longer than `eps`.\n */\nexport function segmentHitsBox(a: Point, b: Point, box: Box, eps = 1e-6): boolean {\n return segmentHitsRect(a, b, box.x, box.y, box.x + box.w, box.y + box.h, eps);\n}\n\n/** This function tells if the segment `ab` goes through the inside of the box from (`x0`, `y0`) to (`x1`, `y1`). */\nexport function segmentHitsRect(a: Point, b: Point, x0: number, y0: number, x1: number, y1: number, eps = 1e-6): boolean {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n let t0 = 0;\n let t1 = 1;\n if (dx === 0) {\n if (a.x <= x0 || a.x >= x1) return false;\n } else {\n const ta = (x0 - a.x) / dx;\n const tb = (x1 - a.x) / dx;\n t0 = Math.max(t0, Math.min(ta, tb));\n t1 = Math.min(t1, Math.max(ta, tb));\n if (t0 > t1) return false;\n }\n if (dy === 0) {\n if (a.y <= y0 || a.y >= y1) return false;\n } else {\n const ta = (y0 - a.y) / dy;\n const tb = (y1 - a.y) / dy;\n t0 = Math.max(t0, Math.min(ta, tb));\n t1 = Math.min(t1, Math.max(ta, tb));\n if (t0 > t1) return false;\n }\n return (t1 - t0) * Math.sqrt(dx * dx + dy * dy) > eps;\n}\n\n/** This function gives the distance from a point to a box. The distance is 0 when the point is in the box. */\nexport function pointBoxDistance(p: Point, b: Box): number {\n const qx = Math.max(b.x, Math.min(b.x + b.w, p.x));\n const qy = Math.max(b.y, Math.min(b.y + b.h, p.y));\n return Math.hypot(p.x - qx, p.y - qy);\n}\n\n/** This function gives the distance from a point to the segment `ab`. */\nexport function pointSegmentDistance(p: Point, a: Point, b: Point): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const l2 = dx * dx + dy * dy;\n const t = l2 === 0 ? 0 : Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / l2));\n return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));\n}\n\n/** This function gives the distance from the segment `ab` to a box. The distance is 0 when they touch. */\nexport function segmentBoxDistance(a: Point, b: Point, box: Box): number {\n if (segmentHitsBox(a, b, box, 0) || pointBoxDistance(a, box) === 0 || pointBoxDistance(b, box) === 0) return 0;\n const corners: Point[] = [\n { x: box.x, y: box.y },\n { x: box.x + box.w, y: box.y },\n { x: box.x, y: box.y + box.h },\n { x: box.x + box.w, y: box.y + box.h },\n ];\n let d = Math.min(pointBoxDistance(a, box), pointBoxDistance(b, box));\n for (const c of corners) d = Math.min(d, pointSegmentDistance(c, a, b));\n return d;\n}\n\n/**\n * This function gives the turn at each inner vertex of a polyline, in radians, from -π to π.\n * A positive turn is counterclockwise in a frame with the y axis up. The function skips segments shorter than `eps`.\n */\nexport function turns(p: readonly Point[], eps = 1e-9): number[] {\n const q: Point[] = [];\n for (const v of p) if (q.length === 0 || dist(q[q.length - 1]!, v) > eps) q.push(v);\n const out: number[] = [];\n for (let i = 1; i + 1 < q.length; i++) {\n const a = q[i - 1]!;\n const b = q[i]!;\n const c = q[i + 1]!;\n const cr = (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x);\n const dt = (b.x - a.x) * (c.x - b.x) + (b.y - a.y) * (c.y - b.y);\n out.push(Math.atan2(cr, dt));\n }\n return out;\n}\n\n/** This function counts the vertices of a polyline where the direction changes by more than `minTurn` radians. */\nexport function bendCount(p: readonly Point[], minTurn = 0.05): number {\n return turns(p).filter((t) => Math.abs(t) > minTurn).length;\n}\n\n/**\n * This function counts the inflections of a polyline: the changes of the sign of the turn.\n * A turn smaller than `minTurn` radians does not count. Thus a straight part between two turns keeps their signs.\n */\nexport function inflectionCount(p: readonly Point[], minTurn = 1e-3): number {\n let n = 0;\n let last = 0;\n for (const t of turns(p)) {\n if (Math.abs(t) <= minTurn) continue;\n const s = Math.sign(t);\n if (last !== 0 && s !== last) n++;\n last = s;\n }\n return n;\n}\n\n/**\n * This function gives the discrete Fréchet distance between two polylines (Eiter and Mannila, 1994).\n * The cost is O(|p|·|q|) in time and O(|q|) in memory.\n */\nexport function frechet(p: readonly Point[], q: readonly Point[]): number {\n if (p.length === 0 || q.length === 0) return p.length === q.length ? 0 : Infinity;\n let prev = new Float64Array(q.length);\n let cur = new Float64Array(q.length);\n for (let i = 0; i < p.length; i++) {\n for (let j = 0; j < q.length; j++) {\n const d = dist(p[i]!, q[j]!);\n if (i === 0 && j === 0) cur[j] = d;\n else if (i === 0) cur[j] = Math.max(cur[j - 1]!, d);\n else if (j === 0) cur[j] = Math.max(prev[j]!, d);\n else cur[j] = Math.max(Math.min(prev[j]!, prev[j - 1]!, cur[j - 1]!), d);\n }\n [prev, cur] = [cur, prev];\n }\n return prev[q.length - 1]!;\n}\n","import type { Box, Point } from \"./geom.ts\";\n\n/**\n * A uniform grid of buckets over the plane. A box item goes into each bucket that the box touches.\n * A segment item goes only into the buckets along the segment, so a long diagonal segment stays cheap.\n * A query gives each item in the buckets that it touches, one time each.\n */\nexport class Grid<T> {\n readonly #cell: number;\n readonly #buckets = new Map<number, number[]>();\n readonly #items: T[] = [];\n readonly #ids = new Map<T, number>();\n // The stamp of the last query that gave each item, by the index of the item.\n #seen = new Int32Array(16);\n #stamp = 0;\n\n /** This constructor makes an empty grid with square buckets of side `cell`. */\n constructor(cell: number) {\n this.#cell = Math.max(1e-9, cell);\n }\n\n #key(i: number, j: number): number {\n // The key packs the two bucket indices into one number. Each index stays within ±2^20.\n return (i + 1_048_576) * 2_097_152 + (j + 1_048_576);\n }\n\n #id(item: T): number {\n let id = this.#ids.get(item);\n if (id === undefined) {\n id = this.#items.length;\n this.#ids.set(item, id);\n this.#items.push(item);\n if (id >= this.#seen.length) {\n const seen = new Int32Array(this.#seen.length * 2);\n seen.set(this.#seen);\n this.#seen = seen;\n }\n }\n return id;\n }\n\n #put(id: number, x0: number, y0: number, x1: number, y1: number): void {\n const c = this.#cell;\n const i1 = Math.floor(x1 / c);\n const j1 = Math.floor(y1 / c);\n for (let i = Math.floor(x0 / c); i <= i1; i++) {\n for (let j = Math.floor(y0 / c); j <= j1; j++) {\n const key = this.#key(i, j);\n const list = this.#buckets.get(key);\n if (list === undefined) this.#buckets.set(key, [id]);\n else if (list[list.length - 1] !== id) list.push(id);\n }\n }\n }\n\n #take(stamp: number, x0: number, y0: number, x1: number, y1: number, visit: (item: T) => void): void {\n const c = this.#cell;\n const i1 = Math.floor(x1 / c);\n const j1 = Math.floor(y1 / c);\n const seen = this.#seen;\n for (let i = Math.floor(x0 / c); i <= i1; i++) {\n for (let j = Math.floor(y0 / c); j <= j1; j++) {\n const list = this.#buckets.get(this.#key(i, j));\n if (list === undefined) continue;\n for (const id of list) {\n if (seen[id] === stamp) continue;\n seen[id] = stamp;\n visit(this.#items[id]!);\n }\n }\n }\n }\n\n /**\n * This method gives each item in the buckets along the segment `ab`, widened by `margin`, to `visit`, one time each.\n * The buckets are those of `#segment`, in the same order, so the items come in the same order.\n * A bucket in the range of the step before has no new item, so the walk skips it.\n * The walk stops when `visit` gives true, and then the method gives true.\n */\n #walk(a: Point, b: Point, margin: number, visit: (item: T) => boolean | void): boolean {\n const stamp = ++this.#stamp;\n const c = this.#cell;\n const items = this.#items;\n const n = Math.max(1, Math.ceil(Math.hypot(b.x - a.x, b.y - a.y) / (c / 2)));\n let px = a.x;\n let py = a.y;\n // The bucket range of the step before. The first step has none.\n let pi0 = 1;\n let pi1 = 0;\n let pj0 = 1;\n let pj1 = 0;\n for (let k = 1; k <= n; k++) {\n const qx = k === n ? b.x : a.x + ((b.x - a.x) * k) / n;\n const qy = k === n ? b.y : a.y + ((b.y - a.y) * k) / n;\n const i0 = Math.floor((Math.min(px, qx) - margin) / c);\n const j0 = Math.floor((Math.min(py, qy) - margin) / c);\n const i1 = Math.floor((Math.max(px, qx) + margin) / c);\n const j1 = Math.floor((Math.max(py, qy) + margin) / c);\n // A visit can add an item and so replace the array of stamps. Each step reads it again, as `#take` does.\n const seen = this.#seen;\n for (let i = i0; i <= i1; i++) {\n const before = i >= pi0 && i <= pi1;\n for (let j = j0; j <= j1; j++) {\n if (before && j >= pj0 && j <= pj1) continue;\n const list = this.#buckets.get(this.#key(i, j));\n if (list === undefined) continue;\n for (const id of list) {\n if (seen[id] === stamp) continue;\n seen[id] = stamp;\n if (visit(items[id]!) === true) return true;\n }\n }\n }\n pi0 = i0;\n pi1 = i1;\n pj0 = j0;\n pj1 = j1;\n px = qx;\n py = qy;\n }\n return false;\n }\n\n // The buckets along a segment, widened by `margin`: the boxes of steps of at most half a bucket.\n #segment(a: Point, b: Point, margin: number, each: (x0: number, y0: number, x1: number, y1: number) => void): void {\n const n = Math.max(1, Math.ceil(Math.hypot(b.x - a.x, b.y - a.y) / (this.#cell / 2)));\n let px = a.x;\n let py = a.y;\n for (let k = 1; k <= n; k++) {\n const qx = k === n ? b.x : a.x + ((b.x - a.x) * k) / n;\n const qy = k === n ? b.y : a.y + ((b.y - a.y) * k) / n;\n each(Math.min(px, qx) - margin, Math.min(py, qy) - margin, Math.max(px, qx) + margin, Math.max(py, qy) + margin);\n px = qx;\n py = qy;\n }\n }\n\n /** This method adds an item with its bounding box. */\n add(item: T, b: Box): void {\n this.#put(this.#id(item), b.x, b.y, b.x + b.w, b.y + b.h);\n }\n\n /** This method adds the segment `ab` as an item. */\n addSegment(item: T, a: Point, b: Point): void {\n const id = this.#id(item);\n this.#segment(a, b, 0, (x0, y0, x1, y1) => this.#put(id, x0, y0, x1, y1));\n }\n\n /** This method gives each item whose buckets touch the box to `visit`, one time each. */\n query(b: Box, visit: (item: T) => void): void {\n this.#take(++this.#stamp, b.x, b.y, b.x + b.w, b.y + b.h, visit);\n }\n\n /** This method gives each item whose buckets come within `margin` of the segment `ab` to `visit`, one time each. */\n querySegment(a: Point, b: Point, margin: number, visit: (item: T) => void): void {\n this.#walk(a, b, margin, (item) => {\n visit(item);\n });\n }\n\n /**\n * This method tells if `test` gives true for an item whose buckets come within `margin` of the segment `ab`.\n * It gives the items in the order of `querySegment`, and it stops at the first item that passes the test.\n */\n someSegment(a: Point, b: Point, margin: number, test: (item: T) => boolean): boolean {\n return this.#walk(a, b, margin, test);\n }\n}\n\n/** This function gives the bounding box of the segment `ab`. */\nexport function segmentBounds(a: Point, b: Point): Box {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n return { x, y, w: Math.abs(a.x - b.x), h: Math.abs(a.y - b.y) };\n}\n","import type { Box, Point } from \"./geom.ts\";\n\n/** A side of a node box. */\nexport type Side = \"north\" | \"east\" | \"south\" | \"west\";\n\n/**\n * A plug of a node: a place where edges go into the node.\n * A plug with `at` is fixed. The router does not move it. A plug without `at` is free: the router places it.\n */\nexport interface Port {\n readonly id: string;\n /** This point is the fixed place of the plug, relative to the top-left corner of the node box. */\n readonly at?: Point;\n /** This side is where a free plug goes. Without it, the router picks the side. */\n readonly side?: Side;\n}\n\n/** A node: a box that routes must not go through. */\nexport interface Node {\n readonly id: string;\n readonly box: Box;\n readonly ports?: readonly Port[];\n}\n\n/** One end of an edge: a node, and optionally one plug of that node. */\nexport interface End {\n readonly node: string;\n readonly port?: string;\n}\n\n/** An edge between two nodes. `data` is free for the grouping rules. */\nexport interface Edge {\n readonly id: string;\n readonly source: End;\n readonly target: End;\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\n/** The input of a router. */\nexport interface Graph {\n readonly nodes: readonly Node[];\n readonly edges: readonly Edge[];\n}\n\n/** The route of one edge: a polyline from the source plug to the target plug, in absolute coordinates. */\nexport interface Route {\n readonly edge: string;\n readonly points: readonly Point[];\n}\n\n/**\n * One zoom level of a result. Each shown item is a node or a group of nodes.\n * Each link joins two shown items and carries the count of the edges that it stands for.\n */\nexport interface Level {\n readonly depth: number;\n readonly items: readonly LevelItem[];\n readonly links: readonly LevelLink[];\n}\n\n/** A shown item of a level: one node, or a group that stands for its nodes. */\nexport interface LevelItem {\n readonly id: string;\n readonly box: Box;\n readonly nodes: readonly string[];\n}\n\n/** A link of a level: the edges between two shown items, drawn as one path. */\nexport interface LevelLink {\n readonly source: string;\n readonly target: string;\n readonly count: number;\n readonly points: readonly Point[];\n}\n\n/** The output of a router. `levels` is present when the router makes zoom levels. */\nexport interface Result {\n readonly routes: readonly Route[];\n readonly levels?: readonly Level[];\n readonly bundles?: readonly Bundle[];\n /** The stretches of way that several routes share, if the router gives them. */\n readonly runs?: readonly SharedRun[];\n}\n\n/**\n * A bundle: edges from one node that share one plug and one trunk. Then the edges fan out to their targets.\n * A renderer draws a bundle as one fat edge with a count, or as one lane for each edge.\n */\nexport interface Bundle {\n readonly id: string;\n /** The key that the grouping rule gave each edge of the bundle. */\n readonly key: string;\n /** The node where the edges share their plug. */\n readonly node: string;\n /** The edges in lane order. Lane 0 turns most to the left of the trunk, in a frame with the y axis down. */\n readonly edges: readonly string[];\n /** The shared start of each route of the bundle, from the plug to the split point. */\n readonly trunk: readonly Point[];\n}\n\n/**\n * A stretch of way that several routes share, with the same points. Each route of `edges` has `points` in it,\n * in this order or in the reverse order. A renderer draws a run as one fat line, or as one lane for each edge.\n */\nexport interface SharedRun {\n readonly id: string;\n /** The key of the grouping rule of the edges. */\n readonly key: string;\n readonly points: readonly Point[];\n /** The edges in lane order. Lane 0 is on the left of the run, from its first point to its last. The y axis points down. */\n readonly edges: readonly string[];\n}\n\n/** A grouping rule gives each edge a key. The edges from one plug with one key make a bundle. An edge without a key stays alone. */\nexport type GroupRule = (edge: Edge) => string | undefined;\n\n/** A router: a strategy with a name. The same input must give the same result. */\nexport interface Router {\n readonly name: string;\n /** The benchmark skips a fixture with more nodes than this. Without it, the router takes each fixture. */\n readonly maxNodes?: number;\n route(graph: Graph): Result;\n}\n\n/** This function gives a map from the id of each node to the node. */\nexport function nodeIndex(g: Graph): Map<string, Node> {\n const m = new Map<string, Node>();\n for (const n of g.nodes) m.set(n.id, n);\n return m;\n}\n\n/** This function gives the absolute place of a fixed plug, or `undefined` for a free plug or no plug. */\nexport function fixedPortPoint(node: Node, end: End): Point | undefined {\n if (end.port === undefined) return undefined;\n const p = node.ports?.find((q) => q.id === end.port);\n if (p?.at === undefined) return undefined;\n return { x: node.box.x + p.at.x, y: node.box.y + p.at.y };\n}\n","import type { Box, Point } from \"./geom.ts\";\nimport { Grid } from \"./grid.ts\";\nimport type { Edge, Graph, Node, Port, Side } from \"./model.ts\";\n\n/** This function gives a seeded random source with values in [0, 1) (mulberry32). */\nexport function rng(seed: number): () => number {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * The ways a fixture puts its nodes and picks its edges. In `collections`, each cluster is one collection,\n * and some nodes link to many nodes of one other collection (a fan-out).\n */\nexport type FixtureKind = \"uniform\" | \"clustered\" | \"grid\" | \"hubs\" | \"collections\";\n\n/** The parameters of a generated graph. */\nexport interface FixtureSpec {\n readonly name: string;\n readonly kind: FixtureKind;\n readonly nodes: number;\n /** The number of edges is about `nodes × edgesPerNode`. */\n readonly edgesPerNode: number;\n readonly seed: number;\n /** This share of the edges, from 0 to 1, joins a node near the source. */\n readonly locality?: number;\n /** This share of the nodes, from 0 to 1, has one fixed plug that its outgoing edges use. */\n readonly fixedPorts?: number;\n}\n\n/** The fixtures of the benchmark, from 10 to 100 000 nodes. */\nexport const FIXTURES: readonly FixtureSpec[] = [\n { name: \"tiny-uniform\", kind: \"uniform\", nodes: 10, edgesPerNode: 1.5, seed: 1 },\n { name: \"small-clustered\", kind: \"clustered\", nodes: 100, edgesPerNode: 2, seed: 2, fixedPorts: 0.2 },\n { name: \"grid-400\", kind: \"grid\", nodes: 400, edgesPerNode: 2, seed: 3 },\n { name: \"mid-uniform\", kind: \"uniform\", nodes: 1000, edgesPerNode: 2, seed: 4 },\n { name: \"mid-clustered\", kind: \"clustered\", nodes: 1000, edgesPerNode: 3, seed: 5, fixedPorts: 0.2 },\n { name: \"mid-hubs\", kind: \"hubs\", nodes: 1000, edgesPerNode: 2, seed: 6 },\n { name: \"mid-fanout\", kind: \"collections\", nodes: 1000, edgesPerNode: 2, seed: 9 },\n { name: \"large-clustered\", kind: \"clustered\", nodes: 10_000, edgesPerNode: 3, seed: 7 },\n { name: \"huge-clustered\", kind: \"clustered\", nodes: 100_000, edgesPerNode: 2, seed: 8 },\n];\n\nconst COLLECTIONS = [\"users\", \"modes\", \"speeds\", \"scores\", \"teams\"] as const;\nconst SIDES: readonly Side[] = [\"north\", \"east\", \"south\", \"west\"];\nconst GAP = 12;\nconst SPACING = 90;\n\n/**\n * This function makes the graph of a fixture. The same spec always gives the same graph.\n * Node boxes do not overlap, and a gap of 12 units stays between them.\n */\nexport function makeFixture(spec: FixtureSpec): Graph {\n const R = rng(spec.seed * 2654435761 + spec.nodes);\n const gauss = (): number => Math.sqrt(-2 * Math.log(R() + 1e-12)) * Math.cos(2 * Math.PI * R());\n const side = Math.sqrt(spec.nodes) * SPACING;\n const grid = new Grid<Box>(SPACING);\n const nodes: Node[] = [];\n const clusterOf: number[] = [];\n const free = (b: Box): boolean => {\n let ok = true;\n const g: Box = { x: b.x - GAP, y: b.y - GAP, w: b.w + 2 * GAP, h: b.h + 2 * GAP };\n grid.query(g, (o) => {\n if (ok && o.x < g.x + g.w && g.x < o.x + o.w && o.y < g.y + g.h && g.y < o.y + o.h) ok = false;\n });\n return ok;\n };\n const centers: Point[] = Array.from({ length: Math.max(3, Math.round(Math.sqrt(spec.nodes) / 3)) }, () => ({\n x: side * (0.1 + 0.8 * R()),\n y: side * (0.1 + 0.8 * R()),\n }));\n const spread = side / (2.5 * Math.sqrt(centers.length));\n const cols = Math.ceil(Math.sqrt(spec.nodes));\n let tries = 0;\n while (nodes.length < spec.nodes && tries++ < spec.nodes * 200) {\n const w = 30 + Math.floor(R() * 30);\n const h = 18 + Math.floor(R() * 12);\n let cx: number;\n let cy: number;\n let cluster = -1;\n if (spec.kind === \"grid\") {\n const i = nodes.length;\n cx = ((i % cols) + 0.5) * SPACING;\n cy = (Math.floor(i / cols) + 0.5) * SPACING;\n } else if (spec.kind === \"clustered\" || spec.kind === \"collections\") {\n cluster = Math.floor(R() * centers.length);\n const c = centers[cluster]!;\n cx = c.x + gauss() * spread;\n cy = c.y + gauss() * spread;\n } else {\n cx = R() * side;\n cy = R() * side;\n }\n const box: Box = { x: Math.round(cx - w / 2), y: Math.round(cy - h / 2), w, h };\n if (spec.kind !== \"grid\" && !free(box)) continue;\n grid.add(box, box);\n clusterOf.push(cluster);\n const id = `n${nodes.length}`;\n if (R() < (spec.fixedPorts ?? 0)) {\n const s = SIDES[Math.floor(R() * 4)]!;\n const t = 0.2 + 0.6 * R();\n const at: Point =\n s === \"north\" ? { x: w * t, y: 0 } : s === \"south\" ? { x: w * t, y: h } : s === \"west\" ? { x: 0, y: h * t } : { x: w, y: h * t };\n const ports: Port[] = [{ id: \"out\", at: { x: Math.round(at.x), y: Math.round(at.y) } }];\n nodes.push({ id, box, ports });\n } else nodes.push({ id, box });\n }\n return { nodes, edges: makeEdges(spec, nodes, clusterOf, R) };\n}\n\nfunction makeEdges(spec: FixtureSpec, nodes: readonly Node[], clusterOf: readonly number[], R: () => number): Edge[] {\n const n = nodes.length;\n if (n < 2) return [];\n const locality = spec.locality ?? 0.65;\n const near = new Grid<number>(SPACING * 2);\n nodes.forEach((v, i) => near.add(i, v.box));\n const kindOf =\n spec.kind === \"collections\"\n ? clusterOf.map((c) => `${COLLECTIONS[c % COLLECTIONS.length]!}-${c}`)\n : nodes.map(() => COLLECTIONS[Math.floor(R() * COLLECTIONS.length)]!);\n // Hubs: a few nodes get most of the far edges (preferential attachment by a power law).\n const pickFar = (): number => (spec.kind === \"hubs\" ? Math.floor(n * R() ** 3) : Math.floor(R() * n));\n const target = Math.round(n * spec.edgesPerNode);\n const seen = new Set<string>();\n const edges: Edge[] = [];\n const add = (u: number, v: number): void => {\n const key = u < v ? `${u}-${v}` : `${v}-${u}`;\n if (u === v || seen.has(key)) return;\n seen.add(key);\n const src = nodes[u]!;\n edges.push({\n id: `e${edges.length}`,\n source: src.ports ? { node: src.id, port: \"out\" } : { node: src.id },\n target: { node: nodes[v]!.id },\n data: { collection: kindOf[v]! },\n });\n };\n if (spec.kind === \"collections\") {\n // Six of ten edges are fan-outs: a node links to 4 to 15 nodes of one other cluster.\n const members = new Map<number, number[]>();\n clusterOf.forEach((c, i) => {\n const list = members.get(c);\n if (list) list.push(i);\n else members.set(c, [i]);\n });\n const clusters = [...members.keys()].sort((a, c) => a - c);\n let rounds = 0;\n while (edges.length < target * 0.6 && clusters.length > 1 && rounds++ < target) {\n const u = Math.floor(R() * n);\n const others = clusters.filter((c) => c !== clusterOf[u]);\n const pool = members.get(others[Math.floor(R() * others.length)]!)!;\n const fan = 4 + Math.floor(R() * 12);\n for (let i = 0; i < fan; i++) add(u, pool[Math.floor(R() * pool.length)]!);\n }\n }\n let tries = 0;\n while (edges.length < target && tries++ < target * 30) {\n const u = Math.floor(R() * n);\n let v = -1;\n if (R() < locality) {\n const b = nodes[u]!.box;\n const cand: number[] = [];\n for (let r = SPACING; cand.length < 8 && r < SPACING * 64; r *= 2) {\n cand.length = 0;\n near.query({ x: b.x - r, y: b.y - r, w: b.w + 2 * r, h: b.h + 2 * r }, (i) => {\n if (i !== u) cand.push(i);\n });\n }\n cand.sort((a, c) => a - c);\n if (cand.length) v = cand[Math.floor(R() * cand.length)]!;\n } else v = pickFar();\n if (v >= 0) add(u, v);\n }\n return edges;\n}\n","import { makeFixture, rng } from \"./fixtures.ts\";\nimport type { Edge, Graph, Node } from \"./model.ts\";\n\n/**\n * A board of made-up data that shows one known defect of the routes or of the zoom levels.\n * The benchmark races the routers on each case, and the measures of `measureLinks` give a number for the defect.\n */\nexport interface CaseBoard {\n readonly name: string;\n /** The defect that the board shows, in a few words. */\n readonly defect: string;\n /** This function makes the graph. The same function always gives the same graph. */\n readonly make: () => Graph;\n}\n\n/** A board while it grows: the functions add nodes and edges in order. */\nclass Board {\n readonly nodes: Node[] = [];\n readonly edges: Edge[] = [];\n readonly #pairs = new Set<string>();\n\n node(id: string, x: number, y: number, w: number, h: number): string {\n this.nodes.push({ id, box: { x, y, w, h } });\n return id;\n }\n\n /** This method adds an edge. It adds nothing for a loop or for a second edge between the same two nodes. */\n link(source: string, target: string): void {\n const key = source < target ? `${source}|${target}` : `${target}|${source}`;\n if (source === target || this.#pairs.has(key)) return;\n this.#pairs.add(key);\n this.edges.push({ id: `e${this.edges.length}`, source: { node: source }, target: { node: target } });\n }\n\n graph(): Graph {\n return { nodes: this.nodes, edges: this.edges };\n }\n}\n\n/**\n * This function makes a dense board: 150 nodes in tight clusters. At the far view, the boxes of the groups overlap.\n * Then a level link starts or ends in a group that another group covers.\n */\nexport function denseGroupsBoard(): Graph {\n return makeFixture({ name: \"dense-groups\", kind: \"clustered\", nodes: 150, edgesPerNode: 2, seed: 3 });\n}\n\n/**\n * This function makes a board of three rows of 32 cards. Each card links to the next card of its row.\n * Forty long links join cards far apart. The hub of a section is near the middle of its cards.\n * So a long link climbs to hubs behind its source or past its target, and comes back.\n */\nexport function hubChainBoard(): Graph {\n const R = rng(3);\n const b = new Board();\n const rows = 3;\n const cols = 32;\n const gap = 48;\n const id = (r: number, c: number): string => `c${r}-${c}`;\n for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) b.node(id(r, c), c * (80 + gap), r * (36 + gap), 80, 36);\n for (let r = 0; r < rows; r++) for (let c = 0; c + 1 < cols; c++) b.link(id(r, c), id(r, c + 1));\n for (let n = 0; n < 40; n++) {\n const r = Math.floor(R() * rows);\n const c = Math.floor(R() * cols);\n const span = Math.floor(cols / 8 + (R() * cols) / 2);\n if (c + span < cols) b.link(id(r, c), id((r + 1) % rows, c + span));\n }\n return b.graph();\n}\n\n/**\n * This function makes a board of 32 groups in 8 columns and 4 rows. Each group has 4 cards in a square.\n * The cards of a group link in a chain, and 96 random links join cards of two groups.\n * On a level with many groups, some level links go around the outer edge of the board.\n */\nexport function manyGroupsBoard(): Graph {\n const R = rng(7);\n const b = new Board();\n const cols = 8;\n const rows = 4;\n const per = 4;\n const w = 60;\n const h = 30;\n const cardGap = 12;\n const groupGap = 60;\n const side = Math.ceil(Math.sqrt(per));\n const gw = side * w + (side - 1) * cardGap;\n const gh = Math.ceil(per / side) * h + (Math.ceil(per / side) - 1) * cardGap;\n const groups: string[][] = [];\n for (let r = 0; r < rows; r++)\n for (let c = 0; c < cols; c++) {\n const list: string[] = [];\n for (let i = 0; i < per; i++) {\n const x = c * (gw + groupGap) + (i % side) * (w + cardGap);\n const y = r * (gh + groupGap) + Math.floor(i / side) * (h + cardGap);\n list.push(b.node(`g${r}-${c}-${i}`, x, y, w, h));\n }\n groups.push(list);\n }\n for (const list of groups) for (let i = 1; i < list.length; i++) b.link(list[i - 1]!, list[i]!);\n const pick = (list: readonly string[]): string => list[Math.floor(R() * list.length)]!;\n for (let n = 0; n < groups.length * 3; n++) b.link(pick(groups[Math.floor(R() * groups.length)]!), pick(groups[Math.floor(R() * groups.length)]!));\n return b.graph();\n}\n\n/**\n * This function makes the far view of a board after a host layout packs it.\n * The board has 96 boxes of one size in a grid of 12 columns and 8 rows.\n * The boxes touch, with no gap between them. Each box links to a box near it, and 48 long links join boxes far apart.\n * The links have no channel between the boxes. The roadmap item ROOM measures this board before and after `makeRoom`.\n *\n * The board is not in `CASES`, because the digests of the router fix the output on each board of `CASES`.\n */\nexport function packedGridBoard(): Graph {\n const R = rng(11);\n const b = new Board();\n const cols = 12;\n const rows = 8;\n const w = 140;\n const h = 90;\n const id = (r: number, c: number): string => `p${r}-${c}`;\n for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) b.node(id(r, c), c * w, r * h, w, h);\n const step = (): number => Math.floor(R() * 5) - 2;\n for (let r = 0; r < rows; r++)\n for (let c = 0; c < cols; c++) {\n const rr = Math.max(0, Math.min(rows - 1, r + step()));\n const cc = Math.max(0, Math.min(cols - 1, c + step()));\n b.link(id(r, c), id(rr, cc));\n }\n for (let n = 0; n < 48; n++) b.link(id(Math.floor(R() * rows), Math.floor(R() * cols)), id(Math.floor(R() * rows), Math.floor(R() * cols)));\n return b.graph();\n}\n\n/** The case boards of the benchmark. Each board has a few hundred nodes at most, so the benchmark races them on each run. */\nexport const CASES: readonly CaseBoard[] = [\n { name: \"case-dense-groups\", defect: \"Groups overlap at the far view, and level links go through other groups.\", make: denseGroupsBoard },\n { name: \"case-hub-chain\", defect: \"A route climbs a chain of hubs away from its target and comes back.\", make: hubChainBoard },\n { name: \"case-many-groups\", defect: \"On a level with many groups, links go around the outer edge of the board.\", make: manyGroupsBoard },\n];\n","import { center, type Box, type Point } from \"./geom.ts\";\nimport { fixedPortPoint, type End, type Node, type Side } from \"./model.ts\";\n\n/** A plug: the point where a route leaves or enters a node, and the outward normal of its side. */\nexport interface Plug {\n readonly point: Point;\n readonly normal: Point;\n}\n\n/** The outward normal of each side, in a frame with the y axis down. */\nexport const SIDE_NORMAL: Readonly<Record<Side, Point>> = {\n north: { x: 0, y: -1 },\n east: { x: 1, y: 0 },\n south: { x: 0, y: 1 },\n west: { x: -1, y: 0 },\n};\n\n/** This function gives the side of the box that is nearest to the point. */\nexport function nearestSide(box: Box, p: Point): Side {\n const d: [Side, number][] = [\n [\"north\", Math.abs(p.y - box.y)],\n [\"east\", Math.abs(box.x + box.w - p.x)],\n [\"south\", Math.abs(box.y + box.h - p.y)],\n [\"west\", Math.abs(p.x - box.x)],\n ];\n let best = d[0]!;\n for (const x of d) if (x[1] < best[1]) best = x;\n return best[0];\n}\n\n/**\n * This function gives the side that faces `toward`: the side of the larger component of the direction from the center.\n * Thus the angle between the normal of the side and that direction is 45° or less.\n */\nexport function sideToward(box: Box, toward: Point): Side {\n const c = center(box);\n const dx = toward.x - c.x;\n const dy = toward.y - c.y;\n if (Math.abs(dx) >= Math.abs(dy)) return dx >= 0 ? \"east\" : \"west\";\n return dy >= 0 ? \"south\" : \"north\";\n}\n\n/**\n * This function gives the point on a side of the box that is nearest to the line from the center to `toward`.\n * The point stays away from the corners by `inset`, or by a quarter of the side when the side is short.\n */\nexport function pointOnSide(box: Box, side: Side, toward: Point, inset = 6): Point {\n const c = center(box);\n const dx = toward.x - c.x;\n const dy = toward.y - c.y;\n const clamp = (v: number, lo: number, len: number): number => {\n const m = Math.min(inset, len / 4);\n return Math.max(lo + m, Math.min(lo + len - m, v));\n };\n if (side === \"east\" || side === \"west\") {\n const x = side === \"east\" ? box.x + box.w : box.x;\n const y = dx === 0 ? c.y : c.y + (dy * (x - c.x)) / dx;\n return { x, y: clamp(y, box.y, box.h) };\n }\n const y = side === \"south\" ? box.y + box.h : box.y;\n const x = dy === 0 ? c.x : c.x + (dx * (y - c.y)) / dy;\n return { x: clamp(x, box.x, box.w), y };\n}\n\n/**\n * This function places the plug of one end of an edge. A fixed plug stays at its point. A plug with a side stays on that side.\n * The router places a free plug on the side that faces `toward`.\n */\nexport function placePlug(node: Node, end: End, toward: Point): Plug {\n const fixed = fixedPortPoint(node, end);\n const port = end.port === undefined ? undefined : node.ports?.find((p) => p.id === end.port);\n if (fixed) return { point: fixed, normal: SIDE_NORMAL[port?.side ?? nearestSide(node.box, fixed)] };\n const side = port?.side ?? sideToward(node.box, toward);\n return { point: pointOnSide(node.box, side, toward), normal: SIDE_NORMAL[side] };\n}\n","import { dist, type Point } from \"./geom.ts\";\n\n/** The options of the inflection rule. */\nexport interface InflectionOptions {\n /** The half width of the axis and diagonal bands, in radians. The default is 7°. */\n readonly tol?: number;\n /** The number of segments of the curve. The default is 24. */\n readonly samples?: number;\n /** The largest angle between the tangent and the chord, in radians. The default is 1.35 (approximately 77°). */\n readonly maxAngle?: number;\n}\n\n/**\n * This function gives the number of inflections that the rule asks for a chord at the angle `angle` (radians).\n * It gives 0 near an axis, 1 near a diagonal and 2 between them. The bands are `tol` wide on each side.\n */\nexport function inflectionSector(angle: number, tol: number = (7 * Math.PI) / 180): 0 | 1 | 2 {\n const q = Math.PI / 2;\n const mod = ((angle % q) + q) % q;\n if (mod < tol || q - mod < tol) return 0;\n if (Math.abs(mod - q / 2) < tol) return 1;\n return 2;\n}\n\n/**\n * This function draws the curve of the inflection rule from the plug `p0` to `target`.\n * The curve leaves `p0` along `normal`. In the frame of the chord, its side offset f has f(0) = f(L) = 0 and f'(0) = tan θ.\n * Here θ is the angle from the chord to the normal. A polynomial of degree 2, 3 or 4 gives 0, 1 or 2 inflections,\n * at 1/2, or at 1/3 and 2/3, of the chord.\n */\nexport function inflectionCurve(p0: Point, normal: Point, target: Point, options: InflectionOptions = {}): Point[] {\n const L = dist(p0, target);\n if (L === 0) return [p0, target];\n const ux = (target.x - p0.x) / L;\n const uy = (target.y - p0.y) / L;\n const k = inflectionSector(Math.atan2(uy, ux), options.tol);\n const maxAngle = options.maxAngle ?? 1.35;\n const th = -Math.atan2(normal.x * uy - normal.y * ux, normal.x * ux + normal.y * uy);\n const d = Math.tan(Math.max(-maxAngle, Math.min(maxAngle, th)));\n const f =\n k === 0\n ? (s: number): number => (-d / L) * s * s + d * s\n : k === 1\n ? (s: number): number => ((12 * d) / (L * L)) * (s ** 3 / 6 - (L * s * s) / 4) + d * s\n : (s: number): number => ((-36 * d) / L ** 3) * (s ** 4 / 12 - (L * s ** 3) / 6 + (L * L * s * s) / 9) + d * s;\n const n = Math.max(2, options.samples ?? 24);\n const out: Point[] = [];\n for (let i = 0; i <= n; i++) {\n if (i === n) {\n out.push(target);\n break;\n }\n const s = (L * i) / n;\n const o = f(s);\n out.push({ x: p0.x + ux * s - uy * o, y: p0.y + uy * s + ux * o });\n }\n out[0] = p0;\n return out;\n}\n\n/**\n * This function rounds each inner vertex of a polyline with a quadratic Bézier curve.\n * The curve starts and ends at most `radius` from the vertex, and at most half of each segment. The ends of the polyline stay.\n */\nexport function roundCorners(p: readonly Point[], radius: number, steps = 4): Point[] {\n if (p.length < 3 || radius <= 0) return [...p];\n const out: Point[] = [p[0]!];\n for (let i = 1; i + 1 < p.length; i++) {\n const a = p[i - 1]!;\n const v = p[i]!;\n const b = p[i + 1]!;\n const la = dist(a, v);\n const lb = dist(v, b);\n const r = Math.min(radius, la / 2, lb / 2);\n if (r <= 0) {\n out.push(v);\n continue;\n }\n const p1 = { x: v.x + ((a.x - v.x) * r) / la, y: v.y + ((a.y - v.y) * r) / la };\n const p2 = { x: v.x + ((b.x - v.x) * r) / lb, y: v.y + ((b.y - v.y) * r) / lb };\n for (let k = 0; k <= steps; k++) {\n const t = k / steps;\n const u = 1 - t;\n out.push({ x: u * u * p1.x + 2 * u * t * v.x + t * t * p2.x, y: u * u * p1.y + 2 * u * t * v.y + t * t * p2.y });\n }\n }\n out.push(p[p.length - 1]!);\n return out;\n}\n","import type { Point } from \"../geom.ts\";\n\n/**\n * A type of curve for a route.\n *\n * - `straight`: the polyline as it is.\n * - `rounded`: a quadratic Bezier curve at each corner, as `roundCorners` draws it.\n * - `spline`: a centripetal Catmull-Rom spline through the points. It does not overshoot or make loops.\n * - `arc`: a circular arc at each corner, tangent to the two legs.\n */\nexport type CurveType = \"straight\" | \"rounded\" | \"spline\" | \"arc\";\n\n/** The curve types, in the order of the benchmark. */\nexport const CURVE_TYPES: readonly CurveType[] = [\"straight\", \"rounded\", \"spline\", \"arc\"];\n\n/** The start of a curve: the pen goes to `to` and draws nothing. */\nexport interface MoveSegment {\n readonly kind: \"move\";\n readonly to: Point;\n}\n\n/** A straight line from the end of the segment before to `to`. */\nexport interface LineSegment {\n readonly kind: \"line\";\n readonly to: Point;\n}\n\n/** A cubic Bezier curve from the end of the segment before to `to`, with the control points `c1` and `c2`. */\nexport interface CubicSegment {\n readonly kind: \"cubic\";\n readonly c1: Point;\n readonly c2: Point;\n readonly to: Point;\n}\n\n/**\n * A circular arc from the end of the segment before to `to`. The arc has its center at `center` and the radius `radius`.\n * It starts at the angle `start` and turns by `sweep` radians. A positive `sweep` turns from the x axis to the y axis.\n * On a canvas, `ctx.arc(center.x, center.y, radius, start, start + sweep, sweep < 0)` draws it.\n */\nexport interface ArcSegment {\n readonly kind: \"arc\";\n readonly center: Point;\n readonly radius: number;\n readonly start: number;\n readonly sweep: number;\n readonly to: Point;\n}\n\n/**\n * A segment of a curve. A curve is a list of segments: one `move` first, then lines, cubic curves and arcs.\n * A renderer maps the list to SVG path data, to canvas calls or to the vertices of a mesh.\n */\nexport type CurveSegment = MoveSegment | LineSegment | CubicSegment | ArcSegment;\n\n/** This function gives the points of a polyline without the points that are nearer than `eps` to the point before them. */\nexport function distinctPoints(points: readonly Point[], eps = 1e-9): Point[] {\n const out: Point[] = [];\n for (const p of points) {\n const q = out[out.length - 1];\n if (q === undefined || Math.hypot(p.x - q.x, p.y - q.y) > eps) out.push(p);\n }\n return out;\n}\n","import { dist, inflate, pointBoxDistance, segmentHitsBox, type Box, type Point } from \"../geom.ts\";\nimport { Grid } from \"../grid.ts\";\nimport { fixedPortPoint, nodeIndex, type Graph, type Node, type Result } from \"../model.ts\";\n\n/** A broken hard rule. A correct router has none. */\nexport interface Violation {\n readonly rule:\n | \"complete\"\n | \"ends-at-plugs\"\n | \"fixed-plugs\"\n | \"no-pass-through\"\n | \"counts-sum\"\n | \"link-ends\"\n | \"bundle-trunk\"\n | \"run-shared\";\n readonly edge?: string;\n readonly detail: string;\n}\n\n/** The tolerance of the hard rules, in units of the plane. */\nexport const TOLERANCE = 0.5;\n\n/**\n * This function checks the hard rules of a result. Each edge has one route, and each route starts and ends at its nodes.\n * Fixed plugs stay in place. No route goes through a node that is not one of its ends. The counts of each level add up.\n * Each link of a level starts on the box of its source and ends on the box of its target.\n *\n * Each route of a bundle starts with its trunk, and an edge is in one bundle at most.\n * Each run has two edges or more, and the route of each edge holds the points of the run in a row.\n * The function gives at most `limit` violations.\n */\nexport function checkProperties(graph: Graph, result: Result, limit = 100): Violation[] {\n const out: Violation[] = [];\n const add = (v: Violation): boolean => {\n out.push(v);\n return out.length >= limit;\n };\n const byId = nodeIndex(graph);\n const grid = new Grid<Node>(180);\n for (const n of graph.nodes) grid.add(n, n.box);\n const routes = new Map<string, (typeof result.routes)[number]>();\n for (const r of result.routes) routes.set(r.edge, r);\n for (const e of graph.edges) {\n const r = routes.get(e.id);\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n if (!r || r.points.length < 2) {\n if (add({ rule: \"complete\", edge: e.id, detail: \"no route\" })) return out;\n continue;\n }\n const a = r.points[0]!;\n const b = r.points[r.points.length - 1]!;\n if (pointBoxDistance(a, s.box) > TOLERANCE || pointBoxDistance(b, t.box) > TOLERANCE)\n if (add({ rule: \"ends-at-plugs\", edge: e.id, detail: \"an end of the route is away from its node\" })) return out;\n const fs = fixedPortPoint(s, e.source);\n const ft = fixedPortPoint(t, e.target);\n if ((fs && dist(fs, a) > TOLERANCE) || (ft && dist(ft, b) > TOLERANCE))\n if (add({ rule: \"fixed-plugs\", edge: e.id, detail: \"the route does not start or end at its fixed plug\" })) return out;\n for (let i = 1; i < r.points.length; i++) {\n const p = r.points[i - 1]!;\n const q = r.points[i]!;\n let hit: Node | undefined;\n grid.querySegment(p, q, 0, (n) => {\n if (!hit && n !== s && n !== t && segmentHitsBox(p, q, inflate(n.box, -TOLERANCE))) hit = n;\n });\n if (hit) {\n if (add({ rule: \"no-pass-through\", edge: e.id, detail: `segment ${i} goes through ${hit.id}` })) return out;\n break;\n }\n }\n }\n const bundled = new Set<string>();\n for (const b of result.bundles ?? []) {\n for (const id of b.edges) {\n const r = routes.get(id);\n const shares = r !== undefined && r.points.length >= b.trunk.length && b.trunk.every((p, i) => dist(p, r.points[i]!) <= TOLERANCE);\n if (bundled.has(id) || !shares)\n if (add({ rule: \"bundle-trunk\", edge: id, detail: `bundle ${b.id}: the route is in two bundles or does not start with the trunk` })) return out;\n bundled.add(id);\n }\n }\n for (const run of result.runs ?? []) {\n if (run.edges.length < 2)\n if (add({ rule: \"run-shared\", detail: `run ${run.id} has fewer than two edges` })) return out;\n for (const id of run.edges) {\n const r = routes.get(id);\n if (!r || !(holds(r.points, run.points) || holds(r.points, [...run.points].reverse())))\n if (add({ rule: \"run-shared\", edge: id, detail: `run ${run.id}: the route does not hold the points of the run in a row` })) return out;\n }\n }\n for (const level of result.levels ?? []) {\n const itemOf = new Map<string, string>();\n for (const it of level.items) for (const n of it.nodes) itemOf.set(n, it.id);\n if (itemOf.size !== graph.nodes.length)\n if (add({ rule: \"counts-sum\", detail: `level ${level.depth}: the items hold ${itemOf.size} of ${graph.nodes.length} nodes` }))\n return out;\n let between = 0;\n for (const e of graph.edges) if (itemOf.get(e.source.node) !== itemOf.get(e.target.node)) between++;\n const sum = level.links.reduce((s, l) => s + l.count, 0);\n if (sum !== between)\n if (add({ rule: \"counts-sum\", detail: `level ${level.depth}: the links count ${sum} edges, not ${between}` })) return out;\n const boxOf = new Map(level.items.map((it) => [it.id, it.box]));\n for (const l of level.links) {\n const s = boxOf.get(l.source);\n const t = boxOf.get(l.target);\n const p = l.points;\n if (!s || !t || p.length < 2 || !onBoundary(p[0]!, s) || !onBoundary(p[p.length - 1]!, t))\n if (add({ rule: \"link-ends\", detail: `level ${level.depth}: the link ${l.source} to ${l.target} does not start and end on the boundaries of its items` }))\n return out;\n }\n }\n return out;\n}\n\n/** This function tells if the point is on the boundary of the box, within `TOLERANCE`. */\nfunction onBoundary(p: Point, b: Box): boolean {\n const inner = inflate(b, -TOLERANCE);\n const deep = p.x > inner.x && p.x < inner.x + inner.w && p.y > inner.y && p.y < inner.y + inner.h;\n return !deep && pointBoxDistance(p, b) <= TOLERANCE;\n}\n\n/** This function tells if the polyline `p` holds the points of `part` in a row. */\nfunction holds(p: readonly Point[], part: readonly Point[]): boolean {\n if (part.length === 0) return true;\n for (let i = 0; i + part.length <= p.length; i++) if (part.every((q, j) => dist(q, p[i + j]!) <= TOLERANCE)) return true;\n return false;\n}\n","import type { Point } from \"../geom.ts\";\nimport type { CurveSegment } from \"./model.ts\";\n\n/** The largest number of points that `sampleCurve` gives for one segment. */\nconst MAX_STEPS = 1024;\n\n/**\n * This function gives a polyline that follows the curve. The distance from each part of the curve to the polyline is `tolerance` or less.\n * The polyline starts at the point of the `move` and goes through the end of each segment.\n * Hit tests, measures and renderers that draw only lines use this polyline.\n */\nexport function sampleCurve(segments: readonly CurveSegment[], tolerance = 0.5): Point[] {\n const tol = Math.max(1e-6, tolerance);\n const out: Point[] = [];\n let at: Point | undefined;\n for (const s of segments) {\n if (s.kind === \"move\" || at === undefined) {\n out.push(s.to);\n at = s.to;\n continue;\n }\n if (s.kind === \"cubic\") {\n // The chord of a step of 1/n of the parameter is within 3·D/(4·n²) of the curve. D is the largest second difference of the control points.\n const d = Math.max(\n Math.hypot(at.x - 2 * s.c1.x + s.c2.x, at.y - 2 * s.c1.y + s.c2.y),\n Math.hypot(s.c1.x - 2 * s.c2.x + s.to.x, s.c1.y - 2 * s.c2.y + s.to.y),\n );\n const n = Math.min(MAX_STEPS, Math.max(1, Math.ceil(Math.sqrt((3 * d) / (4 * tol)))));\n for (let k = 1; k < n; k++) out.push(cubicAt(at, s.c1, s.c2, s.to, k / n));\n } else if (s.kind === \"arc\") {\n // The chord of an angle φ is within r·(1 - cos(φ/2)) of the arc.\n const step = s.radius <= tol ? Math.PI : 2 * Math.acos(1 - tol / s.radius);\n const n = Math.min(MAX_STEPS, Math.max(1, Math.ceil(Math.abs(s.sweep) / step)));\n for (let k = 1; k < n; k++) {\n const a = s.start + (s.sweep * k) / n;\n out.push({ x: s.center.x + s.radius * Math.cos(a), y: s.center.y + s.radius * Math.sin(a) });\n }\n }\n out.push(s.to);\n at = s.to;\n }\n return out;\n}\n\n/** This function gives the point at the parameter `t` of the cubic Bezier curve with the control points `p0`, `p1`, `p2` and `p3`. */\nexport function cubicAt(p0: Point, p1: Point, p2: Point, p3: Point, t: number): Point {\n const u = 1 - t;\n const a = u * u * u;\n const b = 3 * u * u * t;\n const c = 3 * u * t * t;\n const d = t * t * t;\n return { x: a * p0.x + b * p1.x + c * p2.x + d * p3.x, y: a * p0.y + b * p1.y + c * p2.y + d * p3.y };\n}\n\n/**\n * This function writes the segments as the data of an SVG path: the commands `M`, `L`, `C` and `A`.\n * Each number has at most `digits` digits after the point.\n */\nexport function toSvgPath(segments: readonly CurveSegment[], digits = 2): string {\n const n = (v: number): string => {\n const s = String(Number(v.toFixed(digits)));\n return s === \"-0\" ? \"0\" : s;\n };\n const p = (q: Point): string => `${n(q.x)} ${n(q.y)}`;\n const parts: string[] = [];\n for (const s of segments) {\n if (s.kind === \"move\") parts.push(`M ${p(s.to)}`);\n else if (s.kind === \"line\") parts.push(`L ${p(s.to)}`);\n else if (s.kind === \"cubic\") parts.push(`C ${p(s.c1)} ${p(s.c2)} ${p(s.to)}`);\n else parts.push(`A ${n(s.radius)} ${n(s.radius)} 0 ${Math.abs(s.sweep) > Math.PI ? 1 : 0} ${s.sweep > 0 ? 1 : 0} ${p(s.to)}`);\n }\n return parts.join(\" \");\n}\n","import { TOLERANCE } from \"../bench/properties.ts\";\nimport { inflate, segmentHitsBox, type Box, type Point } from \"../geom.ts\";\nimport { Grid } from \"../grid.ts\";\nimport type { CurveSegment } from \"./model.ts\";\nimport { sampleCurve } from \"./sample.ts\";\n\n/**\n * The free space of a board: the boxes that a curve must not go through.\n * Make it one time for a board with `curveSpace`, and give it to each call of `curveOf`.\n */\nexport interface CurveSpace {\n /** The boxes of the board. */\n readonly boxes: readonly Box[];\n /** The tolerance of the samples of a curve, in units of the plane. */\n readonly tolerance: number;\n /**\n * This method tells if the polyline `q` goes through a box that the polyline `p` does not go through.\n * A polyline goes through a box when a part of it longer than `TOLERANCE` is inside the box made smaller by `TOLERANCE`.\n */\n addsHit(q: readonly Point[], p: readonly Point[]): boolean;\n}\n\n/**\n * This function makes the free space of a board from its boxes. The boxes are the nodes, or the items of a zoom level.\n * The curves sample each piece within `tolerance` of the curve for the test.\n */\nexport function curveSpace(boxes: readonly Box[], tolerance = 0.25): CurveSpace {\n const inner = boxes.map((b) => inflate(b, -TOLERANCE));\n let size = 0;\n for (const b of boxes) size += Math.max(b.w, b.h);\n // The buckets grow with the boxes, as the buckets of `measureLinks` do.\n const grid = new Grid<number>(Math.max(180, (2 * size) / Math.max(1, boxes.length)));\n inner.forEach((b, i) => grid.add(i, b));\n const hits = (p: readonly Point[]): Set<number> => {\n const out = new Set<number>();\n for (let i = 1; i < p.length; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n grid.querySegment(a, b, 0, (id) => {\n if (!out.has(id) && segmentHitsBox(a, b, inner[id]!, TOLERANCE)) out.add(id);\n });\n }\n return out;\n };\n return {\n boxes,\n tolerance,\n addsHit(q: readonly Point[], p: readonly Point[]): boolean {\n let before: Set<number> | undefined;\n for (let i = 1; i < q.length; i++) {\n const a = q[i - 1]!;\n const b = q[i]!;\n const hit = grid.someSegment(a, b, 0, (id) => {\n if (!segmentHitsBox(a, b, inner[id]!, TOLERANCE)) return false;\n before ??= hits(p);\n return !before.has(id);\n });\n if (hit) return true;\n }\n return false;\n },\n };\n}\n\n/**\n * This function finds the largest size from `max` down to 0 that keeps a piece of a curve clear.\n * A clear piece goes through no box that its polyline avoids.\n *\n * The function `piece` gives the segments of the piece at a size. They start with a `move`.\n * The polyline `chord` is the part of the original polyline that the piece replaces.\n * The function tries `max` first, then it halves the interval `steps` times. The result is 0 when no size of the search is clear.\n */\nexport function fitSize(\n space: CurveSpace | undefined,\n max: number,\n chord: (size: number) => readonly Point[],\n piece: (size: number) => readonly CurveSegment[],\n steps = 8,\n): number {\n if (space === undefined || max <= 0) return Math.max(0, max);\n const clear = (size: number): boolean => !space.addsHit(sampleCurve(piece(size), space.tolerance), chord(size));\n if (clear(max)) return max;\n let lo = 0;\n let hi = max;\n for (let i = 0; i < steps; i++) {\n const mid = (lo + hi) / 2;\n if (clear(mid)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\n","import { dist, type Point } from \"../../geom.ts\";\nimport { distinctPoints, type CurveSegment } from \"../model.ts\";\nimport { fitSize, type CurveSpace } from \"../space.ts\";\n\n/** The options of `arcCurve`. */\nexport interface ArcOptions {\n /** The largest radius of the arc at a corner. The default is 12. */\n readonly radius?: number;\n /** The boxes that the curve must not go through. Without it, each corner gets the largest radius that fits on its legs. */\n readonly space?: CurveSpace;\n}\n\n/** A turn smaller than this angle, in radians, is no corner. A turn nearer to a half turn than this angle stays sharp. */\nconst FLAT = 1e-6;\n\n/**\n * This function puts a circular arc at each inner vertex of a polyline. The arc is tangent to the two legs of its corner.\n * The tangent points stay on the first half of each leg, so the ends of the polyline stay.\n * With `space`, the function makes the radius of a corner smaller until the arc goes through no box that the polyline avoids.\n * On a polyline with only horizontal and vertical legs, each arc is a quarter circle.\n */\nexport function arcCurve(points: readonly Point[], options: ArcOptions = {}): CurveSegment[] {\n const p = distinctPoints(points);\n if (p.length === 0) return [];\n const radius = options.radius ?? 12;\n const out: CurveSegment[] = [{ kind: \"move\", to: p[0]! }];\n for (let i = 1; i + 1 < p.length; i++) {\n const a = p[i - 1]!;\n const v = p[i]!;\n const b = p[i + 1]!;\n const la = dist(a, v);\n const lb = dist(v, b);\n const ux = (v.x - a.x) / la;\n const uy = (v.y - a.y) / la;\n const wx = (b.x - v.x) / lb;\n const wy = (b.y - v.y) / lb;\n const turn = Math.atan2(ux * wy - uy * wx, ux * wx + uy * wy);\n if (Math.abs(turn) < FLAT || Math.PI - Math.abs(turn) < FLAT) {\n out.push({ kind: \"line\", to: v });\n continue;\n }\n // The tangent points are r·tan(|turn|/2) from the vertex.\n const k = Math.tan(Math.abs(turn) / 2);\n const side = Math.sign(turn);\n const ends = (r: number): [Point, Point] => [\n { x: v.x - ux * r * k, y: v.y - uy * r * k },\n { x: v.x + wx * r * k, y: v.y + wy * r * k },\n ];\n const piece = (r: number): CurveSegment[] => {\n const [p1, p2] = ends(r);\n // The center is on the side of the turn, at the distance r from the first leg.\n const center = { x: p1.x - side * uy * r, y: p1.y + side * ux * r };\n return [{ kind: \"arc\", center, radius: r, start: Math.atan2(p1.y - center.y, p1.x - center.x), sweep: turn, to: p2 }];\n };\n const r = fitSize(\n options.space,\n Math.min(radius, Math.min(la, lb) / (2 * k)),\n (s) => [ends(s)[0], v, ends(s)[1]],\n (s) => [{ kind: \"move\", to: ends(s)[0] }, ...piece(s)],\n );\n if (r <= 0) {\n out.push({ kind: \"line\", to: v });\n continue;\n }\n const [p1] = ends(r);\n if (dist(p1, out[out.length - 1]!.to) > 1e-9) out.push({ kind: \"line\", to: p1 });\n out.push(...piece(r));\n }\n if (p.length > 1) out.push({ kind: \"line\", to: p[p.length - 1]! });\n return out;\n}\n","import { dist, type Point } from \"../../geom.ts\";\nimport { distinctPoints, type CurveSegment } from \"../model.ts\";\nimport { fitSize, type CurveSpace } from \"../space.ts\";\n\n/** The options of `roundedCurve`. */\nexport interface RoundedOptions {\n /** The largest distance from a corner to the start and to the end of its curve. The default is 12. */\n readonly radius?: number;\n /** The boxes that the curve must not go through. Without it, each corner gets the full radius. */\n readonly space?: CurveSpace;\n}\n\n/**\n * This function rounds each inner vertex of a polyline with a quadratic Bezier curve, as `roundCorners` does.\n * The curve of a corner starts and ends at most `radius` from the vertex, and at most half of each leg. The ends of the polyline stay.\n * The function gives each quadratic curve as the same cubic curve. With `space`, it makes the radius of a corner smaller until the curve\n * goes through no box that the polyline avoids.\n */\nexport function roundedCurve(points: readonly Point[], options: RoundedOptions = {}): CurveSegment[] {\n const p = distinctPoints(points);\n if (p.length === 0) return [];\n const radius = options.radius ?? 12;\n const out: CurveSegment[] = [{ kind: \"move\", to: p[0]! }];\n for (let i = 1; i + 1 < p.length; i++) {\n const a = p[i - 1]!;\n const v = p[i]!;\n const b = p[i + 1]!;\n const la = dist(a, v);\n const lb = dist(v, b);\n const ends = (r: number): [Point, Point] => [\n { x: v.x + ((a.x - v.x) * r) / la, y: v.y + ((a.y - v.y) * r) / la },\n { x: v.x + ((b.x - v.x) * r) / lb, y: v.y + ((b.y - v.y) * r) / lb },\n ];\n const piece = (r: number): CurveSegment[] => {\n const [p1, p2] = ends(r);\n // A quadratic curve with the control point v is the cubic curve with the control points 2/3 of the way to v.\n return [{ kind: \"cubic\", c1: { x: p1.x + (2 * (v.x - p1.x)) / 3, y: p1.y + (2 * (v.y - p1.y)) / 3 }, c2: { x: p2.x + (2 * (v.x - p2.x)) / 3, y: p2.y + (2 * (v.y - p2.y)) / 3 }, to: p2 }];\n };\n const r = fitSize(\n options.space,\n Math.min(radius, la / 2, lb / 2),\n (s) => [ends(s)[0], v, ends(s)[1]],\n (s) => [{ kind: \"move\", to: ends(s)[0] }, ...piece(s)],\n );\n if (r <= 0) {\n out.push({ kind: \"line\", to: v });\n continue;\n }\n const [p1] = ends(r);\n if (dist(p1, at(out)) > 1e-9) out.push({ kind: \"line\", to: p1 });\n out.push(...piece(r));\n }\n if (p.length > 1) out.push({ kind: \"line\", to: p[p.length - 1]! });\n return out;\n}\n\n/** This function gives the end of the last segment. */\nfunction at(segments: readonly CurveSegment[]): Point {\n return segments[segments.length - 1]!.to;\n}\n","import { dist, type Point } from \"../../geom.ts\";\nimport { distinctPoints, type CurveSegment } from \"../model.ts\";\nimport { fitSize, type CurveSpace } from \"../space.ts\";\n\n/** The options of `splineCurve`. */\nexport interface SplineOptions {\n /**\n * The tension of the spline, from 0 to 1. The value 0 gives the centripetal Catmull-Rom spline, and 1 gives the polyline.\n * The default is 0.\n */\n readonly tension?: number;\n /** The outward normal of the plug at the first point. With it, the curve leaves the first point along this normal. */\n readonly startNormal?: Point;\n /** The outward normal of the plug at the last point. With it, the curve comes into the last point against this normal. */\n readonly endNormal?: Point;\n /** The boxes that the curve must not go through. Without it, each piece gets the full tangents. */\n readonly space?: CurveSpace;\n}\n\n/**\n * This function draws a centripetal Catmull-Rom spline through the points of a polyline (Yuksel, Schaefer and Keyser, 2011).\n * Each piece between two points is one cubic Bezier curve. The centripetal knots keep the curve free of cusps and loops in a piece.\n * The curve goes through each point. Its tangent at a point keeps one direction on the two sides of the point.\n *\n * With `space`, the function makes the tangents of a piece shorter until the piece goes through no box that its leg avoids.\n * A piece with no tangent is the straight leg.\n */\nexport function splineCurve(points: readonly Point[], options: SplineOptions = {}): CurveSegment[] {\n const p = distinctPoints(points);\n if (p.length === 0) return [];\n const out: CurveSegment[] = [{ kind: \"move\", to: p[0]! }];\n const n = p.length;\n if (n === 1) return out;\n const scale = 1 - Math.max(0, Math.min(1, options.tension ?? 0));\n // The knot interval of each leg is the square root of its length.\n const dt = Array.from({ length: n - 1 }, (_, i) => Math.sqrt(dist(p[i]!, p[i + 1]!)));\n const unit = (q: Point): Point => {\n const l = Math.hypot(q.x, q.y);\n return l === 0 ? { x: 0, y: 0 } : { x: q.x / l, y: q.y / l };\n };\n // The tangent at each point, as a speed in the parameter of the knots.\n const m: Point[] = p.map((v, i) => {\n if (i === 0) {\n const leg = { x: p[1]!.x - v.x, y: p[1]!.y - v.y };\n if (!options.startNormal) return { x: leg.x / dt[0]!, y: leg.y / dt[0]! };\n const u = unit(options.startNormal);\n return { x: u.x * dt[0]!, y: u.y * dt[0]! };\n }\n if (i === n - 1) {\n const a = p[i - 1]!;\n const leg = { x: v.x - a.x, y: v.y - a.y };\n if (!options.endNormal) return { x: leg.x / dt[i - 1]!, y: leg.y / dt[i - 1]! };\n const u = unit(options.endNormal);\n return { x: -u.x * dt[i - 1]!, y: -u.y * dt[i - 1]! };\n }\n const a = p[i - 1]!;\n const b = p[i + 1]!;\n const t0 = dt[i - 1]!;\n const t1 = dt[i]!;\n return {\n x: (v.x - a.x) / t0 - (b.x - a.x) / (t0 + t1) + (b.x - v.x) / t1,\n y: (v.y - a.y) / t0 - (b.y - a.y) / (t0 + t1) + (b.y - v.y) / t1,\n };\n });\n for (let i = 0; i + 1 < n; i++) {\n const a = p[i]!;\n const b = p[i + 1]!;\n const h = dt[i]! / 3;\n const piece = (s: number): CurveSegment[] => [\n { kind: \"move\", to: a },\n { kind: \"cubic\", c1: { x: a.x + m[i]!.x * h * s, y: a.y + m[i]!.y * h * s }, c2: { x: b.x - m[i + 1]!.x * h * s, y: b.y - m[i + 1]!.y * h * s }, to: b },\n ];\n const s = fitSize(options.space, scale, () => [a, b], piece);\n out.push(s > 0 ? piece(s)[1]! : { kind: \"line\", to: b });\n }\n return out;\n}\n","import type { Point } from \"../../geom.ts\";\nimport type { CurveSegment } from \"../model.ts\";\n\n/** This function gives the polyline as it is: one `move` to the first point and one `line` to each other point. */\nexport function straightCurve(points: readonly Point[]): CurveSegment[] {\n return points.map((to, i): CurveSegment => (i === 0 ? { kind: \"move\", to } : { kind: \"line\", to }));\n}\n","import type { Point } from \"../geom.ts\";\nimport { arcCurve } from \"./arc/index.ts\";\nimport type { CurveSegment, CurveType } from \"./model.ts\";\nimport { roundedCurve } from \"./rounded/index.ts\";\nimport type { CurveSpace } from \"./space.ts\";\nimport { splineCurve } from \"./spline/index.ts\";\nimport { straightCurve } from \"./straight/index.ts\";\n\nexport * from \"./model.ts\";\nexport { cubicAt, sampleCurve, toSvgPath } from \"./sample.ts\";\nexport { curveSpace, type CurveSpace } from \"./space.ts\";\nexport { straightCurve } from \"./straight/index.ts\";\nexport { roundedCurve, type RoundedOptions } from \"./rounded/index.ts\";\nexport { splineCurve, type SplineOptions } from \"./spline/index.ts\";\nexport { arcCurve, type ArcOptions } from \"./arc/index.ts\";\n\n/** The options of `curveOf`. Each type reads only the options that it uses. */\nexport interface CurveOptions {\n readonly type: CurveType;\n /** The types `rounded` and `arc` read this radius of the corners. The default is 12. */\n readonly radius?: number;\n /** The type `spline` reads this tension, from 0 to 1. The default is 0. */\n readonly tension?: number;\n /** The type `spline` leaves the first point along this outward normal of its plug. */\n readonly startNormal?: Point;\n /** The type `spline` comes into the last point against this outward normal of its plug. */\n readonly endNormal?: Point;\n /** The boxes that the curve must not go through, from `curveSpace`. The type `straight` does not read it. */\n readonly space?: CurveSpace;\n}\n\n/**\n * This function gives the curve of a route: a polyline of a router, a lane of `laneRoutes` or a link of a zoom level.\n * The curve starts at the first point and ends at the last point of the polyline.\n * The output is a list of segments for any renderer. `toSvgPath` writes it as SVG path data, and `sampleCurve` gives points.\n */\nexport function curveOf(points: readonly Point[], options: CurveOptions): CurveSegment[] {\n switch (options.type) {\n case \"straight\":\n return straightCurve(points);\n case \"rounded\":\n return roundedCurve(points, options);\n case \"spline\":\n return splineCurve(points, options);\n case \"arc\":\n return arcCurve(points, options);\n }\n}\n","import { dist, inflate, segmentHitsRect, type Box, type Point } from \"./geom.ts\";\nimport { Grid } from \"./grid.ts\";\nimport type { Node } from \"./model.ts\";\n\n/** The nodes as obstacles, with a grid for fast tests. */\nexport class Obstacles {\n readonly #grid: Grid<Node>;\n\n /** This constructor indexes the boxes of the nodes. */\n constructor(nodes: readonly Node[], cell: number) {\n this.#grid = new Grid<Node>(cell);\n for (const n of nodes) this.#grid.add(n, n.box);\n }\n\n /** This method tells if the segment `ab` stays out of each box, made larger by `pad`. The nodes in `skip` do not count. */\n clear(a: Point, b: Point, pad: number, skip?: ReadonlySet<Node>): boolean {\n return this.hit(a, b, pad, skip) === undefined;\n }\n\n /**\n * This method gives a node whose box, made larger by `pad`, the segment `ab` goes into, or `undefined` when the segment is clear.\n * The nodes in `skip` do not count. The test stops at the first such node.\n */\n hit(a: Point, b: Point, pad: number, skip?: ReadonlySet<Node>): Node | undefined {\n let found: Node | undefined;\n this.#grid.someSegment(a, b, pad, (n) => {\n if (skip?.has(n) || !hits(a, b, n, pad)) return false;\n found = n;\n return true;\n });\n return found;\n }\n\n /** This method tells if the polyline stays out of each box, made larger by `pad`. The nodes in `skip` do not count. */\n clearPath(p: readonly Point[], pad: number, skip?: ReadonlySet<Node>): boolean {\n for (let i = 1; i < p.length; i++) if (!this.clear(p[i - 1]!, p[i]!, pad, skip)) return false;\n return true;\n }\n\n /** This method gives each node whose bucket the box touches to `visit`. A node can be outside the box. */\n query(box: Box, visit: (n: Node) => void): void {\n this.#grid.query(box, visit);\n }\n\n /** This method tells if the point is inside a box, made larger by `pad`. The node `skip` does not count. */\n inside(p: Point, pad: number, skip?: Node): boolean {\n let hit = false;\n this.#grid.query({ x: p.x, y: p.y, w: 0, h: 0 }, (n) => {\n if (!hit && n !== skip) {\n const b = n.box;\n hit = p.x > b.x - pad && p.x < b.x + b.w + pad && p.y > b.y - pad && p.y < b.y + b.h + pad;\n }\n });\n return hit;\n }\n}\n\n/** This function tells if the segment `ab` goes into the box of the node, made larger by `pad`. */\nfunction hits(a: Point, b: Point, n: Node, pad: number): boolean {\n const x = n.box;\n return segmentHitsRect(a, b, x.x - pad, x.y - pad, x.x + x.w + pad, x.y + x.h + pad);\n}\n\n/** A free point at an end of a search of `CornerGraph.pathAmong`, and the cost to reach it. */\nexport interface Terminal {\n readonly point: Point;\n readonly cost: number;\n}\n\n/** A path of `CornerGraph.pathAmong`: its points, the index of its first point in `from`, the index of its last point in `to`, and its cost. */\nexport interface Among {\n readonly points: Point[];\n readonly from: number;\n readonly to: number;\n readonly cost: number;\n}\n\n/** The options of the corner graph. */\nexport interface CornerGraphOptions {\n /** The distance from a box to its corners. */\n readonly margin: number;\n /** The number of visible neighbours of each corner. */\n readonly k: number;\n /**\n * The spacing of a lattice of free points over the plane, in units of the mean node size. The default is 3, and 0 turns it off.\n * The lattice links groups of nodes across empty space. Without it, the nearest corners of a group are all in that group.\n */\n readonly lattice?: number;\n /**\n * With `cones`, each corner also links to the nearest corner that it can see in each of four cones around the axes.\n * Then a path can go along a long corridor between rows or columns of boxes. The default is false.\n */\n readonly cones?: boolean;\n}\n\n/**\n * A sparse visibility graph. Its vertices are the corners of the boxes, made larger by `margin`.\n * Each corner links to its `k` nearest corners that it can see. A lattice of free points links the groups of nodes.\n * A path goes from corner to corner around the boxes.\n * The obstacle test uses half of the margin, so a path keeps a clearance of at least half of the margin.\n */\nexport class CornerGraph {\n readonly points: Point[] = [];\n readonly #adj: number[][] = [];\n // The length of each link, in the order of #adj.\n readonly #len: number[][] = [];\n readonly #obstacles: Obstacles;\n readonly #pointGrid: Grid<number>;\n readonly #cell: number;\n readonly #pad: number;\n readonly #k: number;\n // The work arrays of A*, made once and cleared by a stamp.\n #g = new Float64Array(0);\n #parent = new Int32Array(0);\n #open = new Int32Array(0);\n #closed = new Int32Array(0);\n #stamp = 0;\n // The corners in each bucket of the point grid, by the key of the bucket. A corner is in one bucket: the bucket of its point.\n readonly #buckets = new Map<number, number[]>();\n // The distance from the point of the last call of nearestVisible to each corner that the call found.\n #dist = new Float64Array(0);\n // The corners of one ring of nearestVisible, nearest first.\n readonly #near = new MinHeap();\n // The corners that each end of a path sees, by the coordinates of the end.\n readonly #endCache = new Map<string, number[]>();\n // The corners that each end of a path of `pathAmong` sees. Such a path has several ends, so each end takes fewer corners.\n readonly #fewCache = new Map<string, number[]>();\n // The connected part of the graph of each corner. The first call of `path` makes it.\n #part: Int32Array | undefined;\n\n /** This constructor makes the graph of the nodes. */\n constructor(nodes: readonly Node[], obstacles: Obstacles, options: CornerGraphOptions) {\n this.#obstacles = obstacles;\n this.#pad = options.margin / 2;\n this.#k = options.k;\n let size = 0;\n for (const n of nodes) size += (n.box.w + n.box.h) / 2;\n this.#cell = Math.max(1, size / Math.max(1, nodes.length) + 2 * options.margin);\n this.#pointGrid = new Grid<number>(this.#cell);\n for (const n of nodes) {\n const b = inflate(n.box, options.margin);\n for (const c of [\n { x: b.x, y: b.y },\n { x: b.x + b.w, y: b.y },\n { x: b.x + b.w, y: b.y + b.h },\n { x: b.x, y: b.y + b.h },\n ]) {\n if (!obstacles.inside(c, this.#pad)) this.#addPoint(c);\n }\n }\n const spacing = (options.lattice ?? 3) * this.#cell;\n if (spacing > 0 && nodes.length > 0) {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const n of nodes) {\n x0 = Math.min(x0, n.box.x);\n y0 = Math.min(y0, n.box.y);\n x1 = Math.max(x1, n.box.x + n.box.w);\n y1 = Math.max(y1, n.box.y + n.box.h);\n }\n for (let x = x0 - spacing / 2; x <= x1 + spacing; x += spacing) {\n for (let y = y0 - spacing / 2; y <= y1 + spacing; y += spacing) {\n const c = { x, y };\n if (!obstacles.inside(c, options.margin)) this.#addPoint(c);\n }\n }\n }\n const links: Set<number>[] = this.points.map(() => new Set<number>());\n for (let i = 0; i < this.points.length; i++) {\n // The k nearest corners of a corner in a long corridor are often all on one side. The cones add a link along the corridor.\n for (const j of this.#nearestVisible(this.points[i]!, this.#k, i, this.#pad, options.cones ?? false)) {\n links[i]!.add(j);\n links[j]!.add(i);\n }\n }\n links.forEach((s, i) => {\n const adj = [...s].sort((a, b) => a - b);\n this.#adj.push(adj);\n this.#len.push(adj.map((j) => dist(this.points[i]!, this.points[j]!)));\n });\n }\n\n #addPoint(c: Point): void {\n const j = this.points.length;\n this.#pointGrid.add(j, { x: c.x, y: c.y, w: 0, h: 0 });\n const key = bucketKey(Math.floor(c.x / this.#cell), Math.floor(c.y / this.#cell));\n const list = this.#buckets.get(key);\n if (list === undefined) this.#buckets.set(key, [j]);\n else list.push(j);\n this.points.push(c);\n }\n\n /** This method gives the number of links of the graph. */\n get linkCount(): number {\n let n = 0;\n for (const a of this.#adj) n += a.length;\n return n / 2;\n }\n\n /** This method gives the index of the corner nearest to `p`, seen or not, or -1 when the graph has no corner near it. */\n nearest(p: Point): number {\n for (let r = this.#cell; r <= this.#cell * 64; r *= 2) {\n let best = -1;\n let bestD = Infinity;\n this.#pointGrid.query({ x: p.x - r, y: p.y - r, w: 2 * r, h: 2 * r }, (j) => {\n const d = dist(p, this.points[j]!);\n if (d < bestD || (d === bestD && j < best)) {\n bestD = d;\n best = j;\n }\n });\n // A corner beyond r can be nearer than a corner in a corner of the square. Within r, none is.\n if (best >= 0 && bestD <= r) return best;\n }\n return -1;\n }\n\n /** This method gives at most `k` corners that `p` can see, nearest first. The corner `self` does not count. */\n nearestVisible(p: Point, k: number, self = -1): number[] {\n return this.#nearestVisible(p, k, self, this.#pad);\n }\n\n /**\n * This method tests the corners in rings of radius `r` = 1, 2, 4 and 8 cells. In each ring, it tests the corners\n * within `r` that an earlier ring did not test, nearest first, and equal distances by index.\n * The ring of `r` takes the corners of the buckets that the square of side `2r` around `p` touches.\n * A corner of these buckets beyond `r` waits for the next ring. So the method visits each bucket one time.\n * With `cones`, the method also gives the nearest visible corner of each of four cones around the axes that the `k` nearest corners leave empty.\n */\n #nearestVisible(p: Point, k: number, self: number, pad: number, cones = false): number[] {\n const out: number[] = [];\n // The bits of the full cones: 1 is +x, 2 is +y, 4 is -x and 8 is -y.\n let full = 0;\n if (this.#dist.length < this.points.length) this.#dist = new Float64Array(this.points.length);\n const dd = this.#dist;\n const points = this.points;\n const cell = this.#cell;\n const reach = CONE_CELLS * cell;\n const blockers: Node[] = [];\n const now = this.#near;\n // The corners that the rings found beyond their radius. The next ring takes them.\n let wait: number[] = [];\n // The bucket range of the ring before. The first ring has none.\n let pi0 = 1;\n let pi1 = 0;\n let pj0 = 1;\n let pj1 = 0;\n for (let r = cell; r <= cell * 8; r *= 2) {\n // The ring of `r` holds the corners beyond `r / 2`. With the k nearest corners, the cones take no corner beyond `reach`.\n if (out.length >= k && r / 2 >= reach) return out;\n // These bounds are the bounds of a query of the box at (p.x - r, p.y - r) with the side 2r.\n const x0 = p.x - r;\n const y0 = p.y - r;\n const i0 = Math.floor(x0 / cell);\n const j0 = Math.floor(y0 / cell);\n const i1 = Math.floor((x0 + 2 * r) / cell);\n const j1 = Math.floor((y0 + 2 * r) / cell);\n const later: number[] = [];\n now.clear();\n for (const j of wait) {\n if (dd[j]! > r) later.push(j);\n else now.add(dd[j]!, j);\n }\n for (let bi = i0; bi <= i1; bi++) {\n const before = bi >= pi0 && bi <= pi1;\n for (let bj = j0; bj <= j1; bj++) {\n if (before && bj >= pj0 && bj <= pj1) continue;\n const list = this.#buckets.get(bucketKey(bi, bj));\n if (list === undefined) continue;\n for (const j of list) {\n if (j === self) continue;\n const d = dist(p, points[j]!);\n dd[j] = d;\n if (d > r) later.push(j);\n else now.add(d, j);\n }\n }\n }\n // The heap gives the corners nearest first, and equal distances by index. A call often stops after a few corners.\n now.build();\n while (now.size > 0) {\n const j = now.pop();\n // A node that stopped an earlier segment often stops this segment too, so the test takes these nodes first.\n // The order of the nodes does not change the result.\n const q = points[j]!;\n const cone = cones ? coneOf(q.x - p.x, q.y - p.y) : 0;\n if (out.length >= k) {\n // After the k nearest corners, only a corner of an empty cone counts, up to `CONE_CELLS` cells from `p`.\n if (dd[j]! > reach) return out;\n if ((full & cone) !== 0) continue;\n }\n let blocked = false;\n for (let b = 0; b < blockers.length && !blocked; b++) blocked = hits(p, q, blockers[b]!, pad);\n if (blocked) continue;\n const hit = this.#obstacles.hit(p, q, pad);\n if (hit !== undefined) blockers.push(hit);\n else {\n out.push(j);\n full |= cone;\n if (out.length >= k && (!cones || full === 15)) return out;\n }\n }\n wait = later;\n pi0 = i0;\n pi1 = i1;\n pj0 = j0;\n pj1 = j1;\n }\n return out;\n }\n\n /**\n * This method gives a shortest path from `from` to `to` in the graph (A*), with the two points as its ends.\n * It gives `undefined` when the graph links no corner near `from` to a corner near `to`.\n * The function `cost` can change the cost of the link from corner `i` to corner `j`, of length `d`.\n * It must give at least `floor` × `d`, so that the estimate of A* stays below the true cost.\n */\n path(from: Point, to: Point, cost?: (i: number, j: number, d: number) => number, floor: number = 1): Point[] | undefined {\n if (this.#obstacles.clear(from, to, this.#pad)) return [from, to];\n return this.#search([{ point: from, cost: 0 }], [{ point: to, cost: 0 }], cost, floor, this.#k * 2)?.points;\n }\n\n /**\n * This method gives the shortest path from a point of `from` to a point of `to`, or `undefined` when the graph has none.\n * The cost of a path includes the costs of its two points. One search finds the path, so this method is faster than a call of `path` for each pair.\n */\n pathAmong(from: readonly Terminal[], to: readonly Terminal[]): Among | undefined {\n const found = this.#search(from, to, undefined, 1, this.#k);\n // A straight line between two points that costs less than the found path is better. The test takes the lines in order of cost.\n const lines: Among[] = [];\n from.forEach((a, i) =>\n to.forEach((b, k) => {\n const c = a.cost + dist(a.point, b.point) + b.cost;\n if (!found || c < found.cost) lines.push({ points: [a.point, b.point], from: i, to: k, cost: c });\n }),\n );\n lines.sort((u, v) => u.cost - v.cost);\n return lines.find((l) => this.#obstacles.clear(l.points[0]!, l.points[1]!, this.#pad)) ?? found;\n }\n\n /** This method is the search (A*) of `path` and `pathAmong`. */\n #search(\n from: readonly Terminal[],\n to: readonly Terminal[],\n cost: ((i: number, j: number, d: number) => number) | undefined,\n floor: number,\n count: number,\n ): Among | undefined {\n const n = this.points.length;\n if (this.#g.length < n) {\n this.#g = new Float64Array(n);\n this.#parent = new Int32Array(n);\n this.#open = new Int32Array(n);\n this.#closed = new Int32Array(n);\n }\n const stamp = ++this.#stamp;\n const points = this.points;\n // The cost from each corner near a point of `to` to that point, and the index of that point.\n const goal = new Map<number, number>();\n const goalOf = new Map<number, number>();\n to.forEach((b, k) => {\n for (const j of this.#ends(b.point, count)) {\n const tail = dist(points[j]!, b.point) + b.cost;\n const now = goal.get(j);\n if (now === undefined || tail < now) {\n goal.set(j, tail);\n goalOf.set(j, k);\n }\n }\n });\n if (goal.size === 0) return undefined;\n const starts = from.map((a) => this.#ends(a.point, count));\n // Without a start and a goal in one connected part, A* finds no path. This test stops it before it visits the whole part.\n if (!starts.some((list) => this.#joined(list, goal))) return undefined;\n const heap = new MinHeap();\n const G = this.#g;\n const parentOf = this.#parent;\n const open = this.#open;\n const closed = this.#closed;\n const estimate = (p: Point): number => {\n let h = Infinity;\n for (const b of to) h = Math.min(h, dist(p, b.point));\n return floor * h;\n };\n const relax = (j: number, g: number, parent: number): void => {\n if (closed[j] === stamp) return;\n if (open[j] === stamp && G[j]! <= g) return;\n open[j] = stamp;\n G[j] = g;\n parentOf[j] = parent;\n heap.push(g + estimate(points[j]!), j);\n };\n // The parent of a first corner is -1 - i, where i is the index of its point in `from`.\n from.forEach((a, i) => {\n for (const j of starts[i]!) relax(j, a.cost + dist(a.point, points[j]!), -1 - i);\n });\n let best = Infinity;\n let bestEnd = -1;\n while (heap.size > 0) {\n if (heap.topKey >= best) break;\n const i = heap.pop();\n if (closed[i] === stamp) continue;\n closed[i] = stamp;\n const gi = G[i]!;\n const tail = goal.get(i);\n if (tail !== undefined && gi + tail < best) {\n best = gi + tail;\n bestEnd = i;\n }\n const adj = this.#adj[i]!;\n const len = this.#len[i]!;\n for (let m = 0; m < adj.length; m++) {\n const j = adj[m]!;\n if (closed[j] === stamp) continue;\n const d = len[m]!;\n relax(j, gi + (cost ? cost(i, j, d) : d), i);\n }\n }\n if (bestEnd < 0) return undefined;\n const k = goalOf.get(bestEnd)!;\n const out: Point[] = [to[k]!.point];\n for (let i = bestEnd; ; i = parentOf[i]!) {\n out.push(points[i]!);\n if (parentOf[i]! < 0) {\n const f = -1 - parentOf[i]!;\n out.push(from[f]!.point);\n return { points: out.reverse(), from: f, to: k, cost: best };\n }\n }\n }\n\n /** This method tells if a corner of `starts` and a corner of `goal` are in one connected part of the graph. */\n #joined(starts: readonly number[], goal: ReadonlyMap<number, number>): boolean {\n const part = (this.#part ??= this.#parts());\n const goals = new Set<number>();\n for (const j of goal.keys()) goals.add(part[j]!);\n for (const j of starts) if (goals.has(part[j]!)) return true;\n return false;\n }\n\n /** This method gives the number of the connected part of each corner. */\n #parts(): Int32Array {\n const part = new Int32Array(this.points.length).fill(-1);\n const stack: number[] = [];\n let count = 0;\n for (let i = 0; i < part.length; i++) {\n if (part[i] !== -1) continue;\n part[i] = count;\n stack.push(i);\n while (stack.length > 0) {\n for (const j of this.#adj[stack.pop()!]!) {\n if (part[j] !== -1) continue;\n part[j] = count;\n stack.push(j);\n }\n }\n count++;\n }\n return part;\n }\n\n /**\n * This method gives at most `count` corners that an end of a path can see. An end near a box sees no corner with the clearance.\n * Then the end takes the corners that it sees without the clearance, so the path does not cut through the boxes.\n * The graph does not change, so the method keeps the corners of each end.\n */\n #ends(p: Point, count: number): number[] {\n const cache = count === this.#k * 2 ? this.#endCache : this.#fewCache;\n const key = `${p.x},${p.y}`;\n let out = cache.get(key);\n if (!out) {\n out = this.nearestVisible(p, count);\n if (out.length === 0) out = this.#nearestVisible(p, count, -1, 0);\n cache.set(key, out);\n }\n return out;\n }\n\n /** This method removes the vertices that a later vertex makes needless: from each vertex, it goes to the farthest vertex in view. */\n pull(p: readonly Point[], lookahead = 16): Point[] {\n if (p.length < 3) return [...p];\n const out: Point[] = [p[0]!];\n let i = 0;\n while (i < p.length - 1) {\n let j = Math.min(p.length - 1, i + lookahead);\n while (j > i + 1 && !this.#obstacles.clear(p[i]!, p[j]!, this.#pad)) j--;\n out.push(p[j]!);\n i = j;\n }\n return out;\n }\n}\n\n/** A link of a cone is at most this number of cells long. A longer search costs time on a dense level and finds few new links. */\nconst CONE_CELLS = 3;\n\n/** This function gives the bit of the cone of the offset (`dx`, `dy`): 1 is +x, 2 is +y, 4 is -x and 8 is -y. A diagonal offset is in a cone of the x axis. */\nconst coneOf = (dx: number, dy: number): number => (Math.abs(dx) >= Math.abs(dy) ? (dx > 0 ? 1 : 4) : dy > 0 ? 2 : 8);\n\n/** This function packs the two indices of a bucket into one number. Each index stays within ±2^20. */\nconst bucketKey = (i: number, j: number): number => (i + 1_048_576) * 2_097_152 + (j + 1_048_576);\n\n/**\n * A binary min-heap of (key, value) pairs in typed arrays. The pairs come out by key, and equal keys by value, so the order is deterministic.\n * The method `push` adds a pair to the heap. The method `add` only appends a pair, and the method `build` then makes the heap of all the pairs.\n */\nclass MinHeap {\n #d = new Float64Array(64);\n #j = new Int32Array(64);\n size = 0;\n\n /** The smallest key. */\n get topKey(): number {\n return this.#d[0]!;\n }\n\n push(key: number, value: number): void {\n this.add(key, value);\n const d = this.#d;\n const jj = this.#j;\n let i = this.size - 1;\n while (i > 0) {\n const p = (i - 1) >> 1;\n if (!(key < d[p]! || (key === d[p] && value < jj[p]!))) break;\n d[i] = d[p]!;\n jj[i] = jj[p]!;\n i = p;\n }\n d[i] = key;\n jj[i] = value;\n }\n\n clear(): void {\n this.size = 0;\n }\n\n add(d: number, j: number): void {\n if (this.size === this.#d.length) {\n const dd = new Float64Array(2 * this.size);\n dd.set(this.#d);\n this.#d = dd;\n const jj = new Int32Array(2 * this.size);\n jj.set(this.#j);\n this.#j = jj;\n }\n this.#d[this.size] = d;\n this.#j[this.size] = j;\n this.size++;\n }\n\n build(): void {\n for (let i = (this.size >> 1) - 1; i >= 0; i--) this.#down(i);\n }\n\n /** This method removes the pair with the smallest key and gives its value. */\n pop(): number {\n const top = this.#j[0]!;\n this.size--;\n if (this.size > 0) {\n this.#d[0] = this.#d[this.size]!;\n this.#j[0] = this.#j[this.size]!;\n this.#down(0);\n }\n return top;\n }\n\n #down(i: number): void {\n const d = this.#d;\n const jj = this.#j;\n const n = this.size;\n const di = d[i]!;\n const ji = jj[i]!;\n for (;;) {\n const l = 2 * i + 1;\n if (l >= n) break;\n const r = l + 1;\n let m = l;\n if (r < n && (d[r]! < d[l]! || (d[r] === d[l] && jj[r]! < jj[l]!))) m = r;\n if (!(d[m]! < di || (d[m] === di && jj[m]! < ji))) break;\n d[i] = d[m]!;\n jj[i] = jj[m]!;\n i = m;\n }\n d[i] = di;\n jj[i] = ji;\n }\n}\n","import { inflectionCurve, roundCorners } from \"./curves.ts\";\nimport type { Point } from \"./geom.ts\";\nimport type { Node } from \"./model.ts\";\nimport type { Plug } from \"./plugs.ts\";\nimport { CornerGraph, Obstacles } from \"./visibility.ts\";\n\n/** The options of a way finder. */\nexport interface WayOptions {\n /** The distance from a box to the corners of the graph. The default is 5. */\n readonly margin?: number;\n /** The number of visible neighbours of each corner. The default is 8. */\n readonly k?: number;\n /** With `smooth`, a way in clear view uses the inflection rule, and the other ways get round corners. */\n readonly smooth?: boolean;\n}\n\n/**\n * The ways around the nodes of one graph. A way leaves a plug along its normal.\n * It goes a shortest way (A*) through the corner graph, without the needless corners. It enters the other plug along its normal.\n */\nexport class WayFinder {\n readonly obstacles: Obstacles;\n readonly corners: CornerGraph;\n readonly margin: number;\n readonly #smooth: boolean;\n\n /** This constructor makes the obstacles and the corner graph of the nodes. */\n constructor(nodes: readonly Node[], options: WayOptions = {}) {\n this.margin = options.margin ?? 5;\n this.#smooth = options.smooth ?? false;\n this.obstacles = new Obstacles(nodes, 180);\n this.corners = new CornerGraph(nodes, this.obstacles, { margin: this.margin, k: options.k ?? 8 });\n }\n\n /** This method gives the point at `margin` from the plug, along its normal. */\n out(p: Plug): Point {\n return { x: p.point.x + p.normal.x * this.margin, y: p.point.y + p.normal.y * this.margin };\n }\n\n /** This method gives a way from plug to plug. Without a way in the graph, it gives the straight line. */\n between(ps: Plug, pt: Plug, ends: ReadonlySet<Node>): Point[] {\n if (this.#smooth) {\n const curve = inflectionCurve(ps.point, ps.normal, pt.point);\n if (this.obstacles.clearPath(curve, this.margin / 2, ends)) return curve;\n }\n const way = this.corners.path(this.out(ps), this.out(pt));\n if (!way) return [ps.point, pt.point];\n const poly = [ps.point, ...this.corners.pull(way), pt.point];\n if (this.#smooth) {\n const round = roundCorners(poly, this.margin);\n if (this.obstacles.clearPath(round, 0, ends)) return round;\n }\n return poly;\n }\n\n /** This method gives a way from a plug to a free point, or `undefined` when the graph has none. */\n fromPlug(ps: Plug, to: Point): Point[] | undefined {\n const way = this.corners.path(this.out(ps), to);\n return way && [ps.point, ...this.corners.pull(way)];\n }\n\n /** This method gives a way from a free point to a plug, or `undefined` when the graph has none. */\n toPlug(from: Point, pt: Plug): Point[] | undefined {\n const way = this.corners.path(from, this.out(pt));\n return way && [...this.corners.pull(way), pt.point];\n }\n}\n","import { dist, type Point } from \"./geom.ts\";\nimport type { Result, Route } from \"./model.ts\";\n\n/** A piece of drawn way. A shared segment carries several edges, in lane order. A private segment carries one edge. */\nexport interface Segment {\n readonly id: string;\n readonly points: readonly Point[];\n /** The edges in lane order. Lane 0 is on the left of the segment, from its first point to its last. The y axis points down. */\n readonly edges: readonly string[];\n /** The number of edges. A renderer shows it on a fat edge. */\n readonly count: number;\n}\n\n/** One step of a path: a segment, the way through it, and the lane of the edge in it. */\nexport interface SegmentRef {\n readonly segment: string;\n /** This value is true when the edge goes from the last point of the segment to its first point. */\n readonly reverse: boolean;\n readonly lane: number;\n}\n\n/** The route of one edge as a list of segments. */\nexport interface Path {\n readonly edge: string;\n readonly segments: readonly SegmentRef[];\n}\n\n/** The routes of a result as shared geometry. A renderer can draw each segment one time, with a count. */\nexport interface SegmentGraph {\n readonly segments: readonly Segment[];\n readonly paths: readonly Path[];\n}\n\nconst SAME = 1e-6;\n\n/** This function gives the index where `p` holds the points of `part` in a row, from `from` on, or -1. */\nfunction indexOf(p: readonly Point[], part: readonly Point[], from: number): number {\n for (let i = from; i + part.length <= p.length; i++) {\n let ok = true;\n for (let j = 0; ok && j < part.length; j++) ok = dist(p[i + j]!, part[j]!) <= SAME;\n if (ok) return i;\n }\n return -1;\n}\n\n/**\n * This function breaks each route into segments. The runs and the trunks of the bundles become shared segments.\n * The other parts of each route become private segments. The segments of a path, in order, give the points of its route again.\n */\nexport function segmentsOf(result: Result): SegmentGraph {\n const shared = [\n ...(result.runs ?? []).map((r) => ({ id: r.id, points: r.points, edges: r.edges })),\n ...(result.bundles ?? []).map((b) => ({ id: b.id, points: b.trunk, edges: b.edges })),\n ].filter((s) => s.points.length >= 2);\n const onEdge = new Map<string, { id: string; points: readonly Point[]; lane: number }[]>();\n for (const s of shared) {\n s.edges.forEach((edge, lane) => {\n const list = onEdge.get(edge);\n if (list) list.push({ id: s.id, points: s.points, lane });\n else onEdge.set(edge, [{ id: s.id, points: s.points, lane }]);\n });\n }\n const segments: Segment[] = shared.map((s) => ({ id: s.id, points: s.points, edges: s.edges, count: s.edges.length }));\n const paths: Path[] = [];\n for (const route of result.routes) {\n const p = route.points;\n // The place of each shared segment in the route, in the order of the route.\n const found: { at: number; end: number; ref: SegmentRef }[] = [];\n for (const s of onEdge.get(route.edge) ?? []) {\n let at = indexOf(p, s.points, 0);\n let reverse = false;\n if (at < 0) {\n at = indexOf(p, [...s.points].reverse(), 0);\n reverse = true;\n }\n if (at >= 0) found.push({ at, end: at + s.points.length - 1, ref: { segment: s.id, reverse, lane: s.lane } });\n }\n found.sort((a, b) => a.at - b.at);\n const refs: SegmentRef[] = [];\n let i = 0;\n const own = (to: number): void => {\n if (to <= i) return;\n const id = `${route.edge}/${refs.length}`;\n segments.push({ id, points: p.slice(i, to + 1), edges: [route.edge], count: 1 });\n refs.push({ segment: id, reverse: false, lane: 0 });\n };\n for (const f of found) {\n if (f.at < i) continue;\n own(f.at);\n refs.push(f.ref);\n i = f.end;\n }\n own(p.length - 1);\n paths.push({ edge: route.edge, segments: refs });\n }\n return { segments, paths };\n}\n\n/** This function gives the points of a path, with the segments in the order and the way of the path. */\nexport function pathPoints(graph: SegmentGraph, path: Path): Point[] {\n const byId = new Map(graph.segments.map((s) => [s.id, s]));\n const out: Point[] = [];\n for (const ref of path.segments) {\n const s = byId.get(ref.segment);\n if (!s) continue;\n const pts = ref.reverse ? [...s.points].reverse() : s.points;\n for (const q of pts) if (out.length === 0 || dist(q, out[out.length - 1]!) > SAME) out.push(q);\n }\n return out;\n}\n\n/**\n * This function moves each point of a polyline by `d` to the left, in a frame with the y axis down.\n * At an inner point, it moves along the bisector, at most 2 × `d` far.\n */\nexport function offsetPolyline(p: readonly Point[], d: number): Point[] {\n if (d === 0 || p.length < 2) return [...p];\n const normals: Point[] = [];\n for (let i = 1; i < p.length; i++) {\n const dx = p[i]!.x - p[i - 1]!.x;\n const dy = p[i]!.y - p[i - 1]!.y;\n const l = Math.hypot(dx, dy);\n normals.push(l > 0 ? { x: dy / l, y: -dx / l } : (normals[normals.length - 1] ?? { x: 0, y: 0 }));\n }\n return p.map((q, i) => {\n const a = normals[Math.max(0, i - 1)]!;\n const b = normals[Math.min(normals.length - 1, i)]!;\n const mx = a.x + b.x;\n const my = a.y + b.y;\n const ml = Math.hypot(mx, my);\n if (ml < 1e-9) return { x: q.x + a.x * d, y: q.y + a.y * d };\n const cos = (mx * a.x + my * a.y) / ml;\n const k = Math.min(2, 1 / Math.max(cos, 1e-9)) * d;\n return { x: q.x + (mx / ml) * k, y: q.y + (my / ml) * k };\n });\n}\n\n/** The options of `pullApart`. */\nexport interface PullApartOptions {\n /** The distance between two lanes. */\n readonly spacing: number;\n /** The largest width of a segment, from its outer lane on the left to its outer lane on the right. */\n readonly maxWidth: number;\n}\n\n/**\n * This function pulls the lanes of each shared segment apart, and gives a route for each edge.\n * The lanes keep the lane order, so they do not cross in a segment. The two ends of each route stay at their plugs.\n */\nexport function pullApart(graph: SegmentGraph, options: PullApartOptions): Route[] {\n return lanePaths(graph, (s) => (s.count > 1 ? Math.min(options.spacing, options.maxWidth / (s.count - 1)) : 0));\n}\n\n/** This function gives the key of a shared run: the ids of its edges, sorted and joined with commas. */\nexport function runKey(edges: readonly string[]): string {\n return [...edges].sort().join(\",\");\n}\n\n/**\n * This function opens the shared segments whose key is in `open`: each edge of an open segment gets its own lane.\n * The lanes are `laneWidth` apart, and an open segment is at most `maxWidth` wide. The other segments stay as one way.\n *\n * Lane 0 is on the left of the segment, from its first point to its last, with the y axis down.\n * The function takes a result or its segments. It gives a route for each edge, with the ends at their plugs.\n * The key of a segment is `runKey` of its edges.\n */\nexport function laneRoutes(source: Result | SegmentGraph, open: ReadonlySet<string>, laneWidth: number, maxWidth: number = Infinity): Route[] {\n const graph = \"paths\" in source ? source : segmentsOf(source);\n if (open.size === 0) return graph.paths.map((path) => ({ edge: path.edge, points: pathPoints(graph, path) }));\n return lanePaths(graph, (s) => (s.count > 1 && open.has(runKey(s.edges)) ? Math.min(laneWidth, maxWidth / (s.count - 1)) : 0));\n}\n\n/** This function gives the route of each path, with the lanes of each segment at the spacing that `spacingOf` gives. */\nfunction lanePaths(graph: SegmentGraph, spacingOf: (s: Segment) => number): Route[] {\n const byId = new Map(graph.segments.map((s) => [s.id, s]));\n const routes: Route[] = [];\n for (const path of graph.paths) {\n const ends = pathPoints(graph, path);\n const out: Point[] = [];\n for (const ref of path.segments) {\n const s = byId.get(ref.segment);\n if (!s) continue;\n const spacing = spacingOf(s);\n const moved = offsetPolyline(s.points, ((s.count - 1) / 2 - ref.lane) * spacing);\n for (const q of ref.reverse ? moved.reverse() : moved) if (out.length === 0 || dist(q, out[out.length - 1]!) > SAME) out.push(q);\n }\n if (out.length >= 2 && ends.length >= 2) {\n out[0] = ends[0]!;\n out[out.length - 1] = ends[ends.length - 1]!;\n }\n routes.push({ edge: path.edge, points: out });\n }\n return routes;\n}\n\n/** The angle, from -π to π, of the turn at `base` from the direction `from` → `base` to the point `to`. */\nfunction turn(from: Point, base: Point, to: Point): number {\n const dx = base.x - from.x;\n const dy = base.y - from.y;\n const vx = to.x - base.x;\n const vy = to.y - base.y;\n return Math.atan2(dx * vy - dy * vx, dx * vx + dy * vy);\n}\n\n/**\n * This function gives the lane order of the edges on a shared way `run` (metro-line order). Two routes go on together\n * past the last point of the run until they part. The route that turns more to the left there gets the lane more to the left.\n * Two routes can part only before the first point. Then the route that comes from more to the left gets the lane more to the left.\n * A route that does not hold the run goes last.\n */\nexport function orderLanes(run: readonly Point[], routes: readonly Route[]): string[] {\n const placed: { edge: string; p: readonly Point[]; s: number; e: number }[] = [];\n const lost: string[] = [];\n for (const r of routes) {\n let at = indexOf(r.points, run, 0);\n if (at >= 0) placed.push({ edge: r.edge, p: r.points, s: at, e: at + run.length - 1 });\n else {\n const p = [...r.points].reverse();\n at = indexOf(p, run, 0);\n if (at >= 0) placed.push({ edge: r.edge, p, s: at, e: at + run.length - 1 });\n else lost.push(r.edge);\n }\n }\n const same = (a: Point, b: Point): boolean => dist(a, b) <= SAME;\n placed.sort((P, Q) => {\n for (let j = 1; ; j++) {\n const a = P.p[P.e + j];\n const b = Q.p[Q.e + j];\n if (a === undefined || b === undefined) break;\n if (!same(a, b)) {\n const d = turn(P.p[P.e + j - 2]!, P.p[P.e + j - 1]!, a) - turn(P.p[P.e + j - 2]!, P.p[P.e + j - 1]!, b);\n if (d !== 0) return d;\n break;\n }\n }\n for (let j = 1; ; j++) {\n const a = P.p[P.s - j];\n const b = Q.p[Q.s - j];\n if (a === undefined || b === undefined) break;\n if (!same(a, b)) {\n // Seen backward, the left side is the right side. Thus the order turns around.\n const d = turn(P.p[P.s - j + 2]!, P.p[P.s - j + 1]!, b) - turn(P.p[P.s - j + 2]!, P.p[P.s - j + 1]!, a);\n if (d !== 0) return d;\n break;\n }\n }\n return P.edge < Q.edge ? -1 : P.edge > Q.edge ? 1 : 0;\n });\n return [...placed.map((x) => x.edge), ...lost.sort()];\n}\n","import { center, type Box } from \"./geom.ts\";\nimport type { Node } from \"./model.ts\";\n\n/** A section of the plane: a cell of a quadtree, with the nodes whose centers are in it. */\nexport interface Section {\n /** The path from the root: \"s\", then one digit from 0 to 3 for each step down. */\n readonly id: string;\n readonly depth: number;\n readonly cell: Box;\n /** The indices of the nodes, in the order of the graph. */\n readonly nodes: readonly number[];\n readonly children: readonly Section[];\n}\n\n/** The options of the tree of sections. */\nexport interface SectionOptions {\n /** A section with more nodes splits. The default is 8. */\n readonly cap?: number;\n /** The tree stops at this depth. The default is 16. */\n readonly maxDepth?: number;\n}\n\n/**\n * This function makes the tree of sections of the nodes. A cell with more than `cap` nodes splits in four.\n * When the nodes of a cell are all in one quarter, the cell becomes that quarter and does not make a level.\n */\nexport function buildSections(nodes: readonly Node[], options: SectionOptions = {}): Section {\n const cap = Math.max(1, options.cap ?? 8);\n const maxDepth = options.maxDepth ?? 16;\n const centers = nodes.map((n) => center(n.box));\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const n of nodes) {\n x0 = Math.min(x0, n.box.x);\n y0 = Math.min(y0, n.box.y);\n x1 = Math.max(x1, n.box.x + n.box.w);\n y1 = Math.max(y1, n.box.y + n.box.h);\n }\n const root: Box = nodes.length ? { x: x0, y: y0, w: x1 - x0, h: y1 - y0 } : { x: 0, y: 0, w: 0, h: 0 };\n const make = (id: string, depth: number, cell: Box, list: readonly number[]): Section => {\n let box = cell;\n for (let guard = 0; list.length > cap && depth < maxDepth && guard < 32; guard++) {\n const mx = box.x + box.w / 2;\n const my = box.y + box.h / 2;\n const parts: number[][] = [[], [], [], []];\n for (const i of list) parts[(centers[i]!.x < mx ? 0 : 1) + (centers[i]!.y < my ? 0 : 2)]!.push(i);\n const quarter = (q: number): Box => ({\n x: q % 2 === 0 ? box.x : mx,\n y: q < 2 ? box.y : my,\n w: box.w / 2,\n h: box.h / 2,\n });\n const full = parts.map((p, q) => [p, q] as const).filter(([p]) => p.length > 0);\n if (full.length === 1) {\n box = quarter(full[0]![1]);\n continue;\n }\n const children = full.map(([p, q]) => make(`${id}${q}`, depth + 1, quarter(q), p));\n return { id, depth, cell: box, nodes: list, children };\n }\n return { id, depth, cell: box, nodes: list, children: [] };\n };\n return make(\"s\", 0, root, nodes.map((_, i) => i));\n}\n\n/** This function gives the sections of the tree, parents before children. */\nexport function allSections(root: Section): Section[] {\n const out: Section[] = [];\n const walk = (s: Section): void => {\n out.push(s);\n for (const c of s.children) walk(c);\n };\n walk(root);\n return out;\n}\n\n/** This function gives the depth of the deepest section. */\nexport function treeDepth(root: Section): number {\n return root.children.reduce((d, c) => Math.max(d, treeDepth(c)), root.depth);\n}\n","import { center } from \"../geom.ts\";\nimport { nodeIndex, type Graph, type Node, type Result, type Route, type Router } from \"../model.ts\";\nimport { placePlug } from \"../plugs.ts\";\nimport { WayFinder, type WayOptions } from \"../ways.ts\";\n\n/** The options of the corner router. */\nexport interface CornersOptions extends WayOptions {\n /** The name in the benchmark. */\n readonly name: string;\n /** The benchmark skips a fixture with more nodes. */\n readonly maxNodes?: number;\n}\n\n/**\n * This function makes a router that goes around the nodes.\n * Each edge leaves its plug along the normal of the side. It goes a shortest way (A*) through a sparse visibility graph\n * of the box corners, without the needless corners. It enters the target plug along its normal.\n */\nexport function cornersRouter(options: CornersOptions): Router {\n const router: Router = {\n name: options.name,\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const ways = new WayFinder(graph.nodes, options);\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n }\n return { routes };\n },\n };\n return options.maxNodes === undefined ? router : { ...router, maxNodes: options.maxNodes };\n}\n","import { inflectionCurve } from \"../curves.ts\";\nimport { center } from \"../geom.ts\";\nimport { nodeIndex, type Graph, type Result, type Route, type Router } from \"../model.ts\";\nimport { placePlug } from \"../plugs.ts\";\n\n/**\n * Plugs and the inflection rule, with no obstacles. Each edge leaves its source plug at the tangent of the side.\n * It goes to the target plug on the curve of the rule. This router measures the rule alone.\n */\nexport const plugsRouter: Router = {\n name: \"plugs\",\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n routes.push({ edge: e.id, points: inflectionCurve(ps.point, ps.normal, pt.point) });\n }\n return { routes };\n },\n};\n","import { dist, inflate, pointSegmentDistance, polylineLength, segmentHitsBox, type Box, type Point } from \"../geom.ts\";\nimport { Grid } from \"../grid.ts\";\nimport type { Graph, Level, Result } from \"../model.ts\";\nimport { TOLERANCE } from \"./properties.ts\";\n\n/**\n * The faults of a set of links: the routes of the edges, or the links of one zoom level.\n * Each value counts links, except `worstDetour`. Lower is better for each value.\n */\nexport interface LinkFaults {\n /** The number of links that the measure examined. */\n readonly links: number;\n /**\n * The number of links that go through the inside of a box that is not one of their two ends.\n * A segment goes through a box when a part of it longer than `TOLERANCE` is inside the box made smaller by `TOLERANCE`.\n */\n readonly through: number;\n /**\n * The number of links that go out and back. The distance from a point of the link to its last point grows after the nearest approach.\n * A link goes out and back when this growth is more than `BACKTRACK_SHARE` of the distance between its ends, and more than `BACKTRACK_MIN` units.\n */\n readonly backtrack: number;\n /** The largest ratio of the length of a link to the distance between its ends. Links with ends nearer than 1 unit do not count. */\n readonly worstDetour: number;\n /**\n * The number of links with a point outside the bounding box of all the boxes, made larger by `slack`.\n * Both ends of a link are always in that bounding box, so such a link goes around the outer edge of the board.\n */\n readonly outside: number;\n}\n\n/** The faults of the links of one zoom level. */\nexport interface LevelFaults extends LinkFaults {\n readonly depth: number;\n /** The number of items of the level. */\n readonly items: number;\n /** The number of items that hold more than one node. */\n readonly groups: number;\n /** The number of pairs of items whose boxes overlap by more than `TOLERANCE` on each axis. */\n readonly overlaps: number;\n}\n\n/** The options of the link measures. */\nexport interface LinkFaultOptions {\n /** A link that goes farther than this distance outside the bounding box of all the boxes counts in `outside`. The default is 24. */\n readonly slack?: number;\n}\n\n/** A link goes out and back when its distance to its target grows by more than this share of the distance between its ends. */\nexport const BACKTRACK_SHARE = 0.25;\n/** A link goes out and back only when its distance to its target grows by more than this number of units. */\nexport const BACKTRACK_MIN = 40;\n/** The default `slack` of `LinkFaultOptions`. */\nexport const OUTSIDE_SLACK = 24;\n\n/** A link from one box to another box, as `measureLinks` sees it. */\nexport interface MeasuredLink {\n readonly source: string;\n readonly target: string;\n readonly points: readonly Point[];\n}\n\n/**\n * This function gives the largest growth of the distance to the last point of a polyline.\n * The growth at a vertex is its distance to the last point, less the nearest approach of the polyline before that vertex.\n */\nexport function backtrackOf(p: readonly Point[]): number {\n if (p.length < 3) return 0;\n const end = p[p.length - 1]!;\n let near = dist(p[0]!, end);\n let worst = 0;\n for (let i = 1; i < p.length; i++) {\n worst = Math.max(worst, dist(p[i]!, end) - near);\n near = Math.min(near, pointSegmentDistance(end, p[i - 1]!, p[i]!));\n }\n return worst;\n}\n\n/** This function tells if the polyline `p` goes out and back: `backtrackOf(p)` is more than `BACKTRACK_MIN` and more than `BACKTRACK_SHARE` of the span. */\nexport function goesOutAndBack(p: readonly Point[]): boolean {\n if (p.length < 3) return false;\n const span = dist(p[0]!, p[p.length - 1]!);\n return backtrackOf(p) > Math.max(BACKTRACK_MIN, BACKTRACK_SHARE * span);\n}\n\n/**\n * This function measures the faults of links between boxes. The map `boxes` gives the box of each end.\n * The bounding box of `outside` is the bounding box of all the boxes of the map.\n */\nexport function measureLinks(boxes: ReadonlyMap<string, Box>, links: readonly MeasuredLink[], options: LinkFaultOptions = {}): LinkFaults {\n const slack = options.slack ?? OUTSIDE_SLACK;\n let size = 0;\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const b of boxes.values()) {\n size += Math.max(b.w, b.h);\n x0 = Math.min(x0, b.x);\n y0 = Math.min(y0, b.y);\n x1 = Math.max(x1, b.x + b.w);\n y1 = Math.max(y1, b.y + b.h);\n }\n // Large items cover many buckets of a small grid, so the buckets grow with the items.\n const grid = new Grid<string>(Math.max(180, (2 * size) / Math.max(1, boxes.size)));\n for (const [id, b] of boxes) grid.add(id, b);\n let through = 0;\n let backtrack = 0;\n let worstDetour = 0;\n let outside = 0;\n for (const l of links) {\n const p = l.points;\n if (p.length === 0) continue;\n let hit = false;\n for (let i = 1; i < p.length && !hit; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n grid.querySegment(a, b, 0, (id) => {\n if (!hit && id !== l.source && id !== l.target && segmentHitsBox(a, b, inflate(boxes.get(id)!, -TOLERANCE), TOLERANCE)) hit = true;\n });\n }\n if (hit) through++;\n if (goesOutAndBack(p)) backtrack++;\n const span = dist(p[0]!, p[p.length - 1]!);\n if (span > 1) worstDetour = Math.max(worstDetour, polylineLength(p) / span);\n if (p.some((q) => q.x < x0 - slack || q.x > x1 + slack || q.y < y0 - slack || q.y > y1 + slack)) outside++;\n }\n return { links: links.length, through, backtrack, worstDetour, outside };\n}\n\n/** This function measures the faults of the routes of a result. The ends of a route are the nodes of its edge. */\nexport function measureRouteFaults(graph: Graph, result: Result, options: LinkFaultOptions = {}): LinkFaults {\n const boxes = new Map(graph.nodes.map((n) => [n.id, n.box]));\n const edges = new Map(graph.edges.map((e) => [e.id, e]));\n const links: MeasuredLink[] = [];\n for (const r of result.routes) {\n const e = edges.get(r.edge);\n if (e) links.push({ source: e.source.node, target: e.target.node, points: r.points });\n }\n return measureLinks(boxes, links, options);\n}\n\n/** This function counts the pairs of boxes that overlap by more than `TOLERANCE` on each axis. */\nexport function countOverlaps(boxes: readonly Box[]): number {\n let size = 0;\n for (const b of boxes) size += Math.max(b.w, b.h);\n const grid = new Grid<number>(Math.max(180, (2 * size) / Math.max(1, boxes.length)));\n boxes.forEach((b, i) => grid.add(i, b));\n let n = 0;\n boxes.forEach((a, i) => {\n grid.query(a, (j) => {\n const b = boxes[j]!;\n if (j > i && Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x) > TOLERANCE && Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y) > TOLERANCE) n++;\n });\n });\n return n;\n}\n\n/** This function measures the faults of the links of one zoom level. The items of the level are the boxes. */\nexport function measureLevel(level: Level, options: LinkFaultOptions = {}): LevelFaults {\n const boxes = new Map(level.items.map((i) => [i.id, i.box]));\n return {\n depth: level.depth,\n items: level.items.length,\n groups: level.items.filter((i) => i.nodes.length > 1).length,\n overlaps: countOverlaps(level.items.map((i) => i.box)),\n ...measureLinks(boxes, level.links, options),\n };\n}\n\n/**\n * This function measures the faults of each zoom level of a result that has groups: the levels of the far view.\n * A level of single nodes only is the near view. Its links are routes, and `measureRouteFaults` measures them.\n */\nexport function measureLevelFaults(result: Result, options: LinkFaultOptions = {}): LevelFaults[] {\n return (result.levels ?? []).filter((l) => l.items.some((i) => i.nodes.length > 1)).map((l) => measureLevel(l, options));\n}\n\n/** This function adds the faults of several levels: it sums the counts and keeps the largest `worstDetour`. */\nexport function sumFaults(list: readonly LinkFaults[]): LinkFaults {\n return list.reduce<LinkFaults>(\n (s, f) => ({\n links: s.links + f.links,\n through: s.through + f.through,\n backtrack: s.backtrack + f.backtrack,\n worstDetour: Math.max(s.worstDetour, f.worstDetour),\n outside: s.outside + f.outside,\n }),\n { links: 0, through: 0, backtrack: 0, worstDetour: 0, outside: 0 },\n );\n}\n","import { center, dist, polylineLength, type Box, type Point } from \"./geom.ts\";\nimport type { LevelItem, LevelLink, Node, Side } from \"./model.ts\";\nimport { pointOnSide, SIDE_NORMAL, sideToward, type Plug } from \"./plugs.ts\";\nimport { CornerGraph, Obstacles } from \"./visibility.ts\";\nimport type { WayFinder, WayOptions } from \"./ways.ts\";\n\n/** Two items of a level that a link joins, and the count of the edges between them. */\nexport interface ItemPair {\n readonly source: string;\n readonly target: string;\n readonly count: number;\n}\n\n/** The parts of a way finder that a link uses. */\ntype Ways = Pick<WayFinder, \"obstacles\" | \"corners\" | \"margin\" | \"out\">;\n\n/** The free plugs of a node, and the reach of each plug. */\ninterface FreePlugs {\n readonly plugs: readonly Plug[];\n readonly reach: readonly number[];\n}\n\n/** The ways of a level, with a second corner graph and the free plugs of the nodes. */\ninterface LevelWays extends Ways {\n /** This function gives a second corner graph with a small margin. The first link that needs it makes it. */\n readonly tight: () => CornerGraph;\n /** The free plugs of each node that a link needed. */\n readonly free: Map<Node, FreePlugs>;\n}\n\n/** The margin of the second corner graph. A gap between two boxes wider than approximately 1.5 times this margin lets a link through. */\nconst TIGHT_MARGIN = 1;\n\nconst EPS = 1e-6;\n\n/**\n * This function removes the repeated points, the points in the middle of a straight run,\n * and the points where the way turns back on itself.\n */\nfunction tidy(p: readonly Point[]): Point[] {\n const out: Point[] = [];\n for (const q of p) {\n if (out.length > 0 && dist(q, out[out.length - 1]!) <= EPS) continue;\n while (out.length >= 2) {\n const a = out[out.length - 2]!;\n const b = out[out.length - 1]!;\n const cross = (b.x - a.x) * (q.y - b.y) - (b.y - a.y) * (q.x - b.x);\n if (Math.abs(cross) > EPS * (1 + dist(a, b) * dist(b, q))) break;\n // The point b is on the line through a and q: in the middle of a straight run, or at the tip of a turn back.\n out.pop();\n }\n if (out.length > 0 && dist(q, out[out.length - 1]!) <= EPS) continue;\n out.push(q);\n }\n return out;\n}\n\n/**\n * This function gives the links of one level. The items of the level are the obstacles.\n * A link starts on the boundary of the box of its source and ends on the boundary of the box of its target.\n * It goes around the boxes of the other items. Where there is space, its legs are parallel to the axes.\n */\nexport function levelLinks(items: readonly LevelItem[], pairs: readonly ItemPair[], options: WayOptions = {}): LevelLink[] {\n if (pairs.length === 0) return [];\n const nodes: Node[] = items.map((i) => ({ id: i.id, box: i.box }));\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const ways = levelWays(nodes, options);\n const inset = Math.min(6, ways.margin);\n const out: LevelLink[] = [];\n for (const p of pairs) {\n const s = byId.get(p.source);\n const t = byId.get(p.target);\n if (!s || !t) continue;\n // Two items with a clear way between their facing sides get the short way.\n const [fs, ft] = facingPlugs(s.box, t.box, inset);\n let points = isFree(ways, s, fs) && isFree(ways, t, ft) ? quickWay(ways, ends(ways, s, fs, t, ft)) : undefined;\n // Else the link goes from the middle of a side. Each item has at most four such plugs, so the corner graph finds their ends one time.\n points ??= sideWay(ways, s, t, inset);\n out.push({ source: p.source, target: p.target, count: p.count, points });\n }\n return out;\n}\n\n/**\n * This function gives a way from plug to plug between the plugs at the middle of a side of the two nodes.\n * Without a way in the corner graph, the link goes straight between the ends, with legs parallel to the axes where they are clear.\n * When that line goes through another box, the link goes between the free plugs of the two nodes (`freeWay`) instead.\n */\nfunction sideWay(ways: LevelWays, s: Node, t: Node, inset: number): Point[] {\n const e = ends(ways, s, sidePlug(ways, s, center(t.box)), t, sidePlug(ways, t, center(s.box)));\n const quick = quickWay(ways, e);\n if (quick) return quick;\n const path = ways.corners.path(e.a, e.b);\n const way = pulled(ways, e.ps, path ?? [e.a, e.b], e.pt);\n if (path || ways.obstacles.clearPath(way, 0, new Set([s, t]))) return way;\n return freeWay(ways, s, t, inset) ?? way;\n}\n\n/**\n * This function makes the obstacles and the corner graph of the items of a level.\n * The buckets of the obstacles grow with the items, so a long link visits few buckets.\n * The corner graphs use `cones`, so a link goes along the corridors between the groups, not around the outer edge of the board.\n */\nfunction levelWays(nodes: readonly Node[], options: WayOptions): LevelWays {\n const margin = options.margin ?? 5;\n const k = options.k ?? 8;\n let size = 0;\n for (const n of nodes) size += Math.max(n.box.w, n.box.h);\n const obstacles = new Obstacles(nodes, Math.max(180, (2 * size) / Math.max(1, nodes.length)));\n const corners = new CornerGraph(nodes, obstacles, { margin, k, cones: true });\n const out = (p: Plug): Point => ({ x: p.point.x + p.normal.x * margin, y: p.point.y + p.normal.y * margin });\n let tight: CornerGraph | undefined;\n const tightGraph = (): CornerGraph => (tight ??= new CornerGraph(nodes, obstacles, { margin: Math.min(margin, TIGHT_MARGIN), k, cones: true }));\n return { obstacles, corners, margin, out, tight: tightGraph, free: new Map() };\n}\n\n/**\n * This function gives the plugs of a link between two boxes. Each plug is on the side that faces the other box.\n * When the two sides face each other and their spans overlap, both plugs are at the middle of the overlap, so the link is straight.\n */\nexport function facingPlugs(a: Box, b: Box, inset: number): [Plug, Plug] {\n const sa = sideToward(a, center(b));\n const sb = sideToward(b, center(a));\n const plug = (box: Box, side: Side, toward: Point): Plug => ({ point: pointOnSide(box, side, toward, inset), normal: SIDE_NORMAL[side] });\n const across = (sa === \"east\" && sb === \"west\") || (sa === \"west\" && sb === \"east\");\n const down = (sa === \"south\" && sb === \"north\") || (sa === \"north\" && sb === \"south\");\n if (across || down) {\n const lo = across ? Math.max(a.y, b.y) + inset : Math.max(a.x, b.x) + inset;\n const hi = across ? Math.min(a.y + a.h, b.y + b.h) - inset : Math.min(a.x + a.w, b.x + b.w) - inset;\n if (lo <= hi) {\n const ca = center(a);\n const cb = center(b);\n const m = Math.max(lo, Math.min(hi, across ? (ca.y + cb.y) / 2 : (ca.x + cb.x) / 2));\n const at = (box: Box, side: Side): Point =>\n across\n ? { x: side === \"east\" ? box.x + box.w : box.x, y: m }\n : { x: m, y: side === \"south\" ? box.y + box.h : box.y };\n return [\n { point: at(a, sa), normal: SIDE_NORMAL[sa] },\n { point: at(b, sb), normal: SIDE_NORMAL[sb] },\n ];\n }\n }\n return [plug(a, sa, center(b)), plug(b, sb, center(a))];\n}\n\nconst SIDES: readonly Side[] = [\"north\", \"east\", \"south\", \"west\"];\n\n/** This function tells if the way out of a plug is free. The plug and the point at `margin` from it are in no other box. */\nfunction isFree(ways: Ways, node: Node, plug: Plug): boolean {\n return !ways.obstacles.inside(ways.out(plug), 0, node) && !ways.obstacles.inside(plug.point, 0, node);\n}\n\n/** This function gives the plug at the middle of a side of the node: the side with a free way out that faces `toward` most. */\nfunction sidePlug(ways: Ways, node: Node, toward: Point): Plug {\n const b = node.box;\n const c = center(b);\n const d = { x: toward.x - c.x, y: toward.y - c.y };\n const facing = (s: Side): number => SIDE_NORMAL[s].x * d.x + SIDE_NORMAL[s].y * d.y;\n const order = [...SIDES].sort((u, v) => facing(v) - facing(u));\n const plug = (s: Side): Plug => {\n const n = SIDE_NORMAL[s];\n return { point: { x: c.x + (n.x * b.w) / 2, y: c.y + (n.y * b.h) / 2 }, normal: n };\n };\n for (const s of order) if (isFree(ways, node, plug(s))) return plug(s);\n return plug(order[0]!);\n}\n\n/**\n * This function gives the free plugs of a node: on each side, the free point nearest to the middle of the side.\n * A point is free when it and the point at `margin` from it are in no other box. The function keeps the plugs of each node.\n */\nfunction freePlugs(ways: LevelWays, node: Node, inset: number): FreePlugs {\n const known = ways.free.get(node);\n if (known) return known;\n const b = node.box;\n const out: Plug[] = [];\n for (const side of SIDES) {\n const n = SIDE_NORMAL[side];\n const across = n.x === 0;\n // The side goes from `lo` to `hi` along its axis, at the coordinate `at` of the other axis.\n const lo = across ? b.x : b.y;\n const hi = across ? b.x + b.w : b.y + b.h;\n const at = across ? (n.y > 0 ? b.y + b.h : b.y) : n.x > 0 ? b.x + b.w : b.x;\n const far = at + (across ? n.y : n.x) * ways.margin;\n // A box covers a point of the side when the point or its way out is inside the box, as in `isFree`.\n const covered: [number, number][] = [];\n const strip = across\n ? { x: lo, y: Math.min(at, far), w: hi - lo, h: Math.abs(far - at) }\n : { x: Math.min(at, far), y: lo, w: Math.abs(far - at), h: hi - lo };\n ways.obstacles.query(strip, (m) => {\n if (m === node) return;\n const o = m.box;\n const [o0, o1, p0, p1] = across ? [o.x, o.x + o.w, o.y, o.y + o.h] : [o.y, o.y + o.h, o.x, o.x + o.w];\n if ((at > p0 && at < p1) || (far > p0 && far < p1)) covered.push([o0, o1]);\n });\n const mid = (lo + hi) / 2;\n let best: number | undefined;\n for (const [f0, f1] of freeSpans(lo, hi, covered)) {\n const room = Math.min(inset, (f1 - f0) / 2);\n const u = Math.max(f0 + room, Math.min(f1 - room, mid));\n if (best === undefined || Math.abs(u - mid) < Math.abs(best - mid)) best = u;\n }\n if (best !== undefined) out.push({ point: across ? { x: best, y: at } : { x: at, y: best }, normal: n });\n }\n const free = { plugs: out, reach: out.map((p) => reach(ways, node, p)) };\n ways.free.set(node, free);\n return free;\n}\n\n/** This function gives the indices of the plugs, and the plugs that face `toward` most come first. */\nfunction facingOrder(plugs: readonly Plug[], from: Point, toward: Point): number[] {\n const facing = (p: Plug): number => p.normal.x * (toward.x - from.x) + p.normal.y * (toward.y - from.y);\n return plugs.map((_, i) => i).sort((u, v) => facing(plugs[v]!) - facing(plugs[u]!) || u - v);\n}\n\n/** This function gives the parts of the span from `lo` to `hi` outside each open interval of `covered`. A part of zero length does not count. */\nfunction freeSpans(lo: number, hi: number, covered: [number, number][]): [number, number][] {\n covered.sort((u, v) => u[0] - v[0]);\n const out: [number, number][] = [];\n let x = lo;\n for (const [c0, c1] of covered) {\n if (c0 > x) out.push([x, Math.min(c0, hi)]);\n x = Math.max(x, c1);\n if (x >= hi) break;\n }\n if (x < hi) out.push([x, hi]);\n return out.filter(([a, b]) => b - a > EPS);\n}\n\n/**\n * This function gives the shortest way between the free plugs of the two nodes, or `undefined` when the second corner graph has none.\n * A link uses it when its plugs at the middle of a side find no way. Other boxes can cover such a plug, or close the space in front of it.\n */\nfunction freeWay(ways: LevelWays, s: Node, t: Node, inset: number): Point[] | undefined {\n const fs = freePlugs(ways, s, inset);\n const ft = freePlugs(ways, t, inset);\n const cs = center(s.box);\n const ct = center(t.box);\n const is = facingOrder(fs.plugs, cs, ct);\n const it = facingOrder(ft.plugs, ct, cs);\n const from = is.map((i) => fs.plugs[i]!);\n const to = it.map((k) => ft.plugs[k]!);\n const ra = is.map((i) => fs.reach[i]!);\n const rb = it.map((k) => ft.reach[k]!);\n // A pair of plugs with one or two clear legs between them gives the short way.\n let best: Point[] | undefined;\n let bestLength = Infinity;\n from.forEach((ps, i) =>\n to.forEach((pt, k) => {\n const way = quickWay(ways, endsAt(ps, ra[i]!, pt, rb[k]!));\n const length = way ? polylineLength(way) : Infinity;\n if (length < bestLength) {\n best = way;\n bestLength = length;\n }\n }),\n );\n if (best) return best;\n // Else one search of the second corner graph finds the shortest way from a plug of `s` to a plug of `t`.\n // The corners of the second graph are near the boxes, so the way can go through a gap that is narrower than the margin.\n const a = from.map((ps, i) => ({ point: along(ps, ra[i]!), cost: ra[i]! }));\n const b = to.map((pt, k) => ({ point: along(pt, rb[k]!), cost: rb[k]! }));\n const found = ways.tight().pathAmong(a, b);\n return found && pulled(ways, from[found.from]!, found.points, to[found.to]!);\n}\n\n/** The two ends of a link: each plug, and the point where the link turns away from the normal of the plug. */\ninterface Ends {\n readonly ps: Plug;\n readonly pt: Plug;\n readonly a: Point;\n readonly b: Point;\n}\n\n/**\n * This function gives the ends of a link. The link leaves each plug along its normal for the margin.\n * A box can be nearer than twice the margin in front of a plug. Then the link turns in the middle of the space before that box.\n * Two plugs that face each other across a narrow space make the link turn in the middle of that space.\n */\nfunction ends(ways: Ways, s: Node, ps: Plug, t: Node, pt: Plug): Ends {\n return endsAt(ps, reach(ways, s, ps), pt, reach(ways, t, pt));\n}\n\n/** This function gives the ends of a link from the plug `ps` to the plug `pt`, with the reach of each plug. */\nfunction endsAt(ps: Plug, ra: number, pt: Plug, rb: number): Ends {\n // Two plugs that face each other turn at the same distance, so the link does not go past itself.\n if (ps.normal.x === -pt.normal.x && ps.normal.y === -pt.normal.y) {\n const d = (pt.point.x - ps.point.x) * ps.normal.x + (pt.point.y - ps.point.y) * ps.normal.y;\n if (d > 0 && ra + rb > d) ra = rb = d / 2;\n }\n return { ps, pt, a: along(ps, ra), b: along(pt, rb) };\n}\n\nconst along = (p: Plug, d: number): Point => ({ x: p.point.x + p.normal.x * d, y: p.point.y + p.normal.y * d });\n\n/** This function gives the distance that a link goes along the normal of a plug before it turns. */\nfunction reach(ways: Ways, node: Node, plug: Plug): number {\n const skip = new Set([node]);\n const far = 2 * ways.margin;\n if (ways.obstacles.clear(plug.point, along(plug, far), 0, skip)) return ways.margin;\n let lo = 0;\n let hi = far;\n for (let i = 0; i < 10; i++) {\n const m = (lo + hi) / 2;\n if (ways.obstacles.clear(plug.point, along(plug, m), 0, skip)) lo = m;\n else hi = m;\n }\n return lo / 2;\n}\n\n/**\n * This function gives the way between the ends when one or two legs parallel to the axes are clear, or `undefined`.\n * The legs keep half the margin from the boxes, or less when an end turns nearer to a box.\n */\nfunction quickWay(ways: Ways, e: Ends): Point[] | undefined {\n const near = Math.min(dist(e.ps.point, e.a), dist(e.pt.point, e.b));\n const pad = Math.max(0, Math.min(ways.margin / 2, near - 1));\n const legs = square(e.a, e.b, ways.obstacles, pad, axisOf(e.ps.normal), axisOf(e.pt.normal));\n return legs && tidy([e.ps.point, e.a, ...legs, e.pt.point]);\n}\n\n/**\n * This function gives a way from the plug `ps` through the points of `path` to the plug `pt`.\n * The way leaves and enters each plug along its normal. Then it pulls the corners tight with legs that are parallel to the axes, where the obstacles let it.\n */\nfunction pulled(ways: Ways, ps: Plug, path: readonly Point[], pt: Plug): Point[] {\n const legs = squarePull(path, ways.obstacles, ways.margin / 2, axisOf(ps.normal), axisOf(pt.normal));\n return tidy([ps.point, ...legs, pt.point]);\n}\n\ntype Axis = \"x\" | \"y\";\n\nconst axisOf = (n: Point): Axis => (Math.abs(n.x) > Math.abs(n.y) ? \"x\" : \"y\");\n\n/**\n * This function pulls a path tight. From each vertex, it goes to the farthest vertex that one or two legs can reach.\n * These legs are parallel to the axes and clear of the obstacles by `pad`. It keeps a diagonal leg only where no such legs are clear.\n * `first` is the axis of the way into the first vertex, and `last` is the axis of the way out of the last vertex.\n */\nfunction squarePull(p: readonly Point[], obstacles: Obstacles, pad: number, first: Axis, last: Axis, lookahead = 16): Point[] {\n if (p.length === 0) return [];\n const out: Point[] = [p[0]!];\n let axis: Axis | undefined = first;\n let i = 0;\n while (i < p.length - 1) {\n let step: { j: number; legs: Point[] } | undefined;\n for (let j = Math.min(p.length - 1, i + lookahead); j > i && !step; j--) {\n const legs = square(p[i]!, p[j]!, obstacles, pad, axis, j === p.length - 1 ? last : undefined);\n if (legs) step = { j, legs };\n }\n // With no clear legs to the next vertex, the legs may touch a box, but they do not go through it.\n step ??= {\n j: i + 1,\n legs: square(p[i]!, p[i + 1]!, obstacles, 0, axis, i + 1 === p.length - 1 ? last : undefined) ?? [p[i + 1]!],\n };\n out.push(...step.legs);\n const end = out[out.length - 1]!;\n const before = out[out.length - 2]!;\n axis = Math.abs(end.y - before.y) < EPS ? \"x\" : Math.abs(end.x - before.x) < EPS ? \"y\" : undefined;\n i = step.j;\n }\n return out;\n}\n\n/**\n * This function gives one or two legs parallel to the axes from `a` to `b`, clear of the obstacles by `pad`, or `undefined`.\n * Of two clear corners, it picks the corner that continues the axis `from` and arrives along the axis `to`.\n */\nfunction square(a: Point, b: Point, obstacles: Obstacles, pad: number, from: Axis | undefined, to: Axis | undefined): Point[] | undefined {\n if (Math.abs(a.x - b.x) < EPS || Math.abs(a.y - b.y) < EPS) return obstacles.clear(a, b, pad) ? [b] : undefined;\n // The corner of `x` goes along the x axis first, and the corner of `y` along the y axis first.\n const options: { c: Point; bends: number }[] = [\n { c: { x: b.x, y: a.y }, bends: (from === \"y\" ? 1 : 0) + (to === \"x\" ? 1 : 0) },\n { c: { x: a.x, y: b.y }, bends: (from === \"x\" ? 1 : 0) + (to === \"y\" ? 1 : 0) },\n ];\n options.sort((u, v) => u.bends - v.bends);\n for (const { c } of options) if (obstacles.clear(a, c, pad) && obstacles.clear(c, b, pad)) return [c, b];\n return undefined;\n}\n","import { BACKTRACK_MIN, goesOutAndBack } from \"../bench/links.ts\";\nimport { center, dist, pointSegmentDistance, polylineLength, type Box, type Point } from \"../geom.ts\";\nimport { levelLinks, type ItemPair } from \"../levels.ts\";\nimport { nodeIndex, type Graph, type Level, type LevelItem, type Node, type Result, type Route, type Router, type SharedRun } from \"../model.ts\";\nimport { placePlug } from \"../plugs.ts\";\nimport { allSections, buildSections, treeDepth, type Section, type SectionOptions } from \"../sections.ts\";\nimport { orderLanes } from \"../segments.ts\";\nimport { WayFinder, type WayOptions } from \"../ways.ts\";\n\n/** The options of the router with sections. */\nexport interface SectionsOptions extends WayOptions, SectionOptions {\n /** The name in the benchmark. */\n readonly name: string;\n /**\n * The number of hubs on each side of the lowest common section that a way passes. A smaller number gives shorter ways\n * and fewer shared ways. Without it, a way passes each hub from its node up.\n */\n readonly hubs?: number;\n /** A way through the hubs can be at most this many times as long as the line between its plugs. Else the edge goes directly. The default is 2. */\n readonly stretch?: number;\n /** The benchmark skips a fixture with more nodes. */\n readonly maxNodes?: number;\n}\n\nconst dedupe = (p: readonly Point[]): Point[] => p.filter((q, i) => i === 0 || dist(q, p[i - 1]!) > 1e-9);\n\n/**\n * A hub can be this many units farther from the target than the nearest approach of the way before it.\n * A hub farther away goes out and back, so the way skips it.\n */\nconst HUB_SLACK = 2 * BACKTRACK_MIN;\n\n/**\n * This function makes a router with a tree of sections. Each section has a hub: the free corner nearest to the center of its nodes.\n * An edge goes from its node up the hubs of its sections to the lowest common section, across, and down to the other node.\n * Each way from hub to hub is found one time, so all the edges on it share its points.\n * The edges in one section of the lowest level go straight around the nodes.\n *\n * An edge skips a hub that takes it away from its target. A way that still goes out and back gives way to the direct way.\n *\n * The result gives one zoom level for each depth of the tree.\n * A link of a level goes from the boundary of one item to the boundary of the other, around the other items.\n */\nexport function sectionsRouter(options: SectionsOptions): Router {\n const router: Router = {\n name: options.name,\n route(graph: Graph): Result {\n const stretch = options.stretch ?? 2;\n const byId = nodeIndex(graph);\n const indexOfNode = new Map(graph.nodes.map((n, i) => [n.id, i]));\n const ways = new WayFinder(graph.nodes, options);\n const corners = ways.corners;\n const root = buildSections(graph.nodes, options);\n const parent = new Map<Section, Section>();\n const leafOf: Section[] = [];\n for (const s of allSections(root)) {\n for (const c of s.children) parent.set(c, s);\n if (s.children.length === 0) for (const i of s.nodes) leafOf[i] = s;\n }\n const hubs = new Map<Section, Point>();\n const hub = (s: Section): Point => {\n let h = hubs.get(s);\n if (!h) {\n let x = 0;\n let y = 0;\n for (const i of s.nodes) {\n const c = center(graph.nodes[i]!.box);\n x += c.x;\n y += c.y;\n }\n const c = { x: x / Math.max(1, s.nodes.length), y: y / Math.max(1, s.nodes.length) };\n const j = corners.nearest(c);\n h = j >= 0 ? corners.points[j]! : c;\n hubs.set(s, h);\n }\n return h;\n };\n // The sections of the chain whose hubs do not take the way away from its target. The test uses the straight lines from hub to hub.\n const forward = (list: readonly Section[], from: Point, to: Point): Section[] => {\n const kept: Section[] = [];\n let near = dist(from, to);\n let last = from;\n for (const c of list) {\n const h = hub(c);\n if (dist(h, to) > near + HUB_SLACK) continue;\n near = Math.min(near, pointSegmentDistance(to, last, h));\n last = h;\n kept.push(c);\n }\n return kept;\n };\n const up = (s: Section): Section[] => {\n const out: Section[] = [];\n for (let x: Section | undefined = s; x; x = parent.get(x)) out.push(x);\n return out;\n };\n\n // The ways between two places, found one time. A place is a hub or a free point.\n const pieces = new Map<string, Point[]>();\n const users = new Map<string, string[]>();\n const piece = (ka: string, a: Point, kb: string, b: Point, used: string[]): Point[] => {\n const forward = ka <= kb;\n const key = forward ? `${ka}>${kb}` : `${kb}>${ka}`;\n let p = pieces.get(key);\n if (!p) {\n const [from, to] = forward ? [a, b] : [b, a];\n const way = corners.path(from, to);\n p = dedupe(way ? corners.pull(way) : [from, to]);\n pieces.set(key, p);\n }\n if (!used.includes(key)) used.push(key);\n return forward ? p : [...p].reverse();\n };\n const at = (p: Point): string => `${p.x},${p.y}`;\n\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n const iu = indexOfNode.get(e.source.node);\n const iv = indexOfNode.get(e.target.node);\n if (!s || !t || iu === undefined || iv === undefined) continue;\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n const lu = leafOf[iu]!;\n const lv = leafOf[iv]!;\n if (lu === lv) {\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n continue;\n }\n const a = up(lu);\n const b = up(lv);\n const common = new Set(b);\n const lca = a.find((x) => common.has(x))!;\n const keep = options.hubs ?? Infinity;\n const side = (list: Section[]): Section[] => list.slice(Math.max(0, list.indexOf(lca) - keep), list.indexOf(lca));\n const end = ways.out(pt);\n const start = ways.out(ps);\n const chain = forward([...side(a), ...side(b).reverse()], start, pt.point);\n if (chain.length === 0) {\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n continue;\n }\n const out: Point[] = [ps.point];\n const append = (p: readonly Point[]): void => {\n for (const q of p) if (dist(q, out[out.length - 1]!) > 1e-9) out.push(q);\n };\n const used: string[] = [];\n append(piece(at(start), start, chain[0]!.id, hub(chain[0]!), used));\n for (let i = 1; i < chain.length; i++) append(piece(chain[i - 1]!.id, hub(chain[i - 1]!), chain[i]!.id, hub(chain[i]!), used));\n append(piece(chain[chain.length - 1]!.id, hub(chain[chain.length - 1]!), at(end), end, used));\n append([pt.point]);\n // A way through the hubs that is too long, or that goes out and back, gives way to the direct way.\n if (polylineLength(out) > stretch * dist(ps.point, pt.point) + 4 * ways.margin || goesOutAndBack(out)) {\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n continue;\n }\n for (const key of used) {\n const list = users.get(key);\n if (list) list.push(e.id);\n else users.set(key, [e.id]);\n }\n routes.push({ edge: e.id, points: out });\n }\n\n const routeOf = new Map(routes.map((r) => [r.edge, r]));\n const runs: SharedRun[] = [];\n for (const [key, p] of pieces) {\n const list = users.get(key) ?? [];\n if (list.length < 2 || p.length < 2) continue;\n runs.push({ id: `r${runs.length}`, key, points: p, edges: orderLanes(p, list.map((id) => routeOf.get(id)!)) });\n }\n return { routes, runs, levels: makeLevels(graph, root, routeOf, options) };\n },\n };\n return options.maxNodes === undefined ? router : { ...router, maxNodes: options.maxNodes };\n}\n\n/**\n * This function gives one zoom level for each depth of the tree, and a last level with each node alone.\n * At depth d, a section of depth d is one item. A link joins two items and counts the edges between them.\n * In a level with groups, a link goes around the boxes of the other items (`levelLinks`).\n * In the last level, the points of a link are the route of its first edge.\n */\nfunction makeLevels(graph: Graph, root: Section, routeOf: ReadonlyMap<string, Route>, options: WayOptions): Level[] {\n const indexOfNode = new Map(graph.nodes.map((n, i) => [n.id, i]));\n const levels: Level[] = [];\n const deepest = treeDepth(root);\n for (let d = 0; d <= deepest + 1; d++) {\n const items: LevelItem[] = [];\n const itemOf: (Section | number)[] = [];\n const boxOf = (list: readonly number[]): Box => {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const i of list) {\n const b = graph.nodes[i]!.box;\n x0 = Math.min(x0, b.x);\n y0 = Math.min(y0, b.y);\n x1 = Math.max(x1, b.x + b.w);\n y1 = Math.max(y1, b.y + b.h);\n }\n return { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n };\n const visit = (s: Section): void => {\n if (s.depth >= d) {\n items.push({ id: s.id, box: boxOf(s.nodes), nodes: s.nodes.map((i) => graph.nodes[i]!.id) });\n for (const i of s.nodes) itemOf[i] = s;\n } else if (s.children.length > 0) for (const c of s.children) visit(c);\n else\n for (const i of s.nodes) {\n const n = graph.nodes[i]!;\n items.push({ id: n.id, box: n.box, nodes: [n.id] });\n itemOf[i] = i;\n }\n };\n if (graph.nodes.length > 0) visit(root);\n const links = new Map<string, { source: string; target: string; count: number; edge: string }>();\n for (const e of graph.edges) {\n const iu = indexOfNode.get(e.source.node);\n const iv = indexOfNode.get(e.target.node);\n if (iu === undefined || iv === undefined) continue;\n const a = itemOf[iu]!;\n const b = itemOf[iv]!;\n if (a === b) continue;\n const ida = typeof a === \"number\" ? graph.nodes[a]!.id : a.id;\n const idb = typeof b === \"number\" ? graph.nodes[b]!.id : b.id;\n const key = `${ida}\\u0000${idb}`;\n const link = links.get(key);\n if (link) {\n link.count++;\n continue;\n }\n links.set(key, { source: ida, target: idb, count: 1, edge: e.id });\n }\n const pairs: ItemPair[] = [...links.values()].map(({ source, target, count }) => ({ source, target, count }));\n if (d > deepest)\n levels.push({ depth: d, items, links: [...links.values()].map(({ edge, ...l }) => ({ ...l, points: routeOf.get(edge)?.points ?? [] })) });\n else levels.push({ depth: d, items, links: levelLinks(items, pairs, options) });\n }\n return levels;\n}\n","import { center, dist, type Point } from \"../geom.ts\";\nimport { nodeIndex, type Edge, type Graph, type GroupRule, type Result, type Route, type Router, type SharedRun } from \"../model.ts\";\nimport { placePlug, type Plug } from \"../plugs.ts\";\nimport { WayFinder, type WayOptions } from \"../ways.ts\";\n\n/** The options of the router with shared ways. */\nexport interface SharedOptions extends WayOptions {\n /** The name in the benchmark. */\n readonly name: string;\n /** The edges with one key share their ways. Without a rule, all edges share. An edge without a key shares with no edge. */\n readonly rule?: GroupRule;\n /** The cost of a link that an edge with the same key uses already, as a share of its length. The default is 0.5. */\n readonly discount?: number;\n /** The benchmark skips a fixture with more nodes. */\n readonly maxNodes?: number;\n}\n\ninterface Way {\n readonly edge: Edge;\n readonly key: string;\n readonly ps: Plug;\n readonly pt: Plug;\n /** The way through the corner graph, from the point out of the source plug to the point out of the target plug. */\n seq: Point[];\n /** The index of each point of `seq` in the corner graph. The two ends get an index after the corners, one for each place. */\n ids: number[];\n found: boolean;\n}\n\ninterface Run {\n readonly key: string;\n readonly first: number;\n readonly last: number;\n /** The points from the corner `first` to the corner `last`, without the needless corners. */\n readonly points: Point[];\n readonly ways: Way[];\n}\n\nconst byText = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0);\n\n/** The angle, from -π to π, of the turn at `base` from the direction `from` → `base` to the point `to`. */\nfunction turn(from: Point, base: Point, to: Point): number {\n const dx = base.x - from.x;\n const dy = base.y - from.y;\n const vx = to.x - base.x;\n const vy = to.y - base.y;\n return Math.atan2(dx * vy - dy * vx, dx * vx + dy * vy);\n}\n\n/**\n * This function makes a router where edges share their ways (after Pupyrev, Nachmanson, Bereg and Holroyd, \"Edge routing with ordered bundles\").\n * The edges go one by one through the corner graph. A link that an edge with the same key uses already costs less.\n * Thus the edges of a key come together on common ways. Each stretch that several edges share has the same points in each route.\n * The result gives each stretch as a run, with the order of its lanes.\n */\nexport function sharedRouter(options: SharedOptions): Router {\n const discount = Math.min(1, Math.max(0.05, options.discount ?? 0.5));\n const keyOf = (e: Edge): string => {\n if (!options.rule) return \"*\";\n return options.rule(e) ?? `\\u0000${e.id}`;\n };\n const router: Router = {\n name: options.name,\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const ways = new WayFinder(graph.nodes, options);\n const corners = ways.corners;\n const index = new Map<Point, number>();\n corners.points.forEach((p, i) => index.set(p, i));\n const M = corners.points.length + 1;\n const link = (i: number, j: number): number => (i < j ? i * M + j : j * M + i);\n const ends = new Map<string, number>();\n const endId = (p: Point): number => {\n const k = `${p.x},${p.y}`;\n let id = ends.get(k);\n if (id === undefined) ends.set(k, (id = corners.points.length + ends.size));\n return id;\n };\n\n const all: Way[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n all.push({ edge: e, key: keyOf(e), ps, pt, seq: [], ids: [], found: false });\n }\n\n // The edges of one key go one after the other, the longest first, so that the short edges join the long ways.\n const discounted = new Map<string, Map<number, string[]>>();\n const order = [...all].sort(\n (p, q) => byText(p.key, q.key) || dist(q.ps.point, q.pt.point) - dist(p.ps.point, p.pt.point) || byText(p.edge.id, q.edge.id),\n );\n for (const w of order) {\n let used = discounted.get(w.key);\n if (!used) discounted.set(w.key, (used = new Map()));\n const mine = used;\n const way = corners.path(ways.out(w.ps), ways.out(w.pt), (i, j, d) => (mine.has(link(i, j)) ? d * discount : d), discount);\n if (!way) continue;\n w.found = true;\n w.seq = way;\n w.ids = way.map((p, i) => (i === 0 || i === way.length - 1 ? endId(p) : index.get(p)!));\n for (let i = 1; i < w.ids.length; i++) {\n const a = w.ids[i - 1]!;\n const b = w.ids[i]!;\n if (a >= corners.points.length || b >= corners.points.length) continue;\n const list = mine.get(link(a, b));\n if (list) list.push(w.edge.id);\n else mine.set(link(a, b), [w.edge.id]);\n }\n }\n\n // The users of each link, with the links to the ends. Two edges from one plug share the link from it.\n const users = new Map<string, Map<string, string[]>>();\n for (const w of order) {\n if (!w.found) continue;\n let mine = users.get(w.key);\n if (!mine) users.set(w.key, (mine = new Map()));\n for (let i = 1; i < w.ids.length; i++) {\n const a = w.ids[i - 1]!;\n const b = w.ids[i]!;\n const k = a < b ? `${a}:${b}` : `${b}:${a}`;\n const list = mine.get(k);\n if (list) list.push(w.edge.id);\n else mine.set(k, [w.edge.id]);\n }\n }\n\n // Each way breaks into stretches where the set of edges on the links stays the same.\n // A shared stretch loses its needless corners one time, so it has the same points in each of its routes.\n const runs = new Map<string, Run>();\n const points = new Map<string, Point[]>();\n for (const w of all) {\n if (!w.found) continue;\n const used = users.get(w.key)!;\n const sig = (i: number): string => {\n const a = w.ids[i]!;\n const b = w.ids[i + 1]!;\n const list = used.get(a < b ? `${a}:${b}` : `${b}:${a}`)!;\n return list.length < 2 ? \"\" : [...list].sort(byText).join(\"\\u0001\");\n };\n const out: Point[] = [w.ps.point];\n const append = (piece: readonly Point[]): void => {\n for (const p of piece) if (dist(p, out[out.length - 1]!) > 1e-9) out.push(p);\n };\n let start = 0;\n for (let i = 0; i < w.seq.length - 1; i++) {\n const s = sig(i);\n if (i + 1 < w.seq.length - 1 && sig(i + 1) === s) continue;\n const raw = w.seq.slice(start, i + 2);\n if (s === \"\") append(corners.pull(raw));\n else {\n const a = w.ids[start]!;\n const b = w.ids[i + 1]!;\n const id = `${s}\\u0002${Math.min(a, b)}\\u0002${Math.max(a, b)}`;\n let run = runs.get(id);\n if (!run) {\n run = { key: w.key, first: Math.min(a, b), last: Math.max(a, b), points: corners.pull(a < b ? raw : [...raw].reverse()), ways: [] };\n runs.set(id, run);\n }\n run.ways.push(w);\n append(a < b ? run.points : [...run.points].reverse());\n }\n start = i + 1;\n }\n append([w.pt.point]);\n points.set(w.edge.id, out);\n }\n\n const routes: Route[] = [];\n for (const w of all) routes.push({ edge: w.edge.id, points: points.get(w.edge.id) ?? [w.ps.point, w.pt.point] });\n const shared: SharedRun[] = [];\n for (const run of runs.values()) {\n shared.push({ id: `r${shared.length}`, key: run.key, points: run.points, edges: laneOrderOfRun(run) });\n }\n return { routes, runs: shared };\n },\n };\n return options.maxNodes === undefined ? router : { ...router, maxNodes: options.maxNodes };\n}\n\n/**\n * This function gives the lane order of a run (metro-line order). Two edges of the run go together past its last corner\n * until they part. The edge that turns more to the left there gets the lane more to the left.\n * Two edges can part only before the first corner. Then the edge that comes from more to the left gets the lane more to the left.\n */\nfunction laneOrderOfRun(run: Run): string[] {\n const oriented = new Map<Way, { seq: Point[]; ids: number[]; s: number; e: number }>();\n for (const w of run.ways) {\n const s0 = w.ids.indexOf(run.first);\n const e0 = w.ids.indexOf(run.last);\n if (s0 < e0) oriented.set(w, { seq: w.seq, ids: w.ids, s: s0, e: e0 });\n else oriented.set(w, { seq: [...w.seq].reverse(), ids: [...w.ids].reverse(), s: w.seq.length - 1 - s0, e: w.seq.length - 1 - e0 });\n }\n const compare = (p: Way, q: Way): number => {\n const P = oriented.get(p)!;\n const Q = oriented.get(q)!;\n for (let j = 1; ; j++) {\n const a = P.seq[P.e + j];\n const b = Q.seq[Q.e + j];\n if (a === undefined || b === undefined) break;\n if (P.ids[P.e + j] !== Q.ids[Q.e + j]) {\n const d = turn(P.seq[P.e + j - 2]!, P.seq[P.e + j - 1]!, a) - turn(P.seq[P.e + j - 2]!, P.seq[P.e + j - 1]!, b);\n if (d !== 0) return d;\n break;\n }\n }\n for (let j = 1; ; j++) {\n const a = P.seq[P.s - j];\n const b = Q.seq[Q.s - j];\n if (a === undefined || b === undefined) break;\n if (P.ids[P.s - j] !== Q.ids[Q.s - j]) {\n // Seen backward, the left side is the right side. Thus the order turns around.\n const d = turn(P.seq[P.s - j + 2]!, P.seq[P.s - j + 1]!, b) - turn(P.seq[P.s - j + 2]!, P.seq[P.s - j + 1]!, a);\n if (d !== 0) return d;\n break;\n }\n }\n return byText(p.edge.id, q.edge.id);\n };\n return [...run.ways].sort(compare).map((w) => w.edge.id);\n}\n","import { center, type Box, type Point } from \"../geom.ts\";\nimport { fixedPortPoint, nodeIndex, type Graph, type Result, type Route, type Router } from \"../model.ts\";\n\n/** This function gives the point where the ray from the center of the box to `toward` leaves the box. */\nexport function boxExit(box: Box, toward: Point): Point {\n const c = center(box);\n const dx = toward.x - c.x;\n const dy = toward.y - c.y;\n if (dx === 0 && dy === 0) return c;\n const tx = dx === 0 ? Infinity : box.w / 2 / Math.abs(dx);\n const ty = dy === 0 ? Infinity : box.h / 2 / Math.abs(dy);\n const t = Math.min(tx, ty);\n return { x: c.x + dx * t, y: c.y + dy * t };\n}\n\n/**\n * The control of the benchmark: each edge is one straight line between its plugs.\n * A free plug goes where the line between the two centers leaves the box.\n */\nexport const straightRouter: Router = {\n name: \"straight\",\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const fs = fixedPortPoint(s, e.source);\n const ft = fixedPortPoint(t, e.target);\n const a = fs ?? boxExit(s.box, ft ?? center(t.box));\n const b = ft ?? boxExit(t.box, fs ?? center(s.box));\n routes.push({ edge: e.id, points: [a, b] });\n }\n return { routes };\n },\n};\n","import { center, dist, type Point } from \"../geom.ts\";\nimport { nodeIndex, type Bundle, type Edge, type Graph, type GroupRule, type Node, type Result, type Route, type Router } from \"../model.ts\";\nimport { placePlug, type Plug } from \"../plugs.ts\";\nimport { WayFinder, type WayOptions } from \"../ways.ts\";\n\n/** The options of the trunk router. */\nexport interface TrunksOptions extends WayOptions {\n /** The name in the benchmark. */\n readonly name: string;\n /** The grouping rule. The edges from one plug with one key share a trunk. */\n readonly rule: GroupRule;\n /** The split point is at this share of the way to the center of the targets. The default is 0.5. */\n readonly split?: number;\n /** A group with fewer edges stays unbundled. The default is 2. */\n readonly minSize?: number;\n /** The benchmark skips a fixture with more nodes. */\n readonly maxNodes?: number;\n}\n\n/** The rule that groups the edges by the collection of their target, in `data.collection`. */\nexport const byCollection: GroupRule = (e) => {\n const c = e.data?.[\"collection\"];\n return typeof c === \"string\" ? c : undefined;\n};\n\n/**\n * This function groups the edges by their source plug and their key. Each group keeps the order of the edges.\n * A group with fewer than `minSize` edges does not appear.\n */\nexport function groupEdges(edges: readonly Edge[], rule: GroupRule, minSize = 2): Map<string, Edge[]> {\n const all = new Map<string, Edge[]>();\n for (const e of edges) {\n const key = rule(e);\n if (key === undefined) continue;\n const id = `${e.source.node}\\u0000${e.source.port ?? \"\"}\\u0000${key}`;\n const list = all.get(id);\n if (list) list.push(e);\n else all.set(id, [e]);\n }\n for (const [id, list] of all) if (list.length < minSize) all.delete(id);\n return all;\n}\n\n/**\n * This function gives the lane order of the branches that leave the split point `from`, with the trunk along `dir`.\n * Lane 0 turns most to the left, in a frame with the y axis down. Thus two lanes do not cross at the split.\n */\nexport function laneOrder(dir: Point, from: Point, branches: readonly { readonly edge: string; readonly next: Point }[]): string[] {\n const angle = (p: Point): number => {\n const vx = p.x - from.x;\n const vy = p.y - from.y;\n return Math.atan2(dir.x * vy - dir.y * vx, dir.x * vx + dir.y * vy);\n };\n return branches\n .map((b) => ({ edge: b.edge, a: angle(b.next) }))\n .sort((p, q) => p.a - q.a || (p.edge < q.edge ? -1 : p.edge > q.edge ? 1 : 0))\n .map((x) => x.edge);\n}\n\n/**\n * This function gives the split point of a bundle, on the line from `start` to the center of the targets.\n * The point is at `split` of the way, but at most half of the way to the nearest target. It moves back toward `start` out of the boxes.\n */\nexport function splitPoint(start: Point, targets: readonly Point[], split: number, free: (p: Point) => boolean, step: number): Point {\n if (targets.length === 0) return start;\n const c = { x: targets.reduce((s, p) => s + p.x, 0) / targets.length, y: targets.reduce((s, p) => s + p.y, 0) / targets.length };\n const L = dist(start, c);\n if (L === 0) return start;\n let d = Math.min(split * L, 0.5 * Math.min(...targets.map((p) => dist(start, p))));\n const at = (t: number): Point => ({ x: start.x + ((c.x - start.x) * t) / L, y: start.y + ((c.y - start.y) * t) / L });\n while (d > 0 && !free(at(d))) d -= step;\n return d > 0 ? at(d) : start;\n}\n\nconst dedupe = (p: readonly Point[]): Point[] => p.filter((q, i) => i === 0 || dist(q, p[i - 1]!) > 1e-9);\n\n/**\n * This function makes a router that bundles the edges by a rule. The edges of a group share one plug and one trunk\n * to a split point. From there, each edge goes its own way. The router gives the bundles with their lane order.\n * The edges outside the groups go as in the corner router.\n */\nexport function trunksRouter(options: TrunksOptions): Router {\n const router: Router = {\n name: options.name,\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const ways = new WayFinder(graph.nodes, options);\n const points = new Map<string, Point[]>();\n const bundles: Bundle[] = [];\n for (const [id, group] of groupEdges(graph.edges, options.rule, options.minSize ?? 2)) {\n const first = group[0]!;\n const s = byId.get(first.source.node);\n const targets = group.map((e) => byId.get(e.target.node));\n if (!s || targets.some((t) => !t)) continue;\n const centers = targets.map((t) => center(t!.box));\n const c = { x: centers.reduce((a, p) => a + p.x, 0) / centers.length, y: centers.reduce((a, p) => a + p.y, 0) / centers.length };\n const plug: Plug = placePlug(s, first.source, c);\n const start = ways.out(plug);\n const split = splitPoint(start, centers, options.split ?? 0.5, (p) => !ways.obstacles.inside(p, ways.margin), ways.margin);\n const way = ways.fromPlug(plug, split);\n if (!way) continue;\n const trunk = dedupe(way);\n const end = trunk[trunk.length - 1]!;\n const prev = trunk.length >= 2 ? trunk[trunk.length - 2]! : plug.point;\n const len = dist(prev, end);\n const dir = len > 0 ? { x: (end.x - prev.x) / len, y: (end.y - prev.y) / len } : plug.normal;\n const branches: { edge: string; next: Point }[] = [];\n group.forEach((e, i) => {\n const pt = placePlug(targets[i]!, e.target, end);\n const branch = dedupe(ways.toPlug(end, pt) ?? [end, pt.point]);\n points.set(e.id, dedupe([...trunk, ...branch.slice(1)]));\n branches.push({ edge: e.id, next: branch[1] ?? pt.point });\n });\n bundles.push({ id: `b${bundles.length}`, key: id.split(\"\\u0000\")[2]!, node: s.id, edges: laneOrder(dir, end, branches), trunk });\n }\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const known = points.get(e.id);\n if (known) {\n routes.push({ edge: e.id, points: known });\n continue;\n }\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n }\n return { routes, bundles };\n },\n };\n return options.maxNodes === undefined ? router : { ...router, maxNodes: options.maxNodes };\n}\n","import type { Router } from \"../model.ts\";\nimport { cornersRouter } from \"./corners.ts\";\nimport { plugsRouter } from \"./plugs.ts\";\nimport { sectionsRouter } from \"./sections.ts\";\nimport { sharedRouter } from \"./shared.ts\";\nimport { straightRouter } from \"./straight.ts\";\nimport { byCollection, trunksRouter } from \"./trunks.ts\";\n\nexport { boxExit, straightRouter } from \"./straight.ts\";\nexport { plugsRouter } from \"./plugs.ts\";\nexport { cornersRouter, type CornersOptions } from \"./corners.ts\";\nexport { sharedRouter, type SharedOptions } from \"./shared.ts\";\nexport { sectionsRouter, type SectionsOptions } from \"./sections.ts\";\nexport { byCollection, groupEdges, laneOrder, splitPoint, trunksRouter, type TrunksOptions } from \"./trunks.ts\";\n\n/** The routers that the benchmark races. */\nexport const ROUTERS: readonly Router[] = [\n straightRouter,\n plugsRouter,\n cornersRouter({ name: \"corners\", maxNodes: 10_000 }),\n cornersRouter({ name: \"corners-smooth\", smooth: true, maxNodes: 10_000 }),\n trunksRouter({ name: \"trunks\", rule: byCollection, maxNodes: 10_000 }),\n sharedRouter({ name: \"shared\", rule: byCollection, maxNodes: 10_000 }),\n sharedRouter({ name: \"shared-all\", maxNodes: 10_000 }),\n sectionsRouter({ name: \"sections\", maxNodes: 100_000 }),\n sectionsRouter({ name: \"sections-tree\", stretch: Infinity, maxNodes: 100_000 }),\n];\n","import { center, type Box, type Point } from \"../geom.ts\";\nimport { levelLinks } from \"../levels.ts\";\nimport type { Edge, Graph, Router } from \"../model.ts\";\n\n/** An item with a box: a node of a graph, an item of a level or a box of a host layout. */\nexport interface Boxed {\n readonly id: string;\n readonly box: Box;\n}\n\n/** A link between two boxes. For a bundled link, `count` is the number of its edges. The default count is 1. */\nexport interface RoomLink {\n readonly source: string;\n readonly target: string;\n readonly count?: number;\n}\n\n/**\n * A gap of a board: a boundary of the sweep over the left or top edges of the boxes.\n * On the axis `x`, the gap is a vertical channel between two columns. On the axis `y`, it is a horizontal channel between two rows.\n */\nexport interface Gap {\n readonly axis: \"x\" | \"y\";\n /** The place of the gap in the order of the gaps on its axis, from 0. */\n readonly index: number;\n /** The coordinate where the boxes after the gap start, on the axis of the gap. */\n readonly at: number;\n /** The ids of the boxes that end at the near side of the gap. */\n readonly before: readonly string[];\n /** The ids of the boxes that start at the far side of the gap, at `at`. */\n readonly after: readonly string[];\n /** The current width of the gap: the distance from the nearest box edge before the gap to `at`. */\n readonly width: number;\n /** The number of lanes that the links need in the gap. */\n readonly lanes: number;\n /** The width that the gap needs: at least the current width, and at least `gutter + lanes × spacing`. */\n readonly need: number;\n}\n\n/** The ways that `roomDemand` finds the lanes of each gap. */\nexport type RoomMethod = \"routes\" | \"lines\";\n\n/** The options of `roomDemand` and `makeRoom`. */\nexport interface RoomOptions {\n /** The smallest width of each gap. The default is 8. */\n readonly gutter?: number;\n /** The width of one lane: the distance between two lines that run side by side. The default is 4. */\n readonly spacing?: number;\n /**\n * The largest growth of the board on each axis, as a share of its size. The default is `Infinity`.\n * When the lanes need more, each gap gets its gutter, and the lanes share the rest in proportion.\n */\n readonly maxGrowth?: number;\n /**\n * The way to find the lanes. The default is `routes`.\n * With `routes`, the function routes the links one time on the board with each gap open to the gutter.\n * The lanes of a gap are the most routes that run along the gap side by side.\n * With `lines`, the lanes of a gap are the straight lines between the centers of the boxes that cross the gap.\n */\n readonly method?: RoomMethod;\n /** The router of the method `routes`. Without it, the links go as the links of a zoom level (`levelLinks`), with the margin `gutter / 2`. */\n readonly router?: Router;\n /** With `count`, a link takes one lane for each of its edges. With `link`, the default, a link takes one lane. */\n readonly lanes?: \"link\" | \"count\";\n /** Two box edges nearer than this distance make one boundary of the sweep. The default is 0.5. */\n readonly snap?: number;\n}\n\n/** The demand of a board and the board with its gaps open. */\nexport interface Room<T extends Boxed> {\n readonly gaps: readonly Gap[];\n readonly items: T[];\n}\n\nconst DEFAULT_GUTTER = 8;\nconst DEFAULT_SPACING = 4;\nconst DEFAULT_SNAP = 0.5;\n\ntype Axis = \"x\" | \"y\";\n\nconst lo = (b: Box, a: Axis): number => (a === \"x\" ? b.x : b.y);\nconst len = (b: Box, a: Axis): number => (a === \"x\" ? b.w : b.h);\nconst other = (a: Axis): Axis => (a === \"x\" ? \"y\" : \"x\");\n\n/**\n * This function gives the gaps of a board. A sweep over each axis sorts the left (or top) edges of the boxes.\n * Each distinct edge after the first is a gap. The `lanes` of each gap are 0, and its `need` is its current width.\n */\nexport function boardGaps(items: readonly Boxed[], snap: number = DEFAULT_SNAP): Gap[] {\n return [...axisGaps(items, \"x\", snap), ...axisGaps(items, \"y\", snap)];\n}\n\nfunction axisGaps(items: readonly Boxed[], axis: Axis, snap: number): Gap[] {\n const starts = [...new Set(items.map((i) => lo(i.box, axis)))].sort((u, v) => u - v);\n const bounds: number[] = [];\n for (const s of starts) if (bounds.length === 0 || s - bounds[bounds.length - 1]! > snap) bounds.push(s);\n const after: string[][] = bounds.map(() => []);\n for (const i of items) after[lastAtOrBefore(bounds, lo(i.box, axis) + snap)]!.push(i.id);\n const ends = items.map((i) => ({ id: i.id, end: lo(i.box, axis) + len(i.box, axis) })).sort((u, v) => u.end - v.end);\n const gaps: Gap[] = [];\n let k = 0;\n for (let n = 1; n < bounds.length; n++) {\n const at = bounds[n]!;\n // The nearest box edge before the gap is the largest end at or before the boundary.\n while (k < ends.length && ends[k]!.end <= at + snap) k++;\n const near = k > 0 ? ends[k - 1]!.end : at;\n const before: string[] = [];\n for (let j = k - 1; j >= 0 && ends[j]!.end >= near - snap; j--) before.push(ends[j]!.id);\n gaps.push({ axis, index: n - 1, at, before: before.reverse(), after: after[n]!, width: Math.max(0, at - near), lanes: 0, need: Math.max(0, at - near) });\n }\n return gaps;\n}\n\n/** This function gives the index of the last value of the sorted list `v` that is at or before `x`, or 0. */\nfunction lastAtOrBefore(v: readonly number[], x: number): number {\n let a = 0;\n let b = v.length - 1;\n while (a < b) {\n const m = (a + b + 1) >> 1;\n if (v[m]! <= x) a = m;\n else b = m - 1;\n }\n return a;\n}\n\n/**\n * This function moves the boxes apart, so that each gap gets the width `need`. The boxes keep their size, their order and their alignment.\n * A box moves by the sum of the growth of each gap at or before its left (or top) edge. Thus a grid stays a grid.\n * The function moves no box nearer to another box, so it makes no overlap.\n */\nexport function openGaps<T extends Boxed>(items: readonly T[], gaps: readonly Gap[], snap: number = DEFAULT_SNAP): T[] {\n const shift = (axis: Axis): ((v: number) => number) => {\n const list = gaps.filter((g) => g.axis === axis).sort((u, v) => u.at - v.at);\n const at = list.map((g) => g.at);\n const sum: number[] = [];\n let s = 0;\n for (const g of list) sum.push((s += Math.max(0, g.need - g.width)));\n return (v) => (list.length === 0 || at[0]! > v + snap ? 0 : sum[lastAtOrBefore(at, v + snap)]!);\n };\n const sx = shift(\"x\");\n const sy = shift(\"y\");\n return items.map((i) => ({ ...i, box: { ...i.box, x: i.box.x + sx(i.box.x), y: i.box.y + sy(i.box.y) } }));\n}\n\n/**\n * This function gives the room that the links need in each gap of the board.\n * The lanes of a gap come from the `method` of the options. The need of a gap is `gutter + lanes × spacing`, and not less than its current width.\n */\nexport function roomDemand(items: readonly Boxed[], links: readonly RoomLink[], options: RoomOptions = {}): Gap[] {\n const gutter = options.gutter ?? DEFAULT_GUTTER;\n const spacing = options.spacing ?? DEFAULT_SPACING;\n const snap = options.snap ?? DEFAULT_SNAP;\n const weight = (l: RoomLink): number => (options.lanes === \"count\" ? Math.max(1, l.count ?? 1) : 1);\n const gaps = boardGaps(items, snap);\n const lanes = (options.method ?? \"routes\") === \"lines\" ? lineLanes(items, links, gaps, weight) : routeLanes(items, links, gaps, gutter, snap, weight, options.router);\n const raw = gaps.map((g, i) => ({ ...g, lanes: lanes[i]!, need: Math.max(g.width, gutter + lanes[i]! * spacing) }));\n return capGrowth(items, raw, gutter, options.maxGrowth ?? Infinity);\n}\n\n/** This function gives the demand of the board and the board with each gap open to its need. */\nexport function makeRoom<T extends Boxed>(items: readonly T[], links: readonly RoomLink[], options: RoomOptions = {}): Room<T> {\n const gaps = roomDemand(items, links, options);\n return { gaps, items: openGaps(items, gaps, options.snap ?? DEFAULT_SNAP) };\n}\n\n/** This function gives the links between the nodes of a graph, with the count of the edges of each pair. A loop does not count. */\nexport function roomLinks(graph: Graph): RoomLink[] {\n const byPair = new Map<string, { source: string; target: string; count: number }>();\n for (const e of graph.edges) {\n const [s, t] = [e.source.node, e.target.node];\n if (s === t) continue;\n const key = s < t ? `${s}\\u0000${t}` : `${t}\\u0000${s}`;\n const known = byPair.get(key);\n if (known) known.count++;\n else byPair.set(key, { source: s, target: t, count: 1 });\n }\n return [...byPair.values()];\n}\n\n/** This function counts, for each gap, the straight lines between the centers of the boxes of a link that cross the gap. */\nfunction lineLanes(items: readonly Boxed[], links: readonly RoomLink[], gaps: readonly Gap[], weight: (l: RoomLink) => number): number[] {\n const byId = new Map(items.map((i) => [i.id, center(i.box)]));\n return gaps.map((g) => {\n let n = 0;\n for (const l of links) {\n const a = byId.get(l.source);\n const b = byId.get(l.target);\n if (a && b && Math.min(a[g.axis], b[g.axis]) < g.at && Math.max(a[g.axis], b[g.axis]) > g.at) n += weight(l);\n }\n return n;\n });\n}\n\n/**\n * This function routes the links one time on the board with each gap open to the gutter.\n * The lanes of a gap are the largest number of routes that run along the gap at one place.\n * A piece of a route goes along a gap when it is in the channel of the gap.\n * It must also go farther along the gap than across it.\n */\nfunction routeLanes(\n items: readonly Boxed[],\n links: readonly RoomLink[],\n gaps: readonly Gap[],\n gutter: number,\n snap: number,\n weight: (l: RoomLink) => number,\n router: Router | undefined,\n): number[] {\n const probeGaps = gaps.map((g) => ({ ...g, need: Math.max(g.width, gutter) }));\n const probe = openGaps(items, probeGaps, snap);\n const ways = probeWays(probe, links, gutter, router);\n return probeGaps.map((g) => {\n // The channel of the gap on the probe board: its far side moves with the growth of each gap up to this one.\n let grow = 0;\n for (const h of probeGaps) if (h.axis === g.axis && h.at <= g.at + snap) grow += h.need - h.width;\n const hi = g.at + grow;\n const lo = hi - g.need;\n const spans: { from: number; to: number; w: number }[] = [];\n ways.forEach((points, i) => {\n const along = alongSpans(points, g.axis, lo, hi);\n for (const [from, to] of merge(along)) spans.push({ from, to, w: weight(links[i]!) });\n });\n return density(spans);\n });\n}\n\n/** This function gives the points of the way of each link on the probe board, in the order of the links. */\nfunction probeWays(items: readonly Boxed[], links: readonly RoomLink[], gutter: number, router: Router | undefined): (readonly Point[])[] {\n if (router) {\n const edges: Edge[] = links.map((l, i) => ({ id: `l${i}`, source: { node: l.source }, target: { node: l.target } }));\n const routes = new Map(router.route({ nodes: items, edges }).routes.map((r) => [r.edge, r.points]));\n return edges.map((e) => routes.get(e.id) ?? []);\n }\n const level = items.map((i) => ({ id: i.id, box: i.box, nodes: [i.id] }));\n const pairs = links.map((l) => ({ source: l.source, target: l.target, count: l.count ?? 1 }));\n // The margin puts the corners of the two sides of a gap on its middle line.\n const out = levelLinks(level, pairs, { margin: Math.max(1, gutter / 2) });\n const byPair = new Map(out.map((l) => [`${l.source}\\u0000${l.target}`, l.points]));\n return links.map((l) => byPair.get(`${l.source}\\u0000${l.target}`) ?? []);\n}\n\n/**\n * This function gives the spans along the axis of a gap where the polyline goes along the channel from `lo` to `hi`.\n * The axis `x` gap is a vertical channel, so its spans are on the y axis.\n */\nfunction alongSpans(p: readonly Point[], axis: Axis, lo: number, hi: number): [number, number][] {\n const across = axis;\n const along = other(axis);\n const out: [number, number][] = [];\n for (let i = 1; i < p.length; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n const da = b[across] - a[across];\n // The part of the segment inside the channel, as the parameters t0 and t1 of the segment.\n let t0 = 0;\n let t1 = 1;\n if (Math.abs(da) < 1e-9) {\n if (a[across] < lo - 1e-6 || a[across] > hi + 1e-6) continue;\n } else {\n const u = (lo - a[across]) / da;\n const v = (hi - a[across]) / da;\n t0 = Math.max(0, Math.min(u, v));\n t1 = Math.min(1, Math.max(u, v));\n if (t1 <= t0) continue;\n }\n const s = a[along] + (b[along] - a[along]) * t0;\n const e = a[along] + (b[along] - a[along]) * t1;\n const run = Math.abs(e - s);\n const cross = Math.abs(da) * (t1 - t0);\n if (run > cross && run > 1e-6) out.push([Math.min(s, e), Math.max(s, e)]);\n }\n return out;\n}\n\n/** This function joins the spans that overlap, so that one link counts one time at each place. */\nfunction merge(spans: [number, number][]): [number, number][] {\n spans.sort((u, v) => u[0] - v[0]);\n const out: [number, number][] = [];\n for (const s of spans) {\n const last = out[out.length - 1];\n if (last && s[0] <= last[1]) last[1] = Math.max(last[1], s[1]);\n else out.push([s[0], s[1]]);\n }\n return out;\n}\n\n/** This function gives the largest sum of the weights of the spans that overlap at one place. Spans that only touch do not overlap. */\nfunction density(spans: readonly { from: number; to: number; w: number }[]): number {\n const events: [number, number][] = [];\n for (const s of spans) events.push([s.from, s.w], [s.to, -s.w]);\n // At one coordinate, the ends come before the starts.\n events.sort((u, v) => u[0] - v[0] || u[1] - v[1]);\n let n = 0;\n let best = 0;\n for (const [, w] of events) {\n n += w;\n best = Math.max(best, n);\n }\n return best;\n}\n\n/**\n * This function keeps the growth of the board on each axis at most `maxGrowth` times its size.\n * Each gap keeps its gutter. The lanes of all gaps of the axis share the rest of the growth in proportion.\n */\nfunction capGrowth(items: readonly Boxed[], gaps: Gap[], gutter: number, maxGrowth: number): Gap[] {\n if (!Number.isFinite(maxGrowth)) return gaps;\n const out = [...gaps];\n for (const axis of [\"x\", \"y\"] as const) {\n let x0 = Infinity;\n let x1 = -Infinity;\n for (const i of items) {\n x0 = Math.min(x0, lo(i.box, axis));\n x1 = Math.max(x1, lo(i.box, axis) + len(i.box, axis));\n }\n const budget = Math.max(0, maxGrowth) * Math.max(0, x1 - x0);\n let base = 0;\n let spare = 0;\n for (const g of gaps) {\n if (g.axis !== axis) continue;\n const b = Math.max(0, gutter - g.width);\n base += b;\n spare += Math.max(0, g.need - g.width - b);\n }\n if (base + spare <= budget || spare === 0) continue;\n const f = Math.max(0, (budget - base) / spare);\n gaps.forEach((g, i) => {\n if (g.axis !== axis) return;\n const b = Math.max(0, gutter - g.width);\n out[i] = { ...g, need: g.width + b + f * Math.max(0, g.need - g.width - b) };\n });\n }\n return out;\n}\n","import {\n bendCount,\n dist,\n frechet,\n inflectionCount,\n polylineLength,\n segmentBoxDistance,\n segmentsCross,\n type Box,\n type Point,\n} from \"../geom.ts\";\nimport { rng } from \"../fixtures.ts\";\nimport { Grid } from \"../grid.ts\";\nimport { nodeIndex, type Graph, type Node, type Result } from \"../model.ts\";\n\n/** The quality of a result. Lower is better for each value except `clearance`. */\nexport interface Quality {\n /** The length of all drawn lines. A segment that several routes share counts one time. */\n readonly ink: number;\n /** The number of points where two drawn segments cross. */\n readonly crossings: number;\n /** This value is true when `crossings` is an estimate from a sample of the segments. */\n readonly crossingsEstimated: boolean;\n /** The mean number of bends of a route. */\n readonly bends: number;\n /** The mean number of inflections of a route. */\n readonly inflections: number;\n /** The mean distance from a route to the nearest node that is not one of its ends, up to `CLEARANCE_CAP`. */\n readonly clearance: number;\n /** The share of the routes that come closer than 4 units to a node that is not one of their ends. */\n readonly tight: number;\n /** The mean ratio of the length of a route to the distance between its ends. */\n readonly detour: number;\n /** The mean angle, in degrees, between the first or last segment of a route and the normal of the side of its node. */\n readonly plugAngle: number;\n}\n\n/** The clearance stops at this distance. */\nexport const CLEARANCE_CAP = 40;\nconst TIGHT = 4;\nconst EXACT_CROSSINGS = 20_000;\nconst SAMPLE = 2_000;\n\nconst key = (p: Point): string => `${Math.round(p.x * 8)},${Math.round(p.y * 8)}`;\n\n/** This function measures the quality of a result. */\nexport function measureQuality(graph: Graph, result: Result): Quality {\n const byId = nodeIndex(graph);\n const nodes = new Grid<Node>(180);\n for (const n of graph.nodes) nodes.add(n, n.box);\n\n // The drawn segments: one for each distinct pair of ends.\n const segs: [Point, Point][] = [];\n const seen = new Set<string>();\n let bends = 0;\n let infl = 0;\n let clear = 0;\n let tight = 0;\n let detour = 0;\n let detourN = 0;\n let angle = 0;\n let angleN = 0;\n for (const r of result.routes) {\n const p = r.points;\n for (let i = 1; i < p.length; i++) {\n const ka = key(p[i - 1]!);\n const kb = key(p[i]!);\n if (ka === kb) continue;\n const k = ka < kb ? `${ka}|${kb}` : `${kb}|${ka}`;\n if (seen.has(k)) continue;\n seen.add(k);\n segs.push([p[i - 1]!, p[i]!]);\n }\n bends += bendCount(p);\n infl += inflectionCount(p);\n const ends = endNodes(graph, byId, r.edge);\n let c = CLEARANCE_CAP;\n for (let i = 1; i < p.length; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n nodes.querySegment(a, b, c, (n) => {\n if (n !== ends.source && n !== ends.target) c = Math.min(c, segmentBoxDistance(a, b, n.box));\n });\n }\n clear += c;\n if (c < TIGHT) tight++;\n if (p.length >= 2) {\n const d = dist(p[0]!, p[p.length - 1]!);\n if (d > 1) {\n detour += polylineLength(p) / d;\n detourN++;\n }\n for (const [at, next, node] of [\n [p[0]!, p[1]!, ends.source],\n [p[p.length - 1]!, p[p.length - 2]!, ends.target],\n ] as const) {\n if (!node) continue;\n const a = sideAngle(node.box, at, next);\n if (a !== undefined) {\n angle += a;\n angleN++;\n }\n }\n }\n }\n const n = Math.max(1, result.routes.length);\n let ink = 0;\n for (const [a, b] of segs) ink += dist(a, b);\n const [crossings, crossingsEstimated] = countCrossings(segs);\n return {\n ink,\n crossings,\n crossingsEstimated,\n bends: bends / n,\n inflections: infl / n,\n clearance: clear / n,\n tight: tight / n,\n detour: detourN ? detour / detourN : 1,\n plugAngle: angleN ? angle / angleN : 0,\n };\n}\n\ninterface Ends {\n readonly source: Node | undefined;\n readonly target: Node | undefined;\n}\n\nfunction endNodes(graph: Graph, byId: Map<string, Node>, edgeId: string): Ends {\n const e = edgeIndex(graph).get(edgeId);\n return { source: e && byId.get(e.source.node), target: e && byId.get(e.target.node) };\n}\n\nconst edgeIndexes = new WeakMap<Graph, Map<string, Graph[\"edges\"][number]>>();\nfunction edgeIndex(graph: Graph): Map<string, Graph[\"edges\"][number]> {\n let m = edgeIndexes.get(graph);\n if (!m) {\n m = new Map();\n for (const e of graph.edges) m.set(e.id, e);\n edgeIndexes.set(graph, m);\n }\n return m;\n}\n\n/**\n * This function gives an angle in degrees: the angle between the segment from `at` to `next` and the outward normal.\n * The normal is the normal of the side of the box nearest to `at`. A route that starts inside the box (an interior route) gives no angle.\n */\nexport function sideAngle(box: Box, at: Point, next: Point): number | undefined {\n const d = [\n [Math.abs(at.y - box.y), 0, -1],\n [Math.abs(at.x - (box.x + box.w)), 1, 0],\n [Math.abs(at.y - (box.y + box.h)), 0, 1],\n [Math.abs(at.x - box.x), -1, 0],\n ].sort((a, b) => a[0]! - b[0]!)[0]!;\n if (d[0]! > 1) return undefined;\n const vx = next.x - at.x;\n const vy = next.y - at.y;\n const l = Math.hypot(vx, vy);\n if (l === 0) return undefined;\n const cos = Math.max(-1, Math.min(1, (vx * d[1]! + vy * d[2]!) / l));\n return (Math.acos(cos) * 180) / Math.PI;\n}\n\n/**\n * This function counts the crossings of a set of segments with a grid of buckets.\n * Above 20 000 segments, it counts the crossings of a seeded sample of 2 000 segments and scales the count.\n */\nexport function countCrossings(segs: readonly (readonly [Point, Point])[]): [number, boolean] {\n if (segs.length < 2) return [0, false];\n const len = segs.reduce((s, [a, b]) => s + dist(a, b), 0) / segs.length;\n const grid = new Grid<number>(Math.max(20, len));\n segs.forEach(([a, b], i) => grid.addSegment(i, a, b));\n const exact = segs.length <= EXACT_CROSSINGS;\n const R = rng(segs.length);\n const pick = exact ? segs.map((_, i) => i) : Array.from({ length: SAMPLE }, () => Math.floor(R() * segs.length));\n let count = 0;\n for (const i of pick) {\n const [a, b] = segs[i]!;\n grid.querySegment(a, b, 0, (j) => {\n if (exact && j <= i) return;\n if (j === i) return;\n const [c, d] = segs[j]!;\n if (segmentsCross(a, b, c, d)) count++;\n });\n }\n return exact ? [count, false] : [Math.round((count * segs.length) / (2 * pick.length)), true];\n}\n\n/** The change between two results of the same graph: the Fréchet distance between the two routes of each edge. */\nexport interface Stability {\n readonly mean: number;\n readonly max: number;\n /** The share of the routes that moved more than 1 unit. */\n readonly moved: number;\n}\n\n/** This function measures how much the routes changed between two results. */\nexport function measureStability(before: Result, after: Result): Stability {\n const prev = new Map(before.routes.map((r) => [r.edge, r.points] as const));\n let sum = 0;\n let max = 0;\n let moved = 0;\n let n = 0;\n for (const r of after.routes) {\n const p = prev.get(r.edge);\n if (!p) continue;\n const f = frechet(p, r.points);\n sum += f;\n max = Math.max(max, f);\n if (f > 1) moved++;\n n++;\n }\n return { mean: n ? sum / n : 0, max, moved: n ? moved / n : 0 };\n}\n","import { makeFixture, type FixtureSpec } from \"../fixtures.ts\";\nimport type { Graph, Result, Router } from \"../model.ts\";\nimport { measureLevelFaults, measureRouteFaults, sumFaults, type LevelFaults, type LinkFaults } from \"./links.ts\";\nimport { checkProperties, type Violation } from \"./properties.ts\";\nimport { measureQuality, type Quality } from \"./quality.ts\";\n\n// The core runs in any host, so it reads the clock without the types of Node or the browser.\nconst now = (): number => (globalThis as { performance?: { now(): number } }).performance?.now() ?? Date.now();\n\n/** One row of the benchmark: one router on one fixture. */\nexport interface BenchRow {\n readonly router: string;\n readonly fixture: string;\n readonly nodes: number;\n readonly edges: number;\n /** The median time of one run, in milliseconds. */\n readonly ms: number;\n /** This value is false when two runs on the same input gave different results. */\n readonly deterministic: boolean;\n readonly violations: number;\n /** The first violations, for the report. */\n readonly sample: readonly Violation[];\n readonly quality: Quality;\n /** The faults of the routes of the edges (`measureRouteFaults`). */\n readonly faults: LinkFaults;\n /** The faults of each zoom level with groups (`measureLevelFaults`). The list is empty for a router without levels. */\n readonly levelFaults: readonly LevelFaults[];\n}\n\n/** The options of a benchmark run. */\nexport interface BenchOptions {\n /** The number of timed routes of each fixture by each router. The default is 3. */\n readonly repeat?: number;\n}\n\n/** This function routes each fixture with each router, checks the hard rules and measures the quality. */\nexport function runBenchmark(routers: readonly Router[], fixtures: readonly FixtureSpec[], options: BenchOptions = {}): BenchRow[] {\n const rows: BenchRow[] = [];\n for (const spec of fixtures) {\n const graph = makeFixture(spec);\n for (const router of routers) if (graph.nodes.length <= (router.maxNodes ?? Infinity)) rows.push(benchOne(router, spec.name, graph, options.repeat ?? 3));\n }\n return rows;\n}\n\n/**\n * This function tells if two values hold the same data, as JSON sees it. It does not make a string,\n * because the result of a large graph can be longer than the longest string.\n */\nexport function sameData(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a === \"number\" && typeof b === \"number\") return Number.isNaN(a) && Number.isNaN(b);\n if (typeof a !== \"object\" || typeof b !== \"object\" || a === null || b === null) return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n if (Array.isArray(a)) {\n const y = b as unknown[];\n if (a.length !== y.length) return false;\n for (let i = 0; i < a.length; i++) if (!sameData(a[i], y[i])) return false;\n return true;\n }\n const x = a as Record<string, unknown>;\n const y = b as Record<string, unknown>;\n const kx = Object.keys(x).filter((k) => x[k] !== undefined);\n const ky = Object.keys(y).filter((k) => y[k] !== undefined);\n if (kx.length !== ky.length) return false;\n for (const k of kx) if (!sameData(x[k], y[k])) return false;\n return true;\n}\n\n/** This function routes one graph with one router and measures the result. */\nexport function benchOne(router: Router, fixture: string, graph: Graph, repeat = 3): BenchRow {\n const times: number[] = [];\n let first: Result | undefined;\n let deterministic = true;\n for (let i = 0; i < Math.max(2, repeat); i++) {\n const t0 = now();\n const r = router.route(graph);\n times.push(now() - t0);\n if (!first) first = r;\n else if (i === 1 && !sameData(r, first)) deterministic = false;\n }\n times.sort((a, b) => a - b);\n const result = first!;\n const all = checkProperties(graph, result, 1_000_000);\n return {\n router: router.name,\n fixture,\n nodes: graph.nodes.length,\n edges: graph.edges.length,\n ms: times[Math.floor(times.length / 2)]!,\n deterministic,\n violations: all.length,\n sample: all.slice(0, 5),\n quality: measureQuality(graph, result),\n faults: measureRouteFaults(graph, result),\n levelFaults: measureLevelFaults(result),\n };\n}\n\n/** This function writes the rows as a Markdown table. */\nexport function formatTable(rows: readonly BenchRow[]): string {\n const head = \"| router | fixture | nodes | edges | ms | same twice | violations | ink | crossings | bends | inflections | clearance | tight | detour | plug angle |\";\n const line = \"|---|---|---:|---:|---:|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|\";\n const f = (v: number, d = 2): string => (Number.isInteger(v) ? String(v) : v.toFixed(d));\n const body = rows.map((r) => {\n const q = r.quality;\n return `| ${r.router} | ${r.fixture} | ${r.nodes} | ${r.edges} | ${f(r.ms, 1)} | ${r.deterministic ? \"yes\" : \"NO\"} | ${r.violations} | ${Math.round(q.ink)} | ${q.crossingsEstimated ? \"≈\" : \"\"}${q.crossings} | ${f(q.bends)} | ${f(q.inflections)} | ${f(q.clearance, 1)} | ${f(q.tight)} | ${f(q.detour)} | ${f(q.plugAngle, 1)} |`;\n });\n return [head, line, ...body].join(\"\\n\");\n}\n\n/**\n * This function writes the faults of the rows as a Markdown table: the routes first, then the sum of the levels with groups.\n * A router without such levels gets a dash in the columns of the levels.\n */\nexport function formatFaults(rows: readonly BenchRow[]): string {\n const head =\n \"| router | fixture | through | out and back | worst detour | outside | level links | level overlaps | level through | level out and back | level worst detour | level outside |\";\n const line = \"|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|\";\n const body = rows.map((r) => {\n const f = r.faults;\n const cells = [r.router, r.fixture, f.through, f.backtrack, f.worstDetour.toFixed(2), f.outside];\n if (r.levelFaults.length === 0) cells.push(\"-\", \"-\", \"-\", \"-\", \"-\", \"-\");\n else {\n const l = sumFaults(r.levelFaults);\n cells.push(l.links, r.levelFaults.reduce((s, x) => s + x.overlaps, 0), l.through, l.backtrack, l.worstDetour.toFixed(2), l.outside);\n }\n return `| ${cells.join(\" | \")} |`;\n });\n return [head, line, ...body].join(\"\\n\");\n}\n","import { curveOf, CURVE_TYPES, curveSpace, sampleCurve, type CurveType } from \"../curves/index.ts\";\nimport { polylineLength } from \"../geom.ts\";\nimport { nodeIndex, type Graph, type Router } from \"../model.ts\";\nimport { nearestSide, SIDE_NORMAL } from \"../plugs.ts\";\nimport { measureLinks, type MeasuredLink } from \"./links.ts\";\n\n// The core runs in any host, so it reads the clock without the types of Node or the browser.\nconst now = (): number => (globalThis as { performance?: { now(): number } }).performance?.now() ?? Date.now();\n\n/** One row of the benchmark of the curves: one curve type on the routes of one router on one fixture. */\nexport interface CurveBenchRow {\n readonly router: string;\n readonly fixture: string;\n readonly type: CurveType;\n /** The number of routes. */\n readonly links: number;\n /** The number of polylines that go through a box that is not one of their ends (`measureLinks`). */\n readonly through: number;\n /** The number of curves without a free space that go through such a box. */\n readonly free: number;\n /** The number of curves with the free space of the nodes (`curveSpace`) that go through such a box. */\n readonly clamped: number;\n /** The ratio of the length of all curves with the free space to the length of all polylines. */\n readonly length: number;\n /** The time to make all curves with the free space, in milliseconds. */\n readonly ms: number;\n}\n\n/** The options of `benchCurves`. */\nexport interface CurveBenchOptions {\n /** The radius of the types `rounded` and `arc`. The default is 12. */\n readonly radius?: number;\n /** The tolerance of the samples of the curves. The default is 0.25. */\n readonly tolerance?: number;\n}\n\n/**\n * This function routes a graph with a router and makes each curve type of each route.\n * It counts the curves that go through a box, with and without the free space, and it compares their length to the polylines.\n * The type `spline` leaves each plug along the normal of the nearest side of its node.\n */\nexport function benchCurves(router: Router, fixture: string, graph: Graph, options: CurveBenchOptions = {}): CurveBenchRow[] {\n const tolerance = options.tolerance ?? 0.25;\n const result = router.route(graph);\n const byId = nodeIndex(graph);\n const boxes = new Map(graph.nodes.map((n) => [n.id, n.box]));\n const edges = new Map(graph.edges.map((e) => [e.id, e]));\n const space = curveSpace(\n graph.nodes.map((n) => n.box),\n tolerance,\n );\n const routes = result.routes.flatMap((r) => {\n const e = edges.get(r.edge);\n const s = e && byId.get(e.source.node);\n const t = e && byId.get(e.target.node);\n if (!e || !s || !t || r.points.length < 2) return [];\n const first = r.points[0]!;\n const last = r.points[r.points.length - 1]!;\n return [{ source: s.id, target: t.id, points: r.points, startNormal: SIDE_NORMAL[nearestSide(s.box, first)], endNormal: SIDE_NORMAL[nearestSide(t.box, last)] }];\n });\n const base = measureLinks(boxes, routes);\n const ink = routes.reduce((sum, r) => sum + polylineLength(r.points), 0);\n return CURVE_TYPES.map((type): CurveBenchRow => {\n const make = (withSpace: boolean): MeasuredLink[] =>\n routes.map((r) => ({\n source: r.source,\n target: r.target,\n points: sampleCurve(\n curveOf(r.points, { type, radius: options.radius ?? 12, startNormal: r.startNormal, endNormal: r.endNormal, ...(withSpace ? { space } : {}) }),\n tolerance,\n ),\n }));\n const free = measureLinks(boxes, make(false));\n const t0 = now();\n const clamped = make(true);\n const ms = now() - t0;\n const length = clamped.reduce((sum, l) => sum + polylineLength(l.points), 0);\n return {\n router: router.name,\n fixture,\n type,\n links: routes.length,\n through: base.through,\n free: free.through,\n clamped: measureLinks(boxes, clamped).through,\n length: ink > 0 ? length / ink : 1,\n ms,\n };\n });\n}\n\n/** This function writes the rows of `benchCurves` as a Markdown table. */\nexport function formatCurves(rows: readonly CurveBenchRow[]): string {\n const head = \"| router | fixture | curve | routes | through, polyline | through, free | through, clamped | length | ms |\";\n const line = \"|---|---|---|---:|---:|---:|---:|---:|---:|\";\n const body = rows.map((r) => `| ${r.router} | ${r.fixture} | ${r.type} | ${r.links} | ${r.through} | ${r.free} | ${r.clamped} | ${r.length.toFixed(3)} | ${r.ms.toFixed(1)} |`);\n return [head, line, ...body].join(\"\\n\");\n}\n","import { levelLinks } from \"../levels.ts\";\nimport type { Graph, Node, Result } from \"../model.ts\";\nimport { makeRoom, roomLinks, type RoomOptions } from \"../room/index.ts\";\nimport { sectionsRouter } from \"../routers/sections.ts\";\nimport { laneRoutes, runKey, segmentsOf } from \"../segments.ts\";\nimport { measureLinks, measureRouteFaults, type LinkFaults } from \"./links.ts\";\nimport { measureQuality } from \"./quality.ts\";\n\n// The core runs in any host, so it reads the clock without the types of Node or the browser.\nconst now = (): number => (globalThis as { performance?: { now(): number } }).performance?.now() ?? Date.now();\n\n/** One row of the benchmark of the room: one state of a board, packed or open, and the measures of its links. */\nexport interface RoomBenchRow {\n readonly fixture: string;\n /** The state of the board: `packed`, `gutter` (each gap open to the gutter only), or a method of `roomDemand`. */\n readonly board: string;\n /** The area of the bounding box of the boxes, as a share of the area of the packed board. */\n readonly area: number;\n /** The faults of the links of the far view (`levelLinks` with each box as one item). */\n readonly faults: LinkFaults;\n /** The crossings of the links of the far view (`measureQuality`). */\n readonly crossings: number;\n /** The ink of the links of the far view. */\n readonly ink: number;\n /** The mean detour of the links of the far view. */\n readonly detour: number;\n /**\n * The number of lane routes of the router `sections` that go through a box. Each shared segment opens to one lane for each edge,\n * at the spacing of the options (`laneRoutes`).\n */\n readonly laneThrough: number;\n /** The time of `makeRoom`, in milliseconds. It is 0 for the packed board. */\n readonly ms: number;\n}\n\n/** This function gives the area of the bounding box of the nodes. */\nfunction areaOf(nodes: readonly Node[]): number {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const n of nodes) {\n x0 = Math.min(x0, n.box.x);\n y0 = Math.min(y0, n.box.y);\n x1 = Math.max(x1, n.box.x + n.box.w);\n y1 = Math.max(y1, n.box.y + n.box.h);\n }\n return nodes.length ? (x1 - x0) * (y1 - y0) : 0;\n}\n\n/**\n * This function measures the links of one board. It measures the links of the far view, with each node of the graph as one item of a level.\n * It also measures the lane routes of the router `sections` at the lane width `spacing`.\n */\nexport function measureBoard(graph: Graph, spacing: number): Omit<RoomBenchRow, \"fixture\" | \"board\" | \"area\" | \"ms\"> {\n const links = roomLinks(graph);\n const items = graph.nodes.map((n) => ({ id: n.id, box: n.box, nodes: [n.id] }));\n const drawn = levelLinks(\n items,\n links.map((l) => ({ source: l.source, target: l.target, count: l.count ?? 1 })),\n );\n const boxes = new Map(graph.nodes.map((n) => [n.id, n.box]));\n // `measureQuality` reads routes of edges, so each link of the far view stands for the first edge of its pair.\n const edgeOf = new Map<string, string>();\n for (const e of graph.edges) {\n const key = `${e.source.node}\\u0000${e.target.node}`;\n if (!edgeOf.has(key)) edgeOf.set(key, e.id);\n }\n const asRoutes: Result = { routes: drawn.map((l) => ({ edge: edgeOf.get(`${l.source}\\u0000${l.target}`)!, points: l.points })) };\n const q = measureQuality(graph, asRoutes);\n const routed = sectionsRouter({ name: \"sections\" }).route(graph);\n const segments = segmentsOf(routed);\n const open = new Set(segments.segments.filter((s) => s.count > 1).map((s) => runKey(s.edges)));\n const lanes = laneRoutes(segments, open, spacing);\n return {\n faults: measureLinks(boxes, drawn),\n crossings: q.crossings,\n ink: q.ink,\n detour: q.detour,\n laneThrough: measureRouteFaults(graph, { routes: lanes }).through,\n };\n}\n\n/**\n * This function measures a packed board, the board with each gap open to the gutter only, and the board that `makeRoom` opens with each method.\n * The options of `makeRoom` are the same for each method, except `method`.\n */\nexport function benchRoom(fixture: string, graph: Graph, options: RoomOptions = {}): RoomBenchRow[] {\n const spacing = options.spacing ?? 4;\n const area0 = areaOf(graph.nodes);\n const links = roomLinks(graph);\n const row = (board: string, nodes: readonly Node[], ms: number): RoomBenchRow => ({\n fixture,\n board,\n area: area0 > 0 ? areaOf(nodes) / area0 : 1,\n ms,\n ...measureBoard({ nodes, edges: graph.edges }, spacing),\n });\n const rows = [row(\"packed\", graph.nodes, 0)];\n const states: [string, RoomOptions][] = [\n [\"gutter\", { ...options, spacing: 0, method: \"routes\" }],\n [\"routes\", { ...options, method: \"routes\" }],\n [\"lines\", { ...options, method: \"lines\" }],\n ];\n for (const [board, o] of states) {\n const t0 = now();\n const room = makeRoom(graph.nodes, links, o);\n rows.push(row(board, room.items, now() - t0));\n }\n return rows;\n}\n\n/** This function writes the rows of `benchRoom` as a Markdown table. */\nexport function formatRoom(rows: readonly RoomBenchRow[]): string {\n const head = \"| fixture | board | area | links | through | outside | out and back | worst detour | crossings | ink | detour | lane through | ms |\";\n const line = \"|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|\";\n const body = rows.map((r) => {\n const f = r.faults;\n return `| ${r.fixture} | ${r.board} | ${r.area.toFixed(3)} | ${f.links} | ${f.through} | ${f.outside} | ${f.backtrack} | ${f.worstDetour.toFixed(2)} | ${r.crossings} | ${Math.round(r.ink)} | ${r.detour.toFixed(3)} | ${r.laneThrough} | ${r.ms.toFixed(1)} |`;\n });\n return [head, line, ...body].join(\"\\n\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["SIDES","hits","turn","EPS","dedupe","now","now","now"],"sources":["../src/geom.ts","../src/grid.ts","../src/model.ts","../src/fixtures.ts","../src/cases.ts","../src/plugs.ts","../src/curves.ts","../src/curves/model.ts","../src/bench/properties.ts","../src/curves/sample.ts","../src/curves/space.ts","../src/curves/arc/index.ts","../src/curves/rounded/index.ts","../src/curves/spline/index.ts","../src/curves/straight/index.ts","../src/curves/index.ts","../src/visibility.ts","../src/ways.ts","../src/segments.ts","../src/sections.ts","../src/groups/quadtree/index.ts","../src/groups/keys/index.ts","../src/pick.ts","../src/routers/corners.ts","../src/routers/plugs.ts","../src/bench/links.ts","../src/levels.ts","../src/routers/sections.ts","../src/routers/shared.ts","../src/routers/straight.ts","../src/routers/trunks.ts","../src/routers/index.ts","../src/room/index.ts","../src/room/lanes.ts","../src/bench/quality.ts","../src/bench/run.ts","../src/strategies/model.ts","../src/strategies/builtins.ts","../src/bench/curves.ts","../src/bench/room.ts","../src/bench/sections.ts"],"sourcesContent":["/** A point in the plane. */\nexport interface Point {\n readonly x: number;\n readonly y: number;\n}\n\n/** A box with its top-left corner at (`x`, `y`). */\nexport interface Box {\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n}\n\n/** This function gives the distance between two points. */\nexport function dist(a: Point, b: Point): number {\n const dx = a.x - b.x;\n const dy = a.y - b.y;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/** This function gives the center of a box. */\nexport function center(b: Box): Point {\n return { x: b.x + b.w / 2, y: b.y + b.h / 2 };\n}\n\n/** This function gives a box that is larger by `m` on each side. A negative `m` makes the box smaller. */\nexport function inflate(b: Box, m: number): Box {\n return { x: b.x - m, y: b.y - m, w: Math.max(0, b.w + 2 * m), h: Math.max(0, b.h + 2 * m) };\n}\n\n/** This function gives the sum of the lengths of the segments of a polyline. */\nexport function polylineLength(p: readonly Point[]): number {\n let s = 0;\n for (let i = 1; i < p.length; i++) s += dist(p[i - 1]!, p[i]!);\n return s;\n}\n\nconst orient = (a: Point, b: Point, c: Point): number => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n\n/**\n * This function tells if the segments `ab` and `cd` cross at one point inside both of them.\n * Segments that only touch at an end, or that are collinear, do not cross.\n */\nexport function segmentsCross(a: Point, b: Point, c: Point, d: Point): boolean {\n const d1 = orient(c, d, a);\n const d2 = orient(c, d, b);\n const d3 = orient(a, b, c);\n const d4 = orient(a, b, d);\n return d1 * d2 < 0 && d3 * d4 < 0;\n}\n\n/**\n * This function tells if the segment `ab` goes through the inside of the box.\n * The function clips the segment to the box (Liang-Barsky) and asks for a part longer than `eps`.\n */\nexport function segmentHitsBox(a: Point, b: Point, box: Box, eps = 1e-6): boolean {\n return segmentHitsRect(a, b, box.x, box.y, box.x + box.w, box.y + box.h, eps);\n}\n\n/** This function tells if the segment `ab` goes through the inside of the box from (`x0`, `y0`) to (`x1`, `y1`). */\nexport function segmentHitsRect(a: Point, b: Point, x0: number, y0: number, x1: number, y1: number, eps = 1e-6): boolean {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n let t0 = 0;\n let t1 = 1;\n if (dx === 0) {\n if (a.x <= x0 || a.x >= x1) return false;\n } else {\n const ta = (x0 - a.x) / dx;\n const tb = (x1 - a.x) / dx;\n t0 = Math.max(t0, Math.min(ta, tb));\n t1 = Math.min(t1, Math.max(ta, tb));\n if (t0 > t1) return false;\n }\n if (dy === 0) {\n if (a.y <= y0 || a.y >= y1) return false;\n } else {\n const ta = (y0 - a.y) / dy;\n const tb = (y1 - a.y) / dy;\n t0 = Math.max(t0, Math.min(ta, tb));\n t1 = Math.min(t1, Math.max(ta, tb));\n if (t0 > t1) return false;\n }\n return (t1 - t0) * Math.sqrt(dx * dx + dy * dy) > eps;\n}\n\n/** This function gives the distance from a point to a box. The distance is 0 when the point is in the box. */\nexport function pointBoxDistance(p: Point, b: Box): number {\n const qx = Math.max(b.x, Math.min(b.x + b.w, p.x));\n const qy = Math.max(b.y, Math.min(b.y + b.h, p.y));\n return Math.hypot(p.x - qx, p.y - qy);\n}\n\n/** This function gives the distance from a point to the segment `ab`. */\nexport function pointSegmentDistance(p: Point, a: Point, b: Point): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const l2 = dx * dx + dy * dy;\n const t = l2 === 0 ? 0 : Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / l2));\n return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));\n}\n\n/** This function gives the distance from the segment `ab` to a box. The distance is 0 when they touch. */\nexport function segmentBoxDistance(a: Point, b: Point, box: Box): number {\n if (segmentHitsBox(a, b, box, 0) || pointBoxDistance(a, box) === 0 || pointBoxDistance(b, box) === 0) return 0;\n const corners: Point[] = [\n { x: box.x, y: box.y },\n { x: box.x + box.w, y: box.y },\n { x: box.x, y: box.y + box.h },\n { x: box.x + box.w, y: box.y + box.h },\n ];\n let d = Math.min(pointBoxDistance(a, box), pointBoxDistance(b, box));\n for (const c of corners) d = Math.min(d, pointSegmentDistance(c, a, b));\n return d;\n}\n\n/**\n * This function gives the turn at each inner vertex of a polyline, in radians, from -π to π.\n * A positive turn is counterclockwise in a frame with the y axis up. The function skips segments shorter than `eps`.\n */\nexport function turns(p: readonly Point[], eps = 1e-9): number[] {\n const q: Point[] = [];\n for (const v of p) if (q.length === 0 || dist(q[q.length - 1]!, v) > eps) q.push(v);\n const out: number[] = [];\n for (let i = 1; i + 1 < q.length; i++) {\n const a = q[i - 1]!;\n const b = q[i]!;\n const c = q[i + 1]!;\n const cr = (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x);\n const dt = (b.x - a.x) * (c.x - b.x) + (b.y - a.y) * (c.y - b.y);\n out.push(Math.atan2(cr, dt));\n }\n return out;\n}\n\n/** This function counts the vertices of a polyline where the direction changes by more than `minTurn` radians. */\nexport function bendCount(p: readonly Point[], minTurn = 0.05): number {\n return turns(p).filter((t) => Math.abs(t) > minTurn).length;\n}\n\n/**\n * This function counts the inflections of a polyline: the changes of the sign of the turn.\n * A turn smaller than `minTurn` radians does not count. Thus a straight part between two turns keeps their signs.\n */\nexport function inflectionCount(p: readonly Point[], minTurn = 1e-3): number {\n let n = 0;\n let last = 0;\n for (const t of turns(p)) {\n if (Math.abs(t) <= minTurn) continue;\n const s = Math.sign(t);\n if (last !== 0 && s !== last) n++;\n last = s;\n }\n return n;\n}\n\n/**\n * This function gives the discrete Fréchet distance between two polylines (Eiter and Mannila, 1994).\n * The cost is O(|p|·|q|) in time and O(|q|) in memory.\n */\nexport function frechet(p: readonly Point[], q: readonly Point[]): number {\n if (p.length === 0 || q.length === 0) return p.length === q.length ? 0 : Infinity;\n let prev = new Float64Array(q.length);\n let cur = new Float64Array(q.length);\n for (let i = 0; i < p.length; i++) {\n for (let j = 0; j < q.length; j++) {\n const d = dist(p[i]!, q[j]!);\n if (i === 0 && j === 0) cur[j] = d;\n else if (i === 0) cur[j] = Math.max(cur[j - 1]!, d);\n else if (j === 0) cur[j] = Math.max(prev[j]!, d);\n else cur[j] = Math.max(Math.min(prev[j]!, prev[j - 1]!, cur[j - 1]!), d);\n }\n [prev, cur] = [cur, prev];\n }\n return prev[q.length - 1]!;\n}\n","import type { Box, Point } from \"./geom.ts\";\n\n/**\n * A uniform grid of buckets over the plane. A box item goes into each bucket that the box touches.\n * A segment item goes only into the buckets along the segment, so a long diagonal segment stays cheap.\n * A query gives each item in the buckets that it touches, one time each.\n */\nexport class Grid<T> {\n readonly #cell: number;\n readonly #buckets = new Map<number, number[]>();\n readonly #items: T[] = [];\n readonly #ids = new Map<T, number>();\n // The stamp of the last query that gave each item, by the index of the item.\n #seen = new Int32Array(16);\n #stamp = 0;\n\n /** This constructor makes an empty grid with square buckets of side `cell`. */\n constructor(cell: number) {\n this.#cell = Math.max(1e-9, cell);\n }\n\n #key(i: number, j: number): number {\n // The key packs the two bucket indices into one number. Each index stays within ±2^20.\n return (i + 1_048_576) * 2_097_152 + (j + 1_048_576);\n }\n\n #id(item: T): number {\n let id = this.#ids.get(item);\n if (id === undefined) {\n id = this.#items.length;\n this.#ids.set(item, id);\n this.#items.push(item);\n if (id >= this.#seen.length) {\n const seen = new Int32Array(this.#seen.length * 2);\n seen.set(this.#seen);\n this.#seen = seen;\n }\n }\n return id;\n }\n\n #put(id: number, x0: number, y0: number, x1: number, y1: number): void {\n const c = this.#cell;\n const i1 = Math.floor(x1 / c);\n const j1 = Math.floor(y1 / c);\n for (let i = Math.floor(x0 / c); i <= i1; i++) {\n for (let j = Math.floor(y0 / c); j <= j1; j++) {\n const key = this.#key(i, j);\n const list = this.#buckets.get(key);\n if (list === undefined) this.#buckets.set(key, [id]);\n else if (list[list.length - 1] !== id) list.push(id);\n }\n }\n }\n\n #take(stamp: number, x0: number, y0: number, x1: number, y1: number, visit: (item: T) => void): void {\n const c = this.#cell;\n const i1 = Math.floor(x1 / c);\n const j1 = Math.floor(y1 / c);\n const seen = this.#seen;\n for (let i = Math.floor(x0 / c); i <= i1; i++) {\n for (let j = Math.floor(y0 / c); j <= j1; j++) {\n const list = this.#buckets.get(this.#key(i, j));\n if (list === undefined) continue;\n for (const id of list) {\n if (seen[id] === stamp) continue;\n seen[id] = stamp;\n visit(this.#items[id]!);\n }\n }\n }\n }\n\n /**\n * This method gives each item in the buckets along the segment `ab`, widened by `margin`, to `visit`, one time each.\n * The buckets are those of `#segment`, in the same order, so the items come in the same order.\n * A bucket in the range of the step before has no new item, so the walk skips it.\n * The walk stops when `visit` gives true, and then the method gives true.\n */\n #walk(a: Point, b: Point, margin: number, visit: (item: T) => boolean | void): boolean {\n const stamp = ++this.#stamp;\n const c = this.#cell;\n const items = this.#items;\n const n = Math.max(1, Math.ceil(Math.hypot(b.x - a.x, b.y - a.y) / (c / 2)));\n let px = a.x;\n let py = a.y;\n // The bucket range of the step before. The first step has none.\n let pi0 = 1;\n let pi1 = 0;\n let pj0 = 1;\n let pj1 = 0;\n for (let k = 1; k <= n; k++) {\n const qx = k === n ? b.x : a.x + ((b.x - a.x) * k) / n;\n const qy = k === n ? b.y : a.y + ((b.y - a.y) * k) / n;\n const i0 = Math.floor((Math.min(px, qx) - margin) / c);\n const j0 = Math.floor((Math.min(py, qy) - margin) / c);\n const i1 = Math.floor((Math.max(px, qx) + margin) / c);\n const j1 = Math.floor((Math.max(py, qy) + margin) / c);\n // A visit can add an item and so replace the array of stamps. Each step reads it again, as `#take` does.\n const seen = this.#seen;\n for (let i = i0; i <= i1; i++) {\n const before = i >= pi0 && i <= pi1;\n for (let j = j0; j <= j1; j++) {\n if (before && j >= pj0 && j <= pj1) continue;\n const list = this.#buckets.get(this.#key(i, j));\n if (list === undefined) continue;\n for (const id of list) {\n if (seen[id] === stamp) continue;\n seen[id] = stamp;\n if (visit(items[id]!) === true) return true;\n }\n }\n }\n pi0 = i0;\n pi1 = i1;\n pj0 = j0;\n pj1 = j1;\n px = qx;\n py = qy;\n }\n return false;\n }\n\n // The buckets along a segment, widened by `margin`: the boxes of steps of at most half a bucket.\n #segment(a: Point, b: Point, margin: number, each: (x0: number, y0: number, x1: number, y1: number) => void): void {\n const n = Math.max(1, Math.ceil(Math.hypot(b.x - a.x, b.y - a.y) / (this.#cell / 2)));\n let px = a.x;\n let py = a.y;\n for (let k = 1; k <= n; k++) {\n const qx = k === n ? b.x : a.x + ((b.x - a.x) * k) / n;\n const qy = k === n ? b.y : a.y + ((b.y - a.y) * k) / n;\n each(Math.min(px, qx) - margin, Math.min(py, qy) - margin, Math.max(px, qx) + margin, Math.max(py, qy) + margin);\n px = qx;\n py = qy;\n }\n }\n\n /** This method adds an item with its bounding box. */\n add(item: T, b: Box): void {\n this.#put(this.#id(item), b.x, b.y, b.x + b.w, b.y + b.h);\n }\n\n /** This method adds the segment `ab` as an item. */\n addSegment(item: T, a: Point, b: Point): void {\n const id = this.#id(item);\n this.#segment(a, b, 0, (x0, y0, x1, y1) => this.#put(id, x0, y0, x1, y1));\n }\n\n /** This method gives each item whose buckets touch the box to `visit`, one time each. */\n query(b: Box, visit: (item: T) => void): void {\n this.#take(++this.#stamp, b.x, b.y, b.x + b.w, b.y + b.h, visit);\n }\n\n /** This method gives each item whose buckets come within `margin` of the segment `ab` to `visit`, one time each. */\n querySegment(a: Point, b: Point, margin: number, visit: (item: T) => void): void {\n this.#walk(a, b, margin, (item) => {\n visit(item);\n });\n }\n\n /**\n * This method tells if `test` gives true for an item whose buckets come within `margin` of the segment `ab`.\n * It gives the items in the order of `querySegment`, and it stops at the first item that passes the test.\n */\n someSegment(a: Point, b: Point, margin: number, test: (item: T) => boolean): boolean {\n return this.#walk(a, b, margin, test);\n }\n}\n\n/** This function gives the bounding box of the segment `ab`. */\nexport function segmentBounds(a: Point, b: Point): Box {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n return { x, y, w: Math.abs(a.x - b.x), h: Math.abs(a.y - b.y) };\n}\n","import type { Box, Point } from \"./geom.ts\";\n\n/** A side of a node box. */\nexport type Side = \"north\" | \"east\" | \"south\" | \"west\";\n\n/**\n * A plug of a node: a place where edges go into the node.\n * A plug with `at` is fixed. The router does not move it. A plug without `at` is free: the router places it.\n */\nexport interface Port {\n readonly id: string;\n /** This point is the fixed place of the plug, relative to the top-left corner of the node box. */\n readonly at?: Point;\n /** This side is where a free plug goes. Without it, the router picks the side. */\n readonly side?: Side;\n}\n\n/** A node: a box that routes must not go through. */\nexport interface Node {\n readonly id: string;\n readonly box: Box;\n readonly ports?: readonly Port[];\n /** This data is free for the grouping rules of the nodes. The rule `keys` reads the string `data.group` by default. */\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\n/** One end of an edge: a node, and optionally one plug of that node. */\nexport interface End {\n readonly node: string;\n readonly port?: string;\n}\n\n/** An edge between two nodes. `data` is free for the grouping rules. */\nexport interface Edge {\n readonly id: string;\n readonly source: End;\n readonly target: End;\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\n/** The input of a router. */\nexport interface Graph {\n readonly nodes: readonly Node[];\n readonly edges: readonly Edge[];\n}\n\n/** The route of one edge: a polyline from the source plug to the target plug, in absolute coordinates. */\nexport interface Route {\n readonly edge: string;\n readonly points: readonly Point[];\n}\n\n/**\n * One zoom level of a result. Each shown item is a node or a group of nodes.\n * Each link joins two shown items and carries the count of the edges that it stands for.\n */\nexport interface Level {\n readonly depth: number;\n readonly items: readonly LevelItem[];\n readonly links: readonly LevelLink[];\n}\n\n/** A shown item of a level: one node, or a group that stands for its nodes. */\nexport interface LevelItem {\n readonly id: string;\n readonly box: Box;\n readonly nodes: readonly string[];\n}\n\n/** A link of a level: the edges between two shown items, drawn as one path. */\nexport interface LevelLink {\n readonly source: string;\n readonly target: string;\n readonly count: number;\n readonly points: readonly Point[];\n}\n\n/** The output of a router. `levels` is present when the router makes zoom levels. */\nexport interface Result {\n readonly routes: readonly Route[];\n readonly levels?: readonly Level[];\n readonly bundles?: readonly Bundle[];\n /** The stretches of way that several routes share, if the router gives them. */\n readonly runs?: readonly SharedRun[];\n}\n\n/**\n * A bundle: edges from one node that share one plug and one trunk. Then the edges fan out to their targets.\n * A renderer draws a bundle as one fat edge with a count, or as one lane for each edge.\n */\nexport interface Bundle {\n readonly id: string;\n /** The key that the grouping rule gave each edge of the bundle. */\n readonly key: string;\n /** The node where the edges share their plug. */\n readonly node: string;\n /** The edges in lane order. Lane 0 turns most to the left of the trunk, in a frame with the y axis down. */\n readonly edges: readonly string[];\n /** The shared start of each route of the bundle, from the plug to the split point. */\n readonly trunk: readonly Point[];\n}\n\n/**\n * A stretch of way that several routes share, with the same points. Each route of `edges` has `points` in it,\n * in this order or in the reverse order. A renderer draws a run as one fat line, or as one lane for each edge.\n */\nexport interface SharedRun {\n readonly id: string;\n /** The key of the grouping rule of the edges. */\n readonly key: string;\n readonly points: readonly Point[];\n /** The edges in lane order. Lane 0 is on the left of the run, from its first point to its last. The y axis points down. */\n readonly edges: readonly string[];\n}\n\n/** A grouping rule gives each edge a key. The edges from one plug with one key make a bundle. An edge without a key stays alone. */\nexport type GroupRule = (edge: Edge) => string | undefined;\n\n/** A router: a strategy with a name. The same input must give the same result. */\nexport interface Router {\n readonly name: string;\n /** The benchmark skips a fixture with more nodes than this. Without it, the router takes each fixture. */\n readonly maxNodes?: number;\n route(graph: Graph): Result;\n}\n\n/** This function gives a map from the id of each node to the node. */\nexport function nodeIndex(g: Graph): Map<string, Node> {\n const m = new Map<string, Node>();\n for (const n of g.nodes) m.set(n.id, n);\n return m;\n}\n\n/** This function gives the absolute place of a fixed plug, or `undefined` for a free plug or no plug. */\nexport function fixedPortPoint(node: Node, end: End): Point | undefined {\n if (end.port === undefined) return undefined;\n const p = node.ports?.find((q) => q.id === end.port);\n if (p?.at === undefined) return undefined;\n return { x: node.box.x + p.at.x, y: node.box.y + p.at.y };\n}\n","import type { Box, Point } from \"./geom.ts\";\nimport { Grid } from \"./grid.ts\";\nimport type { Edge, Graph, Node, Port, Side } from \"./model.ts\";\n\n/** This function gives a seeded random source with values in [0, 1) (mulberry32). */\nexport function rng(seed: number): () => number {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * The ways a fixture puts its nodes and picks its edges. In `collections`, each cluster is one collection,\n * and some nodes link to many nodes of one other collection (a fan-out).\n */\nexport type FixtureKind = \"uniform\" | \"clustered\" | \"grid\" | \"hubs\" | \"collections\";\n\n/** The parameters of a generated graph. */\nexport interface FixtureSpec {\n readonly name: string;\n readonly kind: FixtureKind;\n readonly nodes: number;\n /** The number of edges is about `nodes × edgesPerNode`. */\n readonly edgesPerNode: number;\n readonly seed: number;\n /** This share of the edges, from 0 to 1, joins a node near the source. */\n readonly locality?: number;\n /** This share of the nodes, from 0 to 1, has one fixed plug that its outgoing edges use. */\n readonly fixedPorts?: number;\n}\n\n/** The fixtures of the benchmark, from 10 to 100 000 nodes. */\nexport const FIXTURES: readonly FixtureSpec[] = [\n { name: \"tiny-uniform\", kind: \"uniform\", nodes: 10, edgesPerNode: 1.5, seed: 1 },\n { name: \"small-clustered\", kind: \"clustered\", nodes: 100, edgesPerNode: 2, seed: 2, fixedPorts: 0.2 },\n { name: \"grid-400\", kind: \"grid\", nodes: 400, edgesPerNode: 2, seed: 3 },\n { name: \"mid-uniform\", kind: \"uniform\", nodes: 1000, edgesPerNode: 2, seed: 4 },\n { name: \"mid-clustered\", kind: \"clustered\", nodes: 1000, edgesPerNode: 3, seed: 5, fixedPorts: 0.2 },\n { name: \"mid-hubs\", kind: \"hubs\", nodes: 1000, edgesPerNode: 2, seed: 6 },\n { name: \"mid-fanout\", kind: \"collections\", nodes: 1000, edgesPerNode: 2, seed: 9 },\n { name: \"large-clustered\", kind: \"clustered\", nodes: 10_000, edgesPerNode: 3, seed: 7 },\n { name: \"huge-clustered\", kind: \"clustered\", nodes: 100_000, edgesPerNode: 2, seed: 8 },\n];\n\nconst COLLECTIONS = [\"users\", \"modes\", \"speeds\", \"scores\", \"teams\"] as const;\nconst SIDES: readonly Side[] = [\"north\", \"east\", \"south\", \"west\"];\nconst GAP = 12;\nconst SPACING = 90;\n\n/**\n * This function makes the graph of a fixture. The same spec always gives the same graph.\n * Node boxes do not overlap, and a gap of 12 units stays between them.\n */\nexport function makeFixture(spec: FixtureSpec): Graph {\n const R = rng(spec.seed * 2654435761 + spec.nodes);\n const gauss = (): number => Math.sqrt(-2 * Math.log(R() + 1e-12)) * Math.cos(2 * Math.PI * R());\n const side = Math.sqrt(spec.nodes) * SPACING;\n const grid = new Grid<Box>(SPACING);\n const nodes: Node[] = [];\n const clusterOf: number[] = [];\n const free = (b: Box): boolean => {\n let ok = true;\n const g: Box = { x: b.x - GAP, y: b.y - GAP, w: b.w + 2 * GAP, h: b.h + 2 * GAP };\n grid.query(g, (o) => {\n if (ok && o.x < g.x + g.w && g.x < o.x + o.w && o.y < g.y + g.h && g.y < o.y + o.h) ok = false;\n });\n return ok;\n };\n const centers: Point[] = Array.from({ length: Math.max(3, Math.round(Math.sqrt(spec.nodes) / 3)) }, () => ({\n x: side * (0.1 + 0.8 * R()),\n y: side * (0.1 + 0.8 * R()),\n }));\n const spread = side / (2.5 * Math.sqrt(centers.length));\n const cols = Math.ceil(Math.sqrt(spec.nodes));\n let tries = 0;\n while (nodes.length < spec.nodes && tries++ < spec.nodes * 200) {\n const w = 30 + Math.floor(R() * 30);\n const h = 18 + Math.floor(R() * 12);\n let cx: number;\n let cy: number;\n let cluster = -1;\n if (spec.kind === \"grid\") {\n const i = nodes.length;\n cx = ((i % cols) + 0.5) * SPACING;\n cy = (Math.floor(i / cols) + 0.5) * SPACING;\n } else if (spec.kind === \"clustered\" || spec.kind === \"collections\") {\n cluster = Math.floor(R() * centers.length);\n const c = centers[cluster]!;\n cx = c.x + gauss() * spread;\n cy = c.y + gauss() * spread;\n } else {\n cx = R() * side;\n cy = R() * side;\n }\n const box: Box = { x: Math.round(cx - w / 2), y: Math.round(cy - h / 2), w, h };\n if (spec.kind !== \"grid\" && !free(box)) continue;\n grid.add(box, box);\n clusterOf.push(cluster);\n const id = `n${nodes.length}`;\n if (R() < (spec.fixedPorts ?? 0)) {\n const s = SIDES[Math.floor(R() * 4)]!;\n const t = 0.2 + 0.6 * R();\n const at: Point =\n s === \"north\" ? { x: w * t, y: 0 } : s === \"south\" ? { x: w * t, y: h } : s === \"west\" ? { x: 0, y: h * t } : { x: w, y: h * t };\n const ports: Port[] = [{ id: \"out\", at: { x: Math.round(at.x), y: Math.round(at.y) } }];\n nodes.push({ id, box, ports });\n } else nodes.push({ id, box });\n }\n return { nodes, edges: makeEdges(spec, nodes, clusterOf, R) };\n}\n\nfunction makeEdges(spec: FixtureSpec, nodes: readonly Node[], clusterOf: readonly number[], R: () => number): Edge[] {\n const n = nodes.length;\n if (n < 2) return [];\n const locality = spec.locality ?? 0.65;\n const near = new Grid<number>(SPACING * 2);\n nodes.forEach((v, i) => near.add(i, v.box));\n const kindOf =\n spec.kind === \"collections\"\n ? clusterOf.map((c) => `${COLLECTIONS[c % COLLECTIONS.length]!}-${c}`)\n : nodes.map(() => COLLECTIONS[Math.floor(R() * COLLECTIONS.length)]!);\n // Hubs: a few nodes get most of the far edges (preferential attachment by a power law).\n const pickFar = (): number => (spec.kind === \"hubs\" ? Math.floor(n * R() ** 3) : Math.floor(R() * n));\n const target = Math.round(n * spec.edgesPerNode);\n const seen = new Set<string>();\n const edges: Edge[] = [];\n const add = (u: number, v: number): void => {\n const key = u < v ? `${u}-${v}` : `${v}-${u}`;\n if (u === v || seen.has(key)) return;\n seen.add(key);\n const src = nodes[u]!;\n edges.push({\n id: `e${edges.length}`,\n source: src.ports ? { node: src.id, port: \"out\" } : { node: src.id },\n target: { node: nodes[v]!.id },\n data: { collection: kindOf[v]! },\n });\n };\n if (spec.kind === \"collections\") {\n // Six of ten edges are fan-outs: a node links to 4 to 15 nodes of one other cluster.\n const members = new Map<number, number[]>();\n clusterOf.forEach((c, i) => {\n const list = members.get(c);\n if (list) list.push(i);\n else members.set(c, [i]);\n });\n const clusters = [...members.keys()].sort((a, c) => a - c);\n let rounds = 0;\n while (edges.length < target * 0.6 && clusters.length > 1 && rounds++ < target) {\n const u = Math.floor(R() * n);\n const others = clusters.filter((c) => c !== clusterOf[u]);\n const pool = members.get(others[Math.floor(R() * others.length)]!)!;\n const fan = 4 + Math.floor(R() * 12);\n for (let i = 0; i < fan; i++) add(u, pool[Math.floor(R() * pool.length)]!);\n }\n }\n let tries = 0;\n while (edges.length < target && tries++ < target * 30) {\n const u = Math.floor(R() * n);\n let v = -1;\n if (R() < locality) {\n const b = nodes[u]!.box;\n const cand: number[] = [];\n for (let r = SPACING; cand.length < 8 && r < SPACING * 64; r *= 2) {\n cand.length = 0;\n near.query({ x: b.x - r, y: b.y - r, w: b.w + 2 * r, h: b.h + 2 * r }, (i) => {\n if (i !== u) cand.push(i);\n });\n }\n cand.sort((a, c) => a - c);\n if (cand.length) v = cand[Math.floor(R() * cand.length)]!;\n } else v = pickFar();\n if (v >= 0) add(u, v);\n }\n return edges;\n}\n","import { makeFixture, rng } from \"./fixtures.ts\";\nimport type { Edge, Graph, Node } from \"./model.ts\";\n\n/**\n * A board of made-up data that shows one known defect of the routes or of the zoom levels.\n * The benchmark races the routers on each case, and the measures of `measureLinks` give a number for the defect.\n */\nexport interface CaseBoard {\n readonly name: string;\n /** The defect that the board shows, in a few words. */\n readonly defect: string;\n /** This function makes the graph. The same function always gives the same graph. */\n readonly make: () => Graph;\n}\n\n/** A board while it grows: the functions add nodes and edges in order. */\nclass Board {\n readonly nodes: Node[] = [];\n readonly edges: Edge[] = [];\n readonly #pairs = new Set<string>();\n\n node(id: string, x: number, y: number, w: number, h: number): string {\n this.nodes.push({ id, box: { x, y, w, h } });\n return id;\n }\n\n /** This method adds an edge. It adds nothing for a loop or for a second edge between the same two nodes. */\n link(source: string, target: string): void {\n const key = source < target ? `${source}|${target}` : `${target}|${source}`;\n if (source === target || this.#pairs.has(key)) return;\n this.#pairs.add(key);\n this.edges.push({ id: `e${this.edges.length}`, source: { node: source }, target: { node: target } });\n }\n\n graph(): Graph {\n return { nodes: this.nodes, edges: this.edges };\n }\n}\n\n/**\n * This function makes a dense board: 150 nodes in tight clusters. At the far view, the boxes of the groups overlap.\n * Then a level link starts or ends in a group that another group covers.\n */\nexport function denseGroupsBoard(): Graph {\n return makeFixture({ name: \"dense-groups\", kind: \"clustered\", nodes: 150, edgesPerNode: 2, seed: 3 });\n}\n\n/**\n * This function makes a board of three rows of 32 cards. Each card links to the next card of its row.\n * Forty long links join cards far apart. The hub of a section is near the middle of its cards.\n * So a long link climbs to hubs behind its source or past its target, and comes back.\n */\nexport function hubChainBoard(): Graph {\n const R = rng(3);\n const b = new Board();\n const rows = 3;\n const cols = 32;\n const gap = 48;\n const id = (r: number, c: number): string => `c${r}-${c}`;\n for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) b.node(id(r, c), c * (80 + gap), r * (36 + gap), 80, 36);\n for (let r = 0; r < rows; r++) for (let c = 0; c + 1 < cols; c++) b.link(id(r, c), id(r, c + 1));\n for (let n = 0; n < 40; n++) {\n const r = Math.floor(R() * rows);\n const c = Math.floor(R() * cols);\n const span = Math.floor(cols / 8 + (R() * cols) / 2);\n if (c + span < cols) b.link(id(r, c), id((r + 1) % rows, c + span));\n }\n return b.graph();\n}\n\n/**\n * This function makes a board of 32 groups in 8 columns and 4 rows. Each group has 4 cards in a square.\n * The cards of a group link in a chain, and 96 random links join cards of two groups.\n * On a level with many groups, some level links go around the outer edge of the board.\n */\nexport function manyGroupsBoard(): Graph {\n const R = rng(7);\n const b = new Board();\n const cols = 8;\n const rows = 4;\n const per = 4;\n const w = 60;\n const h = 30;\n const cardGap = 12;\n const groupGap = 60;\n const side = Math.ceil(Math.sqrt(per));\n const gw = side * w + (side - 1) * cardGap;\n const gh = Math.ceil(per / side) * h + (Math.ceil(per / side) - 1) * cardGap;\n const groups: string[][] = [];\n for (let r = 0; r < rows; r++)\n for (let c = 0; c < cols; c++) {\n const list: string[] = [];\n for (let i = 0; i < per; i++) {\n const x = c * (gw + groupGap) + (i % side) * (w + cardGap);\n const y = r * (gh + groupGap) + Math.floor(i / side) * (h + cardGap);\n list.push(b.node(`g${r}-${c}-${i}`, x, y, w, h));\n }\n groups.push(list);\n }\n for (const list of groups) for (let i = 1; i < list.length; i++) b.link(list[i - 1]!, list[i]!);\n const pick = (list: readonly string[]): string => list[Math.floor(R() * list.length)]!;\n for (let n = 0; n < groups.length * 3; n++) b.link(pick(groups[Math.floor(R() * groups.length)]!), pick(groups[Math.floor(R() * groups.length)]!));\n return b.graph();\n}\n\n/**\n * This function makes the far view of a board after a host layout packs it.\n * The board has 96 boxes of one size in a grid of 12 columns and 8 rows.\n * The boxes touch, with no gap between them. Each box links to a box near it, and 48 long links join boxes far apart.\n * The links have no channel between the boxes. The roadmap item ROOM measures this board before and after `makeRoom`.\n *\n * The board is not in `CASES`, because the digests of the router fix the output on each board of `CASES`.\n */\nexport function packedGridBoard(): Graph {\n const R = rng(11);\n const b = new Board();\n const cols = 12;\n const rows = 8;\n const w = 140;\n const h = 90;\n const id = (r: number, c: number): string => `p${r}-${c}`;\n for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) b.node(id(r, c), c * w, r * h, w, h);\n const step = (): number => Math.floor(R() * 5) - 2;\n for (let r = 0; r < rows; r++)\n for (let c = 0; c < cols; c++) {\n const rr = Math.max(0, Math.min(rows - 1, r + step()));\n const cc = Math.max(0, Math.min(cols - 1, c + step()));\n b.link(id(r, c), id(rr, cc));\n }\n for (let n = 0; n < 48; n++) b.link(id(Math.floor(R() * rows), Math.floor(R() * cols)), id(Math.floor(R() * rows), Math.floor(R() * cols)));\n return b.graph();\n}\n\n/** The case boards of the benchmark. Each board has a few hundred nodes at most, so the benchmark races them on each run. */\nexport const CASES: readonly CaseBoard[] = [\n { name: \"case-dense-groups\", defect: \"Groups overlap at the far view, and level links go through other groups.\", make: denseGroupsBoard },\n { name: \"case-hub-chain\", defect: \"A route climbs a chain of hubs away from its target and comes back.\", make: hubChainBoard },\n { name: \"case-many-groups\", defect: \"On a level with many groups, links go around the outer edge of the board.\", make: manyGroupsBoard },\n];\n","import { center, type Box, type Point } from \"./geom.ts\";\nimport { fixedPortPoint, type End, type Node, type Side } from \"./model.ts\";\n\n/** A plug: the point where a route leaves or enters a node, and the outward normal of its side. */\nexport interface Plug {\n readonly point: Point;\n readonly normal: Point;\n}\n\n/** The outward normal of each side, in a frame with the y axis down. */\nexport const SIDE_NORMAL: Readonly<Record<Side, Point>> = {\n north: { x: 0, y: -1 },\n east: { x: 1, y: 0 },\n south: { x: 0, y: 1 },\n west: { x: -1, y: 0 },\n};\n\n/** This function gives the side of the box that is nearest to the point. */\nexport function nearestSide(box: Box, p: Point): Side {\n const d: [Side, number][] = [\n [\"north\", Math.abs(p.y - box.y)],\n [\"east\", Math.abs(box.x + box.w - p.x)],\n [\"south\", Math.abs(box.y + box.h - p.y)],\n [\"west\", Math.abs(p.x - box.x)],\n ];\n let best = d[0]!;\n for (const x of d) if (x[1] < best[1]) best = x;\n return best[0];\n}\n\n/**\n * This function gives the side that faces `toward`: the side of the larger component of the direction from the center.\n * Thus the angle between the normal of the side and that direction is 45° or less.\n */\nexport function sideToward(box: Box, toward: Point): Side {\n const c = center(box);\n const dx = toward.x - c.x;\n const dy = toward.y - c.y;\n if (Math.abs(dx) >= Math.abs(dy)) return dx >= 0 ? \"east\" : \"west\";\n return dy >= 0 ? \"south\" : \"north\";\n}\n\n/**\n * This function gives the point on a side of the box that is nearest to the line from the center to `toward`.\n * The point stays away from the corners by `inset`, or by a quarter of the side when the side is short.\n */\nexport function pointOnSide(box: Box, side: Side, toward: Point, inset = 6): Point {\n const c = center(box);\n const dx = toward.x - c.x;\n const dy = toward.y - c.y;\n const clamp = (v: number, lo: number, len: number): number => {\n const m = Math.min(inset, len / 4);\n return Math.max(lo + m, Math.min(lo + len - m, v));\n };\n if (side === \"east\" || side === \"west\") {\n const x = side === \"east\" ? box.x + box.w : box.x;\n const y = dx === 0 ? c.y : c.y + (dy * (x - c.x)) / dx;\n return { x, y: clamp(y, box.y, box.h) };\n }\n const y = side === \"south\" ? box.y + box.h : box.y;\n const x = dy === 0 ? c.x : c.x + (dx * (y - c.y)) / dy;\n return { x: clamp(x, box.x, box.w), y };\n}\n\n/**\n * This function places the plug of one end of an edge. A fixed plug stays at its point. A plug with a side stays on that side.\n * The router places a free plug on the side that faces `toward`.\n */\nexport function placePlug(node: Node, end: End, toward: Point): Plug {\n const fixed = fixedPortPoint(node, end);\n const port = end.port === undefined ? undefined : node.ports?.find((p) => p.id === end.port);\n if (fixed) return { point: fixed, normal: SIDE_NORMAL[port?.side ?? nearestSide(node.box, fixed)] };\n const side = port?.side ?? sideToward(node.box, toward);\n return { point: pointOnSide(node.box, side, toward), normal: SIDE_NORMAL[side] };\n}\n","import { dist, type Point } from \"./geom.ts\";\n\n/** The options of the inflection rule. */\nexport interface InflectionOptions {\n /** The half width of the axis and diagonal bands, in radians. The default is 7°. */\n readonly tol?: number;\n /** The number of segments of the curve. The default is 24. */\n readonly samples?: number;\n /** The largest angle between the tangent and the chord, in radians. The default is 1.35 (approximately 77°). */\n readonly maxAngle?: number;\n}\n\n/**\n * This function gives the number of inflections that the rule asks for a chord at the angle `angle` (radians).\n * It gives 0 near an axis, 1 near a diagonal and 2 between them. The bands are `tol` wide on each side.\n */\nexport function inflectionSector(angle: number, tol: number = (7 * Math.PI) / 180): 0 | 1 | 2 {\n const q = Math.PI / 2;\n const mod = ((angle % q) + q) % q;\n if (mod < tol || q - mod < tol) return 0;\n if (Math.abs(mod - q / 2) < tol) return 1;\n return 2;\n}\n\n/**\n * This function draws the curve of the inflection rule from the plug `p0` to `target`.\n * The curve leaves `p0` along `normal`. In the frame of the chord, its side offset f has f(0) = f(L) = 0 and f'(0) = tan θ.\n * Here θ is the angle from the chord to the normal. A polynomial of degree 2, 3 or 4 gives 0, 1 or 2 inflections,\n * at 1/2, or at 1/3 and 2/3, of the chord.\n */\nexport function inflectionCurve(p0: Point, normal: Point, target: Point, options: InflectionOptions = {}): Point[] {\n const L = dist(p0, target);\n if (L === 0) return [p0, target];\n const ux = (target.x - p0.x) / L;\n const uy = (target.y - p0.y) / L;\n const k = inflectionSector(Math.atan2(uy, ux), options.tol);\n const maxAngle = options.maxAngle ?? 1.35;\n const th = -Math.atan2(normal.x * uy - normal.y * ux, normal.x * ux + normal.y * uy);\n const d = Math.tan(Math.max(-maxAngle, Math.min(maxAngle, th)));\n const f =\n k === 0\n ? (s: number): number => (-d / L) * s * s + d * s\n : k === 1\n ? (s: number): number => ((12 * d) / (L * L)) * (s ** 3 / 6 - (L * s * s) / 4) + d * s\n : (s: number): number => ((-36 * d) / L ** 3) * (s ** 4 / 12 - (L * s ** 3) / 6 + (L * L * s * s) / 9) + d * s;\n const n = Math.max(2, options.samples ?? 24);\n const out: Point[] = [];\n for (let i = 0; i <= n; i++) {\n if (i === n) {\n out.push(target);\n break;\n }\n const s = (L * i) / n;\n const o = f(s);\n out.push({ x: p0.x + ux * s - uy * o, y: p0.y + uy * s + ux * o });\n }\n out[0] = p0;\n return out;\n}\n\n/**\n * This function rounds each inner vertex of a polyline with a quadratic Bézier curve.\n * The curve starts and ends at most `radius` from the vertex, and at most half of each segment. The ends of the polyline stay.\n */\nexport function roundCorners(p: readonly Point[], radius: number, steps = 4): Point[] {\n if (p.length < 3 || radius <= 0) return [...p];\n const out: Point[] = [p[0]!];\n for (let i = 1; i + 1 < p.length; i++) {\n const a = p[i - 1]!;\n const v = p[i]!;\n const b = p[i + 1]!;\n const la = dist(a, v);\n const lb = dist(v, b);\n const r = Math.min(radius, la / 2, lb / 2);\n if (r <= 0) {\n out.push(v);\n continue;\n }\n const p1 = { x: v.x + ((a.x - v.x) * r) / la, y: v.y + ((a.y - v.y) * r) / la };\n const p2 = { x: v.x + ((b.x - v.x) * r) / lb, y: v.y + ((b.y - v.y) * r) / lb };\n for (let k = 0; k <= steps; k++) {\n const t = k / steps;\n const u = 1 - t;\n out.push({ x: u * u * p1.x + 2 * u * t * v.x + t * t * p2.x, y: u * u * p1.y + 2 * u * t * v.y + t * t * p2.y });\n }\n }\n out.push(p[p.length - 1]!);\n return out;\n}\n","import type { Point } from \"../geom.ts\";\n\n/**\n * A type of curve for a route.\n *\n * - `straight`: the polyline as it is.\n * - `rounded`: a quadratic Bezier curve at each corner, as `roundCorners` draws it.\n * - `spline`: a centripetal Catmull-Rom spline through the points. It does not overshoot or make loops.\n * - `arc`: a circular arc at each corner, tangent to the two legs.\n */\nexport type CurveType = \"straight\" | \"rounded\" | \"spline\" | \"arc\";\n\n/** The curve types, in the order of the benchmark. */\nexport const CURVE_TYPES: readonly CurveType[] = [\"straight\", \"rounded\", \"spline\", \"arc\"];\n\n/** The start of a curve: the pen goes to `to` and draws nothing. */\nexport interface MoveSegment {\n readonly kind: \"move\";\n readonly to: Point;\n}\n\n/** A straight line from the end of the segment before to `to`. */\nexport interface LineSegment {\n readonly kind: \"line\";\n readonly to: Point;\n}\n\n/** A cubic Bezier curve from the end of the segment before to `to`, with the control points `c1` and `c2`. */\nexport interface CubicSegment {\n readonly kind: \"cubic\";\n readonly c1: Point;\n readonly c2: Point;\n readonly to: Point;\n}\n\n/**\n * A circular arc from the end of the segment before to `to`. The arc has its center at `center` and the radius `radius`.\n * It starts at the angle `start` and turns by `sweep` radians. A positive `sweep` turns from the x axis to the y axis.\n * On a canvas, `ctx.arc(center.x, center.y, radius, start, start + sweep, sweep < 0)` draws it.\n */\nexport interface ArcSegment {\n readonly kind: \"arc\";\n readonly center: Point;\n readonly radius: number;\n readonly start: number;\n readonly sweep: number;\n readonly to: Point;\n}\n\n/**\n * A segment of a curve. A curve is a list of segments: one `move` first, then lines, cubic curves and arcs.\n * A renderer maps the list to SVG path data, to canvas calls or to the vertices of a mesh.\n */\nexport type CurveSegment = MoveSegment | LineSegment | CubicSegment | ArcSegment;\n\n/** This function gives the points of a polyline without the points that are nearer than `eps` to the point before them. */\nexport function distinctPoints(points: readonly Point[], eps = 1e-9): Point[] {\n const out: Point[] = [];\n for (const p of points) {\n const q = out[out.length - 1];\n if (q === undefined || Math.hypot(p.x - q.x, p.y - q.y) > eps) out.push(p);\n }\n return out;\n}\n","import { dist, inflate, pointBoxDistance, segmentHitsBox, type Box, type Point } from \"../geom.ts\";\nimport { Grid } from \"../grid.ts\";\nimport { fixedPortPoint, nodeIndex, type Graph, type Node, type Result } from \"../model.ts\";\n\n/** A broken hard rule. A correct router has none. */\nexport interface Violation {\n readonly rule:\n | \"complete\"\n | \"ends-at-plugs\"\n | \"fixed-plugs\"\n | \"no-pass-through\"\n | \"counts-sum\"\n | \"link-ends\"\n | \"bundle-trunk\"\n | \"run-shared\";\n readonly edge?: string;\n readonly detail: string;\n}\n\n/** The tolerance of the hard rules, in units of the plane. */\nexport const TOLERANCE = 0.5;\n\n/**\n * This function checks the hard rules of a result. Each edge has one route, and each route starts and ends at its nodes.\n * Fixed plugs stay in place. No route goes through a node that is not one of its ends. The counts of each level add up.\n * Each link of a level starts on the box of its source and ends on the box of its target.\n *\n * Each route of a bundle starts with its trunk, and an edge is in one bundle at most.\n * Each run has two edges or more, and the route of each edge holds the points of the run in a row.\n * The function gives at most `limit` violations.\n */\nexport function checkProperties(graph: Graph, result: Result, limit = 100): Violation[] {\n const out: Violation[] = [];\n const add = (v: Violation): boolean => {\n out.push(v);\n return out.length >= limit;\n };\n const byId = nodeIndex(graph);\n const grid = new Grid<Node>(180);\n for (const n of graph.nodes) grid.add(n, n.box);\n const routes = new Map<string, (typeof result.routes)[number]>();\n for (const r of result.routes) routes.set(r.edge, r);\n for (const e of graph.edges) {\n const r = routes.get(e.id);\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n if (!r || r.points.length < 2) {\n if (add({ rule: \"complete\", edge: e.id, detail: \"no route\" })) return out;\n continue;\n }\n const a = r.points[0]!;\n const b = r.points[r.points.length - 1]!;\n if (pointBoxDistance(a, s.box) > TOLERANCE || pointBoxDistance(b, t.box) > TOLERANCE)\n if (add({ rule: \"ends-at-plugs\", edge: e.id, detail: \"an end of the route is away from its node\" })) return out;\n const fs = fixedPortPoint(s, e.source);\n const ft = fixedPortPoint(t, e.target);\n if ((fs && dist(fs, a) > TOLERANCE) || (ft && dist(ft, b) > TOLERANCE))\n if (add({ rule: \"fixed-plugs\", edge: e.id, detail: \"the route does not start or end at its fixed plug\" })) return out;\n for (let i = 1; i < r.points.length; i++) {\n const p = r.points[i - 1]!;\n const q = r.points[i]!;\n let hit: Node | undefined;\n grid.querySegment(p, q, 0, (n) => {\n if (!hit && n !== s && n !== t && segmentHitsBox(p, q, inflate(n.box, -TOLERANCE))) hit = n;\n });\n if (hit) {\n if (add({ rule: \"no-pass-through\", edge: e.id, detail: `segment ${i} goes through ${hit.id}` })) return out;\n break;\n }\n }\n }\n const bundled = new Set<string>();\n for (const b of result.bundles ?? []) {\n for (const id of b.edges) {\n const r = routes.get(id);\n const shares = r !== undefined && r.points.length >= b.trunk.length && b.trunk.every((p, i) => dist(p, r.points[i]!) <= TOLERANCE);\n if (bundled.has(id) || !shares)\n if (add({ rule: \"bundle-trunk\", edge: id, detail: `bundle ${b.id}: the route is in two bundles or does not start with the trunk` })) return out;\n bundled.add(id);\n }\n }\n for (const run of result.runs ?? []) {\n if (run.edges.length < 2)\n if (add({ rule: \"run-shared\", detail: `run ${run.id} has fewer than two edges` })) return out;\n for (const id of run.edges) {\n const r = routes.get(id);\n if (!r || !(holds(r.points, run.points) || holds(r.points, [...run.points].reverse())))\n if (add({ rule: \"run-shared\", edge: id, detail: `run ${run.id}: the route does not hold the points of the run in a row` })) return out;\n }\n }\n for (const level of result.levels ?? []) {\n const itemOf = new Map<string, string>();\n for (const it of level.items) for (const n of it.nodes) itemOf.set(n, it.id);\n if (itemOf.size !== graph.nodes.length)\n if (add({ rule: \"counts-sum\", detail: `level ${level.depth}: the items hold ${itemOf.size} of ${graph.nodes.length} nodes` }))\n return out;\n let between = 0;\n for (const e of graph.edges) if (itemOf.get(e.source.node) !== itemOf.get(e.target.node)) between++;\n const sum = level.links.reduce((s, l) => s + l.count, 0);\n if (sum !== between)\n if (add({ rule: \"counts-sum\", detail: `level ${level.depth}: the links count ${sum} edges, not ${between}` })) return out;\n const boxOf = new Map(level.items.map((it) => [it.id, it.box]));\n for (const l of level.links) {\n const s = boxOf.get(l.source);\n const t = boxOf.get(l.target);\n const p = l.points;\n if (!s || !t || p.length < 2 || !onBoundary(p[0]!, s) || !onBoundary(p[p.length - 1]!, t))\n if (add({ rule: \"link-ends\", detail: `level ${level.depth}: the link ${l.source} to ${l.target} does not start and end on the boundaries of its items` }))\n return out;\n }\n }\n return out;\n}\n\n/** This function tells if the point is on the boundary of the box, within `TOLERANCE`. */\nfunction onBoundary(p: Point, b: Box): boolean {\n const inner = inflate(b, -TOLERANCE);\n const deep = p.x > inner.x && p.x < inner.x + inner.w && p.y > inner.y && p.y < inner.y + inner.h;\n return !deep && pointBoxDistance(p, b) <= TOLERANCE;\n}\n\n/** This function tells if the polyline `p` holds the points of `part` in a row. */\nfunction holds(p: readonly Point[], part: readonly Point[]): boolean {\n if (part.length === 0) return true;\n for (let i = 0; i + part.length <= p.length; i++) if (part.every((q, j) => dist(q, p[i + j]!) <= TOLERANCE)) return true;\n return false;\n}\n","import type { Point } from \"../geom.ts\";\nimport type { CurveSegment } from \"./model.ts\";\n\n/** The largest number of points that `sampleCurve` gives for one segment. */\nconst MAX_STEPS = 1024;\n\n/**\n * This function gives a polyline that follows the curve. The distance from each part of the curve to the polyline is `tolerance` or less.\n * The polyline starts at the point of the `move` and goes through the end of each segment.\n * Hit tests, measures and renderers that draw only lines use this polyline.\n */\nexport function sampleCurve(segments: readonly CurveSegment[], tolerance = 0.5): Point[] {\n const tol = Math.max(1e-6, tolerance);\n const out: Point[] = [];\n let at: Point | undefined;\n for (const s of segments) {\n if (s.kind === \"move\" || at === undefined) {\n out.push(s.to);\n at = s.to;\n continue;\n }\n if (s.kind === \"cubic\") {\n // The chord of a step of 1/n of the parameter is within 3·D/(4·n²) of the curve. D is the largest second difference of the control points.\n const d = Math.max(\n Math.hypot(at.x - 2 * s.c1.x + s.c2.x, at.y - 2 * s.c1.y + s.c2.y),\n Math.hypot(s.c1.x - 2 * s.c2.x + s.to.x, s.c1.y - 2 * s.c2.y + s.to.y),\n );\n const n = Math.min(MAX_STEPS, Math.max(1, Math.ceil(Math.sqrt((3 * d) / (4 * tol)))));\n for (let k = 1; k < n; k++) out.push(cubicAt(at, s.c1, s.c2, s.to, k / n));\n } else if (s.kind === \"arc\") {\n // The chord of an angle φ is within r·(1 - cos(φ/2)) of the arc.\n const step = s.radius <= tol ? Math.PI : 2 * Math.acos(1 - tol / s.radius);\n const n = Math.min(MAX_STEPS, Math.max(1, Math.ceil(Math.abs(s.sweep) / step)));\n for (let k = 1; k < n; k++) {\n const a = s.start + (s.sweep * k) / n;\n out.push({ x: s.center.x + s.radius * Math.cos(a), y: s.center.y + s.radius * Math.sin(a) });\n }\n }\n out.push(s.to);\n at = s.to;\n }\n return out;\n}\n\n/** This function gives the point at the parameter `t` of the cubic Bezier curve with the control points `p0`, `p1`, `p2` and `p3`. */\nexport function cubicAt(p0: Point, p1: Point, p2: Point, p3: Point, t: number): Point {\n const u = 1 - t;\n const a = u * u * u;\n const b = 3 * u * u * t;\n const c = 3 * u * t * t;\n const d = t * t * t;\n return { x: a * p0.x + b * p1.x + c * p2.x + d * p3.x, y: a * p0.y + b * p1.y + c * p2.y + d * p3.y };\n}\n\n/**\n * This function writes the segments as the data of an SVG path: the commands `M`, `L`, `C` and `A`.\n * Each number has at most `digits` digits after the point.\n */\nexport function toSvgPath(segments: readonly CurveSegment[], digits = 2): string {\n const n = (v: number): string => {\n const s = String(Number(v.toFixed(digits)));\n return s === \"-0\" ? \"0\" : s;\n };\n const p = (q: Point): string => `${n(q.x)} ${n(q.y)}`;\n const parts: string[] = [];\n for (const s of segments) {\n if (s.kind === \"move\") parts.push(`M ${p(s.to)}`);\n else if (s.kind === \"line\") parts.push(`L ${p(s.to)}`);\n else if (s.kind === \"cubic\") parts.push(`C ${p(s.c1)} ${p(s.c2)} ${p(s.to)}`);\n else parts.push(`A ${n(s.radius)} ${n(s.radius)} 0 ${Math.abs(s.sweep) > Math.PI ? 1 : 0} ${s.sweep > 0 ? 1 : 0} ${p(s.to)}`);\n }\n return parts.join(\" \");\n}\n","import { TOLERANCE } from \"../bench/properties.ts\";\nimport { inflate, segmentHitsBox, type Box, type Point } from \"../geom.ts\";\nimport { Grid } from \"../grid.ts\";\nimport type { CurveSegment } from \"./model.ts\";\nimport { sampleCurve } from \"./sample.ts\";\n\n/**\n * The free space of a board: the boxes that a curve must not go through.\n * Make it one time for a board with `curveSpace`, and give it to each call of `curveOf`.\n */\nexport interface CurveSpace {\n /** The boxes of the board. */\n readonly boxes: readonly Box[];\n /** The tolerance of the samples of a curve, in units of the plane. */\n readonly tolerance: number;\n /**\n * This method tells if the polyline `q` goes through a box that the polyline `p` does not go through.\n * A polyline goes through a box when a part of it longer than `TOLERANCE` is inside the box made smaller by `TOLERANCE`.\n */\n addsHit(q: readonly Point[], p: readonly Point[]): boolean;\n}\n\n/**\n * This function makes the free space of a board from its boxes. The boxes are the nodes, or the items of a zoom level.\n * The curves sample each piece within `tolerance` of the curve for the test.\n */\nexport function curveSpace(boxes: readonly Box[], tolerance = 0.25): CurveSpace {\n const inner = boxes.map((b) => inflate(b, -TOLERANCE));\n let size = 0;\n for (const b of boxes) size += Math.max(b.w, b.h);\n // The buckets grow with the boxes, as the buckets of `measureLinks` do.\n const grid = new Grid<number>(Math.max(180, (2 * size) / Math.max(1, boxes.length)));\n inner.forEach((b, i) => grid.add(i, b));\n const hits = (p: readonly Point[]): Set<number> => {\n const out = new Set<number>();\n for (let i = 1; i < p.length; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n grid.querySegment(a, b, 0, (id) => {\n if (!out.has(id) && segmentHitsBox(a, b, inner[id]!, TOLERANCE)) out.add(id);\n });\n }\n return out;\n };\n return {\n boxes,\n tolerance,\n addsHit(q: readonly Point[], p: readonly Point[]): boolean {\n let before: Set<number> | undefined;\n for (let i = 1; i < q.length; i++) {\n const a = q[i - 1]!;\n const b = q[i]!;\n const hit = grid.someSegment(a, b, 0, (id) => {\n if (!segmentHitsBox(a, b, inner[id]!, TOLERANCE)) return false;\n before ??= hits(p);\n return !before.has(id);\n });\n if (hit) return true;\n }\n return false;\n },\n };\n}\n\n/**\n * This function finds the largest size from `max` down to 0 that keeps a piece of a curve clear.\n * A clear piece goes through no box that its polyline avoids.\n *\n * The function `piece` gives the segments of the piece at a size. They start with a `move`.\n * The polyline `chord` is the part of the original polyline that the piece replaces.\n * The function tries `max` first, then it halves the interval `steps` times. The result is 0 when no size of the search is clear.\n */\nexport function fitSize(\n space: CurveSpace | undefined,\n max: number,\n chord: (size: number) => readonly Point[],\n piece: (size: number) => readonly CurveSegment[],\n steps = 8,\n): number {\n if (space === undefined || max <= 0) return Math.max(0, max);\n const clear = (size: number): boolean => !space.addsHit(sampleCurve(piece(size), space.tolerance), chord(size));\n if (clear(max)) return max;\n let lo = 0;\n let hi = max;\n for (let i = 0; i < steps; i++) {\n const mid = (lo + hi) / 2;\n if (clear(mid)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\n","import { dist, type Point } from \"../../geom.ts\";\nimport { distinctPoints, type CurveSegment } from \"../model.ts\";\nimport { fitSize, type CurveSpace } from \"../space.ts\";\n\n/** The options of `arcCurve`. */\nexport interface ArcOptions {\n /** The largest radius of the arc at a corner. The default is 12. */\n readonly radius?: number;\n /** The boxes that the curve must not go through. Without it, each corner gets the largest radius that fits on its legs. */\n readonly space?: CurveSpace;\n}\n\n/** A turn smaller than this angle, in radians, is no corner. A turn nearer to a half turn than this angle stays sharp. */\nconst FLAT = 1e-6;\n\n/**\n * This function puts a circular arc at each inner vertex of a polyline. The arc is tangent to the two legs of its corner.\n * The tangent points stay on the first half of each leg, so the ends of the polyline stay.\n * With `space`, the function makes the radius of a corner smaller until the arc goes through no box that the polyline avoids.\n * On a polyline with only horizontal and vertical legs, each arc is a quarter circle.\n */\nexport function arcCurve(points: readonly Point[], options: ArcOptions = {}): CurveSegment[] {\n const p = distinctPoints(points);\n if (p.length === 0) return [];\n const radius = options.radius ?? 12;\n const out: CurveSegment[] = [{ kind: \"move\", to: p[0]! }];\n for (let i = 1; i + 1 < p.length; i++) {\n const a = p[i - 1]!;\n const v = p[i]!;\n const b = p[i + 1]!;\n const la = dist(a, v);\n const lb = dist(v, b);\n const ux = (v.x - a.x) / la;\n const uy = (v.y - a.y) / la;\n const wx = (b.x - v.x) / lb;\n const wy = (b.y - v.y) / lb;\n const turn = Math.atan2(ux * wy - uy * wx, ux * wx + uy * wy);\n if (Math.abs(turn) < FLAT || Math.PI - Math.abs(turn) < FLAT) {\n out.push({ kind: \"line\", to: v });\n continue;\n }\n // The tangent points are r·tan(|turn|/2) from the vertex.\n const k = Math.tan(Math.abs(turn) / 2);\n const side = Math.sign(turn);\n const ends = (r: number): [Point, Point] => [\n { x: v.x - ux * r * k, y: v.y - uy * r * k },\n { x: v.x + wx * r * k, y: v.y + wy * r * k },\n ];\n const piece = (r: number): CurveSegment[] => {\n const [p1, p2] = ends(r);\n // The center is on the side of the turn, at the distance r from the first leg.\n const center = { x: p1.x - side * uy * r, y: p1.y + side * ux * r };\n return [{ kind: \"arc\", center, radius: r, start: Math.atan2(p1.y - center.y, p1.x - center.x), sweep: turn, to: p2 }];\n };\n const r = fitSize(\n options.space,\n Math.min(radius, Math.min(la, lb) / (2 * k)),\n (s) => [ends(s)[0], v, ends(s)[1]],\n (s) => [{ kind: \"move\", to: ends(s)[0] }, ...piece(s)],\n );\n if (r <= 0) {\n out.push({ kind: \"line\", to: v });\n continue;\n }\n const [p1] = ends(r);\n if (dist(p1, out[out.length - 1]!.to) > 1e-9) out.push({ kind: \"line\", to: p1 });\n out.push(...piece(r));\n }\n if (p.length > 1) out.push({ kind: \"line\", to: p[p.length - 1]! });\n return out;\n}\n","import { dist, type Point } from \"../../geom.ts\";\nimport { distinctPoints, type CurveSegment } from \"../model.ts\";\nimport { fitSize, type CurveSpace } from \"../space.ts\";\n\n/** The options of `roundedCurve`. */\nexport interface RoundedOptions {\n /** The largest distance from a corner to the start and to the end of its curve. The default is 12. */\n readonly radius?: number;\n /** The boxes that the curve must not go through. Without it, each corner gets the full radius. */\n readonly space?: CurveSpace;\n}\n\n/**\n * This function rounds each inner vertex of a polyline with a quadratic Bezier curve, as `roundCorners` does.\n * The curve of a corner starts and ends at most `radius` from the vertex, and at most half of each leg. The ends of the polyline stay.\n * The function gives each quadratic curve as the same cubic curve. With `space`, it makes the radius of a corner smaller until the curve\n * goes through no box that the polyline avoids.\n */\nexport function roundedCurve(points: readonly Point[], options: RoundedOptions = {}): CurveSegment[] {\n const p = distinctPoints(points);\n if (p.length === 0) return [];\n const radius = options.radius ?? 12;\n const out: CurveSegment[] = [{ kind: \"move\", to: p[0]! }];\n for (let i = 1; i + 1 < p.length; i++) {\n const a = p[i - 1]!;\n const v = p[i]!;\n const b = p[i + 1]!;\n const la = dist(a, v);\n const lb = dist(v, b);\n const ends = (r: number): [Point, Point] => [\n { x: v.x + ((a.x - v.x) * r) / la, y: v.y + ((a.y - v.y) * r) / la },\n { x: v.x + ((b.x - v.x) * r) / lb, y: v.y + ((b.y - v.y) * r) / lb },\n ];\n const piece = (r: number): CurveSegment[] => {\n const [p1, p2] = ends(r);\n // A quadratic curve with the control point v is the cubic curve with the control points 2/3 of the way to v.\n return [{ kind: \"cubic\", c1: { x: p1.x + (2 * (v.x - p1.x)) / 3, y: p1.y + (2 * (v.y - p1.y)) / 3 }, c2: { x: p2.x + (2 * (v.x - p2.x)) / 3, y: p2.y + (2 * (v.y - p2.y)) / 3 }, to: p2 }];\n };\n const r = fitSize(\n options.space,\n Math.min(radius, la / 2, lb / 2),\n (s) => [ends(s)[0], v, ends(s)[1]],\n (s) => [{ kind: \"move\", to: ends(s)[0] }, ...piece(s)],\n );\n if (r <= 0) {\n out.push({ kind: \"line\", to: v });\n continue;\n }\n const [p1] = ends(r);\n if (dist(p1, at(out)) > 1e-9) out.push({ kind: \"line\", to: p1 });\n out.push(...piece(r));\n }\n if (p.length > 1) out.push({ kind: \"line\", to: p[p.length - 1]! });\n return out;\n}\n\n/** This function gives the end of the last segment. */\nfunction at(segments: readonly CurveSegment[]): Point {\n return segments[segments.length - 1]!.to;\n}\n","import { dist, type Point } from \"../../geom.ts\";\nimport { distinctPoints, type CurveSegment } from \"../model.ts\";\nimport { fitSize, type CurveSpace } from \"../space.ts\";\n\n/** The options of `splineCurve`. */\nexport interface SplineOptions {\n /**\n * The tension of the spline, from 0 to 1. The value 0 gives the centripetal Catmull-Rom spline, and 1 gives the polyline.\n * The default is 0.\n */\n readonly tension?: number;\n /** The outward normal of the plug at the first point. With it, the curve leaves the first point along this normal. */\n readonly startNormal?: Point;\n /** The outward normal of the plug at the last point. With it, the curve comes into the last point against this normal. */\n readonly endNormal?: Point;\n /** The boxes that the curve must not go through. Without it, each piece gets the full tangents. */\n readonly space?: CurveSpace;\n}\n\n/**\n * This function draws a centripetal Catmull-Rom spline through the points of a polyline (Yuksel, Schaefer and Keyser, 2011).\n * Each piece between two points is one cubic Bezier curve. The centripetal knots keep the curve free of cusps and loops in a piece.\n * The curve goes through each point. Its tangent at a point keeps one direction on the two sides of the point.\n *\n * With `space`, the function makes the tangents of a piece shorter until the piece goes through no box that its leg avoids.\n * A piece with no tangent is the straight leg.\n */\nexport function splineCurve(points: readonly Point[], options: SplineOptions = {}): CurveSegment[] {\n const p = distinctPoints(points);\n if (p.length === 0) return [];\n const out: CurveSegment[] = [{ kind: \"move\", to: p[0]! }];\n const n = p.length;\n if (n === 1) return out;\n const scale = 1 - Math.max(0, Math.min(1, options.tension ?? 0));\n // The knot interval of each leg is the square root of its length.\n const dt = Array.from({ length: n - 1 }, (_, i) => Math.sqrt(dist(p[i]!, p[i + 1]!)));\n const unit = (q: Point): Point => {\n const l = Math.hypot(q.x, q.y);\n return l === 0 ? { x: 0, y: 0 } : { x: q.x / l, y: q.y / l };\n };\n // The tangent at each point, as a speed in the parameter of the knots.\n const m: Point[] = p.map((v, i) => {\n if (i === 0) {\n const leg = { x: p[1]!.x - v.x, y: p[1]!.y - v.y };\n if (!options.startNormal) return { x: leg.x / dt[0]!, y: leg.y / dt[0]! };\n const u = unit(options.startNormal);\n return { x: u.x * dt[0]!, y: u.y * dt[0]! };\n }\n if (i === n - 1) {\n const a = p[i - 1]!;\n const leg = { x: v.x - a.x, y: v.y - a.y };\n if (!options.endNormal) return { x: leg.x / dt[i - 1]!, y: leg.y / dt[i - 1]! };\n const u = unit(options.endNormal);\n return { x: -u.x * dt[i - 1]!, y: -u.y * dt[i - 1]! };\n }\n const a = p[i - 1]!;\n const b = p[i + 1]!;\n const t0 = dt[i - 1]!;\n const t1 = dt[i]!;\n return {\n x: (v.x - a.x) / t0 - (b.x - a.x) / (t0 + t1) + (b.x - v.x) / t1,\n y: (v.y - a.y) / t0 - (b.y - a.y) / (t0 + t1) + (b.y - v.y) / t1,\n };\n });\n for (let i = 0; i + 1 < n; i++) {\n const a = p[i]!;\n const b = p[i + 1]!;\n const h = dt[i]! / 3;\n const piece = (s: number): CurveSegment[] => [\n { kind: \"move\", to: a },\n { kind: \"cubic\", c1: { x: a.x + m[i]!.x * h * s, y: a.y + m[i]!.y * h * s }, c2: { x: b.x - m[i + 1]!.x * h * s, y: b.y - m[i + 1]!.y * h * s }, to: b },\n ];\n const s = fitSize(options.space, scale, () => [a, b], piece);\n out.push(s > 0 ? piece(s)[1]! : { kind: \"line\", to: b });\n }\n return out;\n}\n","import type { Point } from \"../../geom.ts\";\nimport type { CurveSegment } from \"../model.ts\";\n\n/** This function gives the polyline as it is: one `move` to the first point and one `line` to each other point. */\nexport function straightCurve(points: readonly Point[]): CurveSegment[] {\n return points.map((to, i): CurveSegment => (i === 0 ? { kind: \"move\", to } : { kind: \"line\", to }));\n}\n","import type { Point } from \"../geom.ts\";\nimport { arcCurve } from \"./arc/index.ts\";\nimport type { CurveSegment, CurveType } from \"./model.ts\";\nimport { roundedCurve } from \"./rounded/index.ts\";\nimport type { CurveSpace } from \"./space.ts\";\nimport { splineCurve } from \"./spline/index.ts\";\nimport { straightCurve } from \"./straight/index.ts\";\n\nexport * from \"./model.ts\";\nexport { cubicAt, sampleCurve, toSvgPath } from \"./sample.ts\";\nexport { curveSpace, type CurveSpace } from \"./space.ts\";\nexport { straightCurve } from \"./straight/index.ts\";\nexport { roundedCurve, type RoundedOptions } from \"./rounded/index.ts\";\nexport { splineCurve, type SplineOptions } from \"./spline/index.ts\";\nexport { arcCurve, type ArcOptions } from \"./arc/index.ts\";\n\n/** The options of `curveOf`. Each type reads only the options that it uses. */\nexport interface CurveOptions {\n readonly type: CurveType;\n /** The types `rounded` and `arc` read this radius of the corners. The default is 12. */\n readonly radius?: number;\n /** The type `spline` reads this tension, from 0 to 1. The default is 0. */\n readonly tension?: number;\n /** The type `spline` leaves the first point along this outward normal of its plug. */\n readonly startNormal?: Point;\n /** The type `spline` comes into the last point against this outward normal of its plug. */\n readonly endNormal?: Point;\n /** The boxes that the curve must not go through, from `curveSpace`. The type `straight` does not read it. */\n readonly space?: CurveSpace;\n}\n\n/**\n * This function gives the curve of a route: a polyline of a router, a lane of `laneRoutes` or a link of a zoom level.\n * The curve starts at the first point and ends at the last point of the polyline.\n * The output is a list of segments for any renderer. `toSvgPath` writes it as SVG path data, and `sampleCurve` gives points.\n */\nexport function curveOf(points: readonly Point[], options: CurveOptions): CurveSegment[] {\n switch (options.type) {\n case \"straight\":\n return straightCurve(points);\n case \"rounded\":\n return roundedCurve(points, options);\n case \"spline\":\n return splineCurve(points, options);\n case \"arc\":\n return arcCurve(points, options);\n }\n}\n","import { dist, inflate, segmentHitsRect, type Box, type Point } from \"./geom.ts\";\nimport { Grid } from \"./grid.ts\";\nimport type { Node } from \"./model.ts\";\n\n/** The nodes as obstacles, with a grid for fast tests. */\nexport class Obstacles {\n readonly #grid: Grid<Node>;\n\n /** This constructor indexes the boxes of the nodes. */\n constructor(nodes: readonly Node[], cell: number) {\n this.#grid = new Grid<Node>(cell);\n for (const n of nodes) this.#grid.add(n, n.box);\n }\n\n /** This method tells if the segment `ab` stays out of each box, made larger by `pad`. The nodes in `skip` do not count. */\n clear(a: Point, b: Point, pad: number, skip?: ReadonlySet<Node>): boolean {\n return this.hit(a, b, pad, skip) === undefined;\n }\n\n /**\n * This method gives a node whose box, made larger by `pad`, the segment `ab` goes into, or `undefined` when the segment is clear.\n * The nodes in `skip` do not count. The test stops at the first such node.\n */\n hit(a: Point, b: Point, pad: number, skip?: ReadonlySet<Node>): Node | undefined {\n let found: Node | undefined;\n this.#grid.someSegment(a, b, pad, (n) => {\n if (skip?.has(n) || !hits(a, b, n, pad)) return false;\n found = n;\n return true;\n });\n return found;\n }\n\n /** This method tells if the polyline stays out of each box, made larger by `pad`. The nodes in `skip` do not count. */\n clearPath(p: readonly Point[], pad: number, skip?: ReadonlySet<Node>): boolean {\n for (let i = 1; i < p.length; i++) if (!this.clear(p[i - 1]!, p[i]!, pad, skip)) return false;\n return true;\n }\n\n /** This method gives each node whose bucket the box touches to `visit`. A node can be outside the box. */\n query(box: Box, visit: (n: Node) => void): void {\n this.#grid.query(box, visit);\n }\n\n /** This method tells if the point is inside a box, made larger by `pad`. The node `skip` does not count. */\n inside(p: Point, pad: number, skip?: Node): boolean {\n let hit = false;\n this.#grid.query({ x: p.x, y: p.y, w: 0, h: 0 }, (n) => {\n if (!hit && n !== skip) {\n const b = n.box;\n hit = p.x > b.x - pad && p.x < b.x + b.w + pad && p.y > b.y - pad && p.y < b.y + b.h + pad;\n }\n });\n return hit;\n }\n}\n\n/** This function tells if the segment `ab` goes into the box of the node, made larger by `pad`. */\nfunction hits(a: Point, b: Point, n: Node, pad: number): boolean {\n const x = n.box;\n return segmentHitsRect(a, b, x.x - pad, x.y - pad, x.x + x.w + pad, x.y + x.h + pad);\n}\n\n/** A free point at an end of a search of `CornerGraph.pathAmong`, and the cost to reach it. */\nexport interface Terminal {\n readonly point: Point;\n readonly cost: number;\n}\n\n/** A path of `CornerGraph.pathAmong`: its points, the index of its first point in `from`, the index of its last point in `to`, and its cost. */\nexport interface Among {\n readonly points: Point[];\n readonly from: number;\n readonly to: number;\n readonly cost: number;\n}\n\n/** The options of the corner graph. */\nexport interface CornerGraphOptions {\n /** The distance from a box to its corners. */\n readonly margin: number;\n /** The number of visible neighbours of each corner. */\n readonly k: number;\n /**\n * The spacing of a lattice of free points over the plane, in units of the mean node size. The default is 3, and 0 turns it off.\n * The lattice links groups of nodes across empty space. Without it, the nearest corners of a group are all in that group.\n */\n readonly lattice?: number;\n /**\n * With `cones`, each corner also links to the nearest corner that it can see in each of four cones around the axes.\n * Then a path can go along a long corridor between rows or columns of boxes. The default is false.\n */\n readonly cones?: boolean;\n}\n\n/**\n * A sparse visibility graph. Its vertices are the corners of the boxes, made larger by `margin`.\n * Each corner links to its `k` nearest corners that it can see. A lattice of free points links the groups of nodes.\n * A path goes from corner to corner around the boxes.\n * The obstacle test uses half of the margin, so a path keeps a clearance of at least half of the margin.\n */\nexport class CornerGraph {\n readonly points: Point[] = [];\n readonly #adj: number[][] = [];\n // The length of each link, in the order of #adj.\n readonly #len: number[][] = [];\n readonly #obstacles: Obstacles;\n readonly #pointGrid: Grid<number>;\n readonly #cell: number;\n readonly #pad: number;\n readonly #k: number;\n // The work arrays of A*, made once and cleared by a stamp.\n #g = new Float64Array(0);\n #parent = new Int32Array(0);\n #open = new Int32Array(0);\n #closed = new Int32Array(0);\n #stamp = 0;\n // The corners in each bucket of the point grid, by the key of the bucket. A corner is in one bucket: the bucket of its point.\n readonly #buckets = new Map<number, number[]>();\n // The distance from the point of the last call of nearestVisible to each corner that the call found.\n #dist = new Float64Array(0);\n // The corners of one ring of nearestVisible, nearest first.\n readonly #near = new MinHeap();\n // The corners that each end of a path sees, by the coordinates of the end.\n readonly #endCache = new Map<string, number[]>();\n // The corners that each end of a path of `pathAmong` sees. Such a path has several ends, so each end takes fewer corners.\n readonly #fewCache = new Map<string, number[]>();\n // The connected part of the graph of each corner. The first call of `path` makes it.\n #part: Int32Array | undefined;\n\n /** This constructor makes the graph of the nodes. */\n constructor(nodes: readonly Node[], obstacles: Obstacles, options: CornerGraphOptions) {\n this.#obstacles = obstacles;\n this.#pad = options.margin / 2;\n this.#k = options.k;\n let size = 0;\n for (const n of nodes) size += (n.box.w + n.box.h) / 2;\n this.#cell = Math.max(1, size / Math.max(1, nodes.length) + 2 * options.margin);\n this.#pointGrid = new Grid<number>(this.#cell);\n for (const n of nodes) {\n const b = inflate(n.box, options.margin);\n for (const c of [\n { x: b.x, y: b.y },\n { x: b.x + b.w, y: b.y },\n { x: b.x + b.w, y: b.y + b.h },\n { x: b.x, y: b.y + b.h },\n ]) {\n if (!obstacles.inside(c, this.#pad)) this.#addPoint(c);\n }\n }\n const spacing = (options.lattice ?? 3) * this.#cell;\n if (spacing > 0 && nodes.length > 0) {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const n of nodes) {\n x0 = Math.min(x0, n.box.x);\n y0 = Math.min(y0, n.box.y);\n x1 = Math.max(x1, n.box.x + n.box.w);\n y1 = Math.max(y1, n.box.y + n.box.h);\n }\n for (let x = x0 - spacing / 2; x <= x1 + spacing; x += spacing) {\n for (let y = y0 - spacing / 2; y <= y1 + spacing; y += spacing) {\n const c = { x, y };\n if (!obstacles.inside(c, options.margin)) this.#addPoint(c);\n }\n }\n }\n const links: Set<number>[] = this.points.map(() => new Set<number>());\n for (let i = 0; i < this.points.length; i++) {\n // The k nearest corners of a corner in a long corridor are often all on one side. The cones add a link along the corridor.\n for (const j of this.#nearestVisible(this.points[i]!, this.#k, i, this.#pad, options.cones ?? false)) {\n links[i]!.add(j);\n links[j]!.add(i);\n }\n }\n links.forEach((s, i) => {\n const adj = [...s].sort((a, b) => a - b);\n this.#adj.push(adj);\n this.#len.push(adj.map((j) => dist(this.points[i]!, this.points[j]!)));\n });\n }\n\n #addPoint(c: Point): void {\n const j = this.points.length;\n this.#pointGrid.add(j, { x: c.x, y: c.y, w: 0, h: 0 });\n const key = bucketKey(Math.floor(c.x / this.#cell), Math.floor(c.y / this.#cell));\n const list = this.#buckets.get(key);\n if (list === undefined) this.#buckets.set(key, [j]);\n else list.push(j);\n this.points.push(c);\n }\n\n /** This method gives the number of links of the graph. */\n get linkCount(): number {\n let n = 0;\n for (const a of this.#adj) n += a.length;\n return n / 2;\n }\n\n /** This method gives the index of the corner nearest to `p`, seen or not, or -1 when the graph has no corner near it. */\n nearest(p: Point): number {\n for (let r = this.#cell; r <= this.#cell * 64; r *= 2) {\n let best = -1;\n let bestD = Infinity;\n this.#pointGrid.query({ x: p.x - r, y: p.y - r, w: 2 * r, h: 2 * r }, (j) => {\n const d = dist(p, this.points[j]!);\n if (d < bestD || (d === bestD && j < best)) {\n bestD = d;\n best = j;\n }\n });\n // A corner beyond r can be nearer than a corner in a corner of the square. Within r, none is.\n if (best >= 0 && bestD <= r) return best;\n }\n return -1;\n }\n\n /** This method gives at most `k` corners that `p` can see, nearest first. The corner `self` does not count. */\n nearestVisible(p: Point, k: number, self = -1): number[] {\n return this.#nearestVisible(p, k, self, this.#pad);\n }\n\n /**\n * This method tests the corners in rings of radius `r` = 1, 2, 4 and 8 cells. In each ring, it tests the corners\n * within `r` that an earlier ring did not test, nearest first, and equal distances by index.\n * The ring of `r` takes the corners of the buckets that the square of side `2r` around `p` touches.\n * A corner of these buckets beyond `r` waits for the next ring. So the method visits each bucket one time.\n * With `cones`, the method also gives the nearest visible corner of each of four cones around the axes that the `k` nearest corners leave empty.\n */\n #nearestVisible(p: Point, k: number, self: number, pad: number, cones = false): number[] {\n const out: number[] = [];\n // The bits of the full cones: 1 is +x, 2 is +y, 4 is -x and 8 is -y.\n let full = 0;\n if (this.#dist.length < this.points.length) this.#dist = new Float64Array(this.points.length);\n const dd = this.#dist;\n const points = this.points;\n const cell = this.#cell;\n const reach = CONE_CELLS * cell;\n const blockers: Node[] = [];\n const now = this.#near;\n // The corners that the rings found beyond their radius. The next ring takes them.\n let wait: number[] = [];\n // The bucket range of the ring before. The first ring has none.\n let pi0 = 1;\n let pi1 = 0;\n let pj0 = 1;\n let pj1 = 0;\n for (let r = cell; r <= cell * 8; r *= 2) {\n // The ring of `r` holds the corners beyond `r / 2`. With the k nearest corners, the cones take no corner beyond `reach`.\n if (out.length >= k && r / 2 >= reach) return out;\n // These bounds are the bounds of a query of the box at (p.x - r, p.y - r) with the side 2r.\n const x0 = p.x - r;\n const y0 = p.y - r;\n const i0 = Math.floor(x0 / cell);\n const j0 = Math.floor(y0 / cell);\n const i1 = Math.floor((x0 + 2 * r) / cell);\n const j1 = Math.floor((y0 + 2 * r) / cell);\n const later: number[] = [];\n now.clear();\n for (const j of wait) {\n if (dd[j]! > r) later.push(j);\n else now.add(dd[j]!, j);\n }\n for (let bi = i0; bi <= i1; bi++) {\n const before = bi >= pi0 && bi <= pi1;\n for (let bj = j0; bj <= j1; bj++) {\n if (before && bj >= pj0 && bj <= pj1) continue;\n const list = this.#buckets.get(bucketKey(bi, bj));\n if (list === undefined) continue;\n for (const j of list) {\n if (j === self) continue;\n const d = dist(p, points[j]!);\n dd[j] = d;\n if (d > r) later.push(j);\n else now.add(d, j);\n }\n }\n }\n // The heap gives the corners nearest first, and equal distances by index. A call often stops after a few corners.\n now.build();\n while (now.size > 0) {\n const j = now.pop();\n // A node that stopped an earlier segment often stops this segment too, so the test takes these nodes first.\n // The order of the nodes does not change the result.\n const q = points[j]!;\n const cone = cones ? coneOf(q.x - p.x, q.y - p.y) : 0;\n if (out.length >= k) {\n // After the k nearest corners, only a corner of an empty cone counts, up to `CONE_CELLS` cells from `p`.\n if (dd[j]! > reach) return out;\n if ((full & cone) !== 0) continue;\n }\n let blocked = false;\n for (let b = 0; b < blockers.length && !blocked; b++) blocked = hits(p, q, blockers[b]!, pad);\n if (blocked) continue;\n const hit = this.#obstacles.hit(p, q, pad);\n if (hit !== undefined) blockers.push(hit);\n else {\n out.push(j);\n full |= cone;\n if (out.length >= k && (!cones || full === 15)) return out;\n }\n }\n wait = later;\n pi0 = i0;\n pi1 = i1;\n pj0 = j0;\n pj1 = j1;\n }\n return out;\n }\n\n /**\n * This method gives a shortest path from `from` to `to` in the graph (A*), with the two points as its ends.\n * It gives `undefined` when the graph links no corner near `from` to a corner near `to`.\n * The function `cost` can change the cost of the link from corner `i` to corner `j`, of length `d`.\n * It must give at least `floor` × `d`, so that the estimate of A* stays below the true cost.\n */\n path(from: Point, to: Point, cost?: (i: number, j: number, d: number) => number, floor: number = 1): Point[] | undefined {\n if (this.#obstacles.clear(from, to, this.#pad)) return [from, to];\n return this.#search([{ point: from, cost: 0 }], [{ point: to, cost: 0 }], cost, floor, this.#k * 2)?.points;\n }\n\n /**\n * This method gives the shortest path from a point of `from` to a point of `to`, or `undefined` when the graph has none.\n * The cost of a path includes the costs of its two points. One search finds the path, so this method is faster than a call of `path` for each pair.\n */\n pathAmong(from: readonly Terminal[], to: readonly Terminal[]): Among | undefined {\n const found = this.#search(from, to, undefined, 1, this.#k);\n // A straight line between two points that costs less than the found path is better. The test takes the lines in order of cost.\n const lines: Among[] = [];\n from.forEach((a, i) =>\n to.forEach((b, k) => {\n const c = a.cost + dist(a.point, b.point) + b.cost;\n if (!found || c < found.cost) lines.push({ points: [a.point, b.point], from: i, to: k, cost: c });\n }),\n );\n lines.sort((u, v) => u.cost - v.cost);\n return lines.find((l) => this.#obstacles.clear(l.points[0]!, l.points[1]!, this.#pad)) ?? found;\n }\n\n /** This method is the search (A*) of `path` and `pathAmong`. */\n #search(\n from: readonly Terminal[],\n to: readonly Terminal[],\n cost: ((i: number, j: number, d: number) => number) | undefined,\n floor: number,\n count: number,\n ): Among | undefined {\n const n = this.points.length;\n if (this.#g.length < n) {\n this.#g = new Float64Array(n);\n this.#parent = new Int32Array(n);\n this.#open = new Int32Array(n);\n this.#closed = new Int32Array(n);\n }\n const stamp = ++this.#stamp;\n const points = this.points;\n // The cost from each corner near a point of `to` to that point, and the index of that point.\n const goal = new Map<number, number>();\n const goalOf = new Map<number, number>();\n to.forEach((b, k) => {\n for (const j of this.#ends(b.point, count)) {\n const tail = dist(points[j]!, b.point) + b.cost;\n const now = goal.get(j);\n if (now === undefined || tail < now) {\n goal.set(j, tail);\n goalOf.set(j, k);\n }\n }\n });\n if (goal.size === 0) return undefined;\n const starts = from.map((a) => this.#ends(a.point, count));\n // Without a start and a goal in one connected part, A* finds no path. This test stops it before it visits the whole part.\n if (!starts.some((list) => this.#joined(list, goal))) return undefined;\n const heap = new MinHeap();\n const G = this.#g;\n const parentOf = this.#parent;\n const open = this.#open;\n const closed = this.#closed;\n const estimate = (p: Point): number => {\n let h = Infinity;\n for (const b of to) h = Math.min(h, dist(p, b.point));\n return floor * h;\n };\n const relax = (j: number, g: number, parent: number): void => {\n if (closed[j] === stamp) return;\n if (open[j] === stamp && G[j]! <= g) return;\n open[j] = stamp;\n G[j] = g;\n parentOf[j] = parent;\n heap.push(g + estimate(points[j]!), j);\n };\n // The parent of a first corner is -1 - i, where i is the index of its point in `from`.\n from.forEach((a, i) => {\n for (const j of starts[i]!) relax(j, a.cost + dist(a.point, points[j]!), -1 - i);\n });\n let best = Infinity;\n let bestEnd = -1;\n while (heap.size > 0) {\n if (heap.topKey >= best) break;\n const i = heap.pop();\n if (closed[i] === stamp) continue;\n closed[i] = stamp;\n const gi = G[i]!;\n const tail = goal.get(i);\n if (tail !== undefined && gi + tail < best) {\n best = gi + tail;\n bestEnd = i;\n }\n const adj = this.#adj[i]!;\n const len = this.#len[i]!;\n for (let m = 0; m < adj.length; m++) {\n const j = adj[m]!;\n if (closed[j] === stamp) continue;\n const d = len[m]!;\n relax(j, gi + (cost ? cost(i, j, d) : d), i);\n }\n }\n if (bestEnd < 0) return undefined;\n const k = goalOf.get(bestEnd)!;\n const out: Point[] = [to[k]!.point];\n for (let i = bestEnd; ; i = parentOf[i]!) {\n out.push(points[i]!);\n if (parentOf[i]! < 0) {\n const f = -1 - parentOf[i]!;\n out.push(from[f]!.point);\n return { points: out.reverse(), from: f, to: k, cost: best };\n }\n }\n }\n\n /** This method tells if a corner of `starts` and a corner of `goal` are in one connected part of the graph. */\n #joined(starts: readonly number[], goal: ReadonlyMap<number, number>): boolean {\n const part = (this.#part ??= this.#parts());\n const goals = new Set<number>();\n for (const j of goal.keys()) goals.add(part[j]!);\n for (const j of starts) if (goals.has(part[j]!)) return true;\n return false;\n }\n\n /** This method gives the number of the connected part of each corner. */\n #parts(): Int32Array {\n const part = new Int32Array(this.points.length).fill(-1);\n const stack: number[] = [];\n let count = 0;\n for (let i = 0; i < part.length; i++) {\n if (part[i] !== -1) continue;\n part[i] = count;\n stack.push(i);\n while (stack.length > 0) {\n for (const j of this.#adj[stack.pop()!]!) {\n if (part[j] !== -1) continue;\n part[j] = count;\n stack.push(j);\n }\n }\n count++;\n }\n return part;\n }\n\n /**\n * This method gives at most `count` corners that an end of a path can see. An end near a box sees no corner with the clearance.\n * Then the end takes the corners that it sees without the clearance, so the path does not cut through the boxes.\n * The graph does not change, so the method keeps the corners of each end.\n */\n #ends(p: Point, count: number): number[] {\n const cache = count === this.#k * 2 ? this.#endCache : this.#fewCache;\n const key = `${p.x},${p.y}`;\n let out = cache.get(key);\n if (!out) {\n out = this.nearestVisible(p, count);\n if (out.length === 0) out = this.#nearestVisible(p, count, -1, 0);\n cache.set(key, out);\n }\n return out;\n }\n\n /** This method removes the vertices that a later vertex makes needless: from each vertex, it goes to the farthest vertex in view. */\n pull(p: readonly Point[], lookahead = 16): Point[] {\n if (p.length < 3) return [...p];\n const out: Point[] = [p[0]!];\n let i = 0;\n while (i < p.length - 1) {\n let j = Math.min(p.length - 1, i + lookahead);\n while (j > i + 1 && !this.#obstacles.clear(p[i]!, p[j]!, this.#pad)) j--;\n out.push(p[j]!);\n i = j;\n }\n return out;\n }\n}\n\n/** A link of a cone is at most this number of cells long. A longer search costs time on a dense level and finds few new links. */\nconst CONE_CELLS = 3;\n\n/** This function gives the bit of the cone of the offset (`dx`, `dy`): 1 is +x, 2 is +y, 4 is -x and 8 is -y. A diagonal offset is in a cone of the x axis. */\nconst coneOf = (dx: number, dy: number): number => (Math.abs(dx) >= Math.abs(dy) ? (dx > 0 ? 1 : 4) : dy > 0 ? 2 : 8);\n\n/** This function packs the two indices of a bucket into one number. Each index stays within ±2^20. */\nconst bucketKey = (i: number, j: number): number => (i + 1_048_576) * 2_097_152 + (j + 1_048_576);\n\n/**\n * A binary min-heap of (key, value) pairs in typed arrays. The pairs come out by key, and equal keys by value, so the order is deterministic.\n * The method `push` adds a pair to the heap. The method `add` only appends a pair, and the method `build` then makes the heap of all the pairs.\n */\nclass MinHeap {\n #d = new Float64Array(64);\n #j = new Int32Array(64);\n size = 0;\n\n /** The smallest key. */\n get topKey(): number {\n return this.#d[0]!;\n }\n\n push(key: number, value: number): void {\n this.add(key, value);\n const d = this.#d;\n const jj = this.#j;\n let i = this.size - 1;\n while (i > 0) {\n const p = (i - 1) >> 1;\n if (!(key < d[p]! || (key === d[p] && value < jj[p]!))) break;\n d[i] = d[p]!;\n jj[i] = jj[p]!;\n i = p;\n }\n d[i] = key;\n jj[i] = value;\n }\n\n clear(): void {\n this.size = 0;\n }\n\n add(d: number, j: number): void {\n if (this.size === this.#d.length) {\n const dd = new Float64Array(2 * this.size);\n dd.set(this.#d);\n this.#d = dd;\n const jj = new Int32Array(2 * this.size);\n jj.set(this.#j);\n this.#j = jj;\n }\n this.#d[this.size] = d;\n this.#j[this.size] = j;\n this.size++;\n }\n\n build(): void {\n for (let i = (this.size >> 1) - 1; i >= 0; i--) this.#down(i);\n }\n\n /** This method removes the pair with the smallest key and gives its value. */\n pop(): number {\n const top = this.#j[0]!;\n this.size--;\n if (this.size > 0) {\n this.#d[0] = this.#d[this.size]!;\n this.#j[0] = this.#j[this.size]!;\n this.#down(0);\n }\n return top;\n }\n\n #down(i: number): void {\n const d = this.#d;\n const jj = this.#j;\n const n = this.size;\n const di = d[i]!;\n const ji = jj[i]!;\n for (;;) {\n const l = 2 * i + 1;\n if (l >= n) break;\n const r = l + 1;\n let m = l;\n if (r < n && (d[r]! < d[l]! || (d[r] === d[l] && jj[r]! < jj[l]!))) m = r;\n if (!(d[m]! < di || (d[m] === di && jj[m]! < ji))) break;\n d[i] = d[m]!;\n jj[i] = jj[m]!;\n i = m;\n }\n d[i] = di;\n jj[i] = ji;\n }\n}\n","import { inflectionCurve, roundCorners } from \"./curves.ts\";\nimport type { Point } from \"./geom.ts\";\nimport type { Node } from \"./model.ts\";\nimport type { Plug } from \"./plugs.ts\";\nimport { CornerGraph, Obstacles } from \"./visibility.ts\";\n\n/** The options of a way finder. */\nexport interface WayOptions {\n /** The distance from a box to the corners of the graph. The default is 5. */\n readonly margin?: number;\n /** The number of visible neighbours of each corner. The default is 8. */\n readonly k?: number;\n /** With `smooth`, a way in clear view uses the inflection rule, and the other ways get round corners. */\n readonly smooth?: boolean;\n}\n\n/**\n * The ways around the nodes of one graph. A way leaves a plug along its normal.\n * It goes a shortest way (A*) through the corner graph, without the needless corners. It enters the other plug along its normal.\n */\nexport class WayFinder {\n readonly obstacles: Obstacles;\n readonly corners: CornerGraph;\n readonly margin: number;\n readonly #smooth: boolean;\n\n /** This constructor makes the obstacles and the corner graph of the nodes. */\n constructor(nodes: readonly Node[], options: WayOptions = {}) {\n this.margin = options.margin ?? 5;\n this.#smooth = options.smooth ?? false;\n this.obstacles = new Obstacles(nodes, 180);\n this.corners = new CornerGraph(nodes, this.obstacles, { margin: this.margin, k: options.k ?? 8 });\n }\n\n /** This method gives the point at `margin` from the plug, along its normal. */\n out(p: Plug): Point {\n return { x: p.point.x + p.normal.x * this.margin, y: p.point.y + p.normal.y * this.margin };\n }\n\n /** This method gives a way from plug to plug. Without a way in the graph, it gives the straight line. */\n between(ps: Plug, pt: Plug, ends: ReadonlySet<Node>): Point[] {\n if (this.#smooth) {\n const curve = inflectionCurve(ps.point, ps.normal, pt.point);\n if (this.obstacles.clearPath(curve, this.margin / 2, ends)) return curve;\n }\n const way = this.corners.path(this.out(ps), this.out(pt));\n if (!way) return [ps.point, pt.point];\n const poly = [ps.point, ...this.corners.pull(way), pt.point];\n if (this.#smooth) {\n const round = roundCorners(poly, this.margin);\n if (this.obstacles.clearPath(round, 0, ends)) return round;\n }\n return poly;\n }\n\n /** This method gives a way from a plug to a free point, or `undefined` when the graph has none. */\n fromPlug(ps: Plug, to: Point): Point[] | undefined {\n const way = this.corners.path(this.out(ps), to);\n return way && [ps.point, ...this.corners.pull(way)];\n }\n\n /** This method gives a way from a free point to a plug, or `undefined` when the graph has none. */\n toPlug(from: Point, pt: Plug): Point[] | undefined {\n const way = this.corners.path(from, this.out(pt));\n return way && [...this.corners.pull(way), pt.point];\n }\n}\n","import { dist, type Point } from \"./geom.ts\";\nimport type { Result, Route } from \"./model.ts\";\n\n/** A piece of drawn way. A shared segment carries several edges, in lane order. A private segment carries one edge. */\nexport interface Segment {\n readonly id: string;\n readonly points: readonly Point[];\n /** The edges in lane order. Lane 0 is on the left of the segment, from its first point to its last. The y axis points down. */\n readonly edges: readonly string[];\n /** The number of edges. A renderer shows it on a fat edge. */\n readonly count: number;\n}\n\n/** One step of a path: a segment, the way through it, and the lane of the edge in it. */\nexport interface SegmentRef {\n readonly segment: string;\n /** This value is true when the edge goes from the last point of the segment to its first point. */\n readonly reverse: boolean;\n readonly lane: number;\n}\n\n/** The route of one edge as a list of segments. */\nexport interface Path {\n readonly edge: string;\n readonly segments: readonly SegmentRef[];\n}\n\n/** The routes of a result as shared geometry. A renderer can draw each segment one time, with a count. */\nexport interface SegmentGraph {\n readonly segments: readonly Segment[];\n readonly paths: readonly Path[];\n}\n\nconst SAME = 1e-6;\n\n/** This function gives the index where `p` holds the points of `part` in a row, from `from` on, or -1. */\nfunction indexOf(p: readonly Point[], part: readonly Point[], from: number): number {\n for (let i = from; i + part.length <= p.length; i++) {\n let ok = true;\n for (let j = 0; ok && j < part.length; j++) ok = dist(p[i + j]!, part[j]!) <= SAME;\n if (ok) return i;\n }\n return -1;\n}\n\n/**\n * This function breaks each route into segments. The runs and the trunks of the bundles become shared segments.\n * The other parts of each route become private segments. The segments of a path, in order, give the points of its route again.\n */\nexport function segmentsOf(result: Result): SegmentGraph {\n const shared = [\n ...(result.runs ?? []).map((r) => ({ id: r.id, points: r.points, edges: r.edges })),\n ...(result.bundles ?? []).map((b) => ({ id: b.id, points: b.trunk, edges: b.edges })),\n ].filter((s) => s.points.length >= 2);\n const onEdge = new Map<string, { id: string; points: readonly Point[]; lane: number }[]>();\n for (const s of shared) {\n s.edges.forEach((edge, lane) => {\n const list = onEdge.get(edge);\n if (list) list.push({ id: s.id, points: s.points, lane });\n else onEdge.set(edge, [{ id: s.id, points: s.points, lane }]);\n });\n }\n const segments: Segment[] = shared.map((s) => ({ id: s.id, points: s.points, edges: s.edges, count: s.edges.length }));\n const paths: Path[] = [];\n for (const route of result.routes) {\n const p = route.points;\n // The place of each shared segment in the route, in the order of the route.\n const found: { at: number; end: number; ref: SegmentRef }[] = [];\n for (const s of onEdge.get(route.edge) ?? []) {\n let at = indexOf(p, s.points, 0);\n let reverse = false;\n if (at < 0) {\n at = indexOf(p, [...s.points].reverse(), 0);\n reverse = true;\n }\n if (at >= 0) found.push({ at, end: at + s.points.length - 1, ref: { segment: s.id, reverse, lane: s.lane } });\n }\n found.sort((a, b) => a.at - b.at);\n const refs: SegmentRef[] = [];\n let i = 0;\n const own = (to: number): void => {\n if (to <= i) return;\n const id = `${route.edge}/${refs.length}`;\n segments.push({ id, points: p.slice(i, to + 1), edges: [route.edge], count: 1 });\n refs.push({ segment: id, reverse: false, lane: 0 });\n };\n for (const f of found) {\n if (f.at < i) continue;\n own(f.at);\n refs.push(f.ref);\n i = f.end;\n }\n own(p.length - 1);\n paths.push({ edge: route.edge, segments: refs });\n }\n return { segments, paths };\n}\n\n/** This function gives the points of a path, with the segments in the order and the way of the path. */\nexport function pathPoints(graph: SegmentGraph, path: Path): Point[] {\n const byId = new Map(graph.segments.map((s) => [s.id, s]));\n const out: Point[] = [];\n for (const ref of path.segments) {\n const s = byId.get(ref.segment);\n if (!s) continue;\n const pts = ref.reverse ? [...s.points].reverse() : s.points;\n for (const q of pts) if (out.length === 0 || dist(q, out[out.length - 1]!) > SAME) out.push(q);\n }\n return out;\n}\n\n/**\n * This function moves each point of a polyline by `d` to the left, in a frame with the y axis down.\n * At an inner point, it moves along the bisector, at most 2 × `d` far.\n */\nexport function offsetPolyline(p: readonly Point[], d: number): Point[] {\n if (d === 0 || p.length < 2) return [...p];\n const normals: Point[] = [];\n for (let i = 1; i < p.length; i++) {\n const dx = p[i]!.x - p[i - 1]!.x;\n const dy = p[i]!.y - p[i - 1]!.y;\n const l = Math.hypot(dx, dy);\n normals.push(l > 0 ? { x: dy / l, y: -dx / l } : (normals[normals.length - 1] ?? { x: 0, y: 0 }));\n }\n return p.map((q, i) => {\n const a = normals[Math.max(0, i - 1)]!;\n const b = normals[Math.min(normals.length - 1, i)]!;\n const mx = a.x + b.x;\n const my = a.y + b.y;\n const ml = Math.hypot(mx, my);\n if (ml < 1e-9) return { x: q.x + a.x * d, y: q.y + a.y * d };\n const cos = (mx * a.x + my * a.y) / ml;\n const k = Math.min(2, 1 / Math.max(cos, 1e-9)) * d;\n return { x: q.x + (mx / ml) * k, y: q.y + (my / ml) * k };\n });\n}\n\n/** The options of `pullApart`. */\nexport interface PullApartOptions {\n /** The distance between two lanes. */\n readonly spacing: number;\n /** The largest width of a segment, from its outer lane on the left to its outer lane on the right. */\n readonly maxWidth: number;\n}\n\n/**\n * This function pulls the lanes of each shared segment apart, and gives a route for each edge.\n * The lanes keep the lane order, so they do not cross in a segment. The two ends of each route stay at their plugs.\n */\nexport function pullApart(graph: SegmentGraph, options: PullApartOptions): Route[] {\n return lanePaths(graph, (s) => (s.count > 1 ? Math.min(options.spacing, options.maxWidth / (s.count - 1)) : 0));\n}\n\n/** This function gives the key of a shared run: the ids of its edges, sorted and joined with commas. */\nexport function runKey(edges: readonly string[]): string {\n return [...edges].sort().join(\",\");\n}\n\n/**\n * This function opens the shared segments whose key is in `open`: each edge of an open segment gets its own lane.\n * The lanes are `laneWidth` apart, and an open segment is at most `maxWidth` wide. The other segments stay as one way.\n *\n * Lane 0 is on the left of the segment, from its first point to its last, with the y axis down.\n * The function takes a result or its segments. It gives a route for each edge, with the ends at their plugs.\n * The key of a segment is `runKey` of its edges.\n */\nexport function laneRoutes(source: Result | SegmentGraph, open: ReadonlySet<string>, laneWidth: number, maxWidth: number = Infinity): Route[] {\n const graph = \"paths\" in source ? source : segmentsOf(source);\n if (open.size === 0) return graph.paths.map((path) => ({ edge: path.edge, points: pathPoints(graph, path) }));\n return lanePaths(graph, (s) => (s.count > 1 && open.has(runKey(s.edges)) ? Math.min(laneWidth, maxWidth / (s.count - 1)) : 0));\n}\n\n/** This function gives the route of each path, with the lanes of each segment at the spacing that `spacingOf` gives. */\nfunction lanePaths(graph: SegmentGraph, spacingOf: (s: Segment) => number): Route[] {\n const byId = new Map(graph.segments.map((s) => [s.id, s]));\n const routes: Route[] = [];\n for (const path of graph.paths) {\n const ends = pathPoints(graph, path);\n const out: Point[] = [];\n for (const ref of path.segments) {\n const s = byId.get(ref.segment);\n if (!s) continue;\n const spacing = spacingOf(s);\n const moved = offsetPolyline(s.points, ((s.count - 1) / 2 - ref.lane) * spacing);\n for (const q of ref.reverse ? moved.reverse() : moved) if (out.length === 0 || dist(q, out[out.length - 1]!) > SAME) out.push(q);\n }\n if (out.length >= 2 && ends.length >= 2) {\n out[0] = ends[0]!;\n out[out.length - 1] = ends[ends.length - 1]!;\n }\n routes.push({ edge: path.edge, points: out });\n }\n return routes;\n}\n\n/** The angle, from -π to π, of the turn at `base` from the direction `from` → `base` to the point `to`. */\nfunction turn(from: Point, base: Point, to: Point): number {\n const dx = base.x - from.x;\n const dy = base.y - from.y;\n const vx = to.x - base.x;\n const vy = to.y - base.y;\n return Math.atan2(dx * vy - dy * vx, dx * vx + dy * vy);\n}\n\n/**\n * This function gives the lane order of the edges on a shared way `run` (metro-line order). Two routes go on together\n * past the last point of the run until they part. The route that turns more to the left there gets the lane more to the left.\n * Two routes can part only before the first point. Then the route that comes from more to the left gets the lane more to the left.\n * A route that does not hold the run goes last.\n */\nexport function orderLanes(run: readonly Point[], routes: readonly Route[]): string[] {\n const placed: { edge: string; p: readonly Point[]; s: number; e: number }[] = [];\n const lost: string[] = [];\n for (const r of routes) {\n let at = indexOf(r.points, run, 0);\n if (at >= 0) placed.push({ edge: r.edge, p: r.points, s: at, e: at + run.length - 1 });\n else {\n const p = [...r.points].reverse();\n at = indexOf(p, run, 0);\n if (at >= 0) placed.push({ edge: r.edge, p, s: at, e: at + run.length - 1 });\n else lost.push(r.edge);\n }\n }\n const same = (a: Point, b: Point): boolean => dist(a, b) <= SAME;\n placed.sort((P, Q) => {\n for (let j = 1; ; j++) {\n const a = P.p[P.e + j];\n const b = Q.p[Q.e + j];\n if (a === undefined || b === undefined) break;\n if (!same(a, b)) {\n const d = turn(P.p[P.e + j - 2]!, P.p[P.e + j - 1]!, a) - turn(P.p[P.e + j - 2]!, P.p[P.e + j - 1]!, b);\n if (d !== 0) return d;\n break;\n }\n }\n for (let j = 1; ; j++) {\n const a = P.p[P.s - j];\n const b = Q.p[Q.s - j];\n if (a === undefined || b === undefined) break;\n if (!same(a, b)) {\n // Seen backward, the left side is the right side. Thus the order turns around.\n const d = turn(P.p[P.s - j + 2]!, P.p[P.s - j + 1]!, b) - turn(P.p[P.s - j + 2]!, P.p[P.s - j + 1]!, a);\n if (d !== 0) return d;\n break;\n }\n }\n return P.edge < Q.edge ? -1 : P.edge > Q.edge ? 1 : 0;\n });\n return [...placed.map((x) => x.edge), ...lost.sort()];\n}\n","import { center, type Box } from \"./geom.ts\";\nimport type { Node } from \"./model.ts\";\n\n/** A section of the plane: a cell of a quadtree, with the nodes whose centers are in it. */\nexport interface Section {\n /** The path from the root: \"s\", then one digit from 0 to 3 for each step down. */\n readonly id: string;\n readonly depth: number;\n readonly cell: Box;\n /** The indices of the nodes, in the order of the graph. */\n readonly nodes: readonly number[];\n readonly children: readonly Section[];\n}\n\n/** The options of the tree of sections. */\nexport interface SectionOptions {\n /** A section with more nodes splits. The default is 8. */\n readonly cap?: number;\n /** The tree stops at this depth. The default is 16. */\n readonly maxDepth?: number;\n /** A cell shrinks to one quarter at most this many times without a split. Then it stops. The default is 32. */\n readonly collapse?: number;\n}\n\n/** The default values of `SectionOptions`. */\nexport const SECTION_DEFAULTS: Readonly<Required<SectionOptions>> = Object.freeze({ cap: 8, maxDepth: 16, collapse: 32 });\n\n/**\n * This function makes the tree of sections of the nodes. A cell with more than `cap` nodes splits in four.\n * When the nodes of a cell are all in one quarter, the cell becomes that quarter and does not make a level.\n */\nexport function buildSections(nodes: readonly Node[], options: SectionOptions = {}): Section {\n const cap = Math.max(1, options.cap ?? SECTION_DEFAULTS.cap);\n const maxDepth = options.maxDepth ?? SECTION_DEFAULTS.maxDepth;\n const collapse = options.collapse ?? SECTION_DEFAULTS.collapse;\n const centers = nodes.map((n) => center(n.box));\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const n of nodes) {\n x0 = Math.min(x0, n.box.x);\n y0 = Math.min(y0, n.box.y);\n x1 = Math.max(x1, n.box.x + n.box.w);\n y1 = Math.max(y1, n.box.y + n.box.h);\n }\n const root: Box = nodes.length ? { x: x0, y: y0, w: x1 - x0, h: y1 - y0 } : { x: 0, y: 0, w: 0, h: 0 };\n const make = (id: string, depth: number, cell: Box, list: readonly number[]): Section => {\n let box = cell;\n for (let guard = 0; list.length > cap && depth < maxDepth && guard < collapse; guard++) {\n const mx = box.x + box.w / 2;\n const my = box.y + box.h / 2;\n const parts: number[][] = [[], [], [], []];\n for (const i of list) parts[(centers[i]!.x < mx ? 0 : 1) + (centers[i]!.y < my ? 0 : 2)]!.push(i);\n const quarter = (q: number): Box => ({\n x: q % 2 === 0 ? box.x : mx,\n y: q < 2 ? box.y : my,\n w: box.w / 2,\n h: box.h / 2,\n });\n const full = parts.map((p, q) => [p, q] as const).filter(([p]) => p.length > 0);\n if (full.length === 1) {\n box = quarter(full[0]![1]);\n continue;\n }\n const children = full.map(([p, q]) => make(`${id}${q}`, depth + 1, quarter(q), p));\n return { id, depth, cell: box, nodes: list, children };\n }\n return { id, depth, cell: box, nodes: list, children: [] };\n };\n return make(\"s\", 0, root, nodes.map((_, i) => i));\n}\n\n/** This function gives the sections of the tree, parents before children. */\nexport function allSections(root: Section): Section[] {\n const out: Section[] = [];\n const walk = (s: Section): void => {\n out.push(s);\n for (const c of s.children) walk(c);\n };\n walk(root);\n return out;\n}\n\n/** This function gives the depth of the deepest section. */\nexport function treeDepth(root: Section): number {\n return root.children.reduce((d, c) => Math.max(d, treeDepth(c)), root.depth);\n}\n\n/**\n * This function examines a tree of sections from a grouping rule. It throws an error when the tree is not valid for `count` nodes.\n * In a valid tree, each node is in exactly one leaf. The children of a section split its nodes, and a child is one level deeper than its parent.\n */\nexport function checkSections(root: Section, count: number): void {\n const seen = new Array<number>(count).fill(0);\n const ids = new Set<string>();\n const fail = (s: Section, what: string): never => {\n throw new Error(`The tree of sections is not valid at the section \"${s.id}\": ${what}.`);\n };\n if (root.depth !== 0) fail(root, \"the root has a depth that is not 0\");\n if (root.nodes.length !== count) fail(root, `the root has ${root.nodes.length} nodes, and the graph has ${count}`);\n const walk = (s: Section): void => {\n if (ids.has(s.id)) fail(s, \"two sections have this id\");\n ids.add(s.id);\n if (s.children.length === 0) {\n for (const i of s.nodes) {\n if (!Number.isInteger(i) || i < 0 || i >= count) fail(s, `the node index ${i} is not in the graph`);\n seen[i]!++;\n }\n return;\n }\n let total = 0;\n const own = new Set(s.nodes);\n for (const c of s.children) {\n if (c.depth !== s.depth + 1) fail(c, \"a child is not one level deeper than its parent\");\n for (const i of c.nodes) if (!own.has(i)) fail(c, `the node index ${i} is not in the parent`);\n total += c.nodes.length;\n walk(c);\n }\n if (total !== s.nodes.length) fail(s, \"the children do not split the nodes of the section\");\n };\n walk(root);\n const lost = seen.findIndex((n) => n !== 1);\n if (lost >= 0) fail(root, `the node index ${lost} is in ${seen[lost]} leaves, not in one`);\n}\n","import type { Graph } from \"../../model.ts\";\nimport { buildSections, type Section, type SectionOptions } from \"../../sections.ts\";\n\n/**\n * This function gives the tree of sections of the grouping rule `quadtree`: the cells of a quadtree of the plane (`buildSections`).\n * It is the default grouping rule of the router `sections`.\n */\nexport function quadtreeGroups(graph: Graph, options: SectionOptions = {}): Section {\n return buildSections(graph.nodes, options);\n}\n","import type { Box } from \"../../geom.ts\";\nimport type { Graph, Node } from \"../../model.ts\";\nimport { buildSections, type Section, type SectionOptions } from \"../../sections.ts\";\n\n/** A key rule gives the key of the group of a node. A node without a key is a group alone. */\nexport type NodeKey = (node: Node, index: number) => string | undefined;\n\n/** The options of the grouping rule `keys`. */\nexport interface KeyOptions {\n /** This function gives the key of the group of each node. The default is `byDataGroup`. */\n readonly key?: NodeKey;\n /**\n * With this value, a group with more nodes than its `cap` splits into the cells of a quadtree, as `buildSections` does.\n * Without it, each group is one leaf. The default is no split.\n */\n readonly split?: SectionOptions;\n}\n\n/** This key rule gives the string `data.group` of the node, or `undefined` when the node has no such string. */\nexport const byDataGroup: NodeKey = (node) => {\n const group = node.data?.[\"group\"];\n return typeof group === \"string\" ? group : undefined;\n};\n\n/** This function gives the bounding box of the boxes of the nodes of the list. */\nfunction boundsOf(nodes: readonly Node[], list: readonly number[]): Box {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const i of list) {\n const b = nodes[i]!.box;\n x0 = Math.min(x0, b.x);\n y0 = Math.min(y0, b.y);\n x1 = Math.max(x1, b.x + b.w);\n y1 = Math.max(y1, b.y + b.h);\n }\n return list.length ? { x: x0, y: y0, w: x1 - x0, h: y1 - y0 } : { x: 0, y: 0, w: 0, h: 0 };\n}\n\n/**\n * This function gives the tree of sections of the grouping rule `keys`. The root holds each node. Each child of the root holds the nodes of one key,\n * in the order of their first node. The id of a group is `s:` and its key. A node without a key is a group alone, with the id `s#` and its index.\n * Thus the far view of the router `sections` shows one item for each group.\n */\nexport function keyedSections(nodes: readonly Node[], options: KeyOptions = {}): Section {\n const key = options.key ?? byDataGroup;\n const groups = new Map<string, number[]>();\n nodes.forEach((n, i) => {\n const k = key(n, i);\n const id = k === undefined ? `s#${i}` : `s:${k}`;\n const list = groups.get(id);\n if (list) list.push(i);\n else groups.set(id, [i]);\n });\n const children = [...groups].map(([id, list]) => group(nodes, id, list, options.split));\n return { id: \"s\", depth: 0, cell: boundsOf(nodes, nodes.map((_, i) => i)), nodes: nodes.map((_, i) => i), children };\n}\n\n/** This function gives the section of one group at depth 1. With `split`, the section has the quadtree of its nodes below it. */\nfunction group(nodes: readonly Node[], id: string, list: readonly number[], split: SectionOptions | undefined): Section {\n if (!split) return { id, depth: 1, cell: boundsOf(nodes, list), nodes: list, children: [] };\n const tree = buildSections(\n list.map((i) => nodes[i]!),\n split,\n );\n // The quadtree numbers the nodes of the group from 0. Each section gets the indices of the graph, one more level and the id of the group before its path.\n const rebase = (s: Section): Section => ({\n id: s.id === \"s\" ? id : `${id}/${s.id.slice(1)}`,\n depth: s.depth + 1,\n cell: s.cell,\n nodes: s.nodes.map((j) => list[j]!),\n children: s.children.map(rebase),\n });\n return rebase(tree);\n}\n\n/** This function gives the tree of sections of the grouping rule `keys` for a graph. */\nexport function keyGroups(graph: Graph, options: KeyOptions = {}): Section {\n return keyedSections(graph.nodes, options);\n}\n","import type { Level } from \"./model.ts\";\n\n/** This function gives the median width of the shown items of each level, in units of the plane. */\nexport function itemSizes(levels: readonly Level[]): number[] {\n return levels.map((level) => {\n const sizes = level.items.map((i) => Math.max(i.box.w, i.box.h)).sort((a, b) => a - b);\n return sizes.length ? sizes[Math.floor(sizes.length / 2)]! : 0;\n });\n}\n\n/** The far-view thresholds of `pickLevel`, in pixels on the screen. */\nexport interface PickOptions {\n /** When a node is at least this wide on the screen, the view shows each route. */\n readonly routesAt: number;\n /** A level is fine enough when its median item is at least this wide on the screen. */\n readonly itemAt: number;\n}\n\n/** The default thresholds: a node of 22 pixels shows its routes, and a group of 120 pixels shows its parts. */\nexport const PICK: PickOptions = Object.freeze({ routesAt: 22, itemAt: 120 });\n\n/**\n * This function picks the level that a camera shows at a scale, in pixels for each unit of the plane. The sizes come from `itemSizes`.\n * The value `sizes.length` stands for the routes of each edge. The last level holds the nodes alone.\n * Each threshold that `options` does not give gets its value from `PICK`.\n */\nexport function pickLevel(sizes: readonly number[], scale: number, options: Partial<PickOptions> = PICK): number {\n const routesAt = options.routesAt ?? PICK.routesAt;\n const itemAt = options.itemAt ?? PICK.itemAt;\n const n = sizes.length;\n if (n === 0) return 0;\n if (sizes[n - 1]! * scale >= routesAt) return n;\n let pick = 0;\n for (let d = 0; d < n - 1; d++) if (sizes[d]! * scale >= itemAt) pick = d;\n return pick;\n}\n","import { center } from \"../geom.ts\";\nimport { nodeIndex, type Graph, type Node, type Result, type Route, type Router } from \"../model.ts\";\nimport { placePlug } from \"../plugs.ts\";\nimport { WayFinder, type WayOptions } from \"../ways.ts\";\n\n/** The options of the corner router. */\nexport interface CornersOptions extends WayOptions {\n /** The name in the benchmark. */\n readonly name: string;\n /** The benchmark skips a fixture with more nodes. */\n readonly maxNodes?: number;\n}\n\n/**\n * This function makes a router that goes around the nodes.\n * Each edge leaves its plug along the normal of the side. It goes a shortest way (A*) through a sparse visibility graph\n * of the box corners, without the needless corners. It enters the target plug along its normal.\n */\nexport function cornersRouter(options: CornersOptions): Router {\n const router: Router = {\n name: options.name,\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const ways = new WayFinder(graph.nodes, options);\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n }\n return { routes };\n },\n };\n return options.maxNodes === undefined ? router : { ...router, maxNodes: options.maxNodes };\n}\n","import { inflectionCurve } from \"../curves.ts\";\nimport { center } from \"../geom.ts\";\nimport { nodeIndex, type Graph, type Result, type Route, type Router } from \"../model.ts\";\nimport { placePlug } from \"../plugs.ts\";\n\n/**\n * Plugs and the inflection rule, with no obstacles. Each edge leaves its source plug at the tangent of the side.\n * It goes to the target plug on the curve of the rule. This router measures the rule alone.\n */\nexport const plugsRouter: Router = {\n name: \"plugs\",\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n routes.push({ edge: e.id, points: inflectionCurve(ps.point, ps.normal, pt.point) });\n }\n return { routes };\n },\n};\n","import { dist, inflate, pointSegmentDistance, polylineLength, segmentHitsBox, type Box, type Point } from \"../geom.ts\";\nimport { Grid } from \"../grid.ts\";\nimport type { Graph, Level, Result } from \"../model.ts\";\nimport { TOLERANCE } from \"./properties.ts\";\n\n/**\n * The faults of a set of links: the routes of the edges, or the links of one zoom level.\n * Each value counts links, except `worstDetour`. Lower is better for each value.\n */\nexport interface LinkFaults {\n /** The number of links that the measure examined. */\n readonly links: number;\n /**\n * The number of links that go through the inside of a box that is not one of their two ends.\n * A segment goes through a box when a part of it longer than `TOLERANCE` is inside the box made smaller by `TOLERANCE`.\n */\n readonly through: number;\n /**\n * The number of links that go out and back. The distance from a point of the link to its last point grows after the nearest approach.\n * A link goes out and back when this growth is more than `BACKTRACK_SHARE` of the distance between its ends, and more than `BACKTRACK_MIN` units.\n */\n readonly backtrack: number;\n /** The largest ratio of the length of a link to the distance between its ends. Links with ends nearer than 1 unit do not count. */\n readonly worstDetour: number;\n /**\n * The number of links with a point outside the bounding box of all the boxes, made larger by `slack`.\n * Both ends of a link are always in that bounding box, so such a link goes around the outer edge of the board.\n */\n readonly outside: number;\n}\n\n/** The faults of the links of one zoom level. */\nexport interface LevelFaults extends LinkFaults {\n readonly depth: number;\n /** The number of items of the level. */\n readonly items: number;\n /** The number of items that hold more than one node. */\n readonly groups: number;\n /** The number of pairs of items whose boxes overlap by more than `TOLERANCE` on each axis. */\n readonly overlaps: number;\n}\n\n/** The options of the link measures. */\nexport interface LinkFaultOptions {\n /** A link that goes farther than this distance outside the bounding box of all the boxes counts in `outside`. The default is 24. */\n readonly slack?: number;\n}\n\n/** A link goes out and back when its distance to its target grows by more than this share of the distance between its ends. */\nexport const BACKTRACK_SHARE = 0.25;\n/** A link goes out and back only when its distance to its target grows by more than this number of units. */\nexport const BACKTRACK_MIN = 40;\n/** The default `slack` of `LinkFaultOptions`. */\nexport const OUTSIDE_SLACK = 24;\n\n/** A link from one box to another box, as `measureLinks` sees it. */\nexport interface MeasuredLink {\n readonly source: string;\n readonly target: string;\n readonly points: readonly Point[];\n}\n\n/**\n * This function gives the largest growth of the distance to the last point of a polyline.\n * The growth at a vertex is its distance to the last point, less the nearest approach of the polyline before that vertex.\n */\nexport function backtrackOf(p: readonly Point[]): number {\n if (p.length < 3) return 0;\n const end = p[p.length - 1]!;\n let near = dist(p[0]!, end);\n let worst = 0;\n for (let i = 1; i < p.length; i++) {\n worst = Math.max(worst, dist(p[i]!, end) - near);\n near = Math.min(near, pointSegmentDistance(end, p[i - 1]!, p[i]!));\n }\n return worst;\n}\n\n/** This function tells if the polyline `p` goes out and back: `backtrackOf(p)` is more than `BACKTRACK_MIN` and more than `BACKTRACK_SHARE` of the span. */\nexport function goesOutAndBack(p: readonly Point[]): boolean {\n if (p.length < 3) return false;\n const span = dist(p[0]!, p[p.length - 1]!);\n return backtrackOf(p) > Math.max(BACKTRACK_MIN, BACKTRACK_SHARE * span);\n}\n\n/**\n * This function measures the faults of links between boxes. The map `boxes` gives the box of each end.\n * The bounding box of `outside` is the bounding box of all the boxes of the map.\n */\nexport function measureLinks(boxes: ReadonlyMap<string, Box>, links: readonly MeasuredLink[], options: LinkFaultOptions = {}): LinkFaults {\n const slack = options.slack ?? OUTSIDE_SLACK;\n let size = 0;\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const b of boxes.values()) {\n size += Math.max(b.w, b.h);\n x0 = Math.min(x0, b.x);\n y0 = Math.min(y0, b.y);\n x1 = Math.max(x1, b.x + b.w);\n y1 = Math.max(y1, b.y + b.h);\n }\n // Large items cover many buckets of a small grid, so the buckets grow with the items.\n const grid = new Grid<string>(Math.max(180, (2 * size) / Math.max(1, boxes.size)));\n for (const [id, b] of boxes) grid.add(id, b);\n let through = 0;\n let backtrack = 0;\n let worstDetour = 0;\n let outside = 0;\n for (const l of links) {\n const p = l.points;\n if (p.length === 0) continue;\n let hit = false;\n for (let i = 1; i < p.length && !hit; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n grid.querySegment(a, b, 0, (id) => {\n if (!hit && id !== l.source && id !== l.target && segmentHitsBox(a, b, inflate(boxes.get(id)!, -TOLERANCE), TOLERANCE)) hit = true;\n });\n }\n if (hit) through++;\n if (goesOutAndBack(p)) backtrack++;\n const span = dist(p[0]!, p[p.length - 1]!);\n if (span > 1) worstDetour = Math.max(worstDetour, polylineLength(p) / span);\n if (p.some((q) => q.x < x0 - slack || q.x > x1 + slack || q.y < y0 - slack || q.y > y1 + slack)) outside++;\n }\n return { links: links.length, through, backtrack, worstDetour, outside };\n}\n\n/** This function measures the faults of the routes of a result. The ends of a route are the nodes of its edge. */\nexport function measureRouteFaults(graph: Graph, result: Result, options: LinkFaultOptions = {}): LinkFaults {\n const boxes = new Map(graph.nodes.map((n) => [n.id, n.box]));\n const edges = new Map(graph.edges.map((e) => [e.id, e]));\n const links: MeasuredLink[] = [];\n for (const r of result.routes) {\n const e = edges.get(r.edge);\n if (e) links.push({ source: e.source.node, target: e.target.node, points: r.points });\n }\n return measureLinks(boxes, links, options);\n}\n\n/** This function counts the pairs of boxes that overlap by more than `TOLERANCE` on each axis. */\nexport function countOverlaps(boxes: readonly Box[]): number {\n let size = 0;\n for (const b of boxes) size += Math.max(b.w, b.h);\n const grid = new Grid<number>(Math.max(180, (2 * size) / Math.max(1, boxes.length)));\n boxes.forEach((b, i) => grid.add(i, b));\n let n = 0;\n boxes.forEach((a, i) => {\n grid.query(a, (j) => {\n const b = boxes[j]!;\n if (j > i && Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x) > TOLERANCE && Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y) > TOLERANCE) n++;\n });\n });\n return n;\n}\n\n/** This function measures the faults of the links of one zoom level. The items of the level are the boxes. */\nexport function measureLevel(level: Level, options: LinkFaultOptions = {}): LevelFaults {\n const boxes = new Map(level.items.map((i) => [i.id, i.box]));\n return {\n depth: level.depth,\n items: level.items.length,\n groups: level.items.filter((i) => i.nodes.length > 1).length,\n overlaps: countOverlaps(level.items.map((i) => i.box)),\n ...measureLinks(boxes, level.links, options),\n };\n}\n\n/**\n * This function measures the faults of each zoom level of a result that has groups: the levels of the far view.\n * A level of single nodes only is the near view. Its links are routes, and `measureRouteFaults` measures them.\n */\nexport function measureLevelFaults(result: Result, options: LinkFaultOptions = {}): LevelFaults[] {\n return (result.levels ?? []).filter((l) => l.items.some((i) => i.nodes.length > 1)).map((l) => measureLevel(l, options));\n}\n\n/** This function adds the faults of several levels: it sums the counts and keeps the largest `worstDetour`. */\nexport function sumFaults(list: readonly LinkFaults[]): LinkFaults {\n return list.reduce<LinkFaults>(\n (s, f) => ({\n links: s.links + f.links,\n through: s.through + f.through,\n backtrack: s.backtrack + f.backtrack,\n worstDetour: Math.max(s.worstDetour, f.worstDetour),\n outside: s.outside + f.outside,\n }),\n { links: 0, through: 0, backtrack: 0, worstDetour: 0, outside: 0 },\n );\n}\n","import { center, dist, polylineLength, type Box, type Point } from \"./geom.ts\";\nimport type { LevelItem, LevelLink, Node, Side } from \"./model.ts\";\nimport { pointOnSide, SIDE_NORMAL, sideToward, type Plug } from \"./plugs.ts\";\nimport { CornerGraph, Obstacles } from \"./visibility.ts\";\nimport type { WayFinder, WayOptions } from \"./ways.ts\";\n\n/** Two items of a level that a link joins, and the count of the edges between them. */\nexport interface ItemPair {\n readonly source: string;\n readonly target: string;\n readonly count: number;\n}\n\n/** The parts of a way finder that a link uses. */\ntype Ways = Pick<WayFinder, \"obstacles\" | \"corners\" | \"margin\" | \"out\">;\n\n/** The free plugs of a node, and the reach of each plug. */\ninterface FreePlugs {\n readonly plugs: readonly Plug[];\n readonly reach: readonly number[];\n}\n\n/** The ways of a level, with a second corner graph and the free plugs of the nodes. */\ninterface LevelWays extends Ways {\n /** This function gives a second corner graph with a small margin. The first link that needs it makes it. */\n readonly tight: () => CornerGraph;\n /** The free plugs of each node that a link needed. */\n readonly free: Map<Node, FreePlugs>;\n}\n\n/** The options of the links of a level: the options of the ways, and two limits of the level links. */\nexport interface LevelLinkOptions extends WayOptions {\n /**\n * The margin of the second corner graph. A gap between two boxes wider than approximately 1.5 times this margin lets a link through.\n * The second graph uses the smaller of this value and `margin`. The default is 1.\n */\n readonly tightMargin?: number;\n /** A plug stays at least this far from the corners of its side. The level links use the smaller of this value and `margin`. The default is 6. */\n readonly plugInset?: number;\n}\n\n/** The default values of the two limits of `LevelLinkOptions`. */\nexport const LEVEL_LINK_DEFAULTS: Readonly<Required<Pick<LevelLinkOptions, \"tightMargin\" | \"plugInset\">>> = Object.freeze({ tightMargin: 1, plugInset: 6 });\n\nconst EPS = 1e-6;\n\n/**\n * This function removes the repeated points, the points in the middle of a straight run,\n * and the points where the way turns back on itself.\n */\nfunction tidy(p: readonly Point[]): Point[] {\n const out: Point[] = [];\n for (const q of p) {\n if (out.length > 0 && dist(q, out[out.length - 1]!) <= EPS) continue;\n while (out.length >= 2) {\n const a = out[out.length - 2]!;\n const b = out[out.length - 1]!;\n const cross = (b.x - a.x) * (q.y - b.y) - (b.y - a.y) * (q.x - b.x);\n if (Math.abs(cross) > EPS * (1 + dist(a, b) * dist(b, q))) break;\n // The point b is on the line through a and q: in the middle of a straight run, or at the tip of a turn back.\n out.pop();\n }\n if (out.length > 0 && dist(q, out[out.length - 1]!) <= EPS) continue;\n out.push(q);\n }\n return out;\n}\n\n/**\n * This function gives the links of one level. The items of the level are the obstacles.\n * A link starts on the boundary of the box of its source and ends on the boundary of the box of its target.\n * It goes around the boxes of the other items. Where there is space, its legs are parallel to the axes.\n */\nexport function levelLinks(items: readonly LevelItem[], pairs: readonly ItemPair[], options: LevelLinkOptions = {}): LevelLink[] {\n if (pairs.length === 0) return [];\n const nodes: Node[] = items.map((i) => ({ id: i.id, box: i.box }));\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const ways = levelWays(nodes, options);\n const inset = Math.min(options.plugInset ?? LEVEL_LINK_DEFAULTS.plugInset, ways.margin);\n const out: LevelLink[] = [];\n for (const p of pairs) {\n const s = byId.get(p.source);\n const t = byId.get(p.target);\n if (!s || !t) continue;\n // Two items with a clear way between their facing sides get the short way.\n const [fs, ft] = facingPlugs(s.box, t.box, inset);\n let points = isFree(ways, s, fs) && isFree(ways, t, ft) ? quickWay(ways, ends(ways, s, fs, t, ft)) : undefined;\n // Else the link goes from the middle of a side. Each item has at most four such plugs, so the corner graph finds their ends one time.\n points ??= sideWay(ways, s, t, inset);\n out.push({ source: p.source, target: p.target, count: p.count, points });\n }\n return out;\n}\n\n/**\n * This function gives a way from plug to plug between the plugs at the middle of a side of the two nodes.\n * Without a way in the corner graph, the link goes straight between the ends, with legs parallel to the axes where they are clear.\n * When that line goes through another box, the link goes between the free plugs of the two nodes (`freeWay`) instead.\n */\nfunction sideWay(ways: LevelWays, s: Node, t: Node, inset: number): Point[] {\n const e = ends(ways, s, sidePlug(ways, s, center(t.box)), t, sidePlug(ways, t, center(s.box)));\n const quick = quickWay(ways, e);\n if (quick) return quick;\n const path = ways.corners.path(e.a, e.b);\n const way = pulled(ways, e.ps, path ?? [e.a, e.b], e.pt);\n if (path || ways.obstacles.clearPath(way, 0, new Set([s, t]))) return way;\n return freeWay(ways, s, t, inset) ?? way;\n}\n\n/**\n * This function makes the obstacles and the corner graph of the items of a level.\n * The buckets of the obstacles grow with the items, so a long link visits few buckets.\n * The corner graphs use `cones`, so a link goes along the corridors between the groups, not around the outer edge of the board.\n */\nfunction levelWays(nodes: readonly Node[], options: LevelLinkOptions): LevelWays {\n const margin = options.margin ?? 5;\n const k = options.k ?? 8;\n let size = 0;\n for (const n of nodes) size += Math.max(n.box.w, n.box.h);\n const obstacles = new Obstacles(nodes, Math.max(180, (2 * size) / Math.max(1, nodes.length)));\n const corners = new CornerGraph(nodes, obstacles, { margin, k, cones: true });\n const out = (p: Plug): Point => ({ x: p.point.x + p.normal.x * margin, y: p.point.y + p.normal.y * margin });\n let tight: CornerGraph | undefined;\n const tightGraph = (): CornerGraph => (tight ??= new CornerGraph(nodes, obstacles, { margin: Math.min(margin, options.tightMargin ?? LEVEL_LINK_DEFAULTS.tightMargin), k, cones: true }));\n return { obstacles, corners, margin, out, tight: tightGraph, free: new Map() };\n}\n\n/**\n * This function gives the plugs of a link between two boxes. Each plug is on the side that faces the other box.\n * When the two sides face each other and their spans overlap, both plugs are at the middle of the overlap, so the link is straight.\n */\nexport function facingPlugs(a: Box, b: Box, inset: number): [Plug, Plug] {\n const sa = sideToward(a, center(b));\n const sb = sideToward(b, center(a));\n const plug = (box: Box, side: Side, toward: Point): Plug => ({ point: pointOnSide(box, side, toward, inset), normal: SIDE_NORMAL[side] });\n const across = (sa === \"east\" && sb === \"west\") || (sa === \"west\" && sb === \"east\");\n const down = (sa === \"south\" && sb === \"north\") || (sa === \"north\" && sb === \"south\");\n if (across || down) {\n const lo = across ? Math.max(a.y, b.y) + inset : Math.max(a.x, b.x) + inset;\n const hi = across ? Math.min(a.y + a.h, b.y + b.h) - inset : Math.min(a.x + a.w, b.x + b.w) - inset;\n if (lo <= hi) {\n const ca = center(a);\n const cb = center(b);\n const m = Math.max(lo, Math.min(hi, across ? (ca.y + cb.y) / 2 : (ca.x + cb.x) / 2));\n const at = (box: Box, side: Side): Point =>\n across\n ? { x: side === \"east\" ? box.x + box.w : box.x, y: m }\n : { x: m, y: side === \"south\" ? box.y + box.h : box.y };\n return [\n { point: at(a, sa), normal: SIDE_NORMAL[sa] },\n { point: at(b, sb), normal: SIDE_NORMAL[sb] },\n ];\n }\n }\n return [plug(a, sa, center(b)), plug(b, sb, center(a))];\n}\n\nconst SIDES: readonly Side[] = [\"north\", \"east\", \"south\", \"west\"];\n\n/** This function tells if the way out of a plug is free. The plug and the point at `margin` from it are in no other box. */\nfunction isFree(ways: Ways, node: Node, plug: Plug): boolean {\n return !ways.obstacles.inside(ways.out(plug), 0, node) && !ways.obstacles.inside(plug.point, 0, node);\n}\n\n/** This function gives the plug at the middle of a side of the node: the side with a free way out that faces `toward` most. */\nfunction sidePlug(ways: Ways, node: Node, toward: Point): Plug {\n const b = node.box;\n const c = center(b);\n const d = { x: toward.x - c.x, y: toward.y - c.y };\n const facing = (s: Side): number => SIDE_NORMAL[s].x * d.x + SIDE_NORMAL[s].y * d.y;\n const order = [...SIDES].sort((u, v) => facing(v) - facing(u));\n const plug = (s: Side): Plug => {\n const n = SIDE_NORMAL[s];\n return { point: { x: c.x + (n.x * b.w) / 2, y: c.y + (n.y * b.h) / 2 }, normal: n };\n };\n for (const s of order) if (isFree(ways, node, plug(s))) return plug(s);\n return plug(order[0]!);\n}\n\n/**\n * This function gives the free plugs of a node: on each side, the free point nearest to the middle of the side.\n * A point is free when it and the point at `margin` from it are in no other box. The function keeps the plugs of each node.\n */\nfunction freePlugs(ways: LevelWays, node: Node, inset: number): FreePlugs {\n const known = ways.free.get(node);\n if (known) return known;\n const b = node.box;\n const out: Plug[] = [];\n for (const side of SIDES) {\n const n = SIDE_NORMAL[side];\n const across = n.x === 0;\n // The side goes from `lo` to `hi` along its axis, at the coordinate `at` of the other axis.\n const lo = across ? b.x : b.y;\n const hi = across ? b.x + b.w : b.y + b.h;\n const at = across ? (n.y > 0 ? b.y + b.h : b.y) : n.x > 0 ? b.x + b.w : b.x;\n const far = at + (across ? n.y : n.x) * ways.margin;\n // A box covers a point of the side when the point or its way out is inside the box, as in `isFree`.\n const covered: [number, number][] = [];\n const strip = across\n ? { x: lo, y: Math.min(at, far), w: hi - lo, h: Math.abs(far - at) }\n : { x: Math.min(at, far), y: lo, w: Math.abs(far - at), h: hi - lo };\n ways.obstacles.query(strip, (m) => {\n if (m === node) return;\n const o = m.box;\n const [o0, o1, p0, p1] = across ? [o.x, o.x + o.w, o.y, o.y + o.h] : [o.y, o.y + o.h, o.x, o.x + o.w];\n if ((at > p0 && at < p1) || (far > p0 && far < p1)) covered.push([o0, o1]);\n });\n const mid = (lo + hi) / 2;\n let best: number | undefined;\n for (const [f0, f1] of freeSpans(lo, hi, covered)) {\n const room = Math.min(inset, (f1 - f0) / 2);\n const u = Math.max(f0 + room, Math.min(f1 - room, mid));\n if (best === undefined || Math.abs(u - mid) < Math.abs(best - mid)) best = u;\n }\n if (best !== undefined) out.push({ point: across ? { x: best, y: at } : { x: at, y: best }, normal: n });\n }\n const free = { plugs: out, reach: out.map((p) => reach(ways, node, p)) };\n ways.free.set(node, free);\n return free;\n}\n\n/** This function gives the indices of the plugs, and the plugs that face `toward` most come first. */\nfunction facingOrder(plugs: readonly Plug[], from: Point, toward: Point): number[] {\n const facing = (p: Plug): number => p.normal.x * (toward.x - from.x) + p.normal.y * (toward.y - from.y);\n return plugs.map((_, i) => i).sort((u, v) => facing(plugs[v]!) - facing(plugs[u]!) || u - v);\n}\n\n/** This function gives the parts of the span from `lo` to `hi` outside each open interval of `covered`. A part of zero length does not count. */\nfunction freeSpans(lo: number, hi: number, covered: [number, number][]): [number, number][] {\n covered.sort((u, v) => u[0] - v[0]);\n const out: [number, number][] = [];\n let x = lo;\n for (const [c0, c1] of covered) {\n if (c0 > x) out.push([x, Math.min(c0, hi)]);\n x = Math.max(x, c1);\n if (x >= hi) break;\n }\n if (x < hi) out.push([x, hi]);\n return out.filter(([a, b]) => b - a > EPS);\n}\n\n/**\n * This function gives the shortest way between the free plugs of the two nodes, or `undefined` when the second corner graph has none.\n * A link uses it when its plugs at the middle of a side find no way. Other boxes can cover such a plug, or close the space in front of it.\n */\nfunction freeWay(ways: LevelWays, s: Node, t: Node, inset: number): Point[] | undefined {\n const fs = freePlugs(ways, s, inset);\n const ft = freePlugs(ways, t, inset);\n const cs = center(s.box);\n const ct = center(t.box);\n const is = facingOrder(fs.plugs, cs, ct);\n const it = facingOrder(ft.plugs, ct, cs);\n const from = is.map((i) => fs.plugs[i]!);\n const to = it.map((k) => ft.plugs[k]!);\n const ra = is.map((i) => fs.reach[i]!);\n const rb = it.map((k) => ft.reach[k]!);\n // A pair of plugs with one or two clear legs between them gives the short way.\n let best: Point[] | undefined;\n let bestLength = Infinity;\n from.forEach((ps, i) =>\n to.forEach((pt, k) => {\n const way = quickWay(ways, endsAt(ps, ra[i]!, pt, rb[k]!));\n const length = way ? polylineLength(way) : Infinity;\n if (length < bestLength) {\n best = way;\n bestLength = length;\n }\n }),\n );\n if (best) return best;\n // Else one search of the second corner graph finds the shortest way from a plug of `s` to a plug of `t`.\n // The corners of the second graph are near the boxes, so the way can go through a gap that is narrower than the margin.\n const a = from.map((ps, i) => ({ point: along(ps, ra[i]!), cost: ra[i]! }));\n const b = to.map((pt, k) => ({ point: along(pt, rb[k]!), cost: rb[k]! }));\n const found = ways.tight().pathAmong(a, b);\n return found && pulled(ways, from[found.from]!, found.points, to[found.to]!);\n}\n\n/** The two ends of a link: each plug, and the point where the link turns away from the normal of the plug. */\ninterface Ends {\n readonly ps: Plug;\n readonly pt: Plug;\n readonly a: Point;\n readonly b: Point;\n}\n\n/**\n * This function gives the ends of a link. The link leaves each plug along its normal for the margin.\n * A box can be nearer than twice the margin in front of a plug. Then the link turns in the middle of the space before that box.\n * Two plugs that face each other across a narrow space make the link turn in the middle of that space.\n */\nfunction ends(ways: Ways, s: Node, ps: Plug, t: Node, pt: Plug): Ends {\n return endsAt(ps, reach(ways, s, ps), pt, reach(ways, t, pt));\n}\n\n/** This function gives the ends of a link from the plug `ps` to the plug `pt`, with the reach of each plug. */\nfunction endsAt(ps: Plug, ra: number, pt: Plug, rb: number): Ends {\n // Two plugs that face each other turn at the same distance, so the link does not go past itself.\n if (ps.normal.x === -pt.normal.x && ps.normal.y === -pt.normal.y) {\n const d = (pt.point.x - ps.point.x) * ps.normal.x + (pt.point.y - ps.point.y) * ps.normal.y;\n if (d > 0 && ra + rb > d) ra = rb = d / 2;\n }\n return { ps, pt, a: along(ps, ra), b: along(pt, rb) };\n}\n\nconst along = (p: Plug, d: number): Point => ({ x: p.point.x + p.normal.x * d, y: p.point.y + p.normal.y * d });\n\n/** This function gives the distance that a link goes along the normal of a plug before it turns. */\nfunction reach(ways: Ways, node: Node, plug: Plug): number {\n const skip = new Set([node]);\n const far = 2 * ways.margin;\n if (ways.obstacles.clear(plug.point, along(plug, far), 0, skip)) return ways.margin;\n let lo = 0;\n let hi = far;\n for (let i = 0; i < 10; i++) {\n const m = (lo + hi) / 2;\n if (ways.obstacles.clear(plug.point, along(plug, m), 0, skip)) lo = m;\n else hi = m;\n }\n return lo / 2;\n}\n\n/**\n * This function gives the way between the ends when one or two legs parallel to the axes are clear, or `undefined`.\n * The legs keep half the margin from the boxes, or less when an end turns nearer to a box.\n */\nfunction quickWay(ways: Ways, e: Ends): Point[] | undefined {\n const near = Math.min(dist(e.ps.point, e.a), dist(e.pt.point, e.b));\n const pad = Math.max(0, Math.min(ways.margin / 2, near - 1));\n const legs = square(e.a, e.b, ways.obstacles, pad, axisOf(e.ps.normal), axisOf(e.pt.normal));\n return legs && tidy([e.ps.point, e.a, ...legs, e.pt.point]);\n}\n\n/**\n * This function gives a way from the plug `ps` through the points of `path` to the plug `pt`.\n * The way leaves and enters each plug along its normal. Then it pulls the corners tight with legs that are parallel to the axes, where the obstacles let it.\n */\nfunction pulled(ways: Ways, ps: Plug, path: readonly Point[], pt: Plug): Point[] {\n const legs = squarePull(path, ways.obstacles, ways.margin / 2, axisOf(ps.normal), axisOf(pt.normal));\n return tidy([ps.point, ...legs, pt.point]);\n}\n\ntype Axis = \"x\" | \"y\";\n\nconst axisOf = (n: Point): Axis => (Math.abs(n.x) > Math.abs(n.y) ? \"x\" : \"y\");\n\n/**\n * This function pulls a path tight. From each vertex, it goes to the farthest vertex that one or two legs can reach.\n * These legs are parallel to the axes and clear of the obstacles by `pad`. It keeps a diagonal leg only where no such legs are clear.\n * `first` is the axis of the way into the first vertex, and `last` is the axis of the way out of the last vertex.\n */\nfunction squarePull(p: readonly Point[], obstacles: Obstacles, pad: number, first: Axis, last: Axis, lookahead = 16): Point[] {\n if (p.length === 0) return [];\n const out: Point[] = [p[0]!];\n let axis: Axis | undefined = first;\n let i = 0;\n while (i < p.length - 1) {\n let step: { j: number; legs: Point[] } | undefined;\n for (let j = Math.min(p.length - 1, i + lookahead); j > i && !step; j--) {\n const legs = square(p[i]!, p[j]!, obstacles, pad, axis, j === p.length - 1 ? last : undefined);\n if (legs) step = { j, legs };\n }\n // With no clear legs to the next vertex, the legs may touch a box, but they do not go through it.\n step ??= {\n j: i + 1,\n legs: square(p[i]!, p[i + 1]!, obstacles, 0, axis, i + 1 === p.length - 1 ? last : undefined) ?? [p[i + 1]!],\n };\n out.push(...step.legs);\n const end = out[out.length - 1]!;\n const before = out[out.length - 2]!;\n axis = Math.abs(end.y - before.y) < EPS ? \"x\" : Math.abs(end.x - before.x) < EPS ? \"y\" : undefined;\n i = step.j;\n }\n return out;\n}\n\n/**\n * This function gives one or two legs parallel to the axes from `a` to `b`, clear of the obstacles by `pad`, or `undefined`.\n * Of two clear corners, it picks the corner that continues the axis `from` and arrives along the axis `to`.\n */\nfunction square(a: Point, b: Point, obstacles: Obstacles, pad: number, from: Axis | undefined, to: Axis | undefined): Point[] | undefined {\n if (Math.abs(a.x - b.x) < EPS || Math.abs(a.y - b.y) < EPS) return obstacles.clear(a, b, pad) ? [b] : undefined;\n // The corner of `x` goes along the x axis first, and the corner of `y` along the y axis first.\n const options: { c: Point; bends: number }[] = [\n { c: { x: b.x, y: a.y }, bends: (from === \"y\" ? 1 : 0) + (to === \"x\" ? 1 : 0) },\n { c: { x: a.x, y: b.y }, bends: (from === \"x\" ? 1 : 0) + (to === \"y\" ? 1 : 0) },\n ];\n options.sort((u, v) => u.bends - v.bends);\n for (const { c } of options) if (obstacles.clear(a, c, pad) && obstacles.clear(c, b, pad)) return [c, b];\n return undefined;\n}\n","import { BACKTRACK_MIN, goesOutAndBack } from \"../bench/links.ts\";\nimport { center, dist, pointSegmentDistance, polylineLength, type Box, type Point } from \"../geom.ts\";\nimport { LEVEL_LINK_DEFAULTS, levelLinks, type ItemPair, type LevelLinkOptions } from \"../levels.ts\";\nimport { nodeIndex, type Graph, type Level, type LevelItem, type Node, type Result, type Route, type Router, type SharedRun } from \"../model.ts\";\nimport { placePlug } from \"../plugs.ts\";\nimport { allSections, buildSections, checkSections, SECTION_DEFAULTS, treeDepth, type Section, type SectionOptions } from \"../sections.ts\";\nimport { orderLanes } from \"../segments.ts\";\nimport type { Strategy } from \"../strategies/model.ts\";\nimport { WayFinder } from \"../ways.ts\";\n\n/**\n * The options of the router with sections. Each option has a default, and the defaults give the output of version 0.1.5.\n * The options `cap`, `maxDepth` and `collapse` are the limits of the default grouping rule, the quadtree of `buildSections`.\n * The options `tightMargin` and `plugInset` are the limits of the level links (`levelLinks`).\n */\nexport interface SectionsOptions extends LevelLinkOptions, SectionOptions {\n /** The name in the benchmark. */\n readonly name: string;\n /**\n * The number of hubs on each side of the lowest common section that a way passes. A smaller number gives shorter ways\n * and fewer shared ways. Without it, a way passes each hub from its node up.\n */\n readonly hubs?: number;\n /**\n * The hub limit. A way through the hubs can be at most this many times as long as the line between its plugs, plus `stretchPad` margins.\n * Else the edge goes directly. The default is 2. The value `Infinity` keeps each way through the hubs.\n */\n readonly stretch?: number;\n /** A way through the hubs can be this many margins longer than `stretch` times the line between its plugs. The default is 4. */\n readonly stretchPad?: number;\n /**\n * A way skips a hub that is more than this many units farther from the target than the nearest approach of the way before it.\n * The default is 80, two times `BACKTRACK_MIN`. The value `Infinity` keeps each hub.\n */\n readonly hubSlack?: number;\n /**\n * The grouping rule: a strategy of the step `group` that makes the tree of sections. The hubs and the zoom levels come from this tree.\n * Without it, the router uses the quadtree of `buildSections` with the options `cap`, `maxDepth` and `collapse`.\n */\n readonly group?: Strategy<\"group\">;\n /** The options of the strategy `group`. The strategy gets its `defaults` for each option that this object does not give. */\n readonly groupOptions?: object;\n /**\n * The depths of the tree that get a zoom level with groups. The last level, with each node alone, always comes after them.\n * The default is each depth, from 0 to the depth of the deepest section.\n */\n readonly levels?: readonly number[];\n /** The benchmark skips a fixture with more nodes. */\n readonly maxNodes?: number;\n}\n\n/** The default values of the numbers of `SectionsOptions`: the limits of the hubs, of the tree and of the level links. */\nexport const SECTIONS_DEFAULTS: Readonly<Required<Pick<SectionsOptions, \"cap\" | \"maxDepth\" | \"collapse\" | \"tightMargin\" | \"plugInset\" | \"hubs\" | \"stretch\" | \"stretchPad\" | \"hubSlack\">>> =\n Object.freeze({\n cap: SECTION_DEFAULTS.cap,\n maxDepth: SECTION_DEFAULTS.maxDepth,\n collapse: SECTION_DEFAULTS.collapse,\n tightMargin: LEVEL_LINK_DEFAULTS.tightMargin,\n plugInset: LEVEL_LINK_DEFAULTS.plugInset,\n hubs: Infinity,\n stretch: 2,\n stretchPad: 4,\n hubSlack: 2 * BACKTRACK_MIN,\n });\n\nconst dedupe = (p: readonly Point[]): Point[] => p.filter((q, i) => i === 0 || dist(q, p[i - 1]!) > 1e-9);\n\n/**\n * This function makes a router with a tree of sections. Each section has a hub: the free corner nearest to the center of its nodes.\n * An edge goes from its node up the hubs of its sections to the lowest common section, across, and down to the other node.\n * Each way from hub to hub is found one time, so all the edges on it share its points.\n * The edges in one section of the lowest level go straight around the nodes.\n *\n * An edge skips a hub that takes it away from its target. A way that still goes out and back gives way to the direct way.\n *\n * The result gives one zoom level for each depth of the tree.\n * A link of a level goes from the boundary of one item to the boundary of the other, around the other items.\n */\nexport function sectionsRouter(options: SectionsOptions): Router {\n const router: Router = {\n name: options.name,\n route(graph: Graph): Result {\n const stretch = options.stretch ?? SECTIONS_DEFAULTS.stretch;\n const stretchPad = options.stretchPad ?? SECTIONS_DEFAULTS.stretchPad;\n const hubSlack = options.hubSlack ?? SECTIONS_DEFAULTS.hubSlack;\n const byId = nodeIndex(graph);\n const indexOfNode = new Map(graph.nodes.map((n, i) => [n.id, i]));\n const ways = new WayFinder(graph.nodes, options);\n const corners = ways.corners;\n const root = groupNodes(graph, options);\n const parent = new Map<Section, Section>();\n const leafOf: Section[] = [];\n for (const s of allSections(root)) {\n for (const c of s.children) parent.set(c, s);\n if (s.children.length === 0) for (const i of s.nodes) leafOf[i] = s;\n }\n const hubs = new Map<Section, Point>();\n const hub = (s: Section): Point => {\n let h = hubs.get(s);\n if (!h) {\n let x = 0;\n let y = 0;\n for (const i of s.nodes) {\n const c = center(graph.nodes[i]!.box);\n x += c.x;\n y += c.y;\n }\n const c = { x: x / Math.max(1, s.nodes.length), y: y / Math.max(1, s.nodes.length) };\n const j = corners.nearest(c);\n h = j >= 0 ? corners.points[j]! : c;\n hubs.set(s, h);\n }\n return h;\n };\n // The sections of the chain whose hubs do not take the way away from its target. The test uses the straight lines from hub to hub.\n const forward = (list: readonly Section[], from: Point, to: Point): Section[] => {\n const kept: Section[] = [];\n let near = dist(from, to);\n let last = from;\n for (const c of list) {\n const h = hub(c);\n if (dist(h, to) > near + hubSlack) continue;\n near = Math.min(near, pointSegmentDistance(to, last, h));\n last = h;\n kept.push(c);\n }\n return kept;\n };\n const up = (s: Section): Section[] => {\n const out: Section[] = [];\n for (let x: Section | undefined = s; x; x = parent.get(x)) out.push(x);\n return out;\n };\n\n // The ways between two places, found one time. A place is a hub or a free point.\n const pieces = new Map<string, Point[]>();\n const users = new Map<string, string[]>();\n const piece = (ka: string, a: Point, kb: string, b: Point, used: string[]): Point[] => {\n const forward = ka <= kb;\n const key = forward ? `${ka}>${kb}` : `${kb}>${ka}`;\n let p = pieces.get(key);\n if (!p) {\n const [from, to] = forward ? [a, b] : [b, a];\n const way = corners.path(from, to);\n p = dedupe(way ? corners.pull(way) : [from, to]);\n pieces.set(key, p);\n }\n if (!used.includes(key)) used.push(key);\n return forward ? p : [...p].reverse();\n };\n const at = (p: Point): string => `${p.x},${p.y}`;\n\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n const iu = indexOfNode.get(e.source.node);\n const iv = indexOfNode.get(e.target.node);\n if (!s || !t || iu === undefined || iv === undefined) continue;\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n const lu = leafOf[iu]!;\n const lv = leafOf[iv]!;\n if (lu === lv) {\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n continue;\n }\n const a = up(lu);\n const b = up(lv);\n const common = new Set(b);\n const lca = a.find((x) => common.has(x))!;\n const keep = options.hubs ?? SECTIONS_DEFAULTS.hubs;\n const side = (list: Section[]): Section[] => list.slice(Math.max(0, list.indexOf(lca) - keep), list.indexOf(lca));\n const end = ways.out(pt);\n const start = ways.out(ps);\n const chain = forward([...side(a), ...side(b).reverse()], start, pt.point);\n if (chain.length === 0) {\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n continue;\n }\n const out: Point[] = [ps.point];\n const append = (p: readonly Point[]): void => {\n for (const q of p) if (dist(q, out[out.length - 1]!) > 1e-9) out.push(q);\n };\n const used: string[] = [];\n append(piece(at(start), start, chain[0]!.id, hub(chain[0]!), used));\n for (let i = 1; i < chain.length; i++) append(piece(chain[i - 1]!.id, hub(chain[i - 1]!), chain[i]!.id, hub(chain[i]!), used));\n append(piece(chain[chain.length - 1]!.id, hub(chain[chain.length - 1]!), at(end), end, used));\n append([pt.point]);\n // A way through the hubs that is too long, or that goes out and back, gives way to the direct way.\n if (polylineLength(out) > stretch * dist(ps.point, pt.point) + stretchPad * ways.margin || goesOutAndBack(out)) {\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n continue;\n }\n for (const key of used) {\n const list = users.get(key);\n if (list) list.push(e.id);\n else users.set(key, [e.id]);\n }\n routes.push({ edge: e.id, points: out });\n }\n\n const routeOf = new Map(routes.map((r) => [r.edge, r]));\n const runs: SharedRun[] = [];\n for (const [key, p] of pieces) {\n const list = users.get(key) ?? [];\n if (list.length < 2 || p.length < 2) continue;\n runs.push({ id: `r${runs.length}`, key, points: p, edges: orderLanes(p, list.map((id) => routeOf.get(id)!)) });\n }\n return { routes, runs, levels: makeLevels(graph, root, routeOf, options) };\n },\n };\n return options.maxNodes === undefined ? router : { ...router, maxNodes: options.maxNodes };\n}\n\n/** This function gives the tree of sections of the grouping rule. It examines the tree of a strategy (`checkSections`). */\nfunction groupNodes(graph: Graph, options: SectionsOptions): Section {\n if (!options.group) return buildSections(graph.nodes, options);\n const root = options.group.run(graph, options.groupOptions);\n checkSections(root, graph.nodes.length);\n return root;\n}\n\n/**\n * This function gives one zoom level for each depth of the tree, and a last level with each node alone.\n * With the option `levels`, only those depths get a level with groups.\n * At depth d, a section of depth d is one item. A link joins two items and counts the edges between them.\n * In a level with groups, a link goes around the boxes of the other items (`levelLinks`).\n * In the last level, the points of a link are the route of its first edge.\n */\nfunction makeLevels(graph: Graph, root: Section, routeOf: ReadonlyMap<string, Route>, options: SectionsOptions): Level[] {\n const indexOfNode = new Map(graph.nodes.map((n, i) => [n.id, i]));\n const levels: Level[] = [];\n const deepest = treeDepth(root);\n const shown = options.levels && new Set(options.levels);\n for (let d = 0; d <= deepest + 1; d++) {\n if (shown && d <= deepest && !shown.has(d)) continue;\n const items: LevelItem[] = [];\n const itemOf: (Section | number)[] = [];\n const boxOf = (list: readonly number[]): Box => {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const i of list) {\n const b = graph.nodes[i]!.box;\n x0 = Math.min(x0, b.x);\n y0 = Math.min(y0, b.y);\n x1 = Math.max(x1, b.x + b.w);\n y1 = Math.max(y1, b.y + b.h);\n }\n return { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n };\n const visit = (s: Section): void => {\n if (s.depth >= d) {\n items.push({ id: s.id, box: boxOf(s.nodes), nodes: s.nodes.map((i) => graph.nodes[i]!.id) });\n for (const i of s.nodes) itemOf[i] = s;\n } else if (s.children.length > 0) for (const c of s.children) visit(c);\n else\n for (const i of s.nodes) {\n const n = graph.nodes[i]!;\n items.push({ id: n.id, box: n.box, nodes: [n.id] });\n itemOf[i] = i;\n }\n };\n if (graph.nodes.length > 0) visit(root);\n const links = new Map<string, { source: string; target: string; count: number; edge: string }>();\n for (const e of graph.edges) {\n const iu = indexOfNode.get(e.source.node);\n const iv = indexOfNode.get(e.target.node);\n if (iu === undefined || iv === undefined) continue;\n const a = itemOf[iu]!;\n const b = itemOf[iv]!;\n if (a === b) continue;\n const ida = typeof a === \"number\" ? graph.nodes[a]!.id : a.id;\n const idb = typeof b === \"number\" ? graph.nodes[b]!.id : b.id;\n const key = `${ida}\\u0000${idb}`;\n const link = links.get(key);\n if (link) {\n link.count++;\n continue;\n }\n links.set(key, { source: ida, target: idb, count: 1, edge: e.id });\n }\n const pairs: ItemPair[] = [...links.values()].map(({ source, target, count }) => ({ source, target, count }));\n if (d > deepest)\n levels.push({ depth: d, items, links: [...links.values()].map(({ edge, ...l }) => ({ ...l, points: routeOf.get(edge)?.points ?? [] })) });\n else levels.push({ depth: d, items, links: levelLinks(items, pairs, options) });\n }\n return levels;\n}\n","import { center, dist, type Point } from \"../geom.ts\";\nimport { nodeIndex, type Edge, type Graph, type GroupRule, type Result, type Route, type Router, type SharedRun } from \"../model.ts\";\nimport { placePlug, type Plug } from \"../plugs.ts\";\nimport { WayFinder, type WayOptions } from \"../ways.ts\";\n\n/** The options of the router with shared ways. */\nexport interface SharedOptions extends WayOptions {\n /** The name in the benchmark. */\n readonly name: string;\n /** The edges with one key share their ways. Without a rule, all edges share. An edge without a key shares with no edge. */\n readonly rule?: GroupRule;\n /** The cost of a link that an edge with the same key uses already, as a share of its length. The default is 0.5. */\n readonly discount?: number;\n /** The benchmark skips a fixture with more nodes. */\n readonly maxNodes?: number;\n}\n\ninterface Way {\n readonly edge: Edge;\n readonly key: string;\n readonly ps: Plug;\n readonly pt: Plug;\n /** The way through the corner graph, from the point out of the source plug to the point out of the target plug. */\n seq: Point[];\n /** The index of each point of `seq` in the corner graph. The two ends get an index after the corners, one for each place. */\n ids: number[];\n found: boolean;\n}\n\ninterface Run {\n readonly key: string;\n readonly first: number;\n readonly last: number;\n /** The points from the corner `first` to the corner `last`, without the needless corners. */\n readonly points: Point[];\n readonly ways: Way[];\n}\n\nconst byText = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0);\n\n/** The angle, from -π to π, of the turn at `base` from the direction `from` → `base` to the point `to`. */\nfunction turn(from: Point, base: Point, to: Point): number {\n const dx = base.x - from.x;\n const dy = base.y - from.y;\n const vx = to.x - base.x;\n const vy = to.y - base.y;\n return Math.atan2(dx * vy - dy * vx, dx * vx + dy * vy);\n}\n\n/**\n * This function makes a router where edges share their ways (after Pupyrev, Nachmanson, Bereg and Holroyd, \"Edge routing with ordered bundles\").\n * The edges go one by one through the corner graph. A link that an edge with the same key uses already costs less.\n * Thus the edges of a key come together on common ways. Each stretch that several edges share has the same points in each route.\n * The result gives each stretch as a run, with the order of its lanes.\n */\nexport function sharedRouter(options: SharedOptions): Router {\n const discount = Math.min(1, Math.max(0.05, options.discount ?? 0.5));\n const keyOf = (e: Edge): string => {\n if (!options.rule) return \"*\";\n return options.rule(e) ?? `\\u0000${e.id}`;\n };\n const router: Router = {\n name: options.name,\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const ways = new WayFinder(graph.nodes, options);\n const corners = ways.corners;\n const index = new Map<Point, number>();\n corners.points.forEach((p, i) => index.set(p, i));\n const M = corners.points.length + 1;\n const link = (i: number, j: number): number => (i < j ? i * M + j : j * M + i);\n const ends = new Map<string, number>();\n const endId = (p: Point): number => {\n const k = `${p.x},${p.y}`;\n let id = ends.get(k);\n if (id === undefined) ends.set(k, (id = corners.points.length + ends.size));\n return id;\n };\n\n const all: Way[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n all.push({ edge: e, key: keyOf(e), ps, pt, seq: [], ids: [], found: false });\n }\n\n // The edges of one key go one after the other, the longest first, so that the short edges join the long ways.\n const discounted = new Map<string, Map<number, string[]>>();\n const order = [...all].sort(\n (p, q) => byText(p.key, q.key) || dist(q.ps.point, q.pt.point) - dist(p.ps.point, p.pt.point) || byText(p.edge.id, q.edge.id),\n );\n for (const w of order) {\n let used = discounted.get(w.key);\n if (!used) discounted.set(w.key, (used = new Map()));\n const mine = used;\n const way = corners.path(ways.out(w.ps), ways.out(w.pt), (i, j, d) => (mine.has(link(i, j)) ? d * discount : d), discount);\n if (!way) continue;\n w.found = true;\n w.seq = way;\n w.ids = way.map((p, i) => (i === 0 || i === way.length - 1 ? endId(p) : index.get(p)!));\n for (let i = 1; i < w.ids.length; i++) {\n const a = w.ids[i - 1]!;\n const b = w.ids[i]!;\n if (a >= corners.points.length || b >= corners.points.length) continue;\n const list = mine.get(link(a, b));\n if (list) list.push(w.edge.id);\n else mine.set(link(a, b), [w.edge.id]);\n }\n }\n\n // The users of each link, with the links to the ends. Two edges from one plug share the link from it.\n const users = new Map<string, Map<string, string[]>>();\n for (const w of order) {\n if (!w.found) continue;\n let mine = users.get(w.key);\n if (!mine) users.set(w.key, (mine = new Map()));\n for (let i = 1; i < w.ids.length; i++) {\n const a = w.ids[i - 1]!;\n const b = w.ids[i]!;\n const k = a < b ? `${a}:${b}` : `${b}:${a}`;\n const list = mine.get(k);\n if (list) list.push(w.edge.id);\n else mine.set(k, [w.edge.id]);\n }\n }\n\n // Each way breaks into stretches where the set of edges on the links stays the same.\n // A shared stretch loses its needless corners one time, so it has the same points in each of its routes.\n const runs = new Map<string, Run>();\n const points = new Map<string, Point[]>();\n for (const w of all) {\n if (!w.found) continue;\n const used = users.get(w.key)!;\n const sig = (i: number): string => {\n const a = w.ids[i]!;\n const b = w.ids[i + 1]!;\n const list = used.get(a < b ? `${a}:${b}` : `${b}:${a}`)!;\n return list.length < 2 ? \"\" : [...list].sort(byText).join(\"\\u0001\");\n };\n const out: Point[] = [w.ps.point];\n const append = (piece: readonly Point[]): void => {\n for (const p of piece) if (dist(p, out[out.length - 1]!) > 1e-9) out.push(p);\n };\n let start = 0;\n for (let i = 0; i < w.seq.length - 1; i++) {\n const s = sig(i);\n if (i + 1 < w.seq.length - 1 && sig(i + 1) === s) continue;\n const raw = w.seq.slice(start, i + 2);\n if (s === \"\") append(corners.pull(raw));\n else {\n const a = w.ids[start]!;\n const b = w.ids[i + 1]!;\n const id = `${s}\\u0002${Math.min(a, b)}\\u0002${Math.max(a, b)}`;\n let run = runs.get(id);\n if (!run) {\n run = { key: w.key, first: Math.min(a, b), last: Math.max(a, b), points: corners.pull(a < b ? raw : [...raw].reverse()), ways: [] };\n runs.set(id, run);\n }\n run.ways.push(w);\n append(a < b ? run.points : [...run.points].reverse());\n }\n start = i + 1;\n }\n append([w.pt.point]);\n points.set(w.edge.id, out);\n }\n\n const routes: Route[] = [];\n for (const w of all) routes.push({ edge: w.edge.id, points: points.get(w.edge.id) ?? [w.ps.point, w.pt.point] });\n const shared: SharedRun[] = [];\n for (const run of runs.values()) {\n shared.push({ id: `r${shared.length}`, key: run.key, points: run.points, edges: laneOrderOfRun(run) });\n }\n return { routes, runs: shared };\n },\n };\n return options.maxNodes === undefined ? router : { ...router, maxNodes: options.maxNodes };\n}\n\n/**\n * This function gives the lane order of a run (metro-line order). Two edges of the run go together past its last corner\n * until they part. The edge that turns more to the left there gets the lane more to the left.\n * Two edges can part only before the first corner. Then the edge that comes from more to the left gets the lane more to the left.\n */\nfunction laneOrderOfRun(run: Run): string[] {\n const oriented = new Map<Way, { seq: Point[]; ids: number[]; s: number; e: number }>();\n for (const w of run.ways) {\n const s0 = w.ids.indexOf(run.first);\n const e0 = w.ids.indexOf(run.last);\n if (s0 < e0) oriented.set(w, { seq: w.seq, ids: w.ids, s: s0, e: e0 });\n else oriented.set(w, { seq: [...w.seq].reverse(), ids: [...w.ids].reverse(), s: w.seq.length - 1 - s0, e: w.seq.length - 1 - e0 });\n }\n const compare = (p: Way, q: Way): number => {\n const P = oriented.get(p)!;\n const Q = oriented.get(q)!;\n for (let j = 1; ; j++) {\n const a = P.seq[P.e + j];\n const b = Q.seq[Q.e + j];\n if (a === undefined || b === undefined) break;\n if (P.ids[P.e + j] !== Q.ids[Q.e + j]) {\n const d = turn(P.seq[P.e + j - 2]!, P.seq[P.e + j - 1]!, a) - turn(P.seq[P.e + j - 2]!, P.seq[P.e + j - 1]!, b);\n if (d !== 0) return d;\n break;\n }\n }\n for (let j = 1; ; j++) {\n const a = P.seq[P.s - j];\n const b = Q.seq[Q.s - j];\n if (a === undefined || b === undefined) break;\n if (P.ids[P.s - j] !== Q.ids[Q.s - j]) {\n // Seen backward, the left side is the right side. Thus the order turns around.\n const d = turn(P.seq[P.s - j + 2]!, P.seq[P.s - j + 1]!, b) - turn(P.seq[P.s - j + 2]!, P.seq[P.s - j + 1]!, a);\n if (d !== 0) return d;\n break;\n }\n }\n return byText(p.edge.id, q.edge.id);\n };\n return [...run.ways].sort(compare).map((w) => w.edge.id);\n}\n","import { center, type Box, type Point } from \"../geom.ts\";\nimport { fixedPortPoint, nodeIndex, type Graph, type Result, type Route, type Router } from \"../model.ts\";\n\n/** This function gives the point where the ray from the center of the box to `toward` leaves the box. */\nexport function boxExit(box: Box, toward: Point): Point {\n const c = center(box);\n const dx = toward.x - c.x;\n const dy = toward.y - c.y;\n if (dx === 0 && dy === 0) return c;\n const tx = dx === 0 ? Infinity : box.w / 2 / Math.abs(dx);\n const ty = dy === 0 ? Infinity : box.h / 2 / Math.abs(dy);\n const t = Math.min(tx, ty);\n return { x: c.x + dx * t, y: c.y + dy * t };\n}\n\n/**\n * The control of the benchmark: each edge is one straight line between its plugs.\n * A free plug goes where the line between the two centers leaves the box.\n */\nexport const straightRouter: Router = {\n name: \"straight\",\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const fs = fixedPortPoint(s, e.source);\n const ft = fixedPortPoint(t, e.target);\n const a = fs ?? boxExit(s.box, ft ?? center(t.box));\n const b = ft ?? boxExit(t.box, fs ?? center(s.box));\n routes.push({ edge: e.id, points: [a, b] });\n }\n return { routes };\n },\n};\n","import { center, dist, type Point } from \"../geom.ts\";\nimport { nodeIndex, type Bundle, type Edge, type Graph, type GroupRule, type Node, type Result, type Route, type Router } from \"../model.ts\";\nimport { placePlug, type Plug } from \"../plugs.ts\";\nimport { WayFinder, type WayOptions } from \"../ways.ts\";\n\n/** The options of the trunk router. */\nexport interface TrunksOptions extends WayOptions {\n /** The name in the benchmark. */\n readonly name: string;\n /** The grouping rule. The edges from one plug with one key share a trunk. */\n readonly rule: GroupRule;\n /** The split point is at this share of the way to the center of the targets. The default is 0.5. */\n readonly split?: number;\n /** A group with fewer edges stays unbundled. The default is 2. */\n readonly minSize?: number;\n /** The benchmark skips a fixture with more nodes. */\n readonly maxNodes?: number;\n}\n\n/** The rule that groups the edges by the collection of their target, in `data.collection`. */\nexport const byCollection: GroupRule = (e) => {\n const c = e.data?.[\"collection\"];\n return typeof c === \"string\" ? c : undefined;\n};\n\n/**\n * This function groups the edges by their source plug and their key. Each group keeps the order of the edges.\n * A group with fewer than `minSize` edges does not appear.\n */\nexport function groupEdges(edges: readonly Edge[], rule: GroupRule, minSize = 2): Map<string, Edge[]> {\n const all = new Map<string, Edge[]>();\n for (const e of edges) {\n const key = rule(e);\n if (key === undefined) continue;\n const id = `${e.source.node}\\u0000${e.source.port ?? \"\"}\\u0000${key}`;\n const list = all.get(id);\n if (list) list.push(e);\n else all.set(id, [e]);\n }\n for (const [id, list] of all) if (list.length < minSize) all.delete(id);\n return all;\n}\n\n/**\n * This function gives the lane order of the branches that leave the split point `from`, with the trunk along `dir`.\n * Lane 0 turns most to the left, in a frame with the y axis down. Thus two lanes do not cross at the split.\n */\nexport function laneOrder(dir: Point, from: Point, branches: readonly { readonly edge: string; readonly next: Point }[]): string[] {\n const angle = (p: Point): number => {\n const vx = p.x - from.x;\n const vy = p.y - from.y;\n return Math.atan2(dir.x * vy - dir.y * vx, dir.x * vx + dir.y * vy);\n };\n return branches\n .map((b) => ({ edge: b.edge, a: angle(b.next) }))\n .sort((p, q) => p.a - q.a || (p.edge < q.edge ? -1 : p.edge > q.edge ? 1 : 0))\n .map((x) => x.edge);\n}\n\n/**\n * This function gives the split point of a bundle, on the line from `start` to the center of the targets.\n * The point is at `split` of the way, but at most half of the way to the nearest target. It moves back toward `start` out of the boxes.\n */\nexport function splitPoint(start: Point, targets: readonly Point[], split: number, free: (p: Point) => boolean, step: number): Point {\n if (targets.length === 0) return start;\n const c = { x: targets.reduce((s, p) => s + p.x, 0) / targets.length, y: targets.reduce((s, p) => s + p.y, 0) / targets.length };\n const L = dist(start, c);\n if (L === 0) return start;\n let d = Math.min(split * L, 0.5 * Math.min(...targets.map((p) => dist(start, p))));\n const at = (t: number): Point => ({ x: start.x + ((c.x - start.x) * t) / L, y: start.y + ((c.y - start.y) * t) / L });\n while (d > 0 && !free(at(d))) d -= step;\n return d > 0 ? at(d) : start;\n}\n\nconst dedupe = (p: readonly Point[]): Point[] => p.filter((q, i) => i === 0 || dist(q, p[i - 1]!) > 1e-9);\n\n/**\n * This function makes a router that bundles the edges by a rule. The edges of a group share one plug and one trunk\n * to a split point. From there, each edge goes its own way. The router gives the bundles with their lane order.\n * The edges outside the groups go as in the corner router.\n */\nexport function trunksRouter(options: TrunksOptions): Router {\n const router: Router = {\n name: options.name,\n route(graph: Graph): Result {\n const byId = nodeIndex(graph);\n const ways = new WayFinder(graph.nodes, options);\n const points = new Map<string, Point[]>();\n const bundles: Bundle[] = [];\n for (const [id, group] of groupEdges(graph.edges, options.rule, options.minSize ?? 2)) {\n const first = group[0]!;\n const s = byId.get(first.source.node);\n const targets = group.map((e) => byId.get(e.target.node));\n if (!s || targets.some((t) => !t)) continue;\n const centers = targets.map((t) => center(t!.box));\n const c = { x: centers.reduce((a, p) => a + p.x, 0) / centers.length, y: centers.reduce((a, p) => a + p.y, 0) / centers.length };\n const plug: Plug = placePlug(s, first.source, c);\n const start = ways.out(plug);\n const split = splitPoint(start, centers, options.split ?? 0.5, (p) => !ways.obstacles.inside(p, ways.margin), ways.margin);\n const way = ways.fromPlug(plug, split);\n if (!way) continue;\n const trunk = dedupe(way);\n const end = trunk[trunk.length - 1]!;\n const prev = trunk.length >= 2 ? trunk[trunk.length - 2]! : plug.point;\n const len = dist(prev, end);\n const dir = len > 0 ? { x: (end.x - prev.x) / len, y: (end.y - prev.y) / len } : plug.normal;\n const branches: { edge: string; next: Point }[] = [];\n group.forEach((e, i) => {\n const pt = placePlug(targets[i]!, e.target, end);\n const branch = dedupe(ways.toPlug(end, pt) ?? [end, pt.point]);\n points.set(e.id, dedupe([...trunk, ...branch.slice(1)]));\n branches.push({ edge: e.id, next: branch[1] ?? pt.point });\n });\n bundles.push({ id: `b${bundles.length}`, key: id.split(\"\\u0000\")[2]!, node: s.id, edges: laneOrder(dir, end, branches), trunk });\n }\n const routes: Route[] = [];\n for (const e of graph.edges) {\n const s = byId.get(e.source.node);\n const t = byId.get(e.target.node);\n if (!s || !t) continue;\n const known = points.get(e.id);\n if (known) {\n routes.push({ edge: e.id, points: known });\n continue;\n }\n const ps = placePlug(s, e.source, center(t.box));\n const pt = placePlug(t, e.target, center(s.box));\n routes.push({ edge: e.id, points: ways.between(ps, pt, new Set<Node>([s, t])) });\n }\n return { routes, bundles };\n },\n };\n return options.maxNodes === undefined ? router : { ...router, maxNodes: options.maxNodes };\n}\n","import type { Router } from \"../model.ts\";\nimport { cornersRouter } from \"./corners.ts\";\nimport { plugsRouter } from \"./plugs.ts\";\nimport { sectionsRouter } from \"./sections.ts\";\nimport { sharedRouter } from \"./shared.ts\";\nimport { straightRouter } from \"./straight.ts\";\nimport { byCollection, trunksRouter } from \"./trunks.ts\";\n\nexport { boxExit, straightRouter } from \"./straight.ts\";\nexport { plugsRouter } from \"./plugs.ts\";\nexport { cornersRouter, type CornersOptions } from \"./corners.ts\";\nexport { sharedRouter, type SharedOptions } from \"./shared.ts\";\nexport { sectionsRouter, type SectionsOptions } from \"./sections.ts\";\nexport { byCollection, groupEdges, laneOrder, splitPoint, trunksRouter, type TrunksOptions } from \"./trunks.ts\";\n\n/** The built-in routers. The registry `STRATEGIES` holds the same routers as strategies, and the benchmark races the routers of the registry. */\nexport const ROUTERS: readonly Router[] = [\n straightRouter,\n plugsRouter,\n cornersRouter({ name: \"corners\", maxNodes: 10_000 }),\n cornersRouter({ name: \"corners-smooth\", smooth: true, maxNodes: 10_000 }),\n trunksRouter({ name: \"trunks\", rule: byCollection, maxNodes: 10_000 }),\n sharedRouter({ name: \"shared\", rule: byCollection, maxNodes: 10_000 }),\n sharedRouter({ name: \"shared-all\", maxNodes: 10_000 }),\n sectionsRouter({ name: \"sections\", maxNodes: 100_000 }),\n sectionsRouter({ name: \"sections-tree\", stretch: Infinity, maxNodes: 100_000 }),\n];\n","import { center, type Box, type Point } from \"../geom.ts\";\nimport { levelLinks } from \"../levels.ts\";\nimport type { Edge, Graph, Router } from \"../model.ts\";\n\n/** An item with a box: a node of a graph, an item of a level or a box of a host layout. */\nexport interface Boxed {\n readonly id: string;\n readonly box: Box;\n}\n\n/** A link between two boxes. For a bundled link, `count` is the number of its edges. The default count is 1. */\nexport interface RoomLink {\n readonly source: string;\n readonly target: string;\n readonly count?: number;\n}\n\n/**\n * A gap of a board: a boundary of the sweep over the left or top edges of the boxes.\n * On the axis `x`, the gap is a vertical channel between two columns. On the axis `y`, it is a horizontal channel between two rows.\n */\nexport interface Gap {\n readonly axis: \"x\" | \"y\";\n /** The place of the gap in the order of the gaps on its axis, from 0. */\n readonly index: number;\n /** The coordinate where the boxes after the gap start, on the axis of the gap. */\n readonly at: number;\n /** The ids of the boxes that end at the near side of the gap. */\n readonly before: readonly string[];\n /** The ids of the boxes that start at the far side of the gap, at `at`. */\n readonly after: readonly string[];\n /** The current width of the gap: the distance from the nearest box edge before the gap to `at`. */\n readonly width: number;\n /** The number of lanes that the links need in the gap. */\n readonly lanes: number;\n /** The width that the gap needs: at least the current width, and at least `gutter + lanes × spacing`. */\n readonly need: number;\n}\n\n/** The ways that `roomDemand` finds the lanes of each gap. */\nexport type RoomMethod = \"routes\" | \"lines\";\n\n/** The options of `roomDemand` and `makeRoom`. */\nexport interface RoomOptions {\n /** The smallest width of each gap. The default is 8. */\n readonly gutter?: number;\n /** The width of one lane: the distance between two lines that run side by side. The default is 4. */\n readonly spacing?: number;\n /**\n * The largest growth of the board on each axis, as a share of its size. The default is `Infinity`.\n * When the lanes need more, each gap gets its gutter, and the lanes share the rest in proportion.\n */\n readonly maxGrowth?: number;\n /**\n * The way to find the lanes. The default is `routes`.\n * With `routes`, the function routes the links one time on the board with each gap open to the gutter.\n * The lanes of a gap are the most routes that run along the gap side by side.\n * With `lines`, the lanes of a gap are the straight lines between the centers of the boxes that cross the gap.\n */\n readonly method?: RoomMethod;\n /** The router of the method `routes`. Without it, the links go as the links of a zoom level (`levelLinks`), with the margin `gutter / 2`. */\n readonly router?: Router;\n /** With `count`, a link takes one lane for each of its edges. With `link`, the default, a link takes one lane. */\n readonly lanes?: \"link\" | \"count\";\n /** Two box edges nearer than this distance make one boundary of the sweep. The default is 0.5. */\n readonly snap?: number;\n /**\n * The number of passes of the demand. The default is 1.\n * Each pass after the first finds the lanes again on the board that the passes before it opened, and adds the growth that it needs.\n * The limit `maxGrowth` applies to the sum of the passes.\n */\n readonly passes?: number;\n}\n\n/** The demand of a board and the board with its gaps open. */\nexport interface Room<T extends Boxed> {\n readonly gaps: readonly Gap[];\n readonly items: T[];\n}\n\nconst DEFAULT_GUTTER = 8;\nconst DEFAULT_SPACING = 4;\nconst DEFAULT_SNAP = 0.5;\n\ntype Axis = \"x\" | \"y\";\n\nconst lo = (b: Box, a: Axis): number => (a === \"x\" ? b.x : b.y);\nconst len = (b: Box, a: Axis): number => (a === \"x\" ? b.w : b.h);\nconst other = (a: Axis): Axis => (a === \"x\" ? \"y\" : \"x\");\n\n/**\n * This function gives the gaps of a board. A sweep over each axis sorts the left (or top) edges of the boxes.\n * Each distinct edge after the first is a gap. The `lanes` of each gap are 0, and its `need` is its current width.\n */\nexport function boardGaps(items: readonly Boxed[], snap: number = DEFAULT_SNAP): Gap[] {\n return [...axisGaps(items, \"x\", snap), ...axisGaps(items, \"y\", snap)];\n}\n\nfunction axisGaps(items: readonly Boxed[], axis: Axis, snap: number): Gap[] {\n const starts = [...new Set(items.map((i) => lo(i.box, axis)))].sort((u, v) => u - v);\n const bounds: number[] = [];\n for (const s of starts) if (bounds.length === 0 || s - bounds[bounds.length - 1]! > snap) bounds.push(s);\n const after: string[][] = bounds.map(() => []);\n for (const i of items) after[lastAtOrBefore(bounds, lo(i.box, axis) + snap)]!.push(i.id);\n const ends = items.map((i) => ({ id: i.id, end: lo(i.box, axis) + len(i.box, axis) })).sort((u, v) => u.end - v.end);\n const gaps: Gap[] = [];\n let k = 0;\n for (let n = 1; n < bounds.length; n++) {\n const at = bounds[n]!;\n // The nearest box edge before the gap is the largest end at or before the boundary.\n while (k < ends.length && ends[k]!.end <= at + snap) k++;\n const near = k > 0 ? ends[k - 1]!.end : at;\n const before: string[] = [];\n for (let j = k - 1; j >= 0 && ends[j]!.end >= near - snap; j--) before.push(ends[j]!.id);\n gaps.push({ axis, index: n - 1, at, before: before.reverse(), after: after[n]!, width: Math.max(0, at - near), lanes: 0, need: Math.max(0, at - near) });\n }\n return gaps;\n}\n\n/** This function gives the index of the last value of the sorted list `v` that is at or before `x`, or 0. */\nfunction lastAtOrBefore(v: readonly number[], x: number): number {\n let a = 0;\n let b = v.length - 1;\n while (a < b) {\n const m = (a + b + 1) >> 1;\n if (v[m]! <= x) a = m;\n else b = m - 1;\n }\n return a;\n}\n\n/**\n * This function moves the boxes apart, so that each gap gets the width `need`. The boxes keep their size, their order and their alignment.\n * A box moves by the sum of the growth of each gap at or before its left (or top) edge. Thus a grid stays a grid.\n * The function moves no box nearer to another box, so it makes no overlap.\n */\nexport function openGaps<T extends Boxed>(items: readonly T[], gaps: readonly Gap[], snap: number = DEFAULT_SNAP): T[] {\n const shift = (axis: Axis): ((v: number) => number) => {\n const list = gaps.filter((g) => g.axis === axis).sort((u, v) => u.at - v.at);\n const at = list.map((g) => g.at);\n const sum: number[] = [];\n let s = 0;\n for (const g of list) sum.push((s += Math.max(0, g.need - g.width)));\n return (v) => (list.length === 0 || at[0]! > v + snap ? 0 : sum[lastAtOrBefore(at, v + snap)]!);\n };\n const sx = shift(\"x\");\n const sy = shift(\"y\");\n return items.map((i) => ({ ...i, box: { ...i.box, x: i.box.x + sx(i.box.x), y: i.box.y + sy(i.box.y) } }));\n}\n\n/**\n * This function gives the room that the links need in each gap of the board.\n * The lanes of a gap come from the `method` of the options. The need of a gap is `gutter + lanes × spacing`, and not less than its current width.\n */\nexport function roomDemand(items: readonly Boxed[], links: readonly RoomLink[], options: RoomOptions = {}): Gap[] {\n const gutter = options.gutter ?? DEFAULT_GUTTER;\n const snap = options.snap ?? DEFAULT_SNAP;\n const passes = Math.max(1, Math.floor(options.passes ?? 1));\n let total = demandOnce(items, links, options);\n for (let p = 1; p < passes; p++) {\n // The next pass measures the board that the passes before it opened. Its gaps are the same gaps, in the same order.\n const next = demandOnce(openGaps(items, total, snap), links, options);\n if (next.length !== total.length || next.some((g, i) => g.axis !== total[i]!.axis)) break;\n total = total.map((g, i) => ({ ...g, lanes: Math.max(g.lanes, next[i]!.lanes), need: g.need + Math.max(0, next[i]!.need - next[i]!.width) }));\n }\n return capGrowth(items, total, gutter, options.maxGrowth ?? Infinity);\n}\n\n/** This function gives the demand of one pass, without the limit `maxGrowth`. */\nfunction demandOnce(items: readonly Boxed[], links: readonly RoomLink[], options: RoomOptions): Gap[] {\n const gutter = options.gutter ?? DEFAULT_GUTTER;\n const spacing = options.spacing ?? DEFAULT_SPACING;\n const snap = options.snap ?? DEFAULT_SNAP;\n const weight = (l: RoomLink): number => (options.lanes === \"count\" ? Math.max(1, l.count ?? 1) : 1);\n const gaps = boardGaps(items, snap);\n const lanes = (options.method ?? \"routes\") === \"lines\" ? lineLanes(items, links, gaps, weight) : routeLanes(items, links, gaps, gutter, snap, weight, options.router);\n return gaps.map((g, i) => ({ ...g, lanes: lanes[i]!, need: Math.max(g.width, gutter + lanes[i]! * spacing) }));\n}\n\n/** This function gives the demand of the board and the board with each gap open to its need. */\nexport function makeRoom<T extends Boxed>(items: readonly T[], links: readonly RoomLink[], options: RoomOptions = {}): Room<T> {\n const gaps = roomDemand(items, links, options);\n return { gaps, items: openGaps(items, gaps, options.snap ?? DEFAULT_SNAP) };\n}\n\n/** This function gives the links between the nodes of a graph, with the count of the edges of each pair. A loop does not count. */\nexport function roomLinks(graph: Graph): RoomLink[] {\n const byPair = new Map<string, { source: string; target: string; count: number }>();\n for (const e of graph.edges) {\n const [s, t] = [e.source.node, e.target.node];\n if (s === t) continue;\n const key = s < t ? `${s}\\u0000${t}` : `${t}\\u0000${s}`;\n const known = byPair.get(key);\n if (known) known.count++;\n else byPair.set(key, { source: s, target: t, count: 1 });\n }\n return [...byPair.values()];\n}\n\n/** This function counts, for each gap, the straight lines between the centers of the boxes of a link that cross the gap. */\nfunction lineLanes(items: readonly Boxed[], links: readonly RoomLink[], gaps: readonly Gap[], weight: (l: RoomLink) => number): number[] {\n const byId = new Map(items.map((i) => [i.id, center(i.box)]));\n return gaps.map((g) => {\n let n = 0;\n for (const l of links) {\n const a = byId.get(l.source);\n const b = byId.get(l.target);\n if (a && b && Math.min(a[g.axis], b[g.axis]) < g.at && Math.max(a[g.axis], b[g.axis]) > g.at) n += weight(l);\n }\n return n;\n });\n}\n\n/**\n * This function routes the links one time on the board with each gap open to the gutter.\n * The lanes of a gap are the largest number of routes that run along the gap at one place.\n * A piece of a route goes along a gap when it is in the channel of the gap.\n * It must also go farther along the gap than across it.\n */\nfunction routeLanes(\n items: readonly Boxed[],\n links: readonly RoomLink[],\n gaps: readonly Gap[],\n gutter: number,\n snap: number,\n weight: (l: RoomLink) => number,\n router: Router | undefined,\n): number[] {\n const probeGaps = gaps.map((g) => ({ ...g, need: Math.max(g.width, gutter) }));\n const probe = openGaps(items, probeGaps, snap);\n const ways = probeWays(probe, links, gutter, router);\n return probeGaps.map((g) => {\n // The channel of the gap on the probe board: its far side moves with the growth of each gap up to this one.\n let grow = 0;\n for (const h of probeGaps) if (h.axis === g.axis && h.at <= g.at + snap) grow += h.need - h.width;\n const hi = g.at + grow;\n const lo = hi - g.need;\n const spans: { from: number; to: number; w: number }[] = [];\n ways.forEach((points, i) => {\n const along = alongSpans(points, g.axis, lo, hi);\n for (const [from, to] of merge(along)) spans.push({ from, to, w: weight(links[i]!) });\n });\n return density(spans);\n });\n}\n\n/** This function gives the points of the way of each link on the probe board, in the order of the links. */\nfunction probeWays(items: readonly Boxed[], links: readonly RoomLink[], gutter: number, router: Router | undefined): (readonly Point[])[] {\n if (router) {\n const edges: Edge[] = links.map((l, i) => ({ id: `l${i}`, source: { node: l.source }, target: { node: l.target } }));\n const routes = new Map(router.route({ nodes: items, edges }).routes.map((r) => [r.edge, r.points]));\n return edges.map((e) => routes.get(e.id) ?? []);\n }\n const level = items.map((i) => ({ id: i.id, box: i.box, nodes: [i.id] }));\n const pairs = links.map((l) => ({ source: l.source, target: l.target, count: l.count ?? 1 }));\n // The margin puts the corners of the two sides of a gap on its middle line.\n const out = levelLinks(level, pairs, { margin: Math.max(1, gutter / 2) });\n const byPair = new Map(out.map((l) => [`${l.source}\\u0000${l.target}`, l.points]));\n return links.map((l) => byPair.get(`${l.source}\\u0000${l.target}`) ?? []);\n}\n\n/**\n * This function gives the spans along the axis of a gap where the polyline goes along the channel from `lo` to `hi`.\n * The axis `x` gap is a vertical channel, so its spans are on the y axis.\n */\nfunction alongSpans(p: readonly Point[], axis: Axis, lo: number, hi: number): [number, number][] {\n const across = axis;\n const along = other(axis);\n const out: [number, number][] = [];\n for (let i = 1; i < p.length; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n const da = b[across] - a[across];\n // The part of the segment inside the channel, as the parameters t0 and t1 of the segment.\n let t0 = 0;\n let t1 = 1;\n if (Math.abs(da) < 1e-9) {\n if (a[across] < lo - 1e-6 || a[across] > hi + 1e-6) continue;\n } else {\n const u = (lo - a[across]) / da;\n const v = (hi - a[across]) / da;\n t0 = Math.max(0, Math.min(u, v));\n t1 = Math.min(1, Math.max(u, v));\n if (t1 <= t0) continue;\n }\n const s = a[along] + (b[along] - a[along]) * t0;\n const e = a[along] + (b[along] - a[along]) * t1;\n const run = Math.abs(e - s);\n const cross = Math.abs(da) * (t1 - t0);\n if (run > cross && run > 1e-6) out.push([Math.min(s, e), Math.max(s, e)]);\n }\n return out;\n}\n\n/** This function joins the spans that overlap, so that one link counts one time at each place. */\nfunction merge(spans: [number, number][]): [number, number][] {\n spans.sort((u, v) => u[0] - v[0]);\n const out: [number, number][] = [];\n for (const s of spans) {\n const last = out[out.length - 1];\n if (last && s[0] <= last[1]) last[1] = Math.max(last[1], s[1]);\n else out.push([s[0], s[1]]);\n }\n return out;\n}\n\n/** This function gives the largest sum of the weights of the spans that overlap at one place. Spans that only touch do not overlap. */\nfunction density(spans: readonly { from: number; to: number; w: number }[]): number {\n const events: [number, number][] = [];\n for (const s of spans) events.push([s.from, s.w], [s.to, -s.w]);\n // At one coordinate, the ends come before the starts.\n events.sort((u, v) => u[0] - v[0] || u[1] - v[1]);\n let n = 0;\n let best = 0;\n for (const [, w] of events) {\n n += w;\n best = Math.max(best, n);\n }\n return best;\n}\n\n/**\n * This function keeps the growth of the board on each axis at most `maxGrowth` times its size.\n * Each gap keeps its gutter. The lanes of all gaps of the axis share the rest of the growth in proportion.\n */\nfunction capGrowth(items: readonly Boxed[], gaps: Gap[], gutter: number, maxGrowth: number): Gap[] {\n if (!Number.isFinite(maxGrowth)) return gaps;\n const out = [...gaps];\n for (const axis of [\"x\", \"y\"] as const) {\n let x0 = Infinity;\n let x1 = -Infinity;\n for (const i of items) {\n x0 = Math.min(x0, lo(i.box, axis));\n x1 = Math.max(x1, lo(i.box, axis) + len(i.box, axis));\n }\n const budget = Math.max(0, maxGrowth) * Math.max(0, x1 - x0);\n let base = 0;\n let spare = 0;\n for (const g of gaps) {\n if (g.axis !== axis) continue;\n const b = Math.max(0, gutter - g.width);\n base += b;\n spare += Math.max(0, g.need - g.width - b);\n }\n if (base + spare <= budget || spare === 0) continue;\n const f = Math.max(0, (budget - base) / spare);\n gaps.forEach((g, i) => {\n if (g.axis !== axis) return;\n const b = Math.max(0, gutter - g.width);\n out[i] = { ...g, need: g.width + b + f * Math.max(0, g.need - g.width - b) };\n });\n }\n return out;\n}\n","import { segmentHitsBox, type Box, type Point } from \"../geom.ts\";\nimport { Grid } from \"../grid.ts\";\nimport type { LevelLink } from \"../model.ts\";\nimport { boardGaps, type Boxed } from \"./index.ts\";\n\n/**\n * The lane order of the pieces of the links in one gap.\n *\n * - `links`: the order of the list of links. This order reads nothing of the board.\n * - `ends`: the pieces that turn to the near side at their two ends come first. The pieces that turn to the far side come last.\n * - `crossings`: the order with the fewest crossings between the pieces of the gap and the legs at their ends. A local search finds it.\n */\nexport type LaneOrder = \"links\" | \"ends\" | \"crossings\";\n\n/** The lane orders of `gapLanes`, in the order of the benchmark. */\nexport const LANE_ORDERS: readonly LaneOrder[] = [\"links\", \"ends\", \"crossings\"];\n\n/** The options of `gapLanes`. */\nexport interface GapLaneOptions {\n /** The largest distance between two lanes. A narrow gap puts its lanes nearer. The default is 4. */\n readonly spacing?: number;\n /** The lane order in each gap. The default is `crossings`. */\n readonly order?: LaneOrder;\n /** Two box edges nearer than this distance make one boundary of the sweep, as in `boardGaps`. The default is 0.5. */\n readonly snap?: number;\n}\n\n/** A piece of a link: a leg of the link that runs along a gap. */\ninterface Piece {\n /** The index of the link. */\n readonly link: number;\n /** The index of the last point of the leg. The leg goes from the point `seg - 1` to the point `seg`. */\n readonly seg: number;\n /** The span of the leg along the gap. */\n readonly lo: number;\n readonly hi: number;\n /** For each end of the leg: its place along the gap, and the side (-1 or 1) across the gap where the link turns. */\n readonly turns: readonly (readonly [number, number])[];\n}\n\nconst EPS = 1e-6;\nconst ROUNDS = 8;\n\n/**\n * This function gives each link that runs along a gap its own lane in the gap. The lanes of a gap are `spacing` apart, around its middle line.\n * A leg of a link moves across its gap only, so the link keeps its plugs and the axes of its legs.\n * When a move puts a link through more boxes than before, the link keeps its points.\n */\nexport function gapLanes(items: readonly Boxed[], links: readonly LevelLink[], options: GapLaneOptions = {}): LevelLink[] {\n const spacing = Math.max(0, options.spacing ?? 4);\n const order = options.order ?? \"crossings\";\n const moved = links.map((l) => l.points.map((p) => ({ x: p.x, y: p.y })));\n for (const g of boardGaps(items, options.snap)) {\n if (g.width <= EPS) continue;\n const across = g.axis;\n const along = g.axis === \"x\" ? \"y\" : \"x\";\n const lo = g.at - g.width;\n const hi = g.at;\n const pieces: Piece[] = [];\n links.forEach((l, li) => {\n const p = l.points;\n // The first and the last legs hold the plugs, so they do not move.\n for (let i = 2; i <= p.length - 2; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n if (Math.abs(a[across] - b[across]) > EPS || a[across] <= lo + EPS || a[across] >= hi - EPS) continue;\n if (Math.abs(a[along] - b[along]) <= EPS) continue;\n const side = (q: Point, r: Point): number => Math.sign(r[across] - q[across]);\n pieces.push({\n link: li,\n seg: i,\n lo: Math.min(a[along], b[along]),\n hi: Math.max(a[along], b[along]),\n turns: [\n [a[along], side(a, p[i - 2]!)],\n [b[along], side(b, p[i + 1]!)],\n ],\n });\n }\n });\n if (pieces.length === 0) continue;\n const list = orderPieces(pieces, order);\n // A piece goes one lane past each piece before it in the order that it overlaps. Thus two pieces that overlap keep their order.\n const lane: number[] = [];\n let n = 0;\n list.forEach((P, i) => {\n let k = 0;\n for (let j = 0; j < i; j++) if (overlaps(list[j]!, P)) k = Math.max(k, lane[j]! + 1);\n lane.push(k);\n n = Math.max(n, k + 1);\n });\n const step = Math.min(spacing, g.width / (n + 1));\n const mid = (lo + hi) / 2;\n list.forEach((P, i) => {\n const v = mid + (lane[i]! - (n - 1) / 2) * step;\n moved[P.link]![P.seg - 1]![across] = v;\n moved[P.link]![P.seg]![across] = v;\n });\n }\n const boxes = new Grid<Box>(Math.max(20, meanSide(items)));\n for (const i of items) boxes.add(i.box, i.box);\n return links.map((l, i) => (hits(boxes, moved[i]!) > hits(boxes, l.points) ? l : { ...l, points: moved[i]! }));\n}\n\nconst overlaps = (P: Piece, Q: Piece): boolean => Math.min(P.hi, Q.hi) - Math.max(P.lo, Q.lo) > EPS;\n\n/**\n * This function counts the crossings when the piece `P` is on the near side of the piece `Q`.\n * A turn of `P` to the far side crosses `Q` when it is inside the span of `Q`. A turn of `Q` to the near side crosses `P` in the same way.\n */\nfunction cost(P: Piece, Q: Piece): number {\n let c = 0;\n for (const [y, s] of P.turns) if (s > 0 && y > Q.lo + EPS && y < Q.hi - EPS) c++;\n for (const [y, s] of Q.turns) if (s < 0 && y > P.lo + EPS && y < P.hi - EPS) c++;\n return c;\n}\n\n/** This function gives the pieces of one gap in lane order, from the near side to the far side. */\nfunction orderPieces(pieces: readonly Piece[], order: LaneOrder): Piece[] {\n if (order === \"links\") return [...pieces];\n const sum = (P: Piece): number => P.turns.reduce((s, [, side]) => s + side, 0);\n const list = [...pieces].sort((P, Q) => sum(P) - sum(Q) || P.link - Q.link || P.seg - Q.seg);\n if (order === \"ends\") return list;\n // The local search moves one piece to the place that removes the most crossings, until no move removes one.\n const n = list.length;\n const index = new Map(list.map((P, i) => [P, i]));\n const c: number[][] = list.map((P) => list.map((Q) => (P !== Q && overlaps(P, Q) ? cost(P, Q) : 0)));\n const at = (P: Piece, Q: Piece): number => c[index.get(P)!]![index.get(Q)!]!;\n for (let round = 0; round < ROUNDS; round++) {\n let better = false;\n for (let i = 0; i < n; i++) {\n const x = list[i]!;\n // The change of the crossings when `x` moves to the place `k`, for each `k`.\n let best = 0;\n let to = i;\n let d = 0;\n for (let k = i - 1; k >= 0; k--) {\n d += at(x, list[k]!) - at(list[k]!, x);\n if (d < best) [best, to] = [d, k];\n }\n d = 0;\n for (let k = i + 1; k < n; k++) {\n d += at(list[k]!, x) - at(x, list[k]!);\n if (d < best) [best, to] = [d, k];\n }\n if (to !== i) {\n list.splice(i, 1);\n list.splice(to, 0, x);\n better = true;\n }\n }\n if (!better) break;\n }\n return list;\n}\n\n/** This function gives the mean of the longer side of the boxes. */\nfunction meanSide(items: readonly Boxed[]): number {\n let s = 0;\n for (const i of items) s += Math.max(i.box.w, i.box.h);\n return items.length ? s / items.length : 1;\n}\n\n/** This function counts the legs of a polyline that go through a box, for each box. */\nfunction hits(boxes: Grid<Box>, p: readonly Point[]): number {\n let n = 0;\n for (let i = 1; i < p.length; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n boxes.querySegment(a, b, 0, (box) => {\n if (segmentHitsBox(a, b, box)) n++;\n });\n }\n return n;\n}\n","import {\n bendCount,\n dist,\n frechet,\n inflectionCount,\n polylineLength,\n segmentBoxDistance,\n segmentsCross,\n type Box,\n type Point,\n} from \"../geom.ts\";\nimport { rng } from \"../fixtures.ts\";\nimport { Grid } from \"../grid.ts\";\nimport { nodeIndex, type Graph, type Node, type Result } from \"../model.ts\";\n\n/** The quality of a result. Lower is better for each value except `clearance`. */\nexport interface Quality {\n /** The length of all drawn lines. A segment that several routes share counts one time. */\n readonly ink: number;\n /** The number of points where two drawn segments cross. */\n readonly crossings: number;\n /** This value is true when `crossings` is an estimate from a sample of the segments. */\n readonly crossingsEstimated: boolean;\n /** The mean number of bends of a route. */\n readonly bends: number;\n /** The mean number of inflections of a route. */\n readonly inflections: number;\n /** The mean distance from a route to the nearest node that is not one of its ends, up to `CLEARANCE_CAP`. */\n readonly clearance: number;\n /** The share of the routes that come closer than 4 units to a node that is not one of their ends. */\n readonly tight: number;\n /** The mean ratio of the length of a route to the distance between its ends. */\n readonly detour: number;\n /** The mean angle, in degrees, between the first or last segment of a route and the normal of the side of its node. */\n readonly plugAngle: number;\n}\n\n/** The clearance stops at this distance. */\nexport const CLEARANCE_CAP = 40;\nconst TIGHT = 4;\nconst EXACT_CROSSINGS = 20_000;\nconst SAMPLE = 2_000;\n\nconst key = (p: Point): string => `${Math.round(p.x * 8)},${Math.round(p.y * 8)}`;\n\n/** This function measures the quality of a result. */\nexport function measureQuality(graph: Graph, result: Result): Quality {\n const byId = nodeIndex(graph);\n const nodes = new Grid<Node>(180);\n for (const n of graph.nodes) nodes.add(n, n.box);\n\n // The drawn segments: one for each distinct pair of ends.\n const segs: [Point, Point][] = [];\n const seen = new Set<string>();\n let bends = 0;\n let infl = 0;\n let clear = 0;\n let tight = 0;\n let detour = 0;\n let detourN = 0;\n let angle = 0;\n let angleN = 0;\n for (const r of result.routes) {\n const p = r.points;\n for (let i = 1; i < p.length; i++) {\n const ka = key(p[i - 1]!);\n const kb = key(p[i]!);\n if (ka === kb) continue;\n const k = ka < kb ? `${ka}|${kb}` : `${kb}|${ka}`;\n if (seen.has(k)) continue;\n seen.add(k);\n segs.push([p[i - 1]!, p[i]!]);\n }\n bends += bendCount(p);\n infl += inflectionCount(p);\n const ends = endNodes(graph, byId, r.edge);\n let c = CLEARANCE_CAP;\n for (let i = 1; i < p.length; i++) {\n const a = p[i - 1]!;\n const b = p[i]!;\n nodes.querySegment(a, b, c, (n) => {\n if (n !== ends.source && n !== ends.target) c = Math.min(c, segmentBoxDistance(a, b, n.box));\n });\n }\n clear += c;\n if (c < TIGHT) tight++;\n if (p.length >= 2) {\n const d = dist(p[0]!, p[p.length - 1]!);\n if (d > 1) {\n detour += polylineLength(p) / d;\n detourN++;\n }\n for (const [at, next, node] of [\n [p[0]!, p[1]!, ends.source],\n [p[p.length - 1]!, p[p.length - 2]!, ends.target],\n ] as const) {\n if (!node) continue;\n const a = sideAngle(node.box, at, next);\n if (a !== undefined) {\n angle += a;\n angleN++;\n }\n }\n }\n }\n const n = Math.max(1, result.routes.length);\n let ink = 0;\n for (const [a, b] of segs) ink += dist(a, b);\n const [crossings, crossingsEstimated] = countCrossings(segs);\n return {\n ink,\n crossings,\n crossingsEstimated,\n bends: bends / n,\n inflections: infl / n,\n clearance: clear / n,\n tight: tight / n,\n detour: detourN ? detour / detourN : 1,\n plugAngle: angleN ? angle / angleN : 0,\n };\n}\n\ninterface Ends {\n readonly source: Node | undefined;\n readonly target: Node | undefined;\n}\n\nfunction endNodes(graph: Graph, byId: Map<string, Node>, edgeId: string): Ends {\n const e = edgeIndex(graph).get(edgeId);\n return { source: e && byId.get(e.source.node), target: e && byId.get(e.target.node) };\n}\n\nconst edgeIndexes = new WeakMap<Graph, Map<string, Graph[\"edges\"][number]>>();\nfunction edgeIndex(graph: Graph): Map<string, Graph[\"edges\"][number]> {\n let m = edgeIndexes.get(graph);\n if (!m) {\n m = new Map();\n for (const e of graph.edges) m.set(e.id, e);\n edgeIndexes.set(graph, m);\n }\n return m;\n}\n\n/**\n * This function gives an angle in degrees: the angle between the segment from `at` to `next` and the outward normal.\n * The normal is the normal of the side of the box nearest to `at`. A route that starts inside the box (an interior route) gives no angle.\n */\nexport function sideAngle(box: Box, at: Point, next: Point): number | undefined {\n const d = [\n [Math.abs(at.y - box.y), 0, -1],\n [Math.abs(at.x - (box.x + box.w)), 1, 0],\n [Math.abs(at.y - (box.y + box.h)), 0, 1],\n [Math.abs(at.x - box.x), -1, 0],\n ].sort((a, b) => a[0]! - b[0]!)[0]!;\n if (d[0]! > 1) return undefined;\n const vx = next.x - at.x;\n const vy = next.y - at.y;\n const l = Math.hypot(vx, vy);\n if (l === 0) return undefined;\n const cos = Math.max(-1, Math.min(1, (vx * d[1]! + vy * d[2]!) / l));\n return (Math.acos(cos) * 180) / Math.PI;\n}\n\n/**\n * This function counts the crossings of a set of segments with a grid of buckets.\n * Above 20 000 segments, it counts the crossings of a seeded sample of 2 000 segments and scales the count.\n */\nexport function countCrossings(segs: readonly (readonly [Point, Point])[]): [number, boolean] {\n if (segs.length < 2) return [0, false];\n const len = segs.reduce((s, [a, b]) => s + dist(a, b), 0) / segs.length;\n const grid = new Grid<number>(Math.max(20, len));\n segs.forEach(([a, b], i) => grid.addSegment(i, a, b));\n const exact = segs.length <= EXACT_CROSSINGS;\n const R = rng(segs.length);\n const pick = exact ? segs.map((_, i) => i) : Array.from({ length: SAMPLE }, () => Math.floor(R() * segs.length));\n let count = 0;\n for (const i of pick) {\n const [a, b] = segs[i]!;\n grid.querySegment(a, b, 0, (j) => {\n if (exact && j <= i) return;\n if (j === i) return;\n const [c, d] = segs[j]!;\n if (segmentsCross(a, b, c, d)) count++;\n });\n }\n return exact ? [count, false] : [Math.round((count * segs.length) / (2 * pick.length)), true];\n}\n\n/** The change between two results of the same graph: the Fréchet distance between the two routes of each edge. */\nexport interface Stability {\n readonly mean: number;\n readonly max: number;\n /** The share of the routes that moved more than 1 unit. */\n readonly moved: number;\n}\n\n/** This function measures how much the routes changed between two results. */\nexport function measureStability(before: Result, after: Result): Stability {\n const prev = new Map(before.routes.map((r) => [r.edge, r.points] as const));\n let sum = 0;\n let max = 0;\n let moved = 0;\n let n = 0;\n for (const r of after.routes) {\n const p = prev.get(r.edge);\n if (!p) continue;\n const f = frechet(p, r.points);\n sum += f;\n max = Math.max(max, f);\n if (f > 1) moved++;\n n++;\n }\n return { mean: n ? sum / n : 0, max, moved: n ? moved / n : 0 };\n}\n","import { makeFixture, type FixtureSpec } from \"../fixtures.ts\";\nimport type { Graph, Result, Router } from \"../model.ts\";\nimport { measureLevelFaults, measureRouteFaults, sumFaults, type LevelFaults, type LinkFaults } from \"./links.ts\";\nimport { checkProperties, type Violation } from \"./properties.ts\";\nimport { measureQuality, type Quality } from \"./quality.ts\";\n\n// The core runs in any host, so it reads the clock without the types of Node or the browser.\nconst now = (): number => (globalThis as { performance?: { now(): number } }).performance?.now() ?? Date.now();\n\n/** One row of the benchmark: one router on one fixture. */\nexport interface BenchRow {\n readonly router: string;\n readonly fixture: string;\n readonly nodes: number;\n readonly edges: number;\n /** The median time of one run, in milliseconds. */\n readonly ms: number;\n /** This value is false when two runs on the same input gave different results. */\n readonly deterministic: boolean;\n readonly violations: number;\n /** The first violations, for the report. */\n readonly sample: readonly Violation[];\n readonly quality: Quality;\n /** The faults of the routes of the edges (`measureRouteFaults`). */\n readonly faults: LinkFaults;\n /** The faults of each zoom level with groups (`measureLevelFaults`). The list is empty for a router without levels. */\n readonly levelFaults: readonly LevelFaults[];\n}\n\n/** The options of a benchmark run. */\nexport interface BenchOptions {\n /** The number of timed routes of each fixture by each router. The default is 3. */\n readonly repeat?: number;\n}\n\n/** This function routes each fixture with each router, checks the hard rules and measures the quality. */\nexport function runBenchmark(routers: readonly Router[], fixtures: readonly FixtureSpec[], options: BenchOptions = {}): BenchRow[] {\n const rows: BenchRow[] = [];\n for (const spec of fixtures) {\n const graph = makeFixture(spec);\n for (const router of routers) if (graph.nodes.length <= (router.maxNodes ?? Infinity)) rows.push(benchOne(router, spec.name, graph, options.repeat ?? 3));\n }\n return rows;\n}\n\n/**\n * This function tells if two values hold the same data, as JSON sees it. It does not make a string,\n * because the result of a large graph can be longer than the longest string.\n */\nexport function sameData(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a === \"number\" && typeof b === \"number\") return Number.isNaN(a) && Number.isNaN(b);\n if (typeof a !== \"object\" || typeof b !== \"object\" || a === null || b === null) return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n if (Array.isArray(a)) {\n const y = b as unknown[];\n if (a.length !== y.length) return false;\n for (let i = 0; i < a.length; i++) if (!sameData(a[i], y[i])) return false;\n return true;\n }\n const x = a as Record<string, unknown>;\n const y = b as Record<string, unknown>;\n const kx = Object.keys(x).filter((k) => x[k] !== undefined);\n const ky = Object.keys(y).filter((k) => y[k] !== undefined);\n if (kx.length !== ky.length) return false;\n for (const k of kx) if (!sameData(x[k], y[k])) return false;\n return true;\n}\n\n/** This function routes one graph with one router and measures the result. */\nexport function benchOne(router: Router, fixture: string, graph: Graph, repeat = 3): BenchRow {\n const times: number[] = [];\n let first: Result | undefined;\n let deterministic = true;\n for (let i = 0; i < Math.max(2, repeat); i++) {\n const t0 = now();\n const r = router.route(graph);\n times.push(now() - t0);\n if (!first) first = r;\n else if (i === 1 && !sameData(r, first)) deterministic = false;\n }\n times.sort((a, b) => a - b);\n const result = first!;\n const all = checkProperties(graph, result, 1_000_000);\n return {\n router: router.name,\n fixture,\n nodes: graph.nodes.length,\n edges: graph.edges.length,\n ms: times[Math.floor(times.length / 2)]!,\n deterministic,\n violations: all.length,\n sample: all.slice(0, 5),\n quality: measureQuality(graph, result),\n faults: measureRouteFaults(graph, result),\n levelFaults: measureLevelFaults(result),\n };\n}\n\n/** This function writes the rows as a Markdown table. */\nexport function formatTable(rows: readonly BenchRow[]): string {\n const head = \"| router | fixture | nodes | edges | ms | same twice | violations | ink | crossings | bends | inflections | clearance | tight | detour | plug angle |\";\n const line = \"|---|---|---:|---:|---:|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|\";\n const f = (v: number, d = 2): string => (Number.isInteger(v) ? String(v) : v.toFixed(d));\n const body = rows.map((r) => {\n const q = r.quality;\n return `| ${r.router} | ${r.fixture} | ${r.nodes} | ${r.edges} | ${f(r.ms, 1)} | ${r.deterministic ? \"yes\" : \"NO\"} | ${r.violations} | ${Math.round(q.ink)} | ${q.crossingsEstimated ? \"≈\" : \"\"}${q.crossings} | ${f(q.bends)} | ${f(q.inflections)} | ${f(q.clearance, 1)} | ${f(q.tight)} | ${f(q.detour)} | ${f(q.plugAngle, 1)} |`;\n });\n return [head, line, ...body].join(\"\\n\");\n}\n\n/**\n * This function writes the faults of the rows as a Markdown table: the routes first, then the sum of the levels with groups.\n * A router without such levels gets a dash in the columns of the levels.\n */\nexport function formatFaults(rows: readonly BenchRow[]): string {\n const head =\n \"| router | fixture | through | out and back | worst detour | outside | level links | level overlaps | level through | level out and back | level worst detour | level outside |\";\n const line = \"|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|\";\n const body = rows.map((r) => {\n const f = r.faults;\n const cells = [r.router, r.fixture, f.through, f.backtrack, f.worstDetour.toFixed(2), f.outside];\n if (r.levelFaults.length === 0) cells.push(\"-\", \"-\", \"-\", \"-\", \"-\", \"-\");\n else {\n const l = sumFaults(r.levelFaults);\n cells.push(l.links, r.levelFaults.reduce((s, x) => s + x.overlaps, 0), l.through, l.backtrack, l.worstDetour.toFixed(2), l.outside);\n }\n return `| ${cells.join(\" | \")} |`;\n });\n return [head, line, ...body].join(\"\\n\");\n}\n","import type { CurveSegment } from \"../curves/model.ts\";\nimport type { CurveSpace } from \"../curves/space.ts\";\nimport type { Point } from \"../geom.ts\";\nimport type { Graph, Result, Router } from \"../model.ts\";\nimport type { Boxed, Gap, RoomLink } from \"../room/index.ts\";\nimport type { Section } from \"../sections.ts\";\n\n/** The input of a curve strategy: one polyline and the context of its route. */\nexport interface CurveInput {\n /** These points are the polyline: a route of a router, a lane of `laneRoutes` or a link of a zoom level. */\n readonly points: readonly Point[];\n /** The curve leaves the first point along this outward normal of its plug, if the strategy reads it. */\n readonly startNormal?: Point;\n /** The curve comes into the last point against this outward normal of its plug, if the strategy reads it. */\n readonly endNormal?: Point;\n /** The boxes that the curve must not go through, from `curveSpace`. */\n readonly space?: CurveSpace;\n}\n\n/** The input of a room strategy: the boxes of a board and the links between them. */\nexport interface RoomInput {\n readonly items: readonly Boxed[];\n readonly links: readonly RoomLink[];\n}\n\n/**\n * The steps that have strategies, with the fixed input and output type of each step.\n *\n * - `group`: a graph in, the tree of sections out. The router `sections` makes its hubs and its zoom levels from this tree.\n * - `router`: a graph in, the routes (and the `levels`, `bundles` and `runs`) out.\n * - `curve`: a polyline in, the segments of a curve out.\n * - `room`: the boxes and links of a board in, the gaps of the board with their need out.\n */\nexport interface StepTypes {\n readonly group: { readonly input: Graph; readonly output: Section };\n readonly router: { readonly input: Graph; readonly output: Result };\n readonly curve: { readonly input: CurveInput; readonly output: CurveSegment[] };\n readonly room: { readonly input: RoomInput; readonly output: Gap[] };\n}\n\n/** The name of a step that has strategies. */\nexport type Step = keyof StepTypes;\n\n/** The input type of a step. */\nexport type StepInput<S extends Step> = StepTypes[S][\"input\"];\n\n/** The output type of a step. */\nexport type StepOutput<S extends Step> = StepTypes[S][\"output\"];\n\n/** The steps that have strategies, in the order of the pipeline. */\nexport const STEPS: readonly Step[] = [\"group\", \"router\", \"curve\", \"room\"];\n\n/**\n * A strategy: one way to do one step, with a name and a description.\n * The same input and the same options must give the same output.\n */\nexport interface Strategy<S extends Step = Step, O extends object = object> {\n /** The step of the strategy. It fixes the input and the output type. */\n readonly step: S;\n /** The name of the strategy. Each name is unique in its step of a registry. */\n readonly name: string;\n /** One or two sentences that tell what the strategy does. The site and the documents show them. */\n readonly describe: string;\n /** The values of the options when the caller gives no value. */\n readonly defaults: Readonly<O>;\n /** The benchmark skips an input with more nodes than this. Without it, the strategy takes each input. */\n readonly maxNodes?: number;\n /** This method does the step. Each option that `options` does not give gets its value from `defaults`. */\n run(input: StepInput<S>, options?: Partial<O>): StepOutput<S>;\n}\n\n/** A strategy of any step. A registry holds a list of these. */\nexport type AnyStrategy = { [S in Step]: Strategy<S> }[Step];\n\n/** The definition of a strategy, for `defineStrategy`. */\nexport interface StrategyDefinition<S extends Step, O extends object> {\n readonly step: S;\n readonly name: string;\n readonly describe: string;\n /** These values are the options when the caller gives no value. Give `{}` for a strategy without options. */\n readonly defaults: O;\n readonly maxNodes?: number;\n /** This function does the step. It gets each option, from the caller or from `defaults`. */\n run(input: StepInput<S>, options: Readonly<O>): StepOutput<S>;\n}\n\n/**\n * This function makes a strategy from its definition. The strategy fills the missing options from `defaults`.\n * When the caller gives no option, the definition gets the `defaults` object itself.\n */\nexport function defineStrategy<S extends Step, O extends object>(definition: StrategyDefinition<S, O>): Strategy<S, O> {\n const { step, name, describe, defaults, maxNodes } = definition;\n if (name.length === 0) throw new Error(`A strategy of the step \"${step}\" has no name.`);\n const strategy: Strategy<S, O> = {\n step,\n name,\n describe,\n defaults: Object.freeze({ ...defaults }),\n ...(maxNodes === undefined ? {} : { maxNodes }),\n run(input: StepInput<S>, options?: Partial<O>): StepOutput<S> {\n const all = options === undefined || Object.keys(options).length === 0 ? strategy.defaults : { ...strategy.defaults, ...options };\n return definition.run(input, all as Readonly<O>);\n },\n };\n return Object.freeze(strategy);\n}\n\n/**\n * A registry: the strategies of each step, in order. A registry is data. No import changes it.\n * A consumer makes its own registry with `createRegistry`, and adds a strategy with `register`.\n * The list `group` is optional in the type, so a registry from version 0.1.5 stays a registry. `createRegistry` always gives it.\n */\nexport type Registry = { readonly [S in Exclude<Step, \"group\">]: readonly Strategy<S>[] } & { readonly group?: readonly Strategy<\"group\">[] };\n\n/** This function makes a registry from a list of strategies. It keeps their order. Two strategies with one step and one name are an error. */\nexport function createRegistry(strategies: readonly AnyStrategy[]): Registry {\n const out: { [S in Step]: Strategy<S>[] } = { group: [], router: [], curve: [], room: [] };\n for (const s of strategies) {\n const list = out[s.step] as AnyStrategy[] | undefined;\n if (!list) throw new Error(`There is no step \"${String(s.step)}\". The steps are ${STEPS.join(\", \")}.`);\n if (list.some((t) => t.name === s.name)) throw new Error(`The step \"${s.step}\" has two strategies with the name \"${s.name}\".`);\n list.push(s);\n }\n return Object.freeze({ group: Object.freeze(out.group), router: Object.freeze(out.router), curve: Object.freeze(out.curve), room: Object.freeze(out.room) });\n}\n\n/** This function gives a new registry with the strategies of `registry` and then `strategies`. It does not change `registry`. */\nexport function register(registry: Registry, ...strategies: readonly AnyStrategy[]): Registry {\n return createRegistry([...(registry.group ?? []), ...registry.router, ...registry.curve, ...registry.room, ...strategies]);\n}\n\n/** This function gives the strategies of one step of a registry, in order. */\nexport function listStrategies<S extends Step>(registry: Registry, step: S): readonly Strategy<S>[] {\n return (registry[step] ?? []) as readonly Strategy<S>[];\n}\n\n/** This function gives the strategy of one step with a name, or `undefined` when the registry has no such strategy. */\nexport function findStrategy<S extends Step>(registry: Registry, step: S, name: string): Strategy<S> | undefined {\n return listStrategies(registry, step).find((s) => s.name === name);\n}\n\n/** This function gives the strategy of one step with a name. When the registry has no such strategy, the function throws an error. */\nexport function getStrategy<S extends Step>(registry: Registry, step: S, name: string): Strategy<S> {\n const s = findStrategy(registry, step, name);\n if (!s) throw new Error(`There is no ${step} \"${name}\". The registry has ${listStrategies(registry, step).map((t) => t.name).join(\", \")}.`);\n return s;\n}\n\n/** This function gives a `Router` that runs a router strategy with the options. The router keeps the name and the `maxNodes` of the strategy. */\nexport function asRouter<O extends object>(strategy: Strategy<\"router\", O>, options?: Partial<O>): Router {\n return {\n name: strategy.name,\n ...(strategy.maxNodes === undefined ? {} : { maxNodes: strategy.maxNodes }),\n route: (graph: Graph): Result => strategy.run(graph, options),\n };\n}\n\n/** This function gives the router strategies of a registry as `Router` objects, in order. The benchmark races them. */\nexport function routersOf(registry: Registry): Router[] {\n return listStrategies(registry, \"router\").map((s) => asRouter(s));\n}\n","import { arcCurve, type ArcOptions } from \"../curves/arc/index.ts\";\nimport { roundedCurve, type RoundedOptions } from \"../curves/rounded/index.ts\";\nimport { splineCurve, type SplineOptions } from \"../curves/spline/index.ts\";\nimport { straightCurve } from \"../curves/straight/index.ts\";\nimport { byDataGroup, keyGroups, type KeyOptions } from \"../groups/keys/index.ts\";\nimport { quadtreeGroups } from \"../groups/quadtree/index.ts\";\nimport type { Graph, Result, Router } from \"../model.ts\";\nimport { roomDemand, type RoomMethod, type RoomOptions } from \"../room/index.ts\";\nimport { cornersRouter, type CornersOptions } from \"../routers/corners.ts\";\nimport { plugsRouter } from \"../routers/plugs.ts\";\nimport { sectionsRouter, type SectionsOptions } from \"../routers/sections.ts\";\nimport { sharedRouter, type SharedOptions } from \"../routers/shared.ts\";\nimport { straightRouter } from \"../routers/straight.ts\";\nimport { byCollection, trunksRouter, type TrunksOptions } from \"../routers/trunks.ts\";\nimport { SECTION_DEFAULTS, type SectionOptions } from \"../sections.ts\";\nimport { createRegistry, defineStrategy, type AnyStrategy, type CurveInput, type Registry, type Strategy } from \"./model.ts\";\n\n/** The options of a router strategy: the options of its router, without the name and the limit of the benchmark. */\nexport type RouterPreset<O> = Omit<O, \"name\" | \"maxNodes\">;\n\n/** This function makes a router strategy from a router factory and a preset of its options. Each call makes the router of its options. */\nfunction routerStrategy<O extends object>(\n name: string,\n describe: string,\n maxNodes: number,\n defaults: O,\n make: (options: O & { readonly name: string }) => Router,\n): Strategy<\"router\", O> {\n return defineStrategy({ step: \"router\", name, describe, defaults, maxNodes, run: (graph: Graph, options: Readonly<O>): Result => make({ ...options, name }).route(graph) });\n}\n\n/** This function makes a router strategy for a router without options. */\nfunction fixedRouter(router: Router, describe: string): Strategy<\"router\", object> {\n return defineStrategy({ step: \"router\", name: router.name, describe, defaults: {}, run: (graph: Graph): Result => router.route(graph) });\n}\n\n/** The built-in router strategies, in the order of the benchmark. They route as the routers of `ROUTERS`. */\nexport const routerStrategies: {\n readonly straight: Strategy<\"router\", object>;\n readonly plugs: Strategy<\"router\", object>;\n readonly corners: Strategy<\"router\", RouterPreset<CornersOptions>>;\n readonly \"corners-smooth\": Strategy<\"router\", RouterPreset<CornersOptions>>;\n readonly trunks: Strategy<\"router\", RouterPreset<TrunksOptions>>;\n readonly shared: Strategy<\"router\", RouterPreset<SharedOptions>>;\n readonly \"shared-all\": Strategy<\"router\", RouterPreset<SharedOptions>>;\n readonly sections: Strategy<\"router\", RouterPreset<SectionsOptions>>;\n readonly \"sections-tree\": Strategy<\"router\", RouterPreset<SectionsOptions>>;\n} = Object.freeze({\n straight: fixedRouter(straightRouter, \"The control. Each edge is one straight line between its plugs.\"),\n plugs: fixedRouter(\n plugsRouter,\n \"Each edge leaves its plug along the normal of the side and follows the curve of the inflection rule. It does not go around the nodes.\",\n ),\n corners: routerStrategy<RouterPreset<CornersOptions>>(\n \"corners\",\n \"Each edge goes around the nodes on a shortest path (A*) through a sparse visibility graph of the box corners.\",\n 10_000,\n {},\n cornersRouter,\n ),\n \"corners-smooth\": routerStrategy<RouterPreset<CornersOptions>>(\n \"corners-smooth\",\n \"The same paths as `corners`. A route in clear view follows the inflection rule, and the other routes get round corners.\",\n 10_000,\n { smooth: true },\n cornersRouter,\n ),\n trunks: routerStrategy<RouterPreset<TrunksOptions>>(\n \"trunks\",\n \"A rule puts edges in groups. The edges of a group leave one plug of one node on one trunk. At a split point, each edge goes on to its target.\",\n 10_000,\n { rule: byCollection },\n trunksRouter,\n ),\n shared: routerStrategy<RouterPreset<SharedOptions>>(\n \"shared\",\n \"The edges of one collection share their ways through the corner graph. A link that the group uses already costs half.\",\n 10_000,\n { rule: byCollection },\n sharedRouter,\n ),\n \"shared-all\": routerStrategy<RouterPreset<SharedOptions>>(\"shared-all\", \"The same as `shared`, but all edges share their ways.\", 10_000, {}, sharedRouter),\n sections: routerStrategy<RouterPreset<SectionsOptions>>(\n \"sections\",\n \"A tree of sections, with a hub in each section. A long edge goes through the hubs, and a short edge goes directly.\",\n 100_000,\n {},\n sectionsRouter,\n ),\n \"sections-tree\": routerStrategy<RouterPreset<SectionsOptions>>(\n \"sections-tree\",\n \"The same as `sections`, but without the limit of the stretch.\",\n 100_000,\n { stretch: Infinity },\n sectionsRouter,\n ),\n});\n\n/** The context of a curve input, without the keys that have no value. */\nconst contextOf = (input: CurveInput): Omit<CurveInput, \"points\"> => ({\n ...(input.startNormal ? { startNormal: input.startNormal } : {}),\n ...(input.endNormal ? { endNormal: input.endNormal } : {}),\n ...(input.space ? { space: input.space } : {}),\n});\n\n/** The options of the curve strategies `rounded` and `arc`. */\nexport interface RadiusOptions {\n /** The radius of the corners. The default is 12. */\n readonly radius: number;\n}\n\n/** The options of the curve strategy `spline`. */\nexport interface TensionOptions {\n /** The tension of the spline, from 0 (the spline) to 1 (the polyline). The default is 0. */\n readonly tension: number;\n}\n\n/** The built-in curve strategies, in the order of `CURVE_TYPES`. Each one gives the same segments as `curveOf` with its type. */\nexport const curveStrategies: {\n readonly straight: Strategy<\"curve\", object>;\n readonly rounded: Strategy<\"curve\", RadiusOptions>;\n readonly spline: Strategy<\"curve\", TensionOptions>;\n readonly arc: Strategy<\"curve\", RadiusOptions>;\n} = Object.freeze({\n straight: defineStrategy({ step: \"curve\", name: \"straight\", describe: \"The polyline as it is.\", defaults: {}, run: (input: CurveInput) => straightCurve(input.points) }),\n rounded: defineStrategy({\n step: \"curve\",\n name: \"rounded\",\n describe: \"A quadratic Bezier curve at each corner, as `roundCorners` draws it. The first and the last legs stay.\",\n defaults: { radius: 12 },\n run: (input: CurveInput, o: Readonly<RadiusOptions>) => roundedCurve(input.points, { ...contextOf(input), radius: o.radius } satisfies RoundedOptions),\n }),\n spline: defineStrategy({\n step: \"curve\",\n name: \"spline\",\n describe: \"A centripetal Catmull-Rom spline through each point. It does not overshoot or make loops in a piece.\",\n defaults: { tension: 0 },\n run: (input: CurveInput, o: Readonly<TensionOptions>) => splineCurve(input.points, { ...contextOf(input), tension: o.tension } satisfies SplineOptions),\n }),\n arc: defineStrategy({\n step: \"curve\",\n name: \"arc\",\n describe: \"A circular arc at each corner, tangent to the two legs. The first and the last legs stay.\",\n defaults: { radius: 12 },\n run: (input: CurveInput, o: Readonly<RadiusOptions>) => arcCurve(input.points, { ...contextOf(input), radius: o.radius } satisfies ArcOptions),\n }),\n});\n\n/** The options of a room strategy: the options of `roomDemand`, without the method. */\nexport type RoomPreset = Omit<RoomOptions, \"method\">;\n\nconst roomStrategy = (method: RoomMethod, describe: string): Strategy<\"room\", RoomPreset> =>\n defineStrategy<\"room\", RoomPreset>({ step: \"room\", name: method, describe, defaults: {}, run: (input, o) => roomDemand(input.items, input.links, { ...o, method }) });\n\n/** The built-in room strategies: the methods of `roomDemand`. */\nexport const roomStrategies: {\n readonly routes: Strategy<\"room\", RoomPreset>;\n readonly lines: Strategy<\"room\", RoomPreset>;\n} = Object.freeze({\n routes: roomStrategy(\"routes\", \"The lanes of a gap are the most routes that run along it side by side, with each gap open to the gutter.\"),\n lines: roomStrategy(\"lines\", \"The lanes of a gap are the straight lines between the centers of the boxes that cross the gap.\"),\n});\n\n/** The built-in grouping rules: the strategies of the step `group`. The router `sections` makes its hubs and its zoom levels from their tree. */\nexport const groupStrategies: {\n readonly quadtree: Strategy<\"group\", Required<SectionOptions>>;\n readonly keys: Strategy<\"group\", KeyOptions>;\n} = Object.freeze({\n quadtree: defineStrategy({\n step: \"group\",\n name: \"quadtree\",\n describe: \"The cells of a quadtree of the plane. A cell with more than `cap` nodes splits in four. It is the default rule of the router `sections`.\",\n defaults: { ...SECTION_DEFAULTS },\n run: (graph: Graph, o: Readonly<Required<SectionOptions>>) => quadtreeGroups(graph, o),\n }),\n keys: defineStrategy({\n step: \"group\",\n name: \"keys\",\n describe: \"One group for each key of the nodes. The default key is the string `data.group` of the node. A node without a key is a group alone.\",\n defaults: { key: byDataGroup } as KeyOptions,\n run: (graph: Graph, o: Readonly<KeyOptions>) => keyGroups(graph, o),\n }),\n});\n\n/** The built-in strategies of each step, in order. A consumer adds its own: `createRegistry([...BUILT_IN_STRATEGIES, mine])`. */\nexport const BUILT_IN_STRATEGIES: readonly AnyStrategy[] = Object.freeze([\n ...Object.values(groupStrategies),\n ...Object.values(routerStrategies),\n ...Object.values(curveStrategies),\n ...Object.values(roomStrategies),\n]);\n\n/** The registry of the built-in strategies. The benchmark and the site take their lists from it. */\nexport const STRATEGIES: Registry = createRegistry(BUILT_IN_STRATEGIES);\n","import { CURVE_TYPES, curveSpace, sampleCurve, type CurveType } from \"../curves/index.ts\";\nimport { polylineLength } from \"../geom.ts\";\nimport { nodeIndex, type Graph, type Router } from \"../model.ts\";\nimport { nearestSide, SIDE_NORMAL } from \"../plugs.ts\";\nimport { curveStrategies } from \"../strategies/builtins.ts\";\nimport type { Strategy } from \"../strategies/model.ts\";\nimport { measureLinks, type MeasuredLink } from \"./links.ts\";\n\n// The core runs in any host, so it reads the clock without the types of Node or the browser.\nconst now = (): number => (globalThis as { performance?: { now(): number } }).performance?.now() ?? Date.now();\n\n/**\n * One row of the benchmark of the curves: one curve type on the routes of one router on one fixture.\n * The type `T` of the name of the curve is `CurveType` for `benchCurves`, and `string` for `benchCurveStrategies`.\n */\nexport interface CurveBenchRow<T extends string = CurveType> {\n readonly router: string;\n readonly fixture: string;\n readonly type: T;\n /** The number of routes. */\n readonly links: number;\n /** The number of polylines that go through a box that is not one of their ends (`measureLinks`). */\n readonly through: number;\n /** The number of curves without a free space that go through such a box. */\n readonly free: number;\n /** The number of curves with the free space of the nodes (`curveSpace`) that go through such a box. */\n readonly clamped: number;\n /** The ratio of the length of all curves with the free space to the length of all polylines. */\n readonly length: number;\n /** The time to make all curves with the free space, in milliseconds. */\n readonly ms: number;\n}\n\n/** The options of `benchCurves`. */\nexport interface CurveBenchOptions {\n /** The radius of the types `rounded` and `arc`. The default is 12. */\n readonly radius?: number;\n /** The tolerance of the samples of the curves. The default is 0.25. */\n readonly tolerance?: number;\n}\n\n/**\n * This function routes a graph with a router and makes each curve type of each route.\n * It counts the curves that go through a box, with and without the free space, and it compares their length to the polylines.\n * The type `spline` leaves each plug along the normal of the nearest side of its node.\n */\nexport function benchCurves(router: Router, fixture: string, graph: Graph, options: CurveBenchOptions = {}): CurveBenchRow[] {\n // Each built-in curve strategy has the name of its curve type, so each row has a `CurveType`.\n return benchCurveStrategies(\n router,\n fixture,\n graph,\n CURVE_TYPES.map((t) => curveStrategies[t]),\n options,\n ) as CurveBenchRow[];\n}\n\n/**\n * This function does the work of `benchCurves` with a list of curve strategies, in place of the curve types.\n * The option `radius` goes to each strategy. A strategy without such an option does not read it.\n */\nexport function benchCurveStrategies(\n router: Router,\n fixture: string,\n graph: Graph,\n curves: readonly Strategy<\"curve\">[],\n options: CurveBenchOptions = {},\n): CurveBenchRow<string>[] {\n const tolerance = options.tolerance ?? 0.25;\n const result = router.route(graph);\n const byId = nodeIndex(graph);\n const boxes = new Map(graph.nodes.map((n) => [n.id, n.box]));\n const edges = new Map(graph.edges.map((e) => [e.id, e]));\n const space = curveSpace(\n graph.nodes.map((n) => n.box),\n tolerance,\n );\n const routes = result.routes.flatMap((r) => {\n const e = edges.get(r.edge);\n const s = e && byId.get(e.source.node);\n const t = e && byId.get(e.target.node);\n if (!e || !s || !t || r.points.length < 2) return [];\n const first = r.points[0]!;\n const last = r.points[r.points.length - 1]!;\n return [{ source: s.id, target: t.id, points: r.points, startNormal: SIDE_NORMAL[nearestSide(s.box, first)], endNormal: SIDE_NORMAL[nearestSide(t.box, last)] }];\n });\n const base = measureLinks(boxes, routes);\n const ink = routes.reduce((sum, r) => sum + polylineLength(r.points), 0);\n const radius = { radius: options.radius ?? 12 };\n return curves.map((curve): CurveBenchRow<string> => {\n const make = (withSpace: boolean): MeasuredLink[] =>\n routes.map((r) => ({\n source: r.source,\n target: r.target,\n points: sampleCurve(\n curve.run({ points: r.points, startNormal: r.startNormal, endNormal: r.endNormal, ...(withSpace ? { space } : {}) }, radius),\n tolerance,\n ),\n }));\n const free = measureLinks(boxes, make(false));\n const t0 = now();\n const clamped = make(true);\n const ms = now() - t0;\n const length = clamped.reduce((sum, l) => sum + polylineLength(l.points), 0);\n return {\n router: router.name,\n fixture,\n type: curve.name,\n links: routes.length,\n through: base.through,\n free: free.through,\n clamped: measureLinks(boxes, clamped).through,\n length: ink > 0 ? length / ink : 1,\n ms,\n };\n });\n}\n\n/** This function writes the rows of `benchCurves` as a Markdown table. */\nexport function formatCurves(rows: readonly CurveBenchRow<string>[]): string {\n const head = \"| router | fixture | curve | routes | through, polyline | through, free | through, clamped | length | ms |\";\n const line = \"|---|---|---|---:|---:|---:|---:|---:|---:|\";\n const body = rows.map((r) => `| ${r.router} | ${r.fixture} | ${r.type} | ${r.links} | ${r.through} | ${r.free} | ${r.clamped} | ${r.length.toFixed(3)} | ${r.ms.toFixed(1)} |`);\n return [head, line, ...body].join(\"\\n\");\n}\n","import { levelLinks } from \"../levels.ts\";\nimport type { Graph, Node, Result } from \"../model.ts\";\nimport { makeRoom, openGaps, roomLinks, type RoomOptions } from \"../room/index.ts\";\nimport { gapLanes, LANE_ORDERS, type LaneOrder } from \"../room/lanes.ts\";\nimport { sectionsRouter } from \"../routers/sections.ts\";\nimport { laneRoutes, runKey, segmentsOf } from \"../segments.ts\";\nimport { roomStrategies } from \"../strategies/builtins.ts\";\nimport type { Strategy } from \"../strategies/model.ts\";\nimport { measureLinks, measureRouteFaults, type LinkFaults } from \"./links.ts\";\nimport { measureQuality } from \"./quality.ts\";\n\n// The core runs in any host, so it reads the clock without the types of Node or the browser.\nconst now = (): number => (globalThis as { performance?: { now(): number } }).performance?.now() ?? Date.now();\n\n/** One row of the benchmark of the room: one state of a board, packed or open, and the measures of its links. */\nexport interface RoomBenchRow {\n readonly fixture: string;\n /** The state of the board: `packed`, `gutter` (each gap open to the gutter only), or a method of `roomDemand`. */\n readonly board: string;\n /** The area of the bounding box of the boxes, as a share of the area of the packed board. */\n readonly area: number;\n /** The faults of the links of the far view (`levelLinks` with each box as one item). */\n readonly faults: LinkFaults;\n /** The crossings of the links of the far view (`measureQuality`). */\n readonly crossings: number;\n /** The ink of the links of the far view. */\n readonly ink: number;\n /** The mean detour of the links of the far view. */\n readonly detour: number;\n /**\n * The number of lane routes of the router `sections` that go through a box. Each shared segment opens to one lane for each edge,\n * at the spacing of the options (`laneRoutes`).\n */\n readonly laneThrough: number;\n /** The time of `makeRoom`, in milliseconds. It is 0 for the packed board. */\n readonly ms: number;\n}\n\n/** This function gives the area of the bounding box of the nodes. */\nfunction areaOf(nodes: readonly Node[]): number {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const n of nodes) {\n x0 = Math.min(x0, n.box.x);\n y0 = Math.min(y0, n.box.y);\n x1 = Math.max(x1, n.box.x + n.box.w);\n y1 = Math.max(y1, n.box.y + n.box.h);\n }\n return nodes.length ? (x1 - x0) * (y1 - y0) : 0;\n}\n\n/**\n * This function measures the links of one board. It measures the links of the far view, with each node of the graph as one item of a level.\n * With a lane order, each link of the far view gets its own lane in each gap (`gapLanes` at the lane width `spacing`).\n * Without it, the links of a gap share the lines of the level links.\n * The function also measures the lane routes of the router `sections` at the lane width `spacing`.\n */\nexport function measureBoard(graph: Graph, spacing: number, order?: LaneOrder): Omit<RoomBenchRow, \"fixture\" | \"board\" | \"area\" | \"ms\"> {\n const links = roomLinks(graph);\n const items = graph.nodes.map((n) => ({ id: n.id, box: n.box, nodes: [n.id] }));\n const level = levelLinks(\n items,\n links.map((l) => ({ source: l.source, target: l.target, count: l.count ?? 1 })),\n );\n const drawn = order ? gapLanes(graph.nodes, level, { spacing, order }) : level;\n const boxes = new Map(graph.nodes.map((n) => [n.id, n.box]));\n // `measureQuality` reads routes of edges, so each link of the far view stands for the first edge of its pair.\n const edgeOf = new Map<string, string>();\n for (const e of graph.edges) {\n const key = `${e.source.node}\\u0000${e.target.node}`;\n if (!edgeOf.has(key)) edgeOf.set(key, e.id);\n }\n const asRoutes: Result = { routes: drawn.map((l) => ({ edge: edgeOf.get(`${l.source}\\u0000${l.target}`)!, points: l.points })) };\n const q = measureQuality(graph, asRoutes);\n const routed = sectionsRouter({ name: \"sections\" }).route(graph);\n const segments = segmentsOf(routed);\n const open = new Set(segments.segments.filter((s) => s.count > 1).map((s) => runKey(s.edges)));\n const lanes = laneRoutes(segments, open, spacing);\n return {\n faults: measureLinks(boxes, drawn),\n crossings: q.crossings,\n ink: q.ink,\n detour: q.detour,\n laneThrough: measureRouteFaults(graph, { routes: lanes }).through,\n };\n}\n\n/**\n * This function measures a packed board, the board with each gap open to the gutter only, and the board that each room strategy opens.\n * The options are the same for each strategy, except `method`. The default strategies are the methods `routes` and `lines` of `roomDemand`.\n */\nexport function benchRoom(\n fixture: string,\n graph: Graph,\n options: RoomOptions = {},\n methods: readonly Strategy<\"room\">[] = [roomStrategies.routes, roomStrategies.lines],\n): RoomBenchRow[] {\n const spacing = options.spacing ?? 4;\n const area0 = areaOf(graph.nodes);\n const links = roomLinks(graph);\n const row = (board: string, nodes: readonly Node[], ms: number): RoomBenchRow => ({\n fixture,\n board,\n area: area0 > 0 ? areaOf(nodes) / area0 : 1,\n ms,\n ...measureBoard({ nodes, edges: graph.edges }, spacing),\n });\n const rows = [row(\"packed\", graph.nodes, 0)];\n const t0 = now();\n const gutter = makeRoom(graph.nodes, links, { ...options, spacing: 0, method: \"routes\" });\n rows.push(row(\"gutter\", gutter.items, now() - t0));\n const { method: _method, ...preset } = options;\n for (const s of methods) {\n const t1 = now();\n const gaps = s.run({ items: graph.nodes, links }, preset);\n const nodes = openGaps(graph.nodes, gaps, options.snap);\n rows.push(row(s.name, nodes, now() - t1));\n }\n return rows;\n}\n\n/** One setting of a sweep of the room: the options of `makeRoom` and the lane order of the far view. */\nexport interface RoomSetting {\n /** The name of the setting in the column `board`. */\n readonly name: string;\n readonly options: RoomOptions;\n /** The lane order of the far view. Without it, the links of a gap share the lines of the level links. */\n readonly lanes?: LaneOrder;\n}\n\n/**\n * This function measures the board that `makeRoom` opens with each setting, with the method `routes`.\n * The first row is the fair baseline: the board with each gap open to the gutter of `baseline` only, measured at the spacing of `baseline`.\n */\nexport function sweepRoom(fixture: string, graph: Graph, settings: readonly RoomSetting[], baseline: RoomOptions = { gutter: 8, spacing: 4 }): RoomBenchRow[] {\n const area0 = areaOf(graph.nodes);\n const links = roomLinks(graph);\n const row = (board: string, nodes: readonly Node[], ms: number, spacing: number, lanes?: LaneOrder): RoomBenchRow => ({\n fixture,\n board,\n area: area0 > 0 ? areaOf(nodes) / area0 : 1,\n ms,\n ...measureBoard({ nodes, edges: graph.edges }, spacing, lanes),\n });\n const fair = makeRoom(graph.nodes, links, { ...baseline, spacing: 0, method: \"routes\", maxGrowth: Infinity, passes: 1 });\n const rows = [row(\"gutter\", fair.items, 0, baseline.spacing ?? 4)];\n for (const s of settings) {\n const t0 = now();\n const open = makeRoom(graph.nodes, links, { ...s.options, method: \"routes\" });\n rows.push(row(s.name, open.items, now() - t0, s.options.spacing ?? 4, s.lanes));\n }\n return rows;\n}\n\n/** The values of `maxGrowth` of the sweep of ROOM-A. */\nexport const GROWTH_SWEEP: readonly number[] = [0, 0.06, 0.09, 0.12, 0.15, 0.18, 0.21, 0.25, 0.3, 0.35, 0.5, Infinity];\n\n/** This function gives the settings of ROOM-A: the area and the faults for each `maxGrowth`, at gutter 8 and spacing 4. */\nexport function growthSettings(values: readonly number[] = GROWTH_SWEEP): RoomSetting[] {\n return values.map((m) => ({ name: `maxGrowth ${m}`, options: { gutter: 8, spacing: 4, maxGrowth: m } }));\n}\n\n/**\n * This function gives the settings of ROOM-C: each lane order of the far view at each spacing, at gutter 8.\n * The order `shared` is the far view without lanes, as before ROOM-C.\n */\nexport function laneSettings(spacings: readonly number[] = [2, 4, 6, 8], orders: readonly LaneOrder[] = LANE_ORDERS): RoomSetting[] {\n return spacings.flatMap((spacing) => [\n { name: `shared spacing ${spacing}`, options: { gutter: 8, spacing } },\n ...orders.map((lanes) => ({ name: `${lanes} spacing ${spacing}`, options: { gutter: 8, spacing }, lanes })),\n ]);\n}\n\n/** This function gives the settings of ROOM-D: each gutter with each number of passes, at spacing 4. */\nexport function passSettings(gutters: readonly number[] = [4, 8, 12, 16], passes: readonly number[] = [1, 2]): RoomSetting[] {\n return gutters.flatMap((gutter) => passes.map((p) => ({ name: `gutter ${gutter} passes ${p}`, options: { gutter, spacing: 4, passes: p } })));\n}\n\n/** This function writes the rows of `benchRoom` as a Markdown table. */\nexport function formatRoom(rows: readonly RoomBenchRow[]): string {\n const head = \"| fixture | board | area | links | through | outside | out and back | worst detour | crossings | ink | detour | lane through | ms |\";\n const line = \"|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|\";\n const body = rows.map((r) => {\n const f = r.faults;\n return `| ${r.fixture} | ${r.board} | ${r.area.toFixed(3)} | ${f.links} | ${f.through} | ${f.outside} | ${f.backtrack} | ${f.worstDetour.toFixed(2)} | ${r.crossings} | ${Math.round(r.ink)} | ${r.detour.toFixed(3)} | ${r.laneThrough} | ${r.ms.toFixed(1)} |`;\n });\n return [head, line, ...body].join(\"\\n\");\n}\n","import type { Graph, Result } from \"../model.ts\";\nimport { sectionsRouter, type SectionsOptions } from \"../routers/sections.ts\";\nimport { groupStrategies } from \"../strategies/builtins.ts\";\nimport type { Strategy } from \"../strategies/model.ts\";\nimport { sameData } from \"./run.ts\";\nimport { measureLevelFaults, measureRouteFaults, sumFaults, type LinkFaults } from \"./links.ts\";\n\n// The core runs in any host, so it reads the clock without the types of Node or the browser.\nconst now = (): number => (globalThis as { performance?: { now(): number } }).performance?.now() ?? Date.now();\n\n/** The options of one setting of the router `sections`, without the name. */\nexport type SectionsSettingOptions = Omit<SectionsOptions, \"name\" | \"maxNodes\">;\n\n/** One setting of a sweep of the router `sections`. */\nexport interface SectionsSetting {\n /** The name of the setting in the column `setting`. */\n readonly name: string;\n readonly options: SectionsSettingOptions;\n}\n\n/** One row of a sweep of the router `sections`: one setting on one board, and the measures of its routes and of its zoom levels. */\nexport interface SectionsBenchRow {\n readonly fixture: string;\n readonly setting: string;\n /** The faults of the routes of the edges (`measureRouteFaults`). */\n readonly faults: LinkFaults;\n /** The sum of the faults of the levels with groups (`measureLevelFaults` and `sumFaults`). */\n readonly levelFaults: LinkFaults;\n /** The sum of the overlaps of the levels with groups. */\n readonly overlaps: number;\n /** The number of routes that go through hubs: the routes that are not the same as the direct route of their edge. */\n readonly hubRoutes: number;\n /** The number of shared stretches of way of the result (`runs`). */\n readonly runs: number;\n /** The number of zoom levels, with the last level of single nodes. */\n readonly levels: number;\n /** The number of items of the far view: the first level with more than one item. */\n readonly farItems: number;\n /** The time of one route, in milliseconds. */\n readonly ms: number;\n}\n\n/** This function gives the number of items of the first level with more than one item, or 0 for a result without levels. */\nfunction farItems(result: Result): number {\n return result.levels?.find((l) => l.items.length > 1)?.items.length ?? 0;\n}\n\n/**\n * This function measures the router `sections` on one board with each setting. The first row is the fair baseline: the defaults, with no option.\n * The direct routes come from the hub limit 0, so `hubRoutes` counts the routes that use the hubs.\n */\nexport function sweepSections(fixture: string, graph: Graph, settings: readonly SectionsSetting[]): SectionsBenchRow[] {\n const all: SectionsSetting[] = [{ name: \"defaults\", options: {} }, ...settings];\n return all.map((s) => {\n const direct = sectionsRouter({ ...s.options, name: \"direct\", stretch: 0, stretchPad: 0 }).route(graph);\n const t0 = now();\n const result = sectionsRouter({ ...s.options, name: s.name }).route(graph);\n const ms = now() - t0;\n const levelFaults = measureLevelFaults(result);\n return {\n fixture,\n setting: s.name,\n faults: measureRouteFaults(graph, result),\n levelFaults: sumFaults(levelFaults),\n overlaps: levelFaults.reduce((n, f) => n + f.overlaps, 0),\n hubRoutes: result.routes.filter((r, i) => !sameData(r.points, direct.routes[i]?.points)).length,\n runs: result.runs?.length ?? 0,\n levels: result.levels?.length ?? 0,\n farItems: farItems(result),\n ms,\n };\n });\n}\n\n/** The values of the hub limit (`stretch`) of the sweep of CUSTOM. The default is 2. */\nexport const STRETCH_SWEEP: readonly number[] = [1.25, 1.5, 2, 3, Infinity];\n\n/** This function gives the settings of the sweep of the hub limit: one setting for each value of `stretch`. */\nexport function stretchSettings(values: readonly number[] = STRETCH_SWEEP): SectionsSetting[] {\n return values.map((stretch) => ({ name: `stretch ${stretch}`, options: { stretch } }));\n}\n\n/** The values of `hubSlack` of the sweep of CUSTOM. The default is 80. */\nexport const SLACK_SWEEP: readonly number[] = [0, 40, 80, 160, Infinity];\n\n/** This function gives the settings of the sweep of the slack of the hubs: one setting for each value of `hubSlack`. */\nexport function slackSettings(values: readonly number[] = SLACK_SWEEP): SectionsSetting[] {\n return values.map((hubSlack) => ({ name: `hubSlack ${hubSlack}`, options: { hubSlack } }));\n}\n\n/** The values of the section limit (`cap`) of the sweep of CUSTOM. The default is 8. */\nexport const CAP_SWEEP: readonly number[] = [4, 6, 8, 12, 16];\n\n/** This function gives the settings of the sweep of the section limit: one setting for each value of `cap`. */\nexport function capSettings(values: readonly number[] = CAP_SWEEP): SectionsSetting[] {\n return values.map((cap) => ({ name: `cap ${cap}`, options: { cap } }));\n}\n\n/**\n * This function gives one setting for each grouping rule: the router `sections` with the strategy as its option `group`.\n * The map `options` gives the options of a strategy by its name.\n */\nexport function groupSettings(\n strategies: readonly Strategy<\"group\">[] = Object.values(groupStrategies),\n options: Readonly<Record<string, object>> = {},\n): SectionsSetting[] {\n return strategies.map((group) => ({ name: `group ${group.name}`, options: { group, ...(options[group.name] ? { groupOptions: options[group.name] } : {}) } }));\n}\n\n/** This function writes the rows of `sweepSections` as a Markdown table. */\nexport function formatSections(rows: readonly SectionsBenchRow[]): string {\n const head =\n \"| fixture | setting | through | out and back | worst detour | outside | hub routes | runs | levels | far items | level through | level out and back | level outside | level overlaps | ms |\";\n const line = \"|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|\";\n const body = rows.map((r) => {\n const f = r.faults;\n const l = r.levelFaults;\n return `| ${r.fixture} | ${r.setting} | ${f.through} | ${f.backtrack} | ${f.worstDetour.toFixed(2)} | ${f.outside} | ${r.hubRoutes} | ${r.runs} | ${r.levels} | ${r.farItems} | ${l.through} | ${l.backtrack} | ${l.outside} | ${r.overlaps} | ${r.ms.toFixed(1)} |`;\n });\n return [head, line, ...body].join(\"\\n\");\n}\n"],"mappings":"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"}