@mark1russell7/highways 0.2.0 → 0.4.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.
Files changed (66) hide show
  1. package/README.md +265 -9
  2. package/build/index.d.ts +2168 -101
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +11624 -3422
  5. package/build/index.js.map +1 -1
  6. package/package.json +4 -1
  7. package/src/bench/compare.ts +180 -0
  8. package/src/bench/curves.ts +514 -2
  9. package/src/bench/links.ts +28 -6
  10. package/src/bench/measures/bundles.ts +119 -0
  11. package/src/bench/measures/curves.ts +211 -0
  12. package/src/bench/measures/groups.ts +122 -0
  13. package/src/bench/measures/index.ts +9 -0
  14. package/src/bench/measures/levels.ts +103 -0
  15. package/src/bench/measures/pareto.ts +37 -0
  16. package/src/bench/measures/room.ts +43 -0
  17. package/src/bench/measures/routes.ts +226 -0
  18. package/src/bench/measures/stability.ts +104 -0
  19. package/src/bench/measures/stats.ts +114 -0
  20. package/src/bench/properties.ts +18 -2
  21. package/src/bench/room.ts +209 -2
  22. package/src/bench/run.ts +86 -11
  23. package/src/bench/screen/forms.ts +372 -0
  24. package/src/bench/screen/generators.ts +54 -0
  25. package/src/bench/screen/hash.ts +129 -0
  26. package/src/bench/screen/index.ts +6 -0
  27. package/src/bench/screen/measures.ts +114 -0
  28. package/src/bench/screen/screen.ts +390 -0
  29. package/src/bench/screen/set.ts +136 -0
  30. package/src/bench/suite.ts +839 -0
  31. package/src/cases.ts +41 -5
  32. package/src/curves/clothoid/index.ts +150 -0
  33. package/src/curves/corner.ts +116 -0
  34. package/src/curves/fit.ts +79 -0
  35. package/src/curves/highway/index.ts +636 -0
  36. package/src/curves/index.ts +16 -1
  37. package/src/curves/model.ts +4 -2
  38. package/src/curves/smooth/index.ts +50 -0
  39. package/src/curves/space.ts +76 -0
  40. package/src/groups/cut/index.ts +292 -0
  41. package/src/groups/index.ts +2 -0
  42. package/src/groups/kd/index.ts +207 -0
  43. package/src/highways/corridors/index.ts +305 -0
  44. package/src/highways/follow.ts +155 -0
  45. package/src/highways/index.ts +7 -0
  46. package/src/highways/keys/index.ts +15 -0
  47. package/src/highways/model.ts +111 -0
  48. package/src/highways/result.ts +34 -0
  49. package/src/highways/router.ts +40 -0
  50. package/src/highways/shared-ways/index.ts +15 -0
  51. package/src/index.ts +6 -0
  52. package/src/levels.ts +163 -5
  53. package/src/room/bends.ts +203 -0
  54. package/src/room/index.ts +28 -0
  55. package/src/room/levels/index.ts +155 -0
  56. package/src/routers/sections.ts +15 -40
  57. package/src/routers/shared.ts +7 -2
  58. package/src/routers/trunks.ts +131 -6
  59. package/src/sections.ts +47 -1
  60. package/src/segments.ts +81 -31
  61. package/src/strategies/builtins.ts +206 -9
  62. package/src/strategies/index.ts +1 -0
  63. package/src/strategies/model.ts +55 -7
  64. package/src/strategies/options.ts +296 -0
  65. package/src/strategies/schemas.ts +234 -0
  66. package/src/visibility.ts +190 -1
package/build/index.d.ts CHANGED
@@ -246,6 +246,17 @@ export declare function hubChainBoard(): Graph;
246
246
  * On a level with many groups, some level links go around the outer edge of the board.
247
247
  */
248
248
  export declare function manyGroupsBoard(): Graph;
249
+ /** The options of `packedGridBoard`. */
250
+ export interface PackedGridOptions {
251
+ /** The seed of the links. The default is 11. */
252
+ readonly seed?: number;
253
+ /** The number of columns. The default is 12. */
254
+ readonly cols?: number;
255
+ /** The number of rows. The default is 8. */
256
+ readonly rows?: number;
257
+ /** The number of long links between boxes far apart. The default is 48. */
258
+ readonly long?: number;
259
+ }
249
260
  /**
250
261
  * This function makes the far view of a board after a host layout packs it.
251
262
  * The board has 96 boxes of one size in a grid of 12 columns and 8 rows.
@@ -253,8 +264,17 @@ export declare function manyGroupsBoard(): Graph;
253
264
  * The links have no channel between the boxes. The roadmap item ROOM measures this board before and after `makeRoom`.
254
265
  *
255
266
  * The board is not in `CASES`, because the digests of the router fix the output on each board of `CASES`.
267
+ * The options make a family of such boards for the measure suite. Without options, the board does not change.
268
+ */
269
+ export declare function packedGridBoard(options?: PackedGridOptions): Graph;
270
+ /**
271
+ * This function makes a packed board with three zoom levels of groups. The board has 256 touching boxes in a grid of 16 columns and 16 rows.
272
+ * The quadtree of `buildSections` splits it into 4, 16 and 64 groups. Each box links to a box near it, and 64 long links join boxes far apart.
273
+ * At each level, the boxes of the groups touch, so the level links have no channel. The roadmap item ROOM2 measures this board.
274
+ *
275
+ * The board is not in `CASES`, because the digests of the router fix the output on each board of `CASES`.
256
276
  */
257
- export declare function packedGridBoard(): Graph;
277
+ export declare function nestedGridBoard(): Graph;
258
278
  /** The case boards of the benchmark. Each board has a few hundred nodes at most, so the benchmark races them on each run. */
259
279
  export declare const CASES: readonly CaseBoard[];
260
280
  /** A plug: the point where a route leaves or enters a node, and the outward normal of its side. */
