@itwin/core-geometry 5.9.0-dev.8 → 5.10.0-dev.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 (238) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/lib/cjs/Geometry.d.ts +8 -6
  3. package/lib/cjs/Geometry.d.ts.map +1 -1
  4. package/lib/cjs/Geometry.js +8 -6
  5. package/lib/cjs/Geometry.js.map +1 -1
  6. package/lib/cjs/curve/Arc3d.d.ts +7 -0
  7. package/lib/cjs/curve/Arc3d.d.ts.map +1 -1
  8. package/lib/cjs/curve/Arc3d.js +11 -0
  9. package/lib/cjs/curve/Arc3d.js.map +1 -1
  10. package/lib/cjs/curve/CurveChainWithDistanceIndex.d.ts +11 -2
  11. package/lib/cjs/curve/CurveChainWithDistanceIndex.d.ts.map +1 -1
  12. package/lib/cjs/curve/CurveChainWithDistanceIndex.js +25 -15
  13. package/lib/cjs/curve/CurveChainWithDistanceIndex.js.map +1 -1
  14. package/lib/cjs/curve/CurveCollection.d.ts +15 -6
  15. package/lib/cjs/curve/CurveCollection.d.ts.map +1 -1
  16. package/lib/cjs/curve/CurveCollection.js +15 -6
  17. package/lib/cjs/curve/CurveCollection.js.map +1 -1
  18. package/lib/cjs/curve/CurveCurve.d.ts +1 -1
  19. package/lib/cjs/curve/CurveCurve.d.ts.map +1 -1
  20. package/lib/cjs/curve/CurveCurve.js +2 -1
  21. package/lib/cjs/curve/CurveCurve.js.map +1 -1
  22. package/lib/cjs/curve/CurveLocationDetail.d.ts +21 -0
  23. package/lib/cjs/curve/CurveLocationDetail.d.ts.map +1 -1
  24. package/lib/cjs/curve/CurveLocationDetail.js +59 -0
  25. package/lib/cjs/curve/CurveLocationDetail.js.map +1 -1
  26. package/lib/cjs/curve/CurvePrimitive.d.ts +13 -12
  27. package/lib/cjs/curve/CurvePrimitive.d.ts.map +1 -1
  28. package/lib/cjs/curve/CurvePrimitive.js +12 -11
  29. package/lib/cjs/curve/CurvePrimitive.js.map +1 -1
  30. package/lib/cjs/curve/Loop.d.ts.map +1 -1
  31. package/lib/cjs/curve/Loop.js +3 -1
  32. package/lib/cjs/curve/Loop.js.map +1 -1
  33. package/lib/cjs/curve/RegionOps.d.ts +17 -4
  34. package/lib/cjs/curve/RegionOps.d.ts.map +1 -1
  35. package/lib/cjs/curve/RegionOps.js +114 -18
  36. package/lib/cjs/curve/RegionOps.js.map +1 -1
  37. package/lib/cjs/curve/RegionOpsClassificationSweeps.d.ts +3 -11
  38. package/lib/cjs/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  39. package/lib/cjs/curve/RegionOpsClassificationSweeps.js +1 -91
  40. package/lib/cjs/curve/RegionOpsClassificationSweeps.js.map +1 -1
  41. package/lib/cjs/curve/StrokeOptions.d.ts +13 -6
  42. package/lib/cjs/curve/StrokeOptions.d.ts.map +1 -1
  43. package/lib/cjs/curve/StrokeOptions.js +13 -6
  44. package/lib/cjs/curve/StrokeOptions.js.map +1 -1
  45. package/lib/cjs/curve/internalContexts/AnnounceTangentStrokeHandler.d.ts +1 -1
  46. package/lib/cjs/curve/internalContexts/AnnounceTangentStrokeHandler.d.ts.map +1 -1
  47. package/lib/cjs/curve/internalContexts/AnnounceTangentStrokeHandler.js +1 -2
  48. package/lib/cjs/curve/internalContexts/AnnounceTangentStrokeHandler.js.map +1 -1
  49. package/lib/cjs/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.d.ts +1 -1
  50. package/lib/cjs/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.d.ts.map +1 -1
  51. package/lib/cjs/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.js +1 -2
  52. package/lib/cjs/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.js.map +1 -1
  53. package/lib/cjs/curve/internalContexts/ClosestPointStrokeHandler.d.ts +1 -1
  54. package/lib/cjs/curve/internalContexts/ClosestPointStrokeHandler.d.ts.map +1 -1
  55. package/lib/cjs/curve/internalContexts/ClosestPointStrokeHandler.js +1 -2
  56. package/lib/cjs/curve/internalContexts/ClosestPointStrokeHandler.js.map +1 -1
  57. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.d.ts +113 -109
  58. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.d.ts.map +1 -1
  59. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.js +361 -385
  60. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -1
  61. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts +17 -17
  62. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  63. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js +153 -184
  64. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  65. package/lib/cjs/curve/spiral/DirectSpiral3d.d.ts +1 -2
  66. package/lib/cjs/curve/spiral/DirectSpiral3d.d.ts.map +1 -1
  67. package/lib/cjs/curve/spiral/DirectSpiral3d.js +9 -3
  68. package/lib/cjs/curve/spiral/DirectSpiral3d.js.map +1 -1
  69. package/lib/cjs/curve/spiral/IntegratedSpiral3d.d.ts +1 -2
  70. package/lib/cjs/curve/spiral/IntegratedSpiral3d.d.ts.map +1 -1
  71. package/lib/cjs/curve/spiral/IntegratedSpiral3d.js +10 -4
  72. package/lib/cjs/curve/spiral/IntegratedSpiral3d.js.map +1 -1
  73. package/lib/cjs/geometry3d/AngleSweep.d.ts +3 -1
  74. package/lib/cjs/geometry3d/AngleSweep.d.ts.map +1 -1
  75. package/lib/cjs/geometry3d/AngleSweep.js +6 -2
  76. package/lib/cjs/geometry3d/AngleSweep.js.map +1 -1
  77. package/lib/cjs/geometry3d/GeometryHandler.d.ts +33 -4
  78. package/lib/cjs/geometry3d/GeometryHandler.d.ts.map +1 -1
  79. package/lib/cjs/geometry3d/GeometryHandler.js +79 -1
  80. package/lib/cjs/geometry3d/GeometryHandler.js.map +1 -1
  81. package/lib/cjs/geometry3d/GrowableXYArray.d.ts +9 -6
  82. package/lib/cjs/geometry3d/GrowableXYArray.d.ts.map +1 -1
  83. package/lib/cjs/geometry3d/GrowableXYArray.js +20 -10
  84. package/lib/cjs/geometry3d/GrowableXYArray.js.map +1 -1
  85. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts +9 -6
  86. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  87. package/lib/cjs/geometry3d/GrowableXYZArray.js +20 -10
  88. package/lib/cjs/geometry3d/GrowableXYZArray.js.map +1 -1
  89. package/lib/cjs/geometry3d/Matrix3d.d.ts +4 -4
  90. package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
  91. package/lib/cjs/geometry3d/Matrix3d.js +5 -4
  92. package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
  93. package/lib/cjs/geometry3d/PointHelpers.d.ts.map +1 -1
  94. package/lib/cjs/geometry3d/PointHelpers.js +6 -7
  95. package/lib/cjs/geometry3d/PointHelpers.js.map +1 -1
  96. package/lib/cjs/numerics/BezierPolynomials.d.ts.map +1 -1
  97. package/lib/cjs/numerics/BezierPolynomials.js +1 -1
  98. package/lib/cjs/numerics/BezierPolynomials.js.map +1 -1
  99. package/lib/cjs/numerics/Newton.d.ts +52 -13
  100. package/lib/cjs/numerics/Newton.d.ts.map +1 -1
  101. package/lib/cjs/numerics/Newton.js +73 -23
  102. package/lib/cjs/numerics/Newton.js.map +1 -1
  103. package/lib/cjs/polyface/PolyfaceQuery.d.ts +14 -14
  104. package/lib/cjs/polyface/PolyfaceQuery.d.ts.map +1 -1
  105. package/lib/cjs/polyface/PolyfaceQuery.js +14 -14
  106. package/lib/cjs/polyface/PolyfaceQuery.js.map +1 -1
  107. package/lib/cjs/serialization/BGFBReader.js +2 -2
  108. package/lib/cjs/serialization/BGFBReader.js.map +1 -1
  109. package/lib/cjs/topology/Graph.d.ts +15 -15
  110. package/lib/cjs/topology/Graph.d.ts.map +1 -1
  111. package/lib/cjs/topology/Graph.js +1 -1
  112. package/lib/cjs/topology/Graph.js.map +1 -1
  113. package/lib/cjs/topology/HalfEdgeGraphSearch.d.ts +3 -3
  114. package/lib/cjs/topology/HalfEdgeGraphSearch.d.ts.map +1 -1
  115. package/lib/cjs/topology/HalfEdgeGraphSearch.js.map +1 -1
  116. package/lib/esm/Geometry.d.ts +8 -6
  117. package/lib/esm/Geometry.d.ts.map +1 -1
  118. package/lib/esm/Geometry.js +8 -6
  119. package/lib/esm/Geometry.js.map +1 -1
  120. package/lib/esm/curve/Arc3d.d.ts +7 -0
  121. package/lib/esm/curve/Arc3d.d.ts.map +1 -1
  122. package/lib/esm/curve/Arc3d.js +11 -0
  123. package/lib/esm/curve/Arc3d.js.map +1 -1
  124. package/lib/esm/curve/CurveChainWithDistanceIndex.d.ts +11 -2
  125. package/lib/esm/curve/CurveChainWithDistanceIndex.d.ts.map +1 -1
  126. package/lib/esm/curve/CurveChainWithDistanceIndex.js +25 -15
  127. package/lib/esm/curve/CurveChainWithDistanceIndex.js.map +1 -1
  128. package/lib/esm/curve/CurveCollection.d.ts +15 -6
  129. package/lib/esm/curve/CurveCollection.d.ts.map +1 -1
  130. package/lib/esm/curve/CurveCollection.js +15 -6
  131. package/lib/esm/curve/CurveCollection.js.map +1 -1
  132. package/lib/esm/curve/CurveCurve.d.ts +1 -1
  133. package/lib/esm/curve/CurveCurve.d.ts.map +1 -1
  134. package/lib/esm/curve/CurveCurve.js +2 -1
  135. package/lib/esm/curve/CurveCurve.js.map +1 -1
  136. package/lib/esm/curve/CurveLocationDetail.d.ts +21 -0
  137. package/lib/esm/curve/CurveLocationDetail.d.ts.map +1 -1
  138. package/lib/esm/curve/CurveLocationDetail.js +59 -0
  139. package/lib/esm/curve/CurveLocationDetail.js.map +1 -1
  140. package/lib/esm/curve/CurvePrimitive.d.ts +13 -12
  141. package/lib/esm/curve/CurvePrimitive.d.ts.map +1 -1
  142. package/lib/esm/curve/CurvePrimitive.js +12 -11
  143. package/lib/esm/curve/CurvePrimitive.js.map +1 -1
  144. package/lib/esm/curve/Loop.d.ts.map +1 -1
  145. package/lib/esm/curve/Loop.js +3 -1
  146. package/lib/esm/curve/Loop.js.map +1 -1
  147. package/lib/esm/curve/RegionOps.d.ts +17 -4
  148. package/lib/esm/curve/RegionOps.d.ts.map +1 -1
  149. package/lib/esm/curve/RegionOps.js +116 -20
  150. package/lib/esm/curve/RegionOps.js.map +1 -1
  151. package/lib/esm/curve/RegionOpsClassificationSweeps.d.ts +3 -11
  152. package/lib/esm/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  153. package/lib/esm/curve/RegionOpsClassificationSweeps.js +2 -92
  154. package/lib/esm/curve/RegionOpsClassificationSweeps.js.map +1 -1
  155. package/lib/esm/curve/StrokeOptions.d.ts +13 -6
  156. package/lib/esm/curve/StrokeOptions.d.ts.map +1 -1
  157. package/lib/esm/curve/StrokeOptions.js +13 -6
  158. package/lib/esm/curve/StrokeOptions.js.map +1 -1
  159. package/lib/esm/curve/internalContexts/AnnounceTangentStrokeHandler.d.ts +1 -1
  160. package/lib/esm/curve/internalContexts/AnnounceTangentStrokeHandler.d.ts.map +1 -1
  161. package/lib/esm/curve/internalContexts/AnnounceTangentStrokeHandler.js +1 -2
  162. package/lib/esm/curve/internalContexts/AnnounceTangentStrokeHandler.js.map +1 -1
  163. package/lib/esm/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.d.ts +1 -1
  164. package/lib/esm/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.d.ts.map +1 -1
  165. package/lib/esm/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.js +1 -2
  166. package/lib/esm/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.js.map +1 -1
  167. package/lib/esm/curve/internalContexts/ClosestPointStrokeHandler.d.ts +1 -1
  168. package/lib/esm/curve/internalContexts/ClosestPointStrokeHandler.d.ts.map +1 -1
  169. package/lib/esm/curve/internalContexts/ClosestPointStrokeHandler.js +1 -2
  170. package/lib/esm/curve/internalContexts/ClosestPointStrokeHandler.js.map +1 -1
  171. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.d.ts +113 -109
  172. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.d.ts.map +1 -1
  173. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.js +364 -388
  174. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -1
  175. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts +17 -17
  176. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  177. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js +153 -184
  178. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  179. package/lib/esm/curve/spiral/DirectSpiral3d.d.ts +1 -2
  180. package/lib/esm/curve/spiral/DirectSpiral3d.d.ts.map +1 -1
  181. package/lib/esm/curve/spiral/DirectSpiral3d.js +9 -3
  182. package/lib/esm/curve/spiral/DirectSpiral3d.js.map +1 -1
  183. package/lib/esm/curve/spiral/IntegratedSpiral3d.d.ts +1 -2
  184. package/lib/esm/curve/spiral/IntegratedSpiral3d.d.ts.map +1 -1
  185. package/lib/esm/curve/spiral/IntegratedSpiral3d.js +10 -4
  186. package/lib/esm/curve/spiral/IntegratedSpiral3d.js.map +1 -1
  187. package/lib/esm/geometry3d/AngleSweep.d.ts +3 -1
  188. package/lib/esm/geometry3d/AngleSweep.d.ts.map +1 -1
  189. package/lib/esm/geometry3d/AngleSweep.js +6 -2
  190. package/lib/esm/geometry3d/AngleSweep.js.map +1 -1
  191. package/lib/esm/geometry3d/GeometryHandler.d.ts +33 -4
  192. package/lib/esm/geometry3d/GeometryHandler.d.ts.map +1 -1
  193. package/lib/esm/geometry3d/GeometryHandler.js +77 -0
  194. package/lib/esm/geometry3d/GeometryHandler.js.map +1 -1
  195. package/lib/esm/geometry3d/GrowableXYArray.d.ts +9 -6
  196. package/lib/esm/geometry3d/GrowableXYArray.d.ts.map +1 -1
  197. package/lib/esm/geometry3d/GrowableXYArray.js +20 -10
  198. package/lib/esm/geometry3d/GrowableXYArray.js.map +1 -1
  199. package/lib/esm/geometry3d/GrowableXYZArray.d.ts +9 -6
  200. package/lib/esm/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  201. package/lib/esm/geometry3d/GrowableXYZArray.js +20 -10
  202. package/lib/esm/geometry3d/GrowableXYZArray.js.map +1 -1
  203. package/lib/esm/geometry3d/Matrix3d.d.ts +4 -4
  204. package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
  205. package/lib/esm/geometry3d/Matrix3d.js +5 -4
  206. package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
  207. package/lib/esm/geometry3d/PointHelpers.d.ts.map +1 -1
  208. package/lib/esm/geometry3d/PointHelpers.js +6 -7
  209. package/lib/esm/geometry3d/PointHelpers.js.map +1 -1
  210. package/lib/esm/numerics/BezierPolynomials.d.ts.map +1 -1
  211. package/lib/esm/numerics/BezierPolynomials.js +1 -1
  212. package/lib/esm/numerics/BezierPolynomials.js.map +1 -1
  213. package/lib/esm/numerics/Newton.d.ts +52 -13
  214. package/lib/esm/numerics/Newton.d.ts.map +1 -1
  215. package/lib/esm/numerics/Newton.js +71 -22
  216. package/lib/esm/numerics/Newton.js.map +1 -1
  217. package/lib/esm/polyface/PolyfaceQuery.d.ts +14 -14
  218. package/lib/esm/polyface/PolyfaceQuery.d.ts.map +1 -1
  219. package/lib/esm/polyface/PolyfaceQuery.js +14 -14
  220. package/lib/esm/polyface/PolyfaceQuery.js.map +1 -1
  221. package/lib/esm/serialization/BGFBReader.js +2 -2
  222. package/lib/esm/serialization/BGFBReader.js.map +1 -1
  223. package/lib/esm/topology/Graph.d.ts +15 -15
  224. package/lib/esm/topology/Graph.d.ts.map +1 -1
  225. package/lib/esm/topology/Graph.js +1 -1
  226. package/lib/esm/topology/Graph.js.map +1 -1
  227. package/lib/esm/topology/HalfEdgeGraphSearch.d.ts +3 -3
  228. package/lib/esm/topology/HalfEdgeGraphSearch.d.ts.map +1 -1
  229. package/lib/esm/topology/HalfEdgeGraphSearch.js.map +1 -1
  230. package/package.json +3 -3
  231. package/lib/cjs/curve/internalContexts/NewtonRtoRStrokeHandler.d.ts +0 -23
  232. package/lib/cjs/curve/internalContexts/NewtonRtoRStrokeHandler.d.ts.map +0 -1
  233. package/lib/cjs/curve/internalContexts/NewtonRtoRStrokeHandler.js +0 -37
  234. package/lib/cjs/curve/internalContexts/NewtonRtoRStrokeHandler.js.map +0 -1
  235. package/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.d.ts +0 -23
  236. package/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.d.ts.map +0 -1
  237. package/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js +0 -33
  238. package/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js.map +0 -1
