@itwin/core-geometry 5.2.0 → 5.2.1

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 (90) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/lib/cjs/curve/Arc3d.d.ts.map +1 -1
  3. package/lib/cjs/curve/Arc3d.js +5 -7
  4. package/lib/cjs/curve/Arc3d.js.map +1 -1
  5. package/lib/cjs/curve/CurveOps.d.ts +2 -5
  6. package/lib/cjs/curve/CurveOps.d.ts.map +1 -1
  7. package/lib/cjs/curve/CurveOps.js +2 -5
  8. package/lib/cjs/curve/CurveOps.js.map +1 -1
  9. package/lib/cjs/curve/Query/PlanarSubdivision.d.ts +50 -15
  10. package/lib/cjs/curve/Query/PlanarSubdivision.d.ts.map +1 -1
  11. package/lib/cjs/curve/Query/PlanarSubdivision.js +102 -84
  12. package/lib/cjs/curve/Query/PlanarSubdivision.js.map +1 -1
  13. package/lib/cjs/curve/RegionOps.d.ts +44 -25
  14. package/lib/cjs/curve/RegionOps.d.ts.map +1 -1
  15. package/lib/cjs/curve/RegionOps.js +74 -39
  16. package/lib/cjs/curve/RegionOps.js.map +1 -1
  17. package/lib/cjs/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  18. package/lib/cjs/curve/RegionOpsClassificationSweeps.js +8 -8
  19. package/lib/cjs/curve/RegionOpsClassificationSweeps.js.map +1 -1
  20. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts +1 -0
  21. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  22. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js +102 -92
  23. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  24. package/lib/cjs/geometry3d/GrowableXYArray.d.ts +2 -1
  25. package/lib/cjs/geometry3d/GrowableXYArray.d.ts.map +1 -1
  26. package/lib/cjs/geometry3d/GrowableXYArray.js +2 -1
  27. package/lib/cjs/geometry3d/GrowableXYArray.js.map +1 -1
  28. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts +2 -1
  29. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  30. package/lib/cjs/geometry3d/GrowableXYZArray.js +2 -1
  31. package/lib/cjs/geometry3d/GrowableXYZArray.js.map +1 -1
  32. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts +9 -16
  33. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  34. package/lib/cjs/geometry3d/IndexedXYZCollection.js +3 -3
  35. package/lib/cjs/geometry3d/IndexedXYZCollection.js.map +1 -1
  36. package/lib/cjs/geometry3d/PolylineOps.d.ts +2 -2
  37. package/lib/cjs/geometry3d/PolylineOps.js +2 -2
  38. package/lib/cjs/geometry3d/PolylineOps.js.map +1 -1
  39. package/lib/cjs/numerics/ClusterableArray.d.ts.map +1 -1
  40. package/lib/cjs/numerics/ClusterableArray.js +2 -2
  41. package/lib/cjs/numerics/ClusterableArray.js.map +1 -1
  42. package/lib/cjs/topology/Merging.d.ts +15 -7
  43. package/lib/cjs/topology/Merging.d.ts.map +1 -1
  44. package/lib/cjs/topology/Merging.js +15 -10
  45. package/lib/cjs/topology/Merging.js.map +1 -1
  46. package/lib/esm/curve/Arc3d.d.ts.map +1 -1
  47. package/lib/esm/curve/Arc3d.js +5 -7
  48. package/lib/esm/curve/Arc3d.js.map +1 -1
  49. package/lib/esm/curve/CurveOps.d.ts +2 -5
  50. package/lib/esm/curve/CurveOps.d.ts.map +1 -1
  51. package/lib/esm/curve/CurveOps.js +2 -5
  52. package/lib/esm/curve/CurveOps.js.map +1 -1
  53. package/lib/esm/curve/Query/PlanarSubdivision.d.ts +50 -15
  54. package/lib/esm/curve/Query/PlanarSubdivision.d.ts.map +1 -1
  55. package/lib/esm/curve/Query/PlanarSubdivision.js +102 -84
  56. package/lib/esm/curve/Query/PlanarSubdivision.js.map +1 -1
  57. package/lib/esm/curve/RegionOps.d.ts +44 -25
  58. package/lib/esm/curve/RegionOps.d.ts.map +1 -1
  59. package/lib/esm/curve/RegionOps.js +72 -37
  60. package/lib/esm/curve/RegionOps.js.map +1 -1
  61. package/lib/esm/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  62. package/lib/esm/curve/RegionOpsClassificationSweeps.js +8 -8
  63. package/lib/esm/curve/RegionOpsClassificationSweeps.js.map +1 -1
  64. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts +1 -0
  65. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  66. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js +102 -92
  67. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  68. package/lib/esm/geometry3d/GrowableXYArray.d.ts +2 -1
  69. package/lib/esm/geometry3d/GrowableXYArray.d.ts.map +1 -1
  70. package/lib/esm/geometry3d/GrowableXYArray.js +2 -1
  71. package/lib/esm/geometry3d/GrowableXYArray.js.map +1 -1
  72. package/lib/esm/geometry3d/GrowableXYZArray.d.ts +2 -1
  73. package/lib/esm/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  74. package/lib/esm/geometry3d/GrowableXYZArray.js +2 -1
  75. package/lib/esm/geometry3d/GrowableXYZArray.js.map +1 -1
  76. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts +9 -16
  77. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  78. package/lib/esm/geometry3d/IndexedXYZCollection.js +3 -3
  79. package/lib/esm/geometry3d/IndexedXYZCollection.js.map +1 -1
  80. package/lib/esm/geometry3d/PolylineOps.d.ts +2 -2
  81. package/lib/esm/geometry3d/PolylineOps.js +2 -2
  82. package/lib/esm/geometry3d/PolylineOps.js.map +1 -1
  83. package/lib/esm/numerics/ClusterableArray.d.ts.map +1 -1
  84. package/lib/esm/numerics/ClusterableArray.js +2 -2
  85. package/lib/esm/numerics/ClusterableArray.js.map +1 -1
  86. package/lib/esm/topology/Merging.d.ts +15 -7
  87. package/lib/esm/topology/Merging.d.ts.map +1 -1
  88. package/lib/esm/topology/Merging.js +15 -10
  89. package/lib/esm/topology/Merging.js.map +1 -1
  90. package/package.json +3 -3
