flo-mat 3.0.12 → 3.0.14

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 (126) hide show
  1. package/browser/index.js +188 -50
  2. package/browser/index.min.js +1 -1
  3. package/node/cp-node/cp-node-fs.d.ts +4 -4
  4. package/node/cp-node/cp-node-fs.js +4 -4
  5. package/node/cp-node/cp-node.d.ts +8 -10
  6. package/node/cp-node/fs/clone.d.ts +1 -1
  7. package/node/cp-node/fs/clone.js +14 -10
  8. package/node/cp-node/fs/clone.js.map +1 -1
  9. package/node/cp-node/fs/cp-node-comparator.d.ts +6 -0
  10. package/node/cp-node/fs/cp-node-comparator.js +6 -0
  11. package/node/cp-node/fs/cp-node-comparator.js.map +1 -1
  12. package/node/cp-node/fs/enhance-cp-node.d.ts +5 -2
  13. package/node/cp-node/fs/enhance-cp-node.js +4 -0
  14. package/node/cp-node/fs/enhance-cp-node.js.map +1 -1
  15. package/node/cp-node/fs/get-all-on-circle.d.ts +4 -4
  16. package/node/cp-node/fs/get-all-on-circle.js +4 -4
  17. package/node/cp-node/fs/get-all-on-loop.d.ts +4 -0
  18. package/node/cp-node/fs/get-all-on-loop.js +4 -0
  19. package/node/cp-node/fs/get-all-on-loop.js.map +1 -1
  20. package/node/cp-node/fs/get-boundary-bezier-parts-to-next.d.ts +5 -4
  21. package/node/cp-node/fs/get-boundary-bezier-parts-to-next.js +5 -4
  22. package/node/cp-node/fs/get-boundary-bezier-parts-to-next.js.map +1 -1
  23. package/node/cp-node/fs/get-boundary-beziers-to-next.d.ts +4 -8
  24. package/node/cp-node/fs/get-boundary-beziers-to-next.js +4 -8
  25. package/node/cp-node/fs/get-boundary-beziers-to-next.js.map +1 -1
  26. package/node/cp-node/fs/get-children.d.ts +6 -0
  27. package/node/cp-node/fs/get-children.js +6 -0
  28. package/node/cp-node/fs/get-children.js.map +1 -1
  29. package/node/cp-node/fs/get-edge-direction.d.ts +6 -0
  30. package/node/cp-node/fs/get-edge-direction.js +6 -0
  31. package/node/cp-node/fs/get-edge-direction.js.map +1 -1
  32. package/node/cp-node/fs/get-first-exit.d.ts +4 -0
  33. package/node/cp-node/fs/get-first-exit.js +4 -0
  34. package/node/cp-node/fs/get-first-exit.js.map +1 -1
  35. package/node/cp-node/fs/get-mat-curve-between.d.ts +6 -0
  36. package/node/cp-node/fs/get-mat-curve-between.js +6 -0
  37. package/node/cp-node/fs/get-mat-curve-between.js.map +1 -1
  38. package/node/cp-node/fs/get-mat-curve-to-next.d.ts +6 -0
  39. package/node/cp-node/fs/get-mat-curve-to-next.js +6 -0
  40. package/node/cp-node/fs/get-mat-curve-to-next.js.map +1 -1
  41. package/node/cp-node/fs/get-prong-count.d.ts +8 -0
  42. package/node/cp-node/fs/get-prong-count.js +8 -0
  43. package/node/cp-node/fs/get-prong-count.js.map +1 -1
  44. package/node/cp-node/fs/get-real-prong-count.d.ts +6 -0
  45. package/node/cp-node/fs/get-real-prong-count.js +6 -0
  46. package/node/cp-node/fs/get-real-prong-count.js.map +1 -1
  47. package/node/cp-node/fs/get-vertex-forward-children.d.ts +8 -0
  48. package/node/cp-node/fs/get-vertex-forward-children.js +8 -0
  49. package/node/cp-node/fs/get-vertex-forward-children.js.map +1 -1
  50. package/node/cp-node/fs/is-fully-terminating.d.ts +2 -5
  51. package/node/cp-node/fs/is-fully-terminating.js +2 -5
  52. package/node/cp-node/fs/is-fully-terminating.js.map +1 -1
  53. package/node/cp-node/fs/is-on-same-circle.d.ts +6 -0
  54. package/node/cp-node/fs/is-on-same-circle.js +6 -0
  55. package/node/cp-node/fs/is-on-same-circle.js.map +1 -1
  56. package/node/cp-node/fs/is-one-prong.d.ts +8 -0
  57. package/node/cp-node/fs/is-one-prong.js +8 -0
  58. package/node/cp-node/fs/is-one-prong.js.map +1 -1
  59. package/node/cp-node/fs/is-order-correct.d.ts +1 -1
  60. package/node/cp-node/fs/is-order-correct.js +1 -4
  61. package/node/cp-node/fs/is-order-correct.js.map +1 -1
  62. package/node/cp-node/fs/is-sharp.d.ts +7 -0
  63. package/node/cp-node/fs/is-sharp.js +7 -0
  64. package/node/cp-node/fs/is-sharp.js.map +1 -1
  65. package/node/cp-node/fs/is-special.d.ts +1 -1
  66. package/node/cp-node/fs/is-special.js +1 -3
  67. package/node/cp-node/fs/is-special.js.map +1 -1
  68. package/node/cp-node/fs/is-terminating.d.ts +22 -0
  69. package/node/cp-node/fs/is-terminating.js +22 -0
  70. package/node/cp-node/fs/is-terminating.js.map +1 -1
  71. package/node/cp-node/fs/traverse-cp.d.ts +9 -0
  72. package/node/cp-node/fs/traverse-cp.js +9 -0
  73. package/node/cp-node/fs/traverse-cp.js.map +1 -1
  74. package/node/cp-node/fs/traverse-edges.d.ts +7 -0
  75. package/node/cp-node/fs/traverse-edges.js +7 -0
  76. package/node/cp-node/fs/traverse-edges.js.map +1 -1
  77. package/node/cp-node/fs/traverse-vertices.d.ts +9 -0
  78. package/node/cp-node/fs/traverse-vertices.js +9 -0
  79. package/node/cp-node/fs/traverse-vertices.js.map +1 -1
  80. package/node/find-2-prong/add-2-prong.js +5 -3
  81. package/node/find-2-prong/add-2-prong.js.map +1 -1
  82. package/node/floyd-warshall/get-graph.d.ts +1 -1
  83. package/node/floyd-warshall/get-graph.js +2 -2
  84. package/node/floyd-warshall/get-graph.js.map +1 -1
  85. package/node/floyd-warshall/get-hole-closer-pairs.d.ts +6 -1
  86. package/node/floyd-warshall/get-hole-closer-pairs.js +8 -0
  87. package/node/floyd-warshall/get-hole-closer-pairs.js.map +1 -1
  88. package/node/mat/add-to-cp-tree.js +1 -3
  89. package/node/mat/add-to-cp-tree.js.map +1 -1
  90. package/node/vertex/remove-vertex.d.ts +5 -0
  91. package/node/vertex/remove-vertex.js +5 -0
  92. package/node/vertex/remove-vertex.js.map +1 -1
  93. package/package.json +1 -1
  94. package/src/cp-node/cp-node-fs.ts +4 -4
  95. package/src/cp-node/cp-node.ts +8 -10
  96. package/src/cp-node/fs/clone.ts +20 -14
  97. package/src/cp-node/fs/cp-node-comparator.ts +6 -0
  98. package/src/cp-node/fs/enhance-cp-node.ts +4 -0
  99. package/src/cp-node/fs/get-all-on-circle.ts +4 -4
  100. package/src/cp-node/fs/get-all-on-loop.ts +5 -1
  101. package/src/cp-node/fs/get-boundary-bezier-parts-to-next.ts +6 -5
  102. package/src/cp-node/fs/get-boundary-beziers-to-next.ts +4 -8
  103. package/src/cp-node/fs/get-children.ts +6 -0
  104. package/src/cp-node/fs/get-edge-direction.ts +6 -0
  105. package/src/cp-node/fs/get-first-exit.ts +4 -0
  106. package/src/cp-node/fs/get-mat-curve-between.ts +6 -0
  107. package/src/cp-node/fs/get-mat-curve-to-next.ts +6 -0
  108. package/src/cp-node/fs/get-prong-count.ts +8 -0
  109. package/src/cp-node/fs/get-real-prong-count.ts +6 -0
  110. package/src/cp-node/fs/get-vertex-forward-children.ts +8 -0
  111. package/src/cp-node/fs/is-fully-terminating.ts +2 -5
  112. package/src/cp-node/fs/is-on-same-circle.ts +6 -0
  113. package/src/cp-node/fs/is-one-prong.ts +8 -0
  114. package/src/cp-node/fs/is-order-correct.ts +1 -4
  115. package/src/cp-node/fs/is-sharp.ts +7 -0
  116. package/src/cp-node/fs/is-special.ts +2 -3
  117. package/src/cp-node/fs/is-terminating.ts +22 -0
  118. package/src/cp-node/fs/traverse-cp.ts +9 -0
  119. package/src/cp-node/fs/traverse-edges.ts +7 -0
  120. package/src/cp-node/fs/traverse-vertices.ts +9 -0
  121. package/src/find-2-prong/add-2-prong.ts +4 -1
  122. package/src/floyd-warshall/get-graph.ts +3 -3
  123. package/src/floyd-warshall/get-hole-closer-pairs.ts +9 -1
  124. package/src/mat/add-to-cp-tree.ts +1 -2
  125. package/src/vertex/remove-vertex.ts +5 -0
  126. package/src/cp-node/fs/create-cp-node.ts +0 -21
