@itwin/core-geometry 4.4.0-dev.9 → 4.5.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (655) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/lib/cjs/Constant.js.map +1 -1
  3. package/lib/cjs/Geometry.d.ts +17 -0
  4. package/lib/cjs/Geometry.d.ts.map +1 -1
  5. package/lib/cjs/Geometry.js +14 -0
  6. package/lib/cjs/Geometry.js.map +1 -1
  7. package/lib/cjs/bspline/AkimaCurve3d.js.map +1 -1
  8. package/lib/cjs/bspline/BSpline1dNd.js.map +1 -1
  9. package/lib/cjs/bspline/BSplineCurve.js.map +1 -1
  10. package/lib/cjs/bspline/BSplineCurve3dH.js.map +1 -1
  11. package/lib/cjs/bspline/BSplineCurveOps.js.map +1 -1
  12. package/lib/cjs/bspline/BSplineSurface.js.map +1 -1
  13. package/lib/cjs/bspline/Bezier1dNd.js.map +1 -1
  14. package/lib/cjs/bspline/BezierCurve3d.js.map +1 -1
  15. package/lib/cjs/bspline/BezierCurve3dH.js.map +1 -1
  16. package/lib/cjs/bspline/BezierCurveBase.js.map +1 -1
  17. package/lib/cjs/bspline/InterpolationCurve3d.js.map +1 -1
  18. package/lib/cjs/bspline/KnotVector.js.map +1 -1
  19. package/lib/cjs/bspline/SurfaceLocationDetail.js.map +1 -1
  20. package/lib/cjs/clipping/AlternatingConvexClipTree.js.map +1 -1
  21. package/lib/cjs/clipping/BooleanClipFactory.js.map +1 -1
  22. package/lib/cjs/clipping/BooleanClipNode.js.map +1 -1
  23. package/lib/cjs/clipping/ClipPlane.js.map +1 -1
  24. package/lib/cjs/clipping/ClipPrimitive.js.map +1 -1
  25. package/lib/cjs/clipping/ClipUtils.js.map +1 -1
  26. package/lib/cjs/clipping/ClipVector.js.map +1 -1
  27. package/lib/cjs/clipping/ConvexClipPlaneSet.js.map +1 -1
  28. package/lib/cjs/clipping/UnionOfConvexClipPlaneSets.js.map +1 -1
  29. package/lib/cjs/clipping/internalContexts/LineStringOffsetClipperContext.js.map +1 -1
  30. package/lib/cjs/core-geometry.d.ts +3 -2
  31. package/lib/cjs/core-geometry.d.ts.map +1 -1
  32. package/lib/cjs/core-geometry.js +3 -2
  33. package/lib/cjs/core-geometry.js.map +1 -1
  34. package/lib/cjs/curve/Arc3d.js.map +1 -1
  35. package/lib/cjs/curve/ConstructCurveBetweenCurves.js.map +1 -1
  36. package/lib/cjs/curve/CoordinateXYZ.js.map +1 -1
  37. package/lib/cjs/curve/CurveChainWithDistanceIndex.d.ts +2 -2
  38. package/lib/cjs/curve/CurveChainWithDistanceIndex.js +3 -3
  39. package/lib/cjs/curve/CurveChainWithDistanceIndex.js.map +1 -1
  40. package/lib/cjs/curve/CurveCollection.js.map +1 -1
  41. package/lib/cjs/curve/CurveCurve.js.map +1 -1
  42. package/lib/cjs/curve/CurveExtendMode.d.ts +7 -6
  43. package/lib/cjs/curve/CurveExtendMode.d.ts.map +1 -1
  44. package/lib/cjs/curve/CurveExtendMode.js +7 -6
  45. package/lib/cjs/curve/CurveExtendMode.js.map +1 -1
  46. package/lib/cjs/curve/CurveFactory.js.map +1 -1
  47. package/lib/cjs/curve/CurveLocationDetail.d.ts.map +1 -1
  48. package/lib/cjs/curve/CurveLocationDetail.js +23 -18
  49. package/lib/cjs/curve/CurveLocationDetail.js.map +1 -1
  50. package/lib/cjs/curve/CurveOps.js.map +1 -1
  51. package/lib/cjs/curve/CurvePrimitive.js.map +1 -1
  52. package/lib/cjs/curve/CurveProcessor.js.map +1 -1
  53. package/lib/cjs/curve/CurveTypes.js.map +1 -1
  54. package/lib/cjs/curve/CurveWireMomentsXYZ.js.map +1 -1
  55. package/lib/cjs/curve/GeometryQuery.js.map +1 -1
  56. package/lib/cjs/curve/LineSegment3d.d.ts +14 -4
  57. package/lib/cjs/curve/LineSegment3d.d.ts.map +1 -1
  58. package/lib/cjs/curve/LineSegment3d.js +107 -2
  59. package/lib/cjs/curve/LineSegment3d.js.map +1 -1
  60. package/lib/cjs/curve/LineString3d.d.ts +41 -8
  61. package/lib/cjs/curve/LineString3d.d.ts.map +1 -1
  62. package/lib/cjs/curve/LineString3d.js +53 -15
  63. package/lib/cjs/curve/LineString3d.js.map +1 -1
  64. package/lib/cjs/curve/Loop.js +1 -1
  65. package/lib/cjs/curve/Loop.js.map +1 -1
  66. package/lib/cjs/curve/OffsetOptions.js.map +1 -1
  67. package/lib/cjs/curve/ParityRegion.js.map +1 -1
  68. package/lib/cjs/curve/Path.js.map +1 -1
  69. package/lib/cjs/curve/PointString3d.js.map +1 -1
  70. package/lib/cjs/curve/ProxyCurve.js.map +1 -1
  71. package/lib/cjs/curve/Query/ConsolidateAdjacentPrimitivesContext.js.map +1 -1
  72. package/lib/cjs/curve/Query/CurveSplitContext.js.map +1 -1
  73. package/lib/cjs/curve/Query/CylindricalRange.js.map +1 -1
  74. package/lib/cjs/curve/Query/InOutTests.js.map +1 -1
  75. package/lib/cjs/curve/Query/PlanarSubdivision.d.ts +2 -2
  76. package/lib/cjs/curve/Query/PlanarSubdivision.js +2 -2
  77. package/lib/cjs/curve/Query/PlanarSubdivision.js.map +1 -1
  78. package/lib/cjs/curve/Query/StrokeCountChain.js.map +1 -1
  79. package/lib/cjs/curve/Query/StrokeCountMap.js.map +1 -1
  80. package/lib/cjs/curve/RegionMomentsXY.js.map +1 -1
  81. package/lib/cjs/curve/RegionOps.d.ts +1 -2
  82. package/lib/cjs/curve/RegionOps.d.ts.map +1 -1
  83. package/lib/cjs/curve/RegionOps.js.map +1 -1
  84. package/lib/cjs/curve/RegionOpsClassificationSweeps.d.ts +5 -8
  85. package/lib/cjs/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  86. package/lib/cjs/curve/RegionOpsClassificationSweeps.js +12 -12
  87. package/lib/cjs/curve/RegionOpsClassificationSweeps.js.map +1 -1
  88. package/lib/cjs/curve/StrokeOptions.js.map +1 -1
  89. package/lib/cjs/curve/UnionRegion.js.map +1 -1
  90. package/lib/cjs/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.js.map +1 -1
  91. package/lib/cjs/curve/internalContexts/ChainCollectorContext.js.map +1 -1
  92. package/lib/cjs/curve/internalContexts/CloneCurvesContext.js.map +1 -1
  93. package/lib/cjs/curve/internalContexts/CloneWithExpandedLineStrings.js.map +1 -1
  94. package/lib/cjs/curve/internalContexts/ClosestPointStrokeHandler.js.map +1 -1
  95. package/lib/cjs/curve/internalContexts/CountLinearPartsSearchContext.js.map +1 -1
  96. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -1
  97. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  98. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXYZ.js.map +1 -1
  99. package/lib/cjs/curve/internalContexts/CurveLengthContext.js.map +1 -1
  100. package/lib/cjs/curve/internalContexts/CurveOffsetXYHandler.js.map +1 -1
  101. package/lib/cjs/curve/internalContexts/GapSearchContext.js.map +1 -1
  102. package/lib/cjs/curve/internalContexts/MultiChainCollector.js.map +1 -1
  103. package/lib/cjs/curve/internalContexts/NewtonRtoRStrokeHandler.js.map +1 -1
  104. package/lib/cjs/curve/internalContexts/PlaneAltitudeRangeContext.js.map +1 -1
  105. package/lib/cjs/curve/internalContexts/PolygonOffsetContext.js.map +1 -1
  106. package/lib/cjs/curve/internalContexts/SumLengthsContext.js.map +1 -1
  107. package/lib/cjs/curve/internalContexts/TransformInPlaceContext.js.map +1 -1
  108. package/lib/cjs/curve/spiral/AustralianRailCorpXYEvaluator.js.map +1 -1
  109. package/lib/cjs/curve/spiral/ClothoidSeries.js.map +1 -1
  110. package/lib/cjs/curve/spiral/CubicEvaluator.js.map +1 -1
  111. package/lib/cjs/curve/spiral/CzechSpiralEvaluator.js.map +1 -1
  112. package/lib/cjs/curve/spiral/DirectHalfCosineSpiralEvaluator.js.map +1 -1
  113. package/lib/cjs/curve/spiral/DirectSpiral3d.js.map +1 -1
  114. package/lib/cjs/curve/spiral/IntegratedSpiral3d.js.map +1 -1
  115. package/lib/cjs/curve/spiral/MXCubicAlongArcSpiralEvaluator.js.map +1 -1
  116. package/lib/cjs/curve/spiral/NormalizedTransition.js.map +1 -1
  117. package/lib/cjs/curve/spiral/PolishCubicSpiralEvaluator.js.map +1 -1
  118. package/lib/cjs/curve/spiral/TransitionConditionalProperties.js.map +1 -1
  119. package/lib/cjs/curve/spiral/TransitionSpiral3d.js.map +1 -1
  120. package/lib/cjs/curve/spiral/XYCurveEvaluator.js.map +1 -1
  121. package/lib/cjs/geometry3d/Angle.js.map +1 -1
  122. package/lib/cjs/geometry3d/AngleSweep.js.map +1 -1
  123. package/lib/cjs/geometry3d/BarycentricTriangle.js.map +1 -1
  124. package/lib/cjs/geometry3d/BilinearPatch.js.map +1 -1
  125. package/lib/cjs/geometry3d/CoincidentGeometryOps.js.map +1 -1
  126. package/lib/cjs/geometry3d/Ellipsoid.js.map +1 -1
  127. package/lib/cjs/geometry3d/FrameBuilder.js.map +1 -1
  128. package/lib/cjs/geometry3d/FrustumAnimation.js.map +1 -1
  129. package/lib/cjs/geometry3d/GeometryHandler.js.map +1 -1
  130. package/lib/cjs/geometry3d/GrowableBlockedArray.js.map +1 -1
  131. package/lib/cjs/geometry3d/GrowableFloat64Array.js.map +1 -1
  132. package/lib/cjs/geometry3d/GrowableXYArray.d.ts +2 -2
  133. package/lib/cjs/geometry3d/GrowableXYArray.d.ts.map +1 -1
  134. package/lib/cjs/geometry3d/GrowableXYArray.js +1 -1
  135. package/lib/cjs/geometry3d/GrowableXYArray.js.map +1 -1
  136. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts +2 -3
  137. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  138. package/lib/cjs/geometry3d/GrowableXYZArray.js +1 -1
  139. package/lib/cjs/geometry3d/GrowableXYZArray.js.map +1 -1
  140. package/lib/cjs/geometry3d/IndexedCollectionInterval.js.map +1 -1
  141. package/lib/cjs/geometry3d/IndexedXYCollection.js.map +1 -1
  142. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts +18 -1
  143. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  144. package/lib/cjs/geometry3d/IndexedXYZCollection.js +13 -0
  145. package/lib/cjs/geometry3d/IndexedXYZCollection.js.map +1 -1
  146. package/lib/cjs/geometry3d/LongitudeLatitudeAltitude.js.map +1 -1
  147. package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
  148. package/lib/cjs/geometry3d/OrderedRotationAngles.js.map +1 -1
  149. package/lib/cjs/geometry3d/Plane3d.js.map +1 -1
  150. package/lib/cjs/geometry3d/Plane3dByOriginAndUnitNormal.js.map +1 -1
  151. package/lib/cjs/geometry3d/Plane3dByOriginAndVectors.js.map +1 -1
  152. package/lib/cjs/geometry3d/Point2dArrayCarrier.js.map +1 -1
  153. package/lib/cjs/geometry3d/Point2dVector2d.js.map +1 -1
  154. package/lib/cjs/geometry3d/Point3dArrayCarrier.js.map +1 -1
  155. package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
  156. package/lib/cjs/geometry3d/PointHelpers.d.ts +1 -2
  157. package/lib/cjs/geometry3d/PointHelpers.d.ts.map +1 -1
  158. package/lib/cjs/geometry3d/PointHelpers.js.map +1 -1
  159. package/lib/cjs/geometry3d/PointStreaming.d.ts +1 -1
  160. package/lib/cjs/geometry3d/PointStreaming.d.ts.map +1 -1
  161. package/lib/cjs/geometry3d/PointStreaming.js +3 -1
  162. package/lib/cjs/geometry3d/PointStreaming.js.map +1 -1
  163. package/lib/cjs/geometry3d/PolygonOps.d.ts +68 -1
  164. package/lib/cjs/geometry3d/PolygonOps.d.ts.map +1 -1
  165. package/lib/cjs/geometry3d/PolygonOps.js +152 -4
  166. package/lib/cjs/geometry3d/PolygonOps.js.map +1 -1
  167. package/lib/cjs/geometry3d/PolylineCompressionByEdgeOffset.js.map +1 -1
  168. package/lib/cjs/geometry3d/PolylineOps.d.ts +23 -1
  169. package/lib/cjs/geometry3d/PolylineOps.d.ts.map +1 -1
  170. package/lib/cjs/geometry3d/PolylineOps.js +73 -1
  171. package/lib/cjs/geometry3d/PolylineOps.js.map +1 -1
  172. package/lib/cjs/geometry3d/Range.d.ts +1 -1
  173. package/lib/cjs/geometry3d/Range.d.ts.map +1 -1
  174. package/lib/cjs/geometry3d/Range.js.map +1 -1
  175. package/lib/cjs/geometry3d/Ray2d.js.map +1 -1
  176. package/lib/cjs/geometry3d/Ray3d.js.map +1 -1
  177. package/lib/cjs/geometry3d/ReusableObjectCache.js.map +1 -1
  178. package/lib/cjs/geometry3d/Segment1d.js.map +1 -1
  179. package/lib/cjs/geometry3d/SortablePolygon.js.map +1 -1
  180. package/lib/cjs/geometry3d/Transform.js +1 -1
  181. package/lib/cjs/geometry3d/Transform.js.map +1 -1
  182. package/lib/cjs/geometry3d/UVSurfaceOps.js.map +1 -1
  183. package/lib/cjs/geometry3d/XYZProps.js.map +1 -1
  184. package/lib/cjs/geometry3d/YawPitchRollAngles.d.ts +7 -5
  185. package/lib/cjs/geometry3d/YawPitchRollAngles.d.ts.map +1 -1
  186. package/lib/cjs/geometry3d/YawPitchRollAngles.js +8 -6
  187. package/lib/cjs/geometry3d/YawPitchRollAngles.js.map +1 -1
  188. package/lib/cjs/geometry4d/Map4d.js.map +1 -1
  189. package/lib/cjs/geometry4d/Matrix4d.js.map +1 -1
  190. package/lib/cjs/geometry4d/MomentData.js.map +1 -1
  191. package/lib/cjs/geometry4d/PlaneByOriginAndVectors4d.js.map +1 -1
  192. package/lib/cjs/geometry4d/Point4d.js.map +1 -1
  193. package/lib/cjs/numerics/BandedSystem.js.map +1 -1
  194. package/lib/cjs/numerics/BezierPolynomials.js.map +1 -1
  195. package/lib/cjs/numerics/ClusterableArray.js.map +1 -1
  196. package/lib/cjs/numerics/Complex.js.map +1 -1
  197. package/lib/cjs/numerics/ConvexPolygon2d.js.map +1 -1
  198. package/lib/cjs/numerics/Newton.js.map +1 -1
  199. package/lib/cjs/numerics/PascalCoefficients.js.map +1 -1
  200. package/lib/cjs/numerics/PolarData.js.map +1 -1
  201. package/lib/cjs/numerics/Polynomials.d.ts +13 -1
  202. package/lib/cjs/numerics/Polynomials.d.ts.map +1 -1
  203. package/lib/cjs/numerics/Polynomials.js +13 -1
  204. package/lib/cjs/numerics/Polynomials.js.map +1 -1
  205. package/lib/cjs/numerics/Quadrature.js.map +1 -1
  206. package/lib/cjs/numerics/Range1dArray.js.map +1 -1
  207. package/lib/cjs/numerics/TriDiagonalSystem.js.map +1 -1
  208. package/lib/cjs/numerics/UnionFind.js.map +1 -1
  209. package/lib/cjs/numerics/UsageSums.js.map +1 -1
  210. package/lib/cjs/polyface/AuxData.js.map +1 -1
  211. package/lib/cjs/polyface/BoxTopology.js.map +1 -1
  212. package/lib/cjs/polyface/FacetFaceData.js.map +1 -1
  213. package/lib/cjs/polyface/FacetLocationDetail.d.ts +28 -5
  214. package/lib/cjs/polyface/FacetLocationDetail.d.ts.map +1 -1
  215. package/lib/cjs/polyface/FacetLocationDetail.js +50 -15
  216. package/lib/cjs/polyface/FacetLocationDetail.js.map +1 -1
  217. package/lib/cjs/polyface/FacetOrientation.js.map +1 -1
  218. package/lib/cjs/polyface/GreedyTriangulationBetweenLineStrings.js.map +1 -1
  219. package/lib/cjs/polyface/IndexedEdgeMatcher.js.map +1 -1
  220. package/lib/cjs/polyface/IndexedPolyfaceVisitor.js.map +1 -1
  221. package/lib/cjs/polyface/Polyface.d.ts +1 -1
  222. package/lib/cjs/polyface/Polyface.d.ts.map +1 -1
  223. package/lib/cjs/polyface/Polyface.js.map +1 -1
  224. package/lib/cjs/polyface/PolyfaceBuilder.js.map +1 -1
  225. package/lib/cjs/polyface/PolyfaceClip.js.map +1 -1
  226. package/lib/cjs/polyface/PolyfaceData.js.map +1 -1
  227. package/lib/cjs/polyface/PolyfaceQuery.d.ts +7 -3
  228. package/lib/cjs/polyface/PolyfaceQuery.d.ts.map +1 -1
  229. package/lib/cjs/polyface/PolyfaceQuery.js +23 -0
  230. package/lib/cjs/polyface/PolyfaceQuery.js.map +1 -1
  231. package/lib/cjs/polyface/RangeLengthData.js.map +1 -1
  232. package/lib/cjs/polyface/RangeTree/LineString3dRangeTreeContext.d.ts +52 -0
  233. package/lib/cjs/polyface/RangeTree/LineString3dRangeTreeContext.d.ts.map +1 -0
  234. package/lib/cjs/polyface/RangeTree/LineString3dRangeTreeContext.js +78 -0
  235. package/lib/cjs/polyface/RangeTree/LineString3dRangeTreeContext.js.map +1 -0
  236. package/lib/cjs/polyface/RangeTree/MinimumValueTester.d.ts +60 -0
  237. package/lib/cjs/polyface/RangeTree/MinimumValueTester.d.ts.map +1 -0
  238. package/lib/cjs/polyface/RangeTree/MinimumValueTester.js +96 -0
  239. package/lib/cjs/polyface/RangeTree/MinimumValueTester.js.map +1 -0
  240. package/lib/cjs/polyface/RangeTree/Point3dArrayRangeTreeContext.d.ts +57 -0
  241. package/lib/cjs/polyface/RangeTree/Point3dArrayRangeTreeContext.d.ts.map +1 -0
  242. package/lib/cjs/polyface/RangeTree/Point3dArrayRangeTreeContext.js +73 -0
  243. package/lib/cjs/polyface/RangeTree/Point3dArrayRangeTreeContext.js.map +1 -0
  244. package/lib/cjs/polyface/RangeTree/PolyfaceRangeTreeContext.d.ts +57 -0
  245. package/lib/cjs/polyface/RangeTree/PolyfaceRangeTreeContext.d.ts.map +1 -0
  246. package/lib/cjs/polyface/RangeTree/PolyfaceRangeTreeContext.js +84 -0
  247. package/lib/cjs/polyface/RangeTree/PolyfaceRangeTreeContext.js.map +1 -0
  248. package/lib/cjs/polyface/RangeTree/RangeTreeNode.d.ts +274 -0
  249. package/lib/cjs/polyface/RangeTree/RangeTreeNode.d.ts.map +1 -0
  250. package/lib/cjs/polyface/RangeTree/RangeTreeNode.js +505 -0
  251. package/lib/cjs/polyface/RangeTree/RangeTreeNode.js.map +1 -0
  252. package/lib/cjs/polyface/RangeTree/RangeTreeSearchHandlers.d.ts +204 -0
  253. package/lib/cjs/polyface/RangeTree/RangeTreeSearchHandlers.d.ts.map +1 -0
  254. package/lib/cjs/polyface/RangeTree/RangeTreeSearchHandlers.js +383 -0
  255. package/lib/cjs/polyface/RangeTree/RangeTreeSearchHandlers.js.map +1 -0
  256. package/lib/cjs/polyface/TaggedNumericData.js.map +1 -1
  257. package/lib/cjs/polyface/TriangleCandidate.js.map +1 -1
  258. package/lib/cjs/polyface/multiclip/BuildAverageNormalsContext.js.map +1 -1
  259. package/lib/cjs/polyface/multiclip/GriddedRaggedRange2dSet.js.map +1 -1
  260. package/lib/cjs/polyface/multiclip/GriddedRaggedRange2dSetWithOverflow.js.map +1 -1
  261. package/lib/cjs/polyface/multiclip/LinearSearchRange2dArray.js.map +1 -1
  262. package/lib/cjs/polyface/multiclip/OffsetMeshContext.js.map +1 -1
  263. package/lib/cjs/polyface/multiclip/Range2dSearchInterface.js.map +1 -1
  264. package/lib/cjs/polyface/multiclip/RangeSearch.js.map +1 -1
  265. package/lib/cjs/polyface/multiclip/SweepLineStringToFacetContext.js.map +1 -1
  266. package/lib/cjs/polyface/multiclip/XYPointBuckets.js.map +1 -1
  267. package/lib/cjs/serialization/BGFBAccessors.js.map +1 -1
  268. package/lib/cjs/serialization/BGFBReader.js.map +1 -1
  269. package/lib/cjs/serialization/BGFBWriter.js.map +1 -1
  270. package/lib/cjs/serialization/BentleyGeometryFlatBuffer.js.map +1 -1
  271. package/lib/cjs/serialization/DeepCompare.js.map +1 -1
  272. package/lib/cjs/serialization/GeometrySamples.d.ts +36 -3
  273. package/lib/cjs/serialization/GeometrySamples.d.ts.map +1 -1
  274. package/lib/cjs/serialization/GeometrySamples.js +93 -4
  275. package/lib/cjs/serialization/GeometrySamples.js.map +1 -1
  276. package/lib/cjs/serialization/IModelJsonSchema.js.map +1 -1
  277. package/lib/cjs/serialization/SerializationHelpers.js.map +1 -1
  278. package/lib/cjs/solid/Box.js.map +1 -1
  279. package/lib/cjs/solid/Cone.js.map +1 -1
  280. package/lib/cjs/solid/LinearSweep.d.ts +1 -1
  281. package/lib/cjs/solid/LinearSweep.js +1 -1
  282. package/lib/cjs/solid/LinearSweep.js.map +1 -1
  283. package/lib/cjs/solid/RotationalSweep.js.map +1 -1
  284. package/lib/cjs/solid/RuledSweep.js.map +1 -1
  285. package/lib/cjs/solid/SolidPrimitive.js.map +1 -1
  286. package/lib/cjs/solid/Sphere.js.map +1 -1
  287. package/lib/cjs/solid/SweepContour.d.ts +2 -2
  288. package/lib/cjs/solid/SweepContour.d.ts.map +1 -1
  289. package/lib/cjs/solid/SweepContour.js.map +1 -1
  290. package/lib/cjs/solid/TorusPipe.js.map +1 -1
  291. package/lib/cjs/topology/ChainMerge.js.map +1 -1
  292. package/lib/cjs/topology/Graph.d.ts +5 -6
  293. package/lib/cjs/topology/Graph.d.ts.map +1 -1
  294. package/lib/cjs/topology/Graph.js +7 -6
  295. package/lib/cjs/topology/Graph.js.map +1 -1
  296. package/lib/cjs/topology/HalfEdgeGraphFromIndexedLoopsContext.d.ts +4 -4
  297. package/lib/cjs/topology/HalfEdgeGraphFromIndexedLoopsContext.js +5 -5
  298. package/lib/cjs/topology/HalfEdgeGraphFromIndexedLoopsContext.js.map +1 -1
  299. package/lib/cjs/topology/HalfEdgeGraphSearch.d.ts +108 -71
  300. package/lib/cjs/topology/HalfEdgeGraphSearch.d.ts.map +1 -1
  301. package/lib/cjs/topology/HalfEdgeGraphSearch.js +223 -109
  302. package/lib/cjs/topology/HalfEdgeGraphSearch.js.map +1 -1
  303. package/lib/cjs/topology/HalfEdgeGraphSpineContext.js.map +1 -1
  304. package/lib/cjs/topology/HalfEdgeGraphValidation.js.map +1 -1
  305. package/lib/cjs/topology/HalfEdgeMarkSet.js.map +1 -1
  306. package/lib/cjs/topology/HalfEdgeNodeXYZUV.js.map +1 -1
  307. package/lib/cjs/topology/HalfEdgePointInGraphSearch.js.map +1 -1
  308. package/lib/cjs/topology/HalfEdgePositionDetail.js.map +1 -1
  309. package/lib/cjs/topology/HalfEdgePriorityQueue.js.map +1 -1
  310. package/lib/cjs/topology/InsertAndRetriangulateContext.js.map +1 -1
  311. package/lib/cjs/topology/MaskManager.js.map +1 -1
  312. package/lib/cjs/topology/Merging.d.ts +1 -1
  313. package/lib/cjs/topology/Merging.d.ts.map +1 -1
  314. package/lib/cjs/topology/Merging.js.map +1 -1
  315. package/lib/cjs/topology/RegularizeFace.js.map +1 -1
  316. package/lib/cjs/topology/SignedDataSummary.d.ts +13 -13
  317. package/lib/cjs/topology/SignedDataSummary.d.ts.map +1 -1
  318. package/lib/cjs/topology/SignedDataSummary.js +3 -3
  319. package/lib/cjs/topology/SignedDataSummary.js.map +1 -1
  320. package/lib/cjs/topology/SpaceTriangulation.js.map +1 -1
  321. package/lib/cjs/topology/Triangulation.d.ts +1 -12
  322. package/lib/cjs/topology/Triangulation.d.ts.map +1 -1
  323. package/lib/cjs/topology/Triangulation.js.map +1 -1
  324. package/lib/cjs/topology/XYParitySearchContext.d.ts +27 -21
  325. package/lib/cjs/topology/XYParitySearchContext.d.ts.map +1 -1
  326. package/lib/cjs/topology/XYParitySearchContext.js +73 -71
  327. package/lib/cjs/topology/XYParitySearchContext.js.map +1 -1
  328. package/lib/esm/Constant.js.map +1 -1
  329. package/lib/esm/Geometry.d.ts +17 -0
  330. package/lib/esm/Geometry.d.ts.map +1 -1
  331. package/lib/esm/Geometry.js +14 -0
  332. package/lib/esm/Geometry.js.map +1 -1
  333. package/lib/esm/bspline/AkimaCurve3d.js.map +1 -1
  334. package/lib/esm/bspline/BSpline1dNd.js.map +1 -1
  335. package/lib/esm/bspline/BSplineCurve.js.map +1 -1
  336. package/lib/esm/bspline/BSplineCurve3dH.js.map +1 -1
  337. package/lib/esm/bspline/BSplineCurveOps.js.map +1 -1
  338. package/lib/esm/bspline/BSplineSurface.js.map +1 -1
  339. package/lib/esm/bspline/Bezier1dNd.js.map +1 -1
  340. package/lib/esm/bspline/BezierCurve3d.js.map +1 -1
  341. package/lib/esm/bspline/BezierCurve3dH.js.map +1 -1
  342. package/lib/esm/bspline/BezierCurveBase.js.map +1 -1
  343. package/lib/esm/bspline/InterpolationCurve3d.js.map +1 -1
  344. package/lib/esm/bspline/KnotVector.js.map +1 -1
  345. package/lib/esm/bspline/SurfaceLocationDetail.js.map +1 -1
  346. package/lib/esm/clipping/AlternatingConvexClipTree.js.map +1 -1
  347. package/lib/esm/clipping/BooleanClipFactory.js.map +1 -1
  348. package/lib/esm/clipping/BooleanClipNode.js.map +1 -1
  349. package/lib/esm/clipping/ClipPlane.js.map +1 -1
  350. package/lib/esm/clipping/ClipPrimitive.js.map +1 -1
  351. package/lib/esm/clipping/ClipUtils.js.map +1 -1
  352. package/lib/esm/clipping/ClipVector.js.map +1 -1
  353. package/lib/esm/clipping/ConvexClipPlaneSet.js.map +1 -1
  354. package/lib/esm/clipping/UnionOfConvexClipPlaneSets.js.map +1 -1
  355. package/lib/esm/clipping/internalContexts/LineStringOffsetClipperContext.js.map +1 -1
  356. package/lib/esm/core-geometry.d.ts +3 -2
  357. package/lib/esm/core-geometry.d.ts.map +1 -1
  358. package/lib/esm/core-geometry.js +3 -2
  359. package/lib/esm/core-geometry.js.map +1 -1
  360. package/lib/esm/curve/Arc3d.js.map +1 -1
  361. package/lib/esm/curve/ConstructCurveBetweenCurves.js.map +1 -1
  362. package/lib/esm/curve/CoordinateXYZ.js.map +1 -1
  363. package/lib/esm/curve/CurveChainWithDistanceIndex.d.ts +2 -2
  364. package/lib/esm/curve/CurveChainWithDistanceIndex.js +3 -3
  365. package/lib/esm/curve/CurveChainWithDistanceIndex.js.map +1 -1
  366. package/lib/esm/curve/CurveCollection.js.map +1 -1
  367. package/lib/esm/curve/CurveCurve.js.map +1 -1
  368. package/lib/esm/curve/CurveExtendMode.d.ts +7 -6
  369. package/lib/esm/curve/CurveExtendMode.d.ts.map +1 -1
  370. package/lib/esm/curve/CurveExtendMode.js +7 -6
  371. package/lib/esm/curve/CurveExtendMode.js.map +1 -1
  372. package/lib/esm/curve/CurveFactory.js.map +1 -1
  373. package/lib/esm/curve/CurveLocationDetail.d.ts.map +1 -1
  374. package/lib/esm/curve/CurveLocationDetail.js +23 -18
  375. package/lib/esm/curve/CurveLocationDetail.js.map +1 -1
  376. package/lib/esm/curve/CurveOps.js.map +1 -1
  377. package/lib/esm/curve/CurvePrimitive.js.map +1 -1
  378. package/lib/esm/curve/CurveProcessor.js.map +1 -1
  379. package/lib/esm/curve/CurveTypes.js.map +1 -1
  380. package/lib/esm/curve/CurveWireMomentsXYZ.js.map +1 -1
  381. package/lib/esm/curve/GeometryQuery.js.map +1 -1
  382. package/lib/esm/curve/LineSegment3d.d.ts +14 -4
  383. package/lib/esm/curve/LineSegment3d.d.ts.map +1 -1
  384. package/lib/esm/curve/LineSegment3d.js +108 -3
  385. package/lib/esm/curve/LineSegment3d.js.map +1 -1
  386. package/lib/esm/curve/LineString3d.d.ts +41 -8
  387. package/lib/esm/curve/LineString3d.d.ts.map +1 -1
  388. package/lib/esm/curve/LineString3d.js +53 -15
  389. package/lib/esm/curve/LineString3d.js.map +1 -1
  390. package/lib/esm/curve/Loop.js +1 -1
  391. package/lib/esm/curve/Loop.js.map +1 -1
  392. package/lib/esm/curve/OffsetOptions.js.map +1 -1
  393. package/lib/esm/curve/ParityRegion.js.map +1 -1
  394. package/lib/esm/curve/Path.js.map +1 -1
  395. package/lib/esm/curve/PointString3d.js.map +1 -1
  396. package/lib/esm/curve/ProxyCurve.js.map +1 -1
  397. package/lib/esm/curve/Query/ConsolidateAdjacentPrimitivesContext.js.map +1 -1
  398. package/lib/esm/curve/Query/CurveSplitContext.js.map +1 -1
  399. package/lib/esm/curve/Query/CylindricalRange.js.map +1 -1
  400. package/lib/esm/curve/Query/InOutTests.js.map +1 -1
  401. package/lib/esm/curve/Query/PlanarSubdivision.d.ts +2 -2
  402. package/lib/esm/curve/Query/PlanarSubdivision.js +2 -2
  403. package/lib/esm/curve/Query/PlanarSubdivision.js.map +1 -1
  404. package/lib/esm/curve/Query/StrokeCountChain.js.map +1 -1
  405. package/lib/esm/curve/Query/StrokeCountMap.js.map +1 -1
  406. package/lib/esm/curve/RegionMomentsXY.js.map +1 -1
  407. package/lib/esm/curve/RegionOps.d.ts +1 -2
  408. package/lib/esm/curve/RegionOps.d.ts.map +1 -1
  409. package/lib/esm/curve/RegionOps.js +1 -1
  410. package/lib/esm/curve/RegionOps.js.map +1 -1
  411. package/lib/esm/curve/RegionOpsClassificationSweeps.d.ts +5 -8
  412. package/lib/esm/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  413. package/lib/esm/curve/RegionOpsClassificationSweeps.js +12 -12
  414. package/lib/esm/curve/RegionOpsClassificationSweeps.js.map +1 -1
  415. package/lib/esm/curve/StrokeOptions.js.map +1 -1
  416. package/lib/esm/curve/UnionRegion.js.map +1 -1
  417. package/lib/esm/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.js.map +1 -1
  418. package/lib/esm/curve/internalContexts/ChainCollectorContext.js.map +1 -1
  419. package/lib/esm/curve/internalContexts/CloneCurvesContext.js.map +1 -1
  420. package/lib/esm/curve/internalContexts/CloneWithExpandedLineStrings.js.map +1 -1
  421. package/lib/esm/curve/internalContexts/ClosestPointStrokeHandler.js.map +1 -1
  422. package/lib/esm/curve/internalContexts/CountLinearPartsSearchContext.js.map +1 -1
  423. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -1
  424. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  425. package/lib/esm/curve/internalContexts/CurveCurveIntersectXYZ.js.map +1 -1
  426. package/lib/esm/curve/internalContexts/CurveLengthContext.js.map +1 -1
  427. package/lib/esm/curve/internalContexts/CurveOffsetXYHandler.js.map +1 -1
  428. package/lib/esm/curve/internalContexts/GapSearchContext.js.map +1 -1
  429. package/lib/esm/curve/internalContexts/MultiChainCollector.js.map +1 -1
  430. package/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js.map +1 -1
  431. package/lib/esm/curve/internalContexts/PlaneAltitudeRangeContext.js.map +1 -1
  432. package/lib/esm/curve/internalContexts/PolygonOffsetContext.js.map +1 -1
  433. package/lib/esm/curve/internalContexts/SumLengthsContext.js.map +1 -1
  434. package/lib/esm/curve/internalContexts/TransformInPlaceContext.js.map +1 -1
  435. package/lib/esm/curve/spiral/AustralianRailCorpXYEvaluator.js.map +1 -1
  436. package/lib/esm/curve/spiral/ClothoidSeries.js.map +1 -1
  437. package/lib/esm/curve/spiral/CubicEvaluator.js.map +1 -1
  438. package/lib/esm/curve/spiral/CzechSpiralEvaluator.js.map +1 -1
  439. package/lib/esm/curve/spiral/DirectHalfCosineSpiralEvaluator.js.map +1 -1
  440. package/lib/esm/curve/spiral/DirectSpiral3d.js.map +1 -1
  441. package/lib/esm/curve/spiral/IntegratedSpiral3d.js.map +1 -1
  442. package/lib/esm/curve/spiral/MXCubicAlongArcSpiralEvaluator.js.map +1 -1
  443. package/lib/esm/curve/spiral/NormalizedTransition.js.map +1 -1
  444. package/lib/esm/curve/spiral/PolishCubicSpiralEvaluator.js.map +1 -1
  445. package/lib/esm/curve/spiral/TransitionConditionalProperties.js.map +1 -1
  446. package/lib/esm/curve/spiral/TransitionSpiral3d.js.map +1 -1
  447. package/lib/esm/curve/spiral/XYCurveEvaluator.js.map +1 -1
  448. package/lib/esm/geometry3d/Angle.js.map +1 -1
  449. package/lib/esm/geometry3d/AngleSweep.js.map +1 -1
  450. package/lib/esm/geometry3d/BarycentricTriangle.js.map +1 -1
  451. package/lib/esm/geometry3d/BilinearPatch.js.map +1 -1
  452. package/lib/esm/geometry3d/CoincidentGeometryOps.js.map +1 -1
  453. package/lib/esm/geometry3d/Ellipsoid.js.map +1 -1
  454. package/lib/esm/geometry3d/FrameBuilder.js.map +1 -1
  455. package/lib/esm/geometry3d/FrustumAnimation.js.map +1 -1
  456. package/lib/esm/geometry3d/GeometryHandler.js.map +1 -1
  457. package/lib/esm/geometry3d/GrowableBlockedArray.js.map +1 -1
  458. package/lib/esm/geometry3d/GrowableFloat64Array.js.map +1 -1
  459. package/lib/esm/geometry3d/GrowableXYArray.d.ts +2 -2
  460. package/lib/esm/geometry3d/GrowableXYArray.d.ts.map +1 -1
  461. package/lib/esm/geometry3d/GrowableXYArray.js +1 -1
  462. package/lib/esm/geometry3d/GrowableXYArray.js.map +1 -1
  463. package/lib/esm/geometry3d/GrowableXYZArray.d.ts +2 -3
  464. package/lib/esm/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  465. package/lib/esm/geometry3d/GrowableXYZArray.js +1 -1
  466. package/lib/esm/geometry3d/GrowableXYZArray.js.map +1 -1
  467. package/lib/esm/geometry3d/IndexedCollectionInterval.js.map +1 -1
  468. package/lib/esm/geometry3d/IndexedXYCollection.js.map +1 -1
  469. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts +18 -1
  470. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  471. package/lib/esm/geometry3d/IndexedXYZCollection.js +13 -0
  472. package/lib/esm/geometry3d/IndexedXYZCollection.js.map +1 -1
  473. package/lib/esm/geometry3d/LongitudeLatitudeAltitude.js.map +1 -1
  474. package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
  475. package/lib/esm/geometry3d/OrderedRotationAngles.js.map +1 -1
  476. package/lib/esm/geometry3d/Plane3d.js.map +1 -1
  477. package/lib/esm/geometry3d/Plane3dByOriginAndUnitNormal.js.map +1 -1
  478. package/lib/esm/geometry3d/Plane3dByOriginAndVectors.js.map +1 -1
  479. package/lib/esm/geometry3d/Point2dArrayCarrier.js.map +1 -1
  480. package/lib/esm/geometry3d/Point2dVector2d.js.map +1 -1
  481. package/lib/esm/geometry3d/Point3dArrayCarrier.js.map +1 -1
  482. package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
  483. package/lib/esm/geometry3d/PointHelpers.d.ts +1 -2
  484. package/lib/esm/geometry3d/PointHelpers.d.ts.map +1 -1
  485. package/lib/esm/geometry3d/PointHelpers.js.map +1 -1
  486. package/lib/esm/geometry3d/PointStreaming.d.ts +1 -1
  487. package/lib/esm/geometry3d/PointStreaming.d.ts.map +1 -1
  488. package/lib/esm/geometry3d/PointStreaming.js +3 -1
  489. package/lib/esm/geometry3d/PointStreaming.js.map +1 -1
  490. package/lib/esm/geometry3d/PolygonOps.d.ts +68 -1
  491. package/lib/esm/geometry3d/PolygonOps.d.ts.map +1 -1
  492. package/lib/esm/geometry3d/PolygonOps.js +150 -3
  493. package/lib/esm/geometry3d/PolygonOps.js.map +1 -1
  494. package/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js.map +1 -1
  495. package/lib/esm/geometry3d/PolylineOps.d.ts +23 -1
  496. package/lib/esm/geometry3d/PolylineOps.d.ts.map +1 -1
  497. package/lib/esm/geometry3d/PolylineOps.js +73 -1
  498. package/lib/esm/geometry3d/PolylineOps.js.map +1 -1
  499. package/lib/esm/geometry3d/Range.d.ts +1 -1
  500. package/lib/esm/geometry3d/Range.d.ts.map +1 -1
  501. package/lib/esm/geometry3d/Range.js.map +1 -1
  502. package/lib/esm/geometry3d/Ray2d.js.map +1 -1
  503. package/lib/esm/geometry3d/Ray3d.js.map +1 -1
  504. package/lib/esm/geometry3d/ReusableObjectCache.js.map +1 -1
  505. package/lib/esm/geometry3d/Segment1d.js.map +1 -1
  506. package/lib/esm/geometry3d/SortablePolygon.js.map +1 -1
  507. package/lib/esm/geometry3d/Transform.js +1 -1
  508. package/lib/esm/geometry3d/Transform.js.map +1 -1
  509. package/lib/esm/geometry3d/UVSurfaceOps.js.map +1 -1
  510. package/lib/esm/geometry3d/XYZProps.js.map +1 -1
  511. package/lib/esm/geometry3d/YawPitchRollAngles.d.ts +7 -5
  512. package/lib/esm/geometry3d/YawPitchRollAngles.d.ts.map +1 -1
  513. package/lib/esm/geometry3d/YawPitchRollAngles.js +8 -6
  514. package/lib/esm/geometry3d/YawPitchRollAngles.js.map +1 -1
  515. package/lib/esm/geometry4d/Map4d.js.map +1 -1
  516. package/lib/esm/geometry4d/Matrix4d.js.map +1 -1
  517. package/lib/esm/geometry4d/MomentData.js.map +1 -1
  518. package/lib/esm/geometry4d/PlaneByOriginAndVectors4d.js.map +1 -1
  519. package/lib/esm/geometry4d/Point4d.js.map +1 -1
  520. package/lib/esm/numerics/BandedSystem.js.map +1 -1
  521. package/lib/esm/numerics/BezierPolynomials.js.map +1 -1
  522. package/lib/esm/numerics/ClusterableArray.js.map +1 -1
  523. package/lib/esm/numerics/Complex.js.map +1 -1
  524. package/lib/esm/numerics/ConvexPolygon2d.js.map +1 -1
  525. package/lib/esm/numerics/Newton.js.map +1 -1
  526. package/lib/esm/numerics/PascalCoefficients.js.map +1 -1
  527. package/lib/esm/numerics/PolarData.js.map +1 -1
  528. package/lib/esm/numerics/Polynomials.d.ts +13 -1
  529. package/lib/esm/numerics/Polynomials.d.ts.map +1 -1
  530. package/lib/esm/numerics/Polynomials.js +13 -1
  531. package/lib/esm/numerics/Polynomials.js.map +1 -1
  532. package/lib/esm/numerics/Quadrature.js.map +1 -1
  533. package/lib/esm/numerics/Range1dArray.js.map +1 -1
  534. package/lib/esm/numerics/TriDiagonalSystem.js.map +1 -1
  535. package/lib/esm/numerics/UnionFind.js.map +1 -1
  536. package/lib/esm/numerics/UsageSums.js.map +1 -1
  537. package/lib/esm/polyface/AuxData.js.map +1 -1
  538. package/lib/esm/polyface/BoxTopology.js.map +1 -1
  539. package/lib/esm/polyface/FacetFaceData.js.map +1 -1
  540. package/lib/esm/polyface/FacetLocationDetail.d.ts +28 -5
  541. package/lib/esm/polyface/FacetLocationDetail.d.ts.map +1 -1
  542. package/lib/esm/polyface/FacetLocationDetail.js +48 -14
  543. package/lib/esm/polyface/FacetLocationDetail.js.map +1 -1
  544. package/lib/esm/polyface/FacetOrientation.js.map +1 -1
  545. package/lib/esm/polyface/GreedyTriangulationBetweenLineStrings.js.map +1 -1
  546. package/lib/esm/polyface/IndexedEdgeMatcher.js.map +1 -1
  547. package/lib/esm/polyface/IndexedPolyfaceVisitor.js.map +1 -1
  548. package/lib/esm/polyface/Polyface.d.ts +1 -1
  549. package/lib/esm/polyface/Polyface.d.ts.map +1 -1
  550. package/lib/esm/polyface/Polyface.js.map +1 -1
  551. package/lib/esm/polyface/PolyfaceBuilder.js.map +1 -1
  552. package/lib/esm/polyface/PolyfaceClip.js.map +1 -1
  553. package/lib/esm/polyface/PolyfaceData.js.map +1 -1
  554. package/lib/esm/polyface/PolyfaceQuery.d.ts +7 -3
  555. package/lib/esm/polyface/PolyfaceQuery.d.ts.map +1 -1
  556. package/lib/esm/polyface/PolyfaceQuery.js +23 -0
  557. package/lib/esm/polyface/PolyfaceQuery.js.map +1 -1
  558. package/lib/esm/polyface/RangeLengthData.js.map +1 -1
  559. package/lib/esm/polyface/RangeTree/LineString3dRangeTreeContext.d.ts +52 -0
  560. package/lib/esm/polyface/RangeTree/LineString3dRangeTreeContext.d.ts.map +1 -0
  561. package/lib/esm/polyface/RangeTree/LineString3dRangeTreeContext.js +74 -0
  562. package/lib/esm/polyface/RangeTree/LineString3dRangeTreeContext.js.map +1 -0
  563. package/lib/esm/polyface/RangeTree/MinimumValueTester.d.ts +60 -0
  564. package/lib/esm/polyface/RangeTree/MinimumValueTester.d.ts.map +1 -0
  565. package/lib/esm/polyface/RangeTree/MinimumValueTester.js +92 -0
  566. package/lib/esm/polyface/RangeTree/MinimumValueTester.js.map +1 -0
  567. package/lib/esm/polyface/RangeTree/Point3dArrayRangeTreeContext.d.ts +57 -0
  568. package/lib/esm/polyface/RangeTree/Point3dArrayRangeTreeContext.d.ts.map +1 -0
  569. package/lib/esm/polyface/RangeTree/Point3dArrayRangeTreeContext.js +69 -0
  570. package/lib/esm/polyface/RangeTree/Point3dArrayRangeTreeContext.js.map +1 -0
  571. package/lib/esm/polyface/RangeTree/PolyfaceRangeTreeContext.d.ts +57 -0
  572. package/lib/esm/polyface/RangeTree/PolyfaceRangeTreeContext.d.ts.map +1 -0
  573. package/lib/esm/polyface/RangeTree/PolyfaceRangeTreeContext.js +80 -0
  574. package/lib/esm/polyface/RangeTree/PolyfaceRangeTreeContext.js.map +1 -0
  575. package/lib/esm/polyface/RangeTree/RangeTreeNode.d.ts +274 -0
  576. package/lib/esm/polyface/RangeTree/RangeTreeNode.d.ts.map +1 -0
  577. package/lib/esm/polyface/RangeTree/RangeTreeNode.js +497 -0
  578. package/lib/esm/polyface/RangeTree/RangeTreeNode.js.map +1 -0
  579. package/lib/esm/polyface/RangeTree/RangeTreeSearchHandlers.d.ts +204 -0
  580. package/lib/esm/polyface/RangeTree/RangeTreeSearchHandlers.d.ts.map +1 -0
  581. package/lib/esm/polyface/RangeTree/RangeTreeSearchHandlers.js +374 -0
  582. package/lib/esm/polyface/RangeTree/RangeTreeSearchHandlers.js.map +1 -0
  583. package/lib/esm/polyface/TaggedNumericData.js.map +1 -1
  584. package/lib/esm/polyface/TriangleCandidate.js.map +1 -1
  585. package/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js.map +1 -1
  586. package/lib/esm/polyface/multiclip/GriddedRaggedRange2dSet.js.map +1 -1
  587. package/lib/esm/polyface/multiclip/GriddedRaggedRange2dSetWithOverflow.js.map +1 -1
  588. package/lib/esm/polyface/multiclip/LinearSearchRange2dArray.js.map +1 -1
  589. package/lib/esm/polyface/multiclip/OffsetMeshContext.js.map +1 -1
  590. package/lib/esm/polyface/multiclip/Range2dSearchInterface.js.map +1 -1
  591. package/lib/esm/polyface/multiclip/RangeSearch.js.map +1 -1
  592. package/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js.map +1 -1
  593. package/lib/esm/polyface/multiclip/XYPointBuckets.js.map +1 -1
  594. package/lib/esm/serialization/BGFBAccessors.js.map +1 -1
  595. package/lib/esm/serialization/BGFBReader.js.map +1 -1
  596. package/lib/esm/serialization/BGFBWriter.js.map +1 -1
  597. package/lib/esm/serialization/BentleyGeometryFlatBuffer.js.map +1 -1
  598. package/lib/esm/serialization/DeepCompare.js.map +1 -1
  599. package/lib/esm/serialization/GeometrySamples.d.ts +36 -3
  600. package/lib/esm/serialization/GeometrySamples.d.ts.map +1 -1
  601. package/lib/esm/serialization/GeometrySamples.js +93 -4
  602. package/lib/esm/serialization/GeometrySamples.js.map +1 -1
  603. package/lib/esm/serialization/IModelJsonSchema.js.map +1 -1
  604. package/lib/esm/serialization/SerializationHelpers.js.map +1 -1
  605. package/lib/esm/solid/Box.js.map +1 -1
  606. package/lib/esm/solid/Cone.js.map +1 -1
  607. package/lib/esm/solid/LinearSweep.d.ts +1 -1
  608. package/lib/esm/solid/LinearSweep.js +1 -1
  609. package/lib/esm/solid/LinearSweep.js.map +1 -1
  610. package/lib/esm/solid/RotationalSweep.js.map +1 -1
  611. package/lib/esm/solid/RuledSweep.js.map +1 -1
  612. package/lib/esm/solid/SolidPrimitive.js.map +1 -1
  613. package/lib/esm/solid/Sphere.js.map +1 -1
  614. package/lib/esm/solid/SweepContour.d.ts +2 -2
  615. package/lib/esm/solid/SweepContour.d.ts.map +1 -1
  616. package/lib/esm/solid/SweepContour.js.map +1 -1
  617. package/lib/esm/solid/TorusPipe.js.map +1 -1
  618. package/lib/esm/topology/ChainMerge.js.map +1 -1
  619. package/lib/esm/topology/Graph.d.ts +5 -6
  620. package/lib/esm/topology/Graph.d.ts.map +1 -1
  621. package/lib/esm/topology/Graph.js +7 -6
  622. package/lib/esm/topology/Graph.js.map +1 -1
  623. package/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.d.ts +4 -4
  624. package/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js +5 -5
  625. package/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js.map +1 -1
  626. package/lib/esm/topology/HalfEdgeGraphSearch.d.ts +108 -71
  627. package/lib/esm/topology/HalfEdgeGraphSearch.d.ts.map +1 -1
  628. package/lib/esm/topology/HalfEdgeGraphSearch.js +223 -109
  629. package/lib/esm/topology/HalfEdgeGraphSearch.js.map +1 -1
  630. package/lib/esm/topology/HalfEdgeGraphSpineContext.js.map +1 -1
  631. package/lib/esm/topology/HalfEdgeGraphValidation.js.map +1 -1
  632. package/lib/esm/topology/HalfEdgeMarkSet.js.map +1 -1
  633. package/lib/esm/topology/HalfEdgeNodeXYZUV.js.map +1 -1
  634. package/lib/esm/topology/HalfEdgePointInGraphSearch.js.map +1 -1
  635. package/lib/esm/topology/HalfEdgePositionDetail.js.map +1 -1
  636. package/lib/esm/topology/HalfEdgePriorityQueue.js.map +1 -1
  637. package/lib/esm/topology/InsertAndRetriangulateContext.js.map +1 -1
  638. package/lib/esm/topology/MaskManager.js.map +1 -1
  639. package/lib/esm/topology/Merging.d.ts +1 -1
  640. package/lib/esm/topology/Merging.d.ts.map +1 -1
  641. package/lib/esm/topology/Merging.js.map +1 -1
  642. package/lib/esm/topology/RegularizeFace.js.map +1 -1
  643. package/lib/esm/topology/SignedDataSummary.d.ts +13 -13
  644. package/lib/esm/topology/SignedDataSummary.d.ts.map +1 -1
  645. package/lib/esm/topology/SignedDataSummary.js +3 -3
  646. package/lib/esm/topology/SignedDataSummary.js.map +1 -1
  647. package/lib/esm/topology/SpaceTriangulation.js.map +1 -1
  648. package/lib/esm/topology/Triangulation.d.ts +1 -12
  649. package/lib/esm/topology/Triangulation.d.ts.map +1 -1
  650. package/lib/esm/topology/Triangulation.js.map +1 -1
  651. package/lib/esm/topology/XYParitySearchContext.d.ts +27 -21
  652. package/lib/esm/topology/XYParitySearchContext.d.ts.map +1 -1
  653. package/lib/esm/topology/XYParitySearchContext.js +73 -71
  654. package/lib/esm/topology/XYParitySearchContext.js.map +1 -1
  655. package/package.json +3 -3
