@itwin/core-geometry 4.1.0-dev.68 → 4.1.0-dev.69

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 (349) hide show
  1. package/lib/cjs/Geometry.js.map +1 -1
  2. package/lib/cjs/bspline/BSplineCurve.d.ts +1 -1
  3. package/lib/cjs/bspline/BSplineCurve.d.ts.map +1 -1
  4. package/lib/cjs/bspline/BSplineCurve.js +2 -2
  5. package/lib/cjs/bspline/BSplineCurve.js.map +1 -1
  6. package/lib/cjs/bspline/BSplineSurface.d.ts.map +1 -1
  7. package/lib/cjs/bspline/BSplineSurface.js +1 -1
  8. package/lib/cjs/bspline/BSplineSurface.js.map +1 -1
  9. package/lib/cjs/bspline/BezierCurveBase.d.ts +1 -1
  10. package/lib/cjs/bspline/BezierCurveBase.d.ts.map +1 -1
  11. package/lib/cjs/bspline/BezierCurveBase.js +2 -2
  12. package/lib/cjs/bspline/BezierCurveBase.js.map +1 -1
  13. package/lib/cjs/bspline/InterpolationCurve3d.js.map +1 -1
  14. package/lib/cjs/clipping/ClipUtils.js.map +1 -1
  15. package/lib/cjs/core-geometry.d.ts +3 -2
  16. package/lib/cjs/core-geometry.d.ts.map +1 -1
  17. package/lib/cjs/core-geometry.js +4 -5
  18. package/lib/cjs/core-geometry.js.map +1 -1
  19. package/lib/cjs/curve/Arc3d.d.ts +1 -1
  20. package/lib/cjs/curve/Arc3d.d.ts.map +1 -1
  21. package/lib/cjs/curve/Arc3d.js +2 -2
  22. package/lib/cjs/curve/Arc3d.js.map +1 -1
  23. package/lib/cjs/curve/CurveChainWithDistanceIndex.d.ts +1 -1
  24. package/lib/cjs/curve/CurveChainWithDistanceIndex.d.ts.map +1 -1
  25. package/lib/cjs/curve/CurveChainWithDistanceIndex.js +2 -2
  26. package/lib/cjs/curve/CurveChainWithDistanceIndex.js.map +1 -1
  27. package/lib/cjs/curve/CurveCollection.d.ts +2 -2
  28. package/lib/cjs/curve/CurveCollection.js +2 -2
  29. package/lib/cjs/curve/CurveCollection.js.map +1 -1
  30. package/lib/cjs/curve/CurveCurve.js.map +1 -1
  31. package/lib/cjs/curve/CurveLocationDetail.js.map +1 -1
  32. package/lib/cjs/curve/CurveOps.d.ts +77 -0
  33. package/lib/cjs/curve/CurveOps.d.ts.map +1 -0
  34. package/lib/cjs/curve/CurveOps.js +160 -0
  35. package/lib/cjs/curve/CurveOps.js.map +1 -0
  36. package/lib/cjs/curve/CurvePrimitive.d.ts +13 -13
  37. package/lib/cjs/curve/CurvePrimitive.d.ts.map +1 -1
  38. package/lib/cjs/curve/CurvePrimitive.js.map +1 -1
  39. package/lib/cjs/curve/GeometryQuery.d.ts +2 -2
  40. package/lib/cjs/curve/GeometryQuery.d.ts.map +1 -1
  41. package/lib/cjs/curve/GeometryQuery.js +2 -2
  42. package/lib/cjs/curve/GeometryQuery.js.map +1 -1
  43. package/lib/cjs/curve/LineSegment3d.d.ts +1 -1
  44. package/lib/cjs/curve/LineSegment3d.d.ts.map +1 -1
  45. package/lib/cjs/curve/LineSegment3d.js +2 -2
  46. package/lib/cjs/curve/LineSegment3d.js.map +1 -1
  47. package/lib/cjs/curve/LineString3d.d.ts +1 -1
  48. package/lib/cjs/curve/LineString3d.d.ts.map +1 -1
  49. package/lib/cjs/curve/LineString3d.js +2 -2
  50. package/lib/cjs/curve/LineString3d.js.map +1 -1
  51. package/lib/cjs/curve/Loop.js.map +1 -1
  52. package/lib/cjs/curve/OffsetOptions.d.ts +97 -0
  53. package/lib/cjs/curve/OffsetOptions.d.ts.map +1 -0
  54. package/lib/cjs/curve/OffsetOptions.js +166 -0
  55. package/lib/cjs/curve/OffsetOptions.js.map +1 -0
  56. package/lib/cjs/curve/ProxyCurve.d.ts +1 -1
  57. package/lib/cjs/curve/ProxyCurve.d.ts.map +1 -1
  58. package/lib/cjs/curve/ProxyCurve.js.map +1 -1
  59. package/lib/cjs/curve/Query/StrokeCountMap.js.map +1 -1
  60. package/lib/cjs/curve/RegionOps.d.ts +10 -13
  61. package/lib/cjs/curve/RegionOps.d.ts.map +1 -1
  62. package/lib/cjs/curve/RegionOps.js +16 -17
  63. package/lib/cjs/curve/RegionOps.js.map +1 -1
  64. package/lib/cjs/curve/RegionOpsClassificationSweeps.js +2 -2
  65. package/lib/cjs/curve/RegionOpsClassificationSweeps.js.map +1 -1
  66. package/lib/cjs/curve/StrokeOptions.js.map +1 -1
  67. package/lib/cjs/curve/{ChainCollectorContext.d.ts → internalContexts/ChainCollectorContext.d.ts} +4 -4
  68. package/lib/cjs/curve/internalContexts/ChainCollectorContext.d.ts.map +1 -0
  69. package/lib/cjs/curve/{ChainCollectorContext.js → internalContexts/ChainCollectorContext.js} +4 -4
  70. package/lib/cjs/curve/internalContexts/ChainCollectorContext.js.map +1 -0
  71. package/lib/cjs/curve/internalContexts/MultiChainCollector.d.ts +59 -74
  72. package/lib/cjs/curve/internalContexts/MultiChainCollector.d.ts.map +1 -1
  73. package/lib/cjs/curve/internalContexts/MultiChainCollector.js +130 -223
  74. package/lib/cjs/curve/internalContexts/MultiChainCollector.js.map +1 -1
  75. package/lib/cjs/curve/internalContexts/PlaneAltitudeRangeContext.js.map +1 -1
  76. package/lib/cjs/curve/internalContexts/PolygonOffsetContext.d.ts +6 -100
  77. package/lib/cjs/curve/internalContexts/PolygonOffsetContext.d.ts.map +1 -1
  78. package/lib/cjs/curve/internalContexts/PolygonOffsetContext.js +12 -167
  79. package/lib/cjs/curve/internalContexts/PolygonOffsetContext.js.map +1 -1
  80. package/lib/cjs/curve/spiral/IntegratedSpiral3d.js +1 -1
  81. package/lib/cjs/curve/spiral/IntegratedSpiral3d.js.map +1 -1
  82. package/lib/cjs/curve/spiral/TransitionSpiral3d.d.ts +1 -1
  83. package/lib/cjs/curve/spiral/TransitionSpiral3d.d.ts.map +1 -1
  84. package/lib/cjs/curve/spiral/TransitionSpiral3d.js +2 -2
  85. package/lib/cjs/curve/spiral/TransitionSpiral3d.js.map +1 -1
  86. package/lib/cjs/curve/spiral/XYCurveEvaluator.js +1 -1
  87. package/lib/cjs/curve/spiral/XYCurveEvaluator.js.map +1 -1
  88. package/lib/cjs/geometry3d/Angle.js.map +1 -1
  89. package/lib/cjs/geometry3d/AngleSweep.js.map +1 -1
  90. package/lib/cjs/geometry3d/BarycentricTriangle.js.map +1 -1
  91. package/lib/cjs/geometry3d/BilinearPatch.js.map +1 -1
  92. package/lib/cjs/geometry3d/GrowableBlockedArray.d.ts.map +1 -1
  93. package/lib/cjs/geometry3d/GrowableBlockedArray.js +1 -1
  94. package/lib/cjs/geometry3d/GrowableBlockedArray.js.map +1 -1
  95. package/lib/cjs/geometry3d/GrowableFloat64Array.d.ts.map +1 -1
  96. package/lib/cjs/geometry3d/GrowableFloat64Array.js +1 -1
  97. package/lib/cjs/geometry3d/GrowableFloat64Array.js.map +1 -1
  98. package/lib/cjs/geometry3d/Matrix3d.js +5 -5
  99. package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
  100. package/lib/cjs/geometry3d/OrderedRotationAngles.js.map +1 -1
  101. package/lib/cjs/geometry3d/Plane3d.js.map +1 -1
  102. package/lib/cjs/geometry3d/Plane3dByOriginAndUnitNormal.js.map +1 -1
  103. package/lib/cjs/geometry3d/Plane3dByOriginAndVectors.js.map +1 -1
  104. package/lib/cjs/geometry3d/Point2dVector2d.d.ts +8 -9
  105. package/lib/cjs/geometry3d/Point2dVector2d.d.ts.map +1 -1
  106. package/lib/cjs/geometry3d/Point2dVector2d.js +9 -10
  107. package/lib/cjs/geometry3d/Point2dVector2d.js.map +1 -1
  108. package/lib/cjs/geometry3d/Point3dArrayCarrier.js.map +1 -1
  109. package/lib/cjs/geometry3d/Point3dVector3d.d.ts +4 -4
  110. package/lib/cjs/geometry3d/Point3dVector3d.js +5 -5
  111. package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
  112. package/lib/cjs/geometry3d/PointHelpers.d.ts.map +1 -1
  113. package/lib/cjs/geometry3d/PointHelpers.js +5 -5
  114. package/lib/cjs/geometry3d/PointHelpers.js.map +1 -1
  115. package/lib/cjs/geometry3d/PolygonOps.d.ts +1 -2
  116. package/lib/cjs/geometry3d/PolygonOps.d.ts.map +1 -1
  117. package/lib/cjs/geometry3d/PolygonOps.js +2 -3
  118. package/lib/cjs/geometry3d/PolygonOps.js.map +1 -1
  119. package/lib/cjs/geometry3d/Range.js.map +1 -1
  120. package/lib/cjs/geometry3d/Ray2d.d.ts +69 -0
  121. package/lib/cjs/geometry3d/Ray2d.d.ts.map +1 -0
  122. package/lib/cjs/geometry3d/Ray2d.js +146 -0
  123. package/lib/cjs/geometry3d/Ray2d.js.map +1 -0
  124. package/lib/cjs/geometry3d/Ray3d.js.map +1 -1
  125. package/lib/cjs/geometry3d/Transform.js +3 -3
  126. package/lib/cjs/geometry3d/Transform.js.map +1 -1
  127. package/lib/cjs/geometry3d/YawPitchRollAngles.js.map +1 -1
  128. package/lib/cjs/numerics/ConvexPolygon2d.d.ts +7 -49
  129. package/lib/cjs/numerics/ConvexPolygon2d.d.ts.map +1 -1
  130. package/lib/cjs/numerics/ConvexPolygon2d.js +16 -107
  131. package/lib/cjs/numerics/ConvexPolygon2d.js.map +1 -1
  132. package/lib/cjs/numerics/Newton.js.map +1 -1
  133. package/lib/cjs/numerics/Polynomials.d.ts.map +1 -1
  134. package/lib/cjs/numerics/Polynomials.js +0 -2
  135. package/lib/cjs/numerics/Polynomials.js.map +1 -1
  136. package/lib/cjs/numerics/Quadrature.js +5 -5
  137. package/lib/cjs/numerics/Quadrature.js.map +1 -1
  138. package/lib/cjs/polyface/IndexedEdgeMatcher.js +1 -1
  139. package/lib/cjs/polyface/IndexedEdgeMatcher.js.map +1 -1
  140. package/lib/cjs/polyface/PolyfaceBuilder.d.ts.map +1 -1
  141. package/lib/cjs/polyface/PolyfaceBuilder.js +2 -2
  142. package/lib/cjs/polyface/PolyfaceBuilder.js.map +1 -1
  143. package/lib/cjs/polyface/PolyfaceQuery.d.ts +10 -7
  144. package/lib/cjs/polyface/PolyfaceQuery.d.ts.map +1 -1
  145. package/lib/cjs/polyface/PolyfaceQuery.js +13 -12
  146. package/lib/cjs/polyface/PolyfaceQuery.js.map +1 -1
  147. package/lib/cjs/polyface/TaggedNumericData.js +1 -1
  148. package/lib/cjs/polyface/TaggedNumericData.js.map +1 -1
  149. package/lib/cjs/polyface/multiclip/BuildAverageNormalsContext.js +2 -2
  150. package/lib/cjs/polyface/multiclip/BuildAverageNormalsContext.js.map +1 -1
  151. package/lib/cjs/polyface/multiclip/OffsetMeshContext.js.map +1 -1
  152. package/lib/cjs/polyface/multiclip/SweepLineStringToFacetContext.js.map +1 -1
  153. package/lib/cjs/serialization/BGFBWriter.js.map +1 -1
  154. package/lib/cjs/serialization/GeometrySamples.js.map +1 -1
  155. package/lib/cjs/serialization/IModelJsonSchema.d.ts +2 -7
  156. package/lib/cjs/serialization/IModelJsonSchema.d.ts.map +1 -1
  157. package/lib/cjs/serialization/IModelJsonSchema.js +2 -7
  158. package/lib/cjs/serialization/IModelJsonSchema.js.map +1 -1
  159. package/lib/cjs/topology/ChainMerge.js +1 -1
  160. package/lib/cjs/topology/ChainMerge.js.map +1 -1
  161. package/lib/cjs/topology/HalfEdgeGraphSearch.d.ts.map +1 -1
  162. package/lib/cjs/topology/HalfEdgeGraphSearch.js +1 -1
  163. package/lib/cjs/topology/HalfEdgeGraphSearch.js.map +1 -1
  164. package/lib/cjs/topology/HalfEdgeGraphSpineContext.js +1 -1
  165. package/lib/cjs/topology/HalfEdgeGraphSpineContext.js.map +1 -1
  166. package/lib/cjs/topology/HalfEdgePriorityQueue.d.ts.map +1 -1
  167. package/lib/cjs/topology/HalfEdgePriorityQueue.js +1 -1
  168. package/lib/cjs/topology/HalfEdgePriorityQueue.js.map +1 -1
  169. package/lib/cjs/topology/RegularizeFace.js +3 -3
  170. package/lib/cjs/topology/RegularizeFace.js.map +1 -1
  171. package/lib/cjs/topology/Triangulation.js +1 -1
  172. package/lib/cjs/topology/Triangulation.js.map +1 -1
  173. package/lib/esm/Geometry.js.map +1 -1
  174. package/lib/esm/bspline/BSplineCurve.d.ts +1 -1
  175. package/lib/esm/bspline/BSplineCurve.d.ts.map +1 -1
  176. package/lib/esm/bspline/BSplineCurve.js +1 -1
  177. package/lib/esm/bspline/BSplineCurve.js.map +1 -1
  178. package/lib/esm/bspline/BSplineSurface.d.ts.map +1 -1
  179. package/lib/esm/bspline/BSplineSurface.js +1 -1
  180. package/lib/esm/bspline/BSplineSurface.js.map +1 -1
  181. package/lib/esm/bspline/BezierCurveBase.d.ts +1 -1
  182. package/lib/esm/bspline/BezierCurveBase.d.ts.map +1 -1
  183. package/lib/esm/bspline/BezierCurveBase.js +1 -1
  184. package/lib/esm/bspline/BezierCurveBase.js.map +1 -1
  185. package/lib/esm/bspline/InterpolationCurve3d.js.map +1 -1
  186. package/lib/esm/clipping/ClipUtils.js.map +1 -1
  187. package/lib/esm/core-geometry.d.ts +3 -2
  188. package/lib/esm/core-geometry.d.ts.map +1 -1
  189. package/lib/esm/core-geometry.js +3 -3
  190. package/lib/esm/core-geometry.js.map +1 -1
  191. package/lib/esm/curve/Arc3d.d.ts +1 -1
  192. package/lib/esm/curve/Arc3d.d.ts.map +1 -1
  193. package/lib/esm/curve/Arc3d.js +1 -1
  194. package/lib/esm/curve/Arc3d.js.map +1 -1
  195. package/lib/esm/curve/CurveChainWithDistanceIndex.d.ts +1 -1
  196. package/lib/esm/curve/CurveChainWithDistanceIndex.d.ts.map +1 -1
  197. package/lib/esm/curve/CurveChainWithDistanceIndex.js +1 -1
  198. package/lib/esm/curve/CurveChainWithDistanceIndex.js.map +1 -1
  199. package/lib/esm/curve/CurveCollection.d.ts +2 -2
  200. package/lib/esm/curve/CurveCollection.js +2 -2
  201. package/lib/esm/curve/CurveCollection.js.map +1 -1
  202. package/lib/esm/curve/CurveCurve.js.map +1 -1
  203. package/lib/esm/curve/CurveLocationDetail.js.map +1 -1
  204. package/lib/esm/curve/CurveOps.d.ts +77 -0
  205. package/lib/esm/curve/CurveOps.d.ts.map +1 -0
  206. package/lib/esm/curve/CurveOps.js +156 -0
  207. package/lib/esm/curve/CurveOps.js.map +1 -0
  208. package/lib/esm/curve/CurvePrimitive.d.ts +13 -13
  209. package/lib/esm/curve/CurvePrimitive.d.ts.map +1 -1
  210. package/lib/esm/curve/CurvePrimitive.js.map +1 -1
  211. package/lib/esm/curve/GeometryQuery.d.ts +2 -2
  212. package/lib/esm/curve/GeometryQuery.d.ts.map +1 -1
  213. package/lib/esm/curve/GeometryQuery.js +2 -2
  214. package/lib/esm/curve/GeometryQuery.js.map +1 -1
  215. package/lib/esm/curve/LineSegment3d.d.ts +1 -1
  216. package/lib/esm/curve/LineSegment3d.d.ts.map +1 -1
  217. package/lib/esm/curve/LineSegment3d.js +1 -1
  218. package/lib/esm/curve/LineSegment3d.js.map +1 -1
  219. package/lib/esm/curve/LineString3d.d.ts +1 -1
  220. package/lib/esm/curve/LineString3d.d.ts.map +1 -1
  221. package/lib/esm/curve/LineString3d.js +1 -1
  222. package/lib/esm/curve/LineString3d.js.map +1 -1
  223. package/lib/esm/curve/Loop.js.map +1 -1
  224. package/lib/esm/curve/OffsetOptions.d.ts +97 -0
  225. package/lib/esm/curve/OffsetOptions.d.ts.map +1 -0
  226. package/lib/esm/curve/OffsetOptions.js +161 -0
  227. package/lib/esm/curve/OffsetOptions.js.map +1 -0
  228. package/lib/esm/curve/ProxyCurve.d.ts +1 -1
  229. package/lib/esm/curve/ProxyCurve.d.ts.map +1 -1
  230. package/lib/esm/curve/ProxyCurve.js.map +1 -1
  231. package/lib/esm/curve/Query/StrokeCountMap.js.map +1 -1
  232. package/lib/esm/curve/RegionOps.d.ts +10 -13
  233. package/lib/esm/curve/RegionOps.d.ts.map +1 -1
  234. package/lib/esm/curve/RegionOps.js +17 -18
  235. package/lib/esm/curve/RegionOps.js.map +1 -1
  236. package/lib/esm/curve/RegionOpsClassificationSweeps.js +2 -2
  237. package/lib/esm/curve/RegionOpsClassificationSweeps.js.map +1 -1
  238. package/lib/esm/curve/StrokeOptions.js.map +1 -1
  239. package/lib/esm/curve/{ChainCollectorContext.d.ts → internalContexts/ChainCollectorContext.d.ts} +4 -4
  240. package/lib/esm/curve/internalContexts/ChainCollectorContext.d.ts.map +1 -0
  241. package/lib/esm/curve/{ChainCollectorContext.js → internalContexts/ChainCollectorContext.js} +4 -4
  242. package/lib/esm/curve/internalContexts/ChainCollectorContext.js.map +1 -0
  243. package/lib/esm/curve/internalContexts/MultiChainCollector.d.ts +59 -74
  244. package/lib/esm/curve/internalContexts/MultiChainCollector.d.ts.map +1 -1
  245. package/lib/esm/curve/internalContexts/MultiChainCollector.js +129 -221
  246. package/lib/esm/curve/internalContexts/MultiChainCollector.js.map +1 -1
  247. package/lib/esm/curve/internalContexts/PlaneAltitudeRangeContext.js.map +1 -1
  248. package/lib/esm/curve/internalContexts/PolygonOffsetContext.d.ts +6 -100
  249. package/lib/esm/curve/internalContexts/PolygonOffsetContext.d.ts.map +1 -1
  250. package/lib/esm/curve/internalContexts/PolygonOffsetContext.js +9 -162
  251. package/lib/esm/curve/internalContexts/PolygonOffsetContext.js.map +1 -1
  252. package/lib/esm/curve/spiral/IntegratedSpiral3d.js +1 -1
  253. package/lib/esm/curve/spiral/IntegratedSpiral3d.js.map +1 -1
  254. package/lib/esm/curve/spiral/TransitionSpiral3d.d.ts +1 -1
  255. package/lib/esm/curve/spiral/TransitionSpiral3d.d.ts.map +1 -1
  256. package/lib/esm/curve/spiral/TransitionSpiral3d.js +1 -1
  257. package/lib/esm/curve/spiral/TransitionSpiral3d.js.map +1 -1
  258. package/lib/esm/curve/spiral/XYCurveEvaluator.js +1 -1
  259. package/lib/esm/curve/spiral/XYCurveEvaluator.js.map +1 -1
  260. package/lib/esm/geometry3d/Angle.js.map +1 -1
  261. package/lib/esm/geometry3d/AngleSweep.js.map +1 -1
  262. package/lib/esm/geometry3d/BarycentricTriangle.js.map +1 -1
  263. package/lib/esm/geometry3d/BilinearPatch.js.map +1 -1
  264. package/lib/esm/geometry3d/GrowableBlockedArray.d.ts.map +1 -1
  265. package/lib/esm/geometry3d/GrowableBlockedArray.js +1 -1
  266. package/lib/esm/geometry3d/GrowableBlockedArray.js.map +1 -1
  267. package/lib/esm/geometry3d/GrowableFloat64Array.d.ts.map +1 -1
  268. package/lib/esm/geometry3d/GrowableFloat64Array.js +1 -1
  269. package/lib/esm/geometry3d/GrowableFloat64Array.js.map +1 -1
  270. package/lib/esm/geometry3d/Matrix3d.js +5 -5
  271. package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
  272. package/lib/esm/geometry3d/OrderedRotationAngles.js.map +1 -1
  273. package/lib/esm/geometry3d/Plane3d.js.map +1 -1
  274. package/lib/esm/geometry3d/Plane3dByOriginAndUnitNormal.js.map +1 -1
  275. package/lib/esm/geometry3d/Plane3dByOriginAndVectors.js.map +1 -1
  276. package/lib/esm/geometry3d/Point2dVector2d.d.ts +8 -9
  277. package/lib/esm/geometry3d/Point2dVector2d.d.ts.map +1 -1
  278. package/lib/esm/geometry3d/Point2dVector2d.js +9 -10
  279. package/lib/esm/geometry3d/Point2dVector2d.js.map +1 -1
  280. package/lib/esm/geometry3d/Point3dArrayCarrier.js.map +1 -1
  281. package/lib/esm/geometry3d/Point3dVector3d.d.ts +4 -4
  282. package/lib/esm/geometry3d/Point3dVector3d.js +5 -5
  283. package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
  284. package/lib/esm/geometry3d/PointHelpers.d.ts.map +1 -1
  285. package/lib/esm/geometry3d/PointHelpers.js +5 -5
  286. package/lib/esm/geometry3d/PointHelpers.js.map +1 -1
  287. package/lib/esm/geometry3d/PolygonOps.d.ts +1 -2
  288. package/lib/esm/geometry3d/PolygonOps.d.ts.map +1 -1
  289. package/lib/esm/geometry3d/PolygonOps.js +2 -3
  290. package/lib/esm/geometry3d/PolygonOps.js.map +1 -1
  291. package/lib/esm/geometry3d/Range.js.map +1 -1
  292. package/lib/esm/geometry3d/Ray2d.d.ts +69 -0
  293. package/lib/esm/geometry3d/Ray2d.d.ts.map +1 -0
  294. package/lib/esm/geometry3d/Ray2d.js +142 -0
  295. package/lib/esm/geometry3d/Ray2d.js.map +1 -0
  296. package/lib/esm/geometry3d/Ray3d.js.map +1 -1
  297. package/lib/esm/geometry3d/Transform.js +3 -3
  298. package/lib/esm/geometry3d/Transform.js.map +1 -1
  299. package/lib/esm/geometry3d/YawPitchRollAngles.js.map +1 -1
  300. package/lib/esm/numerics/ConvexPolygon2d.d.ts +7 -49
  301. package/lib/esm/numerics/ConvexPolygon2d.d.ts.map +1 -1
  302. package/lib/esm/numerics/ConvexPolygon2d.js +14 -104
  303. package/lib/esm/numerics/ConvexPolygon2d.js.map +1 -1
  304. package/lib/esm/numerics/Newton.js.map +1 -1
  305. package/lib/esm/numerics/Polynomials.d.ts.map +1 -1
  306. package/lib/esm/numerics/Polynomials.js +0 -2
  307. package/lib/esm/numerics/Polynomials.js.map +1 -1
  308. package/lib/esm/numerics/Quadrature.js +5 -5
  309. package/lib/esm/numerics/Quadrature.js.map +1 -1
  310. package/lib/esm/polyface/IndexedEdgeMatcher.js +1 -1
  311. package/lib/esm/polyface/IndexedEdgeMatcher.js.map +1 -1
  312. package/lib/esm/polyface/PolyfaceBuilder.d.ts.map +1 -1
  313. package/lib/esm/polyface/PolyfaceBuilder.js +2 -2
  314. package/lib/esm/polyface/PolyfaceBuilder.js.map +1 -1
  315. package/lib/esm/polyface/PolyfaceQuery.d.ts +10 -7
  316. package/lib/esm/polyface/PolyfaceQuery.d.ts.map +1 -1
  317. package/lib/esm/polyface/PolyfaceQuery.js +14 -13
  318. package/lib/esm/polyface/PolyfaceQuery.js.map +1 -1
  319. package/lib/esm/polyface/TaggedNumericData.js +1 -1
  320. package/lib/esm/polyface/TaggedNumericData.js.map +1 -1
  321. package/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js +2 -2
  322. package/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js.map +1 -1
  323. package/lib/esm/polyface/multiclip/OffsetMeshContext.js.map +1 -1
  324. package/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js.map +1 -1
  325. package/lib/esm/serialization/BGFBWriter.js.map +1 -1
  326. package/lib/esm/serialization/GeometrySamples.js.map +1 -1
  327. package/lib/esm/serialization/IModelJsonSchema.d.ts +2 -7
  328. package/lib/esm/serialization/IModelJsonSchema.d.ts.map +1 -1
  329. package/lib/esm/serialization/IModelJsonSchema.js +2 -7
  330. package/lib/esm/serialization/IModelJsonSchema.js.map +1 -1
  331. package/lib/esm/topology/ChainMerge.js +1 -1
  332. package/lib/esm/topology/ChainMerge.js.map +1 -1
  333. package/lib/esm/topology/HalfEdgeGraphSearch.d.ts.map +1 -1
  334. package/lib/esm/topology/HalfEdgeGraphSearch.js +1 -1
  335. package/lib/esm/topology/HalfEdgeGraphSearch.js.map +1 -1
  336. package/lib/esm/topology/HalfEdgeGraphSpineContext.js +1 -1
  337. package/lib/esm/topology/HalfEdgeGraphSpineContext.js.map +1 -1
  338. package/lib/esm/topology/HalfEdgePriorityQueue.d.ts.map +1 -1
  339. package/lib/esm/topology/HalfEdgePriorityQueue.js +1 -1
  340. package/lib/esm/topology/HalfEdgePriorityQueue.js.map +1 -1
  341. package/lib/esm/topology/RegularizeFace.js +3 -3
  342. package/lib/esm/topology/RegularizeFace.js.map +1 -1
  343. package/lib/esm/topology/Triangulation.js +1 -1
  344. package/lib/esm/topology/Triangulation.js.map +1 -1
  345. package/package.json +5 -16
  346. package/lib/cjs/curve/ChainCollectorContext.d.ts.map +0 -1
  347. package/lib/cjs/curve/ChainCollectorContext.js.map +0 -1
  348. package/lib/esm/curve/ChainCollectorContext.d.ts.map +0 -1
  349. package/lib/esm/curve/ChainCollectorContext.js.map +0 -1