@@ -20,12 +20,13 @@ import { SortablePolygon } from "../geometry3d/SortablePolygon";
20
20
  import { Transform } from "../geometry3d/Transform";
21
21
  import { MomentData } from "../geometry4d/MomentData";
22
22
  import { PolyfaceBuilder } from "../polyface/PolyfaceBuilder";
23
- import { HalfEdgeMask } from "../topology/Graph";
23
+ import { HalfEdge, HalfEdgeMask } from "../topology/Graph";
24
24
  import { HalfEdgeGraphSearch } from "../topology/HalfEdgeGraphSearch";
25
25
  import { HalfEdgeGraphOps } from "../topology/Merging";
26
26
  import { Triangulator } from "../topology/Triangulation";
27
27
  import { BagOfCurves, CurveChain, CurveCollection } from "./CurveCollection";
28
28
  import { CurveCurve } from "./CurveCurve";
29
+ import { CurveLocationDetail } from "./CurveLocationDetail";
29
30
  import { CurveOps } from "./CurveOps";
30
31
  import { CurvePrimitive } from "./CurvePrimitive";
31
32
  import { CurveWireMomentsXYZ } from "./CurveWireMomentsXYZ";
@@ -44,7 +45,7 @@ import { CurveSplitContext } from "./Query/CurveSplitContext";
44
45
  import { PointInOnOutContext } from "./Query/InOutTests";