@@ -8,14 +8,17 @@ exports.HalfEdgeGraphSearch = exports.HalfEdgeMaskTester = void 0;
8
8
  /** @packageDocumentation
9
9
  * @module Topology
10
10
  */
11
+ const Range_1 = require("../geometry3d/Range");
11
12
  const Graph_1 = require("./Graph");
12
13
  const SignedDataSummary_1 = require("./SignedDataSummary");
13
14
  const XYParitySearchContext_1 = require("./XYParitySearchContext");
14
15
  /**
16
+ * Class to test match of half edge mask.
17
+ * @internal
15
18
  */
16
19
  class HalfEdgeMaskTester {
17
20
  /**
18
- *
21
+ * Constructor
19
22
  * @param mask mask to test in `testEdge` function
20
23
  * @param targetValue value to match for true return
21
24
  */
@@ -23,48 +26,31 @@ class HalfEdgeMaskTester {
23
26
  this._targetMask = mask;
24
27
  this._targetValue = targetValue;
25
28
  }
26
- /** Return true if the value of the targetMask matches the targetValue */
29
+ /** Return true if the value of the targetMask matches the targetValue. */
27
30
  testEdge(edge) {
28
31
  return edge.isMaskSet(this._targetMask) === this._targetValue;
29
32
  }
30
33
  }