package/browser/index.js CHANGED
@@ -893,6 +893,10 @@ function floydWarshall(graph) {
893
893
  // floydWarshall(graph);//?
894
894
 
895
895
  ;// ./src/cp-node/fs/get-all-on-loop.ts
896
+ /**
897
+ * Returns all `CpNode`s on the MAT that this `CpNode` is part of
898
+ * starting from the current one and going anti-clockwise around the shape.
899
+ */
896
900
  function getAllOnLoop(cpNode) {
897
901
  const cpStart = cpNode;
898
902
  const cpNodes = [cpStart];
@@ -6246,6 +6250,12 @@ const isPosSharpCorner = memoize((pos) => {
6246
6250
 
6247
6251
 
6248
6252
 
6253
+ /**
6254
+ * @internal
6255
+ * Returns a line segment of unit length starting in the given Vertex center and
6256
+ * pointing in the direction of the medial axis (viewed as a rooted tree).
6257
+ * @param cpNode
6258
+ */
6249
6259
  function getEdgeDirection(cpNode) {
6250
6260
  const circleCenter = cpNode.cp.circle.center;
6251
6261
  const cp1 = cpNode;
@@ -6296,6 +6306,12 @@ function getEdgeDirection(cpNode) {
6296
6306
  const TOLERANCE_ADD_2PRONG = 0.01;
6297
6307
  /** @internal */
6298
6308
  const TOLERANCE_USE_LINE = 0.0001; // else cubic
6309
+ /**
6310
+ * Returns the bezier curve from the maximal disk of one `CpNode` to another
6311
+ * `CpNode`'s maximal disk.
6312
+ * @param cpNodeFrom
6313
+ * @param cpNodeTo
6314
+ */
6299
6315
  function getMatCurveBetween(cpNodeFrom, cpNodeTo) {
6300
6316
  const fromCc = cpNodeFrom.cp.circle.center;
6301
6317
  const fromL = getEdgeDirection(cpNodeFrom);
@@ -6344,6 +6360,12 @@ function getMatCurveBetween(cpNodeFrom, cpNodeTo) {
6344
6360
  ;// ./src/cp-node/fs/get-mat-curve-to-next.ts
6345
6361
 
6346
6362
 
6363
+ /**
6364
+ * Returns the bezier curve from the maximal disk of the given `CpNode` to the
6365
+ * next `CpNode`'s maximal disk and thus directly represents a piece of the
6366
+ * medial axis.
6367
+ * @param cpNode
6368
+ */
6347
6369
  function getMatCurveToNext(cpNode) {
6348
6370
  return getMatCurveBetween(cpNode, cpNode.next);
6349
6371
  }
@@ -6352,10 +6374,10 @@ const getMatCurveToNext$ = memoize(getMatCurveToNext);
6352
6374
 
6353
6375
  ;// ./src/cp-node/fs/get-all-on-circle.ts
6354
6376
  /**
6355
- * Returns all the `CpNode`s on the same circle.
6356
- *
6357
- * @param cpNode
6358
- * @param exclThis
6377
+ * Return this (except if exclThis is truthy) and the the other CpNodes
6378
+ * around the maximal disk vertex circle in an anti-clockwise order.
6379
+ * @param exclThis If true the returned array does not include this
6380
+ * `CpNode`.
6359
6381
  */
6360
6382
  function getAllOnCircle(cpNode, exclThis = false) {
6361
6383
  const startCpNode = cpNode;
@@ -6370,6 +6392,28 @@ function getAllOnCircle(cpNode, exclThis = false) {
6370
6392
 
6371
6393
 
6372
6394
  ;// ./src/cp-node/fs/is-terminating.ts
6395
+ /**
6396
+ * Returns `true` if this `CpNode` is terminating, i.e. implies a leaf MAT
6397
+ * vertex.
6398
+ *
6399
+ * The following are some instances where this is the case:
6400
+ *
6401
+ * * Sharp corners.
6402
+ *
6403
+ * * Half of Hole-closers, i.e. `CpNode`s whose next `CpNode` is on a different
6404
+ * loop
6405
+ *
6406
+ * * Maximal disks with a single contact point.
6407
+ * Note, however, that even in these cases there are two contact points stored
6408
+ * (sitting 'on top' of each other) for the maximal disk. It can be seen as a
6409
+ * limiting case of a two-prong where the distance between two of the contact
6410
+ * points tend to zero. One point (represented by a `CpNode` of course) will
6411
+ * be terminating with the other point being its `next`, whereas the other
6412
+ * point will *not* be terminating and 'points' back into the shape.
6413
+ *
6414
+ * * Some 3-prongs may also become terminating if the Scale Axis Transform is
6415
+ * applied to the shape.
6416
+ */
6373
6417
  function isTerminating(cpNode) {
6374
6418
  return cpNode === cpNode.next.prevOnCircle;
6375
6419
  }
@@ -6378,6 +6422,12 @@ function isTerminating(cpNode) {
6378
6422
  ;// ./src/cp-node/fs/get-real-prong-count.ts
6379
6423
 
6380
6424
 
6425
+ /**
6426
+ * Returns the number of contact points (up to planar coordinates) on the
6427
+ * maximal disk circle implied by this `CpNode`.
6428
+ *
6429
+ * See also `getProngCount`.
6430
+ */
6381
6431
  function getRealProngCount(cpNode) {
6382
6432
  const nonTerminatingCpNodes = getAllOnCircle(cpNode)
6383
6433
  .filter(cpNode => !isTerminating(cpNode));
@@ -6467,11 +6517,8 @@ function memoizePrimitive(f) {
6467
6517
 
6468
6518
 
6469
6519
  /**
6470
- * Returns `true` if this `CpNode` is fully terminating, meaning that all
6471
- * `CpNode`s (except `CpNode.prevOnCircle`) on the same circle are terminating,
6472
- * `false` otherwise.
6473
- *
6474
- * @param cpNode
6520
+ * Like isTerminating() but only returns true if all cpNodes on the circle
6521
+ * (except this.prevOnCircle) is terminating.
6475
6522
  */
6476
6523
  function isFullyTerminating(cpNode) {
6477
6524
  const otherOnCircle = getAllOnCircle(cpNode.prevOnCircle, true);
@@ -6573,6 +6620,14 @@ function getCpNodeOrdering(cpNode) {
6573
6620
 
6574
6621
 
6575
6622
  ;// ./src/cp-node/fs/get-prong-count.ts
6623
+ /**
6624
+ * Returns the number of contact points on the maximal disk circle implied
6625
+ * by this `CpNode`.
6626
+ *
6627
+ * Note, however, that even one-prongs and sharp corners will return 2 (see
6628
+ * `isTerminating` for more details); if this is not desired use
6629
+ * `getRealProngCount` instead which will return 1 in these cases.
6630
+ */
6576
6631
  function getProngCount(cpNode) {
6577
6632
  const startCpNode = cpNode;
6578
6633
  let cpNode_ = startCpNode;
@@ -6586,6 +6641,13 @@ function getProngCount(cpNode) {
6586
6641
 
6587
6642
 
6588
6643
  ;// ./src/cp-node/fs/is-sharp.ts
6644
+ /**
6645
+ * Returns true if this `CpNode` represents a sharp corner, i.e. the
6646
+ * limiting case of a two-prong having zero radius.
6647
+ *
6648
+ * Note that two `CpNode`s are stored for each sharp corner, one being
6649
+ * terminating and one not. See `isTerminating` for more details.
6650
+ */
6589
6651
  function isSharp(cpNode) {
6590
6652
  return cpNode.cp.circle.radius === 0;
6591
6653
  }
@@ -6598,6 +6660,10 @@ function isSharp(cpNode) {
6598
6660
 
6599
6661
 
6600
6662
 
6663
+ /**
6664
+ * For debugging
6665
+ * @param cpNode
6666
+ */
6601
6667
  function enhanceCpNode(cpNode) {
6602
6668
  const cp = cpNode.cp;
6603
6669
  const pos = cp.pointOnShape;
@@ -6621,6 +6687,15 @@ function enhanceCpNode(cpNode) {
6621
6687
 
6622
6688
  ;// ./src/cp-node/fs/traverse-cp.ts
6623
6689
 
6690
+ /**
6691
+ * @internal
6692
+ *
6693
+ * Traverses the shape from the given `CpNode` going around the shortest path
6694
+ * so that only a piece of the shape is traversed and returns the visited
6695
+ * `CpNode`s (starting from the given `CpNode`).
6696
+ *
6697
+ * @param cpStart The `CpNode` from where to start the traversal.
6698
+ */
6624
6699
  function traverseCp(cpStart) {
6625
6700
  let cpNode = cpStart;
6626
6701
  if (isTerminating(cpNode)) {
@@ -6641,6 +6716,13 @@ function traverseCp(cpStart) {
6641
6716
  ;// ./src/cp-node/fs/traverse-edges.ts
6642
6717
 
6643
6718
 
6719
+ /**
6720
+ * Traverses all edges (depth first) of the given MAT tree starting at the given
6721
+ * vertex (represented by a `CpNode`).
6722
+ * @param cpNode Any `CpNode` representing the start vertex.
6723
+ * @param traverseEdgesCallback A callback function for each CpNode representing the vertex at the
6724
+ * start of an edge.
6725
+ */
6644
6726
  function traverseEdges(cpNode, traverseEdgesCallback) {
6645
6727
  const cpNodes = getAllOnLoop(cpNode);
6646
6728
  const seen = new Set();
@@ -6655,6 +6737,14 @@ function traverseEdges(cpNode, traverseEdgesCallback) {
6655
6737
 
6656
6738
  ;// ./src/cp-node/fs/get-vertex-forward-children.ts
6657
6739
 
6740
+ /**
6741
+ * Similar to `getChildren` but returns the child nodes of the tree when
6742
+ * `CpNode` is seen as a MAT vertex point (as opposed to edge). In this
6743
+ * way the dual graph of the tree can easily be traversed - see e.g.
6744
+ * `traverseVertices`. Generally, however, traversing the edges is
6745
+ * preferred as it returns the entire Medial Axis (by utilizing
6746
+ * `getMatCurveToNext` on each returned edge).
6747
+ */
6658
6748
  function getVertexForwardChildren(cpNode) {
6659
6749
  const children = [];
6660
6750
  const cpStart = cpNode;
@@ -6673,6 +6763,15 @@ function getVertexForwardChildren(cpNode) {
6673
6763
 
6674
6764
 
6675
6765
 
6766
+ /**
6767
+ * Traverses the MAT tree and calls the given callback function for each vertex
6768
+ * (represented by a `CpNode`) on the MAT.
6769
+ *
6770
+ * It is usually preferable to use `traverseEdges` as it allows for the
6771
+ * traversal of all the smooth curves representing the MAT.
6772
+ * @param cpNode Any `CpNode` representing the start vertex.
6773
+ * @param traverseVerticesCallback A callback function taking a single `CpNode` as parameter.
6774
+ */
6676
6775
  function traverseVertices(cpStart, traverseVerticesCallback) {
6677
6776
  traverseVerticesCallback(cpStart);
6678
6777
  // Since the tree is unrooted we must iterate in all directions from the
@@ -6693,7 +6792,7 @@ function traverseVertices(cpStart, traverseVerticesCallback) {
6693
6792
 
6694
6793
  ;// ./src/cp-node/fs/clone.ts
6695
6794
  /** @internal */
6696
- const EDGES = ['prev', 'next', 'prevOnCircle', 'nextOnCircle'];
6795
+ const EDGES = ['prev', 'next', 'prevOnCircle', 'nextOnCircle', 'holeCloserTwin'];
6697
6796
  /**
6698
6797
  * Returns a deep clone of this `CpNode`. Can be used to copy the MAT
6699
6798
  * since cloning a single `CpNode` necessarily implies cloning all
@@ -6703,32 +6802,36 @@ function clone(cpNode) {
6703
6802
  // Don't change this function to be recursive, the call stack may
6704
6803
  // overflow if there are too many CpNodes.
6705
6804
  const nodeMap = new Map();
6706
- const newCpNode = cloneWithoutLinks(cpNode);
6805
+ const newCpNode = cloneWithoutEdges(cpNode);
6707
6806
  nodeMap.set(cpNode, newCpNode);
6708
6807
  const cpStack = [{ cpNode, newCpNode }];
6709
6808
  while (cpStack.length) {
6710
6809
  const { cpNode, newCpNode } = cpStack.pop();
6711
6810
  for (const edge of EDGES) {
6712
6811
  const node = cpNode[edge];
6713
- let newNode = nodeMap.get(node);
6714
- if (!newNode) {
6715
- newNode = cloneWithoutLinks(node);
6716
- nodeMap.set(node, newNode);
6717
- cpStack.push({ cpNode: node, newCpNode: newNode });
6812
+ if (node === undefined) {
6813
+ continue;
6718
6814
  }
6719
- newCpNode[edge] = newNode;
6815
+ let node_ = nodeMap.get(node);
6816
+ if (!node_) {
6817
+ node_ = cloneWithoutEdges(node);
6818
+ nodeMap.set(node, node_);
6819
+ cpStack.push({ cpNode: node, newCpNode: node_ });
6820
+ }
6821
+ newCpNode[edge] = node_;
6720
6822
  }
6721
6823
  }
6722
6824
  return newCpNode;
6723
6825
  }
6724
- function cloneWithoutLinks(cpNode) {
6826
+ function cloneWithoutEdges(cpNode) {
6725
6827
  const newNode = {
6726
6828
  ...cpNode,
6727
6829
  ...{
6728
6830
  prev: undefined,
6729
6831
  next: undefined,
6730
6832
  prevOnCircle: undefined,
6731
- nextOnCircle: undefined
6833
+ nextOnCircle: undefined,
6834
+ holeCloserTwin: undefined
6732
6835
  }
6733
6836
  };
6734
6837
  return newNode;
@@ -6737,11 +6840,12 @@ function cloneWithoutLinks(cpNode) {
6737
6840
 
6738
6841
  ;// ./src/cp-node/fs/get-boundary-bezier-parts-to-next.ts
6739
6842
  /**
6740
- * Returns the boundary beziers pieces between this `CpNode` and the next
6741
- * one.
6843
+ * Returns the ordered `BezierPiece`s from this `CpNode` to the next `CpNode`
6844
+ * on the boundary.
6742
6845
  *
6743
- * * returns `undefined` if the next `CpNode` is on a different loop,
6744
- * as this is a hole-closer and there are no boundary beziers between them.
6846
+ * * returns `[]` if (and only if) the next `CpNode` is on a different loop;
6847
+ * this differs from "returns `[]` if (and only if) the next `CpNode` is a
6848
+ * hole-closer" as half of hole-closers are on the same loop.
6745
6849
  *
6746
6850
  * @param cpNode
6747
6851
  */
@@ -6788,14 +6892,10 @@ function addSkippedBezierPiecess(bezierPieces, curveStart, curveEnd, t1) {
6788
6892
 
6789
6893
 
6790
6894
  /**
6791
- // * Returns the boundary beziers between this `CpNode` and the next
6792
- // * one.
6793
- // *
6794
- // * * returns `[]` if the next `CpNode` is on a different loop,
6795
- // * as this is a hole-closer and there are no boundary beziers between them.
6796
- // *
6797
- // * @param cpNode
6798
- // */
6895
+ * Returns the ordered bezier curves from this `CpNode` to the next `CpNode`
6896
+ * on the boundary.
6897
+ * @param cpNode
6898
+ */
6799
6899
  function getBoundaryBeziersToNext(cpNode) {
6800
6900
  return getBoundaryBezierPartsToNext(cpNode).map(bp => fromTo(bp.ps, bp.ts[0], bp.ts[1]));
6801
6901
  }
@@ -6877,6 +6977,11 @@ function removeCpNode(cpNode, meta) {
6877
6977
 
6878
6978
 
6879
6979
 
6980
+ /**
6981
+ * Removes a cpNode from the MAT.
6982
+ * @param cpTree The tree graph holding the `CpNodes` of the MAT.
6983
+ * @param cpNode The `CpNode` to remove.
6984
+ */
6880
6985
  function removeVertex(cpNode, meta) {
6881
6986
  // cpTrees: Map<Loop, LlRbTree<CpNode>>): void {
6882
6987
  const prongCount = getProngCount(cpNode);
@@ -6888,6 +6993,12 @@ function removeVertex(cpNode, meta) {
6888
6993
 
6889
6994
 
6890
6995
  ;// ./src/cp-node/fs/get-children.ts
6996
+ /**
6997
+ * Returns the children of this `CpNode` when seen as a MAT edge. Only
6998
+ * children in a 'forward' direction are returned. These include all edges
6999
+ * except the 'backward' edge given by `prevOnCircle`, even terminating
7000
+ * edges.
7001
+ */
6891
7002
  function getChildren(cpNode) {
6892
7003
  const children = [];
6893
7004
  const cp = cpNode.next;
@@ -6901,6 +7012,10 @@ function getChildren(cpNode) {
6901
7012
 
6902
7013
 
6903
7014
  ;// ./src/cp-node/fs/get-first-exit.ts
7015
+ /**
7016
+ * Returns the first `CpNode` (from this one by successively applying
7017
+ * .nextOnCircle) that exits the circle.
7018
+ */
6904
7019
  function getFirstExit(cpNode) {
6905
7020
  // const startNode = this as CpNode;
6906
7021
  const startNode = cpNode;
@@ -6918,6 +7033,12 @@ function getFirstExit(cpNode) {
6918
7033
 
6919
7034
  ;// ./src/cp-node/fs/is-on-same-circle.ts
6920
7035
 
7036
+ /**
7037
+ * Returns true if the 2 given `CpNode`s are on the same maximal disk
7038
+ * circle.
7039
+ * @param cpNode1 A `CpNode`.
7040
+ * @param cpNode2 Another `CpNode`
7041
+ */
6921
7042
  function isOnSameCircle(cpNode1, cpNode2) {
6922
7043
  // const cpNodes = getAllOnCircle(cpNode1, true);
6923
7044
  const cpNodes = getAllOnCircle(cpNode1);
@@ -6926,6 +7047,14 @@ function isOnSameCircle(cpNode1, cpNode2) {
6926
7047
 
6927
7048
 
6928
7049
  ;// ./src/cp-node/fs/is-one-prong.ts
7050
+ /**
7051
+ * Returns true if this `CpNode`'s maximal disk has only one contact point
7052
+ * on the shape boundary (up to planar coordinates). These includes sharp
7053
+ * corners.
7054
+ *
7055
+ * Note, however, that two `CpNode`s are stored for each such point to
7056
+ * preserve symmetry - see `isTerminating` for more details.
7057
+ */
6929
7058
  // TODO2 - remove - or replace with `getRealProngCount === 1`
6930
7059
  function isOneProng(cpNode) {
6931
7060
  const cp1 = cpNode;
@@ -7176,6 +7305,12 @@ function compareCps(a, b) {
7176
7305
 
7177
7306
  ;// ./src/cp-node/fs/cp-node-comparator.ts
7178
7307
 
7308
+ /**
7309
+ * Primarily for internal use.
7310
+ *
7311
+ * Compares the order of two `CpNode`s. The order is cyclic and depends
7312
+ * on a `CpNode`'s relative position along the shape boundary.
7313
+ */
7179
7314
  function cpNodeComparator(a, b) {
7180
7315
  return compareCps(a.cp, b.cp);
7181
7316
  }
@@ -7357,20 +7492,20 @@ const CpNodeFs = {
7357
7492
  */
7358
7493
  clone: clone,
7359
7494
  /**
7360
- * Returns the ordered bezier curves from this CpNode to the next CpNode
7495
+ * Returns the ordered bezier curves from this `CpNode` to the next `CpNode`
7361
7496
  * on the boundary.
7362
7497
  * @param cpNode
7363
7498
  */
7364
7499
  getBoundaryBezierPartsToNext: getBoundaryBezierPartsToNext,
7365
7500
  /**
7366
- * Returns the ordered bezier curves from this CpNode to the next CpNode
7501
+ * Returns the ordered bezier curves from this `CpNode` to the next `CpNode`
7367
7502
  * on the boundary.
7368
7503
  * @param cpNode
7369
7504
  */
7370
7505
  getBoundaryBeziersToNext: getBoundaryBeziersToNext,
7371
7506
  /**
7372
- * Removes a cpNode from the MAT.
7373
- * @param cpTree The tree graph holding the `CpNodes` of the MAT.
7507
+ * Removes a `CpNode` from the MAT.
7508
+ * @param cpTree The tree graph holding the `CpNode`s of the MAT.
7374
7509
  * @param cpNode The `CpNode` to remove.
7375
7510
  */
7376
7511
  removeVertex: removeVertex,
@@ -7413,9 +7548,7 @@ const CpNodeFs = {
7413
7548
 
7414
7549
  function isSpecial(cpNode) {
7415
7550
  return ((getRealProngCount(cpNode) !== 2) &&
7416
- !cpNode.isHoleClosing /* && cpNode.cp.circle.radius !== 0*/
7417
- // !cpNode.isHoleClosing && cpNode.cp.circle.radius !== 0 // TODO2
7418
- );
7551
+ !cpNode.isHoleClosing);
7419
7552
  }
7420
7553
 
7421
7554
 
@@ -26874,10 +27007,7 @@ function getCpNodeToLeftOrSame(cpTree, pos, order, order2) {
26874
27007
 
26875
27008
  ;// ./src/cp-node/fs/is-order-correct.ts
26876
27009
 
26877
- function isOrderCorrect(
26878
- // isHoleClosing: boolean,
26879
- cpTree, cp, next) {
26880
- // if (isHoleClosing) { return true; }
27010
+ function isOrderCorrect(cpTree, cp, next) {
26881
27011
  // TODO2
26882
27012
  const c = compareCps(cp, next.cp);
26883
27013
  if (c < 0) {
@@ -26969,9 +27099,7 @@ function byAngle(circle) {
26969
27099
  *
26970
27100
  * @internal
26971
27101
  */
26972
- function addToCpTree(insertIfOrderIsWrong, isHoleClosing, circle, orders,
26973
- // cpTrees: Map<Loop,LlRbTree<CpNode>>,
26974
- meta, poss, neighbors) {
27102
+ function addToCpTree(insertIfOrderIsWrong, isHoleClosing, circle, orders, meta, poss, neighbors) {
26975
27103
  const { cpTrees } = meta;
26976
27104
  let anyFailed = false;
26977
27105
  const cpNodes = poss.map((pos, i) => {
@@ -28301,16 +28429,18 @@ function add2Prong(meta, circle, poss, isHoleClosing) {
28301
28429
  }
28302
28430
  return cpNodes[0]; // return the source `CpNode`
28303
28431
  }
28304
- function closeHole(meta,
28305
- // cpTrees: Map<Loop, LlRbTree<CpNode>>,
28306
- cpNodes) {
28432
+ function closeHole(meta, cpNodes) {
28307
28433
  const { cpTrees } = meta;
28308
28434
  const [cpNodeA, cpNodeB] = cpNodes;
28309
28435
  // Duplicate ContactPoints
28310
28436
  // const antipodeCpNode = cpNodeB[0];
28311
28437
  const cpAntipode = cpNodeB.cp;
28312
28438
  const cpNodeB2 = insertCpNode(true, true, false, cpTrees.get(cpAntipode.pointOnShape.curve.loop), { ...cpAntipode, order2: +1 }, cpNodeB, meta.lastInsertId);
28439
+ cpNodeB2.holeCloserTwin = cpNodeB;
28440
+ cpNodeB.holeCloserTwin = cpNodeB2;
28313
28441
  const cpNodeB1 = insertCpNode(true, true, false, cpTrees.get(cpNodeA.cp.pointOnShape.curve.loop), { ...cpNodeA.cp, order2: -1 }, cpNodeA.prev, meta.lastInsertId);
28442
+ cpNodeB1.holeCloserTwin = cpNodeA;
28443
+ cpNodeA.holeCloserTwin = cpNodeB1;
28314
28444
  // Connect graph
28315
28445
  cpNodeB1.prevOnCircle = cpNodeB2;
28316
28446
  cpNodeB1.nextOnCircle = cpNodeB2;
@@ -30637,6 +30767,14 @@ const getMatDistanceToNext$ = memoize(getMatDistanceToNext);
30637
30767
 
30638
30768
 
30639
30769
  ;// ./src/floyd-warshall/get-hole-closer-pairs.ts
30770
+ /**
30771
+ *
30772
+ * @param holeClosers
30773
+ * @returns
30774
+ */
30775
+ // TODO - this function is currently O(n^2) but could be made O(n).
30776
+ // TODO - only `pointOnShape.p` is checked but `pointOnShape.t` should also be checked
30777
+ // or better yet, `CpNode.cp.order` and `CpNode.cp.order2`, etc.
30640
30778
  function getHoleCloserPairs(holeClosers) {
30641
30779
  const pairs = new Map();
30642
30780
  for (let hcA of holeClosers) {
@@ -30685,7 +30823,7 @@ function getGraph(specialVertices, holeClosers) {
30685
30823
  }
30686
30824
  if (child.isHoleClosing) {
30687
30825
  // Hole closer found - don't go around loop
30688
- child = holeCloserNext(pairs, child);
30826
+ child = getHoleCloserNext(pairs, child);
30689
30827
  continue;
30690
30828
  }
30691
30829
  if (isVertexSpecial(child)) {
@@ -30706,7 +30844,7 @@ function getGraph(specialVertices, holeClosers) {
30706
30844
  }
30707
30845
  return graph;
30708
30846
  }
30709
- function holeCloserNext(pairs, holeCloser) {
30847
+ function getHoleCloserNext(pairs, holeCloser) {
30710
30848
  return pairs.get(holeCloser).next;
30711
30849
  }
30712
30850