@@ -325,13 +325,21 @@ export class HalfEdgeGraphMerge {
325
325
  static isNullFace(node) {
326
326
  return node.isMaskSet(HalfEdgeMask.NULL_FACE) && node.faceSuccessor.isMaskSet(HalfEdgeMask.NULL_FACE) && node === node.faceSuccessor.faceSuccessor;
327
327
  }
328
- /** Simplest merge algorithm:
329
- * * collect array of (x,y,theta) at all nodes
330
- * * lexical sort of the array.
331
- * * twist all vertices together.
332
- * * This effectively creates valid face loops for a planar subdivision if there are no edge crossings.
333
- * * If there are edge crossings, the graph can be a (highly complicated) Klein bottle topology.
334
- * * Mask.NULL_FACE is cleared throughout and applied within null faces.
328
+ /**
329
+ * Cluster the HalfEdges so that xy-coordinates within `mergeTolerance` are equated.
330
+ * * Note that any additional data (e.g., edgeTag, faceTag) on the HalfEdges are ignored. In particular,
331
+ * [[CurveLocationDetail]]s attached to clustered HalfEdges do *not* get their points adjusted.
332
+ * * This is a simple merge algorithm:
333
+ * * untwist all edges from the vertex loops
334
+ * * collect array of (x,y,theta) at all nodes
335
+ * * lexical sort of the array
336
+ * * twist all edges together in sort order around each vertex
337
+ * * This effectively creates valid face loops for a planar subdivision if there are no edge crossings.
338
+ * * If there are edge crossings, the graph can be a (highly complicated) Klein bottle topology.
339
+ * * [[HalfEdgeMask.NULL_FACE]] is cleared throughout and applied within null faces.
340
+ * @param graph input graph
341
+ * @param outboundRadiansFunction optional function to compute the sort angle of an edge at its start vertex
342
+ * @param clusterTol optional distance tolerance for clustering vertices. Default value is [[Geometry.smallMetricDistance]].
335
343
  */
336
344
  static clusterAndMergeXYTheta(graph, outboundRadiansFunction, clusterTol = Geometry.smallMetricDistance) {
337
345
  const allNodes = graph.allHalfEdges;
@@ -389,14 +397,11 @@ export class HalfEdgeGraphMerge {
389
397
  const unmatchedNullFaceNodes = [];
390
398
  k0 = 0;
391
399
  let thetaA, thetaB;
392
- // GeometryCoreTestIO.consoleLog("START VERTEX LINKS");
393
400
  // now pinch each neighboring pair together
394
401
  for (let k1 = 0; k1 < numK; k1++) {
395
402
  if (order[k1] === ClusterableArray.clusterTerminator) {
396
403
  // nodes identified in order[k0]..order[k1-1] are properly sorted around a vertex.
397
404
  if (k1 > k0) {
398
- // const xy = clusters.getPoint2d(order[k0]);
399
- // GeometryCoreTestIO.consoleLog({ k0, k1, x: xy.x, y: xy.y });
400
405
  if (k1 > k0 + 1)
401
406
  this.secondarySortAroundVertex(clusters, order, allNodes, k0, k1);
402
407
  this.doAnnounceVertexNeighborhood(clusters, order, allNodes, k0, k1);
@@ -1 +1 @@
1
- {"version":3,"file":"Merging.js","sourceRoot":"","sources":["../../../src/topology/Merging.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAE/F;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,qCAAqC,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,mBAAmB;AAEnB,MAAM,OAAO,cAAc;IAClB,SAAS,GAAG,CAAC,CAAC;IACd,mBAAmB,GAAG,CAAC,CAAC;IACxB,QAAQ,GAAG,CAAC,CAAC;IACb,SAAS,GAAG,CAAC,CAAC;IACd,OAAO,GAAG,CAAC,CAAC;IACZ,OAAO,GAAG,CAAC,CAAC;IACnB;IACA,CAAC;CACF;AACD;;GAEG;AACH,MAAM,OAAO,0BAA0B;IAC9B,KAAK,CAAS;IACd,iBAAiB,CAAS;IAC1B,IAAI,CAAW;IACf,OAAO,CAAU;IACxB,YAAmB,KAAa,EAAE,GAAW,EAAE,IAAc,EAAE,OAAgB;QAC7E,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,iBAAiB,GAAG,GAAG,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAID;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IAE3B,iFAAiF;IAC1E,MAAM,CAAC,gBAAgB,CAAC,CAAW,EAAE,CAAW;QACrD,YAAY;QACZ,4CAA4C;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACX,OAAO,CAAC,CAAC,CAAC;aACP,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAChB,OAAO,CAAC,CAAC;QACX,YAAY;QACZ,4CAA4C;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACX,OAAO,CAAC,CAAC,CAAC;aACP,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAChB,OAAO,CAAC,CAAC;QACX,OAAO,CAAC,CAAC;IACX,CAAC;IAED,mIAAmI;IAC5H,MAAM,CAAC,UAAU,CAAC,KAAe;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,CAAC;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC;QAClC,OAAO,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;eACzC,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;eACvC,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,qBAAqB,CAAC,IAAc,EAAE,OAAiB,EAAE,OAAiB;QACtF,OAAO,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACnH,CAAC;IAED,iDAAiD;IAC1C,MAAM,CAAC,UAAU,CAAC,KAA8B;QACrD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACtC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,oDAAoD;IAC7C,MAAM,CAAC,YAAY,CAAC,KAA8B;QACvD,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACtC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,gFAAgF;IACzE,MAAM,CAAC,wBAAwB,CAAC,QAAyB,EAAE,WAA0B,EAAE,IAAkB;QAC9G,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,kFAAkF;QAClF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAE/B,MAAM,KAAK,GAAG,WAAW,CAAC,gBAAgB,CACxC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAC7D,UAAU,EACV,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAC7D,UAAU,GAAG,CAAC,CAAC,CAAC;YAElB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC;YAC7B,UAAU,IAAI,CAAC,CAAC;YAEhB,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAG,sDAAsD;YACvF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,eAAe,CAAC,KAAoB;QAChD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,KAAK,CAAC,iBAAiB,CAAC;YACtC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD;;;;;;;OAOG;IACK,MAAM,CAAC,8BAA8B,CAAC,IAAc,EAAE,MAAoB,EAAE,OAAqB,EAAE,gBAAwB,CAAC;QAClI,IAAI,EAAE,GAAG,IAAI,CAAC;QACd,GAAG,CAAC,CAAC,8DAA8D;YACjE,IAAI,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC;gBACzD,MAAM;YACR,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC;QAC1B,CAAC,QAAQ,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;QAC9C,IAAI,EAAE,KAAK,IAAI;YACb,OAAO,KAAK,CAAC;QACf,IAAI,EAAE,GAAG,IAAI,CAAC;QACd,GAAG,CAAC,CAAC,2DAA2D;YAC9D,IAAI,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC;gBACzD,MAAM;YACR,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC;QAC5B,CAAC,QAAQ,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;QAC9C,IAAI,EAAE,KAAK,IAAI;YACb,OAAO,KAAK,CAAC;QACf,OAAO,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACrF,CAAC;IACD;;;;;;;;OAQG;IACI,MAAM,CAAC,qCAAqC,CAAC,KAAoB,EAAE,IAAkB,EAAE,UAAwB,YAAY,CAAC,aAAa;QAC9I,IAAI,YAAY,CAAC,SAAS,KAAK,IAAI;YACjC,OAAO,CAAC,CAAC;QACX,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;oBAClE,gFAAgF;oBAChF,MAAM,aAAa,GAAG,QAAQ,CAAC,0BAA0B,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;oBACrH,IAAI,IAAI,CAAC,8BAA8B,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,IAAI,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC;wBAChK,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;wBAC7B,EAAE,SAAS,CAAC;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD;;;;;;;OAOG;IACI,MAAM,CAAC,wCAAwC,CAAC,KAAoB,EAAE,UAAwB,YAAY,CAAC,aAAa;QAC7H,MAAM,SAAS,GAAe,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG,IAAI,CAAC,qCAAqC,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YACzE,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACrC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;gBACtC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;oBACrD,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;oBAChC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;YACD,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,iBAAiB,CAAC,KAAoB,EAAE,UAAwB,YAAY,CAAC,aAAa;QACtG,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,eAAe,GAAG,IAAI,CAAC,qCAAqC,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACzF,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,cAAc,GAAG,GAAG,GAAG,KAAK,CAAC,kBAAkB,CAAC,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9F,MAAM,CAAC,cAAc,KAAK,eAAe,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO,eAAe,CAAC;IACzB,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,iBAAiB,CAAC,KAAoB,EAAE,QAAsB,YAAY,CAAC,QAAQ;QAC/F,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;gBAChC,SAAS;YACX,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;gBACtB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAC7B,uEAAuE;IACvE,uDAAuD;IACvD,+EAA+E;IACxE,MAAM,CAAC,sBAAsB,CAAC,QAA0B,EAAE,KAAkB,EAAE,EAAU,EAAE,EAAU;QACzG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAChB,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,EAAE,EAAE,CAAC;QACP,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IACO,MAAM,CAAC,mCAAmC,CAAsC;IACxF;;OAEG;IACI,MAAM,KAAK,kCAAkC,CAAC,IAAoD,IAAI,IAAI,CAAC,mCAAmC,GAAG,IAAI,CAAC,CAAC,CAAC;IACvJ,MAAM,CAAC,4BAA4B,CAAC,QAA0B,EAAE,KAAkB,EAAE,QAAoB,EAAE,EAAU,EAAE,EAAU;QACtI,IAAI,IAAI,CAAC,mCAAmC,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAiC,EAAE,CAAC;YAClD,0CAA0C;YAC1C,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC7B,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACnD,QAAQ,CAAC,IAAI,CAAC,IAAI,0BAA0B,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACvF,CAAC;YACD,IAAI,CAAC,mCAAmC,CAAC,QAAQ,CAAC,CAAC;QACrD,CAAC;IAEH,CAAC;IACD,mCAAmC;IACnC,yCAAyC;IACzC,gDAAgD;IAChD,6DAA6D;IAC7D,mCAAmC;IACnC,iCAAiC;IACzB,MAAM,CAAC,yBAAyB,CAAC,QAA0B,EAAE,KAAkB,EAAE,QAAoB,EAAE,EAAU,EAAE,EAAU;QACnI,MAAM,QAAQ,GAAiC,EAAE,CAAC;QAElD,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/D,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC;gBACf,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;gBACpB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;oBAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;oBAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;oBAC7B,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;oBACnD,QAAQ,CAAC,IAAI,CAAC,IAAI,0BAA0B,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;gBACjF,CAAC;gBACD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAA6B,EAAE,CAA6B,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;gBAC7H,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACzC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;gBACnC,CAAC;YACH,CAAC;YACD,CAAC,GAAG,EAAE,CAAC;QACT,CAAC;IACH,CAAC;IACD;;;OAGG;IACI,MAAM,CAAC,gBAAgB,CAAC,IAAc;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,OAA8B,CAAC;QAChD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;YAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YACxB,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,MAAM,GAAG,KAAK,CAAC,mCAAmC,CAAC,QAAQ,CAAC,CAAC;gBACjE,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC;oBAClD,MAAM,GAAG,CAAC,MAAM,CAAC;gBACnB,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,4FAA4F;IACrF,MAAM,CAAC,UAAU,CAAC,IAAc;QACrC,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,IAAI,KAAK,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC;IACrJ,CAAC;IACD;;;;;;;OAOG;IACI,MAAM,CAAC,sBAAsB,CAClC,KAAoB,EACpB,uBAAkD,EAClD,aAAqB,QAAQ,CAAC,mBAAmB;QAEjD,MAAM,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC;QACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC;QACjC,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAE,yEAAyE;QACjI,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;YACnB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;YACnB,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC,CAAE,0CAA0C;YACzF,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACrC,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,EAAE,GAAG,CAAC,CAAC;QACX,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC;QAC1B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,EAAE,CAAC,KAAK,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;gBACrD,sFAAsF;gBACtF,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;oBACZ,MAAM,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC/C,MAAM,MAAM,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;oBAC5B,KAAK,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;wBACjC,MAAM,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;wBAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;wBAC3B,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;wBACnB,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;oBACrB,CAAC;gBACH,CAAC;gBACD,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC;QACD,MAAM;QACN,4EAA4E;QAC5E,qDAAqD;QAErD,qDAAqD;QACrD,KAAK,MAAM,iBAAiB,IAAI,KAAK,EAAE,CAAC;YACtC,IAAI,iBAAiB,KAAK,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;gBAC7D,MAAM,KAAK,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC;gBAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC;gBAClC,IAAI,qBAAqB,GAAG,uBAAuB,CAAC;gBACpD,IAAI,qBAAqB,EAAE,CAAC;oBAC1B,4HAA4H;oBAC5H,MAAM,MAAM,GAAG,KAAK,CAAC,OAA8B,CAAC;oBACpD,IAAI,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,YAAY,aAAa;wBAC7F,qBAAqB,GAAG,SAAS,CAAC;gBACtC,CAAC;gBACD,IAAI,OAAO,GAAG,qBAAqB,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtH,IAAI,KAAK,CAAC,oCAAoC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/D,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;gBACpB,QAAQ,CAAC,YAAY,CAAC,iBAAiB,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,sBAAsB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1C,MAAM,sBAAsB,GAAe,EAAE,CAAC;QAC9C,EAAE,GAAG,CAAC,CAAC;QACP,IAAI,MAAM,EAAE,MAAM,CAAC;QACnB,uDAAuD;QAEvD,2CAA2C;QAC3C,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,EAAE,CAAC,KAAK,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;gBACrD,kFAAkF;gBAClF,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;oBACZ,6CAA6C;oBAC7C,+DAA+D;oBAC/D,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;wBACb,IAAI,CAAC,yBAAyB,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;oBACpE,IAAI,CAAC,4BAA4B,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;oBACrE,MAAM,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC/C,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;oBAC5B,IAAI,KAAK,GAAG,MAAM,CAAC;oBACnB,KAAK,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;wBACjC,MAAM,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;wBAC9C,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;wBAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;wBAC3B,IAAI,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;4BAC5C,8DAA8D;4BAC9D,MAAM,CAAC,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC,IAAc,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;4BAC/E,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gCACX,sBAAsB,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC,sBAAsB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gCACtF,sBAAsB,CAAC,GAAG,EAAE,CAAC;4BAC/B,CAAC;4BACD,KAAK,GAAG,KAAK,CAAC;4BACd,MAAM,GAAG,MAAM,CAAC;wBAClB,CAAC;6BAAM,IAAI,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;4BACnD,MAAM,CAAC,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC,IAAc,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;4BAC/E,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gCACX,sBAAsB,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC,sBAAsB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gCACtF,sBAAsB,CAAC,GAAG,EAAE,CAAC;4BAC/B,CAAC;4BACD,6FAA6F;wBAC/F,CAAC;6BAAM,CAAC;4BACN,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;4BAE7B,wCAAwC;4BACxC,wDAAwD;4BACxD,6CAA6C;4BAC7C,kDAAkD;4BAClD,8CAA8C;4BAC9C,IAAI,KAAK,CAAC,oCAAoC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;gCAC/D,MAAM,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC;gCACnC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC;gCAC9B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;oCAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;oCACxC,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;oCACxC,IAAI,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,CAAE,kBAAkB;wCACtE,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;wCAC/B,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;wCACtC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;wCACvC,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oCACtC,CAAC;gCACH,CAAC;4BACH,CAAC;4BACD,KAAK,GAAG,KAAK,CAAC;4BACd,MAAM,GAAG,MAAM,CAAC;wBAClB,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAEO,MAAM,CAAC,+BAA+B,CAAC,KAAoB;QACjE,MAAM,SAAS,GAAG,IAAI,qCAAqC,EAAE,CAAC;QAC9D,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YAEnC,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9D,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,MAAM,CAAC,mCAAmC,CAAC,MAAgB,EAAE,MAAgB,EAAE,MAAc,QAAQ,CAAC,mBAAmB;QAC/H,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC;QACpC,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC;QAChE,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC;QACpC,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC;QAChE,IAAI,SAAS,GAAG,WAAW,CAAC,oCAAoC,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAClG,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,qBAAqB,GAAG,CAAC,QAAgB,EAAE,QAAe,EAAE,MAAa,EAAU,EAAE;gBACzF,MAAM,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC/D,MAAM,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC/D,IAAI,QAAQ,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;oBAChE,OAAO,GAAG,CAAC;gBACb,IAAI,QAAQ,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC;oBAC5D,OAAO,GAAG,CAAC;gBACb,OAAO,QAAQ,CAAC;YAClB,CAAC,CAAC;YACF,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACvE,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACvE,IAAI,SAAS,CAAC,EAAE,EAAE,CAAC;gBACjB,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBACvE,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACzE,CAAC;YACD,IAAI,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACvF,SAAS,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,kEAAkE;YAC9F,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1E,IAAI,SAAS,CAAC,EAAE,EAAE,CAAC;oBACjB,SAAS,CAAC,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,oEAAoE;oBACjG,SAAS,CAAC,EAAE,GAAG,SAAS,CAAC;gBAC3B,CAAC;;oBACC,SAAS,GAAG,SAAS,CAAC,CAAC,gDAAgD;YAC3E,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD;;;;OAIG;IACI,MAAM,CAAC,sBAAsB,CAAC,KAAoB,EAAE,cAAsB,QAAQ,CAAC,mBAAmB,EAAE,cAAsB,MAAM;QACzI,MAAM,IAAI,GAAG,IAAI,cAAc,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,+BAA+B,CAAC,KAAK,CAAC,CAAC;QAC9D,IAAI,MAAM,EAAE,MAAM,CAAC;QACnB,MAAM,aAAa,GAAG,WAAW,CAAC;QAClC,MAAM,aAAa,GAAG,GAAG,GAAG,aAAa,CAAC;QAC1C,IAAI,CAAC,CAAC;QACN,IAAI,MAAM,CAAC;QACX,OAAO,SAAS,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC;YACxC,SAAS,CAAC,6BAA6B,CAAC,MAAM,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;YAChE,IAAI,CAAC,SAAS,IAAI,EAAE,GAAG,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC;YACpD,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAClD,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;gBAClC,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC;gBAC9B,IAAI,QAAQ,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC;oBACrF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,CAAC;qBAAM,IAAI,QAAQ,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC;oBAC5F,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,mCAAmC,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;oBACxF,IAAI,SAAS,EAAE,CAAC;wBACd,MAAM,YAAY,GAAG,CAAC,IAAc,EAAE,QAAiB,EAAQ,EAAE;4BAC/D,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,GAAG,aAAa,IAAI,QAAQ,GAAG,aAAa,EAAE,CAAC;gCACnF,MAAM,OAAO,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gCAC1D,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,mCAAmC;gCAC3E,IAAI,CAAC,QAAQ,EAAE,CAAC;4BAClB,CAAC;wBACH,CAAC,CAAC;wBACF,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;wBACrC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBACtC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;wBACrC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBACtC,0EAA0E;oBAC5E,CAAC;gBACH,CAAC;YACH,CAAC;YACD,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACI,MAAM,CAAC,qBAAqB,CAAC,YAA6B;QAC/D,uEAAuE;QACvE,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;QAClC,gBAAgB,CAAC,wBAAwB,CAAC,YAAY,EAAE,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC,CAAC;QAC3F,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,mBAAmB,CAAC,MAAkC,EAAE,aAAsB,IAAI,EAAE,OAAqB,YAAY,CAAC,YAAY;QAC9I,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YACnB,OAAO,SAAS,CAAC;QACnB,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,YAAY,CAAC,iCAAiC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACjF,KAAK,MAAM,IAAI,IAAI,UAAU;YAC3B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAE/B,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;YACjD,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CAEF","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n\r\nimport { assert } from \"@itwin/core-bentley\";\r\nimport { CurveLocationDetail } from \"../curve/CurveLocationDetail\";\r\nimport { LineSegment3d } from \"../curve/LineSegment3d\";\r\nimport { Geometry } from \"../Geometry\";\r\nimport { Angle } from \"../geometry3d/Angle\";\r\nimport { MultiLineStringDataVariant } from \"../geometry3d/IndexedXYZCollection\";\r\nimport { Range2d, Range3d } from \"../geometry3d/Range\";\r\nimport { XAndY } from \"../geometry3d/XYZProps\";\r\nimport { ClusterableArray } from \"../numerics/ClusterableArray\";\r\nimport { SmallSystem } from \"../numerics/SmallSystem\";\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { HalfEdgePriorityQueueWithPartnerArray } from \"./HalfEdgePriorityQueue\";\r\nimport { RegularizationContext } from \"./RegularizeFace\";\r\nimport { Triangulator } from \"./Triangulation\";\r\n\r\n// cspell:word XYUV\r\n\r\nexport class GraphSplitData {\r\n public numUpEdge = 0;\r\n public numIntersectionTest = 0;\r\n public numSplit = 0;\r\n public numPopOut = 0;\r\n public numA0B0 = 0;\r\n public numA0B1 = 0;\r\n public constructor() {\r\n }\r\n}\r\n/**\r\n * Structure for data used when sorting outbound edges \"around a node\"\r\n */\r\nexport class VertexNeighborhoodSortData {\r\n public index: number;\r\n public radiusOfCurvature: number;\r\n public node: HalfEdge;\r\n public radians?: number;\r\n public constructor(index: number, key: number, node: HalfEdge, radians?: number) {\r\n this.index = index;\r\n this.radiusOfCurvature = key;\r\n this.node = node;\r\n this.radians = radians;\r\n }\r\n}\r\n\r\n/** Function signature for announcing a vertex neighborhood during sorting. */\r\nexport type AnnounceVertexNeighborhoodSortData = (data: VertexNeighborhoodSortData[]) => any;\r\n/**\r\n * * Assorted methods used in algorithms on HalfEdgeGraph.\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphOps {\r\n\r\n /** Compare function for sorting with primary y compare, secondary x compare. */\r\n public static compareNodesYXUp(a: HalfEdge, b: HalfEdge) {\r\n // Check y's\r\n // if (!Geometry.isSameCoordinate(a.y, b.y))\r\n if (a.y < b.y)\r\n return -1;\r\n else if (a.y > b.y)\r\n return 1;\r\n // Check x's\r\n // if (!Geometry.isSameCoordinate(a.x, b.x))\r\n if (a.x < b.x)\r\n return -1;\r\n else if (a.x > b.x)\r\n return 1;\r\n return 0;\r\n }\r\n\r\n /** Return true if nodeB (a) is lower than both its neighbors and (b) inflects as a downward peak (rather than an upward trough) */\r\n public static isDownPeak(nodeB: HalfEdge) {\r\n const nodeA = nodeB.facePredecessor;\r\n const nodeC = nodeB.faceSuccessor;\r\n return this.compareNodesYXUp(nodeB, nodeA) < 0\r\n && this.compareNodesYXUp(nodeB, nodeC) < 0\r\n && this.crossProductToTargets(nodeB, nodeA, nodeC) > 0;\r\n }\r\n\r\n /** return the cross product of vectors from base to targetA and base to targetB\r\n * @param base base vertex of both vectors.\r\n * @param targetA target vertex of first vector\r\n * @param targetB target vertex of second vector\r\n */\r\n public static crossProductToTargets(base: HalfEdge, targetA: HalfEdge, targetB: HalfEdge): number {\r\n return Geometry.crossProductXYXY(targetA.x - base.x, targetA.y - base.y, targetB.x - base.x, targetB.y - base.y);\r\n }\r\n\r\n /** Compute the range of the graph's vertices. */\r\n public static graphRange(graph: Readonly<HalfEdgeGraph>): Range3d {\r\n const range = Range3d.create();\r\n for (const node of graph.allHalfEdges) {\r\n range.extendXYZ(node.x, node.y, node.z);\r\n }\r\n return range;\r\n }\r\n /** Compute the xy-range of the graph's vertices. */\r\n public static graphRangeXY(graph: Readonly<HalfEdgeGraph>): Range2d {\r\n const range = Range2d.createNull();\r\n for (const node of graph.allHalfEdges) {\r\n range.extendXY(node.x, node.y);\r\n }\r\n return range;\r\n }\r\n\r\n /** Returns an array of all nodes (both ends) of edges created from segments. */\r\n public static segmentArrayToGraphEdges(segments: LineSegment3d[], returnGraph: HalfEdgeGraph, mask: HalfEdgeMask): HalfEdge[] {\r\n const result = [];\r\n let idxCounter = 0;\r\n\r\n // Push the endpoints of each segment onto arr[] in the form {(x, y, theta), Node}\r\n for (const segment of segments) {\r\n\r\n const node0 = returnGraph.createEdgeXYZXYZ(\r\n segment.point0Ref.x, segment.point0Ref.y, segment.point0Ref.z,\r\n idxCounter,\r\n segment.point1Ref.x, segment.point1Ref.y, segment.point1Ref.z,\r\n idxCounter + 1);\r\n\r\n const node1 = node0.edgeMate;\r\n idxCounter += 2;\r\n\r\n node0.setMaskAroundFace(mask); // Original given coordinates must be part of boundary\r\n result.push(node0);\r\n result.push(node1);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * * Visit all nodes in `graph`.\r\n * * invoke `pinch(node, vertexPredecessor)`\r\n * * this leaves the graph as isolated edges.\r\n * @param graph graph to modify\r\n */\r\n public static isolateAllEdges(graph: HalfEdgeGraph) {\r\n for (const nodeA of graph.allHalfEdges) {\r\n const nodeB = nodeA.vertexPredecessor;\r\n HalfEdge.pinch(nodeA, nodeB);\r\n }\r\n }\r\n /**\r\n * Compute convexity of a sector of a super-face.\r\n * @param base node whose edge is to be tested for removal\r\n * @param ignore edges with this mask (on either side) are ignored for the purposes of computing convexity\r\n * @param barrier edges with this mask (on either side) will not be removed\r\n * @param signedAreaTol optional signed area tolerance to use in test for parallel vectors\r\n * @return whether removing the edge at base would create a convex sector in the super-face\r\n */\r\n private static isSectorConvexAfterEdgeRemoval(base: HalfEdge, ignore: HalfEdgeMask, barrier: HalfEdgeMask, signedAreaTol: number = 0): boolean {\r\n let vs = base;\r\n do { // loop ccw around vertex looking for a super-face predecessor\r\n if (vs.isMaskSet(barrier) || vs.edgeMate.isMaskSet(barrier))\r\n break;\r\n vs = vs.vertexSuccessor;\r\n } while (vs !== base && vs.isMaskSet(ignore));\r\n if (vs === base)\r\n return false;\r\n let vp = base;\r\n do { // loop cw around vertex looking for a super-face successor\r\n if (vp.isMaskSet(barrier) || vp.edgeMate.isMaskSet(barrier))\r\n break;\r\n vp = vp.vertexPredecessor;\r\n } while (vp !== base && vp.isMaskSet(ignore));\r\n if (vp === base)\r\n return false;\r\n return HalfEdge.isSectorConvex(vs.edgeMate, base, vp.faceSuccessor, signedAreaTol);\r\n }\r\n /**\r\n * Mask edges between faces if the union of the faces is convex.\r\n * Uses a greedy algorithm with no regard to quality of resulting convex faces.\r\n * Best results when input faces are convex.\r\n * @param graph graph to examine and mark\r\n * @param mark the mask used to mark (both sides of) removable edges\r\n * @param barrier edges with this mask (on either side) will not be marked. Defaults to HalfEdgeMask.BOUNDARY_EDGE.\r\n * @return number of edges masked (half the number of HalfEdges masked)\r\n */\r\n public static markRemovableEdgesToExpandConvexFaces(graph: HalfEdgeGraph, mark: HalfEdgeMask, barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE): number {\r\n if (HalfEdgeMask.NULL_MASK === mark)\r\n return 0;\r\n const visit = graph.grabMask(true);\r\n let numMarked = 0;\r\n for (const node of graph.allHalfEdges) {\r\n if (!node.isMaskSet(visit)) {\r\n if (!node.isMaskSet(barrier) && !node.edgeMate.isMaskSet(barrier)) {\r\n // tol based on areas of *original* faces on each side of the edge to be removed\r\n const signedAreaTol = Geometry.smallMetricDistanceSquared * (node.signedFaceArea() + node.edgeMate.signedFaceArea());\r\n if (this.isSectorConvexAfterEdgeRemoval(node, mark, barrier, signedAreaTol) && this.isSectorConvexAfterEdgeRemoval(node.edgeMate, mark, barrier, signedAreaTol)) {\r\n node.setMaskAroundEdge(mark);\r\n ++numMarked;\r\n }\r\n }\r\n }\r\n node.setMaskAroundEdge(visit);\r\n }\r\n graph.dropMask(visit);\r\n return numMarked;\r\n }\r\n /**\r\n * Collect edges between faces if the union of the faces is convex.\r\n * Uses a greedy algorithm with no regard to quality of resulting convex faces.\r\n * Best results when input faces are convex.\r\n * @param graph graph to examine\r\n * @param barrier edges with this mask (on either side) will not be collected. Defaults to HalfEdgeMask.BOUNDARY_EDGE.\r\n * @return one HalfEdge per removable edge\r\n */\r\n public static collectRemovableEdgesToExpandConvexFaces(graph: HalfEdgeGraph, barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE): HalfEdge[] | undefined {\r\n const removable: HalfEdge[] = [];\r\n const mark = graph.grabMask(true);\r\n if (0 < this.markRemovableEdgesToExpandConvexFaces(graph, mark, barrier)) {\r\n const visited = graph.grabMask(true);\r\n for (const node of graph.allHalfEdges) {\r\n if (node.isMaskSet(mark) && !node.isMaskSet(visited)) {\r\n node.setMaskAroundEdge(visited);\r\n removable.push(node);\r\n }\r\n }\r\n graph.dropMask(visited);\r\n }\r\n graph.dropMask(mark);\r\n return removable;\r\n }\r\n\r\n /**\r\n * Remove edges between faces if the union of the faces is convex.\r\n * Uses a greedy algorithm with no regard to quality of resulting convex faces.\r\n * Best results when input faces are convex.\r\n * @param graph graph to modify\r\n * @param barrier edges with this mask (on either side) will not be removed. Defaults to HalfEdgeMask.BOUNDARY_EDGE.\r\n * @return number of edges deleted\r\n */\r\n public static expandConvexFaces(graph: HalfEdgeGraph, barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE): number {\r\n const mark = graph.grabMask(true);\r\n const numRemovedEdges = this.markRemovableEdgesToExpandConvexFaces(graph, mark, barrier);\r\n if (numRemovedEdges > 0) {\r\n const numYankedEdges = 0.5 * graph.yankAndDeleteEdges((node: HalfEdge) => node.getMask(mark));\r\n assert(numYankedEdges === numRemovedEdges);\r\n }\r\n graph.dropMask(mark);\r\n return numRemovedEdges;\r\n }\r\n\r\n /**\r\n * Test desired faces for convexity.\r\n * @param graph graph to examine\r\n * @param avoid faces with this mask will not be examined. Defaults to HalfEdgeMask.EXTERIOR.\r\n * @return whether every face in the graph is convex\r\n */\r\n public static isEveryFaceConvex(graph: HalfEdgeGraph, avoid: HalfEdgeMask = HalfEdgeMask.EXTERIOR): boolean {\r\n const allFaces = graph.collectFaceLoops();\r\n for (const node of allFaces) {\r\n if (node.isMaskedAroundFace(avoid))\r\n continue;\r\n if (!node.isFaceConvex())\r\n return false;\r\n }\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Note: this class uses hardcoded micrometer coordinate/cluster tolerance throughout.\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphMerge {\r\n // return kC such that all angles k are equal, with kA <= k < kC <= kB.\r\n // * Assume: angles k are stored at extra data index 0.\r\n // * Note that the usual case (when angle at kA is not repeated) is kA+1 === kC\r\n public static getCommonThetaEndIndex(clusters: ClusterableArray, order: Uint32Array, kA: number, kB: number): number {\r\n let kC = kA + 1;\r\n const thetaA = clusters.getExtraData(order[kA], 0);\r\n while (kC < kB) {\r\n const thetaB = clusters.getExtraData(order[kC], 0);\r\n if (!Angle.isAlmostEqualRadiansAllowPeriodShift(thetaA, thetaB)) {\r\n return kC;\r\n }\r\n kC++;\r\n }\r\n return kC;\r\n }\r\n private static _announceVertexNeighborhoodFunction?: AnnounceVertexNeighborhoodSortData;\r\n /**\r\n * public property setter for a function to be called with sorted edge data around a vertex.\r\n */\r\n public static set announceVertexNeighborhoodFunction(func: AnnounceVertexNeighborhoodSortData | undefined) { this._announceVertexNeighborhoodFunction = func; }\r\n private static doAnnounceVertexNeighborhood(clusters: ClusterableArray, order: Uint32Array, allNodes: HalfEdge[], k0: number, k1: number) {\r\n if (this._announceVertexNeighborhoodFunction) {\r\n const sortData: VertexNeighborhoodSortData[] = [];\r\n // build and share the entire vertex order\r\n for (let k = k0; k < k1; k++) {\r\n const index = clusters.getExtraData(order[k], 1);\r\n const theta = clusters.getExtraData(order[k], 0);\r\n const node = allNodes[index];\r\n const signedDistance = this.curvatureSortKey(node);\r\n sortData.push(new VertexNeighborhoodSortData(order[k], signedDistance, node, theta));\r\n }\r\n this._announceVertexNeighborhoodFunction(sortData);\r\n }\r\n\r\n }\r\n // assumptions about cluster array:\r\n // * data order is: x,y,theta,nodeIndex\r\n // * theta and nodeIndex are the \"extra\" data.\r\n // * only want to do anything here when curves are present.\r\n // * k0<=k<k1 are around a vertex\r\n // * These are sorted by theta.\r\n private static secondarySortAroundVertex(clusters: ClusterableArray, order: Uint32Array, allNodes: HalfEdge[], k0: number, k1: number) {\r\n const sortData: VertexNeighborhoodSortData[] = [];\r\n\r\n for (let k = k0; k < k1;) {\r\n const kB = this.getCommonThetaEndIndex(clusters, order, k, k1);\r\n if (k + 1 < kB) {\r\n sortData.length = 0;\r\n for (let kA = k; kA < kB; kA++) {\r\n const index = clusters.getExtraData(order[kA], 1);\r\n const node = allNodes[index];\r\n const signedDistance = this.curvatureSortKey(node);\r\n sortData.push(new VertexNeighborhoodSortData(order[kA], signedDistance, node));\r\n }\r\n sortData.sort((a: VertexNeighborhoodSortData, b: VertexNeighborhoodSortData) => (a.radiusOfCurvature - b.radiusOfCurvature));\r\n for (let i = 0; i < sortData.length; i++) {\r\n order[k + i] = sortData[i].index;\r\n }\r\n }\r\n k = kB;\r\n }\r\n }\r\n /** Return the sort key for sorting by curvature.\r\n * * This is the signed distance from the curve at the edge start, to center of curvature.\r\n * * NOTE: Currently does not account for higher derivatives in the case of higher-than-tangent match.\r\n */\r\n public static curvatureSortKey(node: HalfEdge): number {\r\n const cld = node.edgeTag as CurveLocationDetail;\r\n if (cld !== undefined) {\r\n const fraction = cld.fraction;\r\n const curve = cld.curve;\r\n if (curve) {\r\n let radius = curve.fractionToSignedXYRadiusOfCurvature(fraction);\r\n if (node.sortData !== undefined && node.sortData < 0)\r\n radius = -radius;\r\n return radius;\r\n }\r\n }\r\n return 0.0;\r\n }\r\n /** Whether the HalfEdge is part of a null face, as marked by [[clusterAndMergeXYTheta]]. */\r\n public static isNullFace(node: HalfEdge): boolean {\r\n return node.isMaskSet(HalfEdgeMask.NULL_FACE) && node.faceSuccessor.isMaskSet(HalfEdgeMask.NULL_FACE) && node === node.faceSuccessor.faceSuccessor;\r\n }\r\n /** Simplest merge algorithm:\r\n * * collect array of (x,y,theta) at all nodes\r\n * * lexical sort of the array.\r\n * * twist all vertices together.\r\n * * This effectively creates valid face loops for a planar subdivision if there are no edge crossings.\r\n * * If there are edge crossings, the graph can be a (highly complicated) Klein bottle topology.\r\n * * Mask.NULL_FACE is cleared throughout and applied within null faces.\r\n */\r\n public static clusterAndMergeXYTheta(\r\n graph: HalfEdgeGraph,\r\n outboundRadiansFunction?: (he: HalfEdge) => number,\r\n clusterTol: number = Geometry.smallMetricDistance,\r\n ) {\r\n const allNodes = graph.allHalfEdges;\r\n const numNodes = allNodes.length;\r\n graph.clearMask(HalfEdgeMask.NULL_FACE);\r\n const clusters = new ClusterableArray(2, 2, numNodes); // data order: x,y,theta,nodeIndex. But theta is not set in first round.\r\n for (let i = 0; i < numNodes; i++) {\r\n const nodeA = allNodes[i];\r\n const xA = nodeA.x;\r\n const yA = nodeA.y;\r\n HalfEdge.pinch(nodeA, nodeA.vertexSuccessor); // pull it out of its current vertex loop.\r\n clusters.addDirect(xA, yA, 0.0, i);\r\n }\r\n const order = clusters.clusterIndicesLexical(clusterTol);\r\n let k0 = 0;\r\n const numK = order.length;\r\n for (let k1 = 0; k1 < numK; k1++) {\r\n if (order[k1] === ClusterableArray.clusterTerminator) {\r\n // nodes identified in order[k0]..order[k1-1] are at a vertex cluster; equate their xy\r\n if (k1 > k0) {\r\n const iA = clusters.getExtraData(order[k0], 1);\r\n const nodeA0 = allNodes[iA];\r\n for (let k = k0 + 1; k < k1; k++) {\r\n const iB = clusters.getExtraData(order[k], 1);\r\n const nodeB = allNodes[iB];\r\n nodeB.x = nodeA0.x;\r\n nodeB.y = nodeA0.y;\r\n }\r\n }\r\n k0 = k1 + 1;\r\n }\r\n }\r\n // NOW\r\n // 1) There are identical coordinates at all nodes around each vertex loop.\r\n // 2) Hence ready do sort (at each vertex) by theta.\r\n\r\n // insert theta as extra data in the sort table . . .\r\n for (const clusterTableIndex of order) {\r\n if (clusterTableIndex !== ClusterableArray.clusterTerminator) {\r\n const nodeA = allNodes[clusterTableIndex];\r\n const nodeB = nodeA.faceSuccessor;\r\n let getPrecomputedRadians = outboundRadiansFunction;\r\n if (getPrecomputedRadians) {\r\n // Recompute theta when edge geometry is completely determined by the vertices, which may have been perturbed by clustering.\r\n const detail = nodeA.edgeTag as CurveLocationDetail;\r\n if (undefined === detail || undefined === detail.curve || detail.curve instanceof LineSegment3d)\r\n getPrecomputedRadians = undefined;\r\n }\r\n let radians = getPrecomputedRadians ? getPrecomputedRadians(nodeA) : Math.atan2(nodeB.y - nodeA.y, nodeB.x - nodeA.x);\r\n if (Angle.isAlmostEqualRadiansAllowPeriodShift(radians, -Math.PI))\r\n radians = Math.PI;\r\n clusters.setExtraData(clusterTableIndex, 0, radians);\r\n }\r\n }\r\n clusters.sortSubsetsBySingleKey(order, 2);\r\n const unmatchedNullFaceNodes: HalfEdge[] = [];\r\n k0 = 0;\r\n let thetaA, thetaB;\r\n // GeometryCoreTestIO.consoleLog(\"START VERTEX LINKS\");\r\n\r\n // now pinch each neighboring pair together\r\n for (let k1 = 0; k1 < numK; k1++) {\r\n if (order[k1] === ClusterableArray.clusterTerminator) {\r\n // nodes identified in order[k0]..order[k1-1] are properly sorted around a vertex.\r\n if (k1 > k0) {\r\n // const xy = clusters.getPoint2d(order[k0]);\r\n // GeometryCoreTestIO.consoleLog({ k0, k1, x: xy.x, y: xy.y });\r\n if (k1 > k0 + 1)\r\n this.secondarySortAroundVertex(clusters, order, allNodes, k0, k1);\r\n this.doAnnounceVertexNeighborhood(clusters, order, allNodes, k0, k1);\r\n const iA = clusters.getExtraData(order[k0], 1);\r\n thetaA = clusters.getExtraData(order[k0], 0);\r\n const nodeA0 = allNodes[iA];\r\n let nodeA = nodeA0;\r\n for (let k = k0 + 1; k < k1; k++) {\r\n const iB = clusters.getExtraData(order[k], 1);\r\n thetaB = clusters.getExtraData(order[k], 0);\r\n const nodeB = allNodes[iB];\r\n if (nodeA.isMaskSet(HalfEdgeMask.NULL_FACE)) {\r\n // nope, this edge was flagged and pinched from the other end.\r\n const j = unmatchedNullFaceNodes.findIndex((node: HalfEdge) => nodeA === node);\r\n if (j >= 0) {\r\n unmatchedNullFaceNodes[j] = unmatchedNullFaceNodes[unmatchedNullFaceNodes.length - 1];\r\n unmatchedNullFaceNodes.pop();\r\n }\r\n nodeA = nodeB;\r\n thetaA = thetaB;\r\n } else if (nodeB.isMaskSet(HalfEdgeMask.NULL_FACE)) {\r\n const j = unmatchedNullFaceNodes.findIndex((node: HalfEdge) => nodeB === node);\r\n if (j >= 0) {\r\n unmatchedNullFaceNodes[j] = unmatchedNullFaceNodes[unmatchedNullFaceNodes.length - 1];\r\n unmatchedNullFaceNodes.pop();\r\n }\r\n // NO leave nodeA and thetaA ignore nodeB -- later step will get the outside of its banana.\r\n } else {\r\n HalfEdge.pinch(nodeA, nodeB);\r\n\r\n // Detect null face using the heuristic:\r\n // * near vertex angles are same (periodic, toleranced)\r\n // * far vertex is clustered (exactly equal)\r\n // * near vertex curvatures are same (toleranced)\r\n // Note that near vertex is already clustered.\r\n if (Angle.isAlmostEqualRadiansAllowPeriodShift(thetaA, thetaB)) {\r\n const nodeA1 = nodeA.faceSuccessor;\r\n const nodeB1 = nodeB.edgeMate;\r\n if (nodeA1.isEqualXY(nodeB1)) {\r\n const cA = this.curvatureSortKey(nodeA);\r\n const cB = this.curvatureSortKey(nodeB);\r\n if (Geometry.isSameCoordinate(cA, cB, clusterTol)) { // rule out banana\r\n HalfEdge.pinch(nodeA1, nodeB1);\r\n nodeA.setMask(HalfEdgeMask.NULL_FACE);\r\n nodeB1.setMask(HalfEdgeMask.NULL_FACE);\r\n unmatchedNullFaceNodes.push(nodeB1);\r\n }\r\n }\r\n }\r\n nodeA = nodeB;\r\n thetaA = thetaB;\r\n }\r\n }\r\n }\r\n k0 = k1 + 1;\r\n }\r\n }\r\n }\r\n\r\n private static buildVerticalSweepPriorityQueue(graph: HalfEdgeGraph): HalfEdgePriorityQueueWithPartnerArray {\r\n const sweepHeap = new HalfEdgePriorityQueueWithPartnerArray();\r\n for (const p of graph.allHalfEdges) {\r\n\r\n if (HalfEdgeGraphOps.compareNodesYXUp(p, p.faceSuccessor) < 0) {\r\n sweepHeap.priorityQueue.push(p);\r\n }\r\n }\r\n return sweepHeap;\r\n }\r\n\r\n private static computeIntersectionFractionsOnEdges(nodeA0: HalfEdge, nodeB0: HalfEdge, tol: number = Geometry.smallMetricDistance): { f0: XAndY, f1?: XAndY} | undefined {\r\n const nodeA1 = nodeA0.faceSuccessor;\r\n const aDir = { x: nodeA1.x - nodeA0.x, y: nodeA1.y - nodeA0.y };\r\n const nodeB1 = nodeB0.faceSuccessor;\r\n const bDir = { x: nodeB1.x - nodeB0.x, y: nodeB1.y - nodeB0.y };\r\n let fractions = SmallSystem.lineSegmentXYUVIntersectionUnbounded(nodeA0, aDir, nodeB0, bDir, tol);\r\n if (fractions) {\r\n const snapFractionToSegment = (fraction: number, segStart: XAndY, segEnd: XAndY): number => {\r\n const x = Geometry.interpolate(segStart.x, fraction, segEnd.x);\r\n const y = Geometry.interpolate(segStart.y, fraction, segEnd.y);\r\n if (Geometry.isSameCoordinateXY(x, y, segStart.x, segStart.y, tol))\r\n return 0.0;\r\n if (Geometry.isSameCoordinateXY(x, y, segEnd.x, segEnd.y, tol))\r\n return 1.0;\r\n return fraction;\r\n };\r\n fractions.f0.x = snapFractionToSegment(fractions.f0.x, nodeA0, nodeA1);\r\n fractions.f0.y = snapFractionToSegment(fractions.f0.y, nodeB0, nodeB1);\r\n if (fractions.f1) {\r\n fractions.f1.x = snapFractionToSegment(fractions.f1.x, nodeA0, nodeA1);\r\n fractions.f1.y = snapFractionToSegment(fractions.f1.y, nodeB0, nodeB1);\r\n }\r\n if (fractions.f1 && !(Geometry.isIn01(fractions.f1.x) && Geometry.isIn01(fractions.f1.y)))\r\n fractions.f1 = undefined; // overlap ends beyond a segment; downgrade to simple intersection\r\n if (!(Geometry.isIn01(fractions.f0.x) && Geometry.isIn01(fractions.f0.y))) {\r\n if (fractions.f1) {\r\n fractions.f0 = fractions.f1; // overlap starts beyond a segment; downgrade to simple intersection\r\n fractions.f1 = undefined;\r\n } else\r\n fractions = undefined; // intersection/overlap is outside both segments\r\n }\r\n }\r\n return fractions;\r\n }\r\n /**\r\n * Split edges at intersections.\r\n * * This is a large operation.\r\n * @param graph\r\n */\r\n public static splitIntersectingEdges(graph: HalfEdgeGraph, distanceTol: number = Geometry.smallMetricDistance, fractionTol: number = 1.0e-8): GraphSplitData {\r\n const data = new GraphSplitData();\r\n const sweepHeap = this.buildVerticalSweepPriorityQueue(graph);\r\n let nodeA0, nodeB1;\r\n const smallFraction = fractionTol;\r\n const largeFraction = 1.0 - smallFraction;\r\n let i;\r\n let nodeB0;\r\n while (undefined !== (nodeA0 = sweepHeap.priorityQueue.pop())) {\r\n data.numUpEdge++;\r\n const n0 = sweepHeap.activeEdges.length;\r\n sweepHeap.removeArrayMembersWithY1Below(nodeA0.y - distanceTol);\r\n data.numPopOut += n0 - sweepHeap.activeEdges.length;\r\n for (i = 0; i < sweepHeap.activeEdges.length; i++) {\r\n nodeB0 = sweepHeap.activeEdges[i];\r\n nodeB1 = nodeB0.faceSuccessor;\r\n if (Geometry.isSameCoordinateXY(nodeA0.x, nodeA0.y, nodeB0.x, nodeB0.y, distanceTol)) {\r\n data.numA0B0++;\r\n } else if (Geometry.isSameCoordinateXY(nodeB1.x, nodeB1.y, nodeA0.x, nodeA0.y, distanceTol)) {\r\n data.numA0B1++;\r\n } else {\r\n data.numIntersectionTest++;\r\n const fractions = this.computeIntersectionFractionsOnEdges(nodeA0, nodeB0, distanceTol);\r\n if (fractions) {\r\n const splitAndPush = (node: HalfEdge, fraction?: number): void => {\r\n if (fraction !== undefined && fraction > smallFraction && fraction < largeFraction) {\r\n const newNode = graph.splitEdgeAtFraction(node, fraction);\r\n sweepHeap.priorityQueue.push(newNode); // will be popped as a nodeA0 later\r\n data.numSplit++;\r\n }\r\n };\r\n splitAndPush(nodeA0, fractions.f0.x);\r\n splitAndPush(nodeA0, fractions.f1?.x);\r\n splitAndPush(nodeB0, fractions.f0.y);\r\n splitAndPush(nodeB0, fractions.f1?.y);\r\n // existing nodeA0 and its shortened edge remain for further intersections\r\n }\r\n }\r\n }\r\n sweepHeap.activeEdges.push(nodeA0);\r\n }\r\n return data;\r\n }\r\n\r\n /**\r\n * Returns a graph structure formed from the given LineSegment array\r\n *\r\n * * Find all intersections among segments, and split them if necessary\r\n * * Record endpoints of every segment in the form X, Y, Theta; This information is stored as a new node and sorted to match up\r\n * vertices.\r\n * * For vertices that match up, pinch the nodes to create vertex loops, which in closed objects, will also eventually form face\r\n * loops\r\n */\r\n public static formGraphFromSegments(lineSegments: LineSegment3d[]): HalfEdgeGraph {\r\n // Structure of an index of the array: { xyTheta: Point3d, node: Node }\r\n const graph = new HalfEdgeGraph();\r\n HalfEdgeGraphOps.segmentArrayToGraphEdges(lineSegments, graph, HalfEdgeMask.BOUNDARY_EDGE);\r\n this.splitIntersectingEdges(graph);\r\n this.clusterAndMergeXYTheta(graph);\r\n return graph;\r\n }\r\n\r\n /**\r\n * * Input is random linestrings, not necessarily loops\r\n * * Graph gets full splitEdges, regularize (optional), and triangulate.\r\n * @returns graph, or undefined if bad data.\r\n */\r\n public static formGraphFromChains(chains: MultiLineStringDataVariant, regularize: boolean = true, mask: HalfEdgeMask = HalfEdgeMask.PRIMARY_EDGE): HalfEdgeGraph | undefined {\r\n if (chains.length < 1)\r\n return undefined;\r\n const graph = new HalfEdgeGraph();\r\n const chainSeeds = Triangulator.directCreateChainsFromCoordinates(graph, chains);\r\n for (const seed of chainSeeds)\r\n seed.setMaskAroundFace(mask);\r\n\r\n this.splitIntersectingEdges(graph);\r\n this.clusterAndMergeXYTheta(graph);\r\n if (regularize) {\r\n const context = new RegularizationContext(graph);\r\n context.regularizeGraph(true, true);\r\n }\r\n return graph;\r\n }\r\n\r\n}\r\n"]}
1
+ {"version":3,"file":"Merging.js","sourceRoot":"","sources":["../../../src/topology/Merging.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n\r\nimport { assert } from \"@itwin/core-bentley\";\r\nimport { CurveLocationDetail } from \"../curve/CurveLocationDetail\";\r\nimport { LineSegment3d } from \"../curve/LineSegment3d\";\r\nimport { Geometry } from \"../Geometry\";\r\nimport { Angle } from \"../geometry3d/Angle\";\r\nimport { MultiLineStringDataVariant } from \"../geometry3d/IndexedXYZCollection\";\r\nimport { Range2d, Range3d } from \"../geometry3d/Range\";\r\nimport { XAndY } from \"../geometry3d/XYZProps\";\r\nimport { ClusterableArray } from \"../numerics/ClusterableArray\";\r\nimport { SmallSystem } from \"../numerics/SmallSystem\";\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { HalfEdgePriorityQueueWithPartnerArray } from \"./HalfEdgePriorityQueue\";\r\nimport { RegularizationContext } from \"./RegularizeFace\";\r\nimport { Triangulator } from \"./Triangulation\";\r\n\r\n// cspell:word XYUV\r\n\r\nexport class GraphSplitData {\r\n public numUpEdge = 0;\r\n public numIntersectionTest = 0;\r\n public numSplit = 0;\r\n public numPopOut = 0;\r\n public numA0B0 = 0;\r\n public numA0B1 = 0;\r\n public constructor() {\r\n }\r\n}\r\n/**\r\n * Structure for data used when sorting outbound edges \"around a node\"\r\n */\r\nexport class VertexNeighborhoodSortData {\r\n public index: number;\r\n public radiusOfCurvature: number;\r\n public node: HalfEdge;\r\n public radians?: number;\r\n public constructor(index: number, key: number, node: HalfEdge, radians?: number) {\r\n this.index = index;\r\n this.radiusOfCurvature = key;\r\n this.node = node;\r\n this.radians = radians;\r\n }\r\n}\r\n\r\n/** Function signature for announcing a vertex neighborhood during sorting. */\r\nexport type AnnounceVertexNeighborhoodSortData = (data: VertexNeighborhoodSortData[]) => any;\r\n/**\r\n * * Assorted methods used in algorithms on HalfEdgeGraph.\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphOps {\r\n\r\n /** Compare function for sorting with primary y compare, secondary x compare. */\r\n public static compareNodesYXUp(a: HalfEdge, b: HalfEdge) {\r\n // Check y's\r\n // if (!Geometry.isSameCoordinate(a.y, b.y))\r\n if (a.y < b.y)\r\n return -1;\r\n else if (a.y > b.y)\r\n return 1;\r\n // Check x's\r\n // if (!Geometry.isSameCoordinate(a.x, b.x))\r\n if (a.x < b.x)\r\n return -1;\r\n else if (a.x > b.x)\r\n return 1;\r\n return 0;\r\n }\r\n\r\n /** Return true if nodeB (a) is lower than both its neighbors and (b) inflects as a downward peak (rather than an upward trough) */\r\n public static isDownPeak(nodeB: HalfEdge) {\r\n const nodeA = nodeB.facePredecessor;\r\n const nodeC = nodeB.faceSuccessor;\r\n return this.compareNodesYXUp(nodeB, nodeA) < 0\r\n && this.compareNodesYXUp(nodeB, nodeC) < 0\r\n && this.crossProductToTargets(nodeB, nodeA, nodeC) > 0;\r\n }\r\n\r\n /** return the cross product of vectors from base to targetA and base to targetB\r\n * @param base base vertex of both vectors.\r\n * @param targetA target vertex of first vector\r\n * @param targetB target vertex of second vector\r\n */\r\n public static crossProductToTargets(base: HalfEdge, targetA: HalfEdge, targetB: HalfEdge): number {\r\n return Geometry.crossProductXYXY(targetA.x - base.x, targetA.y - base.y, targetB.x - base.x, targetB.y - base.y);\r\n }\r\n\r\n /** Compute the range of the graph's vertices. */\r\n public static graphRange(graph: Readonly<HalfEdgeGraph>): Range3d {\r\n const range = Range3d.create();\r\n for (const node of graph.allHalfEdges) {\r\n range.extendXYZ(node.x, node.y, node.z);\r\n }\r\n return range;\r\n }\r\n /** Compute the xy-range of the graph's vertices. */\r\n public static graphRangeXY(graph: Readonly<HalfEdgeGraph>): Range2d {\r\n const range = Range2d.createNull();\r\n for (const node of graph.allHalfEdges) {\r\n range.extendXY(node.x, node.y);\r\n }\r\n return range;\r\n }\r\n\r\n /** Returns an array of all nodes (both ends) of edges created from segments. */\r\n public static segmentArrayToGraphEdges(segments: LineSegment3d[], returnGraph: HalfEdgeGraph, mask: HalfEdgeMask): HalfEdge[] {\r\n const result = [];\r\n let idxCounter = 0;\r\n\r\n // Push the endpoints of each segment onto arr[] in the form {(x, y, theta), Node}\r\n for (const segment of segments) {\r\n\r\n const node0 = returnGraph.createEdgeXYZXYZ(\r\n segment.point0Ref.x, segment.point0Ref.y, segment.point0Ref.z,\r\n idxCounter,\r\n segment.point1Ref.x, segment.point1Ref.y, segment.point1Ref.z,\r\n idxCounter + 1);\r\n\r\n const node1 = node0.edgeMate;\r\n idxCounter += 2;\r\n\r\n node0.setMaskAroundFace(mask); // Original given coordinates must be part of boundary\r\n result.push(node0);\r\n result.push(node1);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * * Visit all nodes in `graph`.\r\n * * invoke `pinch(node, vertexPredecessor)`\r\n * * this leaves the graph as isolated edges.\r\n * @param graph graph to modify\r\n */\r\n public static isolateAllEdges(graph: HalfEdgeGraph) {\r\n for (const nodeA of graph.allHalfEdges) {\r\n const nodeB = nodeA.vertexPredecessor;\r\n HalfEdge.pinch(nodeA, nodeB);\r\n }\r\n }\r\n /**\r\n * Compute convexity of a sector of a super-face.\r\n * @param base node whose edge is to be tested for removal\r\n * @param ignore edges with this mask (on either side) are ignored for the purposes of computing convexity\r\n * @param barrier edges with this mask (on either side) will not be removed\r\n * @param signedAreaTol optional signed area tolerance to use in test for parallel vectors\r\n * @return whether removing the edge at base would create a convex sector in the super-face\r\n */\r\n private static isSectorConvexAfterEdgeRemoval(base: HalfEdge, ignore: HalfEdgeMask, barrier: HalfEdgeMask, signedAreaTol: number = 0): boolean {\r\n let vs = base;\r\n do { // loop ccw around vertex looking for a super-face predecessor\r\n if (vs.isMaskSet(barrier) || vs.edgeMate.isMaskSet(barrier))\r\n break;\r\n vs = vs.vertexSuccessor;\r\n } while (vs !== base && vs.isMaskSet(ignore));\r\n if (vs === base)\r\n return false;\r\n let vp = base;\r\n do { // loop cw around vertex looking for a super-face successor\r\n if (vp.isMaskSet(barrier) || vp.edgeMate.isMaskSet(barrier))\r\n break;\r\n vp = vp.vertexPredecessor;\r\n } while (vp !== base && vp.isMaskSet(ignore));\r\n if (vp === base)\r\n return false;\r\n return HalfEdge.isSectorConvex(vs.edgeMate, base, vp.faceSuccessor, signedAreaTol);\r\n }\r\n /**\r\n * Mask edges between faces if the union of the faces is convex.\r\n * Uses a greedy algorithm with no regard to quality of resulting convex faces.\r\n * Best results when input faces are convex.\r\n * @param graph graph to examine and mark\r\n * @param mark the mask used to mark (both sides of) removable edges\r\n * @param barrier edges with this mask (on either side) will not be marked. Defaults to HalfEdgeMask.BOUNDARY_EDGE.\r\n * @return number of edges masked (half the number of HalfEdges masked)\r\n */\r\n public static markRemovableEdgesToExpandConvexFaces(graph: HalfEdgeGraph, mark: HalfEdgeMask, barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE): number {\r\n if (HalfEdgeMask.NULL_MASK === mark)\r\n return 0;\r\n const visit = graph.grabMask(true);\r\n let numMarked = 0;\r\n for (const node of graph.allHalfEdges) {\r\n if (!node.isMaskSet(visit)) {\r\n if (!node.isMaskSet(barrier) && !node.edgeMate.isMaskSet(barrier)) {\r\n // tol based on areas of *original* faces on each side of the edge to be removed\r\n const signedAreaTol = Geometry.smallMetricDistanceSquared * (node.signedFaceArea() + node.edgeMate.signedFaceArea());\r\n if (this.isSectorConvexAfterEdgeRemoval(node, mark, barrier, signedAreaTol) && this.isSectorConvexAfterEdgeRemoval(node.edgeMate, mark, barrier, signedAreaTol)) {\r\n node.setMaskAroundEdge(mark);\r\n ++numMarked;\r\n }\r\n }\r\n }\r\n node.setMaskAroundEdge(visit);\r\n }\r\n graph.dropMask(visit);\r\n return numMarked;\r\n }\r\n /**\r\n * Collect edges between faces if the union of the faces is convex.\r\n * Uses a greedy algorithm with no regard to quality of resulting convex faces.\r\n * Best results when input faces are convex.\r\n * @param graph graph to examine\r\n * @param barrier edges with this mask (on either side) will not be collected. Defaults to HalfEdgeMask.BOUNDARY_EDGE.\r\n * @return one HalfEdge per removable edge\r\n */\r\n public static collectRemovableEdgesToExpandConvexFaces(graph: HalfEdgeGraph, barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE): HalfEdge[] | undefined {\r\n const removable: HalfEdge[] = [];\r\n const mark = graph.grabMask(true);\r\n if (0 < this.markRemovableEdgesToExpandConvexFaces(graph, mark, barrier)) {\r\n const visited = graph.grabMask(true);\r\n for (const node of graph.allHalfEdges) {\r\n if (node.isMaskSet(mark) && !node.isMaskSet(visited)) {\r\n node.setMaskAroundEdge(visited);\r\n removable.push(node);\r\n }\r\n }\r\n graph.dropMask(visited);\r\n }\r\n graph.dropMask(mark);\r\n return removable;\r\n }\r\n\r\n /**\r\n * Remove edges between faces if the union of the faces is convex.\r\n * Uses a greedy algorithm with no regard to quality of resulting convex faces.\r\n * Best results when input faces are convex.\r\n * @param graph graph to modify\r\n * @param barrier edges with this mask (on either side) will not be removed. Defaults to HalfEdgeMask.BOUNDARY_EDGE.\r\n * @return number of edges deleted\r\n */\r\n public static expandConvexFaces(graph: HalfEdgeGraph, barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE): number {\r\n const mark = graph.grabMask(true);\r\n const numRemovedEdges = this.markRemovableEdgesToExpandConvexFaces(graph, mark, barrier);\r\n if (numRemovedEdges > 0) {\r\n const numYankedEdges = 0.5 * graph.yankAndDeleteEdges((node: HalfEdge) => node.getMask(mark));\r\n assert(numYankedEdges === numRemovedEdges);\r\n }\r\n graph.dropMask(mark);\r\n return numRemovedEdges;\r\n }\r\n\r\n /**\r\n * Test desired faces for convexity.\r\n * @param graph graph to examine\r\n * @param avoid faces with this mask will not be examined. Defaults to HalfEdgeMask.EXTERIOR.\r\n * @return whether every face in the graph is convex\r\n */\r\n public static isEveryFaceConvex(graph: HalfEdgeGraph, avoid: HalfEdgeMask = HalfEdgeMask.EXTERIOR): boolean {\r\n const allFaces = graph.collectFaceLoops();\r\n for (const node of allFaces) {\r\n if (node.isMaskedAroundFace(avoid))\r\n continue;\r\n if (!node.isFaceConvex())\r\n return false;\r\n }\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Note: this class uses hardcoded micrometer coordinate/cluster tolerance throughout.\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphMerge {\r\n // return kC such that all angles k are equal, with kA <= k < kC <= kB.\r\n // * Assume: angles k are stored at extra data index 0.\r\n // * Note that the usual case (when angle at kA is not repeated) is kA+1 === kC\r\n public static getCommonThetaEndIndex(clusters: ClusterableArray, order: Uint32Array, kA: number, kB: number): number {\r\n let kC = kA + 1;\r\n const thetaA = clusters.getExtraData(order[kA], 0);\r\n while (kC < kB) {\r\n const thetaB = clusters.getExtraData(order[kC], 0);\r\n if (!Angle.isAlmostEqualRadiansAllowPeriodShift(thetaA, thetaB)) {\r\n return kC;\r\n }\r\n kC++;\r\n }\r\n return kC;\r\n }\r\n private static _announceVertexNeighborhoodFunction?: AnnounceVertexNeighborhoodSortData;\r\n /**\r\n * public property setter for a function to be called with sorted edge data around a vertex.\r\n */\r\n public static set announceVertexNeighborhoodFunction(func: AnnounceVertexNeighborhoodSortData | undefined) { this._announceVertexNeighborhoodFunction = func; }\r\n private static doAnnounceVertexNeighborhood(clusters: ClusterableArray, order: Uint32Array, allNodes: HalfEdge[], k0: number, k1: number) {\r\n if (this._announceVertexNeighborhoodFunction) {\r\n const sortData: VertexNeighborhoodSortData[] = [];\r\n // build and share the entire vertex order\r\n for (let k = k0; k < k1; k++) {\r\n const index = clusters.getExtraData(order[k], 1);\r\n const theta = clusters.getExtraData(order[k], 0);\r\n const node = allNodes[index];\r\n const signedDistance = this.curvatureSortKey(node);\r\n sortData.push(new VertexNeighborhoodSortData(order[k], signedDistance, node, theta));\r\n }\r\n this._announceVertexNeighborhoodFunction(sortData);\r\n }\r\n\r\n }\r\n // assumptions about cluster array:\r\n // * data order is: x,y,theta,nodeIndex\r\n // * theta and nodeIndex are the \"extra\" data.\r\n // * only want to do anything here when curves are present.\r\n // * k0<=k<k1 are around a vertex\r\n // * These are sorted by theta.\r\n private static secondarySortAroundVertex(clusters: ClusterableArray, order: Uint32Array, allNodes: HalfEdge[], k0: number, k1: number) {\r\n const sortData: VertexNeighborhoodSortData[] = [];\r\n\r\n for (let k = k0; k < k1;) {\r\n const kB = this.getCommonThetaEndIndex(clusters, order, k, k1);\r\n if (k + 1 < kB) {\r\n sortData.length = 0;\r\n for (let kA = k; kA < kB; kA++) {\r\n const index = clusters.getExtraData(order[kA], 1);\r\n const node = allNodes[index];\r\n const signedDistance = this.curvatureSortKey(node);\r\n sortData.push(new VertexNeighborhoodSortData(order[kA], signedDistance, node));\r\n }\r\n sortData.sort((a: VertexNeighborhoodSortData, b: VertexNeighborhoodSortData) => (a.radiusOfCurvature - b.radiusOfCurvature));\r\n for (let i = 0; i < sortData.length; i++) {\r\n order[k + i] = sortData[i].index;\r\n }\r\n }\r\n k = kB;\r\n }\r\n }\r\n /** Return the sort key for sorting by curvature.\r\n * * This is the signed distance from the curve at the edge start, to center of curvature.\r\n * * NOTE: Currently does not account for higher derivatives in the case of higher-than-tangent match.\r\n */\r\n public static curvatureSortKey(node: HalfEdge): number {\r\n const cld = node.edgeTag as CurveLocationDetail;\r\n if (cld !== undefined) {\r\n const fraction = cld.fraction;\r\n const curve = cld.curve;\r\n if (curve) {\r\n let radius = curve.fractionToSignedXYRadiusOfCurvature(fraction);\r\n if (node.sortData !== undefined && node.sortData < 0)\r\n radius = -radius;\r\n return radius;\r\n }\r\n }\r\n return 0.0;\r\n }\r\n /** Whether the HalfEdge is part of a null face, as marked by [[clusterAndMergeXYTheta]]. */\r\n public static isNullFace(node: HalfEdge): boolean {\r\n return node.isMaskSet(HalfEdgeMask.NULL_FACE) && node.faceSuccessor.isMaskSet(HalfEdgeMask.NULL_FACE) && node === node.faceSuccessor.faceSuccessor;\r\n }\r\n /**\r\n * Cluster the HalfEdges so that xy-coordinates within `mergeTolerance` are equated.\r\n * * Note that any additional data (e.g., edgeTag, faceTag) on the HalfEdges are ignored. In particular,\r\n * [[CurveLocationDetail]]s attached to clustered HalfEdges do *not* get their points adjusted.\r\n * * This is a simple merge algorithm:\r\n * * untwist all edges from the vertex loops\r\n * * collect array of (x,y,theta) at all nodes\r\n * * lexical sort of the array\r\n * * twist all edges together in sort order around each vertex\r\n * * This effectively creates valid face loops for a planar subdivision if there are no edge crossings.\r\n * * If there are edge crossings, the graph can be a (highly complicated) Klein bottle topology.\r\n * * [[HalfEdgeMask.NULL_FACE]] is cleared throughout and applied within null faces.\r\n * @param graph input graph\r\n * @param outboundRadiansFunction optional function to compute the sort angle of an edge at its start vertex\r\n * @param clusterTol optional distance tolerance for clustering vertices. Default value is [[Geometry.smallMetricDistance]].\r\n */\r\n public static clusterAndMergeXYTheta(\r\n graph: HalfEdgeGraph,\r\n outboundRadiansFunction?: (he: HalfEdge) => number,\r\n clusterTol: number = Geometry.smallMetricDistance,\r\n ) {\r\n const allNodes = graph.allHalfEdges;\r\n const numNodes = allNodes.length;\r\n graph.clearMask(HalfEdgeMask.NULL_FACE);\r\n const clusters = new ClusterableArray(2, 2, numNodes); // data order: x,y,theta,nodeIndex. But theta is not set in first round.\r\n for (let i = 0; i < numNodes; i++) {\r\n const nodeA = allNodes[i];\r\n const xA = nodeA.x;\r\n const yA = nodeA.y;\r\n HalfEdge.pinch(nodeA, nodeA.vertexSuccessor); // pull it out of its current vertex loop.\r\n clusters.addDirect(xA, yA, 0.0, i);\r\n }\r\n const order = clusters.clusterIndicesLexical(clusterTol);\r\n let k0 = 0;\r\n const numK = order.length;\r\n for (let k1 = 0; k1 < numK; k1++) {\r\n if (order[k1] === ClusterableArray.clusterTerminator) {\r\n // nodes identified in order[k0]..order[k1-1] are at a vertex cluster; equate their xy\r\n if (k1 > k0) {\r\n const iA = clusters.getExtraData(order[k0], 1);\r\n const nodeA0 = allNodes[iA];\r\n for (let k = k0 + 1; k < k1; k++) {\r\n const iB = clusters.getExtraData(order[k], 1);\r\n const nodeB = allNodes[iB];\r\n nodeB.x = nodeA0.x;\r\n nodeB.y = nodeA0.y;\r\n }\r\n }\r\n k0 = k1 + 1;\r\n }\r\n }\r\n // NOW\r\n // 1) There are identical coordinates at all nodes around each vertex loop.\r\n // 2) Hence ready do sort (at each vertex) by theta.\r\n\r\n // insert theta as extra data in the sort table . . .\r\n for (const clusterTableIndex of order) {\r\n if (clusterTableIndex !== ClusterableArray.clusterTerminator) {\r\n const nodeA = allNodes[clusterTableIndex];\r\n const nodeB = nodeA.faceSuccessor;\r\n let getPrecomputedRadians = outboundRadiansFunction;\r\n if (getPrecomputedRadians) {\r\n // Recompute theta when edge geometry is completely determined by the vertices, which may have been perturbed by clustering.\r\n const detail = nodeA.edgeTag as CurveLocationDetail;\r\n if (undefined === detail || undefined === detail.curve || detail.curve instanceof LineSegment3d)\r\n getPrecomputedRadians = undefined;\r\n }\r\n let radians = getPrecomputedRadians ? getPrecomputedRadians(nodeA) : Math.atan2(nodeB.y - nodeA.y, nodeB.x - nodeA.x);\r\n if (Angle.isAlmostEqualRadiansAllowPeriodShift(radians, -Math.PI))\r\n radians = Math.PI;\r\n clusters.setExtraData(clusterTableIndex, 0, radians);\r\n }\r\n }\r\n clusters.sortSubsetsBySingleKey(order, 2);\r\n const unmatchedNullFaceNodes: HalfEdge[] = [];\r\n k0 = 0;\r\n let thetaA, thetaB;\r\n\r\n // now pinch each neighboring pair together\r\n for (let k1 = 0; k1 < numK; k1++) {\r\n if (order[k1] === ClusterableArray.clusterTerminator) {\r\n // nodes identified in order[k0]..order[k1-1] are properly sorted around a vertex.\r\n if (k1 > k0) {\r\n if (k1 > k0 + 1)\r\n this.secondarySortAroundVertex(clusters, order, allNodes, k0, k1);\r\n this.doAnnounceVertexNeighborhood(clusters, order, allNodes, k0, k1);\r\n const iA = clusters.getExtraData(order[k0], 1);\r\n thetaA = clusters.getExtraData(order[k0], 0);\r\n const nodeA0 = allNodes[iA];\r\n let nodeA = nodeA0;\r\n for (let k = k0 + 1; k < k1; k++) {\r\n const iB = clusters.getExtraData(order[k], 1);\r\n thetaB = clusters.getExtraData(order[k], 0);\r\n const nodeB = allNodes[iB];\r\n if (nodeA.isMaskSet(HalfEdgeMask.NULL_FACE)) {\r\n // nope, this edge was flagged and pinched from the other end.\r\n const j = unmatchedNullFaceNodes.findIndex((node: HalfEdge) => nodeA === node);\r\n if (j >= 0) {\r\n unmatchedNullFaceNodes[j] = unmatchedNullFaceNodes[unmatchedNullFaceNodes.length - 1];\r\n unmatchedNullFaceNodes.pop();\r\n }\r\n nodeA = nodeB;\r\n thetaA = thetaB;\r\n } else if (nodeB.isMaskSet(HalfEdgeMask.NULL_FACE)) {\r\n const j = unmatchedNullFaceNodes.findIndex((node: HalfEdge) => nodeB === node);\r\n if (j >= 0) {\r\n unmatchedNullFaceNodes[j] = unmatchedNullFaceNodes[unmatchedNullFaceNodes.length - 1];\r\n unmatchedNullFaceNodes.pop();\r\n }\r\n // NO leave nodeA and thetaA ignore nodeB -- later step will get the outside of its banana.\r\n } else {\r\n HalfEdge.pinch(nodeA, nodeB);\r\n\r\n // Detect null face using the heuristic:\r\n // * near vertex angles are same (periodic, toleranced)\r\n // * far vertex is clustered (exactly equal)\r\n // * near vertex curvatures are same (toleranced)\r\n // Note that near vertex is already clustered.\r\n if (Angle.isAlmostEqualRadiansAllowPeriodShift(thetaA, thetaB)) {\r\n const nodeA1 = nodeA.faceSuccessor;\r\n const nodeB1 = nodeB.edgeMate;\r\n if (nodeA1.isEqualXY(nodeB1)) {\r\n const cA = this.curvatureSortKey(nodeA);\r\n const cB = this.curvatureSortKey(nodeB);\r\n if (Geometry.isSameCoordinate(cA, cB, clusterTol)) { // rule out banana\r\n HalfEdge.pinch(nodeA1, nodeB1);\r\n nodeA.setMask(HalfEdgeMask.NULL_FACE);\r\n nodeB1.setMask(HalfEdgeMask.NULL_FACE);\r\n unmatchedNullFaceNodes.push(nodeB1);\r\n }\r\n }\r\n }\r\n nodeA = nodeB;\r\n thetaA = thetaB;\r\n }\r\n }\r\n }\r\n k0 = k1 + 1;\r\n }\r\n }\r\n }\r\n\r\n private static buildVerticalSweepPriorityQueue(graph: HalfEdgeGraph): HalfEdgePriorityQueueWithPartnerArray {\r\n const sweepHeap = new HalfEdgePriorityQueueWithPartnerArray();\r\n for (const p of graph.allHalfEdges) {\r\n\r\n if (HalfEdgeGraphOps.compareNodesYXUp(p, p.faceSuccessor) < 0) {\r\n sweepHeap.priorityQueue.push(p);\r\n }\r\n }\r\n return sweepHeap;\r\n }\r\n\r\n private static computeIntersectionFractionsOnEdges(nodeA0: HalfEdge, nodeB0: HalfEdge, tol: number = Geometry.smallMetricDistance): { f0: XAndY, f1?: XAndY} | undefined {\r\n const nodeA1 = nodeA0.faceSuccessor;\r\n const aDir = { x: nodeA1.x - nodeA0.x, y: nodeA1.y - nodeA0.y };\r\n const nodeB1 = nodeB0.faceSuccessor;\r\n const bDir = { x: nodeB1.x - nodeB0.x, y: nodeB1.y - nodeB0.y };\r\n let fractions = SmallSystem.lineSegmentXYUVIntersectionUnbounded(nodeA0, aDir, nodeB0, bDir, tol);\r\n if (fractions) {\r\n const snapFractionToSegment = (fraction: number, segStart: XAndY, segEnd: XAndY): number => {\r\n const x = Geometry.interpolate(segStart.x, fraction, segEnd.x);\r\n const y = Geometry.interpolate(segStart.y, fraction, segEnd.y);\r\n if (Geometry.isSameCoordinateXY(x, y, segStart.x, segStart.y, tol))\r\n return 0.0;\r\n if (Geometry.isSameCoordinateXY(x, y, segEnd.x, segEnd.y, tol))\r\n return 1.0;\r\n return fraction;\r\n };\r\n fractions.f0.x = snapFractionToSegment(fractions.f0.x, nodeA0, nodeA1);\r\n fractions.f0.y = snapFractionToSegment(fractions.f0.y, nodeB0, nodeB1);\r\n if (fractions.f1) {\r\n fractions.f1.x = snapFractionToSegment(fractions.f1.x, nodeA0, nodeA1);\r\n fractions.f1.y = snapFractionToSegment(fractions.f1.y, nodeB0, nodeB1);\r\n }\r\n if (fractions.f1 && !(Geometry.isIn01(fractions.f1.x) && Geometry.isIn01(fractions.f1.y)))\r\n fractions.f1 = undefined; // overlap ends beyond a segment; downgrade to simple intersection\r\n if (!(Geometry.isIn01(fractions.f0.x) && Geometry.isIn01(fractions.f0.y))) {\r\n if (fractions.f1) {\r\n fractions.f0 = fractions.f1; // overlap starts beyond a segment; downgrade to simple intersection\r\n fractions.f1 = undefined;\r\n } else\r\n fractions = undefined; // intersection/overlap is outside both segments\r\n }\r\n }\r\n return fractions;\r\n }\r\n /**\r\n * Split edges at intersections.\r\n * * This is a large operation.\r\n * @param graph\r\n */\r\n public static splitIntersectingEdges(graph: HalfEdgeGraph, distanceTol: number = Geometry.smallMetricDistance, fractionTol: number = 1.0e-8): GraphSplitData {\r\n const data = new GraphSplitData();\r\n const sweepHeap = this.buildVerticalSweepPriorityQueue(graph);\r\n let nodeA0, nodeB1;\r\n const smallFraction = fractionTol;\r\n const largeFraction = 1.0 - smallFraction;\r\n let i;\r\n let nodeB0;\r\n while (undefined !== (nodeA0 = sweepHeap.priorityQueue.pop())) {\r\n data.numUpEdge++;\r\n const n0 = sweepHeap.activeEdges.length;\r\n sweepHeap.removeArrayMembersWithY1Below(nodeA0.y - distanceTol);\r\n data.numPopOut += n0 - sweepHeap.activeEdges.length;\r\n for (i = 0; i < sweepHeap.activeEdges.length; i++) {\r\n nodeB0 = sweepHeap.activeEdges[i];\r\n nodeB1 = nodeB0.faceSuccessor;\r\n if (Geometry.isSameCoordinateXY(nodeA0.x, nodeA0.y, nodeB0.x, nodeB0.y, distanceTol)) {\r\n data.numA0B0++;\r\n } else if (Geometry.isSameCoordinateXY(nodeB1.x, nodeB1.y, nodeA0.x, nodeA0.y, distanceTol)) {\r\n data.numA0B1++;\r\n } else {\r\n data.numIntersectionTest++;\r\n const fractions = this.computeIntersectionFractionsOnEdges(nodeA0, nodeB0, distanceTol);\r\n if (fractions) {\r\n const splitAndPush = (node: HalfEdge, fraction?: number): void => {\r\n if (fraction !== undefined && fraction > smallFraction && fraction < largeFraction) {\r\n const newNode = graph.splitEdgeAtFraction(node, fraction);\r\n sweepHeap.priorityQueue.push(newNode); // will be popped as a nodeA0 later\r\n data.numSplit++;\r\n }\r\n };\r\n splitAndPush(nodeA0, fractions.f0.x);\r\n splitAndPush(nodeA0, fractions.f1?.x);\r\n splitAndPush(nodeB0, fractions.f0.y);\r\n splitAndPush(nodeB0, fractions.f1?.y);\r\n // existing nodeA0 and its shortened edge remain for further intersections\r\n }\r\n }\r\n }\r\n sweepHeap.activeEdges.push(nodeA0);\r\n }\r\n return data;\r\n }\r\n\r\n /**\r\n * Returns a graph structure formed from the given LineSegment array\r\n *\r\n * * Find all intersections among segments, and split them if necessary\r\n * * Record endpoints of every segment in the form X, Y, Theta; This information is stored as a new node and sorted to match up\r\n * vertices.\r\n * * For vertices that match up, pinch the nodes to create vertex loops, which in closed objects, will also eventually form face\r\n * loops\r\n */\r\n public static formGraphFromSegments(lineSegments: LineSegment3d[]): HalfEdgeGraph {\r\n // Structure of an index of the array: { xyTheta: Point3d, node: Node }\r\n const graph = new HalfEdgeGraph();\r\n HalfEdgeGraphOps.segmentArrayToGraphEdges(lineSegments, graph, HalfEdgeMask.BOUNDARY_EDGE);\r\n this.splitIntersectingEdges(graph);\r\n this.clusterAndMergeXYTheta(graph);\r\n return graph;\r\n }\r\n\r\n /**\r\n * * Input is random linestrings, not necessarily loops\r\n * * Graph gets full splitEdges, regularize (optional), and triangulate.\r\n * @returns graph, or undefined if bad data.\r\n */\r\n public static formGraphFromChains(chains: MultiLineStringDataVariant, regularize: boolean = true, mask: HalfEdgeMask = HalfEdgeMask.PRIMARY_EDGE): HalfEdgeGraph | undefined {\r\n if (chains.length < 1)\r\n return undefined;\r\n const graph = new HalfEdgeGraph();\r\n const chainSeeds = Triangulator.directCreateChainsFromCoordinates(graph, chains);\r\n for (const seed of chainSeeds)\r\n seed.setMaskAroundFace(mask);\r\n\r\n this.splitIntersectingEdges(graph);\r\n this.clusterAndMergeXYTheta(graph);\r\n if (regularize) {\r\n const context = new RegularizationContext(graph);\r\n context.regularizeGraph(true, true);\r\n }\r\n return graph;\r\n }\r\n\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/core-geometry",
3
- "version": "5.2.0",
3
+ "version": "5.2.1",
4
4
  "description": "iTwin.js Core Geometry library",
5
5
  "main": "lib/cjs/core-geometry.js",
6
6
  "module": "lib/esm/core-geometry.js",
@@ -31,11 +31,11 @@
31
31
  "rimraf": "^6.0.1",
32
32
  "typescript": "~5.6.2",
33
33
  "vitest": "^3.0.6",
34
- "@itwin/build-tools": "5.2.0"
34
+ "@itwin/build-tools": "5.2.1"
35
35
  },
36
36
  "dependencies": {
37
37
  "flatbuffers": "~1.12.0",
38
- "@itwin/core-bentley": "5.2.0"
38
+ "@itwin/core-bentley": "5.2.1"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "npm run -s build:cjs && npm run -s build:esm",