@@ -314,8 +334,10 @@ export declare function roundCorners(p: readonly Point[], radius: number, steps?
314
334
  * - `rounded`: a quadratic Bezier curve at each corner, as `roundCorners` draws it.
315
335
  * - `spline`: a centripetal Catmull-Rom spline through the points. It does not overshoot or make loops.
316
336
  * - `arc`: a circular arc at each corner, tangent to the two legs.
337
+ * - `smooth`: a cubic spiral, an arc and a second cubic spiral at each corner, as the corner smoothing of Figma.
338
+ * - `clothoid`: a clothoid, an arc and a second clothoid at each corner, as a transition curve of a road.
317
339
  */
318
- export type CurveType = "straight" | "rounded" | "spline" | "arc";
340
+ export type CurveType = "straight" | "rounded" | "spline" | "arc" | "smooth" | "clothoid";
319
341
  /** The curve types, in the order of the benchmark. */
320
342
  export declare const CURVE_TYPES: readonly CurveType[];
321
343
  /** The start of a curve: the pen goes to `to` and draws nothing. */
@@ -369,6 +391,12 @@ interface CurveSpace {
369
391
  * A polyline goes through a box when a part of it longer than `TOLERANCE` is inside the box made smaller by `TOLERANCE`.
370
392
  */
371
393
  addsHit(q: readonly Point[], p: readonly Point[]): boolean;
394
+ /**
395
+ * This method tells if the triangle `(a, v, b)` overlaps a box that the polyline `(a, v, b)` does not go through.
396
+ * A convex corner from `a` to `b` stays in this triangle, so a clear triangle proves a clear corner with no samples.
397
+ * The method is optional. Without it, a corner samples its curve.
398
+ */
399
+ addsHitTriangle?(a: Point, v: Point, b: Point): boolean;
372
400
  }
373
401
  /**
374
402
  * This function makes the free space of a board from its boxes. The boxes are the nodes, or the items of a zoom level.
@@ -441,13 +469,191 @@ interface ArcOptions {
441
469
  * On a polyline with only horizontal and vertical legs, each arc is a quarter circle.
442
470
  */
443
471
  export declare function arcCurve(points: readonly Point[], options?: ArcOptions): CurveSegment[];
472
+ /** The options of `smoothCurve`. */
473
+ interface SmoothOptions {
474
+ /** The radius of the arc in the middle of each corner: the smallest radius of the corner. The default is 12. */
475
+ readonly radius?: number;
476
+ /** The share of the turn of a corner in its two spirals, from 0 (a circular arc) to 1 (no arc). The default is 0.6. */
477
+ readonly smoothing?: number;
478
+ /** The boxes that the curve must not go through. Without it, each corner gets the largest radius that fits on its legs. */
479
+ readonly space?: CurveSpace;
480
+ }
481
+ /**
482
+ * This function rounds each inner vertex of a polyline with a cubic spiral, a circular arc and a second cubic spiral.
483
+ * It is the shape of the corner smoothing of Figma (F7 of the note CURVES). The curvature rises from 0 on the leg to `1 / radius` on the arc,
484
+ * so the curve is G2: it has no jump of the curvature. Each spiral turns by `smoothing` times half of the turn, up to `MAX_SPIRAL_TURN`.
485
+ * The ends of each corner stay on the first half of each leg, so the ends of the polyline stay.
486
+ * With `space`, the radius of a corner shrinks until its corner triangle overlaps no box that the polyline avoids.
487
+ */
488
+ export declare function smoothCurve(points: readonly Point[], options?: SmoothOptions): CurveSegment[];
489
+ /** The options of `clothoidCurve`. */
490
+ interface ClothoidOptions {
491
+ /** The radius of the arc in the middle of each corner: the smallest radius of the corner. The default is 12. */
492
+ readonly radius?: number;
493
+ /** The share of the turn of a corner in its two clothoids, from 0 (a circular arc) to 1 (no arc). The default is 0.5. */
494
+ readonly spiral?: number;
495
+ /** The largest distance from the cubic pieces to the true clothoid, in units of the plane. The default is 0.25. */
496
+ readonly tolerance?: number;
497
+ /** The boxes that the curve must not go through. Without it, each corner gets the largest radius that fits on its legs. */
498
+ readonly space?: CurveSpace;
499
+ }
500
+ /**
501
+ * This function rounds each inner vertex of a polyline with a clothoid, a circular arc and a second clothoid (F6 of the note CURVES).
502
+ * The curvature of a clothoid grows linearly with its length, from 0 on the leg to `1 / radius` on the arc. This is the transition curve of roads and railways.
503
+ * Each clothoid turns by `spiral` times half of the turn. G2 cubic pieces draw it within `tolerance` of the true clothoid.
504
+ *
505
+ * The ends of each corner stay on the first half of each leg, so the ends of the polyline stay.
506
+ * With `space`, the radius of a corner shrinks until its corner triangle overlaps no box that the polyline avoids.
507
+ */
508
+ export declare function clothoidCurve(points: readonly Point[], options?: ClothoidOptions): CurveSegment[];
509
+ /** A piece of drawn way. A shared segment carries several edges, in lane order. A private segment carries one edge. */
510
+ export interface Segment {
511
+ readonly id: string;
512
+ readonly points: readonly Point[];
513
+ /** 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. */
514
+ readonly edges: readonly string[];
515
+ /** The number of edges. A renderer shows it on a fat edge. */
516
+ readonly count: number;
517
+ }
518
+ /** One step of a path: a segment, the way through it, and the lane of the edge in it. */
519
+ export interface SegmentRef {
520
+ readonly segment: string;
521
+ /** This value is true when the edge goes from the last point of the segment to its first point. */
522
+ readonly reverse: boolean;
523
+ readonly lane: number;
524
+ }
525
+ /** The route of one edge as a list of segments. */
526
+ export interface Path {
527
+ readonly edge: string;
528
+ readonly segments: readonly SegmentRef[];
529
+ }
530
+ /** The routes of a result as shared geometry. A renderer can draw each segment one time, with a count. */
531
+ export interface SegmentGraph {
532
+ readonly segments: readonly Segment[];
533
+ readonly paths: readonly Path[];
534
+ }
535
+ /**
536
+ * This function breaks each route into segments. The runs and the trunks of the bundles become shared segments.
537
+ * The other parts of each route become private segments. The segments of a path, in order, give the points of its route again.
538
+ */
539
+ export declare function segmentsOf(result: Result): SegmentGraph;
540
+ /** This function gives the points of a path, with the segments in the order and the way of the path. */
541
+ export declare function pathPoints(graph: SegmentGraph, path: Path): Point[];
542
+ /**
543
+ * This function moves each point of a polyline by `d` to the left, in a frame with the y axis down.
544
+ * At an inner point, it moves along the bisector, at most 2 × `d` far.
545
+ */
546
+ export declare function offsetPolyline(p: readonly Point[], d: number): Point[];
547
+ /** The options of `pullApart`. */
548
+ export interface PullApartOptions {
549
+ /** The distance between two lanes. */
550
+ readonly spacing: number;
551
+ /** The largest width of a segment, from its outer lane on the left to its outer lane on the right. */
552
+ readonly maxWidth: number;
553
+ }
554
+ /**
555
+ * This function pulls the lanes of each shared segment apart, and gives a route for each edge.
556
+ * The lanes keep the lane order, so they do not cross in a segment. The two ends of each route stay at their plugs.
557
+ */
558
+ export declare function pullApart(graph: SegmentGraph, options: PullApartOptions): Route[];
559
+ /** This function gives the key of a shared run: the ids of its edges, sorted and joined with commas. */
560
+ export declare function runKey(edges: readonly string[]): string;
561
+ /**
562
+ * This function opens the shared segments whose key is in `open`: each edge of an open segment gets its own lane.
563
+ * The lanes are `laneWidth` apart, and an open segment is at most `maxWidth` wide. The other segments stay as one way.
564
+ *
565
+ * Lane 0 is on the left of the segment, from its first point to its last, with the y axis down.
566
+ * The function takes a result or its segments. It gives a route for each edge, with the ends at their plugs.
567
+ * The key of a segment is `runKey` of its edges.
568
+ */
569
+ export declare function laneRoutes(source: Result | SegmentGraph, open: ReadonlySet<string>, laneWidth: number, maxWidth?: number): Route[];
570
+ /**
571
+ * The lane order of the shared ways of a router.
572
+ * With `bundle`, two edges keep one order on all the shared ways of their common stretch.
573
+ * With `run`, each shared way gets its order alone. Two edges can change sides from one shared way to the next.
574
+ */
575
+ export type RunOrder = "bundle" | "run";
576
+ /**
577
+ * This function gives the lane order of the edges on a shared way `run` (metro-line order).
578
+ * The routes are polylines that hold the points of the run in a row, in either direction. A route that does not hold the run goes last.
579
+ *
580
+ * Two routes go on together past each end of the run until they part. The route that turns more to the left there gets the lane more to the left.
581
+ *
582
+ * With the order `run`, the default, the end after the last point of the run tells the side first.
583
+ * With the order `bundle`, two routes that part on one side at both ends keep that side.
584
+ * When the two ends disagree, the two routes must cross. The end with the smaller x, then the smaller y, tells the side.
585
+ * Thus each shared way of a common stretch gives two routes the same order, and the crossing is where they part.
586
+ */
587
+ export declare function orderLanes(run: readonly Point[], routes: readonly Route[], order?: RunOrder): string[];
588
+ /** The options of `highwayCurves`. */
589
+ interface HighwayOptions {
590
+ /** The radius at a bend of the center line of a bundle, at a lone corner, and at a merge or a split. The default is 12. */
591
+ readonly radius?: number;
592
+ /** The smallest radius of each lane at a bend, a merge or a split. A bend of a bundle grows to keep its inner lane at this radius. The default is 4. */
593
+ readonly minRadius?: number;
594
+ /** The largest width of an open segment, from its outer lane on the left to its outer lane on the right, as in `laneRoutes`. The default is `Infinity`. */
595
+ readonly maxWidth?: number;
596
+ /** The boxes that the lanes must not go through, from `curveSpace`. With it, no lane goes through a box that its lane of `laneRoutes` avoids. */
597
+ readonly space?: CurveSpace;
598
+ /** The shape of the S curve where a lane joins or leaves a bundle. The default is `biarc`. */
599
+ readonly jog?: JogStyle;
600
+ /** The number of cubic pieces of a `quintic` S curve, from 1 to 8. The default is 4. */
601
+ readonly jogPieces?: number;
602
+ }
603
+ /**
604
+ * The shape of the S curve where a lane changes its offset.
605
+ *
606
+ * - `biarc`: two circular arcs. The curvature jumps at each end and at the inflection.
607
+ * - `cubic`: one cubic Bezier curve with its handles along the leg. The curvature jumps at each end.
608
+ * - `quintic`: the quintic `y = d (10 t³ - 15 t⁴ + 6 t⁵)`, in G2 cubic pieces. The curvature is 0 at each end and has no jump.
609
+ *
610
+ * Each shape keeps its curvature at `1 / radius` or less. The polynomial shapes are longer than the biarc for this reason.
611
+ */
612
+ type JogStyle = "biarc" | "cubic" | "quintic";
613
+ /**
614
+ * The S curves of the lanes, by the order of `laneRoutes`. Each S curve has the first and the last index of its segments in the curve of its lane, and its shape.
615
+ * A polynomial S curve that does not fit on its leg is a biarc.
616
+ */
617
+ type JogTrace = (readonly [number, number, JogStyle])[][];
618
+ /** The curve of the lane of one edge: a list of segments for any renderer, as `curveOf` gives. */
619
+ interface LaneCurve {
620
+ readonly edge: string;
621
+ readonly segments: CurveSegment[];
622
+ }
623
+ /**
624
+ * This function gives the curve of one polyline as a lane alone: an arc at each corner, as `arcCurve` gives.
625
+ * A lane alone has no merge and no split, so the curve strategy `highway` gives this curve for one polyline.
626
+ */
627
+ export declare function highwayCurve(points: readonly Point[], options?: Pick<HighwayOptions, "radius" | "space">): CurveSegment[];
628
+ /**
629
+ * This function gives the curve of each lane of `laneRoutes`. The lanes of one open segment bend as one highway.
630
+ *
631
+ * At each bend of an open segment, the lanes are arcs with one center. The radius of a lane is the radius of the center line,
632
+ * plus or minus its offset. So the lanes stay at the lane spacing through the bend. The bend grows to keep the inner lane at `minRadius`,
633
+ * and it shrinks to fit on the legs and in the free space.
634
+ *
635
+ * A lane joins (merges) or leaves (splits) a bundle on an S curve on the leg with fewer lanes. The option `jog` gives its shape.
636
+ * The smallest radius of the S curve is `radius` or less.
637
+ * Each curve has no break of its tangent where each radius is more than 0.
638
+ * A lane that is in no open segment gets the curve of `arcCurve`.
639
+ *
640
+ * The function takes the same input as `laneRoutes`, and it gives the curves in the order of `laneRoutes`.
641
+ * The output is a list of segments for any renderer. `toSvgPath` writes it as SVG path data, and `sampleCurve` gives points.
642
+ */
643
+ export declare function highwayCurves(source: Result | SegmentGraph, open: ReadonlySet<string>, laneWidth: number, options?: HighwayOptions): LaneCurve[];
444
644
  /** The options of `curveOf`. Each type reads only the options that it uses. */
445
645
  export interface CurveOptions {
446
646
  readonly type: CurveType;
447
- /** The types `rounded` and `arc` read this radius of the corners. The default is 12. */
647
+ /** The types `rounded`, `arc`, `smooth` and `clothoid` read this radius of the corners. The default is 12. */
448
648
  readonly radius?: number;
449
649
  /** The type `spline` reads this tension, from 0 to 1. The default is 0. */
450
650
  readonly tension?: number;
651
+ /** The type `smooth` reads this share of the turn of a corner in its spirals, from 0 to 1. The default is 0.6. */
652
+ readonly smoothing?: number;
653
+ /** The type `clothoid` reads this share of the turn of a corner in its clothoids, from 0 to 1. The default is 0.5. */
654
+ readonly spiral?: number;
655
+ /** The type `clothoid` reads this largest distance from its cubic pieces to the true clothoid. The default is 0.25. */
656
+ readonly tolerance?: number;
451
657
  /** The type `spline` leaves the first point along this outward normal of its plug. */
452
658
  readonly startNormal?: Point;
453
659
  /** The type `spline` comes into the last point against this outward normal of its plug. */
@@ -475,6 +681,12 @@ export declare class Obstacles {
475
681
  hit(a: Point, b: Point, pad: number, skip?: ReadonlySet<Node>): Node | undefined;
476
682
  /** This method tells if the polyline stays out of each box, made larger by `pad`. The nodes in `skip` do not count. */
477
683
  clearPath(p: readonly Point[], pad: number, skip?: ReadonlySet<Node>): boolean;
684
+ /**
685
+ * This method gives each node whose box the segment `ab` goes through to `visit`, one time each.
686
+ * The segment goes through a box when a part of it longer than `TOLERANCE` is inside the box made smaller by `TOLERANCE`.
687
+ * The link measures (`measureLinks`) use the same test.
688
+ */
689
+ through(a: Point, b: Point, visit: (n: Node) => void): void;
478
690
  /** This method gives each node whose bucket the box touches to `visit`. A node can be outside the box. */
479
691
  query(box: Box, visit: (n: Node) => void): void;
480
692
  /** This method tells if the point is inside a box, made larger by `pad`. The node `skip` does not count. */
@@ -541,6 +753,36 @@ export declare class CornerGraph {
541
753
  /** This method removes the vertices that a later vertex makes needless: from each vertex, it goes to the farthest vertex in view. */
542
754
  pull(p: readonly Point[], lookahead?: number): Point[];
543
755
  }
756
+ /** The options of the soft graph. */
757
+ export interface SoftGraphOptions {
758
+ /** The distance from a box to its corners. */
759
+ readonly margin: number;
760
+ /** The number of nearest neighbours of each vertex. */
761
+ readonly k: number;
762
+ /**
763
+ * The spacing of a lattice of points in the bounding box of the boxes, in units of the mean node size. The default is 3, and 0 turns it off.
764
+ * The lattice links groups of boxes across empty space.
765
+ */
766
+ readonly lattice?: number;
767
+ }
768
+ /**
769
+ * A graph whose links can go through the boxes. Its vertices are the corners of the boxes, made larger by `margin`,
770
+ * and a lattice of points in the bounding box of the boxes. Each vertex links to its `k` nearest vertices, in view or not.
771
+ * The graph keeps the boxes that each link goes through (`Obstacles.through`).
772
+ * A search gives each box a cost, so a path goes through few boxes, and only through boxes of a low cost.
773
+ */
774
+ export declare class SoftGraph {
775
+ #private;
776
+ readonly points: Point[];
777
+ /** This constructor makes the graph of the nodes. */
778
+ constructor(nodes: readonly Node[], obstacles: Obstacles, options: SoftGraphOptions);
779
+ /**
780
+ * This method gives a path of least cost from `from` to `to` (A*), with the two points as its ends.
781
+ * The cost of a path is its length, plus `cost(n)` for each link of the path and each box `n` of that link.
782
+ * Each cost must be 0 or more. The straight line from `from` to `to` is a path too, so the method always gives a path.
783
+ */
784
+ path(from: Point, to: Point, cost: (n: Node) => number): Point[];
785
+ }
544
786
  /** The options of a way finder. */
545
787
  export interface WayOptions {
546
788
  /** The distance from a box to the corners of the graph. The default is 5. */
@@ -570,74 +812,6 @@ export declare class WayFinder {
570
812
  /** This method gives a way from a free point to a plug, or `undefined` when the graph has none. */
571
813
  toPlug(from: Point, pt: Plug): Point[] | undefined;
572
814
  }
573
- /** A piece of drawn way. A shared segment carries several edges, in lane order. A private segment carries one edge. */
574
- export interface Segment {
575
- readonly id: string;
576
- readonly points: readonly Point[];
577
- /** 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. */
578
- readonly edges: readonly string[];
579
- /** The number of edges. A renderer shows it on a fat edge. */
580
- readonly count: number;
581
- }
582
- /** One step of a path: a segment, the way through it, and the lane of the edge in it. */
583
- export interface SegmentRef {
584
- readonly segment: string;
585
- /** This value is true when the edge goes from the last point of the segment to its first point. */
586
- readonly reverse: boolean;
587
- readonly lane: number;
588
- }
589
- /** The route of one edge as a list of segments. */
590
- export interface Path {
591
- readonly edge: string;
592
- readonly segments: readonly SegmentRef[];
593
- }
594
- /** The routes of a result as shared geometry. A renderer can draw each segment one time, with a count. */
595
- export interface SegmentGraph {
596
- readonly segments: readonly Segment[];
597
- readonly paths: readonly Path[];
598
- }
599
- /**
600
- * This function breaks each route into segments. The runs and the trunks of the bundles become shared segments.
601
- * The other parts of each route become private segments. The segments of a path, in order, give the points of its route again.
602
- */
603
- export declare function segmentsOf(result: Result): SegmentGraph;
604
- /** This function gives the points of a path, with the segments in the order and the way of the path. */
605
- export declare function pathPoints(graph: SegmentGraph, path: Path): Point[];
606
- /**
607
- * This function moves each point of a polyline by `d` to the left, in a frame with the y axis down.
608
- * At an inner point, it moves along the bisector, at most 2 × `d` far.
609
- */
610
- export declare function offsetPolyline(p: readonly Point[], d: number): Point[];
611
- /** The options of `pullApart`. */
612
- export interface PullApartOptions {
613
- /** The distance between two lanes. */
614
- readonly spacing: number;
615
- /** The largest width of a segment, from its outer lane on the left to its outer lane on the right. */
616
- readonly maxWidth: number;
617
- }
618
- /**
619
- * This function pulls the lanes of each shared segment apart, and gives a route for each edge.
620
- * The lanes keep the lane order, so they do not cross in a segment. The two ends of each route stay at their plugs.
621
- */
622
- export declare function pullApart(graph: SegmentGraph, options: PullApartOptions): Route[];
623
- /** This function gives the key of a shared run: the ids of its edges, sorted and joined with commas. */
624
- export declare function runKey(edges: readonly string[]): string;
625
- /**
626
- * This function opens the shared segments whose key is in `open`: each edge of an open segment gets its own lane.
627
- * The lanes are `laneWidth` apart, and an open segment is at most `maxWidth` wide. The other segments stay as one way.
628
- *
629
- * Lane 0 is on the left of the segment, from its first point to its last, with the y axis down.
630
- * The function takes a result or its segments. It gives a route for each edge, with the ends at their plugs.
631
- * The key of a segment is `runKey` of its edges.
632
- */
633
- export declare function laneRoutes(source: Result | SegmentGraph, open: ReadonlySet<string>, laneWidth: number, maxWidth?: number): Route[];
634
- /**
635
- * This function gives the lane order of the edges on a shared way `run` (metro-line order). Two routes go on together
636
- * 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.
637
- * 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.
638
- * A route that does not hold the run goes last.
639
- */
640
- export declare function orderLanes(run: readonly Point[], routes: readonly Route[]): string[];
641
815
  /** A section of the plane: a cell of a quadtree, with the nodes whose centers are in it. */
642
816
  export interface Section {
643
817
  /** The path from the root: "s", then one digit from 0 to 3 for each step down. */
@@ -673,6 +847,19 @@ export declare function treeDepth(root: Section): number;
673
847
  * 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.
674
848
  */
675
849
  export declare function checkSections(root: Section, count: number): void;
850
+ /** The items of one zoom level of a tree of sections, and the item of each node. */
851
+ export interface LevelCut {
852
+ /** The items of the level: a section of the depth of the level, or one node of a leaf above that depth. */
853
+ readonly items: LevelItem[];
854
+ /** The index in `items` of the item of each node, in the order of the nodes. */
855
+ readonly owner: readonly number[];
856
+ }
857
+ /**
858
+ * This function gives the items of the zoom level at `depth`. A section of that depth is one item, with the bounding box of its nodes.
859
+ * A node of a leaf above that depth is an item alone. The items come in the order of the walk of the tree, parents before children.
860
+ * A depth past the depth of the deepest section gives each node alone.
861
+ */
862
+ export declare function levelCut(nodes: readonly Pick<Node, "id" | "box">[], root: Section, depth: number): LevelCut;
676
863
  /**
677
864
  * This function gives the tree of sections of the grouping rule `quadtree`: the cells of a quadtree of the plane (`buildSections`).
678
865
  * It is the default grouping rule of the router `sections`.
@@ -700,6 +887,73 @@ export declare const byDataGroup: NodeKey;
700
887
  export declare function keyedSections(nodes: readonly Node[], options?: KeyOptions): Section;
701
888
  /** This function gives the tree of sections of the grouping rule `keys` for a graph. */
702
889
  export declare function keyGroups(graph: Graph, options?: KeyOptions): Section;
890
+ /** The cost of a line of the rule `cut`, from the cut `c` and the parts `A` and `B` of the split. */
891
+ type CutObjective = "ratio" | "normalized" | "sparsest";
892
+ /** The options of the grouping rule `cut` (M1 of GRP-R, the guillotine cut). */
893
+ interface CutOptions {
894
+ /** A section with more nodes splits. The default is 8, as for the quadtree. */
895
+ readonly cap?: number;
896
+ /** The tree stops at this depth. The default is 16. */
897
+ readonly maxDepth?: number;
898
+ /** The number of children of a section: 2 or 4. With 4, a section splits two times on one level. The default is 4. */
899
+ readonly fanout?: number;
900
+ /** The smallest share of the nodes in each part of a split (`β`), from 0.05 to 0.5. The default is 0.25. */
901
+ readonly balance?: number;
902
+ /**
903
+ * The cost of a line. The value `ratio` is `c / min(|A|, |B|)`. The value `normalized` is `c / vol(A) + c / vol(B)`, with `vol` the sum of the degrees
904
+ * inside the section. The value `sparsest` is `c / (|A| · |B|)`. The default is `ratio`.
905
+ */
906
+ readonly objective?: CutObjective;
907
+ /**
908
+ * The cost of a line grows by the factor `1 + pull · d`. The value `d` is the distance of the line from the middle of the cell, as a share of the side.
909
+ * A large value prefers the middle line, as the quadtree does. The default is 0.5.
910
+ */
911
+ readonly pull?: number;
912
+ /**
913
+ * With `true`, each section also tests the split of the quadtree, and keeps the split that cuts fewer edges.
914
+ * Thus no section cuts more edges than the quadtree split of its cell. With the fan-out 2, the test uses each midline of the cell. The default is `true`.
915
+ */
916
+ readonly guard?: boolean;
917
+ }
918
+ /** The default values of `CutOptions`. */
919
+ export declare const CUT_DEFAULTS: Readonly<Required<CutOptions>>;
920
+ /**
921
+ * This function gives the tree of sections of the grouping rule `cut`: a guillotine cut that reads the edges (M1 of GRP-R).
922
+ * A section with more than `cap` nodes splits in two along the line with the lowest cost, on either axis. A line goes between two centers.
923
+ * Each part of a split holds at least the share `balance` of the nodes. With the fan-out 4, each half splits again on the same level.
924
+ *
925
+ * The cells nest and do not overlap. The option `guard` keeps the split of the quadtree when that split cuts fewer edges.
926
+ */
927
+ export declare function cutGroups(graph: Graph, options?: CutOptions): Section;
928
+ /** The place of the line of a split of the rule `kd`. */
929
+ type KdLine = "median" | "middle" | "slide";
930
+ /** The axis of each split of the rule `kd`. */
931
+ type KdAxis = "longer" | "alternate";
932
+ /** The options of the grouping rule `kd` (S3 of GRP-R). */
933
+ interface KdOptions {
934
+ /** A section with more nodes splits. The default is 8, as for the quadtree. */
935
+ readonly cap?: number;
936
+ /** The tree stops at this depth. The default is 16. */
937
+ readonly maxDepth?: number;
938
+ /**
939
+ * This value sets the place of the line in the cell. The value `median` puts half of the nodes on each side. The value `middle` cuts the cell in half,
940
+ * and an empty half makes the cell shrink to the other half. The value `slide` cuts the cell in half, and a line with an empty side slides to the nearest node.
941
+ * The default is `slide`.
942
+ */
943
+ readonly line?: KdLine;
944
+ /** The number of children of a section: 2 or 4. With 4, a section splits two times on one level. The default is 4. */
945
+ readonly fanout?: number;
946
+ /** The value `longer` cuts across the longer side of the cell. The value `alternate` cuts across x, then y, then x again. The default is `longer`. */
947
+ readonly axis?: KdAxis;
948
+ }
949
+ /** The default values of `KdOptions`. */
950
+ export declare const KD_DEFAULTS: Readonly<Required<KdOptions>>;
951
+ /**
952
+ * This function gives the tree of sections of the grouping rule `kd`: a k-d tree of the plane (S3 of GRP-R).
953
+ * A section with more than `cap` nodes splits in two with a line across one axis. With the fan-out 4, each half splits again on the same level.
954
+ * The cells nest and do not overlap. The line `median` gives halves of equal size.
955
+ */
956
+ export declare function kdGroups(graph: Graph, options?: KdOptions): Section;
703
957
  /** This function gives the median width of the shown items of each level, in units of the plane. */
704
958
  export declare function itemSizes(levels: readonly Level[]): number[];
705
959
  /** The far-view thresholds of `pickLevel`, in pixels on the screen. */
@@ -750,6 +1004,8 @@ interface SharedOptions extends WayOptions {
750
1004
  readonly rule?: GroupRule;
751
1005
  /** 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. */
752
1006
  readonly discount?: number;
1007
+ /** The lane order of the runs. With `bundle`, the default, two edges keep one order on each run of their common stretch. With `run`, each run gets its order alone. */
1008
+ readonly laneOrder?: RunOrder;
753
1009
  /** The benchmark skips a fixture with more nodes. */
754
1010
  readonly maxNodes?: number;
755
1011
  }
@@ -760,6 +1016,12 @@ interface SharedOptions extends WayOptions {
760
1016
  * The result gives each stretch as a run, with the order of its lanes.
761
1017
  */
762
1018
  export declare function sharedRouter(options: SharedOptions): Router;
1019
+ /** Two items of a level that a link joins, and the count of the edges between them. */
1020
+ interface ItemPair {
1021
+ readonly source: string;
1022
+ readonly target: string;
1023
+ readonly count: number;
1024
+ }
763
1025
  /** The options of the links of a level: the options of the ways, and two limits of the level links. */
764
1026
  interface LevelLinkOptions extends WayOptions {
765
1027
  /**
@@ -769,6 +1031,88 @@ interface LevelLinkOptions extends WayOptions {
769
1031
  readonly tightMargin?: number;
770
1032
  /** 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. */
771
1033
  readonly plugInset?: number;
1034
+ /**
1035
+ * The cost of a level link through a far box, in units of the mean box size. A far box overlaps neither end of the link.
1036
+ * A link through a far box gets a second way that can go through boxes (`SoftGraph`). The link keeps the way with fewer far boxes.
1037
+ * The value 0 turns the second way off and gives the links of version 0.1.5. The default is 8.
1038
+ */
1039
+ readonly throughCost?: number;
1040
+ }
1041
+ /** The input of a highway strategy: the boxes and the edges, and optionally the first routes of a router. */
1042
+ interface HighwayInput {
1043
+ readonly graph: Graph;
1044
+ /**
1045
+ * These routes are the first routes, from a router. A strategy that reads first routes makes them itself when this value is absent.
1046
+ * The strategy `corridors` makes the ways of the corner graph, as the router `corners` finds them.
1047
+ */
1048
+ readonly routes?: Result;
1049
+ }
1050
+ /**
1051
+ * One edge of a highway. The edge joins the spine at the merge point and leaves it at the split point.
1052
+ * A place on the spine is the index of a point of the spine plus the share of the next leg. Point `i` of the spine is at `i`.
1053
+ * When `on` is larger than `off`, the edge goes along the spine from its last point to its first point.
1054
+ */
1055
+ interface HighwayMember {
1056
+ readonly edge: string;
1057
+ /** The place of the merge point on the spine. */
1058
+ readonly on: number;
1059
+ /** The place of the split point on the spine. */
1060
+ readonly off: number;
1061
+ /** The point where the edge joins the spine. */
1062
+ readonly merge: Point;
1063
+ /** The point where the edge leaves the spine. */
1064
+ readonly split: Point;
1065
+ /**
1066
+ * The place of this highway in the trip of the edge, from 0. An edge can go along several highways, one after the other.
1067
+ * `follow` takes the highways of an edge in the order of this value.
1068
+ */
1069
+ readonly seq: number;
1070
+ }
1071
+ /** A highway: a shared way that a bundle of edges follows, from their merge points to their split points. */
1072
+ interface Highway {
1073
+ readonly id: string;
1074
+ /** The key of the highway, for example the key of the grouping rule or the index of a cluster. */
1075
+ readonly key: string;
1076
+ /** The spine: the polyline that the edges follow, in free space. */
1077
+ readonly spine: readonly Point[];
1078
+ /** The edges in lane order. Lane 0 is on the left of the spine, from its first point to its last point. The y axis points down. */
1079
+ readonly lanes: readonly string[];
1080
+ /** The edges with their merge points and their split points, in the order of `lanes`. */
1081
+ readonly members: readonly HighwayMember[];
1082
+ }
1083
+ /** The output of a highway strategy: the highways, as data. `follow` routes the edges along them. */
1084
+ interface HighwayPlan {
1085
+ readonly highways: readonly Highway[];
1086
+ }
1087
+ /** This function gives the point at a place on a polyline. A place outside the polyline gives its nearest end. */
1088
+ export declare function pointAt(line: readonly Point[], at: number): Point;
1089
+ /** This function gives the length of a polyline from the place `from` to the place `to`, with `from` not larger than `to`. */
1090
+ export declare function lengthBetween(line: readonly Point[], from: number, to: number): number;
1091
+ /** This function gives a member of a highway with its merge point and its split point at the places `on` and `off` of the spine. */
1092
+ export declare function memberAt(spine: readonly Point[], edge: string, on: number, off: number, seq?: number): HighwayMember;
1093
+ /**
1094
+ * This function lists the problems of a plan against its graph. A good plan gives an empty list.
1095
+ * Each highway has a spine of two points or more, and two members or more. Each member is an edge of the graph, with `on` and `off` on the spine and apart.
1096
+ * An edge is a member of a highway one time at most.
1097
+ */
1098
+ export declare function checkPlan(graph: Graph, plan: HighwayPlan): string[];
1099
+ /**
1100
+ * The options of the room for the bends of the bundles (HWC-D). With them, `roomDemand` also opens the gaps where a bundle bends.
1101
+ * The values agree with the options of `highwayCurves` that draw the bundles.
1102
+ */
1103
+ interface RoomBends {
1104
+ /** The router that bundles the edges. Each segment of its routes with two or more edges is a bundle. */
1105
+ readonly router: Router;
1106
+ /** The edges that the router routes. Without them, each link gives `count` edges, with no data. */
1107
+ readonly edges?: readonly Edge[];
1108
+ /** The distance between two lanes of a bundle, as `laneWidth` of `highwayCurves`. The default is 4. */
1109
+ readonly spacing?: number;
1110
+ /** The largest width of a bundle, from its outer lane to its outer lane, as `maxWidth` of `highwayCurves`. The default is `Infinity`. */
1111
+ readonly maxWidth?: number;
1112
+ /** The smallest radius of each lane, as `minRadius` of `highwayCurves`. The default is 4. */
1113
+ readonly minRadius?: number;
1114
+ /** The number of passes of the demand of the bends. Each pass routes the board that the passes before it opened. The default is 1. */
1115
+ readonly passes?: number;
772
1116
  }
773
1117
  /** An item with a box: a node of a graph, an item of a level or a box of a host layout. */
774
1118
  export interface Boxed {
@@ -834,6 +1178,12 @@ export interface RoomOptions {
834
1178
  * The limit `maxGrowth` applies to the sum of the passes.
835
1179
  */
836
1180
  readonly passes?: number;
1181
+ /**
1182
+ * The room for the bends of the bundles (HWC-D). Without it, the default, the demand counts only the lanes of the links.
1183
+ * With it, the router of `bends` routes the open board. Each leg of a bundle that is too short for its arcs grows by a gap.
1184
+ * The limit `maxGrowth` applies to the sum of the growth of the links and of the bends.
1185
+ */
1186
+ readonly bends?: RoomBends;
837
1187
  }
838
1188
  /** The demand of a board and the board with its gaps open. */
839
1189
  export interface Room<T extends Boxed> {
@@ -856,33 +1206,192 @@ export declare function openGaps<T extends Boxed>(items: readonly T[], gaps: rea
856
1206
  * 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.
857
1207
  */
858
1208
  export declare function roomDemand(items: readonly Boxed[], links: readonly RoomLink[], options?: RoomOptions): Gap[];
1209
+ /**
1210
+ * This function adds the growth for the bends of the bundles to the need of each gap. Each pass routes the board with each gap open to its need.
1211
+ * The open board has the same gaps in the same order. So the growth of each gap adds to the need of that gap.
1212
+ */
1213
+ export declare function withBends(items: readonly Boxed[], links: readonly RoomLink[], gaps: readonly Gap[], bends: RoomBends, snap?: number): Gap[];
859
1214
  /** This function gives the demand of the board and the board with each gap open to its need. */
860
1215
  export declare function makeRoom<T extends Boxed>(items: readonly T[], links: readonly RoomLink[], options?: RoomOptions): Room<T>;
861
1216
  /** 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. */
862
1217
  export declare function roomLinks(graph: Graph): RoomLink[];
863
- /** The input of a curve strategy: one polyline and the context of its route. */
864
- export interface CurveInput {
865
- /** These points are the polyline: a route of a router, a lane of `laneRoutes` or a link of a zoom level. */
866
- readonly points: readonly Point[];
867
- /** The curve leaves the first point along this outward normal of its plug, if the strategy reads it. */
868
- readonly startNormal?: Point;
869
- /** The curve comes into the last point against this outward normal of its plug, if the strategy reads it. */
870
- readonly endNormal?: Point;
871
- /** The boxes that the curve must not go through, from `curveSpace`. */
872
- readonly space?: CurveSpace;
873
- }
874
- /** The input of a room strategy: the boxes of a board and the links between them. */
875
- export interface RoomInput {
876
- readonly items: readonly Boxed[];
877
- readonly links: readonly RoomLink[];
1218
+ /** The scale of a number option. A sweep on the scale `log` gives values with equal ratios, not with equal differences. */
1219
+ export type OptionScale = "linear" | "log";
1220
+ /** The fields of each option declaration. */
1221
+ interface OptionBase {
1222
+ /** One short sentence that tells what the option sets. The site and the documents show it. */
1223
+ readonly describe: string;
878
1224
  }
879
1225
  /**
880
- * The steps that have strategies, with the fixed input and output type of each step.
881
- *
882
- * - `group`: a graph in, the tree of sections out. The router `sections` makes its hubs and its zoom levels from this tree.
883
- * - `router`: a graph in, the routes (and the `levels`, `bundles` and `runs`) out.
884
- * - `curve`: a polyline in, the segments of a curve out.
885
- * - `room`: the boxes and links of a board in, the gaps of the board with their need out.
1226
+ * The declaration of a number option. The range from `min` to `max` is the range of a control and of a sweep.
1227
+ * The strategy can take a value outside the range. `checkOptions` reports such a value, and `clampOptions` moves it into the range.
1228
+ */
1229
+ export interface NumberOption extends OptionBase {
1230
+ /** The type `integer` takes only whole numbers. */
1231
+ readonly type: "number" | "integer";
1232
+ readonly min: number;
1233
+ readonly max: number;
1234
+ /** The grain of a control and of a sweep. A value off the step is valid. Without it, the grain is free (or 1 for an integer). */
1235
+ readonly step?: number;
1236
+ /** The scale of a control and of a sweep. The default is `linear`. The scale `log` needs a `min` above 0. */
1237
+ readonly scale?: OptionScale;
1238
+ /** These values are valid outside the range. For example, `Infinity` sets no limit. */
1239
+ readonly special?: readonly number[];
1240
+ /** These values are the notable values of the option: the default and the values of the sweeps of the benchmark. */
1241
+ readonly marks?: readonly number[];
1242
+ /** The strategy uses this value when the caller and `defaults` give no value. */
1243
+ readonly default?: number;
1244
+ }
1245
+ /** The declaration of a boolean option. */
1246
+ export interface BooleanOption extends OptionBase {
1247
+ readonly type: "boolean";
1248
+ /** The strategy uses this value when the caller and `defaults` give no value. */
1249
+ readonly default?: boolean;
1250
+ }
1251
+ /** The declaration of an option with a fixed list of string values. */
1252
+ export interface EnumOption<V extends string = string> extends OptionBase {
1253
+ readonly type: "enum";
1254
+ /** The values of the option, in the order of a control. */
1255
+ readonly values: readonly V[];
1256
+ /** The strategy uses this value when the caller and `defaults` give no value. */
1257
+ readonly default?: V;
1258
+ }
1259
+ /**
1260
+ * The declaration of an option that a control or a sweep cannot set from a range.
1261
+ * The type `function` is a rule, `strategy` is a strategy of the step `step`, `list` is an array and `object` is any other object.
1262
+ */
1263
+ export interface ValueOption<V = unknown> extends OptionBase {
1264
+ readonly type: "function" | "strategy" | "list" | "object";
1265
+ /** The step of the strategy, for the type `strategy`. A control lists the strategies of this step of a registry. */
1266
+ readonly step?: Step;
1267
+ /** The strategy uses this value when the caller and `defaults` give no value. */
1268
+ readonly default?: V;
1269
+ }
1270
+ /** The declaration of one option of any type. */
1271
+ export type AnyOption = NumberOption | BooleanOption | EnumOption | ValueOption;
1272
+ /** The declaration that fits the type of an option value: numbers, booleans, string unions or other values. */
1273
+ export type OptionDeclaration<V> = [V] extends [number] ? NumberOption : [V] extends [boolean] ? BooleanOption : [V] extends [string] ? EnumOption<V> : ValueOption<V>;
1274
+ /** The declarations of the options of a strategy. The schema has one declaration for each key of the options type, and no other key. */
1275
+ export type OptionSchema<O> = { readonly [K in keyof O]-?: OptionDeclaration<NonNullable<O[K]>>; };
1276
+ /** One problem of an option value against its declaration. */
1277
+ export interface OptionIssue {
1278
+ /** The key of the option. */
1279
+ readonly key: string;
1280
+ readonly value: unknown;
1281
+ /** The kind of the problem: no declaration, the wrong type, out of the range, not a whole number or not one of the values. */
1282
+ readonly problem: "unknown" | "type" | "range" | "integer" | "value";
1283
+ /** One sentence that tells the problem. */
1284
+ readonly message: string;
1285
+ }
1286
+ /** One setting of a sweep: a name for the rows of a table, and the options of the strategy. */
1287
+ export interface OptionSetting<O extends object> {
1288
+ /** The key and the value of each option of the setting, for example `stretch 1.5`. */
1289
+ readonly name: string;
1290
+ readonly options: Partial<O>;
1291
+ }
1292
+ /** The options of `sweepValues`, `sweepOf` and `sweepGrid`. */
1293
+ export interface SweepOptions {
1294
+ /**
1295
+ * The number of values on the range of a number option. Without it, the sweep gives the `marks` of the declaration.
1296
+ * A declaration without `marks` gets 5 values.
1297
+ */
1298
+ readonly count?: number;
1299
+ /** With `true`, a sweep of a number option on the range also gives the `special` values. The default is `false`. */
1300
+ readonly special?: boolean;
1301
+ }
1302
+ /** This function gives the declared options of a strategy, in the order of its schema, with the effective default of each one. */
1303
+ export declare function listOptions<S extends Step, O extends object>(strategy: Strategy<S, O>): {
1304
+ readonly key: keyof O & string;
1305
+ readonly declaration: AnyOption;
1306
+ readonly value: unknown;
1307
+ }[];
1308
+ /**
1309
+ * This function gives the effective default of each declared option: the value of `defaults`, else the `default` of the declaration.
1310
+ * An option without either value stays out. The strategy gives the same output with this object as with no options.
1311
+ */
1312
+ export declare function optionDefaults<S extends Step, O extends object>(strategy: Strategy<S, O>): Partial<O>;
1313
+ /**
1314
+ * This function examines option values against the schema of a strategy. It gives one issue for each key without a declaration.
1315
+ * It also gives one issue for each value of the wrong type, out of the range, not whole or not one of the values.
1316
+ * It changes no value.
1317
+ * A strategy without a schema gives no issue.
1318
+ */
1319
+ export declare function checkOptions<S extends Step, O extends object>(strategy: Strategy<S, O>, options: Partial<O>): OptionIssue[];
1320
+ /**
1321
+ * This function moves each number option into the range of its declaration, for a control. An integer option gets the nearest whole number.
1322
+ * A special value stays. The function keeps each other value as it is. `checkOptions` reports the values that this function cannot correct.
1323
+ */
1324
+ export declare function clampOptions<S extends Step, O extends object>(strategy: Strategy<S, O>, options: Partial<O>): Partial<O>;
1325
+ /**
1326
+ * This function gives the values of a sweep of one option declaration.
1327
+ * A number option gives its `marks`, or `count` values on its range and its scale. A boolean gives `false` and `true`. An enum gives its values.
1328
+ * An option of another type has no sweep, so the function throws an error.
1329
+ */
1330
+ export declare function sweepValues(declaration: AnyOption, options?: SweepOptions): unknown[];
1331
+ /**
1332
+ * This function gives the settings of a sweep of one option of a strategy, from its declaration only.
1333
+ * The name of each setting is the key and the value, for example `stretch 1.5`.
1334
+ */
1335
+ export declare function sweepOf<S extends Step, O extends object>(strategy: Strategy<S, O>, key: keyof O & string, options?: SweepOptions): OptionSetting<O>[];
1336
+ /**
1337
+ * This function gives the settings of a grid of options: each combination of the values of the sweeps of the keys.
1338
+ * The name of a setting joins the names of its values with commas, in the order of the keys.
1339
+ */
1340
+ export declare function sweepGrid<S extends Step, O extends object>(strategy: Strategy<S, O>, keys: readonly (keyof O & string)[], options?: SweepOptions): OptionSetting<O>[];
1341
+ /**
1342
+ * This function examines the schema of a strategy. It gives one message for each option of `defaults` without a declaration.
1343
+ * It also gives one message for each bad declaration, and for each value of `defaults` that does not fit its declaration.
1344
+ * A good schema gives an empty list.
1345
+ */
1346
+ export declare function checkSchema(strategy: Strategy<Step, object>): string[];
1347
+ /** The input of a curve strategy: one polyline and the context of its route. */
1348
+ export interface CurveInput {
1349
+ /** These points are the polyline: a route of a router, a lane of `laneRoutes` or a link of a zoom level. */
1350
+ readonly points: readonly Point[];
1351
+ /** The curve leaves the first point along this outward normal of its plug, if the strategy reads it. */
1352
+ readonly startNormal?: Point;
1353
+ /** The curve comes into the last point against this outward normal of its plug, if the strategy reads it. */
1354
+ readonly endNormal?: Point;
1355
+ /** The boxes that the curve must not go through, from `curveSpace`. */
1356
+ readonly space?: CurveSpace;
1357
+ /**
1358
+ * The lane of the polyline on its board, for a strategy that bends the lanes of a bundle as one. Then `points` is the route of `laneRoutes` with the index `index`.
1359
+ * The other strategies do not read it.
1360
+ */
1361
+ readonly lane?: {
1362
+ readonly board: LaneBoard;
1363
+ readonly index: number;
1364
+ };
1365
+ }
1366
+ /** The lanes of the bundles of one board: the input of `laneRoutes` and `highwayCurves`. */
1367
+ export interface LaneBoard {
1368
+ /** The shared segments and the paths of the routes, from `segmentsOf`. */
1369
+ readonly graph: SegmentGraph;
1370
+ /** The keys of the open segments, from `runKey`. Each edge of an open segment gets its own lane. */
1371
+ readonly open: ReadonlySet<string>;
1372
+ /** The distance between two lanes of an open segment. */
1373
+ readonly width: number;
1374
+ /** The largest width of an open segment, from its outer lane to its outer lane. The default is `Infinity`. */
1375
+ readonly maxWidth?: number;
1376
+ }
1377
+ /** The input of a room strategy: the boxes of a board and the links between them. */
1378
+ export interface RoomInput {
1379
+ readonly items: readonly Boxed[];
1380
+ readonly links: readonly RoomLink[];
1381
+ /**
1382
+ * The tree of sections of the items, for a strategy that gives room to each zoom level. The indices of its nodes are the indices of `items`.
1383
+ * Without it, such a strategy makes the quadtree of `buildSections`. The other strategies do not read it.
1384
+ */
1385
+ readonly sections?: Section;
1386
+ }
1387
+ /**
1388
+ * The steps that have strategies, with the fixed input and output type of each step.
1389
+ *
1390
+ * - `group`: a graph in, the tree of sections out. The router `sections` makes its hubs and its zoom levels from this tree.
1391
+ * - `router`: a graph in, the routes (and the `levels`, `bundles` and `runs`) out.
1392
+ * - `highway`: a graph and optionally its first routes in, a highway plan out. `follow` routes the edges along the plan.
1393
+ * - `curve`: a polyline in, the segments of a curve out.
1394
+ * - `room`: the boxes and links of a board in, the gaps of the board with their need out.
886
1395
  */
887
1396
  export interface StepTypes {
888
1397
  readonly group: {
@@ -893,6 +1402,10 @@ export interface StepTypes {
893
1402
  readonly input: Graph;
894
1403
  readonly output: Result;
895
1404
  };
1405
+ readonly highway: {
1406
+ readonly input: HighwayInput;
1407
+ readonly output: HighwayPlan;
1408
+ };
896
1409
  readonly curve: {
897
1410
  readonly input: CurveInput;
898
1411
  readonly output: CurveSegment[];
@@ -923,6 +1436,8 @@ export interface Strategy<S extends Step = Step, O extends object = object> {
923
1436
  readonly describe: string;
924
1437
  /** The values of the options when the caller gives no value. */
925
1438
  readonly defaults: Readonly<O>;
1439
+ /** The declarations of the options: the type, the range, the step and the meaning of each one. A strategy without it declares nothing. */
1440
+ readonly schema?: OptionSchema<O>;
926
1441
  /** The benchmark skips an input with more nodes than this. Without it, the strategy takes each input. */
927
1442
  readonly maxNodes?: number;
928
1443
  /** This method does the step. Each option that `options` does not give gets its value from `defaults`. */
@@ -937,6 +1452,8 @@ export interface StrategyDefinition<S extends Step, O extends object> {
937
1452
  readonly describe: string;
938
1453
  /** These values are the options when the caller gives no value. Give `{}` for a strategy without options. */
939
1454
  readonly defaults: O;
1455
+ /** These declarations tell the type, the range, the step and the meaning of each option. `checkSchema` examines them. */
1456
+ readonly schema?: NoInfer<OptionSchema<O>>;
940
1457
  readonly maxNodes?: number;
941
1458
  /** This function does the step. It gets each option, from the caller or from `defaults`. */
942
1459
  run(input: StepInput<S>, options: Readonly<O>): StepOutput<S>;
@@ -949,10 +1466,11 @@ export declare function defineStrategy<S extends Step, O extends object>(definit
949
1466
  /**
950
1467
  * A registry: the strategies of each step, in order. A registry is data. No import changes it.
951
1468
  * A consumer makes its own registry with `createRegistry`, and adds a strategy with `register`.
952
- * The list `group` is optional in the type, so a registry from version 0.1.5 stays a registry. `createRegistry` always gives it.
1469
+ * The lists `group` and `highway` are optional in the type, so a registry from version 0.1.5 or 0.3.0 stays a registry. `createRegistry` always gives them.
953
1470
  */
954
- export type Registry = { readonly [S in Exclude<Step, "group">]: readonly Strategy<S>[]; } & {
1471
+ export type Registry = { readonly [S in Exclude<Step, "group" | "highway">]: readonly Strategy<S>[]; } & {
955
1472
  readonly group?: readonly Strategy<"group">[];
1473
+ readonly highway?: readonly Strategy<"highway">[];
956
1474
  };
957
1475
  /** 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. */
958
1476
  export declare function createRegistry(strategies: readonly AnyStrategy[]): Registry;
@@ -971,7 +1489,7 @@ export declare function routersOf(registry: Registry): Router[];
971
1489
  /**
972
1490
  * The options of the router with sections. Each option has a default, and the defaults give the output of version 0.1.5.
973
1491
  * The options `cap`, `maxDepth` and `collapse` are the limits of the default grouping rule, the quadtree of `buildSections`.
974
- * The options `tightMargin` and `plugInset` are the limits of the level links (`levelLinks`).
1492
+ * The options `tightMargin`, `plugInset` and `throughCost` are the limits of the level links (`levelLinks`).
975
1493
  */
976
1494
  interface SectionsOptions extends LevelLinkOptions, SectionOptions {
977
1495
  /** The name in the benchmark. */
@@ -1005,6 +1523,8 @@ interface SectionsOptions extends LevelLinkOptions, SectionOptions {
1005
1523
  * The default is each depth, from 0 to the depth of the deepest section.
1006
1524
  */
1007
1525
  readonly levels?: readonly number[];
1526
+ /** The lane order of the runs. With `run`, the default, each run gets its order alone. With `bundle`, two edges keep one order on each run of their common stretch. */
1527
+ readonly laneOrder?: RunOrder;
1008
1528
  /** The benchmark skips a fixture with more nodes. */
1009
1529
  readonly maxNodes?: number;
1010
1530
  }
@@ -1030,9 +1550,18 @@ interface TrunksOptions extends WayOptions {
1030
1550
  readonly split?: number;
1031
1551
  /** A group with fewer edges stays unbundled. The default is 2. */
1032
1552
  readonly minSize?: number;
1553
+ /** The lane order of a trunk. With `bundle`, the default, the branches part in lane order. With `run`, the first leg of each branch tells the order. */
1554
+ readonly laneOrder?: RunOrder;
1555
+ /**
1556
+ * The place where each lane leaves the trunk. With `part`, the default, a lane leaves where its way parts from the ways of the other lanes.
1557
+ * A lane that turns back over the trunk leaves at an earlier point of the trunk. With `split`, each lane leaves at the split point, as in version 0.2.0.
1558
+ */
1559
+ readonly leave?: TrunkLeave;
1033
1560
  /** The benchmark skips a fixture with more nodes. */
1034
1561
  readonly maxNodes?: number;
1035
1562
  }
1563
+ /** The place where the lanes of a trunk leave it: where their ways part, or at the split point. */
1564
+ type TrunkLeave = "part" | "split";
1036
1565
  /** The rule that groups the edges by the collection of their target, in `data.collection`. */
1037
1566
  export declare const byCollection: GroupRule;
1038
1567
  /**
@@ -1086,6 +1615,58 @@ export interface GapLaneOptions {
1086
1615
  * When a move puts a link through more boxes than before, the link keeps its points.
1087
1616
  */
1088
1617
  export declare function gapLanes(items: readonly Boxed[], links: readonly LevelLink[], options?: GapLaneOptions): LevelLink[];
1618
+ /**
1619
+ * The boards of the zoom levels of `levelRoom`.
1620
+ *
1621
+ * - `shared`: each level uses the board of the nearest level. No box moves between two levels. A far level gets the area of the nearest level.
1622
+ * - `each`: each level has its own board. A far level opens only the gaps of its own links, and a nearer level adds to them.
1623
+ * Thus the items of a far level are nearer together, but a box moves in its parent when the level changes.
1624
+ */
1625
+ export type LevelBoard = "each" | "shared";
1626
+ /** The options of `levelRoom`: the options of `roomDemand` for each level, and the levels that get room. */
1627
+ export interface LevelRoomOptions extends RoomOptions {
1628
+ /** The depths of the tree that get room for their links. The default is each depth from 1 to the depth of the deepest section. */
1629
+ readonly depths?: readonly number[];
1630
+ /** With `true`, the last level, with each node alone, also gets room for the links between the nodes. The default is `false`. */
1631
+ readonly nodes?: boolean;
1632
+ /** The board of each level. The default is `shared`. */
1633
+ readonly board?: LevelBoard;
1634
+ }
1635
+ /** One zoom level of `levelRoom`: its items at their open places, its links and its demand. */
1636
+ export interface RoomLevel<T extends Boxed> {
1637
+ readonly depth: number;
1638
+ /** The items of the level, with the bounding box of their nodes at the places of this level. */
1639
+ readonly items: LevelItem[];
1640
+ /** The links between the items of the level. A link counts the links of the nodes between its two items. */
1641
+ readonly pairs: ItemPair[];
1642
+ /** The demand of the level on the board that it gets from the level before it. A level without room has no gaps. */
1643
+ readonly gaps: Gap[];
1644
+ /** The nodes at the places of this level. */
1645
+ readonly nodes: T[];
1646
+ }
1647
+ /** The room of each zoom level, and the board of the nearest level. */
1648
+ export interface LevelRoom<T extends Boxed> {
1649
+ /** The levels from depth 0 to the level with each node alone, in order. */
1650
+ readonly levels: RoomLevel<T>[];
1651
+ /** The gaps of the board of the nodes. `openGaps(nodes, gaps)` gives the nodes of the nearest level. */
1652
+ readonly gaps: Gap[];
1653
+ /** The nodes of the nearest level. */
1654
+ readonly items: T[];
1655
+ }
1656
+ /**
1657
+ * This function gives the links between the items of a level. Each pair of items gets one link, in the order of the first link of the pair.
1658
+ * The count of a link is the sum of the counts of its node links. A link inside one item does not count.
1659
+ */
1660
+ export declare function levelPairs(items: readonly LevelItem[], owner: readonly number[], indexOf: ReadonlyMap<string, number>, links: readonly RoomLink[]): ItemPair[];
1661
+ /**
1662
+ * This function gives the room of each zoom level of a tree of sections. The indices of the nodes of the tree are the indices of `nodes`.
1663
+ * The far levels open first, and each nearer level keeps their growth.
1664
+ *
1665
+ * At each level, `roomDemand` measures the links of that level on the board of the level before it. Then the nodes move with `openGaps`.
1666
+ * The nodes move by one monotone shift on each axis, so each level keeps the order and the alignment of the boxes.
1667
+ * A nearer level only adds growth, so no gap of a far level gets narrower, and a box moves with its parent.
1668
+ */
1669
+ export declare function levelRoom<T extends Boxed>(nodes: readonly T[], links: readonly RoomLink[], root: Section, options?: LevelRoomOptions): LevelRoom<T>;
1089
1670
  /** A broken hard rule. A correct router has none. */
1090
1671
  export interface Violation {
1091
1672
  readonly rule: "complete" | "ends-at-plugs" | "fixed-plugs" | "no-pass-through" | "counts-sum" | "link-ends" | "bundle-trunk" | "run-shared";
@@ -1104,6 +1685,12 @@ export declare const TOLERANCE = .5;
1104
1685
  * The function gives at most `limit` violations.
1105
1686
  */
1106
1687
  export declare function checkProperties(graph: Graph, result: Result, limit?: number): Violation[];
1688
+ /**
1689
+ * This function checks the hard rules of the zoom levels. The counts of each level add up (`counts-sum`).
1690
+ * Each link of a level starts on the box of its source and ends on the box of its target (`link-ends`).
1691
+ * The function gives at most `limit` violations.
1692
+ */
1693
+ export declare function checkLevels(graph: Graph, levels: readonly Level[], limit?: number): Violation[];
1107
1694
  /** The quality of a result. Lower is better for each value except `clearance`. */
1108
1695
  export interface Quality {
1109
1696
  /** The length of all drawn lines. A segment that several routes share counts one time. */
@@ -1160,6 +1747,13 @@ export interface LinkFaults {
1160
1747
  * A segment goes through a box when a part of it longer than `TOLERANCE` is inside the box made smaller by `TOLERANCE`.
1161
1748
  */
1162
1749
  readonly through: number;
1750
+ /**
1751
+ * The number of links of `through` that no route can keep out of the other boxes.
1752
+ * Each box that such a link goes through overlaps the box of its source or of its target, as `countOverlaps` sees it.
1753
+ */
1754
+ readonly unavoidable: number;
1755
+ /** The number of links of `through` that go through at least one box that overlaps neither end. `through` is `unavoidable` plus `avoidable`. */
1756
+ readonly avoidable: number;
1163
1757
  /**
1164
1758
  * 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.
1165
1759
  * 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.
@@ -1212,6 +1806,8 @@ export declare function goesOutAndBack(p: readonly Point[]): boolean;
1212
1806
  * The bounding box of `outside` is the bounding box of all the boxes of the map.
1213
1807
  */
1214
1808
  export declare function measureLinks(boxes: ReadonlyMap<string, Box>, links: readonly MeasuredLink[], options?: LinkFaultOptions): LinkFaults;
1809
+ /** This function tells if two boxes overlap by more than `TOLERANCE` on each axis, as `countOverlaps` counts them. */
1810
+ export declare function boxesOverlap(a: Box, b: Box): boolean;
1215
1811
  /** This function measures the faults of the routes of a result. The ends of a route are the nodes of its edge. */
1216
1812
  export declare function measureRouteFaults(graph: Graph, result: Result, options?: LinkFaultOptions): LinkFaults;
1217
1813
  /** This function counts the pairs of boxes that overlap by more than `TOLERANCE` on each axis. */
@@ -1243,11 +1839,26 @@ export interface BenchRow {
1243
1839
  readonly faults: LinkFaults;
1244
1840
  /** The faults of each zoom level with groups (`measureLevelFaults`). The list is empty for a router without levels. */
1245
1841
  readonly levelFaults: readonly LevelFaults[];
1842
+ /** The routes of this cell took longer than the cell limit. The cell did not start more routes. A row within the limit has no such field. */
1843
+ readonly overLimit?: OverLimit;
1844
+ }
1845
+ /** The record of a cell over its time limit. */
1846
+ export interface OverLimit {
1847
+ /** The cell limit, in milliseconds. */
1848
+ readonly limit: number;
1849
+ /** The number of routes that the cell finished. With one route, the cell did not check "same twice". */
1850
+ readonly runs: number;
1246
1851
  }
1247
1852
  /** The options of a benchmark run. */
1248
1853
  export interface BenchOptions {
1249
1854
  /** The number of timed routes of each fixture by each router. The default is 3. */
1250
1855
  readonly repeat?: number;
1856
+ /**
1857
+ * The time limit of one cell (one router on one fixture), in milliseconds. The default is no limit.
1858
+ * After the routes of a cell pass the limit, the cell starts no more routes, and its row gets `overLimit`.
1859
+ * A route that runs does not stop.
1860
+ */
1861
+ readonly cellLimit?: number;
1251
1862
  }
1252
1863
  /** This function routes each fixture with each router, checks the hard rules and measures the quality. */
1253
1864
  export declare function runBenchmark(routers: readonly Router[], fixtures: readonly FixtureSpec[], options?: BenchOptions): BenchRow[];
@@ -1256,15 +1867,39 @@ export declare function runBenchmark(routers: readonly Router[], fixtures: reado
1256
1867
  * because the result of a large graph can be longer than the longest string.
1257
1868
  */
1258
1869
  export declare function sameData(a: unknown, b: unknown): boolean;
1259
- /** This function routes one graph with one router and measures the result. */
1260
- export declare function benchOne(router: Router, fixture: string, graph: Graph, repeat?: number): BenchRow;
1261
- /** This function writes the rows as a Markdown table. */
1870
+ /**
1871
+ * This function routes one graph with one router and measures the result. It routes at least two times, for the rule "same twice".
1872
+ * After the routes pass `cellLimit` milliseconds, it starts no more routes and marks the row with `overLimit`.
1873
+ */
1874
+ export declare function benchOne(router: Router, fixture: string, graph: Graph, repeat?: number, cellLimit?: number): BenchRow;
1875
+ /** One run of `benchRun`: the row of the benchmark and the result that the row measures. */
1876
+ export interface BenchRun {
1877
+ readonly row: BenchRow;
1878
+ readonly result: Result;
1879
+ }
1880
+ /** This function does the work of `benchOne` and also gives the result, so more measures can read it without a second route. */
1881
+ export declare function benchRun(router: Router, fixture: string, graph: Graph, repeat?: number, cellLimit?: number): BenchRun;
1882
+ /**
1883
+ * This function puts rows in the order of one benchmark run: by fixture, then by router, each in the order of its list.
1884
+ * A name that is not in its list goes after the names of the list. Rows with the same place keep their order.
1885
+ * The workflow `Bench` uses it to join the rows of its parts.
1886
+ */
1887
+ export declare function orderRows(rows: readonly BenchRow[], routers: readonly string[], fixtures: readonly string[]): BenchRow[];
1888
+ /** This function writes the rows as a Markdown table. A cell over its limit shows "over the limit" after its time, and a dash for "same twice" when it did not check it. */
1262
1889
  export declare function formatTable(rows: readonly BenchRow[]): string;
1263
1890
  /**
1264
1891
  * This function writes the faults of the rows as a Markdown table: the routes first, then the sum of the levels with groups.
1265
1892
  * A router without such levels gets a dash in the columns of the levels.
1266
1893
  */
1267
1894
  export declare function formatFaults(rows: readonly BenchRow[]): string;
1895
+ /** A row with the faults of each zoom level, as `formatLevels` reads it: a router or a setting on one fixture. */
1896
+ export interface LevelRow {
1897
+ readonly router: string;
1898
+ readonly fixture: string;
1899
+ readonly levelFaults: readonly LevelFaults[];
1900
+ }
1901
+ /** This function writes the faults of each zoom level with groups as a Markdown table, one line for each level. */
1902
+ export declare function formatLevels(rows: readonly LevelRow[]): string;
1268
1903
  /**
1269
1904
  * One row of the benchmark of the curves: one curve type on the routes of one router on one fixture.
1270
1905
  * The type `T` of the name of the curve is `CurveType` for `benchCurves`, and `string` for `benchCurveStrategies`.
@@ -1306,6 +1941,127 @@ export declare function benchCurves(router: Router, fixture: string, graph: Grap
1306
1941
  export declare function benchCurveStrategies(router: Router, fixture: string, graph: Graph, curves: readonly Strategy<"curve">[], options?: CurveBenchOptions): CurveBenchRow<string>[];
1307
1942
  /** This function writes the rows of `benchCurves` as a Markdown table. */
1308
1943
  export declare function formatCurves(rows: readonly CurveBenchRow<string>[]): string;
1944
+ /** The options of `measureHighways`. */
1945
+ export interface HighwayMeasureOptions {
1946
+ /** The largest width of an open segment, as in `laneRoutes`. The default is 16. */
1947
+ readonly maxWidth?: number;
1948
+ /** A piece of a curve with a radius under this value counts in `underMin`. The default is 4. */
1949
+ readonly minRadius?: number;
1950
+ /** The length at each end of a segment that the spacing does not sample, for the merges and the splits. The default is 12. */
1951
+ readonly ends?: number;
1952
+ /** The free space of the board. With it, the measure counts the lanes that go through a box that their polyline avoids. */
1953
+ readonly space?: CurveSpace;
1954
+ }
1955
+ /**
1956
+ * The measures of the lanes of the open segments of a board, after a curve.
1957
+ * The spacing errors are shares of the spacing of the segment: 0.05 is 5% of the spacing.
1958
+ */
1959
+ export interface HighwayMeasures {
1960
+ /** The number of open segments with two lanes or more. */
1961
+ readonly bundles: number;
1962
+ /** The number of curves of edges in an open segment. */
1963
+ readonly lanes: number;
1964
+ /** The number of sample points of the spacing. */
1965
+ readonly samples: number;
1966
+ /** The largest spacing error at a sample point. */
1967
+ readonly worstSpacing: number;
1968
+ /** The mean spacing error of the sample points. */
1969
+ readonly meanSpacing: number;
1970
+ /** The share of the sample points with a spacing error over `SPACING_LIMIT`. */
1971
+ readonly overLimit: number;
1972
+ /** The number of points where two lanes of one open segment cross, in the body of the segment: its bends and its straight parts. */
1973
+ readonly crossings: number;
1974
+ /** The number of points where two lanes of one open segment cross near an end of the segment, in the option `ends`. These are the merges and splits. */
1975
+ readonly endCrossings: number;
1976
+ /** The number of breaks of the tangent (G1 faults) near the open segments, by more than `BREAK` radians. */
1977
+ readonly breaks: number;
1978
+ /** The smallest radius of an arc or a cubic piece near the open segments. It is `Infinity` when there is no such piece. */
1979
+ readonly minRadius: number;
1980
+ /** The number of arcs and cubic pieces near the open segments with a radius under the option `minRadius`. */
1981
+ readonly underMin: number;
1982
+ /** The number of lanes that go through a box that their polyline of `laneRoutes` avoids. */
1983
+ readonly through: number;
1984
+ }
1985
+ /** A break of the tangent larger than this angle, in radians, counts in `breaks`. */
1986
+ export declare const BREAK = .01;
1987
+ /** A spacing error over this share of the spacing counts in `overLimit`. */
1988
+ export declare const SPACING_LIMIT = .05;
1989
+ /**
1990
+ * This function measures the lanes of the open segments of a board after a curve. It measures the spacing, the crossings,
1991
+ * the breaks of the tangent, the radii and the lanes that go through a box.
1992
+ *
1993
+ * A lane is in a segment where it goes near the center line of the segment, in its direction along the segment.
1994
+ * The spacing samples each lane `spacing / 4` apart, from the middle of the first leg to the middle of the last leg.
1995
+ * It does not sample the lane in the option `ends`. The ends of a segment are for the merges and the splits.
1996
+ *
1997
+ * A sample compares the distance to the next lane with the spacing. It counts when the next lane is in the band of the segment.
1998
+ * The crossings, the breaks and the radii count along the full segment, and `ends` past each end of it.
1999
+ */
2000
+ export declare function measureHighways(graph: SegmentGraph, open: ReadonlySet<string>, laneWidth: number, curves: readonly LaneCurve[], options?: HighwayMeasureOptions): HighwayMeasures;
2001
+ /** One row of `benchHighways`: the measures of the lanes of one router on one board, after one way to curve them. */
2002
+ export interface HighwayBenchRow extends HighwayMeasures {
2003
+ readonly router: string;
2004
+ readonly fixture: string;
2005
+ /** The way to curve the lanes: `rounded` curves each lane alone, and `highway` curves the lanes of a bundle together. */
2006
+ readonly curve: "rounded" | "highway";
2007
+ /** The shape of the S curves of a row `highway`. */
2008
+ readonly jog?: JogStyle;
2009
+ /** The measures of the S curves of a row `highway`. */
2010
+ readonly jogs?: JogMeasures;
2011
+ /** The time to make all curves, in milliseconds. */
2012
+ readonly ms: number;
2013
+ }
2014
+ /** The measures of the S curves where the lanes join or leave a bundle. Each curvature is in 1 / units. */
2015
+ export interface JogMeasures {
2016
+ /** The number of S curves. */
2017
+ readonly count: number;
2018
+ /** The number of S curves that are a biarc. A polynomial S curve that does not fit on its leg is a biarc. */
2019
+ readonly biarcs: number;
2020
+ /** The median and the largest of the peak curvature of each S curve with the shape of the row. */
2021
+ readonly peakMedian: number;
2022
+ readonly peakMax: number;
2023
+ /** The median ratio of the peak curvature of each S curve of the row to the peak curvature of the same biarc S curve. */
2024
+ readonly peakRatio?: number;
2025
+ /** The largest curvature at an end of an S curve with the shape of the row. The straight leg next to it has the curvature 0, so it is the jump at the end. */
2026
+ readonly endJump: number;
2027
+ /** The largest jump of the curvature at a joint inside an S curve with the shape of the row. */
2028
+ readonly innerJump: number;
2029
+ }
2030
+ /** This function gives the peak curvature of each S curve, by lane. `jogs` has the first and the last index of each S curve in the segments of its lane. */
2031
+ export declare function jogPeaks(curves: readonly LaneCurve[], jogs: JogTrace): number[][];
2032
+ /**
2033
+ * This function gives the peak curvature of one curve, in 1 / units: the largest curvature of its lines, cubic pieces and arcs (C5 of MEAS0 as `1 / rmin`).
2034
+ * A joint with a tangent break of more than 0.5 degrees is a sharp corner, so such a curve gets `Infinity`. A curve of lines only gives 0.
2035
+ */
2036
+ export declare function peakCurvature(segments: readonly CurveSegment[]): number;
2037
+ /**
2038
+ * This function measures the S curves of the lanes that have the shape `style`. `jogs` has the first and the last index of each S curve in the segments of its lane.
2039
+ * With `biarcPeaks`, the peak curvatures of the same S curves as biarcs, it also gives the median ratio of the peaks.
2040
+ */
2041
+ export declare function measureJogs(curves: readonly LaneCurve[], jogs: JogTrace, style?: JogStyle, biarcPeaks?: readonly (readonly number[])[]): JogMeasures;
2042
+ /** The options of `benchHighways`. */
2043
+ export interface HighwayBenchOptions {
2044
+ /** The spacing of the lanes. The default is 4. */
2045
+ readonly spacing?: number;
2046
+ /** The largest width of an open segment. The default is 16. */
2047
+ readonly maxWidth?: number;
2048
+ /** The radius of each curve. The default is 12. */
2049
+ readonly radius?: number;
2050
+ /** The smallest radius of `highwayCurves`, and the limit of `underMin`. The default is 4. */
2051
+ readonly minRadius?: number;
2052
+ /** The shapes of the S curves. Each shape gives one row `highway`. The default is `["biarc"]`. */
2053
+ readonly jogs?: readonly JogStyle[];
2054
+ /** The number of cubic pieces of a `quintic` S curve. The default is 4. */
2055
+ readonly jogPieces?: number;
2056
+ }
2057
+ /**
2058
+ * This function routes a graph, opens each shared segment, and curves the lanes in two ways.
2059
+ * The row `rounded` curves each lane of `laneRoutes` alone with the curve `rounded`. Each row `highway` curves them with `highwayCurves` and one shape of S curve.
2060
+ * Both ways get the free space of the nodes.
2061
+ */
2062
+ export declare function benchHighways(router: Router, fixture: string, graph: Graph, options?: HighwayBenchOptions): HighwayBenchRow[];
2063
+ /** This function writes the rows of `benchHighways` as a Markdown table. The spacing errors are percents of the spacing. */
2064
+ export declare function formatHighways(rows: readonly HighwayBenchRow[]): string;
1309
2065
  /** One row of the benchmark of the room: one state of a board, packed or open, and the measures of its links. */
1310
2066
  export interface RoomBenchRow {
1311
2067
  readonly fixture: string;
@@ -1367,6 +2123,74 @@ export declare function laneSettings(spacings?: readonly number[], orders?: read
1367
2123
  export declare function passSettings(gutters?: readonly number[], passes?: readonly number[]): RoomSetting[];
1368
2124
  /** This function writes the rows of `benchRoom` as a Markdown table. */
1369
2125
  export declare function formatRoom(rows: readonly RoomBenchRow[]): string;
2126
+ /** One row of the benchmark of the room of the zoom levels: one level with groups of one board. */
2127
+ export interface LevelRoomRow {
2128
+ readonly fixture: string;
2129
+ /** The board: `packed`, `gutter` (each level open to the gutter only), `routes` (the room of the nodes alone), `levels` or `levels each`. */
2130
+ readonly board: string;
2131
+ readonly depth: number;
2132
+ /** The number of items of the level. */
2133
+ readonly items: number;
2134
+ /** The number of links of the level. */
2135
+ readonly links: number;
2136
+ /** The area of the bounding box of the items of the level, as a share of the area of the packed board. */
2137
+ readonly area: number;
2138
+ /** The number of level links that go through a box that is not one of their ends. */
2139
+ readonly through: number;
2140
+ /** The crossings of the level links, with a lane for each link in each gap (`gapLanes` with the order `crossings`). */
2141
+ readonly crossings: number;
2142
+ /** The crossings of the level links without lanes. The links of a gap share one line, so this count hides crossings. */
2143
+ readonly sharedCrossings: number;
2144
+ /** The mean detour of the level links. */
2145
+ readonly detour: number;
2146
+ /** The worst detour of the level links. */
2147
+ readonly worstDetour: number;
2148
+ /** The number of pairs of items of the level whose order or alignment on an axis is not the order of the packed board. */
2149
+ readonly order: number;
2150
+ /** The number of pairs of items of the level before whose order or alignment on an axis changes at this level. */
2151
+ readonly levelOrder: number;
2152
+ /**
2153
+ * The mean shift of an item against its parent from the level before, in gutters. The shift compares the place of the item in its parent
2154
+ * at this level with its place in its parent at the level before. The value 0 means that the item moves with its parent.
2155
+ */
2156
+ readonly shift: number;
2157
+ /** The largest shift of an item against its parent, in gutters. */
2158
+ readonly worstShift: number;
2159
+ /** The time to open the board of all levels, in milliseconds. It is 0 for the packed board. */
2160
+ readonly ms: number;
2161
+ }
2162
+ /**
2163
+ * This function counts the pairs of boxes whose order or alignment on an axis is not the same in `a` and in `b`.
2164
+ * The order of two boxes is the order of their left (or top) edges. The cost is quadratic in the number of boxes.
2165
+ */
2166
+ export declare function orderChanges(a: readonly Box[], b: readonly Box[], snap?: number): number;
2167
+ /**
2168
+ * This function measures the room of the zoom levels of a board. The rows of each board give each level with groups, from depth 1.
2169
+ * The boards are the packed board, the fair baseline with each level open to the gutter only, and the room of the nodes alone (`makeRoom`).
2170
+ * Then come two boards of `levelRoom` with the options. The board `levels` uses the board of the nearest level for each level.
2171
+ * The board `levels each` has a board for each level.
2172
+ *
2173
+ * The links of each level are `levelLinks` with their defaults. Each link gets a lane of `spacing` in each gap.
2174
+ */
2175
+ export declare function benchLevelRoom(fixture: string, graph: Graph, options?: LevelRoomOptions, sections?: SectionOptions): LevelRoomRow[];
2176
+ /** This function writes the rows of `benchLevelRoom` as a Markdown table. */
2177
+ export declare function formatLevelRoom(rows: readonly LevelRoomRow[]): string;
2178
+ /** One row of `benchBendRoom`: the lanes of the bundles of one router on one open board, after `highwayCurves`. */
2179
+ export interface BendRoomRow extends HighwayMeasures {
2180
+ readonly router: string;
2181
+ readonly fixture: string;
2182
+ /** The board: `room` opens the gaps for the links only, and `room + bends` also opens them for the bends of the bundles. */
2183
+ readonly board: "room" | "room + bends";
2184
+ /** The area of the bounding box of the boxes, as a share of the area of the board before the room. */
2185
+ readonly area: number;
2186
+ }
2187
+ /**
2188
+ * This function measures the room for the bends of the bundles (HWC-D). It opens the board two times with `makeRoom`, without and with the option `bends`.
2189
+ * The option `bends` gets the router and the lane options of the curves. Then the router routes each open board, and `benchHighways` curves its bundles with `highway`.
2190
+ */
2191
+ export declare function benchBendRoom(router: Router, fixture: string, graph: Graph, options?: RoomOptions): BendRoomRow[];
2192
+ /** This function writes the rows of `benchBendRoom` as a Markdown table. The spacing error is a percent of the spacing. */
2193
+ export declare function formatBendRoom(rows: readonly BendRoomRow[]): string;
1370
2194
  /** The options of one setting of the router `sections`, without the name. */
1371
2195
  export type SectionsSettingOptions = Omit<SectionsOptions, "name" | "maxNodes">;
1372
2196
  /** One setting of a sweep of the router `sections`. */
@@ -1420,6 +2244,605 @@ export declare function capSettings(values?: readonly number[]): SectionsSetting
1420
2244
  export declare function groupSettings(strategies?: readonly Strategy<"group">[], options?: Readonly<Record<string, object>>): SectionsSetting[];
1421
2245
  /** This function writes the rows of `sweepSections` as a Markdown table. */
1422
2246
  export declare function formatSections(rows: readonly SectionsBenchRow[]): string;
2247
+ /**
2248
+ * This function gives the `p` quantile of the values, with a linear step between two ranks (type 7 of Hyndman and Fan).
2249
+ * The result is `NaN` for an empty list.
2250
+ */
2251
+ export declare function quantile(values: readonly number[], p: number): number;
2252
+ /** The spread of a measure over the seeds of a fixture family. */
2253
+ export interface Spread {
2254
+ /** The number of values. */
2255
+ readonly n: number;
2256
+ readonly median: number;
2257
+ /** The `0.25` quantile. */
2258
+ readonly q1: number;
2259
+ /** The `0.75` quantile. */
2260
+ readonly q3: number;
2261
+ /** The interquartile range: `q3 - q1`. */
2262
+ readonly iqr: number;
2263
+ readonly min: number;
2264
+ readonly max: number;
2265
+ }
2266
+ /** This function gives the median, the quartiles, the interquartile range, the smallest and the largest value of a list. */
2267
+ export declare function summarize(values: readonly number[]): Spread;
2268
+ /** The largest number of values for which `kendallTau` examines each pair. Above it, the function examines a seeded sample of pairs. */
2269
+ export declare const KENDALL_EXACT = 1500;
2270
+ /**
2271
+ * This function gives the Kendall tau-b of two lists of the same length (Kendall, 1938).
2272
+ * The value is from -1 to 1. A value of 1 means the same order. A pair with a tie in both lists does not count.
2273
+ * When one list has only ties, the value is 1. Above `KENDALL_EXACT` values, a seeded sample of 200 000 pairs gives an estimate.
2274
+ */
2275
+ export declare function kendallTau(a: readonly number[], b: readonly number[], seed?: number): number;
2276
+ /**
2277
+ * This function gives the adjusted Rand index of two groupings of the same items (Hubert and Arabie, 1985).
2278
+ * The item `i` is in the group `a[i]` of the first grouping and in the group `b[i]` of the second grouping.
2279
+ * The value is 1 for the same grouping, and near 0 for a random grouping. Two groupings with one group each give 1.
2280
+ */
2281
+ export declare function adjustedRandIndex(a: readonly (string | number)[], b: readonly (string | number)[]): number;
2282
+ /** A drawn segment: a pair of points. */
2283
+ export type DrawnSegment = readonly [Point, Point];
2284
+ /**
2285
+ * This function gives the drawn segments of the routes: one segment for each distinct pair of ends.
2286
+ * A segment that several routes share is one drawn segment, as in `measureQuality`.
2287
+ */
2288
+ export declare function drawnSegments(routes: readonly Route[]): DrawnSegment[];
2289
+ /** This function gives the key of the drawn segment between two points. Two routes share a segment when they give the same key. */
2290
+ export declare function segmentKey(a: Point, b: Point): string | undefined;
2291
+ /**
2292
+ * This function gives the unit of length of a board: the median of the short sides of the boxes of the nodes.
2293
+ * A length divided by the unit has no unit, so boards of different sizes compare. The unit of a board without nodes is 1.
2294
+ */
2295
+ export declare function boardUnit(graph: Graph): number;
2296
+ /** The crossings of a set of drawn segments and their angles (R1 and R2 of MEAS0). */
2297
+ export interface CrossingAngles {
2298
+ /** The number of crossings (R1). It is the same value as `crossings` of `measureQuality`. */
2299
+ readonly crossings: number;
2300
+ /** This value is true when the values come from a sample of the segments. */
2301
+ readonly estimated: boolean;
2302
+ /** The mean angle of a crossing, divided by 90 degrees (R2). The scale is 0 to 1, and higher is better. A set without crossings gives 1. */
2303
+ readonly mean: number;
2304
+ /** The smallest angle of a crossing, in degrees from 0 to 90 (R2). Higher is better. A set without crossings gives 90. */
2305
+ readonly min: number;
2306
+ }
2307
+ /** This function gives the angle between two segments, in degrees from 0 to 90. */
2308
+ export declare function crossingAngle(a: Point, b: Point, c: Point, d: Point): number;
2309
+ /**
2310
+ * This function measures the crossings of a set of segments and their angles (R1 and R2 of MEAS0).
2311
+ * It uses the grid and the sample of `countCrossings`. Above 20 000 segments, a seeded sample of 2 000 segments gives an estimate.
2312
+ * The cost is `n log n`.
2313
+ */
2314
+ export declare function crossingAngles(segs: readonly DrawnSegment[]): CrossingAngles;
2315
+ /** The total turn of the routes (R4 of MEAS0). */
2316
+ export interface TotalTurn {
2317
+ /** The mean over the routes of `T(r) = Σ abs(φ_i) / π`, in half turns. Lower is better. */
2318
+ readonly mean: number;
2319
+ /** The largest turn at one vertex of a route, in degrees from 0 to 180. Lower is better. */
2320
+ readonly max: number;
2321
+ }
2322
+ /** This function measures the total turn of the routes (R4 of MEAS0). A path that goes straight on has 0. The cost is linear. */
2323
+ export declare function totalTurn(routes: readonly Route[]): TotalTurn;
2324
+ /** The spread of the detour of the routes (R5 of MEAS0). */
2325
+ export interface DetourSpread {
2326
+ /** The median of `δ(e) = L(r_e) / span(e)`. */
2327
+ readonly median: number;
2328
+ /** The `0.95` quantile of `δ(e)`: the tail of bad routes. */
2329
+ readonly q95: number;
2330
+ readonly mean: number;
2331
+ }
2332
+ /**
2333
+ * This function measures the spread of the detour `δ(e) = L(r_e) / span(e)` of the routes (R5 of MEAS0).
2334
+ * A route with ends nearer than 1 unit does not count. Each value is 1 or more, and lower is better. The cost is linear.
2335
+ */
2336
+ export declare function detourSpread(routes: readonly Route[]): DetourSpread;
2337
+ /** The spacing of the plugs on the sides of the boxes (R11 of MEAS0). */
2338
+ export interface PlugSpacing {
2339
+ /** The smallest spacing of a side. The scale is 0 to 1, and higher is better. A value of 1 is even spacing. */
2340
+ readonly min: number;
2341
+ /** The `0.05` quantile of the spacing of the sides. */
2342
+ readonly q05: number;
2343
+ /** The number of sides with two plugs or more. */
2344
+ readonly sides: number;
2345
+ }
2346
+ /**
2347
+ * This function measures the spacing of the plugs on each side of each box (R11 of MEAS0), the angular resolution of a box.
2348
+ * For a side with `k` distinct plugs, `ps = min gap / (side / (k + 1))`, with a limit of 1.
2349
+ * Two ends nearer than `TOLERANCE` are one plug, because a bundle shares its plug. An end farther than 1 unit from the side does not count.
2350
+ * Without a side with two plugs, each value is 1. The cost is `n log n`.
2351
+ */
2352
+ export declare function plugSpacing(graph: Graph, routes: readonly Route[]): PlugSpacing;
2353
+ /**
2354
+ * This function gives the share of the ink that shared segments save (B1 of MEAS0): `inkSaved = 1 - ink(S) / Σ_e L(r_e)`.
2355
+ * `ink(S)` counts a shared segment one time, as `measureQuality` does. The scale is 0 to 1, and higher is better. The cost is `n log n`.
2356
+ */
2357
+ export declare function inkSaved(routes: readonly Route[]): number;
2358
+ /** The ambiguity of a result (B4 of MEAS0). */
2359
+ export interface Ambiguity {
2360
+ /** The share of false neighbours, from 0 to 1. Lower is better. */
2361
+ readonly value: number;
2362
+ /** This value is true when the value comes from a sample of the nodes. */
2363
+ readonly estimated: boolean;
2364
+ }
2365
+ /** The options of `ambiguity`. */
2366
+ export interface AmbiguityOptions {
2367
+ /** Up to this number of nodes, the function examines each node. The default is 1000. */
2368
+ readonly exact?: number;
2369
+ /** Above `exact` nodes, the function examines this number of nodes from a seeded sample. The default is 2000. */
2370
+ readonly sample?: number;
2371
+ /** The seed of the sample. The default is 1. */
2372
+ readonly seed?: number;
2373
+ }
2374
+ /**
2375
+ * This function measures the ambiguity of the routes (B4 of MEAS0), with one step of neighbours.
2376
+ * `N(v)` holds the nodes whose routes share a drawn segment with a route of `v`.
2377
+ * `amb = Σ_v count(w in N(v) : no edge v-w) / Σ_v count(N(v))`. The cost is quadratic, so a seeded sample serves above `exact` nodes.
2378
+ */
2379
+ export declare function ambiguity(graph: Graph, routes: readonly Route[], options?: AmbiguityOptions): Ambiguity;
2380
+ /** A joint of a curve: the end of one drawn segment and the start of the next drawn segment. */
2381
+ export interface CurveJoint {
2382
+ readonly at: Point;
2383
+ /** The angle between the tangent at the end of the first segment and the tangent at the start of the second segment, in degrees. */
2384
+ readonly angle: number;
2385
+ /** The jump of the curvature at the joint, `abs(κ^- - κ^+)`, in 1 / units. */
2386
+ readonly jump: number;
2387
+ /** The unit tangent at the end of the first segment. */
2388
+ readonly before: Point;
2389
+ /** The unit tangent at the start of the second segment. */
2390
+ readonly after: Point;
2391
+ }
2392
+ /**
2393
+ * This function gives the joints of a curve: each point where one drawn segment ends and the next one starts.
2394
+ * A segment of length 0 has no tangent, so the joint skips it. The analytic tangents and curvatures of lines, cubic curves and arcs give the values.
2395
+ */
2396
+ export declare function curveJoints(segments: readonly CurveSegment[]): CurveJoint[];
2397
+ /**
2398
+ * This function gives the G1 defect of a curve (C1 of MEAS0): `g1 = max_j angle(T_j^-, T_j^+)` over the joints, in degrees.
2399
+ * Lower is better. A curve is G1 when `g1` is 0.5 degrees or less. The cost is linear.
2400
+ */
2401
+ export declare function g1Defect(segments: readonly CurveSegment[]): number;
2402
+ /**
2403
+ * This function gives the G2 defect of a curve (C2 of MEAS0): `g2 = max_j abs(κ_j^- - κ_j^+) · u` over the joints.
2404
+ * The value has no unit, and lower is better. `u` is the unit of the board (`boardUnit`). The cost is linear.
2405
+ */
2406
+ export declare function g2Defect(segments: readonly CurveSegment[], u: number): number;
2407
+ /**
2408
+ * This function gives the bending energy of a sampled curve (C3 of MEAS0): `E = L · ∫ κ(s)^2 ds`.
2409
+ * At each inner sample, `κ = φ / l`, so `E = L · Σ φ_i^2 / l_i`. The length `l_i` is the mean of the two legs, with a limit of `8τ / φ_i`.
2410
+ * Thus a sharp corner counts as an arc with a sagitta of `τ`, the tolerance of the samples.
2411
+ *
2412
+ * The value has no unit, and lower is better. A full circle gives `4π^2`. The cost is linear.
2413
+ */
2414
+ export declare function bendingEnergy(points: readonly Point[], tolerance?: number): number;
2415
+ /** This function tells if a polyline crosses itself. Two legs next to each other do not count. The cost is `n log n`. */
2416
+ export declare function crossesItself(p: readonly Point[]): boolean;
2417
+ /** This function tells if a polyline turns back on itself at a vertex: a turn of more than 179 degrees, as at a cusp. */
2418
+ export declare function hasCusp(p: readonly Point[]): boolean;
2419
+ /** The input of `curveFaults`: one curve and the polyline that it draws. */
2420
+ export interface CurveCheck {
2421
+ /** The polyline of the route. */
2422
+ readonly polyline: readonly Point[];
2423
+ /** The segments of the curve. */
2424
+ readonly segments: readonly CurveSegment[];
2425
+ /** The samples of the curve (`sampleCurve`). */
2426
+ readonly samples: readonly Point[];
2427
+ /** The free space of the board. Without it, the check `clear` gives false. */
2428
+ readonly space?: CurveSpace;
2429
+ /** With these normals, the check `ends` also examines the direction of the curve at its two ends. */
2430
+ readonly startNormal?: Point;
2431
+ readonly endNormal?: Point;
2432
+ /** With this value, the check `g1` examines the joints. Give it for a curve type that is G1 by its design. */
2433
+ readonly smooth?: boolean;
2434
+ }
2435
+ /** The faults of one curve: one value for each proposed hard rule of the curves in MEAS0. */
2436
+ export interface CurveFaults {
2437
+ /** `curve-clear`: the curve goes through a box that its polyline avoids (C7). */
2438
+ readonly clear: boolean;
2439
+ /** `curve-ends`: the curve misses an end of its polyline, or an end tangent is more than 1 degree off its normal (C10). */
2440
+ readonly ends: boolean;
2441
+ /** `curve-g1`: a joint has a G1 defect of more than 0.5 degrees, and it is not a corner that the free space keeps sharp (C1). */
2442
+ readonly g1: boolean;
2443
+ /** `curve-simple`: the curve crosses itself or turns back at a cusp, and its polyline does not (C9). */
2444
+ readonly simple: boolean;
2445
+ }
2446
+ /** This function checks one curve against the proposed hard rules of the curves of MEAS0. The cost is `n log n` for each curve. */
2447
+ export declare function curveFaults(c: CurveCheck): CurveFaults;
2448
+ /**
2449
+ * This function counts the faults of the nesting of the levels (Z6 of MEAS0, the proposed rule `level-nesting`).
2450
+ * It counts the items of each level whose nodes are in more than one item of the level before it. Lower is better, and 0 is correct.
2451
+ * The cost is linear.
2452
+ */
2453
+ export declare function nestingFaults(levels: readonly Level[]): number;
2454
+ /**
2455
+ * This function measures the position stability of the levels (Z7 of MEAS0).
2456
+ * `ps = mean_(v,d) dist(center(item_d(v)), center(item_(d+1)(v))) / size(item_d(v))`, with `size` the longer side of the box.
2457
+ * The value has no unit, and lower is better. A result with one level gives 0. The cost is linear.
2458
+ */
2459
+ export declare function positionStability(levels: readonly Level[]): number;
2460
+ /**
2461
+ * This function measures the order stability of the levels with groups (Z8 of MEAS0).
2462
+ * For each level, `τ_x` and `τ_y` are the Kendall tau between the item centers and the centroids of their nodes on each axis.
2463
+ * The value is the mean of `(τ_x + τ_y) / 2` over the levels with groups and two items or more. The scale is -1 to 1, and higher is better.
2464
+ * A result without such a level gives 1. The cost is `n log n`, with a sample above 1500 items.
2465
+ */
2466
+ export declare function orderStability(graph: Graph, levels: readonly Level[]): number;
2467
+ /** A grouping of the nodes: a map from the id of each node to the id of its group. */
2468
+ export type Grouping = ReadonlyMap<string, string>;
2469
+ /** This function gives the grouping of one level: each node goes to the id of its item. */
2470
+ export declare function levelGrouping(level: Level): Map<string, string>;
2471
+ /** This function gives the far view of a result: the first level with more than one item, in the order of depth. */
2472
+ export declare function farLevel(levels: readonly Level[]): Level | undefined;
2473
+ /**
2474
+ * This function gives the modularity of a grouping (G1 of MEAS0, Newman and Girvan, 2004).
2475
+ * `Q = Σ_c (e_c / m - (d_c / (2m))^2)`, with `e_c` the edges inside `c` and `d_c` the sum of the degrees in `c`.
2476
+ * The scale is -0.5 to 1, and higher is better. A node without a group is a group alone. The cost is linear.
2477
+ */
2478
+ export declare function modularity(graph: Graph, groups: Grouping): number;
2479
+ /**
2480
+ * This function gives the cut share of a grouping (G2 of MEAS0): the share of the edges between two groups.
2481
+ * For the grouping of a level, it is the sum of the counts of the links of the level, divided by `m`. The scale is 0 to 1, and lower is better.
2482
+ */
2483
+ export declare function cutShare(graph: Graph, groups: Grouping): number;
2484
+ /**
2485
+ * This function gives the balance of one level (G6 of MEAS0): `H(s) / log(k)`, with `s` the shares of the nodes of the `k` items and `H` the entropy.
2486
+ * The scale is 0 to 1, and higher is better. A value of 1 is items of equal size. A level with one item gives 1.
2487
+ */
2488
+ export declare function balance(level: Level): number;
2489
+ /**
2490
+ * This function gives the tree cost of the levels (G8 of MEAS0, Dasgupta, 2016): `D = Σ_(u,v) leaves(lca(u, v)) / (m n)`.
2491
+ * The levels make the tree. `leaves(lca(u, v))` is the number of nodes of the deepest item that holds both ends.
2492
+ * Without such an item, the value is `n`. The scale is 0 to 1, and lower is better. The cost is linear times the depth.
2493
+ */
2494
+ export declare function treeCost(graph: Graph, levels: readonly Level[]): number;
2495
+ /** This function gives the leaf of each node in a tree of sections: the id of the leaf, by the index of the node. */
2496
+ export declare function leafGroups(root: Section, count: number): string[];
2497
+ /**
2498
+ * This function gives the group stability of two trees of the same nodes (G9 of MEAS0): the adjusted Rand index of their leaves.
2499
+ * The second tree comes from the graph after a small change (`changeGraph`). The scale is -1 to 1, and higher is better.
2500
+ */
2501
+ export declare function groupStability(before: Section, after: Section, count: number): number;
2502
+ /** A small change of a graph, for the stability measures Z10 and G9 of MEAS0. */
2503
+ export interface GraphChange {
2504
+ /** The graph after the change. It keeps the order of the nodes. */
2505
+ readonly graph: Graph;
2506
+ /** The node that moved by one unit, if a free place was found. */
2507
+ readonly moved?: string;
2508
+ /** The new edge, if the graph has two nodes without an edge between them. */
2509
+ readonly added?: string;
2510
+ /** The edge that the change removed. */
2511
+ readonly removed?: string;
2512
+ }
2513
+ /**
2514
+ * This function makes a seeded small change of a graph: one node moves by `boardUnit`, one edge goes and one new edge comes.
2515
+ * The moved box keeps a gap of 4 units to the other boxes. The same graph and the same seed give the same change.
2516
+ */
2517
+ export declare function changeGraph(graph: Graph, seed: number): GraphChange;
2518
+ /** The route stability of a router (Z10 of MEAS0). */
2519
+ export interface RouteStability {
2520
+ /** The mean Fréchet distance between the two routes of an edge, divided by the unit of the board. */
2521
+ readonly mean: number;
2522
+ /** The largest Fréchet distance, divided by the unit of the board. */
2523
+ readonly max: number;
2524
+ /** The share of the routes that moved more than 1 unit of length. */
2525
+ readonly moved: number;
2526
+ }
2527
+ /** The options of `routeStability`. */
2528
+ export interface RouteStabilityOptions {
2529
+ /** Above this number of routes, a seeded sample of this size serves. The default is 2000. */
2530
+ readonly sample?: number;
2531
+ readonly seed?: number;
2532
+ }
2533
+ /**
2534
+ * This function measures the route stability of a router (Z10 of MEAS0) with `measureStability`.
2535
+ * It compares the routes of the edges that both results have. Each distance is divided by the unit of the board.
2536
+ * The cost is quadratic for each route, so a seeded sample serves above `sample` routes.
2537
+ */
2538
+ export declare function routeStability(graph: Graph, before: Result, after: Result, options?: RouteStabilityOptions): RouteStability;
2539
+ /**
2540
+ * This function counts the pairs of boxes whose order or alignment changes on an axis (M2 of MEAS0, the proposed rule `room-order`).
2541
+ * On each axis, it compares the order of the low edges, the order of the high edges, and the relation "a ends before b starts".
2542
+ * Two values nearer than `snap` are equal. Lower is better, and 0 is correct. Above 2000 boxes, a seeded sample of pairs gives an estimate.
2543
+ */
2544
+ export declare function roomOrderFaults(before: readonly Boxed[], after: readonly Boxed[], snap?: number): number;
2545
+ /** One axis of a Pareto front: the key of a measure and the direction that is better. */
2546
+ export interface Objective {
2547
+ readonly key: string;
2548
+ /** `min`: lower is better. `max`: higher is better. */
2549
+ readonly better: "min" | "max";
2550
+ }
2551
+ /**
2552
+ * This function tells if the values `a` dominate the values `b`: `a` is no worse on each objective and better on one objective.
2553
+ * A missing value or `NaN` is the worst value.
2554
+ */
2555
+ export declare function dominates(a: Readonly<Record<string, number>>, b: Readonly<Record<string, number>>, objectives: readonly Objective[]): boolean;
2556
+ /**
2557
+ * This function gives the Pareto front of a list: the items that no other item dominates (MEAS0, "Pareto fronts").
2558
+ * The function `values` gives the measures of an item. The front keeps the order of the list. The cost is quadratic in the items.
2559
+ */
2560
+ export declare function paretoFront<T>(items: readonly T[], values: (item: T) => Readonly<Record<string, number>>, objectives: readonly Objective[]): T[];
2561
+ /** The names of the proposed hard rules of MEAS0. The suite counts them. It does not apply them as rules yet. */
2562
+ export declare const PROPOSED_RULES: readonly string[];
2563
+ /** The options of `runSuite`. */
2564
+ export interface SuiteOptions {
2565
+ /** The largest fixture, in nodes. The default is 1000. */
2566
+ readonly max?: number;
2567
+ /** The number of seeds of each fixture family. The default is 5. The first seed is the seed of the fixture. */
2568
+ readonly seeds?: number;
2569
+ /** A fixture family or a room family with more nodes than this number gets one seed only. The default is 1000. */
2570
+ readonly seedsMaxNodes?: number;
2571
+ /** The number of timed routes of the first seed. The other seeds route two times, for the rule "same twice". The default is 3. */
2572
+ readonly repeat?: number;
2573
+ /** The route stability (Z10) routes a changed graph again, so the suite measures it only up to this number of nodes. The default is 1000. */
2574
+ readonly stabilityMax?: number;
2575
+ /** The step `curve` draws the routes of the fixtures up to this number of nodes. The default is 1000. */
2576
+ readonly curveMax?: number;
2577
+ /** The router whose routes the step `curve` draws. The default is `corners`. */
2578
+ readonly curveRouter?: string;
2579
+ /** The curve strategies that are G1 by their design. The rule `curve-g1` examines them. The default is `rounded`, `arc`, `spline`, `smooth`, `clothoid` and `highway`. */
2580
+ readonly smoothCurves?: readonly string[];
2581
+ /** The curve strategies that read the normals of the plugs. The rule `curve-ends` examines their end tangents. The default is `spline`. */
2582
+ readonly normalCurves?: readonly string[];
2583
+ /** The strategies of each step. The default is the registry of the built-in strategies. */
2584
+ readonly registry?: Registry;
2585
+ /** The fixtures of the families of the steps `router`, `curve` and `group`. The default is `FIXTURES`. */
2586
+ readonly fixtures?: readonly FixtureSpec[];
2587
+ /** The families of the step `room`. The default is `ROOM_FAMILIES`. */
2588
+ readonly roomFamilies?: readonly RoomFamily[];
2589
+ /** The names of the routers of the step `router`. The default is each router of the registry. */
2590
+ readonly routers?: readonly string[];
2591
+ /** The steps that the suite runs. The default is each step. Each part of the workflow `Bench` runs some steps only. The step `curve` needs the step `router`. */
2592
+ readonly steps?: readonly Step[];
2593
+ /** The time limit of one cell of the step `router`, in milliseconds, as `BenchOptions.cellLimit` gives it. The default is no limit. */
2594
+ readonly cellLimit?: number;
2595
+ /** This function gets one line of progress for each fixture and seed. */
2596
+ readonly log?: (line: string) => void;
2597
+ }
2598
+ /** A family of packed boards for the step `room`: `packedGridBoard` with a seed for each member. */
2599
+ export interface RoomFamily {
2600
+ readonly name: string;
2601
+ readonly cols: number;
2602
+ readonly rows: number;
2603
+ /** The number of long links. */
2604
+ readonly long: number;
2605
+ }
2606
+ /** The families of the step `room`: the board of ROOM, and a board of 1000 boxes. */
2607
+ export declare const ROOM_FAMILIES: readonly RoomFamily[];
2608
+ /** One row of the suite: one strategy of one step on one member of a fixture family. */
2609
+ export interface SuiteRow {
2610
+ readonly step: Step;
2611
+ /** The name of the fixture family. */
2612
+ readonly fixture: string;
2613
+ /** The index of the seed in the family, from 0. */
2614
+ readonly seed: number;
2615
+ readonly strategy: string;
2616
+ readonly nodes: number;
2617
+ readonly edges: number;
2618
+ /**
2619
+ * The violations of the hard rules of today. The step `router` checks `checkProperties` and "same twice".
2620
+ * The step `group` checks `checkSections` and the rules of the levels (`checkLevels`).
2621
+ */
2622
+ readonly violations: number;
2623
+ /** The time of the step and of the measures of today, in milliseconds. */
2624
+ readonly ms: number;
2625
+ /** The time of the new measures of MEAS1, without the extra runs, in milliseconds. */
2626
+ readonly measureMs: number;
2627
+ /** The time of the extra routes of the stability measures (Z10 and G9), in milliseconds. */
2628
+ readonly extraMs: number;
2629
+ /** The time of the grouping rule alone, without the router, in milliseconds. Only the rows of the step `group` have it. */
2630
+ readonly treeMs?: number;
2631
+ /** The measures, by a key that starts with the id of MEAS0, or the name of a proposed rule. */
2632
+ readonly values: Readonly<Record<string, number>>;
2633
+ }
2634
+ /** The spread of each measure of one strategy on one fixture family, over the seeds. */
2635
+ export interface SuiteSummary {
2636
+ readonly step: Step;
2637
+ readonly fixture: string;
2638
+ readonly strategy: string;
2639
+ readonly nodes: number;
2640
+ readonly seeds: number;
2641
+ /** The sum of the violations over the seeds. */
2642
+ readonly violations: number;
2643
+ readonly measures: Readonly<Record<string, Spread>>;
2644
+ }
2645
+ /** The Pareto front of one step on one fixture family, over the medians of the seeds. */
2646
+ export interface SuiteFront {
2647
+ readonly step: Step;
2648
+ readonly fixture: string;
2649
+ readonly nodes: number;
2650
+ readonly objectives: readonly Objective[];
2651
+ /** The strategies on the front, in the order of the registry. */
2652
+ readonly front: readonly string[];
2653
+ /** The strategies with a violation of a hard rule. They do not enter the front. */
2654
+ readonly excluded: readonly string[];
2655
+ /** Each strategy that the front compares. */
2656
+ readonly strategies: readonly string[];
2657
+ }
2658
+ /** The count of one proposed hard rule for one strategy, over each fixture and each seed. */
2659
+ export interface RuleCount {
2660
+ readonly step: Step;
2661
+ readonly strategy: string;
2662
+ readonly rule: string;
2663
+ readonly count: number;
2664
+ }
2665
+ /** The report of the suite. The workflow `Bench` keeps it as an artifact. */
2666
+ export interface SuiteReport {
2667
+ readonly options: {
2668
+ readonly max: number;
2669
+ readonly seeds: number;
2670
+ readonly seedsMaxNodes: number;
2671
+ readonly repeat: number;
2672
+ readonly stabilityMax: number;
2673
+ readonly curveMax: number;
2674
+ readonly curveRouter: string;
2675
+ };
2676
+ readonly rows: readonly SuiteRow[];
2677
+ readonly summaries: readonly SuiteSummary[];
2678
+ readonly fronts: readonly SuiteFront[];
2679
+ readonly rules: readonly RuleCount[];
2680
+ }
2681
+ /** The axes of the Pareto front of each step. The note MEAS0 asks for two to four scores. */
2682
+ export declare const FRONT_OBJECTIVES: Readonly<Record<Step, readonly Objective[]>>;
2683
+ /** This function gives the seed of the member `k` of the family of a fixture. The member 0 is the fixture itself. */
2684
+ export declare function familySeed(spec: FixtureSpec, k: number): number;
2685
+ /** This function gives the measures of the levels of a result: Z6, Z7, Z8, and G1, G2 and G8 of the far view. A result without groups gives none. */
2686
+ export declare function levelMeasures(graph: Graph, result: Result): Record<string, number>;
2687
+ /** This function gives the new measures of the routes of a result (MEAS1). The row of `benchRun` gives the values of today. */
2688
+ export declare function routeMeasures(graph: Graph, result: Result, row: BenchRow): Record<string, number>;
2689
+ /** The options of `curveRuns`. */
2690
+ export interface CurveRunOptions {
2691
+ /** The name of the fixture family, for the rows. */
2692
+ readonly fixture: string;
2693
+ /** The index of the seed in the family, for the rows. */
2694
+ readonly seed: number;
2695
+ /** The curve strategies that are G1 by their design. The rule `curve-g1` examines them. */
2696
+ readonly smooth: ReadonlySet<string>;
2697
+ /** The curve strategies that read the normals of the plugs. The rule `curve-ends` examines their end tangents. */
2698
+ readonly normals: ReadonlySet<string>;
2699
+ /** The options of each curve strategy, by its name. A strategy without an entry gets its defaults. */
2700
+ readonly curveOptions?: Readonly<Record<string, object>>;
2701
+ /**
2702
+ * With this board, each curve draws the lanes of `laneRoutes` in place of the routes of the result, and each input has its `lane`.
2703
+ * So the curve `highway` bends the lanes of a bundle as one. Without it, each curve draws the routes of the result.
2704
+ */
2705
+ readonly lanes?: LaneBoard;
2706
+ }
2707
+ /** One curve strategy on the routes of one result: the row of the suite and the drawn curves. */
2708
+ export interface CurveRun {
2709
+ readonly row: SuiteRow;
2710
+ /** The segments of each curve, in the order of the routes that have two points or more. */
2711
+ readonly drawn: readonly CurveSegment[][];
2712
+ /** The edge of each curve of `drawn`. */
2713
+ readonly edges: readonly string[];
2714
+ }
2715
+ /** This function draws the routes of a result with each curve strategy and measures the curves (C1, C2, C3, C6 and the curve rules). */
2716
+ export declare function curveRuns(graph: Graph, result: Result, curves: readonly Strategy<"curve">[], options: CurveRunOptions): CurveRun[];
2717
+ /** One grouping rule on one graph: the row of the suite, the tree of the rule and the result of `sections` on that tree. */
2718
+ export interface GroupRun {
2719
+ readonly row: SuiteRow;
2720
+ readonly tree: Section;
2721
+ /** The result of the router `sections` with the tree of the rule. A tree that `checkSections` refuses gives no result. */
2722
+ readonly result?: Result;
2723
+ }
2724
+ /**
2725
+ * This function groups one graph with one grouping rule, routes it with the router `sections` on that tree, and measures the levels.
2726
+ * The grouping of the changed graph gives the group stability (G9). `options` are the options of the rule on `graph`.
2727
+ */
2728
+ export declare function groupRun(graph: Graph, strategy: Strategy<"group">, options: object, change: {
2729
+ readonly graph: Graph;
2730
+ readonly options: object;
2731
+ }, at: {
2732
+ readonly fixture: string;
2733
+ readonly seed: number;
2734
+ }): GroupRun;
2735
+ /**
2736
+ * This function gives the options of a grouping rule on a fixture. The rule `keys` gets the string `data.group` of the node.
2737
+ * A node without it gets a key from the data of the edges: the collection of the first edge into the node. A node without such an edge is a group alone.
2738
+ */
2739
+ export declare function fixtureGroupOptions(strategy: string, graph: Graph): object;
2740
+ /**
2741
+ * This function starts the measure suite of MEAS1. The suite measures each strategy of each step on each seed of each fixture family.
2742
+ * The step `router` keeps the rows of today in `bench` for the first seed, so the tables of the benchmark stay the same.
2743
+ */
2744
+ export declare function runSuite(options?: SuiteOptions): {
2745
+ report: SuiteReport;
2746
+ bench: BenchRow[];
2747
+ };
2748
+ /**
2749
+ * This function puts the rows of the suite in the order of one run. It sorts them by fixture family, then by seed.
2750
+ * In one seed, the routers come first, and the curves come after the router of the curves. Then the highway strategies come, and the grouping rules and the room come last.
2751
+ * A name that is not in its list goes after the names of the list.
2752
+ * The workflow `Bench` uses it to join the reports of its parts.
2753
+ */
2754
+ export declare function orderSuiteRows(rows: readonly SuiteRow[], options?: {
2755
+ registry?: Registry;
2756
+ fixtures?: readonly FixtureSpec[];
2757
+ roomFamilies?: readonly RoomFamily[];
2758
+ curveRouter?: string;
2759
+ }): SuiteRow[];
2760
+ /**
2761
+ * This function joins the reports of the parts of one benchmark into one report. It puts the rows in the order of one run.
2762
+ * Then it calculates the summaries, the fronts and the rule counts again from all the rows.
2763
+ */
2764
+ export declare function joinReports(reports: readonly SuiteReport[], options?: {
2765
+ registry?: Registry;
2766
+ fixtures?: readonly FixtureSpec[];
2767
+ roomFamilies?: readonly RoomFamily[];
2768
+ }): SuiteReport;
2769
+ /** This function gives the spread of each measure of each strategy on each fixture family, over the seeds. It keeps the order of the rows. */
2770
+ export declare function summarizeRows(rows: readonly SuiteRow[]): SuiteSummary[];
2771
+ /**
2772
+ * This function gives the Pareto front of each step on each fixture family, over the medians of the seeds.
2773
+ * A strategy with a violation of a hard rule does not enter the front, as MEAS0 asks.
2774
+ */
2775
+ export declare function suiteFronts(summaries: readonly SuiteSummary[], objectives?: Readonly<Record<Step, readonly Objective[]>>): SuiteFront[];
2776
+ /** This function sums each proposed hard rule of MEAS0 for each strategy of each step, over each fixture and each seed. */
2777
+ export declare function ruleCounts(rows: readonly SuiteRow[]): RuleCount[];
2778
+ /** The columns of the tables of `formatSuite`: the keys of the measures of each step. */
2779
+ export declare const SUITE_COLUMNS: Readonly<Record<Step, readonly string[]>>;
2780
+ /**
2781
+ * This function writes the summaries of one step as a Markdown table. Each cell is the median over the seeds, with the interquartile range in brackets.
2782
+ * The column `R1 IQR/median` gives the spread of the crossings.
2783
+ */
2784
+ export declare function formatSummaries(summaries: readonly SuiteSummary[], step: Step, columns?: readonly string[]): string;
2785
+ /** This function writes the Pareto fronts as a Markdown table. */
2786
+ export declare function formatFronts(fronts: readonly SuiteFront[]): string;
2787
+ /** This function writes the counts of the proposed hard rules as a Markdown table: one row for each step and strategy. */
2788
+ export declare function formatRules(rules: readonly RuleCount[]): string;
2789
+ /**
2790
+ * This function compares the time of the new measures with the time of the step and the measures of today.
2791
+ * It gives one row for each fixture family of a step. The extra routes of the stability measures have their own column.
2792
+ */
2793
+ export declare function formatMeasureTime(rows: readonly SuiteRow[], step?: Step): string;
2794
+ /**
2795
+ * The options of the highway strategy `corridors` (HWY-031 of the note on highways).
2796
+ * The options `margin` and `k` set the corner graph of the first ways, when the input has no first routes.
2797
+ */
2798
+ interface CorridorOptions extends Pick<WayOptions, "margin" | "k"> {
2799
+ /** Two edges join when their common links are this share of the shorter way, or longer. The default is 0.3. */
2800
+ readonly rho: number;
2801
+ /** A highway has this number of edges or more. The default is 2. */
2802
+ readonly minSize: number;
2803
+ /** The number of hash functions of the MinHash signature of a way. The default is 64. */
2804
+ readonly hashes: number;
2805
+ /** The number of bands of the signature. Two ways with one equal band are a candidate pair. The default is 32. */
2806
+ readonly bands: number;
2807
+ /** Two link ends nearer than this grid size are one point. With 0, the default, only equal points are one point. */
2808
+ readonly near: number;
2809
+ /** The gap between two lanes. Two edges join only when their common links are longer than the break-even overlap for this gap. The default is 4. */
2810
+ readonly lane: number;
2811
+ }
2812
+ /** The default options of the strategy `corridors`. */
2813
+ export declare const CORRIDOR_DEFAULTS: Readonly<Required<Omit<CorridorOptions, "margin" | "k">>>;
2814
+ /**
2815
+ * The break-even overlap of two parallel edges for each unit of the lane gap, with the cost exponent 0.5 of the note.
2816
+ * A shared stretch shorter than this times the gap adds ink.
2817
+ */
2818
+ export declare const BREAK_EVEN: number;
2819
+ /** This function gives the MinHash signature of a set of keys with `count` hash functions. */
2820
+ export declare function minHash(keys: Iterable<string>, count: number): number[];
2821
+ /**
2822
+ * This function gives the highways of corridor signatures (HWY-031). Each edge gets a first way: the route of `input.routes`, or its way through the corner graph.
2823
+ * The signature of a way is the set of its links. Two edges join when their common links are at least `rho` times the shorter way, and longer than the break-even overlap.
2824
+ * MinHash with `hashes` hash functions in `bands` bands finds the candidate pairs fast. Union-find gives the clusters.
2825
+ *
2826
+ * In each cluster, the spine is the longest common run of links of the way with the most shared length. Each edge on the spine joins it at its first common link and leaves it at its last one.
2827
+ * The edges of the cluster that are not on the spine make the next highway, while `minSize` of them remain.
2828
+ */
2829
+ export declare function corridorPlan(input: HighwayInput, o: Readonly<CorridorOptions>): HighwayPlan;
2830
+ /** The options of the highway strategy `keys`: the options of the router `trunks`, without the name and the limit of the benchmark. */
2831
+ type KeysOptions = Omit<TrunksOptions, "name" | "maxNodes">;
2832
+ /**
2833
+ * This function gives the highways that the router `trunks` decides. A rule gives each edge a key.
2834
+ * The edges from one plug with one key share a trunk to a split point. The edges that go on together share a run past it.
2835
+ * Each trunk and each run becomes one highway. The function does not change the router: it reads its bundles and its runs.
2836
+ */
2837
+ export declare function keysPlan(input: HighwayInput, options: KeysOptions): HighwayPlan;
2838
+ /** The options of the highway strategy `shared-ways`: the options of the router `shared`, without the name and the limit of the benchmark. */
2839
+ type SharedWaysOptions = Omit<SharedOptions, "name" | "maxNodes">;
2840
+ /**
2841
+ * This function gives the highways that the router `shared` decides. The edges of one key go one by one through the corner graph.
2842
+ * A link that the key uses already costs less, so the ways of a key come together. Each stretch that two edges or more share becomes one highway.
2843
+ * The function does not change the router: it reads its runs.
2844
+ */
2845
+ export declare function sharedWaysPlan(input: HighwayInput, options: SharedWaysOptions): HighwayPlan;
1423
2846
  /** The options of a router strategy: the options of its router, without the name and the limit of the benchmark. */
1424
2847
  export type RouterPreset<O> = Omit<O, "name" | "maxNodes">;
1425
2848
  /** The built-in router strategies, in the order of the benchmark. They route as the routers of `ROUTERS`. */
@@ -1444,28 +2867,672 @@ export interface TensionOptions {
1444
2867
  /** The tension of the spline, from 0 (the spline) to 1 (the polyline). The default is 0. */
1445
2868
  readonly tension: number;
1446
2869
  }
1447
- /** The built-in curve strategies, in the order of `CURVE_TYPES`. Each one gives the same segments as `curveOf` with its type. */
2870
+ /**
2871
+ * The options of the curve strategy `highway`. The options `minRadius`, `jog` and `jogPieces` change only the lanes of a bundle.
2872
+ * So they change the curve only when the input has a `lane` on a board with open segments.
2873
+ */
2874
+ export interface HighwayStrategyOptions {
2875
+ /** The radius of the center line of a bundle at a bend, and of each lone corner. The default is 12. */
2876
+ readonly radius: number;
2877
+ /** The smallest radius of a lane at a bend of a bundle. The default is 4. */
2878
+ readonly minRadius: number;
2879
+ /** The shape of the S curve where a lane changes its offset. The default is `biarc`. */
2880
+ readonly jog: JogStyle;
2881
+ /** The number of cubic pieces of a `quintic` S curve. The default is 4. */
2882
+ readonly jogPieces: number;
2883
+ }
2884
+ /** The options of the curve strategy `smooth`. */
2885
+ export interface SmoothStrategyOptions {
2886
+ /** The radius of the arc of each corner. The default is 12. */
2887
+ readonly radius: number;
2888
+ /** The share of the turn of a corner in its two spirals, from 0 to 1. The default is 0.6. */
2889
+ readonly smoothing: number;
2890
+ }
2891
+ /** The options of the curve strategy `clothoid`. */
2892
+ export interface ClothoidStrategyOptions {
2893
+ /** The radius of the arc of each corner. The default is 12. */
2894
+ readonly radius: number;
2895
+ /** The share of the turn of a corner in its two clothoids, from 0 to 1. The default is 0.5. */
2896
+ readonly spiral: number;
2897
+ /** The largest distance from the cubic pieces to the true clothoid. The default is 0.25. */
2898
+ readonly tolerance: number;
2899
+ }
2900
+ /**
2901
+ * The built-in curve strategies. The first six are in the order of `CURVE_TYPES`, and each one gives the same segments as `curveOf` with its type.
2902
+ * The strategy `highway` gives the curve of `arc` for one polyline. For a polyline with a `lane`, it bends the lanes of each bundle as one with `highwayCurves`.
2903
+ */
1448
2904
  export declare const curveStrategies: {
1449
2905
  readonly straight: Strategy<"curve", object>;
1450
2906
  readonly rounded: Strategy<"curve", RadiusOptions>;
1451
2907
  readonly spline: Strategy<"curve", TensionOptions>;
1452
2908
  readonly arc: Strategy<"curve", RadiusOptions>;
2909
+ readonly smooth: Strategy<"curve", SmoothStrategyOptions>;
2910
+ readonly clothoid: Strategy<"curve", ClothoidStrategyOptions>;
2911
+ readonly highway: Strategy<"curve", HighwayStrategyOptions>;
1453
2912
  };
1454
2913
  /** The options of a room strategy: the options of `roomDemand`, without the method. */
1455
2914
  export type RoomPreset = Omit<RoomOptions, "method">;
1456
- /** The built-in room strategies: the methods of `roomDemand`. */
2915
+ /** The options of the room strategy `levels`: the options of `levelRoom` without the method, and the limits of the quadtree. */
2916
+ export type LevelRoomPreset = Omit<LevelRoomOptions, "method"> & SectionOptions;
2917
+ /** The built-in room strategies: the methods of `roomDemand`, and the room of each zoom level (`levelRoom`). */
1457
2918
  export declare const roomStrategies: {
1458
2919
  readonly routes: Strategy<"room", RoomPreset>;
1459
2920
  readonly lines: Strategy<"room", RoomPreset>;
2921
+ readonly levels: Strategy<"room", LevelRoomPreset>;
1460
2922
  };
1461
2923
  /** The built-in grouping rules: the strategies of the step `group`. The router `sections` makes its hubs and its zoom levels from their tree. */
1462
2924
  export declare const groupStrategies: {
1463
2925
  readonly quadtree: Strategy<"group", Required<SectionOptions>>;
1464
2926
  readonly keys: Strategy<"group", KeyOptions>;
2927
+ readonly kd: Strategy<"group", Required<KdOptions>>;
2928
+ readonly cut: Strategy<"group", Required<CutOptions>>;
2929
+ };
2930
+ /**
2931
+ * The built-in highway strategies: the decisions of the routers `trunks` and `shared` as plans, and corridor signatures (HWY-031).
2932
+ * `follow` routes the edges along a plan, and `highwayRouter` gives a router that does both.
2933
+ */
2934
+ export declare const highwayStrategies: {
2935
+ readonly keys: Strategy<"highway", KeysOptions>;
2936
+ readonly "shared-ways": Strategy<"highway", SharedWaysOptions>;
2937
+ readonly corridors: Strategy<"highway", CorridorOptions>;
1465
2938
  };
1466
2939
  /** The built-in strategies of each step, in order. A consumer adds its own: `createRegistry([...BUILT_IN_STRATEGIES, mine])`. */
1467
2940
  export declare const BUILT_IN_STRATEGIES: readonly AnyStrategy[];
1468
2941
  /** The registry of the built-in strategies. The benchmark and the site take their lists from it. */
1469
2942
  export declare const STRATEGIES: Registry;
1470
- export type { ArcOptions, CornersOptions, CurveSpace, KeyOptions, NodeKey, RoundedOptions, SectionsOptions, SharedOptions, SplineOptions, TrunksOptions };
2943
+ /**
2944
+ * The steps that `compareStep` compares. The step `room` takes a packed board, not a graph, so it is not in the list.
2945
+ * The step `highway` gives a plan, not routes. The screen routes each plan with `follow` and compares it as a router.
2946
+ */
2947
+ export type CompareStep = Exclude<Step, "room" | "highway">;
2948
+ /** The steps that `compareStep` compares, in the order of the pipeline. */
2949
+ export declare const COMPARE_STEPS: readonly CompareStep[];
2950
+ /** The options of `compareStep`. */
2951
+ export interface CompareOptions {
2952
+ /** The strategies of each step. The default is the registry of the built-in strategies. */
2953
+ readonly registry?: Registry;
2954
+ /** The options of each strategy of the step, by its name. A strategy without an entry gets its defaults. */
2955
+ readonly options?: Readonly<Record<string, object>>;
2956
+ /** The router whose routes the step `curve` draws. The default is `corners`, as in `runSuite`. */
2957
+ readonly curveRouter?: string;
2958
+ /**
2959
+ * With this value, the step `curve` opens each shared segment of the routes of `curveRouter`, and each curve draws the lanes of `laneRoutes`.
2960
+ * So the curve `highway` bends the lanes of a bundle as one. Without it, each curve draws the routes. A router without shared segments gives the routes in both cases.
2961
+ */
2962
+ readonly lanes?: {
2963
+ readonly width: number;
2964
+ readonly maxWidth?: number;
2965
+ };
2966
+ /** The seed of the small change of the graph for the stability measures (Z10 and G9). The default is 1. */
2967
+ readonly seed?: number;
2968
+ /** The route stability (Z10) routes a changed graph again, so the function measures it only up to this number of nodes. The default is 1000. */
2969
+ readonly stabilityMax?: number;
2970
+ /** The name of the graph in the rows. The default is `board`. */
2971
+ readonly name?: string;
2972
+ }
2973
+ /** One strategy of one step on one graph: its measures and its output. */
2974
+ export interface CompareRow {
2975
+ readonly step: CompareStep;
2976
+ readonly strategy: string;
2977
+ /** The violations of the hard rules, as `runSuite` counts them. A strategy with a violation does not enter the front. */
2978
+ readonly violations: number;
2979
+ /** The time of the step, in milliseconds. For the step `router`, it is the median of two routes. */
2980
+ readonly ms: number;
2981
+ /**
2982
+ * The measures, by the keys of `runSuite`, and `ms`. The step `router` adds `ink`, and the step `curve` adds `C5.peak`.
2983
+ * A router with zoom levels also gets `Z3.through` and `Z3.length`, the measures of its level links.
2984
+ */
2985
+ readonly values: Readonly<Record<string, number>>;
2986
+ /** The reason when the strategy did not run, for example a graph over its `maxNodes`. */
2987
+ readonly skipped?: string;
2988
+ /** The result of the router, for the steps `router` and `group`. The step `group` routes with `sections` on the tree of the rule. */
2989
+ readonly result?: Result;
2990
+ /** The tree of the grouping rule, for the step `group`. */
2991
+ readonly tree?: Section;
2992
+ /** The segments of each curve, for the step `curve`, in the order of `edges`. */
2993
+ readonly curves?: readonly CurveSegment[][];
2994
+ /** The edge of each curve of `curves`. */
2995
+ readonly edges?: readonly string[];
2996
+ }
2997
+ /** The comparison of the strategies of one step on one graph. */
2998
+ export interface StepComparison {
2999
+ readonly step: CompareStep;
3000
+ /** One row for each strategy of the step, in the order of the registry. */
3001
+ readonly rows: readonly CompareRow[];
3002
+ /** The axes of the Pareto front: `FRONT_OBJECTIVES` of the step. */
3003
+ readonly objectives: readonly Objective[];
3004
+ /** The strategies on the Pareto front, in the order of the registry. */
3005
+ readonly front: readonly string[];
3006
+ /** The strategies with a violation of a hard rule, or that did not run. They do not enter the front. */
3007
+ readonly excluded: readonly string[];
3008
+ }
3009
+ /**
3010
+ * This function runs each strategy of one step on one graph and measures it with the measures of `runSuite`. Then it gives the Pareto front.
3011
+ * The step `router` routes the graph with each router. The step `curve` draws the routes of `curveRouter` with each curve, or their lanes with the option `lanes`.
3012
+ * The step `group` routes the graph with `sections` on the tree of each grouping rule.
3013
+ *
3014
+ * The same graph and the same options give the same measures. Only the times change.
3015
+ */
3016
+ export declare function compareStep(step: CompareStep, graph: Graph, options?: CompareOptions): StepComparison;
3017
+ /** This function gives the bytes of a string in UTF-8. */
3018
+ export declare function utf8(text: string): Uint8Array;
3019
+ /** This function gives the SHA-256 digest of a string, as 64 lowercase hex characters. It encodes the string in UTF-8. */
3020
+ export declare function sha256Hex(text: string): string;
3021
+ /**
3022
+ * This function writes a value as canonical JSON: the keys of each object in sorted order, and no whitespace.
3023
+ * It drops a key whose value is `undefined`, as `JSON.stringify` does.
3024
+ */
3025
+ export declare function canonicalJson(value: unknown): string;
3026
+ /**
3027
+ * This function gives the hash of a JSON document: the first 16 hex characters of the SHA-256 of its canonical JSON.
3028
+ * The document does not include its own field `hash`. The function removes that field before it calculates the hash.
3029
+ */
3030
+ export declare function documentHash(value: object): string;
3031
+ /** This function gives the 32-bit FNV-1a hash of the UTF-8 bytes of a text, as an unsigned integer. */
3032
+ export declare function fnv1a32(text: string): number;
3033
+ /** This function gives the seed of one step of a generator: `fnv1a32("<seed>:<step>")`. */
3034
+ export declare function stepSeed(seed: number, step: string): number;
3035
+ /** This function gives the generator `mulberry32` for a seed. Each call gives the next number from 0 to below 1. */
3036
+ export declare function mulberry32(seed: number): () => number;
3037
+ /** This function rounds a number to 3 decimals, as the files of a corpus keep it. The value `-0` becomes `0`. */
3038
+ export declare function round3(value: number): number;
3039
+ /** The side of a port in an input file. The router calls the same sides `north`, `east`, `south` and `west`. */
3040
+ export type LayoutSide = "top" | "right" | "bottom" | "left";
3041
+ /** A port of a box in an input file. */
3042
+ export interface LayoutPort {
3043
+ readonly id: string;
3044
+ /** The side of the box. Without it and without `x` and `y`, the router picks the side. */
3045
+ readonly side?: LayoutSide;
3046
+ /** The fixed place of the port, from the top-left corner of the box. The router does not move a port with `x` and `y`. */
3047
+ readonly x?: number;
3048
+ readonly y?: number;
3049
+ }
3050
+ /** A point of a region: `[x, y]`. The y axis points down. */
3051
+ export type RegionPoint = readonly [number, number];
3052
+ /**
3053
+ * An area of the plane. The y axis points down. A ring of a polygon closes itself: its last point joins its first point.
3054
+ * A hole of a polygon does not touch the outer ring. The router reads only the bounding box of a region.
3055
+ */
3056
+ export type Region = {
3057
+ readonly kind: "rect";
3058
+ readonly x: number;
3059
+ readonly y: number;
3060
+ readonly w: number;
3061
+ readonly h: number;
3062
+ } | {
3063
+ readonly kind: "polygon";
3064
+ readonly points: readonly RegionPoint[];
3065
+ readonly holes?: readonly (readonly RegionPoint[])[];
3066
+ } | {
3067
+ readonly kind: "circle";
3068
+ readonly cx: number;
3069
+ readonly cy: number;
3070
+ readonly r: number;
3071
+ } | {
3072
+ readonly kind: "ellipse";
3073
+ readonly cx: number;
3074
+ readonly cy: number;
3075
+ readonly rx: number;
3076
+ readonly ry: number;
3077
+ };
3078
+ /** An area that the boxes and the routes must not use. The router uses the bounding box of its region as a box without edges. */
3079
+ export interface LayoutObstacle {
3080
+ readonly id: string;
3081
+ readonly region: Region;
3082
+ /** The cost to move the obstacle. Only the packer reads it. */
3083
+ readonly move?: {
3084
+ readonly cost: number;
3085
+ };
3086
+ }
3087
+ /** A box of an input file. */
3088
+ export interface LayoutBox {
3089
+ readonly id: string;
3090
+ readonly w: number;
3091
+ readonly h: number;
3092
+ /** The position of the top-left corner. The packer writes it. The router reads it. */
3093
+ readonly x?: number;
3094
+ readonly y?: number;
3095
+ /** The id of the box that holds this box. */
3096
+ readonly parent?: string;
3097
+ /** The group of the box. */
3098
+ readonly group?: string;
3099
+ /** This value is `true` when the box is an obstacle: the packer keeps its `x` and `y`. The router ignores it. */
3100
+ readonly locked?: true;
3101
+ /** The reading order that the caller wants. The router ignores it. */
3102
+ readonly rank?: number;
3103
+ readonly ports?: readonly LayoutPort[];
3104
+ /** The shape of the box, relative to the top-left corner of the box. The router ignores it and uses `w` and `h` as the bounding box. */
3105
+ readonly shape?: Region;
3106
+ /** The free data of the node. The grouping rule `keys` reads `data.group`. */
3107
+ readonly data?: Readonly<Record<string, unknown>>;
3108
+ }
3109
+ /** An edge of an input file. `sourcePort` and `targetPort` name a port of the box at that end. */
3110
+ export interface LayoutEdge {
3111
+ readonly id: string;
3112
+ readonly source: string;
3113
+ readonly target: string;
3114
+ readonly sourcePort?: string;
3115
+ readonly targetPort?: string;
3116
+ readonly data?: Readonly<Record<string, unknown>>;
3117
+ }
3118
+ /** The change of a variant against its base input. */
3119
+ export type LayoutChange = "add" | "remove" | "resize" | "reorder" | "packed";
3120
+ /** The origin of an input: `made-up`, `published:<set>` or `known-best:<construction>`. */
3121
+ export type LayoutSource = "made-up" | `published:${string}` | `known-best:${string}`;
3122
+ /** The generator of an input. The same name, version, parameters and seed give the same file, byte for byte. */
3123
+ export interface LayoutGenerator {
3124
+ readonly name: string;
3125
+ readonly version: number;
3126
+ readonly params: Readonly<Record<string, unknown>>;
3127
+ readonly seed: number;
3128
+ }
3129
+ /**
3130
+ * The cell of an input in the taxonomy of the corpus, with one value for each dimension.
3131
+ * The packer reads the first six dimensions. The router reads the last four.
3132
+ */
3133
+ export interface LayoutCell {
3134
+ readonly containerSize?: "fixed" | "freeWidth" | "freeAspect";
3135
+ readonly containerShape?: "rect" | "convex" | "polygon" | "circle" | "ellipse" | "holes";
3136
+ readonly obstacles?: "none" | "center" | "scattered" | "wall" | "corridors" | "touching" | "edge";
3137
+ readonly sizes?: "identical" | "uniform" | "heavyTail" | "bimodal" | "extremeAspect" | "nearIdentical";
3138
+ readonly count?: "1" | "10" | "100" | "1k" | "10k";
3139
+ readonly mode?: "offline" | "online" | "incremental";
3140
+ readonly edgeDensity?: "sparse" | "medium" | "dense";
3141
+ readonly edgeShape?: "random" | "clustered" | "hubChain" | "longRange" | "tree" | "bundled";
3142
+ readonly groups?: "none" | "flat" | "nested";
3143
+ readonly ports?: "free" | "sides" | "fixed";
3144
+ }
3145
+ /** The outer rectangle of a packing. The router ignores it. */
3146
+ export interface LayoutContainer {
3147
+ readonly w?: number;
3148
+ readonly h?: number;
3149
+ /** `none`: the packer picks the size. `width`: the width stays. `height`: the height stays. `size`: the width and the height stay. */
3150
+ readonly fixed: "none" | "width" | "height" | "size";
3151
+ /** The ratio `w / h` that the packer aims for. */
3152
+ readonly aspect?: number;
3153
+ /** The shape of the container. */
3154
+ readonly shape?: Region;
3155
+ }
3156
+ /** The identity of an input in a set: the set, the family, the seed, and the base of a variant. */
3157
+ export interface LayoutInputHead {
3158
+ /** The id: `<set>/<family>/s<seed>`. */
3159
+ readonly id: string;
3160
+ readonly set: string;
3161
+ readonly family: string;
3162
+ readonly seed: number;
3163
+ /** The id of the base input of a variant. The stability measures compare the run on the variant with the run on its base. */
3164
+ readonly base?: string;
3165
+ readonly change?: LayoutChange;
3166
+ /** The place of the input in a change sequence. */
3167
+ readonly step?: number;
3168
+ /** The generator of the input. The default is `null`: a hand-made input. */
3169
+ readonly generator?: LayoutGenerator | null;
3170
+ /** The origin of the input. The default is `made-up`. */
3171
+ readonly source?: LayoutSource;
3172
+ readonly cell?: LayoutCell;
3173
+ }
3174
+ /**
3175
+ * An input file of the form `layout-input/1`. The packer and the router read the same files.
3176
+ * The file `docs/LAYOUT-RECORDS.md` gives the form. The repository `packing` keeps a twin of that document.
3177
+ */
3178
+ export interface LayoutInput extends LayoutInputHead {
3179
+ readonly schema: "layout-input/1";
3180
+ /** The origin of the input. The data of this repository is made-up, because the repository is public. */
3181
+ readonly source: LayoutSource;
3182
+ /** The generator of the input, or `null` for a hand-made input. */
3183
+ readonly generator: LayoutGenerator | null;
3184
+ /** The first 16 hex characters of the SHA-256 of the canonical file without this field. `documentHash` calculates it. */
3185
+ readonly hash: string;
3186
+ readonly container?: LayoutContainer;
3187
+ /** The space between two boxes. The router ignores it. */
3188
+ readonly gap?: number;
3189
+ /** The areas that the boxes and the routes must not use. */
3190
+ readonly obstacles?: readonly LayoutObstacle[];
3191
+ readonly boxes: readonly LayoutBox[];
3192
+ readonly edges: readonly LayoutEdge[];
3193
+ }
3194
+ /** One run of one strategy on one input and one seed: a line of the form `layout-record/1`. */
3195
+ export interface LayoutRecord {
3196
+ readonly schema: "layout-record/1";
3197
+ /** `pack`, `route` or `joint`. The screen of this package writes `route`. */
3198
+ readonly stage: "pack" | "route" | "joint";
3199
+ readonly step: string;
3200
+ readonly strategy: string;
3201
+ /** The options of the run: the defaults of the strategy with the options of the caller. A function is the text `function:<name>`. */
3202
+ readonly options: Readonly<Record<string, unknown>>;
3203
+ /** The corpus version, for example `screen-v1`. */
3204
+ readonly corpus: string;
3205
+ /** The id of the input. */
3206
+ readonly input: string;
3207
+ /** The `hash` of the input file. */
3208
+ readonly inputHash: string;
3209
+ readonly set: string;
3210
+ readonly seed: number;
3211
+ readonly nodes: number;
3212
+ readonly edges: number;
3213
+ /** The measures, by the names of `MEASURES`. A measure without a finite value is not in the record. */
3214
+ readonly measures: Readonly<Record<string, number>>;
3215
+ /** The count of the breaks of each hard rule. A good run has 0 for each rule. */
3216
+ readonly hard: Readonly<Record<string, number>>;
3217
+ /** The tolerance of each hard rule of the run, for example `{ through: 0.5 }`. */
3218
+ readonly tolerance?: Readonly<Record<string, number>>;
3219
+ /** This value is `true` when two runs on the same input give the same output. */
3220
+ readonly deterministic: boolean;
3221
+ /** The id of the prediction of this run, from the predictions file. */
3222
+ readonly prediction?: string;
3223
+ /** The time of the run, in milliseconds. Only the times of CI compare. */
3224
+ readonly ms: number;
3225
+ /** The commit of the code that made the record. */
3226
+ readonly commit?: string;
3227
+ /** The reason when the strategy did not run, for example an input over its `maxNodes`. Then the record has no measures. */
3228
+ readonly skipped?: string;
3229
+ }
3230
+ /** The comparison of a prediction. Without it, `<=` applies to a measure where lower is better, and `>=` to the other measures. */
3231
+ export type PredictionOp = "<" | "<=" | "=" | ">=" | ">";
3232
+ /** A prediction about a run: one line of a predictions file. A commit adds the file before the run starts. */
3233
+ export interface LayoutPrediction {
3234
+ readonly schema?: "layout-prediction/1";
3235
+ readonly id: string;
3236
+ readonly strategy: string;
3237
+ readonly set: string;
3238
+ /** The id of one input. Without it, the prediction is about the median of the measure over the set. */
3239
+ readonly input?: string;
3240
+ /** The name of the measure, from `MEASURES`. */
3241
+ readonly measure: string;
3242
+ readonly expected: number;
3243
+ readonly op?: PredictionOp;
3244
+ readonly reason: string;
3245
+ }
3246
+ /**
3247
+ * This function writes a graph as an input file of the form `layout-input/1`, with its hash.
3248
+ * A fixed plug gets `x`, `y` and the side that holds it. `inputGraph` reads the file back.
3249
+ */
3250
+ export declare function graphInput(graph: Graph, head: LayoutInputHead): LayoutInput;
3251
+ /**
3252
+ * This function gives the bounding box of a region: the smallest box that holds it.
3253
+ */
3254
+ export declare function regionBounds(region: Region): {
3255
+ x: number;
3256
+ y: number;
3257
+ w: number;
3258
+ h: number;
3259
+ };
3260
+ /**
3261
+ * This function reads the graph of the router from an input file. The router reads the positions, the ports, the edges and the data.
3262
+ * Each obstacle becomes a node without edges, with the bounding box of its region, after the boxes.
3263
+ * The router ignores the other fields of the packer: `container`, `gap`, `locked`, `rank`, the `shape` of a box and the `move` of an obstacle.
3264
+ * A box without `x` and `y` is an error.
3265
+ */
3266
+ export declare function inputGraph(input: LayoutInput): Graph;
3267
+ /**
3268
+ * This function writes an input file as text: the keys in sorted order, and one box or one edge on each line.
3269
+ * `JSON.parse` of the text gives the input again.
3270
+ */
3271
+ export declare function formatInput(input: LayoutInput): string;
3272
+ /** This function writes records as JSON Lines: one record on each line. */
3273
+ export declare function recordLines(records: readonly LayoutRecord[]): string;
3274
+ /** This function reads JSON Lines. It ignores an empty line. */
3275
+ export declare function parseLines<T>(text: string): T[];
3276
+ /**
3277
+ * This function gives a copy of a value that JSON keeps.
3278
+ * A function becomes the text `function:<name>`, and a number that is not finite becomes its text.
3279
+ */
3280
+ export declare function jsonSafe(value: unknown): unknown;
3281
+ /**
3282
+ * One measure of a record. `key` is the key of the measure in the values of `runSuite` and `compareStep`.
3283
+ * `name` is the name of the measure in a record of the form `layout-record/1`.
3284
+ */
3285
+ export interface MeasureInfo {
3286
+ /** The key in the values of `runSuite` and `compareStep`, for example `R5.median`. */
3287
+ readonly key: string;
3288
+ /** The id of the measure in `docs/research/MEASURES.md` (MEAS0), for example `R5`. */
3289
+ readonly id: string;
3290
+ /** The name in a record: lowercase, with a dot after the stage, for example `route.detour.median`. */
3291
+ readonly name: string;
3292
+ readonly unit: string;
3293
+ readonly better: "lower" | "higher";
3294
+ /**
3295
+ * This value is `true` when the positions of the boxes alone can move the value, with the same router.
3296
+ * Then two values compare only on the same input. The value is `false` when the measure scores the routes or the curves for a fixed placement.
3297
+ */
3298
+ readonly placementDependent: boolean;
3299
+ }
3300
+ /**
3301
+ * The measures of the records of the stage `route`, with the placement dependence of each one.
3302
+ * A joint harness that moves the boxes and routes the edges reads `placementDependent`.
3303
+ * It compares a measure with the value `true` only between runs on the same input.
3304
+ */
3305
+ export declare const MEASURES: readonly MeasureInfo[];
3306
+ /** This function gives the measure of a key of `runSuite` or `compareStep`, or `undefined` for a key that is not in `MEASURES`. */
3307
+ export declare function measureByKey(key: string): MeasureInfo | undefined;
3308
+ /** This function gives the measure of a name of a record, or `undefined` for a name that is not in `MEASURES`. */
3309
+ export declare function measureByName(name: string): MeasureInfo | undefined;
3310
+ /** This function gives the name of a key in a record. A key that is not in `MEASURES` gets the name `route.other.<key>`. */
3311
+ export declare function measureName(key: string): string;
3312
+ /** This function gives the objectives of a Pareto front by the names of a record, from objectives by the keys of `runSuite`. */
3313
+ export declare function namedObjectives(objectives: readonly Objective[]): Objective[];
3314
+ /** A family of boards of a screen set. The member `k` of the family has the seed `k`. */
3315
+ export interface ScreenFamily {
3316
+ readonly name: string;
3317
+ /** The known hard case that the family shows, in a few words. */
3318
+ readonly shows: string;
3319
+ /** The number of members. */
3320
+ readonly seeds: number;
3321
+ /** This function makes the member `k`. The same `k` always gives the same graph. */
3322
+ readonly make: (k: number) => Graph;
3323
+ /** This function gives the generator of the member `k`: its name, version, parameters and seed. */
3324
+ readonly generator: (k: number) => LayoutGenerator;
3325
+ /** The cell of each member in the taxonomy of the corpus. */
3326
+ readonly cell: LayoutCell;
3327
+ }
3328
+ /** A screen set: a fixed list of small boards with an id. A new board or a changed board gets a new id. */
3329
+ export interface ScreenSet {
3330
+ /** The id of the set, for example `screen-v1`. The records name it in `set` and `corpus`. */
3331
+ readonly id: string;
3332
+ readonly families: readonly ScreenFamily[];
3333
+ }
3334
+ /**
3335
+ * The screen set `screen-v1`: 14 boards of made-up data from 10 to 150 nodes. Each family shows a known hard case.
3336
+ * The seed 0 of each family is the fixture or the case board of the benchmark. The seed `k` of a fixture family is `familySeed(spec, k)`, as in `runSuite`.
3337
+ * The generators wrap the fixtures and the case boards without a change to their output.
3338
+ * This set does not change. The tests compare it with the files in `corpus/screen-v1`.
3339
+ */
3340
+ export declare const SCREEN_V1: ScreenSet;
3341
+ /** The screen sets by id. */
3342
+ export declare const SCREEN_SETS: Readonly<Record<string, ScreenSet>>;
3343
+ /** This function gives the id of the member `seed` of a family of a set: `<set>/<family>/s<seed>`. */
3344
+ export declare function inputId(set: string, family: string, seed: number): string;
3345
+ /** This function gives the input files of a screen set, in the order of its families and seeds. Each file has its hash. */
3346
+ export declare function screenInputs(set?: ScreenSet): LayoutInput[];
3347
+ /** A spec of a manifest: one generator with its version and parameters, and the seeds that the corpus uses. */
3348
+ export interface CorpusSpec {
3349
+ readonly generator: string;
3350
+ readonly version: number;
3351
+ readonly params: Readonly<Record<string, unknown>>;
3352
+ readonly seeds: readonly number[];
3353
+ }
3354
+ /** The manifest `corpus.json` of a corpus, of the form `layout-corpus/1`. */
3355
+ export interface LayoutCorpus {
3356
+ readonly schema: "layout-corpus/1";
3357
+ readonly corpus: string;
3358
+ readonly specs: readonly CorpusSpec[];
3359
+ readonly inputs: readonly {
3360
+ readonly id: string;
3361
+ readonly hash: string;
3362
+ readonly cell: LayoutCell;
3363
+ }[];
3364
+ }
3365
+ /** This function gives the manifest of a list of inputs. The inputs of one generator, version and parameters share one spec. */
3366
+ export declare function corpusManifest(corpus: string, inputs: readonly LayoutInput[]): LayoutCorpus;
3367
+ /**
3368
+ * The steps of the screen: the steps of `compareStep` and the step `highway`.
3369
+ * The screen of the step `highway` routes the plan of each strategy with `follow`, and measures the routes as the routes of a router.
3370
+ */
3371
+ export type ScreenStep = CompareStep | "highway";
3372
+ /** The steps of the screen, in the order of the pipeline. */
3373
+ export declare const SCREEN_STEPS: readonly ScreenStep[];
3374
+ /** The routers that the screen of the step `highway` also runs by default. They are the baselines of the note on highways. */
3375
+ export declare const HIGHWAY_BASE_ROUTERS: readonly string[];
3376
+ /** The hard rules of each step of the screen, in the order of the records. A good run has 0 for each rule. */
3377
+ export declare const SCREEN_RULES: Readonly<Record<ScreenStep, readonly string[]>>;
3378
+ /** The options of `screen`. */
3379
+ export interface ScreenOptions {
3380
+ /** The screen set. The default is `SCREEN_V1`. */
3381
+ readonly set?: ScreenSet;
3382
+ /** The input files. The default is the files of `set`. */
3383
+ readonly inputs?: readonly LayoutInput[];
3384
+ /** The families of the inputs that the screen runs. The default is each family. */
3385
+ readonly families?: readonly string[];
3386
+ /**
3387
+ * With `true`, the screen also runs each built-in strategy of the step, and the front compares the new strategies with them.
3388
+ * With `false`, it runs only the strategies of the call. The default is `true`.
3389
+ */
3390
+ readonly baseline?: boolean;
3391
+ /** The options of each strategy, by its name. A strategy without an entry gets its defaults. */
3392
+ readonly options?: Readonly<Record<string, object>>;
3393
+ /** The router whose routes the step `curve` draws. The default is `corners`. */
3394
+ readonly curveRouter?: string;
3395
+ /**
3396
+ * The routers that the screen of the step `highway` also runs. Their records have the step `router`.
3397
+ * The default is `HIGHWAY_BASE_ROUTERS`. The other steps do not read it.
3398
+ */
3399
+ readonly baseRouters?: readonly string[];
3400
+ /** The seed of the small change of the stability measures. The default is 1. */
3401
+ readonly seed?: number;
3402
+ /** The commit of the code, for the records. */
3403
+ readonly commit?: string;
3404
+ /** The predictions of the run. Each record names the first prediction with its strategy, its set and its input. */
3405
+ readonly predictions?: readonly LayoutPrediction[];
3406
+ /** This function gets one line of progress for each input. */
3407
+ readonly log?: (line: string) => void;
3408
+ }
3409
+ /** The summary of one strategy over the inputs of a screen. */
3410
+ export interface ScreenStrategySummary {
3411
+ readonly strategy: string;
3412
+ /** This value is `true` for a strategy of the call, and `false` for a built-in strategy of the baseline. */
3413
+ readonly candidate: boolean;
3414
+ /** The number of inputs where the strategy ran. */
3415
+ readonly runs: number;
3416
+ /** The number of inputs that the strategy skipped. */
3417
+ readonly skipped: number;
3418
+ /** This value is `true` when each run gave the same output two times. */
3419
+ readonly deterministic: boolean;
3420
+ /** The sum of the breaks of each hard rule over the runs. */
3421
+ readonly hard: Readonly<Record<string, number>>;
3422
+ /** The sum of `hard`. */
3423
+ readonly hardTotal: number;
3424
+ /**
3425
+ * The breaks over the floor of each input. The floor is the counts of the built-in strategy with the fewest breaks on that input.
3426
+ * Each built-in breaks a rule on some boards, for example on a board where the boxes touch. Without built-ins, the floor is 0.
3427
+ */
3428
+ readonly hardOverFloor: number;
3429
+ /** The median of each measure over the runs, by the names of a record. */
3430
+ readonly medians: Readonly<Record<string, number>>;
3431
+ /** The median time of a run, in milliseconds. */
3432
+ readonly ms: number;
3433
+ /** The number of inputs where the strategy is on the Pareto front of its input. */
3434
+ readonly onFront: number;
3435
+ }
3436
+ /** A prediction with the measured value. */
3437
+ export interface PredictionCheck extends LayoutPrediction {
3438
+ readonly op: PredictionOp;
3439
+ /** The measured value: the value of the record of the input, or the median over the set. It is absent when no record has the measure. */
3440
+ readonly measured?: number;
3441
+ /** This value is `true` when the measured value meets the prediction. It is absent when there is no measured value. */
3442
+ readonly met?: boolean;
3443
+ }
3444
+ /** The summary of a screen. */
3445
+ export interface ScreenSummary {
3446
+ readonly set: string;
3447
+ readonly step: ScreenStep;
3448
+ /** The number of inputs. */
3449
+ readonly inputs: number;
3450
+ /** The axes of the Pareto front, by the names of a record. */
3451
+ readonly objectives: readonly Objective[];
3452
+ /** One summary for each strategy, in the order of the registry. */
3453
+ readonly strategies: readonly ScreenStrategySummary[];
3454
+ /** The strategies on the Pareto front of the medians over the set. */
3455
+ readonly front: readonly string[];
3456
+ /** The strategies with a break over the floor, without a run or with two different outputs of one input. They do not enter the front. */
3457
+ readonly excluded: readonly string[];
3458
+ readonly predictions: readonly PredictionCheck[];
3459
+ }
3460
+ /** The result of `screen`: one record for each strategy and input, and the summary. */
3461
+ export interface ScreenReport {
3462
+ readonly records: readonly LayoutRecord[];
3463
+ readonly summary: ScreenSummary;
3464
+ }
3465
+ /**
3466
+ * This function screens strategies of one step on the inputs of a screen set. It is the cheap test of a new idea before a full build.
3467
+ * Each strategy runs on each input with `compareStep`, and each run gives one record of the form `layout-record/1`.
3468
+ * A strategy can be a name of the registry or a strategy object, for example from a prototype file. The registry does not change.
3469
+ *
3470
+ * The step `router` routes each input two times for the rule "same twice". The steps `group` and `curve` run each input two times for the same rule.
3471
+ *
3472
+ * The step `highway` makes the plan of each strategy and routes it with `follow`, two times. It also runs the routers of `baseRouters`.
3473
+ * An input with a `base` in the inputs also gets the measures `route.stability.base.*`: the routes on the variant against the routes on its base.
3474
+ * The same inputs and the same options give the same records. Only the times change.
3475
+ */
3476
+ export declare function screen(step: ScreenStep, strategies?: readonly (Strategy<ScreenStep> | string)[], options?: ScreenOptions): ScreenReport;
3477
+ /** This function writes the summary of a screen as Markdown: one row for each strategy, the front and the predictions. */
3478
+ export declare function formatScreen(summary: ScreenSummary): string;
3479
+ /** This function gives a whole number from `lo` to `hi`, both included, from a generator of random numbers. */
3480
+ export declare function randomInt(r: () => number, lo: number, hi: number): number;
3481
+ /** The parameters of the generator `rect-scattered`. */
3482
+ export interface RectScatteredParams {
3483
+ /** The number of boxes. */
3484
+ readonly count: number;
3485
+ }
3486
+ /**
3487
+ * This function makes the input of the shared generator `rect-scattered`, version 1: a fixed rectangle container, scattered obstacles and boxes without positions.
3488
+ * The repository `packing` makes the same file, byte for byte. A test in each repository pins the hashes of the seeds 1, 2 and 3.
3489
+ * The steps are `container`, `obstacles` and `boxes`. Each step has its own generator from `stepSeed`.
3490
+ */
3491
+ export declare function rectScattered(seed: number, params: RectScatteredParams, set?: string): LayoutInput;
3492
+ /** The options of `follow`. */
3493
+ interface FollowOptions extends WayOptions {
3494
+ /**
3495
+ * These routes are the routes of the base router. Each edge outside the plan keeps its route from them.
3496
+ * Without them, or for an edge without a route in them, `follow` routes the edge as the router `corners` does.
3497
+ */
3498
+ readonly routes?: Result;
3499
+ /** The lane order of the shared runs. The default is `bundle`. */
3500
+ readonly laneOrder?: RunOrder;
3501
+ }
3502
+ /**
3503
+ * This function routes the edges along a highway plan.
3504
+ *
3505
+ * An edge of a highway goes from its source plug to its merge point. Then it goes along the spine to its split point, and to its target plug.
3506
+ * The ramps go around the boxes through the corner graph (`WayFinder.fromPlug` and `WayFinder.toPlug`).
3507
+ * A spine point on the box of the node is the plug itself. When the end has a fixed plug, the point is at that plug.
3508
+ *
3509
+ * An edge on several highways takes them in the order of `seq`.
3510
+ * A way through the corner graph goes from each split point to the next merge point.
3511
+ * An edge outside the plan keeps its route from `options.routes`, or goes as in the router `corners`.
3512
+ *
3513
+ * The result has a shared run for each stretch of a spine where the same two edges or more go. Each run holds the points of its routes in a row.
3514
+ * The same graph, plan and options give the same result.
3515
+ */
3516
+ export declare function follow(graph: Graph, plan: HighwayPlan, options?: FollowOptions): Result;
3517
+ /**
3518
+ * This function gives the highways of a result of a router: one highway for each shared run and for each trunk of a bundle.
3519
+ * The spine is the points of the run or of the trunk. Each edge of the run is a member, from one end of the spine to the other end, in the way of its route.
3520
+ * The member `seq` is the place of the shared stretch in the route of the edge. The lanes keep the lane order of the router.
3521
+ *
3522
+ * Thus `follow` routes each edge along the shared stretches of the router. A route that does not hold its run is not a member.
3523
+ */
3524
+ export declare function planOfResult(result: Result): HighwayPlan;
3525
+ /**
3526
+ * This function gives a router that runs a highway strategy and then `follow`. The strategy gets the graph without first routes.
3527
+ * The way finder of `follow` takes `margin` and `k` from the options of the strategy, and then from `followOptions`.
3528
+ * The router keeps the name and the `maxNodes` of the strategy.
3529
+ */
3530
+ export declare function highwayRouter<O extends object>(strategy: Strategy<"highway", O>, options?: Partial<O>, followOptions?: FollowOptions): Router;
3531
+ /**
3532
+ * This function gives a router strategy that runs a highway strategy and then `follow`.
3533
+ * The router strategy has the name, the options and the schema of the highway strategy.
3534
+ * The benchmark and the screen race such a router with the other routers.
3535
+ */
3536
+ export declare function highwayRouterStrategy<O extends object>(strategy: Strategy<"highway", O>): Strategy<"router", O>;
3537
+ export type { ArcOptions, ClothoidOptions, CornersOptions, CorridorOptions, CurveSpace, CutObjective, CutOptions, FollowOptions, Highway, HighwayInput, HighwayMember, HighwayOptions, HighwayPlan, JogStyle, KdAxis, KdLine, KdOptions, KeyOptions, KeysOptions, LaneCurve, NodeKey, RoomBends, RoundedOptions, SectionsOptions, SharedOptions, SharedWaysOptions, SmoothOptions, SplineOptions, TrunksOptions };
1471
3538
  //# sourceMappingURL=index.d.ts.map