45
46
  import { PlanarSubdivision } from "./Query/PlanarSubdivision";
46
47
  import { RegionMomentsXY } from "./RegionMomentsXY";
47
- import { RegionBooleanContext, RegionGroupOpType, RegionOpsFaceToFaceSearch } from "./RegionOpsClassificationSweeps";
48
+ import { RegionBooleanContext, RegionGroupMember, RegionGroupOpType, RegionOpsFaceToFaceSearch } from "./RegionOpsClassificationSweeps";
48
49
  import { UnionRegion } from "./UnionRegion";
49
50
  /**
50
51
  * * Options to control method [[RegionOps.consolidateAdjacentPrimitives]].
@@ -743,27 +744,113 @@ export class RegionOps {
743
744
  }
744
745
  return SortablePolygon.sortAsAnyRegion(loopAndArea);
745
746
  }
747
+ /**
748
+ * Simplify the graph by removing bridge edges that do not serve to connect inner and outer loops.
749
+ * * If edgeTags are `CurveLocationDetail`s, e.g., as set by `PlanarSubdivision.assembleHalfEdgeGraph`, attempt to heal edges split by removed bridge edges.
750
+ * @param graph half edges to process.
751
+ * @param isBridgeEdge optional function to identify a bridge edge. Default looks for `HalfEdgeMask.BRIDGE_EDGE`.
752
+ * @param faceToArea optional function to compute face area. Default is `HalfEdgeGraphSearch.signedFaceArea`.
753
+ * @returns the number of extraneous bridge edges removed from the graph.
754
+ * @internal
755
+ */
756
+ static removeExtraneousBridgeEdges(graph, isBridgeEdge, faceToArea) {
757
+ const toHeal = [];
758
+ const interiorBridges = [];
759
+ if (!faceToArea)
760
+ faceToArea = (node) => HalfEdgeGraphSearch.signedFaceArea(node);
761
+ if (!isBridgeEdge)
762
+ isBridgeEdge = (node) => node.isMaskSet(HalfEdgeMask.BRIDGE_EDGE);
763
+ // isolate dangling bridges, bridges separating different faces, and "exterior" bridges in the negative area face
764
+ graph.announceEdges((_g, node) => {
765
+ if (isBridgeEdge(node)) {
766
+ if (node.isDangling || node.edgeMate.isDangling || !node.findAroundFace(node.edgeMate) || faceToArea(node) < 0.0) {
767
+ toHeal.push(node.vertexSuccessor);
768
+ toHeal.push(node.edgeMate.vertexSuccessor);
769
+ node.isolateEdge();
770
+ }
771
+ else {
772
+ interiorBridges.push(node);
773
+ }
774
+ }
775
+ return true;
776
+ });
777
+ // Relies only on face loop orientation. Doesn't use static HalfEdgeMasks!
778
+ const isBoundaryEdge = (node) => {
779
+ if (faceToArea(node) < 0.0)
780
+ return true; // exterior face
781
+ if (node.findAroundFace(node.edgeMate))
782
+ return false; // interior washer face
783
+ return faceToArea(node.edgeMate) < 0.0; // adjacent to exterior face
784
+ };
785
+ // All bridges in the negative area face were isolated, but this may have promoted other bridges to the
786
+ // negative area face. Keep isolating these bridge edges until none remain.
787
+ let numIsolatedThisPass;
788
+ do {
789
+ numIsolatedThisPass = 0;
790
+ for (const node of interiorBridges) {
791
+ if (!node.isIsolatedEdge && isBoundaryEdge(node)) {
792
+ toHeal.push(node.vertexSuccessor);
793
+ toHeal.push(node.edgeMate.vertexSuccessor);
794
+ node.isolateEdge();
795
+ numIsolatedThisPass++;
796
+ }
797
+ }
798
+ } while (numIsolatedThisPass > 0);
799
+ // lambda to extend the detail interval on a side of a healed edge
800
+ const mergeDetails = (he, newFraction, newPoint) => {
801
+ if (he && he.edgeTag instanceof CurveLocationDetail && he.sortData !== undefined && newFraction !== undefined && newPoint) {
802
+ if (he.sortData > 0)
803
+ he.edgeTag.captureFraction1Point1(newFraction, newPoint);
804
+ else
805
+ he.edgeTag.captureFractionPoint(newFraction, newPoint);
806
+ }
807
+ };
808
+ // At this point all removable bridges are isolated. Clean up their original vertex loops, if possible.
809
+ for (const doomedA of toHeal) {
810
+ const doomedB = doomedA.vertexSuccessor;
811
+ if ( // are the geometries mergeable?
812
+ doomedA !== doomedB &&
813
+ doomedA.edgeTag instanceof CurveLocationDetail && doomedA.sortData !== undefined &&
814
+ doomedB.edgeTag instanceof CurveLocationDetail && doomedB.sortData !== undefined &&
815
+ doomedA.edgeTag.curve === doomedB.edgeTag.curve &&
816
+ doomedA.edgeTag.isInterval() && doomedB.edgeTag.isInterval() &&
817
+ doomedA.sortData * doomedB.sortData < 0 &&
818
+ ((doomedA.sortData > 0 && Geometry.isSmallRelative(doomedA.edgeTag.fraction - doomedB.edgeTag.fraction1)) ||
819
+ (doomedA.sortData < 0 && Geometry.isSmallRelative(doomedA.edgeTag.fraction1 - doomedB.edgeTag.fraction)))) {
820
+ const survivorA = HalfEdge.healEdge(doomedA, false);
821
+ if (survivorA) {
822
+ const endFractionA = (doomedA.sortData > 0) ? doomedA.edgeTag.fraction1 : doomedA.edgeTag.fraction;
823
+ const endPointA = (doomedA.sortData > 0) ? doomedA.edgeTag.point1 : doomedA.edgeTag.point;
824
+ mergeDetails(survivorA, endFractionA, endPointA);
825
+ const endFractionB = (doomedB.sortData > 0) ? doomedB.edgeTag.fraction1 : doomedB.edgeTag.fraction;
826
+ const endPointB = (doomedB.sortData > 0) ? doomedB.edgeTag.point1 : doomedB.edgeTag.point;
827
+ mergeDetails(survivorA.edgeMate, endFractionB, endPointB);
828
+ }
829
+ }
830
+ }
831
+ return graph.deleteIsolatedEdges();
832
+ }
746
833
  /**
747
834
  * Collect inputs that are nominally closed: regions, and physically closed curves.
748
835
  * * Physically closed input curves are each returned wrapped in a Loop to facilitate xy-algorithms,
749
836
  * but outside this limited context, these Loops only makes sense if they are planar.
837
+ * @param curves inputs
838
+ * @param openCurves optional array to receive open input curves that were not returned as regions.
839
+ * @param tolerance optional distance tolerance for determining physical closure. Default is [[Geometry.smallMetricDistance]].
750
840
  */