@@ -152,7 +152,7 @@ class ChainMergeContext {
152
152
  p.sortData = this.primarySortKey(p);
153
153
  }
154
154
  const sortArray = this._graph.allHalfEdges.slice();
155
- sortArray.sort(ChainMergeContext.nodeCompareSortData);
155
+ sortArray.sort((nodeA, nodeB) => ChainMergeContext.nodeCompareSortData(nodeA, nodeB));
156
156
  const xyzTolerance = this._options.tolerance;
157
157
  // A node is unvisited if it is its own vertex successor !!!
158
158
  // otherwise the node has already been twisted into a base vertex.
@@ -1 +1 @@
1
- {"version":3,"file":"ChainMerge.js","sourceRoot":"","sources":["../../../src/topology/ChainMerge.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 { ConvexClipPlaneSet } from \"../clipping/ConvexClipPlaneSet\";\r\nimport { LineSegment3d } from \"../curve/LineSegment3d\";\r\nimport { LineString3d } from \"../curve/LineString3d\";\r\nimport { Geometry, PlaneAltitudeEvaluator } from \"../Geometry\";\r\nimport { GrowableXYZArray } from \"../geometry3d/GrowableXYZArray\";\r\nimport { Point3d, Vector3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { HalfEdgeGraphOps } from \"./Merging\";\r\n\r\n/**\r\n * interface containing various options appropriate to merging lines segments into chains.\r\n * @internal\r\n */\r\nexport interface ChainMergeContextOptions {\r\n /**\r\n * Tolerance for declaring points equal\r\n * * Default is `Geometry.smallMetricDistance`\r\n */\r\n tolerance?: number;\r\n /**\r\n * Direction for primary sort.\r\n * * Default is `Vector3d.create(0.294234298, 0.72391399, 0.45234328798)`\r\n * * this vector should NOT be along a principal x,y,z direction.\r\n * * The internal form will be normalized.\r\n */\r\n primarySortDirection?: Vector3d;\r\n}\r\n/** Internal form of ChainMergeContextOptions -- same field names, but required to have contents. */\r\nclass ChainMergeContextValidatedOptions {\r\n /**\r\n * Tolerance for declaring points equal.\r\n */\r\n public tolerance: number;\r\n /** UNNORMALIZED base vector for sorting.\r\n * * Actual vector hoisted into an instance is normalized.\r\n */\r\n private static readonly _defaultPrimarySortDirection = Vector3d.create(0.294234298, 0.72391399, 0.45234328798);\r\n /**\r\n * Direction for primary sort. This is normalized !!!\r\n */\r\n public primarySortDirection: Vector3d;\r\n /** return a unit vector aligned with optional direction.\r\n * * Default return is into the first quadrant at a quirky angle so any perpendicular plane is unlikely to hit many points\r\n */\r\n public static createPrimarySortVector(vector?: Vector3d): Vector3d {\r\n if (vector === undefined) {\r\n vector = this._defaultPrimarySortDirection.clone();\r\n }\r\n return vector.normalizeWithDefault(\r\n ChainMergeContextValidatedOptions._defaultPrimarySortDirection.x,\r\n ChainMergeContextValidatedOptions._defaultPrimarySortDirection.y,\r\n ChainMergeContextValidatedOptions._defaultPrimarySortDirection.z);\r\n }\r\n /**\r\n * PRIVATE constructor -- assumes all inputs are validated in public create method !!!!\r\n * @param tolerance\r\n * @param unitVectorForPrimarySort\r\n */\r\n private constructor(tolerance: number, unitVectorForPrimarySort: Vector3d) {\r\n this.tolerance = tolerance;\r\n this.primarySortDirection = unitVectorForPrimarySort;\r\n }\r\n /** return the default option set. */\r\n public static createFromUnValidated(options?: ChainMergeContextOptions): ChainMergeContextValidatedOptions {\r\n const result = new ChainMergeContextValidatedOptions(Geometry.smallMetricDistance, ChainMergeContextValidatedOptions.createPrimarySortVector());\r\n if (options !== undefined) {\r\n if (options.tolerance !== undefined)\r\n result.tolerance = options.tolerance;\r\n if (options.primarySortDirection !== undefined)\r\n result.primarySortDirection = ChainMergeContextValidatedOptions.createPrimarySortVector();\r\n }\r\n return result;\r\n }\r\n /** Clone this context. */\r\n public clone(): ChainMergeContextValidatedOptions {\r\n return new ChainMergeContextValidatedOptions(this.tolerance, this.primarySortDirection);\r\n }\r\n}\r\n/**\r\n * * Context for assembling line segments into chains.\r\n * * Use the context in phases:\r\n * * Create the context: `context = ChainMergeContext.create ()`\r\n * * Add line with any combination of:\r\n * * `context.addSegment(pointA, pointB)`\r\n * * `context.addLineSegment3dArray (segments)`\r\n * * Scan all coordinate data for common coordinates. Twist nodes together to form chains:\r\n * * `context.clusterAndMergeVerticesXYZ ()`\r\n * * Collect the chains:\r\n * * myLinestringArray = context.collectMaximalChains();\r\n * * The context carries an optional plane which is used by addSegmentsOnPlane\r\n *\r\n * @internal\r\n */\r\nexport class ChainMergeContext {\r\n\r\n private _graph: HalfEdgeGraph;\r\n private _options: ChainMergeContextValidatedOptions;\r\n private _plane?: PlaneAltitudeEvaluator;\r\n private _convexClipper?: ConvexClipPlaneSet;\r\n private constructor(options: ChainMergeContextValidatedOptions) {\r\n this._graph = new HalfEdgeGraph();\r\n this._options = options;\r\n }\r\n /** Save a reference plane for later use, e.g. in addSegmentsOnPlane */\r\n public set plane(value: PlaneAltitudeEvaluator | undefined) { this._plane = value; }\r\n /** Property access for the reference plane. */\r\n public get plane(): PlaneAltitudeEvaluator | undefined { return this._plane; }\r\n\r\n /** Save a reference plane for later use, e.g. in addSegmentsOnPlane */\r\n public set convexClipper(value: ConvexClipPlaneSet | undefined) { this._convexClipper = value; }\r\n /** Property access for the reference plane. */\r\n public get convexClipper(): ConvexClipPlaneSet | undefined { return this._convexClipper; }\r\n\r\n /**\r\n * * Construct an empty chain merge graph.\r\n * * The options parameter may contain any combination of the options values.\r\n * * tolerance = absolute tolerance for declaring points equal.\r\n * * Default is `Geometry.smallMetricDistance`\r\n * * primarySortDirection = direction for first sort.\r\n * * To minimize clash among points on primary sort, this should NOT be perpendicular to any principal plane.\r\n * * The default points into the first octant with non-obvious components.\r\n */\r\n public static create(options?: ChainMergeContextOptions): ChainMergeContext {\r\n const validatedOptions = ChainMergeContextValidatedOptions.createFromUnValidated(options);\r\n return new ChainMergeContext(validatedOptions);\r\n }\r\n /** Add a segment to the evolving graph. */\r\n public addSegment(pointA: Point3d, pointB: Point3d) {\r\n this._graph.createEdgeXYZXYZ(pointA.x, pointA.y, pointA.z, 0, pointB.x, pointB.y, pointB.z, 0);\r\n }\r\n /** Add all segments from an array to the graph. */\r\n public addLineSegment3dArray(data: LineSegment3d[]) {\r\n for (const segment of data) {\r\n this.addSegment(segment.point0Ref, segment.point1Ref);\r\n }\r\n }\r\n /** Add edges for all segments that are \"on\" the plane.\r\n * * No action if `this.plane` is undefined.\r\n */\r\n public addSegmentsOnPlane(points: GrowableXYZArray, addClosure: boolean = false) {\r\n if (!this._plane)\r\n return;\r\n const plane = this._plane;\r\n let i0 = addClosure ? points.length - 1 : 0;\r\n let a0 = points.evaluateUncheckedIndexPlaneAltitude(i0, plane);\r\n let i1 = addClosure ? 0 : 1;\r\n let a1;\r\n for (; i1 < points.length; i0 = i1++ , a0 = a1) {\r\n a1 = points.evaluateUncheckedIndexPlaneAltitude(i1, plane);\r\n if (Geometry.isSmallMetricDistance(a0) && Geometry.isSmallMetricDistance(a1))\r\n this._graph.createEdgeXYZXYZ(\r\n points.getXAtUncheckedPointIndex(i0), points.getYAtUncheckedPointIndex(i0), points.getZAtUncheckedPointIndex(i0), 0,\r\n points.getXAtUncheckedPointIndex(i1), points.getYAtUncheckedPointIndex(i1), points.getZAtUncheckedPointIndex(i1), 0);\r\n }\r\n }\r\n /**\r\n * Return a numeric value to be used for sorting, with little chance widely separated nodes will have identical key.\r\n * * Any single x,y,z component is a poor choice because horizontal and vertical alignment is common.\r\n * * Hence take dot product of x,y,z with non-trivial fraction values.\r\n * @param node node with x,y,z coordinates\r\n */\r\n private primarySortKey(node: HalfEdge): number {\r\n return this._options.primarySortDirection.dotProductXYZ(node.x, node.y, node.z);\r\n }\r\n /** Return difference of sortData members as sort comparison */\r\n private static nodeCompareSortData(nodeA: HalfEdge, nodeB: HalfEdge): number {\r\n return nodeA.sortData! - nodeB.sortData!;\r\n }\r\n /** test if nodeA is a dangling edge end (i.e. edges around vertex equal 1, but detect it without walking all the way around. */\r\n private static isIsolatedEnd(nodeA: HalfEdge): boolean {\r\n return nodeA.vertexSuccessor === nodeA;\r\n }\r\n\r\n /** test if nodeA is at a vertex with exactly 2 edges (i.e. edges around vertex equal w, but detect it without walking all the way around. */\r\n private static isChainInteriorVertex(nodeA: HalfEdge): boolean {\r\n const nodeB = nodeA.vertexSuccessor;\r\n return nodeB !== nodeA && nodeB.vertexSuccessor === nodeA;\r\n }\r\n\r\n /**\r\n * * isolate all edge ends.\r\n * * perform cluster analysis to determine nearly coincident points.\r\n * * pinch all edges together at each vertex.\r\n */\r\n public clusterAndMergeVerticesXYZ() {\r\n HalfEdgeGraphOps.isolateAllEdges(this._graph);\r\n for (const p of this._graph.allHalfEdges) {\r\n p.sortData = this.primarySortKey(p);\r\n }\r\n const sortArray = this._graph.allHalfEdges.slice();\r\n sortArray.sort(ChainMergeContext.nodeCompareSortData);\r\n const xyzTolerance = this._options.tolerance;\r\n // A node is unvisited if it is its own vertex successor !!!\r\n // otherwise the node has already been twisted into a base vertex.\r\n const n = sortArray.length;\r\n for (let i0 = 0; i0 < n; i0++) {\r\n const node0 = sortArray[i0];\r\n const qMin = node0.sortData!;\r\n const qMax = qMin + xyzTolerance;\r\n if (ChainMergeContext.isIsolatedEnd(node0)) {\r\n for (let i1 = i0 + 1; i1 < n; i1++) {\r\n const node1 = sortArray[i1];\r\n if (ChainMergeContext.isIsolatedEnd(node1)) {\r\n if (node1.sortData! > qMax)\r\n break;\r\n if (node0.distanceXYZ(node1) <= xyzTolerance) {\r\n HalfEdge.pinch(node0, node1);\r\n node1.setXYZFrom(node0); // force true equal coordinates.\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n /**\r\n * If node0 is not visited, creating a linestring with that starting edge and all successive edges along a chain.\r\n * @param chains growing array of chains.\r\n * @param node0 start node for search.\r\n */\r\n private collectMaximalLineString3dFromStartNode(chains: LineString3d[], node0: HalfEdge, visitMask: HalfEdgeMask) {\r\n if (!node0.isMaskSet(visitMask)) {\r\n const ls = LineString3d.create();\r\n ls.addPointXYZ(node0.x, node0.y, node0.z);\r\n for (; ;) {\r\n node0.setMask(visitMask);\r\n node0.edgeMate.setMask(visitMask);\r\n node0 = node0.faceSuccessor;\r\n ls.addPointXYZ(node0.x, node0.y, node0.z);\r\n if (node0.isMaskSet(visitMask) || !ChainMergeContext.isChainInteriorVertex(node0))\r\n break;\r\n }\r\n chains.push(ls);\r\n }\r\n }\r\n /**\r\n * If node0 is not visited, creating a linestring with that starting edge and all successive edges along a chain.\r\n * @param chains growing array of chains.\r\n * @param node0 start node for search.\r\n */\r\n private collectMaximalGrowableXYXArrayFromStartNode(result: GrowableXYZArray[], node0: HalfEdge, visitMask: HalfEdgeMask) {\r\n if (!node0.isMaskSet(visitMask)) {\r\n const points = new GrowableXYZArray();\r\n points.pushXYZ(node0.x, node0.y, node0.z);\r\n for (; ;) {\r\n node0.setMask(visitMask);\r\n node0.edgeMate.setMask(visitMask);\r\n node0 = node0.faceSuccessor;\r\n points.pushXYZ(node0.x, node0.y, node0.z);\r\n if (node0.isMaskSet(visitMask) || !ChainMergeContext.isChainInteriorVertex(node0))\r\n break;\r\n }\r\n if (points.length > 0)\r\n result.push(points);\r\n }\r\n }\r\n\r\n /**\r\n * * find edges with start, end in same vertex loop.\r\n * * pinch them away from the loop\r\n * * set mask on both sides.\r\n * * Return the number of excisions.\r\n */\r\n private exciseAndMarkSlingEdges(mask: HalfEdgeMask): number {\r\n let n = 0;\r\n for (const p of this._graph.allHalfEdges) {\r\n if (p.distanceXYZ(p.edgeMate) < this._options.tolerance\r\n && !p.isMaskSet(mask)) {\r\n const q = p.edgeMate;\r\n HalfEdge.pinch(p, p.vertexPredecessor);\r\n HalfEdge.pinch(q, q.vertexPredecessor);\r\n p.setMask(mask);\r\n q.setMask(mask);\r\n n++;\r\n }\r\n }\r\n return n;\r\n }\r\n /** Collect chains which have maximum edge count, broken at an vertex with other than 2 edges.\r\n * * This is assumed to be preceded by a call to a vertex-cluster step such as `clusterAndMergeVerticesYXZ`\r\n */\r\n public collectMaximalChains(): LineString3d[] {\r\n const result: LineString3d[] = [];\r\n const visitMask = HalfEdgeMask.VISITED;\r\n // Pass 0: excise and mark zero-length edges.\r\n this.exciseAndMarkSlingEdges(visitMask);\r\n this._graph.clearMask(visitMask);\r\n // Pass 1: only start at non-interior edges -- vertices with one edge or more than 2 edges.\r\n // (Note that collectMaximalChain checks the visit mask.)\r\n for (const node0 of this._graph.allHalfEdges) {\r\n if (!ChainMergeContext.isChainInteriorVertex(node0)) {\r\n this.collectMaximalLineString3dFromStartNode(result, node0, visitMask);\r\n }\r\n }\r\n // Pass 2: start anywhere in an unvisited loop.\r\n for (const node0 of this._graph.allHalfEdges) {\r\n this.collectMaximalLineString3dFromStartNode(result, node0, visitMask);\r\n }\r\n return result;\r\n }\r\n public collectMaximalGrowableXYZArrays(): GrowableXYZArray[] {\r\n const result: GrowableXYZArray[] = [];\r\n const visitMask = HalfEdgeMask.VISITED;\r\n // Pass 0: excise and mark zero-length edges.\r\n this.exciseAndMarkSlingEdges(visitMask);\r\n this._graph.clearMask(visitMask);\r\n // Pass 1: only start at non-interior edges -- vertices with one edge or more than 2 edges.\r\n // (Note that collectMaximalChain checks the visit mask.)\r\n for (const node0 of this._graph.allHalfEdges) {\r\n if (!ChainMergeContext.isChainInteriorVertex(node0)) {\r\n this.collectMaximalGrowableXYXArrayFromStartNode(result, node0, visitMask);\r\n }\r\n }\r\n // Pass 2: start anywhere in an unvisited loop.\r\n for (const node0 of this._graph.allHalfEdges) {\r\n this.collectMaximalGrowableXYXArrayFromStartNode(result, node0, visitMask);\r\n }\r\n return result;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"ChainMerge.js","sourceRoot":"","sources":["../../../src/topology/ChainMerge.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 { ConvexClipPlaneSet } from \"../clipping/ConvexClipPlaneSet\";\r\nimport { LineSegment3d } from \"../curve/LineSegment3d\";\r\nimport { LineString3d } from \"../curve/LineString3d\";\r\nimport { Geometry, PlaneAltitudeEvaluator } from \"../Geometry\";\r\nimport { GrowableXYZArray } from \"../geometry3d/GrowableXYZArray\";\r\nimport { Point3d, Vector3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { HalfEdgeGraphOps } from \"./Merging\";\r\n\r\n/**\r\n * interface containing various options appropriate to merging lines segments into chains.\r\n * @internal\r\n */\r\nexport interface ChainMergeContextOptions {\r\n /**\r\n * Tolerance for declaring points equal\r\n * * Default is `Geometry.smallMetricDistance`\r\n */\r\n tolerance?: number;\r\n /**\r\n * Direction for primary sort.\r\n * * Default is `Vector3d.create(0.294234298, 0.72391399, 0.45234328798)`\r\n * * this vector should NOT be along a principal x,y,z direction.\r\n * * The internal form will be normalized.\r\n */\r\n primarySortDirection?: Vector3d;\r\n}\r\n/** Internal form of ChainMergeContextOptions -- same field names, but required to have contents. */\r\nclass ChainMergeContextValidatedOptions {\r\n /**\r\n * Tolerance for declaring points equal.\r\n */\r\n public tolerance: number;\r\n /** UNNORMALIZED base vector for sorting.\r\n * * Actual vector hoisted into an instance is normalized.\r\n */\r\n private static readonly _defaultPrimarySortDirection = Vector3d.create(0.294234298, 0.72391399, 0.45234328798);\r\n /**\r\n * Direction for primary sort. This is normalized !!!\r\n */\r\n public primarySortDirection: Vector3d;\r\n /** return a unit vector aligned with optional direction.\r\n * * Default return is into the first quadrant at a quirky angle so any perpendicular plane is unlikely to hit many points\r\n */\r\n public static createPrimarySortVector(vector?: Vector3d): Vector3d {\r\n if (vector === undefined) {\r\n vector = this._defaultPrimarySortDirection.clone();\r\n }\r\n return vector.normalizeWithDefault(\r\n ChainMergeContextValidatedOptions._defaultPrimarySortDirection.x,\r\n ChainMergeContextValidatedOptions._defaultPrimarySortDirection.y,\r\n ChainMergeContextValidatedOptions._defaultPrimarySortDirection.z);\r\n }\r\n /**\r\n * PRIVATE constructor -- assumes all inputs are validated in public create method !!!!\r\n * @param tolerance\r\n * @param unitVectorForPrimarySort\r\n */\r\n private constructor(tolerance: number, unitVectorForPrimarySort: Vector3d) {\r\n this.tolerance = tolerance;\r\n this.primarySortDirection = unitVectorForPrimarySort;\r\n }\r\n /** return the default option set. */\r\n public static createFromUnValidated(options?: ChainMergeContextOptions): ChainMergeContextValidatedOptions {\r\n const result = new ChainMergeContextValidatedOptions(Geometry.smallMetricDistance, ChainMergeContextValidatedOptions.createPrimarySortVector());\r\n if (options !== undefined) {\r\n if (options.tolerance !== undefined)\r\n result.tolerance = options.tolerance;\r\n if (options.primarySortDirection !== undefined)\r\n result.primarySortDirection = ChainMergeContextValidatedOptions.createPrimarySortVector();\r\n }\r\n return result;\r\n }\r\n /** Clone this context. */\r\n public clone(): ChainMergeContextValidatedOptions {\r\n return new ChainMergeContextValidatedOptions(this.tolerance, this.primarySortDirection);\r\n }\r\n}\r\n/**\r\n * * Context for assembling line segments into chains.\r\n * * Use the context in phases:\r\n * * Create the context: `context = ChainMergeContext.create ()`\r\n * * Add line with any combination of:\r\n * * `context.addSegment(pointA, pointB)`\r\n * * `context.addLineSegment3dArray (segments)`\r\n * * Scan all coordinate data for common coordinates. Twist nodes together to form chains:\r\n * * `context.clusterAndMergeVerticesXYZ ()`\r\n * * Collect the chains:\r\n * * myLinestringArray = context.collectMaximalChains();\r\n * * The context carries an optional plane which is used by addSegmentsOnPlane\r\n *\r\n * @internal\r\n */\r\nexport class ChainMergeContext {\r\n\r\n private _graph: HalfEdgeGraph;\r\n private _options: ChainMergeContextValidatedOptions;\r\n private _plane?: PlaneAltitudeEvaluator;\r\n private _convexClipper?: ConvexClipPlaneSet;\r\n private constructor(options: ChainMergeContextValidatedOptions) {\r\n this._graph = new HalfEdgeGraph();\r\n this._options = options;\r\n }\r\n /** Save a reference plane for later use, e.g. in addSegmentsOnPlane */\r\n public set plane(value: PlaneAltitudeEvaluator | undefined) { this._plane = value; }\r\n /** Property access for the reference plane. */\r\n public get plane(): PlaneAltitudeEvaluator | undefined { return this._plane; }\r\n\r\n /** Save a reference plane for later use, e.g. in addSegmentsOnPlane */\r\n public set convexClipper(value: ConvexClipPlaneSet | undefined) { this._convexClipper = value; }\r\n /** Property access for the reference plane. */\r\n public get convexClipper(): ConvexClipPlaneSet | undefined { return this._convexClipper; }\r\n\r\n /**\r\n * * Construct an empty chain merge graph.\r\n * * The options parameter may contain any combination of the options values.\r\n * * tolerance = absolute tolerance for declaring points equal.\r\n * * Default is `Geometry.smallMetricDistance`\r\n * * primarySortDirection = direction for first sort.\r\n * * To minimize clash among points on primary sort, this should NOT be perpendicular to any principal plane.\r\n * * The default points into the first octant with non-obvious components.\r\n */\r\n public static create(options?: ChainMergeContextOptions): ChainMergeContext {\r\n const validatedOptions = ChainMergeContextValidatedOptions.createFromUnValidated(options);\r\n return new ChainMergeContext(validatedOptions);\r\n }\r\n /** Add a segment to the evolving graph. */\r\n public addSegment(pointA: Point3d, pointB: Point3d) {\r\n this._graph.createEdgeXYZXYZ(pointA.x, pointA.y, pointA.z, 0, pointB.x, pointB.y, pointB.z, 0);\r\n }\r\n /** Add all segments from an array to the graph. */\r\n public addLineSegment3dArray(data: LineSegment3d[]) {\r\n for (const segment of data) {\r\n this.addSegment(segment.point0Ref, segment.point1Ref);\r\n }\r\n }\r\n /** Add edges for all segments that are \"on\" the plane.\r\n * * No action if `this.plane` is undefined.\r\n */\r\n public addSegmentsOnPlane(points: GrowableXYZArray, addClosure: boolean = false) {\r\n if (!this._plane)\r\n return;\r\n const plane = this._plane;\r\n let i0 = addClosure ? points.length - 1 : 0;\r\n let a0 = points.evaluateUncheckedIndexPlaneAltitude(i0, plane);\r\n let i1 = addClosure ? 0 : 1;\r\n let a1;\r\n for (; i1 < points.length; i0 = i1++ , a0 = a1) {\r\n a1 = points.evaluateUncheckedIndexPlaneAltitude(i1, plane);\r\n if (Geometry.isSmallMetricDistance(a0) && Geometry.isSmallMetricDistance(a1))\r\n this._graph.createEdgeXYZXYZ(\r\n points.getXAtUncheckedPointIndex(i0), points.getYAtUncheckedPointIndex(i0), points.getZAtUncheckedPointIndex(i0), 0,\r\n points.getXAtUncheckedPointIndex(i1), points.getYAtUncheckedPointIndex(i1), points.getZAtUncheckedPointIndex(i1), 0);\r\n }\r\n }\r\n /**\r\n * Return a numeric value to be used for sorting, with little chance widely separated nodes will have identical key.\r\n * * Any single x,y,z component is a poor choice because horizontal and vertical alignment is common.\r\n * * Hence take dot product of x,y,z with non-trivial fraction values.\r\n * @param node node with x,y,z coordinates\r\n */\r\n private primarySortKey(node: HalfEdge): number {\r\n return this._options.primarySortDirection.dotProductXYZ(node.x, node.y, node.z);\r\n }\r\n /** Return difference of sortData members as sort comparison */\r\n private static nodeCompareSortData(nodeA: HalfEdge, nodeB: HalfEdge): number {\r\n return nodeA.sortData! - nodeB.sortData!;\r\n }\r\n /** test if nodeA is a dangling edge end (i.e. edges around vertex equal 1, but detect it without walking all the way around. */\r\n private static isIsolatedEnd(nodeA: HalfEdge): boolean {\r\n return nodeA.vertexSuccessor === nodeA;\r\n }\r\n\r\n /** test if nodeA is at a vertex with exactly 2 edges (i.e. edges around vertex equal w, but detect it without walking all the way around. */\r\n private static isChainInteriorVertex(nodeA: HalfEdge): boolean {\r\n const nodeB = nodeA.vertexSuccessor;\r\n return nodeB !== nodeA && nodeB.vertexSuccessor === nodeA;\r\n }\r\n\r\n /**\r\n * * isolate all edge ends.\r\n * * perform cluster analysis to determine nearly coincident points.\r\n * * pinch all edges together at each vertex.\r\n */\r\n public clusterAndMergeVerticesXYZ() {\r\n HalfEdgeGraphOps.isolateAllEdges(this._graph);\r\n for (const p of this._graph.allHalfEdges) {\r\n p.sortData = this.primarySortKey(p);\r\n }\r\n const sortArray = this._graph.allHalfEdges.slice();\r\n sortArray.sort((nodeA, nodeB) => ChainMergeContext.nodeCompareSortData(nodeA, nodeB));\r\n const xyzTolerance = this._options.tolerance;\r\n // A node is unvisited if it is its own vertex successor !!!\r\n // otherwise the node has already been twisted into a base vertex.\r\n const n = sortArray.length;\r\n for (let i0 = 0; i0 < n; i0++) {\r\n const node0 = sortArray[i0];\r\n const qMin = node0.sortData!;\r\n const qMax = qMin + xyzTolerance;\r\n if (ChainMergeContext.isIsolatedEnd(node0)) {\r\n for (let i1 = i0 + 1; i1 < n; i1++) {\r\n const node1 = sortArray[i1];\r\n if (ChainMergeContext.isIsolatedEnd(node1)) {\r\n if (node1.sortData! > qMax)\r\n break;\r\n if (node0.distanceXYZ(node1) <= xyzTolerance) {\r\n HalfEdge.pinch(node0, node1);\r\n node1.setXYZFrom(node0); // force true equal coordinates.\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n /**\r\n * If node0 is not visited, creating a linestring with that starting edge and all successive edges along a chain.\r\n * @param chains growing array of chains.\r\n * @param node0 start node for search.\r\n */\r\n private collectMaximalLineString3dFromStartNode(chains: LineString3d[], node0: HalfEdge, visitMask: HalfEdgeMask) {\r\n if (!node0.isMaskSet(visitMask)) {\r\n const ls = LineString3d.create();\r\n ls.addPointXYZ(node0.x, node0.y, node0.z);\r\n for (; ;) {\r\n node0.setMask(visitMask);\r\n node0.edgeMate.setMask(visitMask);\r\n node0 = node0.faceSuccessor;\r\n ls.addPointXYZ(node0.x, node0.y, node0.z);\r\n if (node0.isMaskSet(visitMask) || !ChainMergeContext.isChainInteriorVertex(node0))\r\n break;\r\n }\r\n chains.push(ls);\r\n }\r\n }\r\n /**\r\n * If node0 is not visited, creating a linestring with that starting edge and all successive edges along a chain.\r\n * @param chains growing array of chains.\r\n * @param node0 start node for search.\r\n */\r\n private collectMaximalGrowableXYXArrayFromStartNode(result: GrowableXYZArray[], node0: HalfEdge, visitMask: HalfEdgeMask) {\r\n if (!node0.isMaskSet(visitMask)) {\r\n const points = new GrowableXYZArray();\r\n points.pushXYZ(node0.x, node0.y, node0.z);\r\n for (; ;) {\r\n node0.setMask(visitMask);\r\n node0.edgeMate.setMask(visitMask);\r\n node0 = node0.faceSuccessor;\r\n points.pushXYZ(node0.x, node0.y, node0.z);\r\n if (node0.isMaskSet(visitMask) || !ChainMergeContext.isChainInteriorVertex(node0))\r\n break;\r\n }\r\n if (points.length > 0)\r\n result.push(points);\r\n }\r\n }\r\n\r\n /**\r\n * * find edges with start, end in same vertex loop.\r\n * * pinch them away from the loop\r\n * * set mask on both sides.\r\n * * Return the number of excisions.\r\n */\r\n private exciseAndMarkSlingEdges(mask: HalfEdgeMask): number {\r\n let n = 0;\r\n for (const p of this._graph.allHalfEdges) {\r\n if (p.distanceXYZ(p.edgeMate) < this._options.tolerance\r\n && !p.isMaskSet(mask)) {\r\n const q = p.edgeMate;\r\n HalfEdge.pinch(p, p.vertexPredecessor);\r\n HalfEdge.pinch(q, q.vertexPredecessor);\r\n p.setMask(mask);\r\n q.setMask(mask);\r\n n++;\r\n }\r\n }\r\n return n;\r\n }\r\n /** Collect chains which have maximum edge count, broken at an vertex with other than 2 edges.\r\n * * This is assumed to be preceded by a call to a vertex-cluster step such as `clusterAndMergeVerticesYXZ`\r\n */\r\n public collectMaximalChains(): LineString3d[] {\r\n const result: LineString3d[] = [];\r\n const visitMask = HalfEdgeMask.VISITED;\r\n // Pass 0: excise and mark zero-length edges.\r\n this.exciseAndMarkSlingEdges(visitMask);\r\n this._graph.clearMask(visitMask);\r\n // Pass 1: only start at non-interior edges -- vertices with one edge or more than 2 edges.\r\n // (Note that collectMaximalChain checks the visit mask.)\r\n for (const node0 of this._graph.allHalfEdges) {\r\n if (!ChainMergeContext.isChainInteriorVertex(node0)) {\r\n this.collectMaximalLineString3dFromStartNode(result, node0, visitMask);\r\n }\r\n }\r\n // Pass 2: start anywhere in an unvisited loop.\r\n for (const node0 of this._graph.allHalfEdges) {\r\n this.collectMaximalLineString3dFromStartNode(result, node0, visitMask);\r\n }\r\n return result;\r\n }\r\n public collectMaximalGrowableXYZArrays(): GrowableXYZArray[] {\r\n const result: GrowableXYZArray[] = [];\r\n const visitMask = HalfEdgeMask.VISITED;\r\n // Pass 0: excise and mark zero-length edges.\r\n this.exciseAndMarkSlingEdges(visitMask);\r\n this._graph.clearMask(visitMask);\r\n // Pass 1: only start at non-interior edges -- vertices with one edge or more than 2 edges.\r\n // (Note that collectMaximalChain checks the visit mask.)\r\n for (const node0 of this._graph.allHalfEdges) {\r\n if (!ChainMergeContext.isChainInteriorVertex(node0)) {\r\n this.collectMaximalGrowableXYXArrayFromStartNode(result, node0, visitMask);\r\n }\r\n }\r\n // Pass 2: start anywhere in an unvisited loop.\r\n for (const node0 of this._graph.allHalfEdges) {\r\n this.collectMaximalGrowableXYXArrayFromStartNode(result, node0, visitMask);\r\n }\r\n return result;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgeGraphSearch.d.ts","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSearch.ts"],"names":[],"mappings":"AAKA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACjH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAChC;AACD;GACG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,YAAY,CAAU;IAC9B;;;;OAIG;gBACgB,IAAI,EAAE,YAAY,EAAE,WAAW,GAAE,OAAc;IAIlE,yEAAyE;IAClE,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO;CAIzC;AAED,qBAAa,mBAAmB;IAE9B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAQxC;;;;OAIG;WACW,mBAAmB,CAAC,uBAAuB,EAAE,aAAa,GAAG,QAAQ,EAAE,EAAE,gBAAgB,CAAC,EAAE,oBAAoB,GAAG,QAAQ,GAAG,SAAS;IAKrJ;;;;OAIG;WACW,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM;IACpD;;;;;;;;OAQG;WACW,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,EAAE,EAAE,eAAe,GAAE,OAAe,EACvG,YAAY,GAAE,oBAAyD,GAAG,iBAAiB,CAAC,QAAQ,CAAC;IAgBvG;;;;;;OAMG;WACW,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,EAAE,EAAE,8BAA8B,GAAE,OAAc,EAAE,4BAA4B,SAAI,GAAG,OAAO;IA+B9J;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAsBlC;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,8BAA8B;IAgB7C,0GAA0G;IAC1G,OAAO,CAAC,MAAM,CAAC,8BAA8B;IAM7C;;;;;OAKG;WACW,iDAAiD,CAAC,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,GAAG,SAAS,EAAE,UAAU,GAAE,YAAqC,GAAG,QAAQ,EAAE,EAAE;IAcxM;;;;;OAKG;WACW,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IA4B7F;;;;;;;;;;;OAWG;WACW,mCAAmC,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,yBAAyB,EAClI,YAAY,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI;IAoBzD;;;;;;;;;;;OAWG;WACW,mCAAmC,CAAC,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,GAAG,QAAQ,EAAE,EAAE;CAiBlH"}
1
+ {"version":3,"file":"HalfEdgeGraphSearch.d.ts","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSearch.ts"],"names":[],"mappings":"AAKA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACjH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAChC;AACD;GACG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,YAAY,CAAU;IAC9B;;;;OAIG;gBACgB,IAAI,EAAE,YAAY,EAAE,WAAW,GAAE,OAAc;IAIlE,yEAAyE;IAClE,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO;CAIzC;AAED,qBAAa,mBAAmB;IAE9B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAQxC;;;;OAIG;WACW,mBAAmB,CAAC,uBAAuB,EAAE,aAAa,GAAG,QAAQ,EAAE,EAAE,gBAAgB,CAAC,EAAE,oBAAoB,GAAG,QAAQ,GAAG,SAAS;IAKrJ;;;;OAIG;WACW,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM;IACpD;;;;;;;;OAQG;WACW,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,EAAE,EAAE,eAAe,GAAE,OAAe,EACvG,YAAY,GAAE,oBAAyE,GAAG,iBAAiB,CAAC,QAAQ,CAAC;IAgBvH;;;;;;OAMG;WACW,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,EAAE,EAAE,8BAA8B,GAAE,OAAc,EAAE,4BAA4B,SAAI,GAAG,OAAO;IA+B9J;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAsBlC;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,8BAA8B;IAgB7C,0GAA0G;IAC1G,OAAO,CAAC,MAAM,CAAC,8BAA8B;IAM7C;;;;;OAKG;WACW,iDAAiD,CAAC,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,GAAG,SAAS,EAAE,UAAU,GAAE,YAAqC,GAAG,QAAQ,EAAE,EAAE;IAcxM;;;;;OAKG;WACW,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IA4B7F;;;;;;;;;;;OAWG;WACW,mCAAmC,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,yBAAyB,EAClI,YAAY,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI;IAoBzD;;;;;;;;;;;OAWG;WACW,mCAAmC,CAAC,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,GAAG,QAAQ,EAAE,EAAE;CAiBlH"}
@@ -66,7 +66,7 @@ class HalfEdgeGraphSearch {
66
66
  * @param collectAllNodes flag to pass to the SignedDataSummary constructor to control collection of nodes.
67
67
  * @param areaFunction function to all to obtain area (or other numeric value)
68
68
  */
69
- static collectFaceAreaSummary(source, collectAllNodes = false, areaFunction = HalfEdgeGraphSearch.signedFaceArea) {
69
+ static collectFaceAreaSummary(source, collectAllNodes = false, areaFunction = (node) => HalfEdgeGraphSearch.signedFaceArea(node)) {
70
70
  const result = new SignedDataSummary_1.SignedDataSummary(collectAllNodes);
71
71
  let allFaces;
72
72
  if (source instanceof Graph_1.HalfEdgeGraph)
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgeGraphSearch.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSearch.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 { HalfEdge, HalfEdgeGraph, HalfEdgeMask, HalfEdgeToBooleanFunction, NodeToNumberFunction } from \"./Graph\";\r\nimport { SignedDataSummary } from \"./SignedDataSummary\";\r\nimport { XYParitySearchContext } from \"./XYParitySearchContext\";\r\n\r\n/**\r\n * Interface for an object that executes boolean tests on edges.\r\n */\r\nexport interface HalfEdgeTestObject {\r\n testEdge(h: HalfEdge): boolean;\r\n}\r\n/**\r\n */\r\nexport class HalfEdgeMaskTester {\r\n private _targetMask: HalfEdgeMask;\r\n private _targetValue: boolean;\r\n /**\r\n *\r\n * @param mask mask to test in `testEdge` function\r\n * @param targetValue value to match for true return\r\n */\r\n public constructor(mask: HalfEdgeMask, targetValue: boolean = true) {\r\n this._targetMask = mask;\r\n this._targetValue = targetValue;\r\n }\r\n /** Return true if the value of the targetMask matches the targetValue */\r\n public testEdge(edge: HalfEdge): boolean {\r\n return edge.isMaskSet(this._targetMask) === this._targetValue;\r\n }\r\n\r\n}\r\n// Search services for HalfEdgeGraph\r\nexport class HalfEdgeGraphSearch {\r\n\r\n /**\r\n * * for each node of face, set the mask push to allNodesStack\r\n * * push the faceSeed on onePerFaceStack[]\r\n */\r\n private static pushAndMaskAllNodesInFace(faceSeed: HalfEdge, mask: number, allNodeStack: HalfEdge[], onePerFaceStack: HalfEdge[]) {\r\n onePerFaceStack.push(faceSeed);\r\n faceSeed.collectAroundFace((node: HalfEdge) => {\r\n node.setMask(mask);\r\n allNodeStack.push(node);\r\n });\r\n }\r\n\r\n /**\r\n * Search an array of faceSeed nodes for the face with the most negative area.\r\n * @param oneCandidateNodePerFace array containing one node from each face to be considered.\r\n * @returns node on the minimum area face, or undefined if no such face (e.g., all faces have zero area).\r\n */\r\n public static findMinimumAreaFace(oneCandidateNodePerFace: HalfEdgeGraph | HalfEdge[], faceAreaFunction?: NodeToNumberFunction): HalfEdge | undefined {\r\n const summary = HalfEdgeGraphSearch.collectFaceAreaSummary(oneCandidateNodePerFace, false, faceAreaFunction);\r\n return summary.largestNegativeItem;\r\n }\r\n\r\n /**\r\n * static method for face area computation -- useful as function parameter in collect FaceAreaSummary.\r\n * * This simply calls `node.signedFaceArea ()`\r\n * @param node instance for signedFaceArea call.\r\n */\r\n public static signedFaceArea(node: HalfEdge): number { return node.signedFaceArea(); }\r\n /**\r\n *\r\n * Return a summary structure data about face (or other numeric quantity if the caller's areaFunction returns other value)\r\n * * The default areaFunction computes area of polygonal face.\r\n * * Callers with curved edge graphs must supply their own area function.\r\n * @param source graph or array of nodes to examine\r\n * @param collectAllNodes flag to pass to the SignedDataSummary constructor to control collection of nodes.\r\n * @param areaFunction function to all to obtain area (or other numeric value)\r\n */\r\n public static collectFaceAreaSummary(source: HalfEdgeGraph | HalfEdge[], collectAllNodes: boolean = false,\r\n areaFunction: NodeToNumberFunction = HalfEdgeGraphSearch.signedFaceArea): SignedDataSummary<HalfEdge> {\r\n const result = new SignedDataSummary<HalfEdge>(collectAllNodes);\r\n let allFaces: HalfEdge[];\r\n\r\n if (source instanceof HalfEdgeGraph)\r\n allFaces = source.collectFaceLoops();\r\n else\r\n allFaces = source;\r\n\r\n for (const node of allFaces) {\r\n const area = areaFunction(node);\r\n result.announceItem(node, area);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * * Test if the graph is triangulated.\r\n * * Return false if:\r\n * * Positive area face with more than 3 edges\r\n * * more than 1 negative area face with `allowMultipleNegativeAreaFaces` false\r\n * * 2-edge faces are ignored.\r\n */\r\n public static isTriangulatedCCW(source: HalfEdgeGraph | HalfEdge[], allowMultipleNegativeAreaFaces: boolean = true, numPositiveExceptionsAllowed = 0): boolean {\r\n let allFaces: HalfEdge[];\r\n\r\n if (source instanceof HalfEdgeGraph)\r\n allFaces = source.collectFaceLoops();\r\n else\r\n allFaces = source;\r\n let numNegative = 0;\r\n let numPositiveExceptions = 0;\r\n for (const node of allFaces) {\r\n const numEdges = node.countEdgesAroundFace();\r\n if (numEdges >= 3) {\r\n const area = node.signedFaceArea();\r\n if (area > 0) {\r\n if (numEdges > 3) {\r\n numPositiveExceptions++;\r\n if (numPositiveExceptions > numPositiveExceptionsAllowed)\r\n return false;\r\n }\r\n } else {\r\n numNegative++;\r\n if (numNegative > 1) {\r\n if (!allowMultipleNegativeAreaFaces)\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Search to all accessible faces from given seed.\r\n * * The returned array contains one representative node in each face of the connected component.\r\n * * If (nonnull) parity mask is given, on return:\r\n * * It is entirely set or entirely clear around each face\r\n * * It is entirely set on all faces that are an even number of face-to-face steps away from the seed.\r\n * * It is entirely clear on all faces that are an odd number of face-to-face steps away from the seed.\r\n * @param seedEdge first edge to search.\r\n * @param visitMask mask applied to all faces as visited.\r\n * @param parityMask mask to apply (a) to first face, (b) to faces with alternating parity during the search.\r\n */\r\n private static parityFloodFromSeed(seedEdge: HalfEdge, visitMask: HalfEdgeMask, parityEdgeTester: HalfEdgeTestObject | undefined, parityMask: HalfEdgeMask): HalfEdge[] {\r\n const faces: HalfEdge[] = [];\r\n if (seedEdge.isMaskSet(visitMask)) return faces; // empty\r\n\r\n const allMasks = parityMask | visitMask;\r\n const stack: HalfEdge[] = [];\r\n // arbitrarily call the seed face exterior ... others will alternate as visited.\r\n HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(seedEdge, allMasks, stack, faces); // Start with exterior as mask\r\n while (stack.length > 0) {\r\n const p = stack.pop()!;\r\n const mate = p.edgeMate;\r\n if (!mate)\r\n continue;\r\n if (!mate.isMaskSet(visitMask)) {\r\n let newState = p.isMaskSet(parityMask);\r\n if (!parityEdgeTester || parityEdgeTester.testEdge(p))\r\n newState = !newState;\r\n HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(mate, newState ? allMasks : visitMask, stack, faces);\r\n }\r\n }\r\n return faces;\r\n }\r\n /**\r\n * * Search the given faces for the one with the minimum area.\r\n * * If the mask in that face is OFF, toggle it on (all half edges of) all the faces.\r\n * * In a properly merged planar subdivision there should be only one true negative area face per component.\r\n * @param graph parent graph\r\n * @param parityMask mask which was previously set with alternating parity, but with an arbitrary start face.\r\n * @param faces array of faces to search.\r\n */\r\n private static correctParityInSingleComponent(_graph: HalfEdgeGraph, mask: HalfEdgeMask, faces: HalfEdge[]) {\r\n const exteriorHalfEdge = HalfEdgeGraphSearch.findMinimumAreaFace(faces);\r\n if (!exteriorHalfEdge) {\r\n } else if (exteriorHalfEdge.isMaskSet(mask)) {\r\n // all should be well .. nothing to do.\r\n } else {\r\n // TOGGLE around the face (assuming all are consistent with the seed)\r\n for (const faceSeed of faces) {\r\n if (faceSeed.isMaskSet(mask)) {\r\n faceSeed.clearMaskAroundFace(mask);\r\n } else {\r\n faceSeed.setMaskAroundFace(mask);\r\n }\r\n }\r\n }\r\n }\r\n /** Apply correctParityInSingleComponent to each array in components. (Quick exit if mask in NULL_MASK) */\r\n private static correctParityInComponentArrays(graph: HalfEdgeGraph, mask: HalfEdgeMask, components: HalfEdge[][]) {\r\n if (mask === HalfEdgeMask.NULL_MASK)\r\n return;\r\n for (const facesInComponent of components)\r\n HalfEdgeGraphSearch.correctParityInSingleComponent(graph, mask, facesInComponent);\r\n }\r\n /**\r\n * Collect arrays gathering faces by connected component.\r\n * @param graph graph to inspect\r\n * @param parityEdgeTester (optional) function to test if an edge is a parity change (e.g., a boundary edge).\r\n * @param parityMask (optional, along with parityEdgeTester) mask to apply indicating parity. If this is Mask.NULL_MASK, there is no record of parity.\r\n */\r\n public static collectConnectedComponentsWithExteriorParityMasks(graph: HalfEdgeGraph, parityEdgeTester: HalfEdgeTestObject | undefined, parityMask: HalfEdgeMask = HalfEdgeMask.NULL_MASK): HalfEdge[][] {\r\n const components = [];\r\n const visitMask = HalfEdgeMask.VISITED;\r\n const allMasks = parityMask | visitMask;\r\n graph.clearMask(allMasks);\r\n for (const faceSeed of graph.allHalfEdges) {\r\n if (!faceSeed.isMaskSet(HalfEdgeMask.VISITED)) {\r\n const newFaces = HalfEdgeGraphSearch.parityFloodFromSeed(faceSeed, visitMask, parityEdgeTester, parityMask);\r\n components.push(newFaces);\r\n }\r\n }\r\n HalfEdgeGraphSearch.correctParityInComponentArrays(graph, parityMask, components);\r\n return components;\r\n }\r\n /**\r\n * Test if (x,y) is inside (1), on an edge (0) or outside (-1) a face.\r\n * @param seedNode any node on the face loop\r\n * @param x x coordinate of test point.\r\n * @param y y coordinate of test point.\r\n */\r\n public static pointInOrOnFaceXY(seedNode: HalfEdge, x: number, y: number): number | undefined {\r\n const context = new XYParitySearchContext(x, y);\r\n // walk around looking for an accepted node to start the search (seedNode is usually ok!)\r\n let nodeA = seedNode;\r\n let nodeB = seedNode.faceSuccessor;\r\n for (; ; nodeA = nodeB) {\r\n if (context.tryStartEdge(nodeA.x, nodeA.y, nodeB.x, nodeB.y))\r\n break;\r\n if (nodeB === seedNode) {\r\n // umm.. the face is all on the x axis?\r\n return context.classifyCounts();\r\n }\r\n nodeB = nodeA.faceSuccessor;\r\n }\r\n\r\n // nodeB is the real start node for search ... emit ends of each edge around the face,\r\n // stopping after emitting nodeB as an edge end.\r\n let node = nodeB.faceSuccessor;\r\n for (; ;) {\r\n if (!context.advance(node.x, node.y)) {\r\n return context.classifyCounts();\r\n }\r\n if (node === nodeB)\r\n break;\r\n node = node.faceSuccessor;\r\n }\r\n return context.classifyCounts();\r\n }\r\n /**\r\n * Announce nodes that are \"extended face boundary\" by conditions (usually mask of node and mate) in test functions.\r\n * * After each node, the next candidate in reached by looking \"around the head vertex loop\" for the next boundary.\r\n * * \"Around the vertex\" from nodeA means\r\n * * First look at nodeA.faceSuccessor;\r\n * * Then look at vertexPredecessor around that vertex loop.\r\n * * Each accepted node is passed to announceNode, and marked with the visit mask.\r\n * * The counter of the announceEdge function is zero for the first edge, then increases with each edge.\r\n * @param seed start node.\r\n * @param isBoundaryEdge\r\n * @param announceEdge\r\n */\r\n public static collectExtendedBoundaryLoopFromSeed(seed: HalfEdge, visitMask: HalfEdgeMask, isBoundaryEdge: HalfEdgeToBooleanFunction,\r\n announceEdge: (edge: HalfEdge, counter: number) => void) {\r\n let counter = 0;\r\n while (!seed.getMask(visitMask) && isBoundaryEdge(seed)) {\r\n announceEdge(seed, counter++);\r\n seed.setMask(visitMask);\r\n const vertexBase = seed.faceSuccessor;\r\n let candidateAroundVertex = vertexBase;\r\n for (; ;) {\r\n if (candidateAroundVertex.getMask(visitMask))\r\n return;\r\n if (isBoundaryEdge(candidateAroundVertex)) {\r\n seed = candidateAroundVertex;\r\n break;\r\n }\r\n candidateAroundVertex = candidateAroundVertex.vertexPredecessor;\r\n if (candidateAroundVertex === vertexBase)\r\n break;\r\n }\r\n }\r\n }\r\n /**\r\n * Collect arrays of nodes \"around the boundary\" of a graph with extraneous (non-boundary) edges.\r\n * * The \"boundary\" is nodes that do NOT have the exterior mask, but whose mates DO have the exterior mask.\r\n * * After each node, the next candidate in reached by looking \"around the head vertex loop\" for the next boundary.\r\n * * \"Around the vertex\" from nodeA means\r\n * * First look at nodeA.faceSuccessor;\r\n * * Then look at vertexPredecessor around that vertex loop.\r\n * * Each accepted node is passed to announceNode, and marked with the visit mask.\r\n * @param seed start node.\r\n * @param isBoundaryNode\r\n * @param announceNode\r\n */\r\n public static collectExtendedBoundaryLoopsInGraph(graph: HalfEdgeGraph, exteriorMask: HalfEdgeMask): HalfEdge[][] {\r\n const loops: HalfEdge[][] = [];\r\n const visitMask = graph.grabMask(true);\r\n const isBoundaryEdge = (edge: HalfEdge): boolean => {\r\n return edge.getMask(exteriorMask) === 0 && edge.edgeMate.getMask(exteriorMask) !== 0;\r\n };\r\n const announceEdgeInBoundary = (edge: HalfEdge, counter: number) => {\r\n if (counter === 0)\r\n loops.push([]);\r\n loops[loops.length - 1].push(edge);\r\n };\r\n for (const seed of graph.allHalfEdges) {\r\n this.collectExtendedBoundaryLoopFromSeed(seed, visitMask, isBoundaryEdge, announceEdgeInBoundary);\r\n }\r\n graph.dropMask(visitMask);\r\n return loops;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"HalfEdgeGraphSearch.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSearch.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 { HalfEdge, HalfEdgeGraph, HalfEdgeMask, HalfEdgeToBooleanFunction, NodeToNumberFunction } from \"./Graph\";\r\nimport { SignedDataSummary } from \"./SignedDataSummary\";\r\nimport { XYParitySearchContext } from \"./XYParitySearchContext\";\r\n\r\n/**\r\n * Interface for an object that executes boolean tests on edges.\r\n */\r\nexport interface HalfEdgeTestObject {\r\n testEdge(h: HalfEdge): boolean;\r\n}\r\n/**\r\n */\r\nexport class HalfEdgeMaskTester {\r\n private _targetMask: HalfEdgeMask;\r\n private _targetValue: boolean;\r\n /**\r\n *\r\n * @param mask mask to test in `testEdge` function\r\n * @param targetValue value to match for true return\r\n */\r\n public constructor(mask: HalfEdgeMask, targetValue: boolean = true) {\r\n this._targetMask = mask;\r\n this._targetValue = targetValue;\r\n }\r\n /** Return true if the value of the targetMask matches the targetValue */\r\n public testEdge(edge: HalfEdge): boolean {\r\n return edge.isMaskSet(this._targetMask) === this._targetValue;\r\n }\r\n\r\n}\r\n// Search services for HalfEdgeGraph\r\nexport class HalfEdgeGraphSearch {\r\n\r\n /**\r\n * * for each node of face, set the mask push to allNodesStack\r\n * * push the faceSeed on onePerFaceStack[]\r\n */\r\n private static pushAndMaskAllNodesInFace(faceSeed: HalfEdge, mask: number, allNodeStack: HalfEdge[], onePerFaceStack: HalfEdge[]) {\r\n onePerFaceStack.push(faceSeed);\r\n faceSeed.collectAroundFace((node: HalfEdge) => {\r\n node.setMask(mask);\r\n allNodeStack.push(node);\r\n });\r\n }\r\n\r\n /**\r\n * Search an array of faceSeed nodes for the face with the most negative area.\r\n * @param oneCandidateNodePerFace array containing one node from each face to be considered.\r\n * @returns node on the minimum area face, or undefined if no such face (e.g., all faces have zero area).\r\n */\r\n public static findMinimumAreaFace(oneCandidateNodePerFace: HalfEdgeGraph | HalfEdge[], faceAreaFunction?: NodeToNumberFunction): HalfEdge | undefined {\r\n const summary = HalfEdgeGraphSearch.collectFaceAreaSummary(oneCandidateNodePerFace, false, faceAreaFunction);\r\n return summary.largestNegativeItem;\r\n }\r\n\r\n /**\r\n * static method for face area computation -- useful as function parameter in collect FaceAreaSummary.\r\n * * This simply calls `node.signedFaceArea ()`\r\n * @param node instance for signedFaceArea call.\r\n */\r\n public static signedFaceArea(node: HalfEdge): number { return node.signedFaceArea(); }\r\n /**\r\n *\r\n * Return a summary structure data about face (or other numeric quantity if the caller's areaFunction returns other value)\r\n * * The default areaFunction computes area of polygonal face.\r\n * * Callers with curved edge graphs must supply their own area function.\r\n * @param source graph or array of nodes to examine\r\n * @param collectAllNodes flag to pass to the SignedDataSummary constructor to control collection of nodes.\r\n * @param areaFunction function to all to obtain area (or other numeric value)\r\n */\r\n public static collectFaceAreaSummary(source: HalfEdgeGraph | HalfEdge[], collectAllNodes: boolean = false,\r\n areaFunction: NodeToNumberFunction = (node) => HalfEdgeGraphSearch.signedFaceArea(node)): SignedDataSummary<HalfEdge> {\r\n const result = new SignedDataSummary<HalfEdge>(collectAllNodes);\r\n let allFaces: HalfEdge[];\r\n\r\n if (source instanceof HalfEdgeGraph)\r\n allFaces = source.collectFaceLoops();\r\n else\r\n allFaces = source;\r\n\r\n for (const node of allFaces) {\r\n const area = areaFunction(node);\r\n result.announceItem(node, area);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * * Test if the graph is triangulated.\r\n * * Return false if:\r\n * * Positive area face with more than 3 edges\r\n * * more than 1 negative area face with `allowMultipleNegativeAreaFaces` false\r\n * * 2-edge faces are ignored.\r\n */\r\n public static isTriangulatedCCW(source: HalfEdgeGraph | HalfEdge[], allowMultipleNegativeAreaFaces: boolean = true, numPositiveExceptionsAllowed = 0): boolean {\r\n let allFaces: HalfEdge[];\r\n\r\n if (source instanceof HalfEdgeGraph)\r\n allFaces = source.collectFaceLoops();\r\n else\r\n allFaces = source;\r\n let numNegative = 0;\r\n let numPositiveExceptions = 0;\r\n for (const node of allFaces) {\r\n const numEdges = node.countEdgesAroundFace();\r\n if (numEdges >= 3) {\r\n const area = node.signedFaceArea();\r\n if (area > 0) {\r\n if (numEdges > 3) {\r\n numPositiveExceptions++;\r\n if (numPositiveExceptions > numPositiveExceptionsAllowed)\r\n return false;\r\n }\r\n } else {\r\n numNegative++;\r\n if (numNegative > 1) {\r\n if (!allowMultipleNegativeAreaFaces)\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Search to all accessible faces from given seed.\r\n * * The returned array contains one representative node in each face of the connected component.\r\n * * If (nonnull) parity mask is given, on return:\r\n * * It is entirely set or entirely clear around each face\r\n * * It is entirely set on all faces that are an even number of face-to-face steps away from the seed.\r\n * * It is entirely clear on all faces that are an odd number of face-to-face steps away from the seed.\r\n * @param seedEdge first edge to search.\r\n * @param visitMask mask applied to all faces as visited.\r\n * @param parityMask mask to apply (a) to first face, (b) to faces with alternating parity during the search.\r\n */\r\n private static parityFloodFromSeed(seedEdge: HalfEdge, visitMask: HalfEdgeMask, parityEdgeTester: HalfEdgeTestObject | undefined, parityMask: HalfEdgeMask): HalfEdge[] {\r\n const faces: HalfEdge[] = [];\r\n if (seedEdge.isMaskSet(visitMask)) return faces; // empty\r\n\r\n const allMasks = parityMask | visitMask;\r\n const stack: HalfEdge[] = [];\r\n // arbitrarily call the seed face exterior ... others will alternate as visited.\r\n HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(seedEdge, allMasks, stack, faces); // Start with exterior as mask\r\n while (stack.length > 0) {\r\n const p = stack.pop()!;\r\n const mate = p.edgeMate;\r\n if (!mate)\r\n continue;\r\n if (!mate.isMaskSet(visitMask)) {\r\n let newState = p.isMaskSet(parityMask);\r\n if (!parityEdgeTester || parityEdgeTester.testEdge(p))\r\n newState = !newState;\r\n HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(mate, newState ? allMasks : visitMask, stack, faces);\r\n }\r\n }\r\n return faces;\r\n }\r\n /**\r\n * * Search the given faces for the one with the minimum area.\r\n * * If the mask in that face is OFF, toggle it on (all half edges of) all the faces.\r\n * * In a properly merged planar subdivision there should be only one true negative area face per component.\r\n * @param graph parent graph\r\n * @param parityMask mask which was previously set with alternating parity, but with an arbitrary start face.\r\n * @param faces array of faces to search.\r\n */\r\n private static correctParityInSingleComponent(_graph: HalfEdgeGraph, mask: HalfEdgeMask, faces: HalfEdge[]) {\r\n const exteriorHalfEdge = HalfEdgeGraphSearch.findMinimumAreaFace(faces);\r\n if (!exteriorHalfEdge) {\r\n } else if (exteriorHalfEdge.isMaskSet(mask)) {\r\n // all should be well .. nothing to do.\r\n } else {\r\n // TOGGLE around the face (assuming all are consistent with the seed)\r\n for (const faceSeed of faces) {\r\n if (faceSeed.isMaskSet(mask)) {\r\n faceSeed.clearMaskAroundFace(mask);\r\n } else {\r\n faceSeed.setMaskAroundFace(mask);\r\n }\r\n }\r\n }\r\n }\r\n /** Apply correctParityInSingleComponent to each array in components. (Quick exit if mask in NULL_MASK) */\r\n private static correctParityInComponentArrays(graph: HalfEdgeGraph, mask: HalfEdgeMask, components: HalfEdge[][]) {\r\n if (mask === HalfEdgeMask.NULL_MASK)\r\n return;\r\n for (const facesInComponent of components)\r\n HalfEdgeGraphSearch.correctParityInSingleComponent(graph, mask, facesInComponent);\r\n }\r\n /**\r\n * Collect arrays gathering faces by connected component.\r\n * @param graph graph to inspect\r\n * @param parityEdgeTester (optional) function to test if an edge is a parity change (e.g., a boundary edge).\r\n * @param parityMask (optional, along with parityEdgeTester) mask to apply indicating parity. If this is Mask.NULL_MASK, there is no record of parity.\r\n */\r\n public static collectConnectedComponentsWithExteriorParityMasks(graph: HalfEdgeGraph, parityEdgeTester: HalfEdgeTestObject | undefined, parityMask: HalfEdgeMask = HalfEdgeMask.NULL_MASK): HalfEdge[][] {\r\n const components = [];\r\n const visitMask = HalfEdgeMask.VISITED;\r\n const allMasks = parityMask | visitMask;\r\n graph.clearMask(allMasks);\r\n for (const faceSeed of graph.allHalfEdges) {\r\n if (!faceSeed.isMaskSet(HalfEdgeMask.VISITED)) {\r\n const newFaces = HalfEdgeGraphSearch.parityFloodFromSeed(faceSeed, visitMask, parityEdgeTester, parityMask);\r\n components.push(newFaces);\r\n }\r\n }\r\n HalfEdgeGraphSearch.correctParityInComponentArrays(graph, parityMask, components);\r\n return components;\r\n }\r\n /**\r\n * Test if (x,y) is inside (1), on an edge (0) or outside (-1) a face.\r\n * @param seedNode any node on the face loop\r\n * @param x x coordinate of test point.\r\n * @param y y coordinate of test point.\r\n */\r\n public static pointInOrOnFaceXY(seedNode: HalfEdge, x: number, y: number): number | undefined {\r\n const context = new XYParitySearchContext(x, y);\r\n // walk around looking for an accepted node to start the search (seedNode is usually ok!)\r\n let nodeA = seedNode;\r\n let nodeB = seedNode.faceSuccessor;\r\n for (; ; nodeA = nodeB) {\r\n if (context.tryStartEdge(nodeA.x, nodeA.y, nodeB.x, nodeB.y))\r\n break;\r\n if (nodeB === seedNode) {\r\n // umm.. the face is all on the x axis?\r\n return context.classifyCounts();\r\n }\r\n nodeB = nodeA.faceSuccessor;\r\n }\r\n\r\n // nodeB is the real start node for search ... emit ends of each edge around the face,\r\n // stopping after emitting nodeB as an edge end.\r\n let node = nodeB.faceSuccessor;\r\n for (; ;) {\r\n if (!context.advance(node.x, node.y)) {\r\n return context.classifyCounts();\r\n }\r\n if (node === nodeB)\r\n break;\r\n node = node.faceSuccessor;\r\n }\r\n return context.classifyCounts();\r\n }\r\n /**\r\n * Announce nodes that are \"extended face boundary\" by conditions (usually mask of node and mate) in test functions.\r\n * * After each node, the next candidate in reached by looking \"around the head vertex loop\" for the next boundary.\r\n * * \"Around the vertex\" from nodeA means\r\n * * First look at nodeA.faceSuccessor;\r\n * * Then look at vertexPredecessor around that vertex loop.\r\n * * Each accepted node is passed to announceNode, and marked with the visit mask.\r\n * * The counter of the announceEdge function is zero for the first edge, then increases with each edge.\r\n * @param seed start node.\r\n * @param isBoundaryEdge\r\n * @param announceEdge\r\n */\r\n public static collectExtendedBoundaryLoopFromSeed(seed: HalfEdge, visitMask: HalfEdgeMask, isBoundaryEdge: HalfEdgeToBooleanFunction,\r\n announceEdge: (edge: HalfEdge, counter: number) => void) {\r\n let counter = 0;\r\n while (!seed.getMask(visitMask) && isBoundaryEdge(seed)) {\r\n announceEdge(seed, counter++);\r\n seed.setMask(visitMask);\r\n const vertexBase = seed.faceSuccessor;\r\n let candidateAroundVertex = vertexBase;\r\n for (; ;) {\r\n if (candidateAroundVertex.getMask(visitMask))\r\n return;\r\n if (isBoundaryEdge(candidateAroundVertex)) {\r\n seed = candidateAroundVertex;\r\n break;\r\n }\r\n candidateAroundVertex = candidateAroundVertex.vertexPredecessor;\r\n if (candidateAroundVertex === vertexBase)\r\n break;\r\n }\r\n }\r\n }\r\n /**\r\n * Collect arrays of nodes \"around the boundary\" of a graph with extraneous (non-boundary) edges.\r\n * * The \"boundary\" is nodes that do NOT have the exterior mask, but whose mates DO have the exterior mask.\r\n * * After each node, the next candidate in reached by looking \"around the head vertex loop\" for the next boundary.\r\n * * \"Around the vertex\" from nodeA means\r\n * * First look at nodeA.faceSuccessor;\r\n * * Then look at vertexPredecessor around that vertex loop.\r\n * * Each accepted node is passed to announceNode, and marked with the visit mask.\r\n * @param seed start node.\r\n * @param isBoundaryNode\r\n * @param announceNode\r\n */\r\n public static collectExtendedBoundaryLoopsInGraph(graph: HalfEdgeGraph, exteriorMask: HalfEdgeMask): HalfEdge[][] {\r\n const loops: HalfEdge[][] = [];\r\n const visitMask = graph.grabMask(true);\r\n const isBoundaryEdge = (edge: HalfEdge): boolean => {\r\n return edge.getMask(exteriorMask) === 0 && edge.edgeMate.getMask(exteriorMask) !== 0;\r\n };\r\n const announceEdgeInBoundary = (edge: HalfEdge, counter: number) => {\r\n if (counter === 0)\r\n loops.push([]);\r\n loops[loops.length - 1].push(edge);\r\n };\r\n for (const seed of graph.allHalfEdges) {\r\n this.collectExtendedBoundaryLoopFromSeed(seed, visitMask, isBoundaryEdge, announceEdgeInBoundary);\r\n }\r\n graph.dropMask(visitMask);\r\n return loops;\r\n }\r\n}\r\n"]}
@@ -211,7 +211,7 @@ class HalfEdgeGraphSpineContext {
211
211
  if (b > minA)
212
212
  candidates.push(new NodeSortKey(node, b));
213
213
  }
214
- candidates.sort(NodeSortKey.compareForSort);
214
+ candidates.sort((dataA, dataB) => NodeSortKey.compareForSort(dataA, dataB));
215
215
  let key;
216
216
  while (undefined !== (key = candidates.pop())) {
217
217
  const pA = key.node;
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgeGraphSpineContext.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSpineContext.ts"],"names":[],"mappings":";;;AAAA;;;+FAG+F;AAC/F;;GAEG;AACH,0CAAuC;AACvC,mCAAgE;AAChE,mEAAkE;AAClE,uCAA+C;AAC/C,mDAA+C;AAC/C,qDAAyD;AACzD,+DAAgF;AAChF,+CAA4C;AAC5C,iBAAiB;AACjB,+BAA+B;AAC/B,iCAAiC;AACjC,qCAAqC;AAErC,SAAS,aAAa,CAAC,CAAS;IAC9B,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QACxB,MAAM,CAAC,IAAI,CAAC,yBAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,SAAS,cAAc,CAAC,CAAS;IAC/B,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QACxB,MAAM,CAAC,IAAI,CAAC,0BAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,8EAA8E;AAC9E,MAAM,WAAW;IAGf,IAAW,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAExC,YAAmB,IAAc,EAAE,CAAS;QAC1C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IACd,CAAC;IACM,MAAM,CAAC,cAAc,CAAC,KAAkB,EAAE,KAAkB,IAAY,OAAO,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;CAC7G;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAa,yBAAyB;IAMpC,IAAW,KAAK,KAAK,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/C;;;OAGG;IACH;QACE,IAAI,CAAC,WAAW,GAAG,IAAI,qBAAa,EAAE,CAAC;QACvC,iEAAiE;QACjE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;QACjD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;IAC9C,CAAC;IAED;;OAEG;IACI,QAAQ;QACb,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9C,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;IAClC,CAAC;IAED,kEAAkE;IAC1D,OAAO,CAAC,MAAmB,EAAE,IAAa,EAAE,IAAa;QAC/D,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC;IAEO,aAAa,CAAC,YAAsB,EAC1C,KAAiB,EACjB,MAAiB;QACjB,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC;QAC3C,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACjB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC;eAChD,YAAY,CAAC,oBAAoB,EAAE,KAAK,CAAC;eACzC,YAAY,CAAC,oBAAoB,EAAE,KAAK,CAAC,EAAE;YAC9C,MAAM,KAAK,GAAG,YAAY,CAAC,aAAa,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAChC,MAAM,KAAK,GAAG,YAAY,CAAC,aAAa,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBACxB,MAAM,CAAC,IAAI,CAAC,yBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC;SACb;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,iCAAiC;IACjC,oEAAoE;IACpE,gCAAgC;IACxB,eAAe,CAAC,aAAuB;QAE7C,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE;YACpD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAE1C,MAAM,QAAQ,GAAG,0BAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,0BAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,0BAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,0BAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAErD,MAAM,YAAY,GAAG,0BAAQ,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC3D,MAAM,YAAY,GAAG,0BAAQ,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC3D,YAAY,CAAC,CAAC,GAAG,GAAG,CAAC;YACrB,YAAY,CAAC,CAAC,GAAG,GAAG,CAAC;YACrB,MAAM,OAAO,GAAG,YAAY,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACxE,MAAM,OAAO,GAAG,YAAY,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACxE,MAAM,OAAO,GAAG,YAAY,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACxE,MAAM,OAAO,GAAG,YAAY,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YAExE,MAAM,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YACpD,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YACnD,OAAO,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;SACpC;QAED,OAAO,MAAM,CAAC,iBAAiB,CAAC;IAClC,CAAC;IAED,uCAAuC;IACvC,4FAA4F;IACpF,2BAA2B,CAAC,IAAe;QAEjD,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAK,0BAA0B;QAC/D,MAAM,iBAAiB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAG,sEAAsE;QACpH,mBAAmB;QACnB,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,yBAAO,CAAC,MAAM,EAAE,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9B,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC7B;QACD,QAAQ,CAAC,YAAY,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QAEjC,qBAAqB;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1B,UAAU,CAAC,CAAC,CAAC,GAAG,0BAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAI,iBAAiB;YACjF,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;SACnC;QAED,mDAAmD;QACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;SAChE;QAED,iBAAiB,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;QAEhC,IAAI,SAAS,GAAG,MAAM,CAAC,iBAAiB,CAAC;QACzC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;QACnB,MAAM,KAAK,GAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAClC,IAAI,QAAQ,CAAC;QACb,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAClC,iEAAiE;YACjE,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC;YACpC,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;gBAClC,MAAM,cAAc,GAAG,0BAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;gBAChF,KAAK,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC;gBAC1E,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ;oBACrB,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;aACvB;YACD,IAAI,QAAQ,GAAG,SAAS,EAAE;gBACxB,SAAS,GAAG,QAAQ,CAAC;gBACrB,SAAS,GAAG,CAAC,CAAC;aACf;SACF;QACD,OAAO,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAEO,OAAO,CAAC,EAAY;QAE1B,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC;QACvB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC/B,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC/B,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAEO,sBAAsB,CAAC,IAAY;QAEzC,MAAM,UAAU,GAAkB,EAAE,CAAC;QACrC,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE;YAChD,MAAM,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,CAAC,GAAG,IAAI;gBACV,UAAU,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;SAC7C;QAED,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAE5C,IAAI,GAAG,CAAC;QACR,OAAO,SAAS,KAAK,CAAC,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE;YAC7C,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;YACpB,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC;YACvB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;mBACzB,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAC/B,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACjB,WAAW,EAAE,CAAC;aACf;SACF;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,gEAAgE;IACxD,OAAO,CAAC,IAAa,EAAE,IAAa,EAAE,IAAa,EAAE,IAAa,EAAE,QAAgB;QAE1F,MAAM,QAAQ,GAAG,0BAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,0BAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,0BAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;QACtD,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;QACtD,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IACxE,CAAC;IAED,iDAAiD;IACjD,gDAAgD;IAChD,uCAAuC;IACvC,0DAA0D;IAC1D,0CAA0C;IAC1C,oCAAoC;IAC5B,6BAA6B,CAAC,eAAuB,EAAE,mBAA2B;QAExF,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE;YAC9C,MAAM,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC;YAC5B,MAAM,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC;YAC5B,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,oBAAY,CAAC,QAAQ,CAAC;mBACjC,CAAC,EAAE,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC,CAAG,4BAA4B;mBACtE,CAAC,EAAE,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC,CAAG,4BAA4B;mBACtE,EAAE,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC;mBACtC,EAAE,CAAC,aAAa,KAAK,EAAE,EAC1B;gBACA,MAAM,QAAQ,GAAG,EAAE,CAAC,oBAAoB,EAAE,CAAC;gBAC3C,MAAM,QAAQ,GAAG,EAAE,CAAC,oBAAoB,EAAE,CAAC;gBAC3C,MAAM,QAAQ,GAAG,EAAE,CAAC,oBAAoB,EAAE,CAAC;gBAC3C,MAAM,gBAAgB,GAAG,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;gBACtE,uDAAuD;gBACvD,IAAI,gBAAgB,GAAG,mBAAmB,EAAE,EAAE,wCAAwC;oBACpF,MAAM,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;oBACzC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;oBAC1C,MAAM,CAAC,GAAG,mBAAQ,CAAC,yBAAyB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;oBACrD,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,GAAG,EAAE;wBACzC,MAAM,IAAI,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;wBAC7B,MAAM,IAAI,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;wBAC7B,MAAM,IAAI,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;wBAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;wBACvC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,EAAE;4BACzD,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;4BACvD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,0BAA0B,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;4BACtE,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;4BACnB,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;4BAC9C,MAAM,EAAE,CAAC;yBACV;qBACF;iBACF;aACF;SACF;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,mBAAmB,CACzB,KAAe,EACf,MAAmB,EACnB,gBAAyB;IACzB,oEAAoE;IACpE,aAAsB;IACtB,iFAAiF;IACjF,oBAA6B;QAE7B,IAAI,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC;YACpC,OAAO,KAAK,CAAC;QACf,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAClC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;QAC5B,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QAC7C,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QAC7C,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QAC7C,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAc,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,yBAAO,CAAC,MAAM,EAAE,CAAC;QAClC,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAClC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC,CAAC;YACpE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC;gBAC9C,SAAS,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC;;gBAE7B,SAAS,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC;YAC/B,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;YAC/B,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACpB,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC7B;QACD,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAClC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAClD,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;SAC/B;QAED,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,WAAW,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,EAAE;YAC1C,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE;gBAC1C,IAAI,gBAAgB;oBAClB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;SAC5D;aAAM,IAAI,WAAW,KAAK,CAAC,EAAE;YAC5B,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE;gBAC1C,IAAI,aAAa;oBACf,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;SACjD;aAAM,IAAI,WAAW,KAAK,CAAC,EAAE;YAC5B,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;gBACrC,2CAA2C;gBAC3C,IAAI,gBAAgB;oBAClB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACxE;iBAAM;gBACL,yFAAyF;gBACzF,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;oBAChC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,oBAAoB,CAAC;2BACvC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC;wBACxC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;aACjD;SACF;aAAM,IAAI,WAAW,KAAK,CAAC,EAAE;YAC5B,IAAI,gBAAgB;gBAClB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YACzD,IAAI,aAAa;gBACf,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC9D;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,uBAAuB,CAC7B,KAAe,EAAE,MAAmB,EACpC,gBAAyB,EACzB,aAAsB;QAEtB,IAAI,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC;YACpC,OAAO,KAAK,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,WAAW,GAAG,yBAAO,CAAC,UAAU,EAAE,CAAC;QACzC,MAAM,UAAU,GAAc,EAAE,CAAC;QACjC,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC;QACtB,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC;QACtB,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,GAAG;YACD,GAAG,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,UAAU,EAAE,CAAC;YAClC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/B,UAAU,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;YACtB,IAAI,WAAW,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC,EAAE;gBACnD,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBACrB,WAAW,EAAE,CAAC;gBACd,YAAY,GAAG,CAAC,CAAC;aAClB;iBAAM;gBACL,YAAY,GAAG,CAAC,CAAC;aAClB;YACD,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACpB,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YAClC,CAAC,EAAE,CAAC;SACL,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAC,aAAa,CAAC,KAAK,KAAK,EAAE;QAE9D,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAClC,WAAW,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACrD,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;SACrC;QAED,WAAW,CAAC,YAAY,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QAEpC,IAAI,WAAW,KAAK,CAAC,EAAE;YACrB,kBAAkB;YAClB,MAAM,WAAW,GAAG,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;YAC1D,IAAI,gBAAgB,EAAE;gBACpB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;gBAClD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;gBAClD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;aACnD;SACF;aAAM,IAAI,WAAW,KAAK,CAAC,EAAE;YAC5B,IAAI,gBAAgB;gBAClB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,YAAY,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC;SACtF;aAAM,IAAI,WAAW,KAAK,CAAC,EAAE;YAC5B,IAAI,aAAa,IAAI,YAAY,IAAI,CAAC;gBACpC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC;SAC1E;aAAM,IAAI,WAAW,KAAK,CAAC,EAAE;YAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;YAC1D,IAAI,aAAa,EAAE;gBACjB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;gBAClD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;gBAClD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;aACnD;SACF;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,WAAW,CAAC,KAAgB,EAAE,OAAgB;QACnD,IAAI,UAAU,EAAE,OAAO,CAAC;QACxB,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAC7C,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACpC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC;YAClC,KAAK,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC,CAAC;YAC1C,KAAK,CAAC,OAAO,CAAC,oBAAY,CAAC,aAAa,CAAC,CAAC;YAC1C,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC5B,OAAO,GAAG,KAAK,CAAC;aACjB;iBAAM;gBACL,gBAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;aACnC;YACD,UAAU,GAAG,KAAK,CAAC;SACpB;QACD,IAAI,OAAO,IAAI,OAAO,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS;YAC9D,gBAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IACD;;;;OAIG;IACK,cAAc,CAAC,YAA0B;QAC/C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE;YACjD,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC;YAClC,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC;YAClC,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE;gBACtC,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;oBAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC;oBAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC;oBAC7B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;wBAChE,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;wBAC9B,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;qBAC/B;iBACF;aACF;SACF;IACH,CAAC;IAGD;;;;OAIG;IACI,mBAAmB,CAAC,cAAuB,IAAI,EAAE,kBAA0B,GAAG;QAEnF,MAAM,SAAS,GAAG,EAAE,CAAC;QACrB,MAAM,oBAAoB,GAAG,GAAG,CAAC;QACjC,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,4BAAkB,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,4BAAkB,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEtD,MAAM,QAAQ,GAAG,IAAI,sCAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvD,QAAQ,CAAC,eAAe,CAAC,yBAAyB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACxE,MAAM,QAAQ,GAAG,IAAI,sCAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvD,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE,yBAAyB,CAAC,YAAY,CAAC,CAAC;QACxE,IAAI,WAAW,EAAE;YACf,yCAAmB,CAAC,iDAAiD,CAAC,IAAI,CAAC,KAAK,EAC9E,IAAI,wCAAkB,CAAC,oBAAY,CAAC,aAAa,CAAC,EAAE,oBAAY,CAAC,QAAQ,CAAC,CAAC;YAC7E,IAAI,CAAC,cAAc,CAAC,oBAAY,CAAC,QAAQ,CAAC,CAAC;SAC5C;QAED,4BAAY,CAAC,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzD,4BAAY,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEvC,OAAO,QAAQ,EAAE,GAAG,SAAS,EAAE;YAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,6BAA6B,CAAC,eAAe,EAAE,oBAAoB,CAAC,CAAC;YAC1F,IAAI,OAAO,IAAI,CAAC;gBACd,MAAM;YACR,4BAAY,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACxC;IACH,CAAC;IAED,0BAA0B;IAC1B,qDAAqD;IACrD,sDAAsD;IACtD,gDAAgD;IAChD;;;;;;OAMG;IACI,aAAa,CAAC,mBAA4B,IAAI,EAAE,gBAAyB,IAAI,EAAE,uBAAgC,IAAI;QACxH,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAChC,CAAC,MAAqB,EAAE,QAAkB,EAAE,EAAE;YAC5C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAY,CAAC,QAAQ,CAAC,EAAE;gBAC5C,IAAI,IAAI,CAAC,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAE;iBACpF;qBAAM,IAAI,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,CAAC,EAAE;iBAC7G;aACF;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;QACL,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;OAWG;IACI,2BAA2B,CAAC,gBAAyB,EAAE,WAAkB,aAAK,CAAC,aAAa,CAAC,EAAE,CAAC;QAErG,MAAM,WAAW,GAAG,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClE,IAAI,gBAAgB,IAAI,WAAW,GAAG,CAAC,EAAE;YACvC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAC3B,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;SACzD;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;;AAjFc,sCAAY,GAAG,IAAI,CAAC;AACpB,sCAAY,GAAG,KAAK,CAAC;AAlazB,8DAAyB","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/** @packageDocumentation\r\n * @module Topology\r\n */\r\nimport { Geometry } from \"../Geometry\";\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { Point3d, Vector3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { HalfEdgeGraphMerge } from \"./Merging\";\r\nimport { Triangulator } from \"./Triangulation\";\r\nimport { RegularizationContext } from \"./RegularizeFace\";\r\nimport { HalfEdgeGraphSearch, HalfEdgeMaskTester } from \"./HalfEdgeGraphSearch\";\r\nimport { Angle } from \"../geometry3d/Angle\";\r\n// cSpell:disable\r\n// const sSpineRelTol = 1.0e-8;\r\n// const sSpineGraphAbsTol = 0.0;\r\n// const sSpineGraphRelTol = 1.0e-10;\r\n\r\nfunction createNPoints(n: number): Point3d[] {\r\n const points = [];\r\n for (let i = 0; i < n; i++)\r\n points.push(Point3d.create(0, 0, 0));\r\n return points;\r\n}\r\nfunction createNVectors(n: number): Vector3d[] {\r\n const points = [];\r\n for (let i = 0; i < n; i++)\r\n points.push(Vector3d.create(0, 0, 0));\r\n return points;\r\n}\r\n// Local struct to pair a graph node with a double as a sort key for std::sort\r\nclass NodeSortKey {\r\n private _a: number;\r\n private _node: HalfEdge;\r\n public get node() { return this._node; }\r\n\r\n public constructor(node: HalfEdge, b: number) {\r\n this._node = node;\r\n this._a = b;\r\n }\r\n public static compareForSort(dataA: NodeSortKey, dataB: NodeSortKey): number { return dataA._a - dataB._a; }\r\n}\r\n\r\n/**\r\n * Context manager to hold a vu graph and do spine operations\r\n *\r\n * Spine calculations determine both (a) a \"skeletal\" network of linework that follows the interior\r\n * path through within the boundaries, and (b) a block decomposition into quads and triangles.\r\n *\r\n * Usage pattern:\r\n * ```\r\n * const sc = new HalfEdgeGraphSpineContext();\r\n * // Data setup ....\r\n * foreach polygon or polyline\r\n * {\r\n * sc.InsertEdges (edgePoints, bClosed)\r\n * }\r\n * // Analysis steps ...\r\n * * bParity = true to treat the data as a \"polygon\". The interior is determined by parity rules\r\n * and the triangulation and spine are only constructed \"inside\"\r\n * * bParity = false if \"all\" spaces are to be triangulated and spined.\r\n * * minSplitRadians -- suggested value 0.3. If this value is large, it will encourage add internal\r\n * * edges from a vertex to an edge 'across' the polygon even if it creates small angles.\r\n * * minDiagonalAngle -- suggested value 1.0. If this value is large (up to about 1.5 as max) it favors\r\n * * using triangles to navigate turns. If it is small, it favors using skewed quadrilaterals.\r\n * sc.TriangulateForSpine (bParity, minSplitRadians)\r\n * sc.MarkBoxes (true, minDiagonalAngle);\r\n * edges = sc.GetSpineEdges ();\r\n * ```\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphSpineContext {\r\n /** The Evolving graph */\r\n private _spineGraph: HalfEdgeGraph;\r\n /** mask marking edges that have been paired into quads */\r\n private _diagonalMask: HalfEdgeMask;\r\n private _boxMask: HalfEdgeMask;\r\n public get graph() { return this._spineGraph; }\r\n /**\r\n * Create a context with an empty graph.\r\n * * Reserve masks for specialized markup.\r\n */\r\n public constructor() {\r\n this._spineGraph = new HalfEdgeGraph();\r\n // vu_setTol (_spineGraph, sSpineGraphAbsTol, sSpineGraphRelTol);\r\n this._diagonalMask = this._spineGraph.grabMask();\r\n this._boxMask = this._spineGraph.grabMask();\r\n }\r\n\r\n /**\r\n * Release resources to the graph.\r\n */\r\n public teardown() {\r\n this._spineGraph.dropMask(this._diagonalMask);\r\n this._spineGraph.dropMask(this._boxMask);\r\n this._spineGraph.decommission();\r\n }\r\n\r\n // an edge (as new bvector<DPoint3d> at back, with cloned points>\r\n private addEdge(xyzOut: Point3d[][], xyzA: Point3d, xyzB: Point3d) {\r\n const newArray = [];\r\n newArray.push(xyzA.clone());\r\n newArray.push(xyzB.clone());\r\n xyzOut.push(newArray);\r\n }\r\n\r\n private getBoxCorners(diagonalNode: HalfEdge,\r\n nodes: HalfEdge[],\r\n points: Point3d[]): boolean {\r\n const diagonalMate = diagonalNode.edgeMate;\r\n nodes.length = 0;\r\n points.length = 0;\r\n if (!diagonalNode.getMask(HalfEdgeMask.BOUNDARY_EDGE)\r\n && diagonalNode.countEdgesAroundFace() === 3\r\n && diagonalMate.countEdgesAroundFace() === 3) {\r\n const nodeA = diagonalMate.faceSuccessor;\r\n nodes.push(nodeA);\r\n nodes.push(nodeA.faceSuccessor);\r\n const nodeB = diagonalNode.faceSuccessor;\r\n nodes.push(nodeB);\r\n nodes.push(nodeB.faceSuccessor);\r\n for (let i = 0; i < 4; i++)\r\n points.push(Point3d.create(nodes[i].x, nodes[i].y));\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n // Compute bisectors of the quad.\r\n // function key is the smaller absolute angle between the bisectors.\r\n // (pi/2 is max possible value).\r\n private diagonalKeyFunc(pDiagonalNode: HalfEdge): number {\r\n\r\n const nodes: HalfEdge[] = [];\r\n const points: Point3d[] = [];\r\n if (this.getBoxCorners(pDiagonalNode, nodes, points)) {\r\n const xyzA = points[0];\r\n const xyzB = points[1];\r\n const xyzC = points[2];\r\n const xyzD = points[3];\r\n const xyzAB = xyzA.interpolate(0.5, xyzB);\r\n const xyzBC = xyzB.interpolate(0.5, xyzC);\r\n const xyzCD = xyzC.interpolate(0.5, xyzD);\r\n const xyzDA = xyzD.interpolate(0.5, xyzA);\r\n\r\n const vectorAB = Vector3d.createStartEnd(xyzA, xyzB);\r\n const vectorBC = Vector3d.createStartEnd(xyzB, xyzC);\r\n const vectorCD = Vector3d.createStartEnd(xyzC, xyzD);\r\n const vectorDA = Vector3d.createStartEnd(xyzD, xyzA);\r\n\r\n const vectorABToCD = Vector3d.createStartEnd(xyzCD, xyzAB);\r\n const vectorBCToDA = Vector3d.createStartEnd(xyzDA, xyzBC);\r\n vectorABToCD.z = 0.0;\r\n vectorBCToDA.z = 0.0;\r\n const thetaAB = vectorABToCD.smallerUnorientedAngleTo(vectorAB).radians;\r\n const thetaBC = vectorBCToDA.smallerUnorientedAngleTo(vectorBC).radians;\r\n const thetaCD = vectorABToCD.smallerUnorientedAngleTo(vectorCD).radians;\r\n const thetaDA = vectorBCToDA.smallerUnorientedAngleTo(vectorDA).radians;\r\n\r\n const alpha = thetaAB < thetaCD ? thetaAB : thetaCD;\r\n const beta = thetaBC < thetaDA ? thetaBC : thetaDA;\r\n return alpha < beta ? alpha : beta;\r\n }\r\n\r\n return Number.NEGATIVE_INFINITY;\r\n }\r\n\r\n // Select a branch point in a triangle.\r\n // This may be the centroid or the midpoint of an edge joining midpoints of a pair of edges.\r\n private selectTriangleInteriorPoint(pXYZ: Point3d[]): Point3d {\r\n\r\n const xyz = createNPoints(6);\r\n const xyzMid = createNPoints(6); // Midpoints of each edge.\r\n const interiorCandidate = createNPoints(4); // for i in {012}, [i] is midpoint of midpoint[i+1] and midpoint[i+2].\r\n // [3] is centroid.\r\n const edgeVector = createNVectors(6);\r\n const centroid = Point3d.create();\r\n for (let i = 0; i < 3; i++) {\r\n xyz[i] = xyz[i + 3] = pXYZ[i];\r\n centroid.addInPlace(xyz[i]);\r\n }\r\n centroid.scaleInPlace(1.0 / 3.0);\r\n\r\n // Edge midpoints ...\r\n for (let i = 0; i < 3; i++) {\r\n xyzMid[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n xyzMid[i + 3] = xyzMid[i];\r\n edgeVector[i] = Vector3d.createStartEnd(xyz[i], xyz[i + 1]); // use wraparound\r\n edgeVector[i + 3] = edgeVector[i];\r\n }\r\n\r\n // Midpoints of midpoint-to-midpoint connections ..\r\n for (let i = 0; i < 3; i++) {\r\n const i1 = i + 1;\r\n const i2 = i + 2;\r\n interiorCandidate[i] = xyzMid[i1].interpolate(0.5, xyzMid[i2]);\r\n }\r\n\r\n interiorCandidate[3] = centroid;\r\n\r\n let bestAngle = Number.NEGATIVE_INFINITY;\r\n let bestIndex = -1;\r\n const theta: number[] = [0, 0, 0];\r\n let thetaMin;\r\n for (let k: number = 0; k < 4; k++) {\r\n // Measure angles from edge midpoints towards interior candidate.\r\n thetaMin = Number.POSITIVE_INFINITY;\r\n for (let i: number = 0; i < 3; i++) {\r\n const edgeToInterior = Vector3d.createStartEnd(xyzMid[i], interiorCandidate[k]);\r\n theta[i] = edgeVector[i].smallerUnorientedAngleTo(edgeToInterior).radians;\r\n if (theta[i] < thetaMin)\r\n thetaMin = theta[i];\r\n }\r\n if (thetaMin > bestAngle) {\r\n bestAngle = thetaMin;\r\n bestIndex = k;\r\n }\r\n }\r\n return interiorCandidate[bestIndex];\r\n }\r\n\r\n private markBox(pA: HalfEdge): void {\r\n\r\n const pB = pA.edgeMate;\r\n pA.setMask(this._diagonalMask);\r\n pB.setMask(this._diagonalMask);\r\n pA.setMaskAroundFace(this._boxMask);\r\n pB.setMaskAroundFace(this._boxMask);\r\n }\r\n\r\n private setSortedDiagonalMasks(minA: number): number {\r\n\r\n const candidates: NodeSortKey[] = [];\r\n let numDiagonal = 0;\r\n for (const node of this._spineGraph.allHalfEdges) {\r\n const b = this.diagonalKeyFunc(node);\r\n if (b > minA)\r\n candidates.push(new NodeSortKey(node, b));\r\n }\r\n\r\n candidates.sort(NodeSortKey.compareForSort);\r\n\r\n let key;\r\n while (undefined !== (key = candidates.pop())) {\r\n const pA = key.node;\r\n const pB = pA.edgeMate;\r\n if (!pA.getMask(this._boxMask)\r\n && !pB.getMask(this._boxMask)) {\r\n this.markBox(pA);\r\n numDiagonal++;\r\n }\r\n }\r\n return numDiagonal;\r\n }\r\n\r\n /// <param name=\"xyzA\">Vertex whose angle is being split</param>\r\n private splitOK(xyzA: Point3d, xyzB: Point3d, xyzQ: Point3d, xyzC: Point3d, minAngle: number): boolean {\r\n\r\n const vectorAB = Vector3d.createStartEnd(xyzA, xyzB);\r\n const vectorAQ = Vector3d.createStartEnd(xyzA, xyzQ);\r\n const vectorAC = Vector3d.createStartEnd(xyzA, xyzC);\r\n const angleBAQ = vectorAB.angleToXY(vectorAQ).radians;\r\n const angleQAC = vectorAQ.angleToXY(vectorAC).radians;\r\n return Math.abs(angleBAQ) > minAngle && Math.abs(angleQAC) > minAngle;\r\n }\r\n\r\n // Search a triangulation for vertices which have\r\n // (a) pre-split angle greater than 90 degrees\r\n // (b) the opposite edge is a boundary.\r\n // (c) each post split angle is less than minSplitRadians\r\n // Drop a perpenedicular to that boundary.\r\n // return the number of edges added.\r\n private addPerpendicularsToBoundaries(minSplitRadians: number, minCandidateRadians: number): number {\r\n\r\n let numAdd = 0;\r\n for (const pA of this._spineGraph.allHalfEdges) {\r\n const pB = pA.faceSuccessor;\r\n const pC = pB.faceSuccessor;\r\n if (!pA.getMask(HalfEdgeMask.EXTERIOR)\r\n && !pA.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion\r\n && !pC.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion\r\n && pB.getMask(HalfEdgeMask.BOUNDARY_EDGE)\r\n && pC.faceSuccessor === pA\r\n ) {\r\n const vectorAB = pA.getVector2dAlongEdge();\r\n const vectorBC = pB.getVector2dAlongEdge();\r\n const vectorCA = pC.getVector2dAlongEdge();\r\n const candidateRadians = Math.PI - vectorCA.angleTo(vectorAB).radians;\r\n // const candidateDot = vectorCA.DotProduct (vectorAB);\r\n if (candidateRadians > minCandidateRadians) { // vectorCA.DotProduct (vectorAB) > 0.0)\r\n const bb = vectorBC.dotProduct(vectorBC);\r\n const ba = -vectorBC.dotProduct(vectorAB);\r\n const s = Geometry.conditionalDivideFraction(ba, bb);\r\n if (s !== undefined && s > 0.0 && s < 1.0) {\r\n const xyzA = pA.getPoint3d();\r\n const xyzB = pB.getPoint3d();\r\n const xyzC = pC.getPoint3d();\r\n const xyzE = xyzB.interpolate(s, xyzC);\r\n if (this.splitOK(xyzA, xyzB, xyzE, xyzC, minSplitRadians)) {\r\n const pE = this._spineGraph.splitEdgeAtFraction(pB, s);\r\n const pA1 = this._spineGraph.createEdgeHalfEdgeHalfEdge(pA, 0, pE, 0);\r\n pA1.setXYZFrom(pA);\r\n pE.setXYZAroundVertex(xyzE.x, xyzE.y, xyzE.z);\r\n numAdd++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return numAdd;\r\n }\r\n\r\n private getSpineEdgesInQuad(\r\n pFace: HalfEdge,\r\n xyzOut: Point3d[][],\r\n bIncludeInterior: boolean,\r\n // true to include the edge to boundary when the qued is a dead end.\r\n bIncludeFinal: boolean,\r\n // true to include the two adjacent edges to boundary if the quad is at a corner.\r\n bIncludeCornerSpokes: boolean): boolean {\r\n\r\n if (pFace.countEdgesAroundFace() !== 4)\r\n return false;\r\n const pNode: HalfEdge[] = [];\r\n const xyz = createNPoints(8);\r\n const midpoint = createNPoints(8);\r\n pNode[0] = pNode[4] = pFace;\r\n pNode[1] = pNode[5] = pNode[0].faceSuccessor;\r\n pNode[2] = pNode[6] = pNode[1].faceSuccessor;\r\n pNode[3] = pNode[7] = pNode[2].faceSuccessor;\r\n let numBoundary = 0;\r\n let numInterior = 0;\r\n const iBoundary: number[] = [];\r\n const iInterior: number[] = [];\r\n const bIsBoundary: boolean[] = [];\r\n const centroid = Point3d.create();\r\n for (let i: number = 0; i < 4; i++) {\r\n bIsBoundary[i] = 0 !== pNode[i].getMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n if (pNode[i].getMask(HalfEdgeMask.BOUNDARY_EDGE))\r\n iBoundary[numBoundary++] = i;\r\n else\r\n iInterior[numInterior++] = i;\r\n xyz[i] = pNode[i].getPoint3d();\r\n xyz[i + 4] = xyz[i];\r\n centroid.addInPlace(xyz[i]);\r\n }\r\n for (let i: number = 0; i < 4; i++) {\r\n midpoint[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n midpoint[i + 4] = midpoint[i];\r\n }\r\n\r\n centroid.scaleInPlace(0.25);\r\n if (numBoundary === 0 || numBoundary === 1) {\r\n for (let i: number = 0; i < numInterior; i++)\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[i]], centroid);\r\n } else if (numBoundary === 4) {\r\n for (let i: number = 0; i < numBoundary; i++)\r\n if (bIncludeFinal)\r\n this.addEdge(xyzOut, midpoint[i], centroid);\r\n } else if (numBoundary === 2) {\r\n if (iInterior[1] === iInterior[0] + 2) {\r\n // Spine enters one end, exits the other ..\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[0]], midpoint[iInterior[1]]);\r\n } else {\r\n // Block sits as exterior corner. Let the two spines continue to their opposite faces ..\r\n for (let i: number = 0; i < 4; i++)\r\n if ((bIsBoundary[i] && bIncludeCornerSpokes)\r\n || (!bIsBoundary[i] && bIncludeInterior))\r\n this.addEdge(xyzOut, midpoint[i], centroid);\r\n }\r\n } else if (numBoundary === 3) {\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[0]], centroid);\r\n if (bIncludeFinal)\r\n this.addEdge(xyzOut, centroid, midpoint[iInterior[0] + 2]);\r\n }\r\n return true;\r\n }\r\n\r\n private getSpineEdgesInTriangle(\r\n pFace: HalfEdge, xyzOut: Point3d[][],\r\n bIncludeInterior: boolean,\r\n bIncludeFinal: boolean): boolean {\r\n\r\n if (pFace.countEdgesAroundFace() !== 3)\r\n return false;\r\n let n = 0;\r\n const xyzMidpoint = createNPoints(6);\r\n const xyz = createNPoints(6);\r\n const xyzCentroid = Point3d.createZero();\r\n const isBoundary: boolean[] = [];\r\n let numBoundary = 0;\r\n let lastBoundary = -1;\r\n let lastInterior = -1;\r\n let currentEdge = pFace;\r\n do {\r\n xyz[n] = currentEdge.getPoint3d();\r\n xyzCentroid.addInPlace(xyz[n]);\r\n isBoundary[n] = false;\r\n if (currentEdge.getMask(HalfEdgeMask.BOUNDARY_EDGE)) {\r\n isBoundary[n] = true;\r\n numBoundary++;\r\n lastBoundary = n;\r\n } else {\r\n lastInterior = n;\r\n }\r\n xyz[n + 3] = xyz[n];\r\n isBoundary[n + 3] = isBoundary[n];\r\n n++;\r\n } while ((currentEdge = currentEdge.faceSuccessor) !== pFace);\r\n\r\n for (let i: number = 0; i < 3; i++) {\r\n xyzMidpoint[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n xyzMidpoint[i + 3] = xyzMidpoint[i];\r\n }\r\n\r\n xyzCentroid.scaleInPlace(1.0 / 3.0);\r\n\r\n if (numBoundary === 0) {\r\n // Interior branch\r\n const xyzInterior = this.selectTriangleInteriorPoint(xyz);\r\n if (bIncludeInterior) {\r\n this.addEdge(xyzOut, xyzMidpoint[0], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[1], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[2], xyzInterior);\r\n }\r\n } else if (numBoundary === 1) {\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, xyzMidpoint[lastBoundary + 1], xyzMidpoint[lastBoundary + 2]);\r\n } else if (numBoundary === 2) {\r\n if (bIncludeFinal && lastInterior >= 0)\r\n this.addEdge(xyzOut, xyzMidpoint[lastInterior], xyz[lastInterior + 2]);\r\n } else if (numBoundary === 3) {\r\n const xyzInterior = this.selectTriangleInteriorPoint(xyz);\r\n if (bIncludeFinal) {\r\n this.addEdge(xyzOut, xyzMidpoint[0], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[1], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[2], xyzInterior);\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /** Add a polyline to the graph.\r\n * * This may be called multiple times\r\n */\r\n public insertEdges(xyzIn: Point3d[], bClosed: boolean): void {\r\n let pPreviousB, pFirstA;\r\n for (let i: number = 1; i < xyzIn.length; i++) {\r\n const nodeA = this._spineGraph.createEdgeXYZXYZ(\r\n xyzIn[i - 1].x, xyzIn[i - 1].y, 0, 0,\r\n xyzIn[i].x, xyzIn[i].y, 0, 0);\r\n const nodeB = nodeA.faceSuccessor;\r\n nodeA.setMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n nodeB.setMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n if (pPreviousB === undefined) {\r\n pFirstA = nodeA;\r\n } else {\r\n HalfEdge.pinch(pPreviousB, nodeA);\r\n }\r\n pPreviousB = nodeB;\r\n }\r\n if (bClosed && pFirstA !== undefined && pPreviousB !== undefined)\r\n HalfEdge.pinch(pPreviousB, pFirstA);\r\n }\r\n /**\r\n * Look for trivial (2 edge) faces that have exteriorMask and non-masked on both sides.\r\n * * clear the mask\r\n * @param exteriorMask\r\n */\r\n private purgeNullFaces(exteriorMask: HalfEdgeMask) {\r\n for (const nodeA of this._spineGraph.allHalfEdges) {\r\n const nodeB = nodeA.faceSuccessor;\r\n const nodeC = nodeB.faceSuccessor;\r\n if (nodeB !== nodeA && nodeC === nodeA) {\r\n if (nodeA.getMask(exteriorMask) && nodeB.getMask(exteriorMask)) {\r\n const mateA = nodeA.edgeMate;\r\n const mateB = nodeB.edgeMate;\r\n if (!mateA.getMask(exteriorMask) && !mateB.getMask(exteriorMask)) {\r\n nodeA.clearMask(exteriorMask);\r\n nodeB.clearMask(exteriorMask);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n private static _regularize1 = true;\r\n private static _regularize2 = false;\r\n /**\r\n * Triangulate the graph for the edges that have been inserted.\r\n * @param applyParity if true ()\r\n * @param minSplitRadians smallest allowed angle in the split sector that is split.\r\n */\r\n public triangulateForSpine(applyParity: boolean = true, minSplitRadians: number = 0.3): void {\r\n\r\n const sMaxSplit = 20;\r\n const sMinCandidateRadians = 1.0;\r\n let numSplit = 0;\r\n HalfEdgeGraphMerge.splitIntersectingEdges(this.graph);\r\n HalfEdgeGraphMerge.clusterAndMergeXYTheta(this.graph);\r\n\r\n const context1 = new RegularizationContext(this.graph);\r\n context1.regularizeGraph(HalfEdgeGraphSpineContext._regularize1, false);\r\n const context2 = new RegularizationContext(this.graph);\r\n context2.regularizeGraph(false, HalfEdgeGraphSpineContext._regularize2);\r\n if (applyParity) {\r\n HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(this.graph,\r\n new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR);\r\n this.purgeNullFaces(HalfEdgeMask.EXTERIOR);\r\n }\r\n\r\n Triangulator.triangulateAllPositiveAreaFaces(this.graph);\r\n Triangulator.flipTriangles(this.graph);\r\n\r\n while (numSplit++ < sMaxSplit) {\r\n const numPerp = this.addPerpendicularsToBoundaries(minSplitRadians, sMinCandidateRadians);\r\n if (numPerp <= 0)\r\n break;\r\n Triangulator.flipTriangles(this.graph);\r\n }\r\n }\r\n\r\n // Find pseudo spine edges\r\n // Optionally include pure internal midline segments.\r\n // Optionally include midline segments into \"dead end\"\r\n // Optionally include adjacent spokes to corner.\r\n /**\r\n * Retrieve edges of the spine as arrays of points.\r\n * @param bIncludeInterior true to include fully internal segments\r\n * @param bIncludeFinal true to include segments that terminate at a boundary\r\n * @param bIncludeCornerSpokes\r\n * @return array of line data.\r\n */\r\n public getSpineEdges(bIncludeInterior: boolean = true, bIncludeFinal: boolean = true, bIncludeCornerSpokes: boolean = true): Point3d[][] {\r\n const xyzOut: Point3d[][] = [];\r\n this._spineGraph.announceFaceLoops(\r\n (_graph: HalfEdgeGraph, faceSeed: HalfEdge) => {\r\n if (!faceSeed.getMask(HalfEdgeMask.EXTERIOR)) {\r\n if (this.getSpineEdgesInTriangle(faceSeed, xyzOut, bIncludeInterior, bIncludeFinal)) {\r\n } else if (this.getSpineEdgesInQuad(faceSeed, xyzOut, bIncludeInterior, bIncludeFinal, bIncludeCornerSpokes)) {\r\n }\r\n }\r\n return true;\r\n });\r\n return xyzOut;\r\n }\r\n\r\n /**\r\n * Intermediate markup step to identify quads between corresponding boundary edges.\r\n * * search for and mark triangle edges that should be treated as diagonal of a quad\r\n * * Angle logic is:\r\n * * In a candidate quad (formed by joining triangles that share an edge)\r\n * * form segments between opposite edges of the quad.\r\n * * compute angles between these segments and the edges of their quads.\r\n * * if this angle is larger than minAngleRadians, accept this as a quad.\r\n * * recommended angle is between 15 and 5 degrees; 50 degrees is typical\r\n * @param bDeleteDiagonals if true, eliminate the diagonals.\r\n * @param minAngleRadians angle tolerance, as described above.\r\n */\r\n public consolidateTrianglesToQuads(bDeleteDiagonals: boolean, minAngle: Angle = Angle.createDegrees(50)): number {\r\n\r\n const numDiagonal = this.setSortedDiagonalMasks(minAngle.radians);\r\n if (bDeleteDiagonals && numDiagonal > 0) {\r\n this.graph.yankAndDeleteEdges(\r\n (node: HalfEdge) => node.getMask(this._diagonalMask));\r\n }\r\n return numDiagonal;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"HalfEdgeGraphSpineContext.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSpineContext.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/** @packageDocumentation\r\n * @module Topology\r\n */\r\nimport { Geometry } from \"../Geometry\";\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { Point3d, Vector3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { HalfEdgeGraphMerge } from \"./Merging\";\r\nimport { Triangulator } from \"./Triangulation\";\r\nimport { RegularizationContext } from \"./RegularizeFace\";\r\nimport { HalfEdgeGraphSearch, HalfEdgeMaskTester } from \"./HalfEdgeGraphSearch\";\r\nimport { Angle } from \"../geometry3d/Angle\";\r\n// cSpell:disable\r\n// const sSpineRelTol = 1.0e-8;\r\n// const sSpineGraphAbsTol = 0.0;\r\n// const sSpineGraphRelTol = 1.0e-10;\r\n\r\nfunction createNPoints(n: number): Point3d[] {\r\n const points = [];\r\n for (let i = 0; i < n; i++)\r\n points.push(Point3d.create(0, 0, 0));\r\n return points;\r\n}\r\nfunction createNVectors(n: number): Vector3d[] {\r\n const points = [];\r\n for (let i = 0; i < n; i++)\r\n points.push(Vector3d.create(0, 0, 0));\r\n return points;\r\n}\r\n// Local struct to pair a graph node with a double as a sort key for std::sort\r\nclass NodeSortKey {\r\n private _a: number;\r\n private _node: HalfEdge;\r\n public get node() { return this._node; }\r\n\r\n public constructor(node: HalfEdge, b: number) {\r\n this._node = node;\r\n this._a = b;\r\n }\r\n public static compareForSort(dataA: NodeSortKey, dataB: NodeSortKey): number { return dataA._a - dataB._a; }\r\n}\r\n\r\n/**\r\n * Context manager to hold a vu graph and do spine operations\r\n *\r\n * Spine calculations determine both (a) a \"skeletal\" network of linework that follows the interior\r\n * path through within the boundaries, and (b) a block decomposition into quads and triangles.\r\n *\r\n * Usage pattern:\r\n * ```\r\n * const sc = new HalfEdgeGraphSpineContext();\r\n * // Data setup ....\r\n * foreach polygon or polyline\r\n * {\r\n * sc.InsertEdges (edgePoints, bClosed)\r\n * }\r\n * // Analysis steps ...\r\n * * bParity = true to treat the data as a \"polygon\". The interior is determined by parity rules\r\n * and the triangulation and spine are only constructed \"inside\"\r\n * * bParity = false if \"all\" spaces are to be triangulated and spined.\r\n * * minSplitRadians -- suggested value 0.3. If this value is large, it will encourage add internal\r\n * * edges from a vertex to an edge 'across' the polygon even if it creates small angles.\r\n * * minDiagonalAngle -- suggested value 1.0. If this value is large (up to about 1.5 as max) it favors\r\n * * using triangles to navigate turns. If it is small, it favors using skewed quadrilaterals.\r\n * sc.TriangulateForSpine (bParity, minSplitRadians)\r\n * sc.MarkBoxes (true, minDiagonalAngle);\r\n * edges = sc.GetSpineEdges ();\r\n * ```\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphSpineContext {\r\n /** The Evolving graph */\r\n private _spineGraph: HalfEdgeGraph;\r\n /** mask marking edges that have been paired into quads */\r\n private _diagonalMask: HalfEdgeMask;\r\n private _boxMask: HalfEdgeMask;\r\n public get graph() { return this._spineGraph; }\r\n /**\r\n * Create a context with an empty graph.\r\n * * Reserve masks for specialized markup.\r\n */\r\n public constructor() {\r\n this._spineGraph = new HalfEdgeGraph();\r\n // vu_setTol (_spineGraph, sSpineGraphAbsTol, sSpineGraphRelTol);\r\n this._diagonalMask = this._spineGraph.grabMask();\r\n this._boxMask = this._spineGraph.grabMask();\r\n }\r\n\r\n /**\r\n * Release resources to the graph.\r\n */\r\n public teardown() {\r\n this._spineGraph.dropMask(this._diagonalMask);\r\n this._spineGraph.dropMask(this._boxMask);\r\n this._spineGraph.decommission();\r\n }\r\n\r\n // an edge (as new bvector<DPoint3d> at back, with cloned points>\r\n private addEdge(xyzOut: Point3d[][], xyzA: Point3d, xyzB: Point3d) {\r\n const newArray = [];\r\n newArray.push(xyzA.clone());\r\n newArray.push(xyzB.clone());\r\n xyzOut.push(newArray);\r\n }\r\n\r\n private getBoxCorners(diagonalNode: HalfEdge,\r\n nodes: HalfEdge[],\r\n points: Point3d[]): boolean {\r\n const diagonalMate = diagonalNode.edgeMate;\r\n nodes.length = 0;\r\n points.length = 0;\r\n if (!diagonalNode.getMask(HalfEdgeMask.BOUNDARY_EDGE)\r\n && diagonalNode.countEdgesAroundFace() === 3\r\n && diagonalMate.countEdgesAroundFace() === 3) {\r\n const nodeA = diagonalMate.faceSuccessor;\r\n nodes.push(nodeA);\r\n nodes.push(nodeA.faceSuccessor);\r\n const nodeB = diagonalNode.faceSuccessor;\r\n nodes.push(nodeB);\r\n nodes.push(nodeB.faceSuccessor);\r\n for (let i = 0; i < 4; i++)\r\n points.push(Point3d.create(nodes[i].x, nodes[i].y));\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n // Compute bisectors of the quad.\r\n // function key is the smaller absolute angle between the bisectors.\r\n // (pi/2 is max possible value).\r\n private diagonalKeyFunc(pDiagonalNode: HalfEdge): number {\r\n\r\n const nodes: HalfEdge[] = [];\r\n const points: Point3d[] = [];\r\n if (this.getBoxCorners(pDiagonalNode, nodes, points)) {\r\n const xyzA = points[0];\r\n const xyzB = points[1];\r\n const xyzC = points[2];\r\n const xyzD = points[3];\r\n const xyzAB = xyzA.interpolate(0.5, xyzB);\r\n const xyzBC = xyzB.interpolate(0.5, xyzC);\r\n const xyzCD = xyzC.interpolate(0.5, xyzD);\r\n const xyzDA = xyzD.interpolate(0.5, xyzA);\r\n\r\n const vectorAB = Vector3d.createStartEnd(xyzA, xyzB);\r\n const vectorBC = Vector3d.createStartEnd(xyzB, xyzC);\r\n const vectorCD = Vector3d.createStartEnd(xyzC, xyzD);\r\n const vectorDA = Vector3d.createStartEnd(xyzD, xyzA);\r\n\r\n const vectorABToCD = Vector3d.createStartEnd(xyzCD, xyzAB);\r\n const vectorBCToDA = Vector3d.createStartEnd(xyzDA, xyzBC);\r\n vectorABToCD.z = 0.0;\r\n vectorBCToDA.z = 0.0;\r\n const thetaAB = vectorABToCD.smallerUnorientedAngleTo(vectorAB).radians;\r\n const thetaBC = vectorBCToDA.smallerUnorientedAngleTo(vectorBC).radians;\r\n const thetaCD = vectorABToCD.smallerUnorientedAngleTo(vectorCD).radians;\r\n const thetaDA = vectorBCToDA.smallerUnorientedAngleTo(vectorDA).radians;\r\n\r\n const alpha = thetaAB < thetaCD ? thetaAB : thetaCD;\r\n const beta = thetaBC < thetaDA ? thetaBC : thetaDA;\r\n return alpha < beta ? alpha : beta;\r\n }\r\n\r\n return Number.NEGATIVE_INFINITY;\r\n }\r\n\r\n // Select a branch point in a triangle.\r\n // This may be the centroid or the midpoint of an edge joining midpoints of a pair of edges.\r\n private selectTriangleInteriorPoint(pXYZ: Point3d[]): Point3d {\r\n\r\n const xyz = createNPoints(6);\r\n const xyzMid = createNPoints(6); // Midpoints of each edge.\r\n const interiorCandidate = createNPoints(4); // for i in {012}, [i] is midpoint of midpoint[i+1] and midpoint[i+2].\r\n // [3] is centroid.\r\n const edgeVector = createNVectors(6);\r\n const centroid = Point3d.create();\r\n for (let i = 0; i < 3; i++) {\r\n xyz[i] = xyz[i + 3] = pXYZ[i];\r\n centroid.addInPlace(xyz[i]);\r\n }\r\n centroid.scaleInPlace(1.0 / 3.0);\r\n\r\n // Edge midpoints ...\r\n for (let i = 0; i < 3; i++) {\r\n xyzMid[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n xyzMid[i + 3] = xyzMid[i];\r\n edgeVector[i] = Vector3d.createStartEnd(xyz[i], xyz[i + 1]); // use wraparound\r\n edgeVector[i + 3] = edgeVector[i];\r\n }\r\n\r\n // Midpoints of midpoint-to-midpoint connections ..\r\n for (let i = 0; i < 3; i++) {\r\n const i1 = i + 1;\r\n const i2 = i + 2;\r\n interiorCandidate[i] = xyzMid[i1].interpolate(0.5, xyzMid[i2]);\r\n }\r\n\r\n interiorCandidate[3] = centroid;\r\n\r\n let bestAngle = Number.NEGATIVE_INFINITY;\r\n let bestIndex = -1;\r\n const theta: number[] = [0, 0, 0];\r\n let thetaMin;\r\n for (let k: number = 0; k < 4; k++) {\r\n // Measure angles from edge midpoints towards interior candidate.\r\n thetaMin = Number.POSITIVE_INFINITY;\r\n for (let i: number = 0; i < 3; i++) {\r\n const edgeToInterior = Vector3d.createStartEnd(xyzMid[i], interiorCandidate[k]);\r\n theta[i] = edgeVector[i].smallerUnorientedAngleTo(edgeToInterior).radians;\r\n if (theta[i] < thetaMin)\r\n thetaMin = theta[i];\r\n }\r\n if (thetaMin > bestAngle) {\r\n bestAngle = thetaMin;\r\n bestIndex = k;\r\n }\r\n }\r\n return interiorCandidate[bestIndex];\r\n }\r\n\r\n private markBox(pA: HalfEdge): void {\r\n\r\n const pB = pA.edgeMate;\r\n pA.setMask(this._diagonalMask);\r\n pB.setMask(this._diagonalMask);\r\n pA.setMaskAroundFace(this._boxMask);\r\n pB.setMaskAroundFace(this._boxMask);\r\n }\r\n\r\n private setSortedDiagonalMasks(minA: number): number {\r\n\r\n const candidates: NodeSortKey[] = [];\r\n let numDiagonal = 0;\r\n for (const node of this._spineGraph.allHalfEdges) {\r\n const b = this.diagonalKeyFunc(node);\r\n if (b > minA)\r\n candidates.push(new NodeSortKey(node, b));\r\n }\r\n\r\n candidates.sort((dataA, dataB) => NodeSortKey.compareForSort(dataA, dataB));\r\n\r\n let key;\r\n while (undefined !== (key = candidates.pop())) {\r\n const pA = key.node;\r\n const pB = pA.edgeMate;\r\n if (!pA.getMask(this._boxMask)\r\n && !pB.getMask(this._boxMask)) {\r\n this.markBox(pA);\r\n numDiagonal++;\r\n }\r\n }\r\n return numDiagonal;\r\n }\r\n\r\n /// <param name=\"xyzA\">Vertex whose angle is being split</param>\r\n private splitOK(xyzA: Point3d, xyzB: Point3d, xyzQ: Point3d, xyzC: Point3d, minAngle: number): boolean {\r\n\r\n const vectorAB = Vector3d.createStartEnd(xyzA, xyzB);\r\n const vectorAQ = Vector3d.createStartEnd(xyzA, xyzQ);\r\n const vectorAC = Vector3d.createStartEnd(xyzA, xyzC);\r\n const angleBAQ = vectorAB.angleToXY(vectorAQ).radians;\r\n const angleQAC = vectorAQ.angleToXY(vectorAC).radians;\r\n return Math.abs(angleBAQ) > minAngle && Math.abs(angleQAC) > minAngle;\r\n }\r\n\r\n // Search a triangulation for vertices which have\r\n // (a) pre-split angle greater than 90 degrees\r\n // (b) the opposite edge is a boundary.\r\n // (c) each post split angle is less than minSplitRadians\r\n // Drop a perpenedicular to that boundary.\r\n // return the number of edges added.\r\n private addPerpendicularsToBoundaries(minSplitRadians: number, minCandidateRadians: number): number {\r\n\r\n let numAdd = 0;\r\n for (const pA of this._spineGraph.allHalfEdges) {\r\n const pB = pA.faceSuccessor;\r\n const pC = pB.faceSuccessor;\r\n if (!pA.getMask(HalfEdgeMask.EXTERIOR)\r\n && !pA.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion\r\n && !pC.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion\r\n && pB.getMask(HalfEdgeMask.BOUNDARY_EDGE)\r\n && pC.faceSuccessor === pA\r\n ) {\r\n const vectorAB = pA.getVector2dAlongEdge();\r\n const vectorBC = pB.getVector2dAlongEdge();\r\n const vectorCA = pC.getVector2dAlongEdge();\r\n const candidateRadians = Math.PI - vectorCA.angleTo(vectorAB).radians;\r\n // const candidateDot = vectorCA.DotProduct (vectorAB);\r\n if (candidateRadians > minCandidateRadians) { // vectorCA.DotProduct (vectorAB) > 0.0)\r\n const bb = vectorBC.dotProduct(vectorBC);\r\n const ba = -vectorBC.dotProduct(vectorAB);\r\n const s = Geometry.conditionalDivideFraction(ba, bb);\r\n if (s !== undefined && s > 0.0 && s < 1.0) {\r\n const xyzA = pA.getPoint3d();\r\n const xyzB = pB.getPoint3d();\r\n const xyzC = pC.getPoint3d();\r\n const xyzE = xyzB.interpolate(s, xyzC);\r\n if (this.splitOK(xyzA, xyzB, xyzE, xyzC, minSplitRadians)) {\r\n const pE = this._spineGraph.splitEdgeAtFraction(pB, s);\r\n const pA1 = this._spineGraph.createEdgeHalfEdgeHalfEdge(pA, 0, pE, 0);\r\n pA1.setXYZFrom(pA);\r\n pE.setXYZAroundVertex(xyzE.x, xyzE.y, xyzE.z);\r\n numAdd++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return numAdd;\r\n }\r\n\r\n private getSpineEdgesInQuad(\r\n pFace: HalfEdge,\r\n xyzOut: Point3d[][],\r\n bIncludeInterior: boolean,\r\n // true to include the edge to boundary when the qued is a dead end.\r\n bIncludeFinal: boolean,\r\n // true to include the two adjacent edges to boundary if the quad is at a corner.\r\n bIncludeCornerSpokes: boolean): boolean {\r\n\r\n if (pFace.countEdgesAroundFace() !== 4)\r\n return false;\r\n const pNode: HalfEdge[] = [];\r\n const xyz = createNPoints(8);\r\n const midpoint = createNPoints(8);\r\n pNode[0] = pNode[4] = pFace;\r\n pNode[1] = pNode[5] = pNode[0].faceSuccessor;\r\n pNode[2] = pNode[6] = pNode[1].faceSuccessor;\r\n pNode[3] = pNode[7] = pNode[2].faceSuccessor;\r\n let numBoundary = 0;\r\n let numInterior = 0;\r\n const iBoundary: number[] = [];\r\n const iInterior: number[] = [];\r\n const bIsBoundary: boolean[] = [];\r\n const centroid = Point3d.create();\r\n for (let i: number = 0; i < 4; i++) {\r\n bIsBoundary[i] = 0 !== pNode[i].getMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n if (pNode[i].getMask(HalfEdgeMask.BOUNDARY_EDGE))\r\n iBoundary[numBoundary++] = i;\r\n else\r\n iInterior[numInterior++] = i;\r\n xyz[i] = pNode[i].getPoint3d();\r\n xyz[i + 4] = xyz[i];\r\n centroid.addInPlace(xyz[i]);\r\n }\r\n for (let i: number = 0; i < 4; i++) {\r\n midpoint[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n midpoint[i + 4] = midpoint[i];\r\n }\r\n\r\n centroid.scaleInPlace(0.25);\r\n if (numBoundary === 0 || numBoundary === 1) {\r\n for (let i: number = 0; i < numInterior; i++)\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[i]], centroid);\r\n } else if (numBoundary === 4) {\r\n for (let i: number = 0; i < numBoundary; i++)\r\n if (bIncludeFinal)\r\n this.addEdge(xyzOut, midpoint[i], centroid);\r\n } else if (numBoundary === 2) {\r\n if (iInterior[1] === iInterior[0] + 2) {\r\n // Spine enters one end, exits the other ..\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[0]], midpoint[iInterior[1]]);\r\n } else {\r\n // Block sits as exterior corner. Let the two spines continue to their opposite faces ..\r\n for (let i: number = 0; i < 4; i++)\r\n if ((bIsBoundary[i] && bIncludeCornerSpokes)\r\n || (!bIsBoundary[i] && bIncludeInterior))\r\n this.addEdge(xyzOut, midpoint[i], centroid);\r\n }\r\n } else if (numBoundary === 3) {\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[0]], centroid);\r\n if (bIncludeFinal)\r\n this.addEdge(xyzOut, centroid, midpoint[iInterior[0] + 2]);\r\n }\r\n return true;\r\n }\r\n\r\n private getSpineEdgesInTriangle(\r\n pFace: HalfEdge, xyzOut: Point3d[][],\r\n bIncludeInterior: boolean,\r\n bIncludeFinal: boolean): boolean {\r\n\r\n if (pFace.countEdgesAroundFace() !== 3)\r\n return false;\r\n let n = 0;\r\n const xyzMidpoint = createNPoints(6);\r\n const xyz = createNPoints(6);\r\n const xyzCentroid = Point3d.createZero();\r\n const isBoundary: boolean[] = [];\r\n let numBoundary = 0;\r\n let lastBoundary = -1;\r\n let lastInterior = -1;\r\n let currentEdge = pFace;\r\n do {\r\n xyz[n] = currentEdge.getPoint3d();\r\n xyzCentroid.addInPlace(xyz[n]);\r\n isBoundary[n] = false;\r\n if (currentEdge.getMask(HalfEdgeMask.BOUNDARY_EDGE)) {\r\n isBoundary[n] = true;\r\n numBoundary++;\r\n lastBoundary = n;\r\n } else {\r\n lastInterior = n;\r\n }\r\n xyz[n + 3] = xyz[n];\r\n isBoundary[n + 3] = isBoundary[n];\r\n n++;\r\n } while ((currentEdge = currentEdge.faceSuccessor) !== pFace);\r\n\r\n for (let i: number = 0; i < 3; i++) {\r\n xyzMidpoint[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n xyzMidpoint[i + 3] = xyzMidpoint[i];\r\n }\r\n\r\n xyzCentroid.scaleInPlace(1.0 / 3.0);\r\n\r\n if (numBoundary === 0) {\r\n // Interior branch\r\n const xyzInterior = this.selectTriangleInteriorPoint(xyz);\r\n if (bIncludeInterior) {\r\n this.addEdge(xyzOut, xyzMidpoint[0], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[1], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[2], xyzInterior);\r\n }\r\n } else if (numBoundary === 1) {\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, xyzMidpoint[lastBoundary + 1], xyzMidpoint[lastBoundary + 2]);\r\n } else if (numBoundary === 2) {\r\n if (bIncludeFinal && lastInterior >= 0)\r\n this.addEdge(xyzOut, xyzMidpoint[lastInterior], xyz[lastInterior + 2]);\r\n } else if (numBoundary === 3) {\r\n const xyzInterior = this.selectTriangleInteriorPoint(xyz);\r\n if (bIncludeFinal) {\r\n this.addEdge(xyzOut, xyzMidpoint[0], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[1], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[2], xyzInterior);\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /** Add a polyline to the graph.\r\n * * This may be called multiple times\r\n */\r\n public insertEdges(xyzIn: Point3d[], bClosed: boolean): void {\r\n let pPreviousB, pFirstA;\r\n for (let i: number = 1; i < xyzIn.length; i++) {\r\n const nodeA = this._spineGraph.createEdgeXYZXYZ(\r\n xyzIn[i - 1].x, xyzIn[i - 1].y, 0, 0,\r\n xyzIn[i].x, xyzIn[i].y, 0, 0);\r\n const nodeB = nodeA.faceSuccessor;\r\n nodeA.setMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n nodeB.setMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n if (pPreviousB === undefined) {\r\n pFirstA = nodeA;\r\n } else {\r\n HalfEdge.pinch(pPreviousB, nodeA);\r\n }\r\n pPreviousB = nodeB;\r\n }\r\n if (bClosed && pFirstA !== undefined && pPreviousB !== undefined)\r\n HalfEdge.pinch(pPreviousB, pFirstA);\r\n }\r\n /**\r\n * Look for trivial (2 edge) faces that have exteriorMask and non-masked on both sides.\r\n * * clear the mask\r\n * @param exteriorMask\r\n */\r\n private purgeNullFaces(exteriorMask: HalfEdgeMask) {\r\n for (const nodeA of this._spineGraph.allHalfEdges) {\r\n const nodeB = nodeA.faceSuccessor;\r\n const nodeC = nodeB.faceSuccessor;\r\n if (nodeB !== nodeA && nodeC === nodeA) {\r\n if (nodeA.getMask(exteriorMask) && nodeB.getMask(exteriorMask)) {\r\n const mateA = nodeA.edgeMate;\r\n const mateB = nodeB.edgeMate;\r\n if (!mateA.getMask(exteriorMask) && !mateB.getMask(exteriorMask)) {\r\n nodeA.clearMask(exteriorMask);\r\n nodeB.clearMask(exteriorMask);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n private static _regularize1 = true;\r\n private static _regularize2 = false;\r\n /**\r\n * Triangulate the graph for the edges that have been inserted.\r\n * @param applyParity if true ()\r\n * @param minSplitRadians smallest allowed angle in the split sector that is split.\r\n */\r\n public triangulateForSpine(applyParity: boolean = true, minSplitRadians: number = 0.3): void {\r\n\r\n const sMaxSplit = 20;\r\n const sMinCandidateRadians = 1.0;\r\n let numSplit = 0;\r\n HalfEdgeGraphMerge.splitIntersectingEdges(this.graph);\r\n HalfEdgeGraphMerge.clusterAndMergeXYTheta(this.graph);\r\n\r\n const context1 = new RegularizationContext(this.graph);\r\n context1.regularizeGraph(HalfEdgeGraphSpineContext._regularize1, false);\r\n const context2 = new RegularizationContext(this.graph);\r\n context2.regularizeGraph(false, HalfEdgeGraphSpineContext._regularize2);\r\n if (applyParity) {\r\n HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(this.graph,\r\n new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR);\r\n this.purgeNullFaces(HalfEdgeMask.EXTERIOR);\r\n }\r\n\r\n Triangulator.triangulateAllPositiveAreaFaces(this.graph);\r\n Triangulator.flipTriangles(this.graph);\r\n\r\n while (numSplit++ < sMaxSplit) {\r\n const numPerp = this.addPerpendicularsToBoundaries(minSplitRadians, sMinCandidateRadians);\r\n if (numPerp <= 0)\r\n break;\r\n Triangulator.flipTriangles(this.graph);\r\n }\r\n }\r\n\r\n // Find pseudo spine edges\r\n // Optionally include pure internal midline segments.\r\n // Optionally include midline segments into \"dead end\"\r\n // Optionally include adjacent spokes to corner.\r\n /**\r\n * Retrieve edges of the spine as arrays of points.\r\n * @param bIncludeInterior true to include fully internal segments\r\n * @param bIncludeFinal true to include segments that terminate at a boundary\r\n * @param bIncludeCornerSpokes\r\n * @return array of line data.\r\n */\r\n public getSpineEdges(bIncludeInterior: boolean = true, bIncludeFinal: boolean = true, bIncludeCornerSpokes: boolean = true): Point3d[][] {\r\n const xyzOut: Point3d[][] = [];\r\n this._spineGraph.announceFaceLoops(\r\n (_graph: HalfEdgeGraph, faceSeed: HalfEdge) => {\r\n if (!faceSeed.getMask(HalfEdgeMask.EXTERIOR)) {\r\n if (this.getSpineEdgesInTriangle(faceSeed, xyzOut, bIncludeInterior, bIncludeFinal)) {\r\n } else if (this.getSpineEdgesInQuad(faceSeed, xyzOut, bIncludeInterior, bIncludeFinal, bIncludeCornerSpokes)) {\r\n }\r\n }\r\n return true;\r\n });\r\n return xyzOut;\r\n }\r\n\r\n /**\r\n * Intermediate markup step to identify quads between corresponding boundary edges.\r\n * * search for and mark triangle edges that should be treated as diagonal of a quad\r\n * * Angle logic is:\r\n * * In a candidate quad (formed by joining triangles that share an edge)\r\n * * form segments between opposite edges of the quad.\r\n * * compute angles between these segments and the edges of their quads.\r\n * * if this angle is larger than minAngleRadians, accept this as a quad.\r\n * * recommended angle is between 15 and 5 degrees; 50 degrees is typical\r\n * @param bDeleteDiagonals if true, eliminate the diagonals.\r\n * @param minAngleRadians angle tolerance, as described above.\r\n */\r\n public consolidateTrianglesToQuads(bDeleteDiagonals: boolean, minAngle: Angle = Angle.createDegrees(50)): number {\r\n\r\n const numDiagonal = this.setSortedDiagonalMasks(minAngle.radians);\r\n if (bDeleteDiagonals && numDiagonal > 0) {\r\n this.graph.yankAndDeleteEdges(\r\n (node: HalfEdge) => node.getMask(this._diagonalMask));\r\n }\r\n return numDiagonal;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgePriorityQueue.d.ts","sourceRoot":"","sources":["../../../src/topology/HalfEdgePriorityQueue.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC;;;;;;;;GAQG;AACH,qBAAa,qCAAqC;IACzC,aAAa,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,WAAW,EAAE,QAAQ,EAAE,CAAC;gBAE7B,OAAO,GAAE,iBAAiB,CAAC,QAAQ,CAAqC;IAI1E,qEAAqE;IAC9D,eAAe,IAAI,QAAQ,GAAG,SAAS;IAO9C;;;;OAIG;IACI,oBAAoB,CAAC,CAAC,EAAE,MAAM;IAOrC;;;;OAIG;IACI,6BAA6B,CAAC,CAAC,EAAE,MAAM;CAiB/C"}
1
+ {"version":3,"file":"HalfEdgePriorityQueue.d.ts","sourceRoot":"","sources":["../../../src/topology/HalfEdgePriorityQueue.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC;;;;;;;;GAQG;AACH,qBAAa,qCAAqC;IACzC,aAAa,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,WAAW,EAAE,QAAQ,EAAE,CAAC;gBAE7B,OAAO,GAAE,iBAAiB,CAAC,QAAQ,CAAqD;IAI1F,qEAAqE;IAC9D,eAAe,IAAI,QAAQ,GAAG,SAAS;IAO9C;;;;OAIG;IACI,oBAAoB,CAAC,CAAC,EAAE,MAAM;IAOrC;;;;OAIG;IACI,6BAA6B,CAAC,CAAC,EAAE,MAAM;CAiB/C"}
@@ -20,7 +20,7 @@ const Merging_1 = require("./Merging");
20
20
  * @internal
21
21
  */
22
22
  class HalfEdgePriorityQueueWithPartnerArray {
23
- constructor(compare = Merging_1.HalfEdgeGraphOps.compareNodesYXUp) {
23
+ constructor(compare = (a, b) => Merging_1.HalfEdgeGraphOps.compareNodesYXUp(a, b)) {
24
24
  this.priorityQueue = new core_bentley_1.PriorityQueue(compare);
25
25
  this.activeEdges = [];
26
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgePriorityQueue.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgePriorityQueue.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;;;AAE/F;;GAEG;AACH,sDAAuE;AAEvE,uCAA6C;AAE7C;;;;;;;;GAQG;AACH,MAAa,qCAAqC;IAGhD,YACE,UAAuC,0BAAgB,CAAC,gBAAgB;QACxE,IAAI,CAAC,aAAa,GAAG,IAAI,4BAAa,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACxB,CAAC;IACD,qEAAqE;IAC9D,eAAe;QACpB,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO;YAC5B,OAAO,SAAS,CAAC;QACnB,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAG,CAAC;QACpC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC;IACX,CAAC;IACD;;;;OAIG;IACI,oBAAoB,CAAC,CAAS;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,EAAE;YACT,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAG,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;SACzB;IACH,CAAC;IACD;;;;OAIG;IACI,6BAA6B,CAAC,CAAS;QAC5C,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,EAAE,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;YAC7B,IAAI,EAAE,IAAI,CAAC,EAAE;gBACX,+BAA+B;gBAC/B,IAAI,OAAO,GAAG,CAAC;oBACb,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChC,OAAO,EAAE,CAAC;aACX;iBAAM;gBACL,mBAAmB;aACpB;SACF;QACD,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC;IACpC,CAAC;CACF;AAlDD,sFAkDC","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\nimport { OrderedComparator, PriorityQueue } from \"@itwin/core-bentley\";\r\nimport { HalfEdge } from \"./Graph\";\r\nimport { HalfEdgeGraphOps } from \"./Merging\";\r\n\r\n/**\r\n * * Combination of a priority queue of HalfEdges with\r\n * * Additional \"active\" array to carry edges that have been removed from the queue but are still to be\r\n * inspected (possibly many times)\r\n * * The priority queue default sort is Y-then-X lexical sort.\r\n * * Caller has direct access to the queue and array.\r\n * * Methods are added here only to do things that involve both the queue and the array.\r\n * @internal\r\n */\r\nexport class HalfEdgePriorityQueueWithPartnerArray {\r\n public priorityQueue: PriorityQueue<HalfEdge>;\r\n public activeEdges: HalfEdge[];\r\n public constructor(\r\n compare: OrderedComparator<HalfEdge> = HalfEdgeGraphOps.compareNodesYXUp) {\r\n this.priorityQueue = new PriorityQueue(compare);\r\n this.activeEdges = [];\r\n }\r\n /** Read a member from the queue and transfer to the active array. */\r\n public popQueueToArray(): HalfEdge | undefined {\r\n if (this.priorityQueue.isEmpty)\r\n return undefined;\r\n const x = this.priorityQueue.pop()!;\r\n this.activeEdges.push(x);\r\n return x;\r\n }\r\n /** Pop the last entry and put it back as replacement for current entry at index i.\r\n * * Effectively remove active member at index i\r\n * * The array order is changed.\r\n * * constant time.\r\n */\r\n public popArrayToArrayIndex(i: number) {\r\n const n = this.activeEdges.length;\r\n if (i < n) {\r\n const x = this.activeEdges.pop()!;\r\n this.activeEdges[i] = x;\r\n }\r\n }\r\n /**\r\n * * Scan the active array.\r\n * * remove edges whose top y is below y\r\n * * (pack all remaining ones back towards the beginning)\r\n */\r\n public removeArrayMembersWithY1Below(y: number) {\r\n let numKeep = 0;\r\n const n = this.activeEdges.length;\r\n for (let i = 0; i < n; i++) {\r\n const q = this.activeEdges[i];\r\n const yB = q.faceSuccessor.y;\r\n if (yB >= y) {\r\n // copy [i] forward to [target]\r\n if (numKeep < i)\r\n this.activeEdges[numKeep] = q;\r\n numKeep++;\r\n } else {\r\n // let it go by !!!\r\n }\r\n }\r\n this.activeEdges.length = numKeep;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"HalfEdgePriorityQueue.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgePriorityQueue.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;;;AAE/F;;GAEG;AACH,sDAAuE;AAEvE,uCAA6C;AAE7C;;;;;;;;GAQG;AACH,MAAa,qCAAqC;IAGhD,YACE,UAAuC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,0BAAgB,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC;QACxF,IAAI,CAAC,aAAa,GAAG,IAAI,4BAAa,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACxB,CAAC;IACD,qEAAqE;IAC9D,eAAe;QACpB,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO;YAC5B,OAAO,SAAS,CAAC;QACnB,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAG,CAAC;QACpC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC;IACX,CAAC;IACD;;;;OAIG;IACI,oBAAoB,CAAC,CAAS;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,EAAE;YACT,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAG,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;SACzB;IACH,CAAC;IACD;;;;OAIG;IACI,6BAA6B,CAAC,CAAS;QAC5C,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,EAAE,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;YAC7B,IAAI,EAAE,IAAI,CAAC,EAAE;gBACX,+BAA+B;gBAC/B,IAAI,OAAO,GAAG,CAAC;oBACb,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChC,OAAO,EAAE,CAAC;aACX;iBAAM;gBACL,mBAAmB;aACpB;SACF;QACD,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC;IACpC,CAAC;CACF;AAlDD,sFAkDC","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\nimport { OrderedComparator, PriorityQueue } from \"@itwin/core-bentley\";\r\nimport { HalfEdge } from \"./Graph\";\r\nimport { HalfEdgeGraphOps } from \"./Merging\";\r\n\r\n/**\r\n * * Combination of a priority queue of HalfEdges with\r\n * * Additional \"active\" array to carry edges that have been removed from the queue but are still to be\r\n * inspected (possibly many times)\r\n * * The priority queue default sort is Y-then-X lexical sort.\r\n * * Caller has direct access to the queue and array.\r\n * * Methods are added here only to do things that involve both the queue and the array.\r\n * @internal\r\n */\r\nexport class HalfEdgePriorityQueueWithPartnerArray {\r\n public priorityQueue: PriorityQueue<HalfEdge>;\r\n public activeEdges: HalfEdge[];\r\n public constructor(\r\n compare: OrderedComparator<HalfEdge> = (a, b) => HalfEdgeGraphOps.compareNodesYXUp(a, b)) {\r\n this.priorityQueue = new PriorityQueue(compare);\r\n this.activeEdges = [];\r\n }\r\n /** Read a member from the queue and transfer to the active array. */\r\n public popQueueToArray(): HalfEdge | undefined {\r\n if (this.priorityQueue.isEmpty)\r\n return undefined;\r\n const x = this.priorityQueue.pop()!;\r\n this.activeEdges.push(x);\r\n return x;\r\n }\r\n /** Pop the last entry and put it back as replacement for current entry at index i.\r\n * * Effectively remove active member at index i\r\n * * The array order is changed.\r\n * * constant time.\r\n */\r\n public popArrayToArrayIndex(i: number) {\r\n const n = this.activeEdges.length;\r\n if (i < n) {\r\n const x = this.activeEdges.pop()!;\r\n this.activeEdges[i] = x;\r\n }\r\n }\r\n /**\r\n * * Scan the active array.\r\n * * remove edges whose top y is below y\r\n * * (pack all remaining ones back towards the beginning)\r\n */\r\n public removeArrayMembersWithY1Below(y: number) {\r\n let numKeep = 0;\r\n const n = this.activeEdges.length;\r\n for (let i = 0; i < n; i++) {\r\n const q = this.activeEdges[i];\r\n const yB = q.faceSuccessor.y;\r\n if (yB >= y) {\r\n // copy [i] forward to [target]\r\n if (numKeep < i)\r\n this.activeEdges[numKeep] = q;\r\n numKeep++;\r\n } else {\r\n // let it go by !!!\r\n }\r\n }\r\n this.activeEdges.length = numKeep;\r\n }\r\n}\r\n"]}
@@ -209,7 +209,7 @@ class RegularizationContext {
209
209
  }
210
210
  downwardConnectionFromBottomPeak(node) {
211
211
  let connectTo;
212
- const upFunction = Merging_1.HalfEdgeGraphOps.compareNodesYXUp;
212
+ const upFunction = (a, b) => Merging_1.HalfEdgeGraphOps.compareNodesYXUp(a, b);
213
213
  const upEdgeBase = this.findTopVisibleEdge(node, this.upEdges, 1.0);
214
214
  const downEdgeBase = this.findTopVisibleEdge(node, this.downEdges, -1.0);
215
215
  connectTo = this.updateMaxNode(connectTo, upEdgeBase, upFunction);
@@ -262,7 +262,7 @@ class RegularizationContext {
262
262
  */
263
263
  runRegularization(upSweep = true, downSweep = true) {
264
264
  if (upSweep) {
265
- this.bottomPeaks.sort(Merging_1.HalfEdgeGraphOps.compareNodesYXUp);
265
+ this.bottomPeaks.sort((a, b) => Merging_1.HalfEdgeGraphOps.compareNodesYXUp(a, b));
266
266
  for (const bottomPeak of this.bottomPeaks) {
267
267
  // GeometryCoreTestIO.consoleLog("SEARCH", bottomPeak.id, [bottomPeak.x, bottomPeak.y]);
268
268
  if (!Merging_1.HalfEdgeGraphOps.isDownPeak(bottomPeak))
@@ -279,7 +279,7 @@ class RegularizationContext {
279
279
  this.negateXY();
280
280
  // swap the various p and down seeds ....
281
281
  this.swapArrays();
282
- this.bottomPeaks.sort(Merging_1.HalfEdgeGraphOps.compareNodesYXUp);
282
+ this.bottomPeaks.sort((a, b) => Merging_1.HalfEdgeGraphOps.compareNodesYXUp(a, b));
283
283
  for (const bottomPeak of this.bottomPeaks) {
284
284
  if (!Merging_1.HalfEdgeGraphOps.isDownPeak(bottomPeak))
285
285
  continue;