31
34
  exports.HalfEdgeMaskTester = HalfEdgeMaskTester;
32
- // Search services for HalfEdgeGraph
35
+ /**
36
+ * Class for different types of searches for HalfEdgeGraph.
37
+ * @internal
38
+ */
33
39
  class HalfEdgeGraphSearch {
34
40
  /**
35
- * * for each node of face, set the mask push to allNodesStack
36
- * * push the faceSeed on onePerFaceStack[]
37
- */
38
- static pushAndMaskAllNodesInFace(faceSeed, mask, allNodeStack, onePerFaceStack) {
39
- onePerFaceStack.push(faceSeed);
40
- faceSeed.collectAroundFace((node) => {
41
- node.setMask(mask);
42
- allNodeStack.push(node);
43
- });
44
- }
45
- /**
46
- * Search an array of faceSeed nodes for the face with the most negative area.
47
- * @param oneCandidateNodePerFace array containing one node from each face to be considered.
48
- * @returns node on the minimum area face, or undefined if no such face (e.g., all faces have zero area).
49
- */
50
- static findMinimumAreaFace(oneCandidateNodePerFace, faceAreaFunction) {
51
- const summary = HalfEdgeGraphSearch.collectFaceAreaSummary(oneCandidateNodePerFace, false, faceAreaFunction);
52
- return summary.largestNegativeItem;
53
- }
54
- /**
55
- * static method for face area computation -- useful as function parameter in collect FaceAreaSummary.
56
- * * This simply calls `node.signedFaceArea ()`
41
+ * Static method for face area computation -- useful as function parameter in `collectFaceAreaSummary`.
42
+ * * This simply calls `node.signedFaceArea()`
57
43
  * @param node instance for signedFaceArea call.
58
44
  */
59
- static signedFaceArea(node) { return node.signedFaceArea(); }
45
+ static signedFaceArea(node) {
46
+ return node.signedFaceArea();
47
+ }
60
48
  /**
61
- *
62
- * Return a summary structure data about face (or other numeric quantity if the caller's areaFunction returns other value)
63
- * * The default areaFunction computes area of polygonal face.
49
+ * Return a summary of face data (e.g., area) as computed by the callback on the faces of the graph.
64
50
  * * Callers with curved edge graphs must supply their own area function.
65
- * @param source graph or array of nodes to examine
66
- * @param collectAllNodes flag to pass to the SignedDataSummary constructor to control collection of nodes.
67
- * @param areaFunction function to all to obtain area (or other numeric value)
51
+ * @param source graph or array of nodes to examine.
52
+ * @param collectAllNodes flag to pass to the `SignedDataSummary` constructor to control collection of nodes.
53
+ * @param areaFunction function to obtain area (or other numeric value). Default computes polygonal face area.
68
54
  */
69
55
  static collectFaceAreaSummary(source, collectAllNodes = false, areaFunction = (node) => HalfEdgeGraphSearch.signedFaceArea(node)) {
70
56
  const result = new SignedDataSummary_1.SignedDataSummary(collectAllNodes);
@@ -80,10 +66,19 @@ class HalfEdgeGraphSearch {
80
66
  return result;
81
67
  }
82
68
  /**
83
- * * Test if the graph is triangulated.
84
- * * Return false if:
85
- * * Positive area face with more than 3 edges
86
- * * more than 1 negative area face with `allowMultipleNegativeAreaFaces` false
69
+ * Search the graph for the face with the most negative area.
70
+ * @param oneCandidateNodePerFace graph or an array containing one node from each face to be considered.
71
+ * @returns node on the negative area face with largest absolute area, or `undefined` if no negative area face.
72
+ */
73
+ static findMinimumAreaFace(oneCandidateNodePerFace, faceAreaFunction) {
74
+ const summary = HalfEdgeGraphSearch.collectFaceAreaSummary(oneCandidateNodePerFace, false, faceAreaFunction);
75
+ return summary.largestNegativeItem;
76
+ }
77
+ /**
78
+ * Test if the graph is triangulated.
79
+ * * Return `false` if:
80
+ * * number of positive area faces with more than 3 edges is larger than `numPositiveExceptionsAllowed`.
81
+ * * graph has more than 1 negative area face when `allowMultipleNegativeAreaFaces` is `false`.
87
82
  * * 2-edge faces are ignored.
88
83
  */
89
84
  static isTriangulatedCCW(source, allowMultipleNegativeAreaFaces = true, numPositiveExceptionsAllowed = 0) {
@@ -117,24 +112,41 @@ class HalfEdgeGraphSearch {
117
112
  return true;
118
113
  }
119
114
  /**
120
- * Search to all accessible faces from given seed.
121
- * * The returned array contains one representative node in each face of the connected component.
122
- * * If (nonnull) parity mask is given, on return:
123
- * * It is entirely set or entirely clear around each face
124
- * * It is entirely set on all faces that are an even number of face-to-face steps away from the seed.
125
- * * It is entirely clear on all faces that are an odd number of face-to-face steps away from the seed.
126
- * @param seedEdge first edge to search.
115
+ * Process a face during graph traversal.
116
+ * @param faceSeed a node in the face.
117
+ * @param mask mask to set on each node of the face.
118
+ * @param allNodeStack array appended with each node of the face.
119
+ * @param onePerFaceStack array appended with `faceSeed`.
120
+ */
121
+ static pushAndMaskAllNodesInFace(faceSeed, mask, allNodeStack, onePerFaceStack) {
122
+ onePerFaceStack.push(faceSeed);
123
+ faceSeed.collectAroundFace((node) => {
124
+ node.setMask(mask);
125
+ allNodeStack.push(node);
126
+ });
127
+ }
128
+ /**
129
+ * Traverse (via Depth First Search) to all accessible faces from the given seed.
130
+ * @param faceSeed first node to start the traverse.
127
131
  * @param visitMask mask applied to all faces as visited.
128
- * @param parityMask mask to apply (a) to first face, (b) to faces with alternating parity during the search.
132
+ * @param parityEdgeTester function to test if an edge is adjacent to two faces of opposite parity, e.g., a boundary
133
+ * edge that separates an "interior" face and an "exterior" face. If `parityEdgeTester` is not supplied and `parityMask`
134
+ * is supplied, the default parity rule is to alternate parity state in a "bullseye" pattern starting at the seed face,
135
+ * with each successive concentric ring of faces at constant topological distance from the seed face receiving the
136
+ * opposite parity state of the previous ring.
137
+ * @param parityMask mask to apply to the first face and faces that share the same parity as the first face, as
138
+ * determined by the parity rule. If this is `NULL_MASK`, there is no record of parity. If (non-null) parity mask
139
+ * is given, on return it is entirely set or entirely clear around each face.
140
+ * @returns an array that contains one representative node in each face of the connected component.
129
141
  */
130
- static parityFloodFromSeed(seedEdge, visitMask, parityEdgeTester, parityMask) {
142
+ static parityFloodFromSeed(faceSeed, visitMask, parityEdgeTester, parityMask) {
131
143
  const faces = [];
132
- if (seedEdge.isMaskSet(visitMask))
133
- return faces; // empty
144
+ if (faceSeed.isMaskSet(visitMask))
145
+ return faces; // empty array
134
146
  const allMasks = parityMask | visitMask;
135
147
  const stack = [];
136
- // arbitrarily call the seed face exterior ... others will alternate as visited.
137
- HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(seedEdge, allMasks, stack, faces); // Start with exterior as mask
148
+ // the seed face is arbitrarily assigned the parity mask
149
+ HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(faceSeed, allMasks, stack, faces);
138
150
  while (stack.length > 0) {
139
151
  const p = stack.pop();
140
152
  const mate = p.edgeMate;
@@ -150,113 +162,216 @@ class HalfEdgeGraphSearch {
150
162
  return faces;
151
163
  }
152
164
  /**
153
- * * Search the given faces for the one with the minimum area.
154
- * * If the mask in that face is OFF, toggle it on (all half edges of) all the faces.
165
+ * * Correct the parity mask in the faces of a component.
166
+ * * It is assumed that the parity mask is applied _consistently_ throughout the supplied faces, but maybe
167
+ * not _correctly_.
168
+ * * A consistently applied parity mask is "correct" if it is set on the negative area ("exterior") face of
169
+ * a connected component.
170
+ * * This method finds a face with negative area and toggles the mask throughout the input faces if this face
171
+ * lacks the parity mask.
155
172
  * * In a properly merged planar subdivision there should be only one true negative area face per component.
156
- * @param graph parent graph
157
- * @param parityMask mask which was previously set with alternating parity, but with an arbitrary start face.
158
- * @param faces array of faces to search.
159
173
  */
160
- static correctParityInSingleComponent(_graph, mask, faces) {
174
+ static correctParityInSingleComponent(parityMask, faces) {
161
175
  const exteriorHalfEdge = HalfEdgeGraphSearch.findMinimumAreaFace(faces);
162
176
  if (!exteriorHalfEdge) {
177
+ // graph has all degenerate faces; do nothing
163
178
  }
164
- else if (exteriorHalfEdge.isMaskSet(mask)) {
165
- // all should be well .. nothing to do.
179
+ else if (exteriorHalfEdge.isMaskSet(parityMask)) {
180
+ // all should be well; nothing to do
166
181
  }
167
182
  else {
168
- // TOGGLE around the face (assuming all are consistent with the seed)
169
183
  for (const faceSeed of faces) {
170
- if (faceSeed.isMaskSet(mask)) {
171
- faceSeed.clearMaskAroundFace(mask);
184
+ if (faceSeed.isMaskSet(parityMask)) {
185
+ faceSeed.clearMaskAroundFace(parityMask);
172
186
  }
173
187
  else {
174
- faceSeed.setMaskAroundFace(mask);
188
+ faceSeed.setMaskAroundFace(parityMask);
175
189
  }
176
190
  }
177
191
  }
178
192
  }
179
- /** Apply correctParityInSingleComponent to each array in components. (Quick exit if mask in NULL_MASK) */
180
- static correctParityInComponentArrays(graph, mask, components) {
181
- if (mask === Graph_1.HalfEdgeMask.NULL_MASK)
193
+ /** Apply `correctParityInSingleComponent` to each array in components (quick exit if `parityMask` is `NULL_MASK`). */
194
+ static correctParityInComponentArrays(parityMask, components) {
195
+ if (parityMask === Graph_1.HalfEdgeMask.NULL_MASK)
182
196
  return;
183
197
  for (const facesInComponent of components)
184
- HalfEdgeGraphSearch.correctParityInSingleComponent(graph, mask, facesInComponent);
198
+ HalfEdgeGraphSearch.correctParityInSingleComponent(parityMask, facesInComponent);
185
199
  }
186
200
  /**
187
- * Collect arrays gathering faces by connected component.
188
- * @param graph graph to inspect
189
- * @param parityEdgeTester (optional) function to test if an edge is a parity change (e.g., a boundary edge).
190
- * @param parityMask (optional, along with parityEdgeTester) mask to apply indicating parity. If this is Mask.NULL_MASK, there is no record of parity.
201
+ * Collect connected components of the graph (via Depth First Search).
202
+ * @param graph graph to inspect.
203
+ * @param parityEdgeTester (optional) function to test if an edge is adjacent to two faces of opposite parity,
204
+ * e.g., a boundary edge that separates an "interior" face and an "exterior" face. If `parityEdgeTester` is not
205
+ * supplied and `parityMask` is supplied, the default parity rule is to alternate parity state in a "bullseye"
206
+ * pattern starting at the seed face, with each successive concentric ring of faces at constant topological
207
+ * distance from the seed face receiving the opposite parity state of the previous ring.
208
+ * @param parityMask (optional) mask to apply to the first face and faces that share the same parity as the
209
+ * first face, as determined by the parity rule. If this is `NULL_MASK`, there is no record of parity. If
210
+ * (non-null) parity mask is given, on return it is entirely set or entirely clear around each face.
211
+ * @returns the components of the graph, each component represented by an array of nodes, one node per face
212
+ * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.
191
213
  */
192
214
  static collectConnectedComponentsWithExteriorParityMasks(graph, parityEdgeTester, parityMask = Graph_1.HalfEdgeMask.NULL_MASK) {
215
+ // Illustration of the algorithm can be found at geometry/internaldocs/Graph.md
193
216
  const components = [];
194
217
  const visitMask = Graph_1.HalfEdgeMask.VISITED;
195
218
  const allMasks = parityMask | visitMask;
196
219
  graph.clearMask(allMasks);
197
220
  for (const faceSeed of graph.allHalfEdges) {
198
- if (!faceSeed.isMaskSet(Graph_1.HalfEdgeMask.VISITED)) {
221
+ if (!faceSeed.isMaskSet(visitMask)) {
199
222
  const newFaces = HalfEdgeGraphSearch.parityFloodFromSeed(faceSeed, visitMask, parityEdgeTester, parityMask);
223
+ // parityFloodFromSeed does not return an empty array because it is called on an unvisited faceSeed
200
224
  components.push(newFaces);
201
225
  }
202
226
  }
203
- HalfEdgeGraphSearch.correctParityInComponentArrays(graph, parityMask, components);
227
+ HalfEdgeGraphSearch.correctParityInComponentArrays(parityMask, components);
228
+ return components;
229
+ }
230
+ /**
231
+ * Breadth First Search through connected component of a graph.
232
+ * @param component vector of nodes, one per face.
233
+ * @param seed seed node in component.
234
+ * @param visitMask mask to apply to visited nodes. Assumed cleared throughout component.
235
+ * @param ignoreMask (optional) mask preset on faces to ignore. Default value is `HalfEdgeMask.EXTERIOR` to
236
+ * ignore exterior faces. Pass `HalfEdgeMask.NULL_MASK` to process all faces.
237
+ * @param maxFaceCount (optional) maximum number of faces in the component. Should be positive; otherwise
238
+ * `Infinity` is used.
239
+ * @returns node at which to start next component if maximum face count exceeded, or undefined.
240
+ */
241
+ static exploreComponent(component, seed, visitMask, ignoreMask = Graph_1.HalfEdgeMask.EXTERIOR, maxFaceCount = Infinity) {
242
+ if (maxFaceCount <= 0)
243
+ maxFaceCount = Infinity;
244
+ const boundaryMask = visitMask | ignoreMask;
245
+ let numFaces = 0;
246
+ const candidates = []; // the queue
247
+ candidates.push(seed);
248
+ while (candidates.length !== 0 && numFaces < maxFaceCount) {
249
+ // shift is O(n) and may be inefficient for large queues; if needed, we can replace
250
+ // queue by circular array or implement the queue using 2 stacks; both are O(1)
251
+ const node = candidates.shift();
252
+ if (node.isMaskSet(boundaryMask))
253
+ continue;
254
+ component.push(node);
255
+ ++numFaces;
256
+ const enqueueNeighboringFaces = (heNode) => {
257
+ heNode.setMask(visitMask);
258
+ const neighbor = heNode.vertexSuccessor;
259
+ if (!neighbor.isMaskSet(boundaryMask))
260
+ candidates.push(neighbor);
261
+ };
262
+ node.collectAroundFace(enqueueNeighboringFaces);
263
+ }
264
+ if (candidates.length === 0)
265
+ return undefined;
266
+ else {
267
+ const front = candidates[0];
268
+ while (candidates.length !== 0) {
269
+ // try to find a node at the boundary of both the geometry and previous component
270
+ const node = candidates.shift(); // shift may be inefficient for large queues
271
+ if (node.vertexSuccessor.isMaskSet(ignoreMask))
272
+ return node;
273
+ if (node.edgeMate.isMaskSet(ignoreMask))
274
+ return node;
275
+ }
276
+ return front;
277
+ }
278
+ }
279
+ /**
280
+ * Collect connected components of the graph (via Breadth First Search).
281
+ * @param graph graph to inspect.
282
+ * @param maxFaceCount (optional) maximum number of faces in each component. Should be positive; otherwise
283
+ * `Infinity` is used.
284
+ * @param ignoreMask (optional) mask preset on faces to ignore. Default value is `HalfEdgeMask.EXTERIOR` to ignore
285
+ * exterior faces. Pass `HalfEdgeMask.NULL_MASK` to process all faces.
286
+ * @returns the components of the graph, each component represented by an array of nodes, one node per face
287
+ * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.
288
+ */
289
+ static collectConnectedComponents(graph, maxFaceCount = Infinity, ignoreMask = Graph_1.HalfEdgeMask.EXTERIOR) {
290
+ const components = [];
291
+ if (graph.countMask(ignoreMask) === 0)
292
+ ignoreMask = Graph_1.HalfEdgeMask.NULL_MASK;
293
+ const visitMask = Graph_1.HalfEdgeMask.VISITED;
294
+ const boundaryMask = visitMask | ignoreMask;
295
+ // Starting with the input node, look ahead for a boundary face. Failing that, return the input node.
296
+ // Starting all floods at the boundary reduces the chance of ending up with a ring-shaped component at the boundary.
297
+ const findNextFloodSeed = (index) => {
298
+ for (let i = index; i < graph.countNodes(); ++i) {
299
+ if (!graph.allHalfEdges[i].isMaskSet(boundaryMask)
300
+ && graph.allHalfEdges[i].edgeMate.isMaskSet(boundaryMask)) {
301
+ index = i;
302
+ break;
303
+ }
304
+ }
305
+ return index;
306
+ };
307
+ for (let i = 0; i < graph.countNodes(); ++i) {
308
+ if (graph.allHalfEdges[i].isMaskSet(boundaryMask))
309
+ continue;
310
+ const i0 = findNextFloodSeed(i);
311
+ let seed = graph.allHalfEdges[i0];
312
+ do { // flood this component
313
+ const component = [];
314
+ seed = HalfEdgeGraphSearch.exploreComponent(component, seed, visitMask, ignoreMask, maxFaceCount);
315
+ if (component.length !== 0)
316
+ components.push(component);
317
+ } while (seed !== undefined);
318
+ if (!graph.allHalfEdges[i].isMaskSet(visitMask))
319
+ --i; // reprocess this node
320
+ }
204
321
  return components;
205
322
  }
206
323
  /**
207
- * Test if (x,y) is inside (1), on an edge (0) or outside (-1) a face.
208
- * @param seedNode any node on the face loop
209
- * @param x x coordinate of test point.
210
- * @param y y coordinate of test point.
324
+ * Test if test point (xTest,yTest) is inside/outside a face or on an edge.
325
+ * @param seedNode any node on the face loop.
326
+ * @param xTest x coordinate of the test point.
327
+ * @param yTest y coordinate of the test point.
328
+ * @returns 0 if ON, 1 if IN, -1 if OUT.
211
329
  */
212
- static pointInOrOnFaceXY(seedNode, x, y) {
213
- const context = new XYParitySearchContext_1.XYParitySearchContext(x, y);
214
- // walk around looking for an accepted node to start the search (seedNode is usually ok!)
330
+ static pointInOrOnFaceXY(seedNode, xTest, yTest) {
331
+ const context = new XYParitySearchContext_1.XYParitySearchContext(xTest, yTest);
332
+ // walk around looking for an accepted node to start the search (seedNode is usually ok)
215
333
  let nodeA = seedNode;
216
334
  let nodeB = seedNode.faceSuccessor;
217
335
  for (;; nodeA = nodeB) {
218
336
  if (context.tryStartEdge(nodeA.x, nodeA.y, nodeB.x, nodeB.y))
219
337
  break;
220
338
  if (nodeB === seedNode) {
221
- // umm.. the face is all on the x axis?
222
- return context.classifyCounts();
339
+ // the test point and the face are all on line "y = yTest"
340
+ const range = Range_1.Range1d.createXX(nodeB.x, nodeB.faceSuccessor.x);
341
+ return range.containsX(xTest) ? 0 : -1;
223
342
  }
224
343
  nodeB = nodeA.faceSuccessor;
225
344
  }
226
- // nodeB is the real start node for search ... emit ends of each edge around the face,
227
- // stopping after emitting nodeB as an edge end.
228
- let node = nodeB.faceSuccessor;
345
+ // nodeB is the real start node for search, so stop when we revisit it. For each edge, accumulate parity and hits
346
+ let nodeC = nodeB.faceSuccessor;
229
347
  for (;;) {
230
- if (!context.advance(node.x, node.y)) {
348
+ if (!context.advance(nodeC.x, nodeC.y)) {
231
349
  return context.classifyCounts();
232
350
  }
233
- if (node === nodeB)
351
+ if (nodeC === nodeB)
234
352
  break;
235
- node = node.faceSuccessor;
353
+ nodeC = nodeC.faceSuccessor;
236
354
  }
237
355
  return context.classifyCounts();
238
356
  }
239
357
  /**
240
- * Announce nodes that are "extended face boundary" by conditions (usually mask of node and mate) in test functions.
241
- * * After each node, the next candidate in reached by looking "around the head vertex loop" for the next boundary.
242
- * * "Around the vertex" from nodeA means
243
- * * First look at nodeA.faceSuccessor;
244
- * * Then look at vertexPredecessor around that vertex loop.
245
- * * Each accepted node is passed to announceNode, and marked with the visit mask.
246
- * * The counter of the announceEdge function is zero for the first edge, then increases with each edge.
358
+ * Collect boundary edges starting from `seed`.
359
+ * * If `seed` is not a boundary node or is already visited, the function exists early.
247
360
  * @param seed start node.
248
- * @param isBoundaryEdge
249
- * @param announceEdge
361
+ * @param visitMask mask to set on processed nodes.
362
+ * @param isBoundaryEdge function to test if an edge in a boundary edge.
363
+ * @param announceEdgeInBoundary callback invoked on each edge in the boundary loop in order. The counter is zero
364
+ * for the first edge, and incremented with each successive edge.
250
365
  */
251
- static collectExtendedBoundaryLoopFromSeed(seed, visitMask, isBoundaryEdge, announceEdge) {
366
+ static collectExtendedBoundaryLoopFromSeed(seed, visitMask, isBoundaryEdge, announceEdgeInBoundary) {
252
367
  let counter = 0;
253
368
  while (!seed.getMask(visitMask) && isBoundaryEdge(seed)) {
254
- announceEdge(seed, counter++);
369
+ announceEdgeInBoundary(seed, counter++);
255
370
  seed.setMask(visitMask);
256
371
  const vertexBase = seed.faceSuccessor;
257
372
  let candidateAroundVertex = vertexBase;
258
373
  for (;;) {
259
- if (candidateAroundVertex.getMask(visitMask))
374
+ if (candidateAroundVertex.getMask(visitMask)) // end of boundary loop
260
375
  return;
261
376
  if (isBoundaryEdge(candidateAroundVertex)) {
262
377
  seed = candidateAroundVertex;
@@ -264,23 +379,22 @@ class HalfEdgeGraphSearch {
264
379
  }
265
380
  candidateAroundVertex = candidateAroundVertex.vertexPredecessor;
266
381
  if (candidateAroundVertex === vertexBase)
267
- break;
382
+ break; // prevent infinite loop in case exteriorMask is not set on the edge mate of the boundary edge
268
383
  }
269
384
  }
270
385
  }
271
386
  /**
272
- * Collect arrays of nodes "around the boundary" of a graph with extraneous (non-boundary) edges.
273
- * * The "boundary" is nodes that do NOT have the exterior mask, but whose mates DO have the exterior mask.
274
- * * After each node, the next candidate in reached by looking "around the head vertex loop" for the next boundary.
275
- * * "Around the vertex" from nodeA means
276
- * * First look at nodeA.faceSuccessor;
277
- * * Then look at vertexPredecessor around that vertex loop.
278
- * * Each accepted node is passed to announceNode, and marked with the visit mask.
279
- * @param seed start node.
280
- * @param isBoundaryNode
281
- * @param announceNode
387
+ * Collect boundary edges in the graph.
388
+ * * A boundary edge is defined by `exteriorMask` being set on only its "exterior" edge mate.
389
+ * * Each boundary edge is identified in the output by its edge mate that lacks `exteriorMask`.
390
+ * * Each inner array is ordered in the output so that its boundary edges form a connected path. If `exteriorMask`
391
+ * is preset consistently around each "exterior" face, these paths are loops.
392
+ * @param graph the graph to query
393
+ * @param exteriorMask mask preset on exactly one side of boundary edges
394
+ * @returns array of boundary loops, each loop an array of the unmasked mates of boundary edges
282
395
  */
283
396
  static collectExtendedBoundaryLoopsInGraph(graph, exteriorMask) {
397
+ // Illustration of the algorithm can be found at geometry/internaldocs/Graph.md
284
398
  const loops = [];
285
399
  const visitMask = graph.grabMask(true);
286
400
  const isBoundaryEdge = (edge) => {
@@ -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 = (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"]}
1
+ {"version":3,"file":"HalfEdgeGraphSearch.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSearch.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module Topology\n */\nimport { Range1d } from \"../geometry3d/Range\";\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask, HalfEdgeToBooleanFunction, NodeFunction, NodeToNumberFunction } from \"./Graph\";\nimport { SignedDataSummary } from \"./SignedDataSummary\";\nimport { XYParitySearchContext } from \"./XYParitySearchContext\";\n\n// cspell:word internaldocs\n\n/**\n * Interface for an object that executes boolean tests on edges.\n * @internal\n */\nexport interface HalfEdgeTestObject {\n testEdge(h: HalfEdge): boolean;\n}\n/**\n * Class to test match of half edge mask.\n * @internal\n */\nexport class HalfEdgeMaskTester {\n private _targetMask: HalfEdgeMask;\n private _targetValue: boolean;\n /**\n * Constructor\n * @param mask mask to test in `testEdge` function\n * @param targetValue value to match for true return\n */\n public constructor(mask: HalfEdgeMask, targetValue: boolean = true) {\n this._targetMask = mask;\n this._targetValue = targetValue;\n }\n /** Return true if the value of the targetMask matches the targetValue. */\n public testEdge(edge: HalfEdge): boolean {\n return edge.isMaskSet(this._targetMask) === this._targetValue;\n }\n}\n/**\n * Class for different types of searches for HalfEdgeGraph.\n * @internal\n */\nexport class HalfEdgeGraphSearch {\n /**\n * Static method for face area computation -- useful as function parameter in `collectFaceAreaSummary`.\n * * This simply calls `node.signedFaceArea()`\n * @param node instance for signedFaceArea call.\n */\n public static signedFaceArea(node: HalfEdge): number {\n return node.signedFaceArea();\n }\n /**\n * Return a summary of face data (e.g., area) as computed by the callback on the faces of the graph.\n * * Callers with curved edge graphs must supply their own area function.\n * @param source graph or array of nodes to examine.\n * @param collectAllNodes flag to pass to the `SignedDataSummary` constructor to control collection of nodes.\n * @param areaFunction function to obtain area (or other numeric value). Default computes polygonal face area.\n */\n public static collectFaceAreaSummary(\n source: HalfEdgeGraph | HalfEdge[],\n collectAllNodes: boolean = false,\n areaFunction: NodeToNumberFunction = (node) => HalfEdgeGraphSearch.signedFaceArea(node),\n ): SignedDataSummary<HalfEdge> {\n const result = new SignedDataSummary<HalfEdge>(collectAllNodes);\n let allFaces: HalfEdge[];\n if (source instanceof HalfEdgeGraph)\n allFaces = source.collectFaceLoops();\n else\n allFaces = source;\n for (const node of allFaces) {\n const area = areaFunction(node);\n result.announceItem(node, area);\n }\n return result;\n }\n /**\n * Search the graph for the face with the most negative area.\n * @param oneCandidateNodePerFace graph or an array containing one node from each face to be considered.\n * @returns node on the negative area face with largest absolute area, or `undefined` if no negative area face.\n */\n public static findMinimumAreaFace(\n oneCandidateNodePerFace: HalfEdgeGraph | HalfEdge[], faceAreaFunction?: NodeToNumberFunction,\n ): HalfEdge | undefined {\n const summary = HalfEdgeGraphSearch.collectFaceAreaSummary(oneCandidateNodePerFace, false, faceAreaFunction);\n return summary.largestNegativeItem;\n }\n /**\n * Test if the graph is triangulated.\n * * Return `false` if:\n * * number of positive area faces with more than 3 edges is larger than `numPositiveExceptionsAllowed`.\n * * graph has more than 1 negative area face when `allowMultipleNegativeAreaFaces` is `false`.\n * * 2-edge faces are ignored.\n */\n public static isTriangulatedCCW(\n source: HalfEdgeGraph | HalfEdge[],\n allowMultipleNegativeAreaFaces: boolean = true,\n numPositiveExceptionsAllowed: number = 0,\n ): boolean {\n let allFaces: HalfEdge[];\n if (source instanceof HalfEdgeGraph)\n allFaces = source.collectFaceLoops();\n else\n allFaces = source;\n let numNegative = 0;\n let numPositiveExceptions = 0;\n for (const node of allFaces) {\n const numEdges = node.countEdgesAroundFace();\n if (numEdges >= 3) {\n const area = node.signedFaceArea();\n if (area > 0) {\n if (numEdges > 3) {\n numPositiveExceptions++;\n if (numPositiveExceptions > numPositiveExceptionsAllowed)\n return false;\n }\n } else {\n numNegative++;\n if (numNegative > 1) {\n if (!allowMultipleNegativeAreaFaces)\n return false;\n }\n }\n }\n }\n return true;\n }\n /**\n * Process a face during graph traversal.\n * @param faceSeed a node in the face.\n * @param mask mask to set on each node of the face.\n * @param allNodeStack array appended with each node of the face.\n * @param onePerFaceStack array appended with `faceSeed`.\n */\n private static pushAndMaskAllNodesInFace(\n faceSeed: HalfEdge, mask: number, allNodeStack: HalfEdge[], onePerFaceStack: HalfEdge[],\n ): void {\n onePerFaceStack.push(faceSeed);\n faceSeed.collectAroundFace((node: HalfEdge) => {\n node.setMask(mask);\n allNodeStack.push(node);\n });\n }\n /**\n * Traverse (via Depth First Search) to all accessible faces from the given seed.\n * @param faceSeed first node to start the traverse.\n * @param visitMask mask applied to all faces as visited.\n * @param parityEdgeTester function to test if an edge is adjacent to two faces of opposite parity, e.g., a boundary\n * edge that separates an \"interior\" face and an \"exterior\" face. If `parityEdgeTester` is not supplied and `parityMask`\n * is supplied, the default parity rule is to alternate parity state in a \"bullseye\" pattern starting at the seed face,\n * with each successive concentric ring of faces at constant topological distance from the seed face receiving the\n * opposite parity state of the previous ring.\n * @param parityMask mask to apply to the first face and faces that share the same parity as the first face, as\n * determined by the parity rule. If this is `NULL_MASK`, there is no record of parity. If (non-null) parity mask\n * is given, on return it is entirely set or entirely clear around each face.\n * @returns an array that contains one representative node in each face of the connected component.\n */\n private static parityFloodFromSeed(\n faceSeed: HalfEdge,\n visitMask: HalfEdgeMask,\n parityEdgeTester: HalfEdgeTestObject | undefined,\n parityMask: HalfEdgeMask,\n ): HalfEdge[] {\n const faces: HalfEdge[] = [];\n if (faceSeed.isMaskSet(visitMask))\n return faces; // empty array\n const allMasks = parityMask | visitMask;\n const stack: HalfEdge[] = [];\n // the seed face is arbitrarily assigned the parity mask\n HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(faceSeed, allMasks, stack, faces);\n while (stack.length > 0) {\n const p = stack.pop()!;\n const mate = p.edgeMate;\n if (!mate)\n continue;\n if (!mate.isMaskSet(visitMask)) {\n let newState = p.isMaskSet(parityMask);\n if (!parityEdgeTester || parityEdgeTester.testEdge(p))\n newState = !newState;\n HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(mate, newState ? allMasks : visitMask, stack, faces);\n }\n }\n return faces;\n }\n /**\n * * Correct the parity mask in the faces of a component.\n * * It is assumed that the parity mask is applied _consistently_ throughout the supplied faces, but maybe\n * not _correctly_.\n * * A consistently applied parity mask is \"correct\" if it is set on the negative area (\"exterior\") face of\n * a connected component.\n * * This method finds a face with negative area and toggles the mask throughout the input faces if this face\n * lacks the parity mask.\n * * In a properly merged planar subdivision there should be only one true negative area face per component.\n */\n private static correctParityInSingleComponent(parityMask: HalfEdgeMask, faces: HalfEdge[]): void {\n const exteriorHalfEdge = HalfEdgeGraphSearch.findMinimumAreaFace(faces);\n if (!exteriorHalfEdge) {\n // graph has all degenerate faces; do nothing\n } else if (exteriorHalfEdge.isMaskSet(parityMask)) {\n // all should be well; nothing to do\n } else {\n for (const faceSeed of faces) {\n if (faceSeed.isMaskSet(parityMask)) {\n faceSeed.clearMaskAroundFace(parityMask);\n } else {\n faceSeed.setMaskAroundFace(parityMask);\n }\n }\n }\n }\n /** Apply `correctParityInSingleComponent` to each array in components (quick exit if `parityMask` is `NULL_MASK`). */\n private static correctParityInComponentArrays(parityMask: HalfEdgeMask, components: HalfEdge[][]): void {\n if (parityMask === HalfEdgeMask.NULL_MASK)\n return;\n for (const facesInComponent of components)\n HalfEdgeGraphSearch.correctParityInSingleComponent(parityMask, facesInComponent);\n }\n /**\n * Collect connected components of the graph (via Depth First Search).\n * @param graph graph to inspect.\n * @param parityEdgeTester (optional) function to test if an edge is adjacent to two faces of opposite parity,\n * e.g., a boundary edge that separates an \"interior\" face and an \"exterior\" face. If `parityEdgeTester` is not\n * supplied and `parityMask` is supplied, the default parity rule is to alternate parity state in a \"bullseye\"\n * pattern starting at the seed face, with each successive concentric ring of faces at constant topological\n * distance from the seed face receiving the opposite parity state of the previous ring.\n * @param parityMask (optional) mask to apply to the first face and faces that share the same parity as the\n * first face, as determined by the parity rule. If this is `NULL_MASK`, there is no record of parity. If\n * (non-null) parity mask is given, on return it is entirely set or entirely clear around each face.\n * @returns the components of the graph, each component represented by an array of nodes, one node per face\n * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.\n */\n public static collectConnectedComponentsWithExteriorParityMasks(\n graph: HalfEdgeGraph,\n parityEdgeTester: HalfEdgeTestObject | undefined,\n parityMask: HalfEdgeMask = HalfEdgeMask.NULL_MASK,\n ): HalfEdge[][] {\n // Illustration of the algorithm can be found at geometry/internaldocs/Graph.md\n const components = [];\n const visitMask = HalfEdgeMask.VISITED;\n const allMasks = parityMask | visitMask;\n graph.clearMask(allMasks);\n for (const faceSeed of graph.allHalfEdges) {\n if (!faceSeed.isMaskSet(visitMask)) {\n const newFaces = HalfEdgeGraphSearch.parityFloodFromSeed(faceSeed, visitMask, parityEdgeTester, parityMask);\n // parityFloodFromSeed does not return an empty array because it is called on an unvisited faceSeed\n components.push(newFaces);\n }\n }\n HalfEdgeGraphSearch.correctParityInComponentArrays(parityMask, components);\n return components;\n }\n /**\n * Breadth First Search through connected component of a graph.\n * @param component vector of nodes, one per face.\n * @param seed seed node in component.\n * @param visitMask mask to apply to visited nodes. Assumed cleared throughout component.\n * @param ignoreMask (optional) mask preset on faces to ignore. Default value is `HalfEdgeMask.EXTERIOR` to\n * ignore exterior faces. Pass `HalfEdgeMask.NULL_MASK` to process all faces.\n * @param maxFaceCount (optional) maximum number of faces in the component. Should be positive; otherwise\n * `Infinity` is used.\n * @returns node at which to start next component if maximum face count exceeded, or undefined.\n */\n private static exploreComponent(\n component: HalfEdge[],\n seed: HalfEdge,\n visitMask: HalfEdgeMask,\n ignoreMask: HalfEdgeMask = HalfEdgeMask.EXTERIOR,\n maxFaceCount: number = Infinity,\n ): HalfEdge | undefined {\n if (maxFaceCount <= 0)\n maxFaceCount = Infinity;\n const boundaryMask: HalfEdgeMask = visitMask | ignoreMask;\n let numFaces = 0;\n const candidates: HalfEdge[] = []; // the queue\n candidates.push(seed);\n while (candidates.length !== 0 && numFaces < maxFaceCount) {\n // shift is O(n) and may be inefficient for large queues; if needed, we can replace\n // queue by circular array or implement the queue using 2 stacks; both are O(1)\n const node = candidates.shift()!;\n if (node.isMaskSet(boundaryMask))\n continue;\n component.push(node);\n ++numFaces;\n const enqueueNeighboringFaces: NodeFunction = (heNode: HalfEdge) => {\n heNode.setMask(visitMask);\n const neighbor = heNode.vertexSuccessor;\n if (!neighbor.isMaskSet(boundaryMask))\n candidates.push(neighbor);\n };\n node.collectAroundFace(enqueueNeighboringFaces);\n }\n if (candidates.length === 0)\n return undefined;\n else {\n const front = candidates[0];\n while (candidates.length !== 0) {\n // try to find a node at the boundary of both the geometry and previous component\n const node = candidates.shift()!; // shift may be inefficient for large queues\n if (node.vertexSuccessor.isMaskSet(ignoreMask))\n return node;\n if (node.edgeMate.isMaskSet(ignoreMask))\n return node;\n }\n return front;\n }\n }\n /**\n * Collect connected components of the graph (via Breadth First Search).\n * @param graph graph to inspect.\n * @param maxFaceCount (optional) maximum number of faces in each component. Should be positive; otherwise\n * `Infinity` is used.\n * @param ignoreMask (optional) mask preset on faces to ignore. Default value is `HalfEdgeMask.EXTERIOR` to ignore\n * exterior faces. Pass `HalfEdgeMask.NULL_MASK` to process all faces.\n * @returns the components of the graph, each component represented by an array of nodes, one node per face\n * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.\n */\n public static collectConnectedComponents(\n graph: HalfEdgeGraph,\n maxFaceCount: number = Infinity,\n ignoreMask: HalfEdgeMask = HalfEdgeMask.EXTERIOR,\n ): HalfEdge[][] {\n const components: HalfEdge[][] = [];\n if (graph.countMask(ignoreMask) === 0)\n ignoreMask = HalfEdgeMask.NULL_MASK;\n const visitMask = HalfEdgeMask.VISITED;\n const boundaryMask: HalfEdgeMask = visitMask | ignoreMask;\n // Starting with the input node, look ahead for a boundary face. Failing that, return the input node.\n // Starting all floods at the boundary reduces the chance of ending up with a ring-shaped component at the boundary.\n const findNextFloodSeed = (index: number) => {\n for (let i = index; i < graph.countNodes(); ++i) {\n if (!graph.allHalfEdges[i].isMaskSet(boundaryMask)\n && graph.allHalfEdges[i].edgeMate.isMaskSet(boundaryMask)) {\n index = i;\n break;\n }\n }\n return index;\n };\n for (let i = 0; i < graph.countNodes(); ++i) {\n if (graph.allHalfEdges[i].isMaskSet(boundaryMask))\n continue;\n const i0 = findNextFloodSeed(i);\n let seed: HalfEdge | undefined = graph.allHalfEdges[i0];\n do { // flood this component\n const component: HalfEdge[] = [];\n seed = HalfEdgeGraphSearch.exploreComponent(component, seed, visitMask, ignoreMask, maxFaceCount);\n if (component.length !== 0)\n components.push(component);\n } while (seed !== undefined);\n if (!graph.allHalfEdges[i].isMaskSet(visitMask))\n --i; // reprocess this node\n }\n return components;\n }\n /**\n * Test if test point (xTest,yTest) is inside/outside a face or on an edge.\n * @param seedNode any node on the face loop.\n * @param xTest x coordinate of the test point.\n * @param yTest y coordinate of the test point.\n * @returns 0 if ON, 1 if IN, -1 if OUT.\n */\n public static pointInOrOnFaceXY(seedNode: HalfEdge, xTest: number, yTest: number): number | undefined {\n const context = new XYParitySearchContext(xTest, yTest);\n // walk around looking for an accepted node to start the search (seedNode is usually ok)\n let nodeA = seedNode;\n let nodeB = seedNode.faceSuccessor;\n for (; ; nodeA = nodeB) {\n if (context.tryStartEdge(nodeA.x, nodeA.y, nodeB.x, nodeB.y))\n break;\n if (nodeB === seedNode) {\n // the test point and the face are all on line \"y = yTest\"\n const range = Range1d.createXX(nodeB.x, nodeB.faceSuccessor.x);\n return range.containsX(xTest) ? 0 : -1;\n }\n nodeB = nodeA.faceSuccessor;\n }\n // nodeB is the real start node for search, so stop when we revisit it. For each edge, accumulate parity and hits\n let nodeC = nodeB.faceSuccessor;\n for (; ;) {\n if (!context.advance(nodeC.x, nodeC.y)) {\n return context.classifyCounts();\n }\n if (nodeC === nodeB)\n break;\n nodeC = nodeC.faceSuccessor;\n }\n return context.classifyCounts();\n }\n /**\n * Collect boundary edges starting from `seed`.\n * * If `seed` is not a boundary node or is already visited, the function exists early.\n * @param seed start node.\n * @param visitMask mask to set on processed nodes.\n * @param isBoundaryEdge function to test if an edge in a boundary edge.\n * @param announceEdgeInBoundary callback invoked on each edge in the boundary loop in order. The counter is zero\n * for the first edge, and incremented with each successive edge.\n */\n public static collectExtendedBoundaryLoopFromSeed(\n seed: HalfEdge,\n visitMask: HalfEdgeMask,\n isBoundaryEdge: HalfEdgeToBooleanFunction,\n announceEdgeInBoundary: (edge: HalfEdge, counter: number) => void,\n ): void {\n let counter = 0;\n while (!seed.getMask(visitMask) && isBoundaryEdge(seed)) {\n announceEdgeInBoundary(seed, counter++);\n seed.setMask(visitMask);\n const vertexBase = seed.faceSuccessor;\n let candidateAroundVertex = vertexBase;\n for (; ;) {\n if (candidateAroundVertex.getMask(visitMask)) // end of boundary loop\n return;\n if (isBoundaryEdge(candidateAroundVertex)) {\n seed = candidateAroundVertex;\n break;\n }\n candidateAroundVertex = candidateAroundVertex.vertexPredecessor;\n if (candidateAroundVertex === vertexBase)\n break; // prevent infinite loop in case exteriorMask is not set on the edge mate of the boundary edge\n }\n }\n }\n /**\n * Collect boundary edges in the graph.\n * * A boundary edge is defined by `exteriorMask` being set on only its \"exterior\" edge mate.\n * * Each boundary edge is identified in the output by its edge mate that lacks `exteriorMask`.\n * * Each inner array is ordered in the output so that its boundary edges form a connected path. If `exteriorMask`\n * is preset consistently around each \"exterior\" face, these paths are loops.\n * @param graph the graph to query\n * @param exteriorMask mask preset on exactly one side of boundary edges\n * @returns array of boundary loops, each loop an array of the unmasked mates of boundary edges\n */\n public static collectExtendedBoundaryLoopsInGraph(graph: HalfEdgeGraph, exteriorMask: HalfEdgeMask): HalfEdge[][] {\n // Illustration of the algorithm can be found at geometry/internaldocs/Graph.md\n const loops: HalfEdge[][] = [];\n const visitMask = graph.grabMask(true);\n const isBoundaryEdge = (edge: HalfEdge): boolean => {\n return edge.getMask(exteriorMask) === 0 && edge.edgeMate.getMask(exteriorMask) !== 0;\n };\n const announceEdgeInBoundary = (edge: HalfEdge, counter: number) => {\n if (counter === 0)\n loops.push([]);\n loops[loops.length - 1].push(edge);\n };\n for (const seed of graph.allHalfEdges) {\n this.collectExtendedBoundaryLoopFromSeed(seed, visitMask, isBoundaryEdge, announceEdgeInBoundary);\n }\n graph.dropMask(visitMask);\n return loops;\n }\n}\n"]}