751
- static collectRegionsAndClosedPrimitives(curves, tolerance = Geometry.smallMetricDistance) {
841
+ static collectRegionsAndClosedPrimitives(curves, openCurves, tolerance = Geometry.smallMetricDistance) {
752
842
  const regions = [];
753
843
  if (!Array.isArray(curves))
754
844
  curves = [curves];
755
845
  for (const curve of curves) {
756
- if (curve instanceof Loop || curve instanceof ParityRegion || curve instanceof UnionRegion) {
846
+ if (curve instanceof Loop || curve instanceof ParityRegion || curve instanceof UnionRegion)
757
847
  regions.push(curve);
758
- }
759
- else if (curve instanceof Path) {
760
- if (curve.isPhysicallyClosedCurve(tolerance))
761
- regions.push(Loop.create(...curve.children));
762
- }
763
- else if (curve instanceof CurvePrimitive) {
764
- if (curve.isPhysicallyClosedCurve(tolerance))
765
- regions.push(Loop.create(curve));
766
- }
848
+ else if (curve instanceof Path && curve.isPhysicallyClosedCurve(tolerance))
849
+ regions.push(Loop.create(...curve.children));
850
+ else if (curve instanceof CurvePrimitive && curve.isPhysicallyClosedCurve(tolerance))
851
+ regions.push(Loop.create(curve));
852
+ else if (openCurves)
853
+ openCurves.push(curve);
767
854
  }
768
855
  return regions;
769
856
  }
@@ -773,9 +860,9 @@ export class RegionOps {
773
860
  * * "Holes" implied/bounded by inputs are _not_ preserved/discovered in output; in particular [[ParityRegion]]
774
861
  * hole loops are treated like any other positive area loops.
775
862
  * * A common use case of this method is to assemble the bounding negative-area "exterior" loop for each connected
776
- * component of input curves. Passing `addBridges = true` decreases the number of connected components for nested
777
- * input [[Loop]]s, and thus increases the likelihood of returning exactly one exterior loop. (This is why the
778
- * default value for `addBridges` is `true`.)
863
+ * component of input curves. Passing addBridges = true adds "bridge" segments to connect unconnected input [[Loops]]s
864
+ * and thereby increases the likelihood that a single connected component is returned. (This is why the default value
865
+ * for addBridges is true.)
779
866
  * @param curvesAndRegions Any collection of curves. Each [[AnyRegion]] contributes its children _stripped of
780
867
  * parity context_.
781
868
  * @param tolerance optional distance tolerance for coincidence. Default is [[Geometry.smallMetricDistance]].
@@ -794,21 +881,30 @@ export class RegionOps {
794
881
  primitives = TransferWithSplitArcs.clone(BagOfCurves.create(...primitives)).children;
795
882
  const range = this.curveArrayRange(primitives);
796
883
  const areaTol = this.computeXYAreaTolerance(range, tolerance);
797
- if (addBridges) { // generate a temp graph to extract its bridge edges
884
+ let hasOpenCurve = false;
885
+ if (addBridges) { // generate a temp graph from ONLY the closed inputs to extract its bridge edges
798
886
  const context = RegionBooleanContext.create(RegionGroupOpType.Union, RegionGroupOpType.Union);
799
- const regions = this.collectRegionsAndClosedPrimitives(curvesAndRegions, tolerance);
887
+ const openCurves = [];
888
+ const regions = this.collectRegionsAndClosedPrimitives(curvesAndRegions, openCurves, tolerance);
889
+ hasOpenCurve = openCurves.length > 0;
800
890
  if (regions.length > 0) {
801
891
  context.addMembers(regions, undefined);
802
892
  context.annotateAndMergeCurvesInGraph(tolerance);
803
893
  context.graph.announceEdges((_graph, edge) => {
804
- if (edge.isMaskSet(HalfEdgeMask.BRIDGE_EDGE))
805
- primitives.push(LineSegment3d.create(edge.getPoint3d(), edge.faceSuccessor.getPoint3d()));
894
+ if (edge.isMaskSet(HalfEdgeMask.BRIDGE_EDGE)) {
895
+ // ensure the bridge edge roundtrips thru assembleHalfEdgeGraph so that we can filter it later if necessary
896
+ const bridgeSegment = LineSegment3d.create(edge.getPoint3d(), edge.faceSuccessor.getPoint3d());
897
+ bridgeSegment.parent = new RegionGroupMember(bridgeSegment, context.extraGeometry);
898
+ primitives.push(bridgeSegment);
899
+ }
806
900
  return true;
807
901
  });
808
902
  }
809
903
  }
810
904
  const intersections = CurveCurve.allIntersectionsAmongPrimitivesXY(primitives, tolerance);
811
905
  const graph = PlanarSubdivision.assembleHalfEdgeGraph(primitives, intersections, tolerance);
906
+ if (addBridges && hasOpenCurve)
907
+ RegionOps.removeExtraneousBridgeEdges(graph);
812
908
  return PlanarSubdivision.collectSignedLoopSetsInHalfEdgeGraph(graph, areaTol);
813
909
  }
814
910
  /**