@itwin/core-geometry 5.2.0-dev.30 → 5.2.0-dev.31

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 (451) hide show
  1. package/lib/cjs/Constant.js.map +1 -1
  2. package/lib/cjs/Geometry.js.map +1 -1
  3. package/lib/cjs/bspline/AkimaCurve3d.js.map +1 -1
  4. package/lib/cjs/bspline/BSpline1dNd.js.map +1 -1
  5. package/lib/cjs/bspline/BSplineCurve.js.map +1 -1
  6. package/lib/cjs/bspline/BSplineCurve3dH.js.map +1 -1
  7. package/lib/cjs/bspline/BSplineCurveOps.js.map +1 -1
  8. package/lib/cjs/bspline/BSplineSurface.js.map +1 -1
  9. package/lib/cjs/bspline/Bezier1dNd.js.map +1 -1
  10. package/lib/cjs/bspline/BezierCurve3d.js.map +1 -1
  11. package/lib/cjs/bspline/BezierCurve3dH.js.map +1 -1
  12. package/lib/cjs/bspline/BezierCurveBase.js.map +1 -1
  13. package/lib/cjs/bspline/InterpolationCurve3d.js.map +1 -1
  14. package/lib/cjs/bspline/KnotVector.js.map +1 -1
  15. package/lib/cjs/bspline/SurfaceLocationDetail.js.map +1 -1
  16. package/lib/cjs/clipping/AlternatingConvexClipTree.js.map +1 -1
  17. package/lib/cjs/clipping/BooleanClipFactory.js.map +1 -1
  18. package/lib/cjs/clipping/BooleanClipNode.js.map +1 -1
  19. package/lib/cjs/clipping/ClipPlane.js.map +1 -1
  20. package/lib/cjs/clipping/ClipPrimitive.js.map +1 -1
  21. package/lib/cjs/clipping/ClipUtils.js.map +1 -1
  22. package/lib/cjs/clipping/ClipVector.js.map +1 -1
  23. package/lib/cjs/clipping/ConvexClipPlaneSet.js.map +1 -1
  24. package/lib/cjs/clipping/UnionOfConvexClipPlaneSets.js.map +1 -1
  25. package/lib/cjs/clipping/internalContexts/LineStringOffsetClipperContext.js.map +1 -1
  26. package/lib/cjs/core-geometry.js.map +1 -1
  27. package/lib/cjs/curve/Arc3d.js.map +1 -1
  28. package/lib/cjs/curve/ConstructCurveBetweenCurves.js.map +1 -1
  29. package/lib/cjs/curve/CoordinateXYZ.js.map +1 -1
  30. package/lib/cjs/curve/CurveChainWithDistanceIndex.js.map +1 -1
  31. package/lib/cjs/curve/CurveCollection.js.map +1 -1
  32. package/lib/cjs/curve/CurveCurve.js.map +1 -1
  33. package/lib/cjs/curve/CurveExtendMode.js.map +1 -1
  34. package/lib/cjs/curve/CurveFactory.js.map +1 -1
  35. package/lib/cjs/curve/CurveLocationDetail.js.map +1 -1
  36. package/lib/cjs/curve/CurveOps.js.map +1 -1
  37. package/lib/cjs/curve/CurvePrimitive.js.map +1 -1
  38. package/lib/cjs/curve/CurveProcessor.js.map +1 -1
  39. package/lib/cjs/curve/CurveTypes.js.map +1 -1
  40. package/lib/cjs/curve/CurveWireMomentsXYZ.js.map +1 -1
  41. package/lib/cjs/curve/GeometryQuery.js.map +1 -1
  42. package/lib/cjs/curve/LineSegment3d.js.map +1 -1
  43. package/lib/cjs/curve/LineString3d.js.map +1 -1
  44. package/lib/cjs/curve/Loop.js.map +1 -1
  45. package/lib/cjs/curve/OffsetOptions.js.map +1 -1
  46. package/lib/cjs/curve/ParityRegion.js.map +1 -1
  47. package/lib/cjs/curve/Path.js.map +1 -1
  48. package/lib/cjs/curve/PointString3d.js.map +1 -1
  49. package/lib/cjs/curve/ProxyCurve.js.map +1 -1
  50. package/lib/cjs/curve/Query/ConsolidateAdjacentPrimitivesContext.js.map +1 -1
  51. package/lib/cjs/curve/Query/CurveSplitContext.js.map +1 -1
  52. package/lib/cjs/curve/Query/CylindricalRange.js.map +1 -1
  53. package/lib/cjs/curve/Query/InOutTests.js.map +1 -1
  54. package/lib/cjs/curve/Query/PlanarSubdivision.js.map +1 -1
  55. package/lib/cjs/curve/Query/StrokeCountChain.js.map +1 -1
  56. package/lib/cjs/curve/Query/StrokeCountMap.js.map +1 -1
  57. package/lib/cjs/curve/RegionMomentsXY.js.map +1 -1
  58. package/lib/cjs/curve/RegionOps.js.map +1 -1
  59. package/lib/cjs/curve/RegionOpsClassificationSweeps.js.map +1 -1
  60. package/lib/cjs/curve/StrokeOptions.js.map +1 -1
  61. package/lib/cjs/curve/UnionRegion.js.map +1 -1
  62. package/lib/cjs/curve/internalContexts/AnnounceTangentStrokeHandler.js.map +1 -1
  63. package/lib/cjs/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.js.map +1 -1
  64. package/lib/cjs/curve/internalContexts/ChainCollectorContext.js.map +1 -1
  65. package/lib/cjs/curve/internalContexts/CloneCurvesContext.js.map +1 -1
  66. package/lib/cjs/curve/internalContexts/CloneWithExpandedLineStrings.js.map +1 -1
  67. package/lib/cjs/curve/internalContexts/ClosestPointStrokeHandler.js.map +1 -1
  68. package/lib/cjs/curve/internalContexts/CountLinearPartsSearchContext.js.map +1 -1
  69. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -1
  70. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  71. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXYZ.js.map +1 -1
  72. package/lib/cjs/curve/internalContexts/CurveLengthContext.js.map +1 -1
  73. package/lib/cjs/curve/internalContexts/CurveOffsetXYHandler.js.map +1 -1
  74. package/lib/cjs/curve/internalContexts/EllipticalArcApproximationContext.js.map +1 -1
  75. package/lib/cjs/curve/internalContexts/GapSearchContext.js.map +1 -1
  76. package/lib/cjs/curve/internalContexts/MultiChainCollector.js.map +1 -1
  77. package/lib/cjs/curve/internalContexts/NewtonRtoRStrokeHandler.js.map +1 -1
  78. package/lib/cjs/curve/internalContexts/PlaneAltitudeRangeContext.js.map +1 -1
  79. package/lib/cjs/curve/internalContexts/PolygonOffsetContext.js.map +1 -1
  80. package/lib/cjs/curve/internalContexts/SumLengthsContext.js.map +1 -1
  81. package/lib/cjs/curve/internalContexts/TransferWithSplitArcs.js.map +1 -1
  82. package/lib/cjs/curve/internalContexts/TransformInPlaceContext.js.map +1 -1
  83. package/lib/cjs/curve/spiral/AustralianRailCorpXYEvaluator.js.map +1 -1
  84. package/lib/cjs/curve/spiral/ClothoidSeries.js.map +1 -1
  85. package/lib/cjs/curve/spiral/CubicEvaluator.js.map +1 -1
  86. package/lib/cjs/curve/spiral/CzechSpiralEvaluator.js.map +1 -1
  87. package/lib/cjs/curve/spiral/DirectHalfCosineSpiralEvaluator.js.map +1 -1
  88. package/lib/cjs/curve/spiral/DirectSpiral3d.js.map +1 -1
  89. package/lib/cjs/curve/spiral/IntegratedSpiral3d.js.map +1 -1
  90. package/lib/cjs/curve/spiral/MXCubicAlongArcSpiralEvaluator.js.map +1 -1
  91. package/lib/cjs/curve/spiral/NormalizedTransition.js.map +1 -1
  92. package/lib/cjs/curve/spiral/PolishCubicSpiralEvaluator.js.map +1 -1
  93. package/lib/cjs/curve/spiral/TransitionConditionalProperties.js.map +1 -1
  94. package/lib/cjs/curve/spiral/TransitionSpiral3d.js.map +1 -1
  95. package/lib/cjs/curve/spiral/XYCurveEvaluator.js.map +1 -1
  96. package/lib/cjs/geometry3d/Angle.js.map +1 -1
  97. package/lib/cjs/geometry3d/AngleSweep.js.map +1 -1
  98. package/lib/cjs/geometry3d/BarycentricTriangle.js.map +1 -1
  99. package/lib/cjs/geometry3d/BilinearPatch.js.map +1 -1
  100. package/lib/cjs/geometry3d/CoincidentGeometryOps.js.map +1 -1
  101. package/lib/cjs/geometry3d/Ellipsoid.js.map +1 -1
  102. package/lib/cjs/geometry3d/FrameBuilder.js.map +1 -1
  103. package/lib/cjs/geometry3d/FrustumAnimation.js.map +1 -1
  104. package/lib/cjs/geometry3d/GeometryHandler.js.map +1 -1
  105. package/lib/cjs/geometry3d/GrowableBlockedArray.js.map +1 -1
  106. package/lib/cjs/geometry3d/GrowableFloat64Array.js.map +1 -1
  107. package/lib/cjs/geometry3d/GrowableXYArray.js.map +1 -1
  108. package/lib/cjs/geometry3d/GrowableXYZArray.js.map +1 -1
  109. package/lib/cjs/geometry3d/IndexedCollectionInterval.js.map +1 -1
  110. package/lib/cjs/geometry3d/IndexedXYCollection.js.map +1 -1
  111. package/lib/cjs/geometry3d/IndexedXYZCollection.js.map +1 -1
  112. package/lib/cjs/geometry3d/LongitudeLatitudeAltitude.js.map +1 -1
  113. package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
  114. package/lib/cjs/geometry3d/OrderedRotationAngles.js.map +1 -1
  115. package/lib/cjs/geometry3d/Plane3d.js.map +1 -1
  116. package/lib/cjs/geometry3d/Plane3dByOriginAndUnitNormal.js.map +1 -1
  117. package/lib/cjs/geometry3d/Plane3dByOriginAndVectors.js.map +1 -1
  118. package/lib/cjs/geometry3d/Point2dArrayCarrier.js.map +1 -1
  119. package/lib/cjs/geometry3d/Point2dVector2d.js.map +1 -1
  120. package/lib/cjs/geometry3d/Point3dArrayCarrier.js.map +1 -1
  121. package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
  122. package/lib/cjs/geometry3d/PointHelpers.js.map +1 -1
  123. package/lib/cjs/geometry3d/PointStreaming.js.map +1 -1
  124. package/lib/cjs/geometry3d/PolygonOps.js.map +1 -1
  125. package/lib/cjs/geometry3d/PolylineCompressionByEdgeOffset.js.map +1 -1
  126. package/lib/cjs/geometry3d/PolylineOps.js.map +1 -1
  127. package/lib/cjs/geometry3d/Range.js.map +1 -1
  128. package/lib/cjs/geometry3d/Ray2d.js.map +1 -1
  129. package/lib/cjs/geometry3d/Ray3d.js.map +1 -1
  130. package/lib/cjs/geometry3d/ReusableObjectCache.js.map +1 -1
  131. package/lib/cjs/geometry3d/Segment1d.js.map +1 -1
  132. package/lib/cjs/geometry3d/SortablePolygon.js.map +1 -1
  133. package/lib/cjs/geometry3d/Transform.js.map +1 -1
  134. package/lib/cjs/geometry3d/UVSurfaceOps.js.map +1 -1
  135. package/lib/cjs/geometry3d/XYZProps.js.map +1 -1
  136. package/lib/cjs/geometry3d/YawPitchRollAngles.js.map +1 -1
  137. package/lib/cjs/geometry4d/Map4d.js.map +1 -1
  138. package/lib/cjs/geometry4d/Matrix4d.js.map +1 -1
  139. package/lib/cjs/geometry4d/MomentData.js.map +1 -1
  140. package/lib/cjs/geometry4d/PlaneByOriginAndVectors4d.js.map +1 -1
  141. package/lib/cjs/geometry4d/Point4d.js.map +1 -1
  142. package/lib/cjs/numerics/BandedSystem.js.map +1 -1
  143. package/lib/cjs/numerics/BezierPolynomials.js.map +1 -1
  144. package/lib/cjs/numerics/ClusterableArray.js.map +1 -1
  145. package/lib/cjs/numerics/Complex.js.map +1 -1
  146. package/lib/cjs/numerics/ConvexPolygon2d.js.map +1 -1
  147. package/lib/cjs/numerics/Newton.js.map +1 -1
  148. package/lib/cjs/numerics/PascalCoefficients.js.map +1 -1
  149. package/lib/cjs/numerics/PolarData.js.map +1 -1
  150. package/lib/cjs/numerics/Polynomials.js.map +1 -1
  151. package/lib/cjs/numerics/Quadrature.js.map +1 -1
  152. package/lib/cjs/numerics/Range1dArray.js.map +1 -1
  153. package/lib/cjs/numerics/SmallSystem.js.map +1 -1
  154. package/lib/cjs/numerics/TriDiagonalSystem.js.map +1 -1
  155. package/lib/cjs/numerics/UnionFind.js.map +1 -1
  156. package/lib/cjs/numerics/UsageSums.js.map +1 -1
  157. package/lib/cjs/polyface/AuxData.js.map +1 -1
  158. package/lib/cjs/polyface/BoxTopology.js.map +1 -1
  159. package/lib/cjs/polyface/FacetFaceData.js.map +1 -1
  160. package/lib/cjs/polyface/FacetLocationDetail.js.map +1 -1
  161. package/lib/cjs/polyface/FacetOrientation.js.map +1 -1
  162. package/lib/cjs/polyface/GreedyTriangulationBetweenLineStrings.js.map +1 -1
  163. package/lib/cjs/polyface/IndexedEdgeMatcher.js.map +1 -1
  164. package/lib/cjs/polyface/IndexedPolyfaceVisitor.js.map +1 -1
  165. package/lib/cjs/polyface/IndexedPolyfaceWalker.js.map +1 -1
  166. package/lib/cjs/polyface/Polyface.js.map +1 -1
  167. package/lib/cjs/polyface/PolyfaceBuilder.js.map +1 -1
  168. package/lib/cjs/polyface/PolyfaceClip.js.map +1 -1
  169. package/lib/cjs/polyface/PolyfaceData.js.map +1 -1
  170. package/lib/cjs/polyface/PolyfaceQuery.js.map +1 -1
  171. package/lib/cjs/polyface/RangeLengthData.js.map +1 -1
  172. package/lib/cjs/polyface/RangeTree/LineString3dRangeTreeContext.js.map +1 -1
  173. package/lib/cjs/polyface/RangeTree/MinimumValueTester.js.map +1 -1
  174. package/lib/cjs/polyface/RangeTree/Point3dArrayRangeTreeContext.js.map +1 -1
  175. package/lib/cjs/polyface/RangeTree/PolyfaceRangeTreeContext.js.map +1 -1
  176. package/lib/cjs/polyface/RangeTree/RangeTreeNode.js.map +1 -1
  177. package/lib/cjs/polyface/RangeTree/RangeTreeSearchHandlers.js.map +1 -1
  178. package/lib/cjs/polyface/TaggedNumericData.js.map +1 -1
  179. package/lib/cjs/polyface/TriangleCandidate.js.map +1 -1
  180. package/lib/cjs/polyface/multiclip/BuildAverageNormalsContext.js.map +1 -1
  181. package/lib/cjs/polyface/multiclip/GriddedRaggedRange2dSet.js.map +1 -1
  182. package/lib/cjs/polyface/multiclip/GriddedRaggedRange2dSetWithOverflow.js.map +1 -1
  183. package/lib/cjs/polyface/multiclip/LinearSearchRange2dArray.js.map +1 -1
  184. package/lib/cjs/polyface/multiclip/OffsetMeshContext.js.map +1 -1
  185. package/lib/cjs/polyface/multiclip/Range2dSearchInterface.js.map +1 -1
  186. package/lib/cjs/polyface/multiclip/RangeSearch.js.map +1 -1
  187. package/lib/cjs/polyface/multiclip/SweepLineStringToFacetContext.js.map +1 -1
  188. package/lib/cjs/polyface/multiclip/XYPointBuckets.js.map +1 -1
  189. package/lib/cjs/serialization/BGFBAccessors.js.map +1 -1
  190. package/lib/cjs/serialization/BGFBReader.js.map +1 -1
  191. package/lib/cjs/serialization/BGFBWriter.js.map +1 -1
  192. package/lib/cjs/serialization/BentleyGeometryFlatBuffer.js.map +1 -1
  193. package/lib/cjs/serialization/DeepCompare.js.map +1 -1
  194. package/lib/cjs/serialization/GeometrySamples.js.map +1 -1
  195. package/lib/cjs/serialization/IModelJsonSchema.js.map +1 -1
  196. package/lib/cjs/serialization/SerializationHelpers.js.map +1 -1
  197. package/lib/cjs/solid/Box.js.map +1 -1
  198. package/lib/cjs/solid/Cone.js.map +1 -1
  199. package/lib/cjs/solid/LinearSweep.js.map +1 -1
  200. package/lib/cjs/solid/RotationalSweep.js.map +1 -1
  201. package/lib/cjs/solid/RuledSweep.js.map +1 -1
  202. package/lib/cjs/solid/SolidPrimitive.js.map +1 -1
  203. package/lib/cjs/solid/Sphere.js.map +1 -1
  204. package/lib/cjs/solid/SweepContour.js.map +1 -1
  205. package/lib/cjs/solid/TorusPipe.js.map +1 -1
  206. package/lib/cjs/topology/ChainMerge.js.map +1 -1
  207. package/lib/cjs/topology/Graph.js.map +1 -1
  208. package/lib/cjs/topology/HalfEdgeGraphFromIndexedLoopsContext.js.map +1 -1
  209. package/lib/cjs/topology/HalfEdgeGraphSearch.js.map +1 -1
  210. package/lib/cjs/topology/HalfEdgeGraphSpineContext.js.map +1 -1
  211. package/lib/cjs/topology/HalfEdgeGraphValidation.js.map +1 -1
  212. package/lib/cjs/topology/HalfEdgeMarkSet.js.map +1 -1
  213. package/lib/cjs/topology/HalfEdgeNodeXYZUV.js.map +1 -1
  214. package/lib/cjs/topology/HalfEdgePointInGraphSearch.js.map +1 -1
  215. package/lib/cjs/topology/HalfEdgePositionDetail.js.map +1 -1
  216. package/lib/cjs/topology/HalfEdgePriorityQueue.js.map +1 -1
  217. package/lib/cjs/topology/InsertAndRetriangulateContext.js.map +1 -1
  218. package/lib/cjs/topology/MaskManager.js.map +1 -1
  219. package/lib/cjs/topology/Merging.js.map +1 -1
  220. package/lib/cjs/topology/RegularizeFace.js.map +1 -1
  221. package/lib/cjs/topology/SignedDataSummary.js.map +1 -1
  222. package/lib/cjs/topology/SpaceTriangulation.js.map +1 -1
  223. package/lib/cjs/topology/Triangulation.js.map +1 -1
  224. package/lib/cjs/topology/Voronoi.js.map +1 -1
  225. package/lib/cjs/topology/XYParitySearchContext.js.map +1 -1
  226. package/lib/esm/Constant.js.map +1 -1
  227. package/lib/esm/Geometry.js.map +1 -1
  228. package/lib/esm/bspline/AkimaCurve3d.js.map +1 -1
  229. package/lib/esm/bspline/BSpline1dNd.js.map +1 -1
  230. package/lib/esm/bspline/BSplineCurve.js.map +1 -1
  231. package/lib/esm/bspline/BSplineCurve3dH.js.map +1 -1
  232. package/lib/esm/bspline/BSplineCurveOps.js.map +1 -1
  233. package/lib/esm/bspline/BSplineSurface.js.map +1 -1
  234. package/lib/esm/bspline/Bezier1dNd.js.map +1 -1
  235. package/lib/esm/bspline/BezierCurve3d.js.map +1 -1
  236. package/lib/esm/bspline/BezierCurve3dH.js.map +1 -1
  237. package/lib/esm/bspline/BezierCurveBase.js.map +1 -1
  238. package/lib/esm/bspline/InterpolationCurve3d.js.map +1 -1
  239. package/lib/esm/bspline/KnotVector.js.map +1 -1
  240. package/lib/esm/bspline/SurfaceLocationDetail.js.map +1 -1
  241. package/lib/esm/clipping/AlternatingConvexClipTree.js.map +1 -1
  242. package/lib/esm/clipping/BooleanClipFactory.js.map +1 -1
  243. package/lib/esm/clipping/BooleanClipNode.js.map +1 -1
  244. package/lib/esm/clipping/ClipPlane.js.map +1 -1
  245. package/lib/esm/clipping/ClipPrimitive.js.map +1 -1
  246. package/lib/esm/clipping/ClipUtils.js.map +1 -1
  247. package/lib/esm/clipping/ClipVector.js.map +1 -1
  248. package/lib/esm/clipping/ConvexClipPlaneSet.js.map +1 -1
  249. package/lib/esm/clipping/UnionOfConvexClipPlaneSets.js.map +1 -1
  250. package/lib/esm/clipping/internalContexts/LineStringOffsetClipperContext.js.map +1 -1
  251. package/lib/esm/core-geometry.js.map +1 -1
  252. package/lib/esm/curve/Arc3d.js.map +1 -1
  253. package/lib/esm/curve/ConstructCurveBetweenCurves.js.map +1 -1
  254. package/lib/esm/curve/CoordinateXYZ.js.map +1 -1
  255. package/lib/esm/curve/CurveChainWithDistanceIndex.js.map +1 -1
  256. package/lib/esm/curve/CurveCollection.js.map +1 -1
  257. package/lib/esm/curve/CurveCurve.js.map +1 -1
  258. package/lib/esm/curve/CurveExtendMode.js.map +1 -1
  259. package/lib/esm/curve/CurveFactory.js.map +1 -1
  260. package/lib/esm/curve/CurveLocationDetail.js.map +1 -1
  261. package/lib/esm/curve/CurveOps.js.map +1 -1
  262. package/lib/esm/curve/CurvePrimitive.js.map +1 -1
  263. package/lib/esm/curve/CurveProcessor.js.map +1 -1
  264. package/lib/esm/curve/CurveTypes.js.map +1 -1
  265. package/lib/esm/curve/CurveWireMomentsXYZ.js.map +1 -1
  266. package/lib/esm/curve/GeometryQuery.js.map +1 -1
  267. package/lib/esm/curve/LineSegment3d.js.map +1 -1
  268. package/lib/esm/curve/LineString3d.js.map +1 -1
  269. package/lib/esm/curve/Loop.js.map +1 -1
  270. package/lib/esm/curve/OffsetOptions.js.map +1 -1
  271. package/lib/esm/curve/ParityRegion.js.map +1 -1
  272. package/lib/esm/curve/Path.js.map +1 -1
  273. package/lib/esm/curve/PointString3d.js.map +1 -1
  274. package/lib/esm/curve/ProxyCurve.js.map +1 -1
  275. package/lib/esm/curve/Query/ConsolidateAdjacentPrimitivesContext.js.map +1 -1
  276. package/lib/esm/curve/Query/CurveSplitContext.js.map +1 -1
  277. package/lib/esm/curve/Query/CylindricalRange.js.map +1 -1
  278. package/lib/esm/curve/Query/InOutTests.js.map +1 -1
  279. package/lib/esm/curve/Query/PlanarSubdivision.js.map +1 -1
  280. package/lib/esm/curve/Query/StrokeCountChain.js.map +1 -1
  281. package/lib/esm/curve/Query/StrokeCountMap.js.map +1 -1
  282. package/lib/esm/curve/RegionMomentsXY.js.map +1 -1
  283. package/lib/esm/curve/RegionOps.js.map +1 -1
  284. package/lib/esm/curve/RegionOpsClassificationSweeps.js.map +1 -1
  285. package/lib/esm/curve/StrokeOptions.js.map +1 -1
  286. package/lib/esm/curve/UnionRegion.js.map +1 -1
  287. package/lib/esm/curve/internalContexts/AnnounceTangentStrokeHandler.js.map +1 -1
  288. package/lib/esm/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.js.map +1 -1
  289. package/lib/esm/curve/internalContexts/ChainCollectorContext.js.map +1 -1
  290. package/lib/esm/curve/internalContexts/CloneCurvesContext.js.map +1 -1
  291. package/lib/esm/curve/internalContexts/CloneWithExpandedLineStrings.js.map +1 -1
  292. package/lib/esm/curve/internalContexts/ClosestPointStrokeHandler.js.map +1 -1
  293. package/lib/esm/curve/internalContexts/CountLinearPartsSearchContext.js.map +1 -1
  294. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -1
  295. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  296. package/lib/esm/curve/internalContexts/CurveCurveIntersectXYZ.js.map +1 -1
  297. package/lib/esm/curve/internalContexts/CurveLengthContext.js.map +1 -1
  298. package/lib/esm/curve/internalContexts/CurveOffsetXYHandler.js.map +1 -1
  299. package/lib/esm/curve/internalContexts/EllipticalArcApproximationContext.js.map +1 -1
  300. package/lib/esm/curve/internalContexts/GapSearchContext.js.map +1 -1
  301. package/lib/esm/curve/internalContexts/MultiChainCollector.js.map +1 -1
  302. package/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js.map +1 -1
  303. package/lib/esm/curve/internalContexts/PlaneAltitudeRangeContext.js.map +1 -1
  304. package/lib/esm/curve/internalContexts/PolygonOffsetContext.js.map +1 -1
  305. package/lib/esm/curve/internalContexts/SumLengthsContext.js.map +1 -1
  306. package/lib/esm/curve/internalContexts/TransferWithSplitArcs.js.map +1 -1
  307. package/lib/esm/curve/internalContexts/TransformInPlaceContext.js.map +1 -1
  308. package/lib/esm/curve/spiral/AustralianRailCorpXYEvaluator.js.map +1 -1
  309. package/lib/esm/curve/spiral/ClothoidSeries.js.map +1 -1
  310. package/lib/esm/curve/spiral/CubicEvaluator.js.map +1 -1
  311. package/lib/esm/curve/spiral/CzechSpiralEvaluator.js.map +1 -1
  312. package/lib/esm/curve/spiral/DirectHalfCosineSpiralEvaluator.js.map +1 -1
  313. package/lib/esm/curve/spiral/DirectSpiral3d.js.map +1 -1
  314. package/lib/esm/curve/spiral/IntegratedSpiral3d.js.map +1 -1
  315. package/lib/esm/curve/spiral/MXCubicAlongArcSpiralEvaluator.js.map +1 -1
  316. package/lib/esm/curve/spiral/NormalizedTransition.js.map +1 -1
  317. package/lib/esm/curve/spiral/PolishCubicSpiralEvaluator.js.map +1 -1
  318. package/lib/esm/curve/spiral/TransitionConditionalProperties.js.map +1 -1
  319. package/lib/esm/curve/spiral/TransitionSpiral3d.js.map +1 -1
  320. package/lib/esm/curve/spiral/XYCurveEvaluator.js.map +1 -1
  321. package/lib/esm/geometry3d/Angle.js.map +1 -1
  322. package/lib/esm/geometry3d/AngleSweep.js.map +1 -1
  323. package/lib/esm/geometry3d/BarycentricTriangle.js.map +1 -1
  324. package/lib/esm/geometry3d/BilinearPatch.js.map +1 -1
  325. package/lib/esm/geometry3d/CoincidentGeometryOps.js.map +1 -1
  326. package/lib/esm/geometry3d/Ellipsoid.js.map +1 -1
  327. package/lib/esm/geometry3d/FrameBuilder.js.map +1 -1
  328. package/lib/esm/geometry3d/FrustumAnimation.js.map +1 -1
  329. package/lib/esm/geometry3d/GeometryHandler.js.map +1 -1
  330. package/lib/esm/geometry3d/GrowableBlockedArray.js.map +1 -1
  331. package/lib/esm/geometry3d/GrowableFloat64Array.js.map +1 -1
  332. package/lib/esm/geometry3d/GrowableXYArray.js.map +1 -1
  333. package/lib/esm/geometry3d/GrowableXYZArray.js.map +1 -1
  334. package/lib/esm/geometry3d/IndexedCollectionInterval.js.map +1 -1
  335. package/lib/esm/geometry3d/IndexedXYCollection.js.map +1 -1
  336. package/lib/esm/geometry3d/IndexedXYZCollection.js.map +1 -1
  337. package/lib/esm/geometry3d/LongitudeLatitudeAltitude.js.map +1 -1
  338. package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
  339. package/lib/esm/geometry3d/OrderedRotationAngles.js.map +1 -1
  340. package/lib/esm/geometry3d/Plane3d.js.map +1 -1
  341. package/lib/esm/geometry3d/Plane3dByOriginAndUnitNormal.js.map +1 -1
  342. package/lib/esm/geometry3d/Plane3dByOriginAndVectors.js.map +1 -1
  343. package/lib/esm/geometry3d/Point2dArrayCarrier.js.map +1 -1
  344. package/lib/esm/geometry3d/Point2dVector2d.js.map +1 -1
  345. package/lib/esm/geometry3d/Point3dArrayCarrier.js.map +1 -1
  346. package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
  347. package/lib/esm/geometry3d/PointHelpers.js.map +1 -1
  348. package/lib/esm/geometry3d/PointStreaming.js.map +1 -1
  349. package/lib/esm/geometry3d/PolygonOps.js.map +1 -1
  350. package/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js.map +1 -1
  351. package/lib/esm/geometry3d/PolylineOps.js.map +1 -1
  352. package/lib/esm/geometry3d/Range.js.map +1 -1
  353. package/lib/esm/geometry3d/Ray2d.js.map +1 -1
  354. package/lib/esm/geometry3d/Ray3d.js.map +1 -1
  355. package/lib/esm/geometry3d/ReusableObjectCache.js.map +1 -1
  356. package/lib/esm/geometry3d/Segment1d.js.map +1 -1
  357. package/lib/esm/geometry3d/SortablePolygon.js.map +1 -1
  358. package/lib/esm/geometry3d/Transform.js.map +1 -1
  359. package/lib/esm/geometry3d/UVSurfaceOps.js.map +1 -1
  360. package/lib/esm/geometry3d/XYZProps.js.map +1 -1
  361. package/lib/esm/geometry3d/YawPitchRollAngles.js.map +1 -1
  362. package/lib/esm/geometry4d/Map4d.js.map +1 -1
  363. package/lib/esm/geometry4d/Matrix4d.js.map +1 -1
  364. package/lib/esm/geometry4d/MomentData.js.map +1 -1
  365. package/lib/esm/geometry4d/PlaneByOriginAndVectors4d.js.map +1 -1
  366. package/lib/esm/geometry4d/Point4d.js.map +1 -1
  367. package/lib/esm/numerics/BandedSystem.js.map +1 -1
  368. package/lib/esm/numerics/BezierPolynomials.js.map +1 -1
  369. package/lib/esm/numerics/ClusterableArray.js.map +1 -1
  370. package/lib/esm/numerics/Complex.js.map +1 -1
  371. package/lib/esm/numerics/ConvexPolygon2d.js.map +1 -1
  372. package/lib/esm/numerics/Newton.js.map +1 -1
  373. package/lib/esm/numerics/PascalCoefficients.js.map +1 -1
  374. package/lib/esm/numerics/PolarData.js.map +1 -1
  375. package/lib/esm/numerics/Polynomials.js.map +1 -1
  376. package/lib/esm/numerics/Quadrature.js.map +1 -1
  377. package/lib/esm/numerics/Range1dArray.js.map +1 -1
  378. package/lib/esm/numerics/SmallSystem.js.map +1 -1
  379. package/lib/esm/numerics/TriDiagonalSystem.js.map +1 -1
  380. package/lib/esm/numerics/UnionFind.js.map +1 -1
  381. package/lib/esm/numerics/UsageSums.js.map +1 -1
  382. package/lib/esm/polyface/AuxData.js.map +1 -1
  383. package/lib/esm/polyface/BoxTopology.js.map +1 -1
  384. package/lib/esm/polyface/FacetFaceData.js.map +1 -1
  385. package/lib/esm/polyface/FacetLocationDetail.js.map +1 -1
  386. package/lib/esm/polyface/FacetOrientation.js.map +1 -1
  387. package/lib/esm/polyface/GreedyTriangulationBetweenLineStrings.js.map +1 -1
  388. package/lib/esm/polyface/IndexedEdgeMatcher.js.map +1 -1
  389. package/lib/esm/polyface/IndexedPolyfaceVisitor.js.map +1 -1
  390. package/lib/esm/polyface/IndexedPolyfaceWalker.js.map +1 -1
  391. package/lib/esm/polyface/Polyface.js.map +1 -1
  392. package/lib/esm/polyface/PolyfaceBuilder.js.map +1 -1
  393. package/lib/esm/polyface/PolyfaceClip.js.map +1 -1
  394. package/lib/esm/polyface/PolyfaceData.js.map +1 -1
  395. package/lib/esm/polyface/PolyfaceQuery.js.map +1 -1
  396. package/lib/esm/polyface/RangeLengthData.js.map +1 -1
  397. package/lib/esm/polyface/RangeTree/LineString3dRangeTreeContext.js.map +1 -1
  398. package/lib/esm/polyface/RangeTree/MinimumValueTester.js.map +1 -1
  399. package/lib/esm/polyface/RangeTree/Point3dArrayRangeTreeContext.js.map +1 -1
  400. package/lib/esm/polyface/RangeTree/PolyfaceRangeTreeContext.js.map +1 -1
  401. package/lib/esm/polyface/RangeTree/RangeTreeNode.js.map +1 -1
  402. package/lib/esm/polyface/RangeTree/RangeTreeSearchHandlers.js.map +1 -1
  403. package/lib/esm/polyface/TaggedNumericData.js.map +1 -1
  404. package/lib/esm/polyface/TriangleCandidate.js.map +1 -1
  405. package/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js.map +1 -1
  406. package/lib/esm/polyface/multiclip/GriddedRaggedRange2dSet.js.map +1 -1
  407. package/lib/esm/polyface/multiclip/GriddedRaggedRange2dSetWithOverflow.js.map +1 -1
  408. package/lib/esm/polyface/multiclip/LinearSearchRange2dArray.js.map +1 -1
  409. package/lib/esm/polyface/multiclip/OffsetMeshContext.js.map +1 -1
  410. package/lib/esm/polyface/multiclip/Range2dSearchInterface.js.map +1 -1
  411. package/lib/esm/polyface/multiclip/RangeSearch.js.map +1 -1
  412. package/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js.map +1 -1
  413. package/lib/esm/polyface/multiclip/XYPointBuckets.js.map +1 -1
  414. package/lib/esm/serialization/BGFBAccessors.js.map +1 -1
  415. package/lib/esm/serialization/BGFBReader.js.map +1 -1
  416. package/lib/esm/serialization/BGFBWriter.js.map +1 -1
  417. package/lib/esm/serialization/BentleyGeometryFlatBuffer.js.map +1 -1
  418. package/lib/esm/serialization/DeepCompare.js.map +1 -1
  419. package/lib/esm/serialization/GeometrySamples.js.map +1 -1
  420. package/lib/esm/serialization/IModelJsonSchema.js.map +1 -1
  421. package/lib/esm/serialization/SerializationHelpers.js.map +1 -1
  422. package/lib/esm/solid/Box.js.map +1 -1
  423. package/lib/esm/solid/Cone.js.map +1 -1
  424. package/lib/esm/solid/LinearSweep.js.map +1 -1
  425. package/lib/esm/solid/RotationalSweep.js.map +1 -1
  426. package/lib/esm/solid/RuledSweep.js.map +1 -1
  427. package/lib/esm/solid/SolidPrimitive.js.map +1 -1
  428. package/lib/esm/solid/Sphere.js.map +1 -1
  429. package/lib/esm/solid/SweepContour.js.map +1 -1
  430. package/lib/esm/solid/TorusPipe.js.map +1 -1
  431. package/lib/esm/topology/ChainMerge.js.map +1 -1
  432. package/lib/esm/topology/Graph.js.map +1 -1
  433. package/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js.map +1 -1
  434. package/lib/esm/topology/HalfEdgeGraphSearch.js.map +1 -1
  435. package/lib/esm/topology/HalfEdgeGraphSpineContext.js.map +1 -1
  436. package/lib/esm/topology/HalfEdgeGraphValidation.js.map +1 -1
  437. package/lib/esm/topology/HalfEdgeMarkSet.js.map +1 -1
  438. package/lib/esm/topology/HalfEdgeNodeXYZUV.js.map +1 -1
  439. package/lib/esm/topology/HalfEdgePointInGraphSearch.js.map +1 -1
  440. package/lib/esm/topology/HalfEdgePositionDetail.js.map +1 -1
  441. package/lib/esm/topology/HalfEdgePriorityQueue.js.map +1 -1
  442. package/lib/esm/topology/InsertAndRetriangulateContext.js.map +1 -1
  443. package/lib/esm/topology/MaskManager.js.map +1 -1
  444. package/lib/esm/topology/Merging.js.map +1 -1
  445. package/lib/esm/topology/RegularizeFace.js.map +1 -1
  446. package/lib/esm/topology/SignedDataSummary.js.map +1 -1
  447. package/lib/esm/topology/SpaceTriangulation.js.map +1 -1
  448. package/lib/esm/topology/Triangulation.js.map +1 -1
  449. package/lib/esm/topology/Voronoi.js.map +1 -1
  450. package/lib/esm/topology/XYParitySearchContext.js.map +1 -1
  451. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgeGraphFromIndexedLoopsContext.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphFromIndexedLoopsContext.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAE/F,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEhE;;GAEG;AAEH;;;;;;;GAOG;AACH,MAAM,OAAO,oCAAoC;IAC/C;QACE,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,EAAG,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,IAAI,aAAa,EAAG,CAAC;QACnC,IAAI,CAAC,2BAA2B,GAAG,EAAE,CAAC;IACxC,CAAC;IACO,eAAe,CAAwB;IACvC,MAAM,CAAgB;IAC9B,IAAW,KAAK,KAAmB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAA,CAAC;IAEvD,oCAAoC;IAC5B,2BAA2B,CAAa;IACxC,iBAAiB,CAAC,MAAc,EAAE,MAAc;QACtD,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;IACrD,CAAC;IACD;;;;;;;;;;;;;;;;OAgBG;IACI,UAAU,CAAC,OAAiB,EAAE,sBAAqD;QACxF,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,IAAI,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,2BAA2B,CAAC,MAAM,GAAG,CAAC,CAAC;YAC5C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC7D,MAAM,6CAA6C,GAAyB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAE,YAAY,CAAC,CAAC;gBACpH,IAAI,6CAA6C,KAAK,SAAS,EAAE,CAAC;oBAChE,iEAAiE;oBACjE,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,uDAAuD;oBACtH,MAAM,qBAAqB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAE,MAAM,EAAE,MAAM,CAAC,CAAC;oBAC1E,IAAI,sBAAsB,KAAK,SAAS;wBACtC,sBAAsB,CAAE,qBAAqB,CAAC,CAAC;oBACjD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAE,aAAa,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;oBACzE,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAE,qBAAqB,CAAC,CAAC;oBAC9D,qBAAqB,CAAC,QAAQ,CAAC,OAAO,CAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACjE,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAE,6CAA6C,CAAC,CAAC;oBACtF,6CAA6C,CAAC,SAAS,CAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAClF,CAAC;gBACD,MAAM,GAAG,MAAM,CAAC;YAClB,CAAC;YACD,IAAI,SAAS,GAAG,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,2BAA2B,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC9F,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,2BAA2B,EAAC,CAAC;gBACxD,MAAM,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC;gBAC1C,QAAQ,CAAC,KAAK,CAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBACtC,SAAS,GAAG,SAAS,CAAC;YACxB,CAAC;YACD,OAAO,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF","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\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n\r\n/**\r\n * Context for building a half edge graph from loops defined only by indices.\r\n * * Direct use case:\r\n * * Create the context.\r\n * * Repeatedly call insertLoop(indicesAroundLoop) to announce various loops.\r\n * * Finish by accessing the graph property.\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphFromIndexedLoopsContext {\r\n public constructor(){\r\n this._unmatchedEdges = new Map ();\r\n this._graph = new HalfEdgeGraph ();\r\n this._halfEdgesAroundCurrentLoop = [];\r\n }\r\n private _unmatchedEdges: Map<string, HalfEdge>;\r\n private _graph: HalfEdgeGraph;\r\n public get graph(): HalfEdgeGraph {return this._graph;}\r\n\r\n // for multiple uses by insert loop.\r\n private _halfEdgesAroundCurrentLoop: HalfEdge[];\r\n private indexPairToString(index0: number, index1: number): string{\r\n return `${index0.toString()},${index1.toString()}`;\r\n }\r\n /** Create a loop with specified indices at its vertices.\r\n * * For an edge with index pair [indexA, indexB]:\r\n * * if [indexB, indexA] has never appeared, a HalfEdge mated pair is created.\r\n * * One of that mated pair becomes a HalfEdge in this loop.\r\n * * The other is \"unmatched\" and gets the EXTERIOR mask.\r\n * * When announceMatedHalfEdges(halfEdge) is called:\r\n * * halfEdge and its mate are \"new\".\r\n * * each contains (as its `i` property) one index of the [indexA,indexB] pair.\r\n * * all coordinates are zeros.\r\n * * these coordinates and indices will never be referenced again by this construction sequence.\r\n * * typically the caller sets the halfEdge/mate coordinates in this callback.\r\n * * if [indexB, indexA] appeared previously (and its outer HalfEdge was left \"unmatched\"),\r\n * the \"unmatched\" HalfEdge is used in the loop being constructed, and its EXTERIOR mask is cleared.\r\n * @param indices Array of indices around the loop. This is accessed cyclically, so first and last indices should be different.\r\n * @param announceMatedHalfEdges optional function to be called as mated pairs are created. At the call,\r\n * the given HalfEdge and its mate will have a pair of successive indices from the array in their `i` property.\r\n */\r\n public insertLoop(indices: number[], announceMatedHalfEdges?: (halfEdge: HalfEdge) => void): HalfEdge | undefined{\r\n const n = indices.length;\r\n if (n > 2) {\r\n let index0 = indices[n - 1];\r\n this._halfEdgesAroundCurrentLoop.length = 0;\r\n for (const index1 of indices) {\r\n const insideString = this.indexPairToString (index0, index1);\r\n const halfEdgePreviouslyConstructedFromOppositeSide: HalfEdge | undefined = this._unmatchedEdges.get (insideString);\r\n if (halfEdgePreviouslyConstructedFromOppositeSide === undefined) {\r\n // This is the first appearance of this edge in either direction.\r\n const outsideString = this.indexPairToString (index1, index0); // string referencing the \"other\" side of the new edge.\r\n const newHalfEdgeAroundLoop = this._graph.createEdgeIdId (index0, index1);\r\n if (announceMatedHalfEdges !== undefined)\r\n announceMatedHalfEdges (newHalfEdgeAroundLoop);\r\n this._unmatchedEdges.set (outsideString, newHalfEdgeAroundLoop.edgeMate);\r\n this._halfEdgesAroundCurrentLoop.push (newHalfEdgeAroundLoop);\r\n newHalfEdgeAroundLoop.edgeMate.setMask (HalfEdgeMask.EXTERIOR);\r\n } else {\r\n this._halfEdgesAroundCurrentLoop.push (halfEdgePreviouslyConstructedFromOppositeSide);\r\n halfEdgePreviouslyConstructedFromOppositeSide.clearMask (HalfEdgeMask.EXTERIOR);\r\n }\r\n index0 = index1;\r\n }\r\n let halfEdgeA = this._halfEdgesAroundCurrentLoop[this._halfEdgesAroundCurrentLoop.length - 1];\r\n for (const halfEdgeB of this._halfEdgesAroundCurrentLoop){\r\n const halfEdgeC = halfEdgeA.faceSuccessor;\r\n HalfEdge.pinch (halfEdgeB, halfEdgeC);\r\n halfEdgeA = halfEdgeB;\r\n }\r\n return this._halfEdgesAroundCurrentLoop[0];\r\n }\r\n return undefined;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"HalfEdgeGraphFromIndexedLoopsContext.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphFromIndexedLoopsContext.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAE/F,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEhE;;GAEG;AAEH;;;;;;;GAOG;AACH,MAAM,OAAO,oCAAoC;IAC/C;QACE,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,EAAG,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,IAAI,aAAa,EAAG,CAAC;QACnC,IAAI,CAAC,2BAA2B,GAAG,EAAE,CAAC;IACxC,CAAC;IACO,eAAe,CAAwB;IACvC,MAAM,CAAgB;IAC9B,IAAW,KAAK,KAAmB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAA,CAAC;IAEvD,oCAAoC;IAC5B,2BAA2B,CAAa;IACxC,iBAAiB,CAAC,MAAc,EAAE,MAAc;QACtD,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;IACrD,CAAC;IACD;;;;;;;;;;;;;;;;OAgBG;IACI,UAAU,CAAC,OAAiB,EAAE,sBAAqD;QACxF,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,IAAI,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,2BAA2B,CAAC,MAAM,GAAG,CAAC,CAAC;YAC5C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC7D,MAAM,6CAA6C,GAAyB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAE,YAAY,CAAC,CAAC;gBACpH,IAAI,6CAA6C,KAAK,SAAS,EAAE,CAAC;oBAChE,iEAAiE;oBACjE,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,uDAAuD;oBACtH,MAAM,qBAAqB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAE,MAAM,EAAE,MAAM,CAAC,CAAC;oBAC1E,IAAI,sBAAsB,KAAK,SAAS;wBACtC,sBAAsB,CAAE,qBAAqB,CAAC,CAAC;oBACjD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAE,aAAa,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;oBACzE,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAE,qBAAqB,CAAC,CAAC;oBAC9D,qBAAqB,CAAC,QAAQ,CAAC,OAAO,CAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACjE,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAE,6CAA6C,CAAC,CAAC;oBACtF,6CAA6C,CAAC,SAAS,CAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAClF,CAAC;gBACD,MAAM,GAAG,MAAM,CAAC;YAClB,CAAC;YACD,IAAI,SAAS,GAAG,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,2BAA2B,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC9F,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,2BAA2B,EAAC,CAAC;gBACxD,MAAM,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC;gBAC1C,QAAQ,CAAC,KAAK,CAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBACtC,SAAS,GAAG,SAAS,CAAC;YACxB,CAAC;YACD,OAAO,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF","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\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\n\n/** @packageDocumentation\n * @module Topology\n */\n\n/**\n * Context for building a half edge graph from loops defined only by indices.\n * * Direct use case:\n * * Create the context.\n * * Repeatedly call insertLoop(indicesAroundLoop) to announce various loops.\n * * Finish by accessing the graph property.\n * @internal\n */\nexport class HalfEdgeGraphFromIndexedLoopsContext {\n public constructor(){\n this._unmatchedEdges = new Map ();\n this._graph = new HalfEdgeGraph ();\n this._halfEdgesAroundCurrentLoop = [];\n }\n private _unmatchedEdges: Map<string, HalfEdge>;\n private _graph: HalfEdgeGraph;\n public get graph(): HalfEdgeGraph {return this._graph;}\n\n // for multiple uses by insert loop.\n private _halfEdgesAroundCurrentLoop: HalfEdge[];\n private indexPairToString(index0: number, index1: number): string{\n return `${index0.toString()},${index1.toString()}`;\n }\n /** Create a loop with specified indices at its vertices.\n * * For an edge with index pair [indexA, indexB]:\n * * if [indexB, indexA] has never appeared, a HalfEdge mated pair is created.\n * * One of that mated pair becomes a HalfEdge in this loop.\n * * The other is \"unmatched\" and gets the EXTERIOR mask.\n * * When announceMatedHalfEdges(halfEdge) is called:\n * * halfEdge and its mate are \"new\".\n * * each contains (as its `i` property) one index of the [indexA,indexB] pair.\n * * all coordinates are zeros.\n * * these coordinates and indices will never be referenced again by this construction sequence.\n * * typically the caller sets the halfEdge/mate coordinates in this callback.\n * * if [indexB, indexA] appeared previously (and its outer HalfEdge was left \"unmatched\"),\n * the \"unmatched\" HalfEdge is used in the loop being constructed, and its EXTERIOR mask is cleared.\n * @param indices Array of indices around the loop. This is accessed cyclically, so first and last indices should be different.\n * @param announceMatedHalfEdges optional function to be called as mated pairs are created. At the call,\n * the given HalfEdge and its mate will have a pair of successive indices from the array in their `i` property.\n */\n public insertLoop(indices: number[], announceMatedHalfEdges?: (halfEdge: HalfEdge) => void): HalfEdge | undefined{\n const n = indices.length;\n if (n > 2) {\n let index0 = indices[n - 1];\n this._halfEdgesAroundCurrentLoop.length = 0;\n for (const index1 of indices) {\n const insideString = this.indexPairToString (index0, index1);\n const halfEdgePreviouslyConstructedFromOppositeSide: HalfEdge | undefined = this._unmatchedEdges.get (insideString);\n if (halfEdgePreviouslyConstructedFromOppositeSide === undefined) {\n // This is the first appearance of this edge in either direction.\n const outsideString = this.indexPairToString (index1, index0); // string referencing the \"other\" side of the new edge.\n const newHalfEdgeAroundLoop = this._graph.createEdgeIdId (index0, index1);\n if (announceMatedHalfEdges !== undefined)\n announceMatedHalfEdges (newHalfEdgeAroundLoop);\n this._unmatchedEdges.set (outsideString, newHalfEdgeAroundLoop.edgeMate);\n this._halfEdgesAroundCurrentLoop.push (newHalfEdgeAroundLoop);\n newHalfEdgeAroundLoop.edgeMate.setMask (HalfEdgeMask.EXTERIOR);\n } else {\n this._halfEdgesAroundCurrentLoop.push (halfEdgePreviouslyConstructedFromOppositeSide);\n halfEdgePreviouslyConstructedFromOppositeSide.clearMask (HalfEdgeMask.EXTERIOR);\n }\n index0 = index1;\n }\n let halfEdgeA = this._halfEdgesAroundCurrentLoop[this._halfEdgesAroundCurrentLoop.length - 1];\n for (const halfEdgeB of this._halfEdgesAroundCurrentLoop){\n const halfEdgeC = halfEdgeA.faceSuccessor;\n HalfEdge.pinch (halfEdgeB, halfEdgeC);\n halfEdgeA = halfEdgeB;\n }\n return this._halfEdgesAroundCurrentLoop[0];\n }\n return undefined;\n }\n}\n"]}
@@ -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\nimport { Range1d } from \"../geometry3d/Range\";\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 * @internal\r\n */\r\nexport interface HalfEdgeTestObject {\r\n testEdge(h: HalfEdge): boolean;\r\n}\r\n/**\r\n * Class to test match of half edge mask.\r\n * @internal\r\n */\r\nexport class HalfEdgeMaskTester {\r\n private _targetMask: HalfEdgeMask;\r\n private _targetValue: boolean;\r\n /**\r\n * Constructor\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 * Class for different types of searches for HalfEdgeGraph.\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphSearch {\r\n /**\r\n * Static method for face area computation -- useful as function parameter in `collectFaceAreaSummary`.\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 {\r\n return node.signedFaceArea();\r\n }\r\n /**\r\n * Return a summary of face data (e.g., area) as computed by the callback on the faces of the graph.\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 obtain area (or other numeric value). Default computes polygonal face area.\r\n */\r\n public static collectFaceAreaSummary(\r\n source: HalfEdgeGraph | HalfEdge[],\r\n collectAllNodes: boolean = false,\r\n areaFunction: NodeToNumberFunction = (node) => HalfEdgeGraphSearch.signedFaceArea(node),\r\n ): SignedDataSummary<HalfEdge> {\r\n const result = new SignedDataSummary<HalfEdge>(collectAllNodes);\r\n let allFaces: HalfEdge[];\r\n if (source instanceof HalfEdgeGraph)\r\n allFaces = source.collectFaceLoops();\r\n else\r\n allFaces = source;\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 * Search the graph for the face with the most negative area.\r\n * * If the graph has exactly one connected component, this is its outer face.\r\n * @param oneCandidateNodePerFace graph or an array containing one node from each face to be considered.\r\n * @returns node on the negative area face with largest absolute area, or `undefined` if no negative area face.\r\n */\r\n public static findMinimumAreaFace(\r\n oneCandidateNodePerFace: HalfEdgeGraph | HalfEdge[], faceAreaFunction?: NodeToNumberFunction,\r\n ): HalfEdge | undefined {\r\n const summary = HalfEdgeGraphSearch.collectFaceAreaSummary(oneCandidateNodePerFace, false, faceAreaFunction);\r\n return summary.largestNegativeItem;\r\n }\r\n /**\r\n * Test if the graph is triangulated.\r\n * * Return `false` if:\r\n * * number of positive area faces with more than 3 edges is larger than `numPositiveExceptionsAllowed`.\r\n * * graph has more than 1 negative area face when `allowMultipleNegativeAreaFaces` is `false`.\r\n * * 2-edge faces are ignored.\r\n */\r\n public static isTriangulatedCCW(\r\n source: HalfEdgeGraph | HalfEdge[],\r\n allowMultipleNegativeAreaFaces: boolean = true,\r\n numPositiveExceptionsAllowed: number = 0,\r\n ): boolean {\r\n let allFaces: HalfEdge[];\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 * Process a face during graph traversal.\r\n * @param faceSeed a node in the face.\r\n * @param mask mask to set on each node of the face.\r\n * @param allNodeStack array appended with each node of the face.\r\n * @param onePerFaceStack array appended with `faceSeed`.\r\n */\r\n private static pushAndMaskAllNodesInFace(\r\n faceSeed: HalfEdge, mask: number, allNodeStack: HalfEdge[], onePerFaceStack: HalfEdge[],\r\n ): void {\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 * Traverse (via Depth First Search) to all accessible faces from the given seed.\r\n * @param faceSeed first node to start the traverse.\r\n * @param visitMask mask applied to all faces as visited.\r\n * @param parityEdgeTester function to test if an edge is adjacent to two faces of opposite parity, e.g., a boundary\r\n * edge that separates an \"interior\" face and an \"exterior\" face. If `parityEdgeTester` is not supplied and `parityMask`\r\n * is supplied, the default parity rule is to alternate parity state in a \"bullseye\" pattern starting at the seed face,\r\n * with each successive concentric ring of faces at constant topological distance from the seed face receiving the\r\n * opposite parity state of the previous ring.\r\n * @param parityMask mask to apply to the first face and faces that share the same parity as the first face, as\r\n * determined by the parity rule. If this is `NULL_MASK`, there is no record of parity. If (non-null) parity mask\r\n * is given, on return it is entirely set or entirely clear around each face.\r\n * @returns an array that contains one representative node in each face of the connected component.\r\n */\r\n private static parityFloodFromSeed(\r\n faceSeed: HalfEdge,\r\n visitMask: HalfEdgeMask,\r\n parityEdgeTester: HalfEdgeTestObject | undefined,\r\n parityMask: HalfEdgeMask,\r\n ): HalfEdge[] {\r\n const faces: HalfEdge[] = [];\r\n if (faceSeed.isMaskSet(visitMask))\r\n return faces; // empty array\r\n const allMasks = parityMask | visitMask;\r\n const stack: HalfEdge[] = [];\r\n // the seed face is arbitrarily assigned the parity mask\r\n HalfEdgeGraphSearch.pushAndMaskAllNodesInFace(faceSeed, allMasks, stack, faces);\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 * * Correct the parity mask in the faces of a component.\r\n * * It is assumed that the parity mask is applied _consistently_ throughout the supplied faces, but maybe\r\n * not _correctly_.\r\n * * A consistently applied parity mask is \"correct\" if it is set on the negative area (\"exterior\") face of\r\n * a connected component.\r\n * * This method finds a face with negative area and toggles the mask throughout the input faces if this face\r\n * lacks the parity mask.\r\n * * In a properly merged planar subdivision there should be only one true negative area face per component.\r\n */\r\n private static correctParityInSingleComponent(parityMask: HalfEdgeMask, faces: HalfEdge[]): void {\r\n const exteriorHalfEdge = HalfEdgeGraphSearch.findMinimumAreaFace(faces);\r\n if (!exteriorHalfEdge) {\r\n // graph has all degenerate faces; do nothing\r\n } else if (exteriorHalfEdge.isMaskSet(parityMask)) {\r\n // all should be well; nothing to do\r\n } else {\r\n for (const faceSeed of faces) {\r\n if (faceSeed.isMaskSet(parityMask)) {\r\n faceSeed.clearMaskAroundFace(parityMask);\r\n } else {\r\n faceSeed.setMaskAroundFace(parityMask);\r\n }\r\n }\r\n }\r\n }\r\n /** Apply `correctParityInSingleComponent` to each array in components (quick exit if `parityMask` is `NULL_MASK`). */\r\n private static correctParityInComponentArrays(parityMask: HalfEdgeMask, components: HalfEdge[][]): void {\r\n if (parityMask === HalfEdgeMask.NULL_MASK)\r\n return;\r\n for (const facesInComponent of components)\r\n HalfEdgeGraphSearch.correctParityInSingleComponent(parityMask, facesInComponent);\r\n }\r\n /**\r\n * Collect connected components of the graph (via Depth First Search).\r\n * @param graph graph to inspect.\r\n * @param parityEdgeTester (optional) function to test if an edge is adjacent to two faces of opposite parity,\r\n * e.g., a boundary edge that separates an \"interior\" face and an \"exterior\" face. If `parityEdgeTester` is not\r\n * supplied and `parityMask` is supplied, the default parity rule is to alternate parity state in a \"bullseye\"\r\n * pattern starting at the seed face, with each successive concentric ring of faces at constant topological\r\n * distance from the seed face receiving the opposite parity state of the previous ring.\r\n * @param parityMask (optional) mask to apply to the first face and faces that share the same parity as the\r\n * first face, as determined by the parity rule. If this is `NULL_MASK` (default), there is no record of parity.\r\n * If (non-null) parity mask is given, on return it is entirely set or entirely clear around each face.\r\n * @returns the components of the graph, each component represented by an array of nodes, one node per face\r\n * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.\r\n */\r\n public static collectConnectedComponentsWithExteriorParityMasks(\r\n graph: HalfEdgeGraph,\r\n parityEdgeTester: HalfEdgeTestObject | undefined,\r\n parityMask: HalfEdgeMask = HalfEdgeMask.NULL_MASK,\r\n ): HalfEdge[][] {\r\n // Illustration of the algorithm can be found at geometry/internaldocs/Graph.md\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(visitMask)) {\r\n const newFaces = HalfEdgeGraphSearch.parityFloodFromSeed(faceSeed, visitMask, parityEdgeTester, parityMask);\r\n // parityFloodFromSeed does not return an empty array because it is called on an unvisited faceSeed\r\n components.push(newFaces);\r\n }\r\n }\r\n HalfEdgeGraphSearch.correctParityInComponentArrays(parityMask, components);\r\n return components;\r\n }\r\n /**\r\n * Breadth-first search through the connected component defined by `seed` and `ignoreMask`.\r\n * @param seed a HalfEdge in the component from which to start the search.\r\n * @param visitMask a mask to apply to visited nodes. Assumed cleared throughout component before first call.\r\n * @param ignoreMask (optional) mask preset on faces that are to be treated as _outside_ the component.\r\n * Default value is `HalfEdgeMask.EXTERIOR` to ignore exterior faces.\r\n * Pass `HalfEdgeMask.NULL_MASK` to process all faces of the component.\r\n * Note that if `ignoreMask` is set on both sides of an edge, both adjacent faces will be ignored; thus it\r\n * is generally more useful if set on only one side of an edge.\r\n * @param maxFaceCount (optional) maximum number of faces to search in the component. If nonpositive or\r\n * `undefined`, `Infinity` is used.\r\n * @param result optional array to append with HalfEdges and return as the `faces` array. This array is not\r\n * emptied first, so callers can send it into a subsequent call to continue searching the component at `nextSeed`.\r\n * @returns `faces` consists of one edge per face of the component; `nextSeed` is the seed at which to start\r\n * the next call if `maxFaceCount` is exceeded (otherwise it is `undefined`).\r\n */\r\n public static exploreComponent(\r\n seed: HalfEdge,\r\n visitMask: HalfEdgeMask,\r\n ignoreMask: HalfEdgeMask = HalfEdgeMask.EXTERIOR,\r\n maxFaceCount: number = Infinity,\r\n result?: HalfEdge[],\r\n ): { faces: HalfEdge[], nextSeed: HalfEdge | undefined} {\r\n if (maxFaceCount <= 0)\r\n maxFaceCount = Infinity;\r\n const boundaryMask: HalfEdgeMask = visitMask | ignoreMask;\r\n let numFaces = 0;\r\n const candidates: HalfEdge[] = []; // the queue\r\n const faces: HalfEdge[] = result ? result : [];\r\n candidates.push(seed);\r\n while (candidates.length > 0 && numFaces < maxFaceCount) {\r\n // TODO: shift is O(n) thus inefficient for large queues. If needed, we can\r\n // replace the queue by a circular array or use 2 stacks; both are O(1).\r\n const node = candidates.shift();\r\n if (node && !node.isMaskSet(boundaryMask)) {\r\n faces.push(node);\r\n ++numFaces;\r\n node.collectAroundFace((he: HalfEdge) => {\r\n he.setMask(visitMask);\r\n const neighbor = he.vertexSuccessor;\r\n if (!neighbor.isMaskSet(boundaryMask))\r\n candidates.push(neighbor); // enqueue neighboring face\r\n });\r\n }\r\n }\r\n if (candidates.length === 0)\r\n return { faces, nextSeed: undefined };\r\n\r\n // try to find a node at the boundary of the current component and the next\r\n let nextSeed = candidates[0];\r\n for (const candidate of candidates) {\r\n if (candidate.vertexSuccessor.isMaskSet(ignoreMask) || candidate.edgeMate.isMaskSet(ignoreMask)) {\r\n nextSeed = candidate;\r\n break;\r\n }\r\n }\r\n return { faces, nextSeed };\r\n }\r\n /**\r\n * Collect connected components of the graph (via Breadth First Search).\r\n * @param graph graph to inspect.\r\n * @param maxFaceCount (optional) maximum number of faces in each component. Should be positive; otherwise\r\n * `Infinity` is used.\r\n * @param ignoreMask (optional) mask preset on faces to ignore. Default value is `HalfEdgeMask.EXTERIOR` to ignore\r\n * exterior faces. Pass `HalfEdgeMask.NULL_MASK` to process all faces.\r\n * @returns the components of the graph, each component represented by an array of nodes, one node per face\r\n * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.\r\n */\r\n public static collectConnectedComponents(\r\n graph: HalfEdgeGraph,\r\n maxFaceCount: number = Infinity,\r\n ignoreMask: HalfEdgeMask = HalfEdgeMask.EXTERIOR,\r\n ): HalfEdge[][] {\r\n const components: HalfEdge[][] = [];\r\n if (graph.countMask(ignoreMask) === 0)\r\n ignoreMask = HalfEdgeMask.NULL_MASK;\r\n const visitMask = HalfEdgeMask.VISITED;\r\n graph.clearMask(visitMask);\r\n const boundaryMask: HalfEdgeMask = visitMask | ignoreMask;\r\n // Starting with the input node, look ahead for a boundary face. Failing that, return the input node.\r\n // Starting all floods at the boundary reduces the chance of ending up with a ring-shaped component at the boundary.\r\n const findNextFloodSeed = (index: number) => {\r\n for (let i = index; i < graph.countNodes(); ++i) {\r\n if (!graph.allHalfEdges[i].isMaskSet(boundaryMask)\r\n && graph.allHalfEdges[i].edgeMate.isMaskSet(boundaryMask)) {\r\n index = i;\r\n break;\r\n }\r\n }\r\n return index;\r\n };\r\n for (let i = 0; i < graph.countNodes(); ++i) {\r\n if (graph.allHalfEdges[i].isMaskSet(boundaryMask))\r\n continue;\r\n const i0 = findNextFloodSeed(i);\r\n let seed: HalfEdge | undefined = graph.allHalfEdges[i0];\r\n do { // flood this component\r\n const result = HalfEdgeGraphSearch.exploreComponent(seed, visitMask, ignoreMask, maxFaceCount);\r\n seed = result.nextSeed;\r\n if (result.faces.length > 0)\r\n components.push(result.faces); // each sub-component of length <= maxFaceCount is treated as a component\r\n } while (seed !== undefined);\r\n if (!graph.allHalfEdges[i].isMaskSet(visitMask))\r\n --i; // reprocess this node\r\n }\r\n return components;\r\n }\r\n /**\r\n * Test if test point (xTest,yTest) is inside/outside a face or on an edge.\r\n * * NOTE: a point outside the graph (in the exterior face) returns -1.\r\n * @param seedNode any node on the face loop.\r\n * @param xTest x coordinate of the test point.\r\n * @param yTest y coordinate of the test point.\r\n * @returns 0 if ON, 1 if IN, -1 if OUT.\r\n */\r\n public static pointInOrOnFaceXY(seedNode: HalfEdge, xTest: number, yTest: number): number {\r\n const context = new XYParitySearchContext(xTest, yTest);\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 // the test point and the face are all on line \"y = yTest\"\r\n const range = Range1d.createXX(nodeB.x, nodeB.faceSuccessor.x);\r\n return range.containsX(xTest) ? 0 : -1;\r\n }\r\n nodeB = nodeA.faceSuccessor;\r\n }\r\n // nodeB is the real start node for search, so stop when we revisit it. For each edge, accumulate parity and hits\r\n let nodeC = nodeB.faceSuccessor;\r\n for (; ;) {\r\n if (!context.advance(nodeC.x, nodeC.y)) {\r\n return context.classifyCounts();\r\n }\r\n if (nodeC === nodeB)\r\n break;\r\n nodeC = nodeC.faceSuccessor;\r\n }\r\n return context.classifyCounts();\r\n }\r\n /**\r\n * Collect boundary edges starting from `seed`.\r\n * * If `seed` is not a boundary node or is already visited, the function exists early.\r\n * @param seed start node.\r\n * @param visitMask mask to set on processed nodes.\r\n * @param isBoundaryEdge function to test if an edge in a boundary edge.\r\n * @param announceEdgeInBoundary callback invoked on each edge in the boundary loop in order. The counter is zero\r\n * for the first edge, and incremented with each successive edge.\r\n */\r\n public static collectExtendedBoundaryLoopFromSeed(\r\n seed: HalfEdge,\r\n visitMask: HalfEdgeMask,\r\n isBoundaryEdge: HalfEdgeToBooleanFunction,\r\n announceEdgeInBoundary: (edge: HalfEdge, counter: number) => void,\r\n ): void {\r\n let counter = 0;\r\n while (!seed.getMask(visitMask) && isBoundaryEdge(seed)) {\r\n announceEdgeInBoundary(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)) // end of boundary loop\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; // prevent infinite loop in case exteriorMask is not set on the edge mate of the boundary edge\r\n }\r\n }\r\n }\r\n /**\r\n * Collect boundary edges in the graph.\r\n * * A boundary edge is defined by `exteriorMask` being set on only its \"exterior\" edge mate.\r\n * * Each boundary edge is identified in the output by its edge mate that lacks `exteriorMask`.\r\n * * Each inner array is ordered in the output so that its boundary edges form a connected path. If `exteriorMask`\r\n * is preset consistently around each \"exterior\" face, these paths are loops.\r\n * @param graph the graph to query\r\n * @param exteriorMask mask preset on exactly one side of boundary edges\r\n * @returns array of boundary loops, each loop an array of the unmasked mates of boundary edges\r\n */\r\n public static collectExtendedBoundaryLoopsInGraph(graph: HalfEdgeGraph, exteriorMask: HalfEdgeMask): HalfEdge[][] {\r\n // Illustration of the algorithm can be found at geometry/internaldocs/Graph.md\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, NodeToNumberFunction } from \"./Graph\";\nimport { SignedDataSummary } from \"./SignedDataSummary\";\nimport { XYParitySearchContext } from \"./XYParitySearchContext\";\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 * * If the graph has exactly one connected component, this is its outer face.\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` (default), there is no record of parity.\n * If (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 the connected component defined by `seed` and `ignoreMask`.\n * @param seed a HalfEdge in the component from which to start the search.\n * @param visitMask a mask to apply to visited nodes. Assumed cleared throughout component before first call.\n * @param ignoreMask (optional) mask preset on faces that are to be treated as _outside_ the component.\n * Default value is `HalfEdgeMask.EXTERIOR` to ignore exterior faces.\n * Pass `HalfEdgeMask.NULL_MASK` to process all faces of the component.\n * Note that if `ignoreMask` is set on both sides of an edge, both adjacent faces will be ignored; thus it\n * is generally more useful if set on only one side of an edge.\n * @param maxFaceCount (optional) maximum number of faces to search in the component. If nonpositive or\n * `undefined`, `Infinity` is used.\n * @param result optional array to append with HalfEdges and return as the `faces` array. This array is not\n * emptied first, so callers can send it into a subsequent call to continue searching the component at `nextSeed`.\n * @returns `faces` consists of one edge per face of the component; `nextSeed` is the seed at which to start\n * the next call if `maxFaceCount` is exceeded (otherwise it is `undefined`).\n */\n public static exploreComponent(\n seed: HalfEdge,\n visitMask: HalfEdgeMask,\n ignoreMask: HalfEdgeMask = HalfEdgeMask.EXTERIOR,\n maxFaceCount: number = Infinity,\n result?: HalfEdge[],\n ): { faces: HalfEdge[], nextSeed: 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 const faces: HalfEdge[] = result ? result : [];\n candidates.push(seed);\n while (candidates.length > 0 && numFaces < maxFaceCount) {\n // TODO: shift is O(n) thus inefficient for large queues. If needed, we can\n // replace the queue by a circular array or use 2 stacks; both are O(1).\n const node = candidates.shift();\n if (node && !node.isMaskSet(boundaryMask)) {\n faces.push(node);\n ++numFaces;\n node.collectAroundFace((he: HalfEdge) => {\n he.setMask(visitMask);\n const neighbor = he.vertexSuccessor;\n if (!neighbor.isMaskSet(boundaryMask))\n candidates.push(neighbor); // enqueue neighboring face\n });\n }\n }\n if (candidates.length === 0)\n return { faces, nextSeed: undefined };\n\n // try to find a node at the boundary of the current component and the next\n let nextSeed = candidates[0];\n for (const candidate of candidates) {\n if (candidate.vertexSuccessor.isMaskSet(ignoreMask) || candidate.edgeMate.isMaskSet(ignoreMask)) {\n nextSeed = candidate;\n break;\n }\n }\n return { faces, nextSeed };\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 graph.clearMask(visitMask);\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 result = HalfEdgeGraphSearch.exploreComponent(seed, visitMask, ignoreMask, maxFaceCount);\n seed = result.nextSeed;\n if (result.faces.length > 0)\n components.push(result.faces); // each sub-component of length <= maxFaceCount is treated as a 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 * * NOTE: a point outside the graph (in the exterior face) returns -1.\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 {\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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgeGraphSpineContext.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSpineContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\nimport { Geometry } from \"../Geometry\";\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { Point3d, Vector3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { HalfEdgeGraphMerge } from \"./Merging\";\r\nimport { Triangulator } from \"./Triangulation\";\r\nimport { RegularizationContext } from \"./RegularizeFace\";\r\nimport { HalfEdgeGraphSearch, HalfEdgeMaskTester } from \"./HalfEdgeGraphSearch\";\r\nimport { Angle } from \"../geometry3d/Angle\";\r\n// cSpell:disable\r\n// const sSpineRelTol = 1.0e-8;\r\n// const sSpineGraphAbsTol = 0.0;\r\n// const sSpineGraphRelTol = 1.0e-10;\r\n\r\nfunction createNPoints(n: number): Point3d[] {\r\n const points = [];\r\n for (let i = 0; i < n; i++)\r\n points.push(Point3d.create(0, 0, 0));\r\n return points;\r\n}\r\nfunction createNVectors(n: number): Vector3d[] {\r\n const points = [];\r\n for (let i = 0; i < n; i++)\r\n points.push(Vector3d.create(0, 0, 0));\r\n return points;\r\n}\r\n// Local struct to pair a graph node with a double as a sort key for std::sort\r\nclass NodeSortKey {\r\n private _a: number;\r\n private _node: HalfEdge;\r\n public get node() { return this._node; }\r\n\r\n public constructor(node: HalfEdge, b: number) {\r\n this._node = node;\r\n this._a = b;\r\n }\r\n public static compareForSort(dataA: NodeSortKey, dataB: NodeSortKey): number { return dataA._a - dataB._a; }\r\n}\r\n\r\n/**\r\n * Context manager to hold a vu graph and do spine operations\r\n *\r\n * Spine calculations determine both (a) a \"skeletal\" network of linework that follows the interior\r\n * path through within the boundaries, and (b) a block decomposition into quads and triangles.\r\n *\r\n * Usage pattern:\r\n * ```\r\n * const sc = new HalfEdgeGraphSpineContext();\r\n * // Data setup ....\r\n * foreach polygon or polyline\r\n * {\r\n * sc.InsertEdges (edgePoints, bClosed)\r\n * }\r\n * // Analysis steps ...\r\n * * bParity = true to treat the data as a \"polygon\". The interior is determined by parity rules\r\n * and the triangulation and spine are only constructed \"inside\"\r\n * * bParity = false if \"all\" spaces are to be triangulated and spined.\r\n * * minSplitRadians -- suggested value 0.3. If this value is large, it will encourage add internal\r\n * * edges from a vertex to an edge 'across' the polygon even if it creates small angles.\r\n * * minDiagonalAngle -- suggested value 1.0. If this value is large (up to about 1.5 as max) it favors\r\n * * using triangles to navigate turns. If it is small, it favors using skewed quadrilaterals.\r\n * sc.TriangulateForSpine (bParity, minSplitRadians)\r\n * sc.MarkBoxes (true, minDiagonalAngle);\r\n * edges = sc.GetSpineEdges ();\r\n * ```\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphSpineContext {\r\n /** The Evolving graph */\r\n private _spineGraph: HalfEdgeGraph;\r\n /** mask marking edges that have been paired into quads */\r\n private _diagonalMask: HalfEdgeMask;\r\n private _boxMask: HalfEdgeMask;\r\n public get graph() { return this._spineGraph; }\r\n /**\r\n * Create a context with an empty graph.\r\n * * Reserve masks for specialized markup.\r\n */\r\n public constructor() {\r\n this._spineGraph = new HalfEdgeGraph();\r\n // vu_setTol (_spineGraph, sSpineGraphAbsTol, sSpineGraphRelTol);\r\n this._diagonalMask = this._spineGraph.grabMask();\r\n this._boxMask = this._spineGraph.grabMask();\r\n }\r\n\r\n /**\r\n * Release resources to the graph.\r\n */\r\n public teardown() {\r\n this._spineGraph.dropMask(this._diagonalMask);\r\n this._spineGraph.dropMask(this._boxMask);\r\n this._spineGraph.decommission();\r\n }\r\n\r\n // an edge (as new bvector<DPoint3d> at back, with cloned points>\r\n private addEdge(xyzOut: Point3d[][], xyzA: Point3d, xyzB: Point3d) {\r\n const newArray = [];\r\n newArray.push(xyzA.clone());\r\n newArray.push(xyzB.clone());\r\n xyzOut.push(newArray);\r\n }\r\n\r\n private getBoxCorners(diagonalNode: HalfEdge,\r\n nodes: HalfEdge[],\r\n points: Point3d[]): boolean {\r\n const diagonalMate = diagonalNode.edgeMate;\r\n nodes.length = 0;\r\n points.length = 0;\r\n if (!diagonalNode.getMask(HalfEdgeMask.BOUNDARY_EDGE)\r\n && diagonalNode.countEdgesAroundFace() === 3\r\n && diagonalMate.countEdgesAroundFace() === 3) {\r\n const nodeA = diagonalMate.faceSuccessor;\r\n nodes.push(nodeA);\r\n nodes.push(nodeA.faceSuccessor);\r\n const nodeB = diagonalNode.faceSuccessor;\r\n nodes.push(nodeB);\r\n nodes.push(nodeB.faceSuccessor);\r\n for (let i = 0; i < 4; i++)\r\n points.push(Point3d.create(nodes[i].x, nodes[i].y));\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n // Compute bisectors of the quad.\r\n // function key is the smaller absolute angle between the bisectors.\r\n // (pi/2 is max possible value).\r\n private diagonalKeyFunc(pDiagonalNode: HalfEdge): number {\r\n\r\n const nodes: HalfEdge[] = [];\r\n const points: Point3d[] = [];\r\n if (this.getBoxCorners(pDiagonalNode, nodes, points)) {\r\n const xyzA = points[0];\r\n const xyzB = points[1];\r\n const xyzC = points[2];\r\n const xyzD = points[3];\r\n const xyzAB = xyzA.interpolate(0.5, xyzB);\r\n const xyzBC = xyzB.interpolate(0.5, xyzC);\r\n const xyzCD = xyzC.interpolate(0.5, xyzD);\r\n const xyzDA = xyzD.interpolate(0.5, xyzA);\r\n\r\n const vectorAB = Vector3d.createStartEnd(xyzA, xyzB);\r\n const vectorBC = Vector3d.createStartEnd(xyzB, xyzC);\r\n const vectorCD = Vector3d.createStartEnd(xyzC, xyzD);\r\n const vectorDA = Vector3d.createStartEnd(xyzD, xyzA);\r\n\r\n const vectorABToCD = Vector3d.createStartEnd(xyzCD, xyzAB);\r\n const vectorBCToDA = Vector3d.createStartEnd(xyzDA, xyzBC);\r\n vectorABToCD.z = 0.0;\r\n vectorBCToDA.z = 0.0;\r\n const thetaAB = vectorABToCD.smallerUnorientedAngleTo(vectorAB).radians;\r\n const thetaBC = vectorBCToDA.smallerUnorientedAngleTo(vectorBC).radians;\r\n const thetaCD = vectorABToCD.smallerUnorientedAngleTo(vectorCD).radians;\r\n const thetaDA = vectorBCToDA.smallerUnorientedAngleTo(vectorDA).radians;\r\n\r\n const alpha = thetaAB < thetaCD ? thetaAB : thetaCD;\r\n const beta = thetaBC < thetaDA ? thetaBC : thetaDA;\r\n return alpha < beta ? alpha : beta;\r\n }\r\n\r\n return Number.NEGATIVE_INFINITY;\r\n }\r\n\r\n // Select a branch point in a triangle.\r\n // This may be the centroid or the midpoint of an edge joining midpoints of a pair of edges.\r\n private selectTriangleInteriorPoint(pXYZ: Point3d[]): Point3d {\r\n\r\n const xyz = createNPoints(6);\r\n const xyzMid = createNPoints(6); // Midpoints of each edge.\r\n const interiorCandidate = createNPoints(4); // for i in {012}, [i] is midpoint of midpoint[i+1] and midpoint[i+2].\r\n // [3] is centroid.\r\n const edgeVector = createNVectors(6);\r\n const centroid = Point3d.create();\r\n for (let i = 0; i < 3; i++) {\r\n xyz[i] = xyz[i + 3] = pXYZ[i];\r\n centroid.addInPlace(xyz[i]);\r\n }\r\n centroid.scaleInPlace(1.0 / 3.0);\r\n\r\n // Edge midpoints ...\r\n for (let i = 0; i < 3; i++) {\r\n xyzMid[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n xyzMid[i + 3] = xyzMid[i];\r\n edgeVector[i] = Vector3d.createStartEnd(xyz[i], xyz[i + 1]); // use wraparound\r\n edgeVector[i + 3] = edgeVector[i];\r\n }\r\n\r\n // Midpoints of midpoint-to-midpoint connections ..\r\n for (let i = 0; i < 3; i++) {\r\n const i1 = i + 1;\r\n const i2 = i + 2;\r\n interiorCandidate[i] = xyzMid[i1].interpolate(0.5, xyzMid[i2]);\r\n }\r\n\r\n interiorCandidate[3] = centroid;\r\n\r\n let bestAngle = Number.NEGATIVE_INFINITY;\r\n let bestIndex = -1;\r\n const theta: number[] = [0, 0, 0];\r\n let thetaMin;\r\n for (let k: number = 0; k < 4; k++) {\r\n // Measure angles from edge midpoints towards interior candidate.\r\n thetaMin = Number.POSITIVE_INFINITY;\r\n for (let i: number = 0; i < 3; i++) {\r\n const edgeToInterior = Vector3d.createStartEnd(xyzMid[i], interiorCandidate[k]);\r\n theta[i] = edgeVector[i].smallerUnorientedAngleTo(edgeToInterior).radians;\r\n if (theta[i] < thetaMin)\r\n thetaMin = theta[i];\r\n }\r\n if (thetaMin > bestAngle) {\r\n bestAngle = thetaMin;\r\n bestIndex = k;\r\n }\r\n }\r\n return interiorCandidate[bestIndex];\r\n }\r\n\r\n private markBox(pA: HalfEdge): void {\r\n\r\n const pB = pA.edgeMate;\r\n pA.setMask(this._diagonalMask);\r\n pB.setMask(this._diagonalMask);\r\n pA.setMaskAroundFace(this._boxMask);\r\n pB.setMaskAroundFace(this._boxMask);\r\n }\r\n\r\n private setSortedDiagonalMasks(minA: number): number {\r\n\r\n const candidates: NodeSortKey[] = [];\r\n let numDiagonal = 0;\r\n for (const node of this._spineGraph.allHalfEdges) {\r\n const b = this.diagonalKeyFunc(node);\r\n if (b > minA)\r\n candidates.push(new NodeSortKey(node, b));\r\n }\r\n\r\n candidates.sort((dataA, dataB) => NodeSortKey.compareForSort(dataA, dataB));\r\n\r\n let key;\r\n while (undefined !== (key = candidates.pop())) {\r\n const pA = key.node;\r\n const pB = pA.edgeMate;\r\n if (!pA.getMask(this._boxMask)\r\n && !pB.getMask(this._boxMask)) {\r\n this.markBox(pA);\r\n numDiagonal++;\r\n }\r\n }\r\n return numDiagonal;\r\n }\r\n\r\n /// <param name=\"xyzA\">Vertex whose angle is being split</param>\r\n private splitOK(xyzA: Point3d, xyzB: Point3d, xyzQ: Point3d, xyzC: Point3d, minAngle: number): boolean {\r\n\r\n const vectorAB = Vector3d.createStartEnd(xyzA, xyzB);\r\n const vectorAQ = Vector3d.createStartEnd(xyzA, xyzQ);\r\n const vectorAC = Vector3d.createStartEnd(xyzA, xyzC);\r\n const angleBAQ = vectorAB.angleToXY(vectorAQ).radians;\r\n const angleQAC = vectorAQ.angleToXY(vectorAC).radians;\r\n return Math.abs(angleBAQ) > minAngle && Math.abs(angleQAC) > minAngle;\r\n }\r\n\r\n // Search a triangulation for vertices which have\r\n // (a) pre-split angle greater than 90 degrees\r\n // (b) the opposite edge is a boundary.\r\n // (c) each post split angle is less than minSplitRadians\r\n // Drop a perpenedicular to that boundary.\r\n // return the number of edges added.\r\n private addPerpendicularsToBoundaries(minSplitRadians: number, minCandidateRadians: number): number {\r\n\r\n let numAdd = 0;\r\n for (const pA of this._spineGraph.allHalfEdges) {\r\n const pB = pA.faceSuccessor;\r\n const pC = pB.faceSuccessor;\r\n if (!pA.getMask(HalfEdgeMask.EXTERIOR)\r\n && !pA.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion\r\n && !pC.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion\r\n && pB.getMask(HalfEdgeMask.BOUNDARY_EDGE)\r\n && pC.faceSuccessor === pA\r\n ) {\r\n const vectorAB = pA.getVector2dAlongEdge();\r\n const vectorBC = pB.getVector2dAlongEdge();\r\n const vectorCA = pC.getVector2dAlongEdge();\r\n const candidateRadians = Math.PI - vectorCA.angleTo(vectorAB).radians;\r\n // const candidateDot = vectorCA.DotProduct (vectorAB);\r\n if (candidateRadians > minCandidateRadians) { // vectorCA.DotProduct (vectorAB) > 0.0)\r\n const bb = vectorBC.dotProduct(vectorBC);\r\n const ba = -vectorBC.dotProduct(vectorAB);\r\n const s = Geometry.conditionalDivideFraction(ba, bb);\r\n if (s !== undefined && s > 0.0 && s < 1.0) {\r\n const xyzA = pA.getPoint3d();\r\n const xyzB = pB.getPoint3d();\r\n const xyzC = pC.getPoint3d();\r\n const xyzE = xyzB.interpolate(s, xyzC);\r\n if (this.splitOK(xyzA, xyzB, xyzE, xyzC, minSplitRadians)) {\r\n const pE = this._spineGraph.splitEdgeAtFraction(pB, s);\r\n const pA1 = this._spineGraph.createEdgeHalfEdgeHalfEdge(pA, 0, pE, 0);\r\n pA1.setXYZFrom(pA);\r\n pE.setXYZAroundVertex(xyzE.x, xyzE.y, xyzE.z);\r\n numAdd++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return numAdd;\r\n }\r\n\r\n private getSpineEdgesInQuad(\r\n pFace: HalfEdge,\r\n xyzOut: Point3d[][],\r\n bIncludeInterior: boolean,\r\n // true to include the edge to boundary when the qued is a dead end.\r\n bIncludeFinal: boolean,\r\n // true to include the two adjacent edges to boundary if the quad is at a corner.\r\n bIncludeCornerSpokes: boolean): boolean {\r\n\r\n if (pFace.countEdgesAroundFace() !== 4)\r\n return false;\r\n const pNode: HalfEdge[] = [];\r\n const xyz = createNPoints(8);\r\n const midpoint = createNPoints(8);\r\n pNode[0] = pNode[4] = pFace;\r\n pNode[1] = pNode[5] = pNode[0].faceSuccessor;\r\n pNode[2] = pNode[6] = pNode[1].faceSuccessor;\r\n pNode[3] = pNode[7] = pNode[2].faceSuccessor;\r\n let numBoundary = 0;\r\n let numInterior = 0;\r\n const iBoundary: number[] = [];\r\n const iInterior: number[] = [];\r\n const bIsBoundary: boolean[] = [];\r\n const centroid = Point3d.create();\r\n for (let i: number = 0; i < 4; i++) {\r\n bIsBoundary[i] = 0 !== pNode[i].getMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n if (pNode[i].getMask(HalfEdgeMask.BOUNDARY_EDGE))\r\n iBoundary[numBoundary++] = i;\r\n else\r\n iInterior[numInterior++] = i;\r\n xyz[i] = pNode[i].getPoint3d();\r\n xyz[i + 4] = xyz[i];\r\n centroid.addInPlace(xyz[i]);\r\n }\r\n for (let i: number = 0; i < 4; i++) {\r\n midpoint[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n midpoint[i + 4] = midpoint[i];\r\n }\r\n\r\n centroid.scaleInPlace(0.25);\r\n if (numBoundary === 0 || numBoundary === 1) {\r\n for (let i: number = 0; i < numInterior; i++)\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[i]], centroid);\r\n } else if (numBoundary === 4) {\r\n for (let i: number = 0; i < numBoundary; i++)\r\n if (bIncludeFinal)\r\n this.addEdge(xyzOut, midpoint[i], centroid);\r\n } else if (numBoundary === 2) {\r\n if (iInterior[1] === iInterior[0] + 2) {\r\n // Spine enters one end, exits the other ..\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[0]], midpoint[iInterior[1]]);\r\n } else {\r\n // Block sits as exterior corner. Let the two spines continue to their opposite faces ..\r\n for (let i: number = 0; i < 4; i++)\r\n if ((bIsBoundary[i] && bIncludeCornerSpokes)\r\n || (!bIsBoundary[i] && bIncludeInterior))\r\n this.addEdge(xyzOut, midpoint[i], centroid);\r\n }\r\n } else if (numBoundary === 3) {\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, midpoint[iInterior[0]], centroid);\r\n if (bIncludeFinal)\r\n this.addEdge(xyzOut, centroid, midpoint[iInterior[0] + 2]);\r\n }\r\n return true;\r\n }\r\n\r\n private getSpineEdgesInTriangle(\r\n pFace: HalfEdge, xyzOut: Point3d[][],\r\n bIncludeInterior: boolean,\r\n bIncludeFinal: boolean): boolean {\r\n\r\n if (pFace.countEdgesAroundFace() !== 3)\r\n return false;\r\n let n = 0;\r\n const xyzMidpoint = createNPoints(6);\r\n const xyz = createNPoints(6);\r\n const xyzCentroid = Point3d.createZero();\r\n const isBoundary: boolean[] = [];\r\n let numBoundary = 0;\r\n let lastBoundary = -1;\r\n let lastInterior = -1;\r\n let currentEdge = pFace;\r\n do {\r\n xyz[n] = currentEdge.getPoint3d();\r\n xyzCentroid.addInPlace(xyz[n]);\r\n isBoundary[n] = false;\r\n if (currentEdge.getMask(HalfEdgeMask.BOUNDARY_EDGE)) {\r\n isBoundary[n] = true;\r\n numBoundary++;\r\n lastBoundary = n;\r\n } else {\r\n lastInterior = n;\r\n }\r\n xyz[n + 3] = xyz[n];\r\n isBoundary[n + 3] = isBoundary[n];\r\n n++;\r\n } while ((currentEdge = currentEdge.faceSuccessor) !== pFace);\r\n\r\n for (let i: number = 0; i < 3; i++) {\r\n xyzMidpoint[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\r\n xyzMidpoint[i + 3] = xyzMidpoint[i];\r\n }\r\n\r\n xyzCentroid.scaleInPlace(1.0 / 3.0);\r\n\r\n if (numBoundary === 0) {\r\n // Interior branch\r\n const xyzInterior = this.selectTriangleInteriorPoint(xyz);\r\n if (bIncludeInterior) {\r\n this.addEdge(xyzOut, xyzMidpoint[0], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[1], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[2], xyzInterior);\r\n }\r\n } else if (numBoundary === 1) {\r\n if (bIncludeInterior)\r\n this.addEdge(xyzOut, xyzMidpoint[lastBoundary + 1], xyzMidpoint[lastBoundary + 2]);\r\n } else if (numBoundary === 2) {\r\n if (bIncludeFinal && lastInterior >= 0)\r\n this.addEdge(xyzOut, xyzMidpoint[lastInterior], xyz[lastInterior + 2]);\r\n } else if (numBoundary === 3) {\r\n const xyzInterior = this.selectTriangleInteriorPoint(xyz);\r\n if (bIncludeFinal) {\r\n this.addEdge(xyzOut, xyzMidpoint[0], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[1], xyzInterior);\r\n this.addEdge(xyzOut, xyzMidpoint[2], xyzInterior);\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /** Add a polyline to the graph.\r\n * * This may be called multiple times\r\n */\r\n public insertEdges(xyzIn: Point3d[], bClosed: boolean): void {\r\n let pPreviousB, pFirstA;\r\n for (let i: number = 1; i < xyzIn.length; i++) {\r\n const nodeA = this._spineGraph.createEdgeXYZXYZ(\r\n xyzIn[i - 1].x, xyzIn[i - 1].y, 0, 0,\r\n xyzIn[i].x, xyzIn[i].y, 0, 0);\r\n const nodeB = nodeA.faceSuccessor;\r\n nodeA.setMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n nodeB.setMask(HalfEdgeMask.BOUNDARY_EDGE);\r\n if (pPreviousB === undefined) {\r\n pFirstA = nodeA;\r\n } else {\r\n HalfEdge.pinch(pPreviousB, nodeA);\r\n }\r\n pPreviousB = nodeB;\r\n }\r\n if (bClosed && pFirstA !== undefined && pPreviousB !== undefined)\r\n HalfEdge.pinch(pPreviousB, pFirstA);\r\n }\r\n /**\r\n * Look for trivial (2 edge) faces that have exteriorMask and non-masked on both sides.\r\n * * clear the mask\r\n * @param exteriorMask\r\n */\r\n private purgeNullFaces(exteriorMask: HalfEdgeMask) {\r\n for (const nodeA of this._spineGraph.allHalfEdges) {\r\n const nodeB = nodeA.faceSuccessor;\r\n const nodeC = nodeB.faceSuccessor;\r\n if (nodeB !== nodeA && nodeC === nodeA) {\r\n if (nodeA.getMask(exteriorMask) && nodeB.getMask(exteriorMask)) {\r\n const mateA = nodeA.edgeMate;\r\n const mateB = nodeB.edgeMate;\r\n if (!mateA.getMask(exteriorMask) && !mateB.getMask(exteriorMask)) {\r\n nodeA.clearMask(exteriorMask);\r\n nodeB.clearMask(exteriorMask);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n private static _regularize1 = true;\r\n private static _regularize2 = false;\r\n /**\r\n * Triangulate the graph for the edges that have been inserted.\r\n * @param applyParity if true ()\r\n * @param minSplitRadians smallest allowed angle in the split sector that is split.\r\n */\r\n public triangulateForSpine(applyParity: boolean = true, minSplitRadians: number = 0.3): void {\r\n\r\n const sMaxSplit = 20;\r\n const sMinCandidateRadians = 1.0;\r\n let numSplit = 0;\r\n HalfEdgeGraphMerge.splitIntersectingEdges(this.graph);\r\n HalfEdgeGraphMerge.clusterAndMergeXYTheta(this.graph);\r\n\r\n const context1 = new RegularizationContext(this.graph);\r\n context1.regularizeGraph(HalfEdgeGraphSpineContext._regularize1, false);\r\n const context2 = new RegularizationContext(this.graph);\r\n context2.regularizeGraph(false, HalfEdgeGraphSpineContext._regularize2);\r\n if (applyParity) {\r\n HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(this.graph,\r\n new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR);\r\n this.purgeNullFaces(HalfEdgeMask.EXTERIOR);\r\n }\r\n\r\n Triangulator.triangulateAllPositiveAreaFaces(this.graph);\r\n Triangulator.flipTriangles(this.graph);\r\n\r\n while (numSplit++ < sMaxSplit) {\r\n const numPerp = this.addPerpendicularsToBoundaries(minSplitRadians, sMinCandidateRadians);\r\n if (numPerp <= 0)\r\n break;\r\n Triangulator.flipTriangles(this.graph);\r\n }\r\n }\r\n\r\n // Find pseudo spine edges\r\n // Optionally include pure internal midline segments.\r\n // Optionally include midline segments into \"dead end\"\r\n // Optionally include adjacent spokes to corner.\r\n /**\r\n * Retrieve edges of the spine as arrays of points.\r\n * @param bIncludeInterior true to include fully internal segments\r\n * @param bIncludeFinal true to include segments that terminate at a boundary\r\n * @param bIncludeCornerSpokes\r\n * @return array of line data.\r\n */\r\n public getSpineEdges(bIncludeInterior: boolean = true, bIncludeFinal: boolean = true, bIncludeCornerSpokes: boolean = true): Point3d[][] {\r\n const xyzOut: Point3d[][] = [];\r\n this._spineGraph.announceFaceLoops(\r\n (_graph: HalfEdgeGraph, faceSeed: HalfEdge) => {\r\n if (!faceSeed.getMask(HalfEdgeMask.EXTERIOR)) {\r\n if (this.getSpineEdgesInTriangle(faceSeed, xyzOut, bIncludeInterior, bIncludeFinal)) {\r\n } else if (this.getSpineEdgesInQuad(faceSeed, xyzOut, bIncludeInterior, bIncludeFinal, bIncludeCornerSpokes)) {\r\n }\r\n }\r\n return true;\r\n });\r\n return xyzOut;\r\n }\r\n\r\n /**\r\n * Intermediate markup step to identify quads between corresponding boundary edges.\r\n * * search for and mark triangle edges that should be treated as diagonal of a quad\r\n * * Angle logic is:\r\n * * In a candidate quad (formed by joining triangles that share an edge)\r\n * * form segments between opposite edges of the quad.\r\n * * compute angles between these segments and the edges of their quads.\r\n * * if this angle is larger than minAngleRadians, accept this as a quad.\r\n * * recommended angle is between 15 and 5 degrees; 50 degrees is typical\r\n * @param bDeleteDiagonals if true, eliminate the diagonals.\r\n * @param minAngleRadians angle tolerance, as described above.\r\n */\r\n public consolidateTrianglesToQuads(bDeleteDiagonals: boolean, minAngle: Angle = Angle.createDegrees(50)): number {\r\n\r\n const numDiagonal = this.setSortedDiagonalMasks(minAngle.radians);\r\n if (bDeleteDiagonals && numDiagonal > 0) {\r\n this.graph.yankAndDeleteEdges(\r\n (node: HalfEdge) => node.getMask(this._diagonalMask));\r\n }\r\n return numDiagonal;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"HalfEdgeGraphSpineContext.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphSpineContext.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/** @packageDocumentation\n * @module Topology\n */\nimport { Geometry } from \"../Geometry\";\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\nimport { Point3d, Vector3d } from \"../geometry3d/Point3dVector3d\";\nimport { HalfEdgeGraphMerge } from \"./Merging\";\nimport { Triangulator } from \"./Triangulation\";\nimport { RegularizationContext } from \"./RegularizeFace\";\nimport { HalfEdgeGraphSearch, HalfEdgeMaskTester } from \"./HalfEdgeGraphSearch\";\nimport { Angle } from \"../geometry3d/Angle\";\n// cSpell:disable\n// const sSpineRelTol = 1.0e-8;\n// const sSpineGraphAbsTol = 0.0;\n// const sSpineGraphRelTol = 1.0e-10;\n\nfunction createNPoints(n: number): Point3d[] {\n const points = [];\n for (let i = 0; i < n; i++)\n points.push(Point3d.create(0, 0, 0));\n return points;\n}\nfunction createNVectors(n: number): Vector3d[] {\n const points = [];\n for (let i = 0; i < n; i++)\n points.push(Vector3d.create(0, 0, 0));\n return points;\n}\n// Local struct to pair a graph node with a double as a sort key for std::sort\nclass NodeSortKey {\n private _a: number;\n private _node: HalfEdge;\n public get node() { return this._node; }\n\n public constructor(node: HalfEdge, b: number) {\n this._node = node;\n this._a = b;\n }\n public static compareForSort(dataA: NodeSortKey, dataB: NodeSortKey): number { return dataA._a - dataB._a; }\n}\n\n/**\n * Context manager to hold a vu graph and do spine operations\n *\n * Spine calculations determine both (a) a \"skeletal\" network of linework that follows the interior\n * path through within the boundaries, and (b) a block decomposition into quads and triangles.\n *\n * Usage pattern:\n * ```\n * const sc = new HalfEdgeGraphSpineContext();\n * // Data setup ....\n * foreach polygon or polyline\n * {\n * sc.InsertEdges (edgePoints, bClosed)\n * }\n * // Analysis steps ...\n * * bParity = true to treat the data as a \"polygon\". The interior is determined by parity rules\n * and the triangulation and spine are only constructed \"inside\"\n * * bParity = false if \"all\" spaces are to be triangulated and spined.\n * * minSplitRadians -- suggested value 0.3. If this value is large, it will encourage add internal\n * * edges from a vertex to an edge 'across' the polygon even if it creates small angles.\n * * minDiagonalAngle -- suggested value 1.0. If this value is large (up to about 1.5 as max) it favors\n * * using triangles to navigate turns. If it is small, it favors using skewed quadrilaterals.\n * sc.TriangulateForSpine (bParity, minSplitRadians)\n * sc.MarkBoxes (true, minDiagonalAngle);\n * edges = sc.GetSpineEdges ();\n * ```\n * @internal\n */\nexport class HalfEdgeGraphSpineContext {\n /** The Evolving graph */\n private _spineGraph: HalfEdgeGraph;\n /** mask marking edges that have been paired into quads */\n private _diagonalMask: HalfEdgeMask;\n private _boxMask: HalfEdgeMask;\n public get graph() { return this._spineGraph; }\n /**\n * Create a context with an empty graph.\n * * Reserve masks for specialized markup.\n */\n public constructor() {\n this._spineGraph = new HalfEdgeGraph();\n // vu_setTol (_spineGraph, sSpineGraphAbsTol, sSpineGraphRelTol);\n this._diagonalMask = this._spineGraph.grabMask();\n this._boxMask = this._spineGraph.grabMask();\n }\n\n /**\n * Release resources to the graph.\n */\n public teardown() {\n this._spineGraph.dropMask(this._diagonalMask);\n this._spineGraph.dropMask(this._boxMask);\n this._spineGraph.decommission();\n }\n\n // an edge (as new bvector<DPoint3d> at back, with cloned points>\n private addEdge(xyzOut: Point3d[][], xyzA: Point3d, xyzB: Point3d) {\n const newArray = [];\n newArray.push(xyzA.clone());\n newArray.push(xyzB.clone());\n xyzOut.push(newArray);\n }\n\n private getBoxCorners(diagonalNode: HalfEdge,\n nodes: HalfEdge[],\n points: Point3d[]): boolean {\n const diagonalMate = diagonalNode.edgeMate;\n nodes.length = 0;\n points.length = 0;\n if (!diagonalNode.getMask(HalfEdgeMask.BOUNDARY_EDGE)\n && diagonalNode.countEdgesAroundFace() === 3\n && diagonalMate.countEdgesAroundFace() === 3) {\n const nodeA = diagonalMate.faceSuccessor;\n nodes.push(nodeA);\n nodes.push(nodeA.faceSuccessor);\n const nodeB = diagonalNode.faceSuccessor;\n nodes.push(nodeB);\n nodes.push(nodeB.faceSuccessor);\n for (let i = 0; i < 4; i++)\n points.push(Point3d.create(nodes[i].x, nodes[i].y));\n return true;\n }\n return false;\n }\n\n // Compute bisectors of the quad.\n // function key is the smaller absolute angle between the bisectors.\n // (pi/2 is max possible value).\n private diagonalKeyFunc(pDiagonalNode: HalfEdge): number {\n\n const nodes: HalfEdge[] = [];\n const points: Point3d[] = [];\n if (this.getBoxCorners(pDiagonalNode, nodes, points)) {\n const xyzA = points[0];\n const xyzB = points[1];\n const xyzC = points[2];\n const xyzD = points[3];\n const xyzAB = xyzA.interpolate(0.5, xyzB);\n const xyzBC = xyzB.interpolate(0.5, xyzC);\n const xyzCD = xyzC.interpolate(0.5, xyzD);\n const xyzDA = xyzD.interpolate(0.5, xyzA);\n\n const vectorAB = Vector3d.createStartEnd(xyzA, xyzB);\n const vectorBC = Vector3d.createStartEnd(xyzB, xyzC);\n const vectorCD = Vector3d.createStartEnd(xyzC, xyzD);\n const vectorDA = Vector3d.createStartEnd(xyzD, xyzA);\n\n const vectorABToCD = Vector3d.createStartEnd(xyzCD, xyzAB);\n const vectorBCToDA = Vector3d.createStartEnd(xyzDA, xyzBC);\n vectorABToCD.z = 0.0;\n vectorBCToDA.z = 0.0;\n const thetaAB = vectorABToCD.smallerUnorientedAngleTo(vectorAB).radians;\n const thetaBC = vectorBCToDA.smallerUnorientedAngleTo(vectorBC).radians;\n const thetaCD = vectorABToCD.smallerUnorientedAngleTo(vectorCD).radians;\n const thetaDA = vectorBCToDA.smallerUnorientedAngleTo(vectorDA).radians;\n\n const alpha = thetaAB < thetaCD ? thetaAB : thetaCD;\n const beta = thetaBC < thetaDA ? thetaBC : thetaDA;\n return alpha < beta ? alpha : beta;\n }\n\n return Number.NEGATIVE_INFINITY;\n }\n\n // Select a branch point in a triangle.\n // This may be the centroid or the midpoint of an edge joining midpoints of a pair of edges.\n private selectTriangleInteriorPoint(pXYZ: Point3d[]): Point3d {\n\n const xyz = createNPoints(6);\n const xyzMid = createNPoints(6); // Midpoints of each edge.\n const interiorCandidate = createNPoints(4); // for i in {012}, [i] is midpoint of midpoint[i+1] and midpoint[i+2].\n // [3] is centroid.\n const edgeVector = createNVectors(6);\n const centroid = Point3d.create();\n for (let i = 0; i < 3; i++) {\n xyz[i] = xyz[i + 3] = pXYZ[i];\n centroid.addInPlace(xyz[i]);\n }\n centroid.scaleInPlace(1.0 / 3.0);\n\n // Edge midpoints ...\n for (let i = 0; i < 3; i++) {\n xyzMid[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\n xyzMid[i + 3] = xyzMid[i];\n edgeVector[i] = Vector3d.createStartEnd(xyz[i], xyz[i + 1]); // use wraparound\n edgeVector[i + 3] = edgeVector[i];\n }\n\n // Midpoints of midpoint-to-midpoint connections ..\n for (let i = 0; i < 3; i++) {\n const i1 = i + 1;\n const i2 = i + 2;\n interiorCandidate[i] = xyzMid[i1].interpolate(0.5, xyzMid[i2]);\n }\n\n interiorCandidate[3] = centroid;\n\n let bestAngle = Number.NEGATIVE_INFINITY;\n let bestIndex = -1;\n const theta: number[] = [0, 0, 0];\n let thetaMin;\n for (let k: number = 0; k < 4; k++) {\n // Measure angles from edge midpoints towards interior candidate.\n thetaMin = Number.POSITIVE_INFINITY;\n for (let i: number = 0; i < 3; i++) {\n const edgeToInterior = Vector3d.createStartEnd(xyzMid[i], interiorCandidate[k]);\n theta[i] = edgeVector[i].smallerUnorientedAngleTo(edgeToInterior).radians;\n if (theta[i] < thetaMin)\n thetaMin = theta[i];\n }\n if (thetaMin > bestAngle) {\n bestAngle = thetaMin;\n bestIndex = k;\n }\n }\n return interiorCandidate[bestIndex];\n }\n\n private markBox(pA: HalfEdge): void {\n\n const pB = pA.edgeMate;\n pA.setMask(this._diagonalMask);\n pB.setMask(this._diagonalMask);\n pA.setMaskAroundFace(this._boxMask);\n pB.setMaskAroundFace(this._boxMask);\n }\n\n private setSortedDiagonalMasks(minA: number): number {\n\n const candidates: NodeSortKey[] = [];\n let numDiagonal = 0;\n for (const node of this._spineGraph.allHalfEdges) {\n const b = this.diagonalKeyFunc(node);\n if (b > minA)\n candidates.push(new NodeSortKey(node, b));\n }\n\n candidates.sort((dataA, dataB) => NodeSortKey.compareForSort(dataA, dataB));\n\n let key;\n while (undefined !== (key = candidates.pop())) {\n const pA = key.node;\n const pB = pA.edgeMate;\n if (!pA.getMask(this._boxMask)\n && !pB.getMask(this._boxMask)) {\n this.markBox(pA);\n numDiagonal++;\n }\n }\n return numDiagonal;\n }\n\n /// <param name=\"xyzA\">Vertex whose angle is being split</param>\n private splitOK(xyzA: Point3d, xyzB: Point3d, xyzQ: Point3d, xyzC: Point3d, minAngle: number): boolean {\n\n const vectorAB = Vector3d.createStartEnd(xyzA, xyzB);\n const vectorAQ = Vector3d.createStartEnd(xyzA, xyzQ);\n const vectorAC = Vector3d.createStartEnd(xyzA, xyzC);\n const angleBAQ = vectorAB.angleToXY(vectorAQ).radians;\n const angleQAC = vectorAQ.angleToXY(vectorAC).radians;\n return Math.abs(angleBAQ) > minAngle && Math.abs(angleQAC) > minAngle;\n }\n\n // Search a triangulation for vertices which have\n // (a) pre-split angle greater than 90 degrees\n // (b) the opposite edge is a boundary.\n // (c) each post split angle is less than minSplitRadians\n // Drop a perpenedicular to that boundary.\n // return the number of edges added.\n private addPerpendicularsToBoundaries(minSplitRadians: number, minCandidateRadians: number): number {\n\n let numAdd = 0;\n for (const pA of this._spineGraph.allHalfEdges) {\n const pB = pA.faceSuccessor;\n const pC = pB.faceSuccessor;\n if (!pA.getMask(HalfEdgeMask.EXTERIOR)\n && !pA.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion\n && !pC.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion\n && pB.getMask(HalfEdgeMask.BOUNDARY_EDGE)\n && pC.faceSuccessor === pA\n ) {\n const vectorAB = pA.getVector2dAlongEdge();\n const vectorBC = pB.getVector2dAlongEdge();\n const vectorCA = pC.getVector2dAlongEdge();\n const candidateRadians = Math.PI - vectorCA.angleTo(vectorAB).radians;\n // const candidateDot = vectorCA.DotProduct (vectorAB);\n if (candidateRadians > minCandidateRadians) { // vectorCA.DotProduct (vectorAB) > 0.0)\n const bb = vectorBC.dotProduct(vectorBC);\n const ba = -vectorBC.dotProduct(vectorAB);\n const s = Geometry.conditionalDivideFraction(ba, bb);\n if (s !== undefined && s > 0.0 && s < 1.0) {\n const xyzA = pA.getPoint3d();\n const xyzB = pB.getPoint3d();\n const xyzC = pC.getPoint3d();\n const xyzE = xyzB.interpolate(s, xyzC);\n if (this.splitOK(xyzA, xyzB, xyzE, xyzC, minSplitRadians)) {\n const pE = this._spineGraph.splitEdgeAtFraction(pB, s);\n const pA1 = this._spineGraph.createEdgeHalfEdgeHalfEdge(pA, 0, pE, 0);\n pA1.setXYZFrom(pA);\n pE.setXYZAroundVertex(xyzE.x, xyzE.y, xyzE.z);\n numAdd++;\n }\n }\n }\n }\n }\n return numAdd;\n }\n\n private getSpineEdgesInQuad(\n pFace: HalfEdge,\n xyzOut: Point3d[][],\n bIncludeInterior: boolean,\n // true to include the edge to boundary when the qued is a dead end.\n bIncludeFinal: boolean,\n // true to include the two adjacent edges to boundary if the quad is at a corner.\n bIncludeCornerSpokes: boolean): boolean {\n\n if (pFace.countEdgesAroundFace() !== 4)\n return false;\n const pNode: HalfEdge[] = [];\n const xyz = createNPoints(8);\n const midpoint = createNPoints(8);\n pNode[0] = pNode[4] = pFace;\n pNode[1] = pNode[5] = pNode[0].faceSuccessor;\n pNode[2] = pNode[6] = pNode[1].faceSuccessor;\n pNode[3] = pNode[7] = pNode[2].faceSuccessor;\n let numBoundary = 0;\n let numInterior = 0;\n const iBoundary: number[] = [];\n const iInterior: number[] = [];\n const bIsBoundary: boolean[] = [];\n const centroid = Point3d.create();\n for (let i: number = 0; i < 4; i++) {\n bIsBoundary[i] = 0 !== pNode[i].getMask(HalfEdgeMask.BOUNDARY_EDGE);\n if (pNode[i].getMask(HalfEdgeMask.BOUNDARY_EDGE))\n iBoundary[numBoundary++] = i;\n else\n iInterior[numInterior++] = i;\n xyz[i] = pNode[i].getPoint3d();\n xyz[i + 4] = xyz[i];\n centroid.addInPlace(xyz[i]);\n }\n for (let i: number = 0; i < 4; i++) {\n midpoint[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\n midpoint[i + 4] = midpoint[i];\n }\n\n centroid.scaleInPlace(0.25);\n if (numBoundary === 0 || numBoundary === 1) {\n for (let i: number = 0; i < numInterior; i++)\n if (bIncludeInterior)\n this.addEdge(xyzOut, midpoint[iInterior[i]], centroid);\n } else if (numBoundary === 4) {\n for (let i: number = 0; i < numBoundary; i++)\n if (bIncludeFinal)\n this.addEdge(xyzOut, midpoint[i], centroid);\n } else if (numBoundary === 2) {\n if (iInterior[1] === iInterior[0] + 2) {\n // Spine enters one end, exits the other ..\n if (bIncludeInterior)\n this.addEdge(xyzOut, midpoint[iInterior[0]], midpoint[iInterior[1]]);\n } else {\n // Block sits as exterior corner. Let the two spines continue to their opposite faces ..\n for (let i: number = 0; i < 4; i++)\n if ((bIsBoundary[i] && bIncludeCornerSpokes)\n || (!bIsBoundary[i] && bIncludeInterior))\n this.addEdge(xyzOut, midpoint[i], centroid);\n }\n } else if (numBoundary === 3) {\n if (bIncludeInterior)\n this.addEdge(xyzOut, midpoint[iInterior[0]], centroid);\n if (bIncludeFinal)\n this.addEdge(xyzOut, centroid, midpoint[iInterior[0] + 2]);\n }\n return true;\n }\n\n private getSpineEdgesInTriangle(\n pFace: HalfEdge, xyzOut: Point3d[][],\n bIncludeInterior: boolean,\n bIncludeFinal: boolean): boolean {\n\n if (pFace.countEdgesAroundFace() !== 3)\n return false;\n let n = 0;\n const xyzMidpoint = createNPoints(6);\n const xyz = createNPoints(6);\n const xyzCentroid = Point3d.createZero();\n const isBoundary: boolean[] = [];\n let numBoundary = 0;\n let lastBoundary = -1;\n let lastInterior = -1;\n let currentEdge = pFace;\n do {\n xyz[n] = currentEdge.getPoint3d();\n xyzCentroid.addInPlace(xyz[n]);\n isBoundary[n] = false;\n if (currentEdge.getMask(HalfEdgeMask.BOUNDARY_EDGE)) {\n isBoundary[n] = true;\n numBoundary++;\n lastBoundary = n;\n } else {\n lastInterior = n;\n }\n xyz[n + 3] = xyz[n];\n isBoundary[n + 3] = isBoundary[n];\n n++;\n } while ((currentEdge = currentEdge.faceSuccessor) !== pFace);\n\n for (let i: number = 0; i < 3; i++) {\n xyzMidpoint[i] = xyz[i].interpolate(0.5, xyz[i + 1]);\n xyzMidpoint[i + 3] = xyzMidpoint[i];\n }\n\n xyzCentroid.scaleInPlace(1.0 / 3.0);\n\n if (numBoundary === 0) {\n // Interior branch\n const xyzInterior = this.selectTriangleInteriorPoint(xyz);\n if (bIncludeInterior) {\n this.addEdge(xyzOut, xyzMidpoint[0], xyzInterior);\n this.addEdge(xyzOut, xyzMidpoint[1], xyzInterior);\n this.addEdge(xyzOut, xyzMidpoint[2], xyzInterior);\n }\n } else if (numBoundary === 1) {\n if (bIncludeInterior)\n this.addEdge(xyzOut, xyzMidpoint[lastBoundary + 1], xyzMidpoint[lastBoundary + 2]);\n } else if (numBoundary === 2) {\n if (bIncludeFinal && lastInterior >= 0)\n this.addEdge(xyzOut, xyzMidpoint[lastInterior], xyz[lastInterior + 2]);\n } else if (numBoundary === 3) {\n const xyzInterior = this.selectTriangleInteriorPoint(xyz);\n if (bIncludeFinal) {\n this.addEdge(xyzOut, xyzMidpoint[0], xyzInterior);\n this.addEdge(xyzOut, xyzMidpoint[1], xyzInterior);\n this.addEdge(xyzOut, xyzMidpoint[2], xyzInterior);\n }\n }\n return true;\n }\n\n /** Add a polyline to the graph.\n * * This may be called multiple times\n */\n public insertEdges(xyzIn: Point3d[], bClosed: boolean): void {\n let pPreviousB, pFirstA;\n for (let i: number = 1; i < xyzIn.length; i++) {\n const nodeA = this._spineGraph.createEdgeXYZXYZ(\n xyzIn[i - 1].x, xyzIn[i - 1].y, 0, 0,\n xyzIn[i].x, xyzIn[i].y, 0, 0);\n const nodeB = nodeA.faceSuccessor;\n nodeA.setMask(HalfEdgeMask.BOUNDARY_EDGE);\n nodeB.setMask(HalfEdgeMask.BOUNDARY_EDGE);\n if (pPreviousB === undefined) {\n pFirstA = nodeA;\n } else {\n HalfEdge.pinch(pPreviousB, nodeA);\n }\n pPreviousB = nodeB;\n }\n if (bClosed && pFirstA !== undefined && pPreviousB !== undefined)\n HalfEdge.pinch(pPreviousB, pFirstA);\n }\n /**\n * Look for trivial (2 edge) faces that have exteriorMask and non-masked on both sides.\n * * clear the mask\n * @param exteriorMask\n */\n private purgeNullFaces(exteriorMask: HalfEdgeMask) {\n for (const nodeA of this._spineGraph.allHalfEdges) {\n const nodeB = nodeA.faceSuccessor;\n const nodeC = nodeB.faceSuccessor;\n if (nodeB !== nodeA && nodeC === nodeA) {\n if (nodeA.getMask(exteriorMask) && nodeB.getMask(exteriorMask)) {\n const mateA = nodeA.edgeMate;\n const mateB = nodeB.edgeMate;\n if (!mateA.getMask(exteriorMask) && !mateB.getMask(exteriorMask)) {\n nodeA.clearMask(exteriorMask);\n nodeB.clearMask(exteriorMask);\n }\n }\n }\n }\n }\n private static _regularize1 = true;\n private static _regularize2 = false;\n /**\n * Triangulate the graph for the edges that have been inserted.\n * @param applyParity if true ()\n * @param minSplitRadians smallest allowed angle in the split sector that is split.\n */\n public triangulateForSpine(applyParity: boolean = true, minSplitRadians: number = 0.3): void {\n\n const sMaxSplit = 20;\n const sMinCandidateRadians = 1.0;\n let numSplit = 0;\n HalfEdgeGraphMerge.splitIntersectingEdges(this.graph);\n HalfEdgeGraphMerge.clusterAndMergeXYTheta(this.graph);\n\n const context1 = new RegularizationContext(this.graph);\n context1.regularizeGraph(HalfEdgeGraphSpineContext._regularize1, false);\n const context2 = new RegularizationContext(this.graph);\n context2.regularizeGraph(false, HalfEdgeGraphSpineContext._regularize2);\n if (applyParity) {\n HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(this.graph,\n new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR);\n this.purgeNullFaces(HalfEdgeMask.EXTERIOR);\n }\n\n Triangulator.triangulateAllPositiveAreaFaces(this.graph);\n Triangulator.flipTriangles(this.graph);\n\n while (numSplit++ < sMaxSplit) {\n const numPerp = this.addPerpendicularsToBoundaries(minSplitRadians, sMinCandidateRadians);\n if (numPerp <= 0)\n break;\n Triangulator.flipTriangles(this.graph);\n }\n }\n\n // Find pseudo spine edges\n // Optionally include pure internal midline segments.\n // Optionally include midline segments into \"dead end\"\n // Optionally include adjacent spokes to corner.\n /**\n * Retrieve edges of the spine as arrays of points.\n * @param bIncludeInterior true to include fully internal segments\n * @param bIncludeFinal true to include segments that terminate at a boundary\n * @param bIncludeCornerSpokes\n * @return array of line data.\n */\n public getSpineEdges(bIncludeInterior: boolean = true, bIncludeFinal: boolean = true, bIncludeCornerSpokes: boolean = true): Point3d[][] {\n const xyzOut: Point3d[][] = [];\n this._spineGraph.announceFaceLoops(\n (_graph: HalfEdgeGraph, faceSeed: HalfEdge) => {\n if (!faceSeed.getMask(HalfEdgeMask.EXTERIOR)) {\n if (this.getSpineEdgesInTriangle(faceSeed, xyzOut, bIncludeInterior, bIncludeFinal)) {\n } else if (this.getSpineEdgesInQuad(faceSeed, xyzOut, bIncludeInterior, bIncludeFinal, bIncludeCornerSpokes)) {\n }\n }\n return true;\n });\n return xyzOut;\n }\n\n /**\n * Intermediate markup step to identify quads between corresponding boundary edges.\n * * search for and mark triangle edges that should be treated as diagonal of a quad\n * * Angle logic is:\n * * In a candidate quad (formed by joining triangles that share an edge)\n * * form segments between opposite edges of the quad.\n * * compute angles between these segments and the edges of their quads.\n * * if this angle is larger than minAngleRadians, accept this as a quad.\n * * recommended angle is between 15 and 5 degrees; 50 degrees is typical\n * @param bDeleteDiagonals if true, eliminate the diagonals.\n * @param minAngleRadians angle tolerance, as described above.\n */\n public consolidateTrianglesToQuads(bDeleteDiagonals: boolean, minAngle: Angle = Angle.createDegrees(50)): number {\n\n const numDiagonal = this.setSortedDiagonalMasks(minAngle.radians);\n if (bDeleteDiagonals && numDiagonal > 0) {\n this.graph.yankAndDeleteEdges(\n (node: HalfEdge) => node.getMask(this._diagonalMask));\n }\n return numDiagonal;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgeGraphValidation.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphValidation.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// cspell:word FSFP\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\n\r\n// Search services for HalfEdgeGraph\r\n/**\r\n * HalfEdgePointerInspector has methods to check HalfEdge objects for pointer errors.\r\n * * For a one-step test of the whole graph.\r\n */\r\nexport class HalfEdgePointerInspector {\r\n public numUndefinedEdgeMate: number = 0;\r\n public numUndefinedFS: number = 0;\r\n public numUndefinedFP: number = 0;\r\n public numFSFPError: number = 0;\r\n public numMatePairError: number = 0;\r\n public numTested: number = 0;\r\n public numWithMatchedEdgeMate: number = 0;\r\n /** Clear all counts. */\r\n public clearCounts() {\r\n this.numUndefinedEdgeMate = 0;\r\n this.numUndefinedFP = 0;\r\n this.numUndefinedFS = 0;\r\n this.numFSFPError = 0;\r\n this.numMatePairError = 0;\r\n this.numWithMatchedEdgeMate = 0;\r\n this.numTested = 0;\r\n }\r\n /** Inspect a single half edge. Increment counters according to the half edge's pointers. */\r\n public inspectHalfEdge(he: HalfEdge) {\r\n this.numTested++;\r\n if (he.facePredecessor === undefined)\r\n this.numUndefinedFP++;\r\n else if (he.facePredecessor.faceSuccessor !== he)\r\n this.numFSFPError++;\r\n\r\n if (he.faceSuccessor === undefined)\r\n this.numUndefinedFS++;\r\n else if (he.faceSuccessor.facePredecessor !== he)\r\n this.numFSFPError++;\r\n\r\n if (he.edgeMate === undefined)\r\n this.numUndefinedEdgeMate++;\r\n else if (he.edgeMate.edgeMate === he)\r\n this.numWithMatchedEdgeMate++;\r\n else\r\n this.numMatePairError++;\r\n }\r\n /**\r\n * Return true if all pointer pairings are correct for a closed half edge graph (with no boundary):\r\n * * For each he: `he.edgeMate.edgeMate === he`\r\n * * For each he: `he.faceSuccessor.facePredecessor === he`\r\n * * For each he: `he.facePredecessor.faceSuccessor === he`\r\n */\r\n public get isValidClosedHalfEdgeGraph(): boolean {\r\n return this.numWithMatchedEdgeMate === this.numTested\r\n && this.numUndefinedFS === 0\r\n && this.numUndefinedFP === 0\r\n && this.numFSFPError === 0\r\n && this.numMatePairError === 0;\r\n }\r\n /**\r\n * Return true if all pointer pairings are correct for a half edge graph with possible boundary:\r\n * * For each he: `he.edgeMate.edgeMate === he`\r\n * * For each he: `he.faceSuccessor.facePredecessor === he`\r\n * * For each he: `he.facePredecessor.faceSuccessor === he`\r\n */\r\n public get isValidHalfEdgeGraphAllowRaggedBoundary(): boolean {\r\n return this.numWithMatchedEdgeMate + this.numUndefinedEdgeMate === this.numTested\r\n && this.numUndefinedFS === 0\r\n && this.numUndefinedFP === 0\r\n && this.numFSFPError === 0\r\n && this.numMatePairError === 0;\r\n }\r\n /**\r\n * Inspect all half edges of graph.\r\n * * All pointer counts are left in member vars for later inspection.\r\n */\r\n public inspectHalfEdges(graph: HalfEdgeGraph) {\r\n this.clearCounts();\r\n for (const he of graph.allHalfEdges)\r\n this.inspectHalfEdge(he);\r\n }\r\n /**\r\n * Inspect a graph's pointer properties.\r\n * @param expectAllMates true for \"complete\" graph.\r\n * @returns true if all pointers are valid.\r\n */\r\n public static inspectGraph(graph: HalfEdgeGraph, expectAllMates: boolean): boolean {\r\n const inspector = new HalfEdgePointerInspector();\r\n inspector.inspectHalfEdges(graph);\r\n if (expectAllMates)\r\n return inspector.isValidClosedHalfEdgeGraph;\r\n return inspector.isValidHalfEdgeGraphAllowRaggedBoundary;\r\n }\r\n}\r\n/** Static methods to inspect mask consistency properties in HalfEdgeGraph. */\r\nexport class HalfEdgeMaskValidation {\r\n /**\r\n * Test if a mask is used consistently around faces.\r\n * * At the low level, there is no actual traversal around faces. It is only necessary to verify that the mask\r\n * matches for each HalfEdge and its faceSuccessor.\r\n * @returns Return true if mask is \"all or nothing around all faces\"\r\n */\r\n public static isMaskConsistentAroundAllFaces(graph: HalfEdgeGraph, mask: HalfEdgeMask): boolean {\r\n for (const he of graph.allHalfEdges) {\r\n if (he.faceSuccessor.getMask(mask) !== he.getMask(mask))\r\n return false;\r\n }\r\n return true;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"HalfEdgeGraphValidation.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeGraphValidation.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 */\n// cspell:word FSFP\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\n\n// Search services for HalfEdgeGraph\n/**\n * HalfEdgePointerInspector has methods to check HalfEdge objects for pointer errors.\n * * For a one-step test of the whole graph.\n */\nexport class HalfEdgePointerInspector {\n public numUndefinedEdgeMate: number = 0;\n public numUndefinedFS: number = 0;\n public numUndefinedFP: number = 0;\n public numFSFPError: number = 0;\n public numMatePairError: number = 0;\n public numTested: number = 0;\n public numWithMatchedEdgeMate: number = 0;\n /** Clear all counts. */\n public clearCounts() {\n this.numUndefinedEdgeMate = 0;\n this.numUndefinedFP = 0;\n this.numUndefinedFS = 0;\n this.numFSFPError = 0;\n this.numMatePairError = 0;\n this.numWithMatchedEdgeMate = 0;\n this.numTested = 0;\n }\n /** Inspect a single half edge. Increment counters according to the half edge's pointers. */\n public inspectHalfEdge(he: HalfEdge) {\n this.numTested++;\n if (he.facePredecessor === undefined)\n this.numUndefinedFP++;\n else if (he.facePredecessor.faceSuccessor !== he)\n this.numFSFPError++;\n\n if (he.faceSuccessor === undefined)\n this.numUndefinedFS++;\n else if (he.faceSuccessor.facePredecessor !== he)\n this.numFSFPError++;\n\n if (he.edgeMate === undefined)\n this.numUndefinedEdgeMate++;\n else if (he.edgeMate.edgeMate === he)\n this.numWithMatchedEdgeMate++;\n else\n this.numMatePairError++;\n }\n /**\n * Return true if all pointer pairings are correct for a closed half edge graph (with no boundary):\n * * For each he: `he.edgeMate.edgeMate === he`\n * * For each he: `he.faceSuccessor.facePredecessor === he`\n * * For each he: `he.facePredecessor.faceSuccessor === he`\n */\n public get isValidClosedHalfEdgeGraph(): boolean {\n return this.numWithMatchedEdgeMate === this.numTested\n && this.numUndefinedFS === 0\n && this.numUndefinedFP === 0\n && this.numFSFPError === 0\n && this.numMatePairError === 0;\n }\n /**\n * Return true if all pointer pairings are correct for a half edge graph with possible boundary:\n * * For each he: `he.edgeMate.edgeMate === he`\n * * For each he: `he.faceSuccessor.facePredecessor === he`\n * * For each he: `he.facePredecessor.faceSuccessor === he`\n */\n public get isValidHalfEdgeGraphAllowRaggedBoundary(): boolean {\n return this.numWithMatchedEdgeMate + this.numUndefinedEdgeMate === this.numTested\n && this.numUndefinedFS === 0\n && this.numUndefinedFP === 0\n && this.numFSFPError === 0\n && this.numMatePairError === 0;\n }\n /**\n * Inspect all half edges of graph.\n * * All pointer counts are left in member vars for later inspection.\n */\n public inspectHalfEdges(graph: HalfEdgeGraph) {\n this.clearCounts();\n for (const he of graph.allHalfEdges)\n this.inspectHalfEdge(he);\n }\n /**\n * Inspect a graph's pointer properties.\n * @param expectAllMates true for \"complete\" graph.\n * @returns true if all pointers are valid.\n */\n public static inspectGraph(graph: HalfEdgeGraph, expectAllMates: boolean): boolean {\n const inspector = new HalfEdgePointerInspector();\n inspector.inspectHalfEdges(graph);\n if (expectAllMates)\n return inspector.isValidClosedHalfEdgeGraph;\n return inspector.isValidHalfEdgeGraphAllowRaggedBoundary;\n }\n}\n/** Static methods to inspect mask consistency properties in HalfEdgeGraph. */\nexport class HalfEdgeMaskValidation {\n /**\n * Test if a mask is used consistently around faces.\n * * At the low level, there is no actual traversal around faces. It is only necessary to verify that the mask\n * matches for each HalfEdge and its faceSuccessor.\n * @returns Return true if mask is \"all or nothing around all faces\"\n */\n public static isMaskConsistentAroundAllFaces(graph: HalfEdgeGraph, mask: HalfEdgeMask): boolean {\n for (const he of graph.allHalfEdges) {\n if (he.faceSuccessor.getMask(mask) !== he.getMask(mask))\n return false;\n }\n return true;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgeMarkSet.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeMarkSet.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\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n/**\r\n * A class to manage a set of edges as both (a) an array of possible members and (b) mask bits.\r\n * * A half edge is \"in the MarkSet\" if its mask is set.\r\n * * The MarkSet array is a superset of the half edges in the set.\r\n * * Entry of a HalfEdge into the set is indicated by both\r\n * * adding the HalfEdge to the array\r\n * * setting the mask on the half edge, edge, face, or vertex\r\n * * Half edges can \"go out of the MarkSet\" if the mask is cleared.\r\n * * This clearing can happen independently of the array management.\r\n * * Hence the array can contain half edges that are no longer in the MarkSet\r\n * * the \"remove\" methods monitor this.\r\n * * Derived classes expand this concept for edge, vertex, or face MarkSets.\r\n * * a single representative of an edge, vertex, or face is entered to the array\r\n * * all edges around the edge, vertex, or face are marked with the mask\r\n * * Hence the array contains one or more representatives of the edge, face, or vertex\r\n * * This allows quick query for both:\r\n * * Testing the mask gives constant time test of whether a HalfEdge is in the set\r\n * * access through the array gives direct access to the HalfEdge pointers\r\n * @internal\r\n */\r\nexport abstract class AbstractHalfEdgeGraphMarkSet {\r\n private _graph: HalfEdgeGraph;\r\n private _candidates: HalfEdge[];\r\n protected _mask: HalfEdgeMask;\r\n\r\n protected constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\r\n this._graph = graph;\r\n this._candidates = [];\r\n this._mask = mask;\r\n this._graph.clearMask(mask);\r\n }\r\n /** remove all nodes from the set.\r\n * * This pops from the array, clearing masks as the pop.\r\n * * Note that it does NOT walk the entire graph to clear masks.\r\n */\r\n public clear() {\r\n for (; undefined !== this.chooseAndRemoveAny();) {\r\n }\r\n }\r\n\r\n /**\r\n * count the number of active members.\r\n * * This is the number of HalfEdges which are (a) in the array and (b) masked.\r\n */\r\n public getLength(): number {\r\n let n = 0;\r\n for (const candidate of this._candidates) {\r\n if (candidate.isMaskSet(this._mask)) n++;\r\n }\r\n return n;\r\n }\r\n /**\r\n * Return the number of candidates.\r\n * * This may be more than `getLength ()`\r\n * * This will typically only be called by the iterator.\r\n */\r\n public getNumCandidates(): number {\r\n return this._candidates.length;\r\n }\r\n /** Read property accessor: return the graph */\r\n public get graph(): HalfEdgeGraph { return this._graph; }\r\n\r\n /** return borrowed assets (the mask!) to the graph. */\r\n public teardown() {\r\n this._graph.dropMask(this._mask);\r\n this._candidates.length = 0;\r\n // this._graph = undefined;\r\n }\r\n /** (Read property) return the mask used to mark members of the set. */\r\n public get mask(): HalfEdgeMask { return this._mask; }\r\n\r\n /** pop and return the last node out of the array, without testing if it is still marked. */\r\n protected popAndReturn(): HalfEdge | undefined {\r\n const n = this._candidates.length;\r\n if (n === 0)\r\n return undefined;\r\n const node = this._candidates[n - 1];\r\n this._candidates.pop();\r\n return node;\r\n }\r\n\r\n /**\r\n * * read at an index in the candidates array.\r\n * * if that candidate has the mask, return it.\r\n * * otherwise return undefined.\r\n * * REMARK: This is only to be called by the iterator.\r\n */\r\n public getAtIndex(index: number): HalfEdge | undefined {\r\n if (index >= 0 && index < this._candidates.length) {\r\n const candidate = this._candidates[index];\r\n if (candidate.isMaskSet(this._mask))\r\n return candidate;\r\n }\r\n return undefined;\r\n }\r\n\r\n /** Add a node to the set. This means\r\n * * Set the mask\r\n * * push the node on the array\r\n * * (BUT!) If the node already has the mask, do nothing.\r\n * * This base class method affects only the single given HalfEdge.\r\n * * Derived classes for edge, face, and vertex will override this method and also set the mask around the larger structures.\r\n * @returns true if the HalfEdge is a new member of the set, false if it was already in the set.\r\n */\r\n public addToSet(candidate: HalfEdge) {\r\n if (candidate.isMaskSet(this._mask))\r\n return false;\r\n this._candidates.push(candidate);\r\n this.setMaskInScope(candidate);\r\n return true;\r\n }\r\n /** Test if `candidate` is already in the set.\r\n * * This examines only the mask.\r\n */\r\n public isCandidateInSet(candidate: HalfEdge): boolean {\r\n return candidate.isMaskSet(this._mask);\r\n }\r\n /**\r\n * * If the candidate is not marked as a member of the MarkSet, do nothing.\r\n * * If the candidate is marked:\r\n * * clear the mask\r\n * * but do NOT search the array.\r\n * * As the array is searched, the candidate will appear and be ignored because the mask is not set.\r\n * @param candidate\r\n * @return true if the candidate was a member (an hence removed), false if the candidate was not masked.\r\n */\r\n public removeFromSet(candidate: HalfEdge): boolean {\r\n if (!candidate.isMaskSet(this._mask))\r\n return false;\r\n this.clearMaskInScope(candidate);\r\n return true;\r\n }\r\n /**\r\n * * Search the array to find any current set member\r\n * * If found, clear its mask and return it.\r\n * * If unmasked HalfEdges are found in the array, they are removed from the array.\r\n */\r\n public chooseAndRemoveAny(): HalfEdge | undefined {\r\n for (; ;) {\r\n const candidate = this.popAndReturn();\r\n if (!candidate)\r\n return undefined;\r\n if (this.removeFromSet(candidate))\r\n return candidate;\r\n }\r\n }\r\n /** Set mask on candidate -- i.e. edge, face, vertex, or single half edge as required.\r\n * * Base class only changes the candidate mask.\r\n * * Derived classes change more masks around edge, face, or vertex.\r\n */\r\n protected abstract setMaskInScope(candidate: HalfEdge | undefined): void;\r\n\r\n /** Clear mask on candidate -- i.e. edge, face, vertex, or single half edge as required.\r\n * * Base class only changes the candidate mask.\r\n * * Derived classes change more masks around edge, face, or vertex.\r\n */\r\n protected abstract clearMaskInScope(candidate: HalfEdge | undefined): void;\r\n /**\r\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\r\n * * This is always 1 for HalfEdgeMarkSet\r\n * @param candidate\r\n */\r\n public abstract countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number;\r\n /** Create an iterator over member HalfEdges */\r\n public [Symbol.iterator](): IterableIterator<HalfEdge> { return new IterableHalfEdgeMarkSetIterator(this); }\r\n /**\r\n * * visit all half edges around face.\r\n * * Add each to mark set.\r\n */\r\n public addAroundFace(seed: HalfEdge): void {\r\n let p = seed;\r\n do {\r\n this.addToSet(p);\r\n p = p.faceSuccessor;\r\n } while (p !== seed);\r\n }\r\n\r\n /**\r\n * * visit all half edges around vertex.\r\n * * Add each to mark set.\r\n */\r\n public addAroundVertex(seed: HalfEdge): void {\r\n let p = seed;\r\n do {\r\n this.addToSet(p);\r\n p = p.vertexSuccessor;\r\n } while (p !== seed);\r\n }\r\n}\r\n\r\n/**\r\n * AbstractHalfEdgeGraphMarkSet specialized to manage the masks on individual half edges\r\n * @internal\r\n */\r\nexport class MarkedHalfEdgeSet extends AbstractHalfEdgeGraphMarkSet {\r\n constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\r\n super(graph, mask);\r\n }\r\n /** Create a new 'HalfEdgeMarkSet', operating on half edges with only themselves as scope.\r\n * * Returns undefined if unable to get a mask for the graph.\r\n * * Undefined return can only happen if the caller is failing to return grabbed masks.\r\n */\r\n public static create(graph: HalfEdgeGraph): MarkedHalfEdgeSet | undefined {\r\n const mask = graph.grabMask();\r\n if (mask === HalfEdgeMask.NULL_MASK)\r\n return undefined;\r\n return new MarkedHalfEdgeSet(graph, mask);\r\n }\r\n\r\n /**\r\n * * Set mask on candidate's edge.\r\n * * This overrides the base class implementation.\r\n */\r\n protected setMaskInScope(candidate: HalfEdge) {\r\n candidate.setMask(this._mask);\r\n }\r\n\r\n /**\r\n * * Clear mask on candidate's edge.\r\n * * This overrides the base class implementation.\r\n */\r\n protected clearMaskInScope(candidate: HalfEdge) {\r\n candidate.clearMask(this._mask);\r\n }\r\n /**\r\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\r\n * * This is always 1 for EdgeMarkSet\r\n * * return 0 for undefined candidate\r\n * @param candidate\r\n */\r\n public countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number {\r\n if (!candidate)\r\n return 0;\r\n return 1;\r\n }\r\n}\r\n\r\n/**\r\n * AbstractHalfEdgeGraphMarkSet specialized to manage the mask on both sides of edges.\r\n * @internal\r\n */\r\nexport class MarkedEdgeSet extends AbstractHalfEdgeGraphMarkSet {\r\n constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\r\n super(graph, mask);\r\n }\r\n /** Create a new 'HalfEdgeMarkSet', operating on half edges with only themselves as scope.\r\n * * Returns undefined if unable to get a mask for the graph.\r\n * * Undefined return can only happen if the caller is failing to return grabbed masks.\r\n */\r\n public static create(graph: HalfEdgeGraph): MarkedEdgeSet | undefined {\r\n const mask = graph.grabMask();\r\n if (mask === HalfEdgeMask.NULL_MASK)\r\n return undefined;\r\n return new MarkedEdgeSet(graph, mask);\r\n }\r\n\r\n /**\r\n * * Set mask on candidate's edge.\r\n * * This overrides the base class implementation.\r\n */\r\n protected setMaskInScope(candidate: HalfEdge) {\r\n candidate.setMaskAroundEdge(this._mask);\r\n }\r\n\r\n /**\r\n * * Clear mask on candidate's edge.\r\n * * This overrides the base class implementation.\r\n */\r\n protected clearMaskInScope(candidate: HalfEdge) {\r\n candidate.clearMaskAroundEdge(this._mask);\r\n }\r\n /**\r\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\r\n * * This is always 2 for EdgeMarkSet\r\n * @param candidate\r\n */\r\n public countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number {\r\n if (!candidate)\r\n return 0;\r\n return 2;\r\n }\r\n}\r\n\r\n/**\r\n * AbstractHalfEdgeGraphMarkSet specialized to manage the mask around faces\r\n * @internal\r\n */\r\nexport class MarkedFaceSet extends AbstractHalfEdgeGraphMarkSet {\r\n constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\r\n super(graph, mask);\r\n }\r\n /** Create a new 'HalfEdgeMarkSet', operating on half edges with only themselves as scope.\r\n * * Returns undefined if unable to get a mask for the graph.\r\n * * Undefined return can only happen if the caller is failing to return grabbed masks.\r\n */\r\n public static create(graph: HalfEdgeGraph): MarkedFaceSet | undefined {\r\n const mask = graph.grabMask();\r\n if (mask === HalfEdgeMask.NULL_MASK)\r\n return undefined;\r\n return new MarkedFaceSet(graph, mask);\r\n }\r\n\r\n /**\r\n * * Set mask on (all nodes around) candidate's face\r\n * * This overrides the base class implementation.\r\n */\r\n protected setMaskInScope(candidate: HalfEdge) {\r\n candidate.setMaskAroundFace(this._mask);\r\n }\r\n\r\n /**\r\n * * Clear mask on (all nodes around) candidate's face.\r\n * * This overrides the base class implementation.\r\n */\r\n protected clearMaskInScope(candidate: HalfEdge) {\r\n candidate.clearMaskAroundFace(this._mask);\r\n }\r\n /**\r\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\r\n * * This is the \"aroundFace\" count.\r\n * @param candidate\r\n */\r\n public countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number {\r\n if (!candidate)\r\n return 0;\r\n return candidate.countEdgesAroundFace();\r\n }\r\n}\r\n/**\r\n * AbstractHalfEdgeGraphMarkSet specialized to manage the mask around faces\r\n * @internal\r\n */\r\nexport class MarkedVertexSet extends AbstractHalfEdgeGraphMarkSet {\r\n constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\r\n super(graph, mask);\r\n }\r\n /** Create a new 'HalfEdgeMarkSet', operating on half edges with only themselves as scope.\r\n * * Returns undefined if unable to get a mask for the graph.\r\n * * Undefined return can only happen if the caller is failing to return grabbed masks.\r\n */\r\n public static create(graph: HalfEdgeGraph): MarkedVertexSet | undefined {\r\n const mask = graph.grabMask();\r\n if (mask === HalfEdgeMask.NULL_MASK)\r\n return undefined;\r\n return new MarkedVertexSet(graph, mask);\r\n }\r\n\r\n /**\r\n * * Set mask on (all nodes around) candidate's face\r\n * * This overrides the base class implementation.\r\n */\r\n protected setMaskInScope(candidate: HalfEdge) {\r\n candidate.setMaskAroundVertex(this._mask);\r\n }\r\n\r\n /**\r\n * * Clear mask on (all nodes around) candidate's face.\r\n * * This overrides the base class implementation.\r\n */\r\n protected clearMaskInScope(candidate: HalfEdge) {\r\n candidate.clearMaskAroundVertex(this._mask);\r\n }\r\n /**\r\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\r\n * * This is the \"aroundVertex\" count.\r\n * @param candidate\r\n */\r\n public countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number {\r\n if (!candidate)\r\n return 0;\r\n return candidate.countEdgesAroundVertex();\r\n }\r\n}\r\n\r\n/**\r\n * Class to act as an iterator over points in a markSet.\r\n * * Internal data is:\r\n * * pointer to the parent markSet\r\n * * index of index of the next point to read.\r\n * * the parent markSet class\r\n */\r\nclass IterableHalfEdgeMarkSetIterator implements Iterator<HalfEdge> {\r\n private _markSet: AbstractHalfEdgeGraphMarkSet;\r\n private _nextReadIndex: number;\r\n public constructor(markSet: AbstractHalfEdgeGraphMarkSet) {\r\n this._markSet = markSet;\r\n this._nextReadIndex = 0;\r\n }\r\n public next(): IteratorResult<HalfEdge> {\r\n const n = this._markSet.getNumCandidates();\r\n // Walk over candidates that have been quietly de-masked\r\n while (this._nextReadIndex < n) {\r\n const p = this._markSet.getAtIndex(this._nextReadIndex++);\r\n if (p !== undefined)\r\n return { done: false, value: p };\r\n }\r\n return { done: true, value: undefined } as any as IteratorResult<HalfEdge>;\r\n }\r\n\r\n public [Symbol.iterator](): IterableIterator<HalfEdge> { return this; }\r\n}\r\n"]}
1
+ {"version":3,"file":"HalfEdgeMarkSet.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeMarkSet.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*--------------------------------------------------------------------------------------------*/\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\n\n/** @packageDocumentation\n * @module Topology\n */\n/**\n * A class to manage a set of edges as both (a) an array of possible members and (b) mask bits.\n * * A half edge is \"in the MarkSet\" if its mask is set.\n * * The MarkSet array is a superset of the half edges in the set.\n * * Entry of a HalfEdge into the set is indicated by both\n * * adding the HalfEdge to the array\n * * setting the mask on the half edge, edge, face, or vertex\n * * Half edges can \"go out of the MarkSet\" if the mask is cleared.\n * * This clearing can happen independently of the array management.\n * * Hence the array can contain half edges that are no longer in the MarkSet\n * * the \"remove\" methods monitor this.\n * * Derived classes expand this concept for edge, vertex, or face MarkSets.\n * * a single representative of an edge, vertex, or face is entered to the array\n * * all edges around the edge, vertex, or face are marked with the mask\n * * Hence the array contains one or more representatives of the edge, face, or vertex\n * * This allows quick query for both:\n * * Testing the mask gives constant time test of whether a HalfEdge is in the set\n * * access through the array gives direct access to the HalfEdge pointers\n * @internal\n */\nexport abstract class AbstractHalfEdgeGraphMarkSet {\n private _graph: HalfEdgeGraph;\n private _candidates: HalfEdge[];\n protected _mask: HalfEdgeMask;\n\n protected constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\n this._graph = graph;\n this._candidates = [];\n this._mask = mask;\n this._graph.clearMask(mask);\n }\n /** remove all nodes from the set.\n * * This pops from the array, clearing masks as the pop.\n * * Note that it does NOT walk the entire graph to clear masks.\n */\n public clear() {\n for (; undefined !== this.chooseAndRemoveAny();) {\n }\n }\n\n /**\n * count the number of active members.\n * * This is the number of HalfEdges which are (a) in the array and (b) masked.\n */\n public getLength(): number {\n let n = 0;\n for (const candidate of this._candidates) {\n if (candidate.isMaskSet(this._mask)) n++;\n }\n return n;\n }\n /**\n * Return the number of candidates.\n * * This may be more than `getLength ()`\n * * This will typically only be called by the iterator.\n */\n public getNumCandidates(): number {\n return this._candidates.length;\n }\n /** Read property accessor: return the graph */\n public get graph(): HalfEdgeGraph { return this._graph; }\n\n /** return borrowed assets (the mask!) to the graph. */\n public teardown() {\n this._graph.dropMask(this._mask);\n this._candidates.length = 0;\n // this._graph = undefined;\n }\n /** (Read property) return the mask used to mark members of the set. */\n public get mask(): HalfEdgeMask { return this._mask; }\n\n /** pop and return the last node out of the array, without testing if it is still marked. */\n protected popAndReturn(): HalfEdge | undefined {\n const n = this._candidates.length;\n if (n === 0)\n return undefined;\n const node = this._candidates[n - 1];\n this._candidates.pop();\n return node;\n }\n\n /**\n * * read at an index in the candidates array.\n * * if that candidate has the mask, return it.\n * * otherwise return undefined.\n * * REMARK: This is only to be called by the iterator.\n */\n public getAtIndex(index: number): HalfEdge | undefined {\n if (index >= 0 && index < this._candidates.length) {\n const candidate = this._candidates[index];\n if (candidate.isMaskSet(this._mask))\n return candidate;\n }\n return undefined;\n }\n\n /** Add a node to the set. This means\n * * Set the mask\n * * push the node on the array\n * * (BUT!) If the node already has the mask, do nothing.\n * * This base class method affects only the single given HalfEdge.\n * * Derived classes for edge, face, and vertex will override this method and also set the mask around the larger structures.\n * @returns true if the HalfEdge is a new member of the set, false if it was already in the set.\n */\n public addToSet(candidate: HalfEdge) {\n if (candidate.isMaskSet(this._mask))\n return false;\n this._candidates.push(candidate);\n this.setMaskInScope(candidate);\n return true;\n }\n /** Test if `candidate` is already in the set.\n * * This examines only the mask.\n */\n public isCandidateInSet(candidate: HalfEdge): boolean {\n return candidate.isMaskSet(this._mask);\n }\n /**\n * * If the candidate is not marked as a member of the MarkSet, do nothing.\n * * If the candidate is marked:\n * * clear the mask\n * * but do NOT search the array.\n * * As the array is searched, the candidate will appear and be ignored because the mask is not set.\n * @param candidate\n * @return true if the candidate was a member (an hence removed), false if the candidate was not masked.\n */\n public removeFromSet(candidate: HalfEdge): boolean {\n if (!candidate.isMaskSet(this._mask))\n return false;\n this.clearMaskInScope(candidate);\n return true;\n }\n /**\n * * Search the array to find any current set member\n * * If found, clear its mask and return it.\n * * If unmasked HalfEdges are found in the array, they are removed from the array.\n */\n public chooseAndRemoveAny(): HalfEdge | undefined {\n for (; ;) {\n const candidate = this.popAndReturn();\n if (!candidate)\n return undefined;\n if (this.removeFromSet(candidate))\n return candidate;\n }\n }\n /** Set mask on candidate -- i.e. edge, face, vertex, or single half edge as required.\n * * Base class only changes the candidate mask.\n * * Derived classes change more masks around edge, face, or vertex.\n */\n protected abstract setMaskInScope(candidate: HalfEdge | undefined): void;\n\n /** Clear mask on candidate -- i.e. edge, face, vertex, or single half edge as required.\n * * Base class only changes the candidate mask.\n * * Derived classes change more masks around edge, face, or vertex.\n */\n protected abstract clearMaskInScope(candidate: HalfEdge | undefined): void;\n /**\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\n * * This is always 1 for HalfEdgeMarkSet\n * @param candidate\n */\n public abstract countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number;\n /** Create an iterator over member HalfEdges */\n public [Symbol.iterator](): IterableIterator<HalfEdge> { return new IterableHalfEdgeMarkSetIterator(this); }\n /**\n * * visit all half edges around face.\n * * Add each to mark set.\n */\n public addAroundFace(seed: HalfEdge): void {\n let p = seed;\n do {\n this.addToSet(p);\n p = p.faceSuccessor;\n } while (p !== seed);\n }\n\n /**\n * * visit all half edges around vertex.\n * * Add each to mark set.\n */\n public addAroundVertex(seed: HalfEdge): void {\n let p = seed;\n do {\n this.addToSet(p);\n p = p.vertexSuccessor;\n } while (p !== seed);\n }\n}\n\n/**\n * AbstractHalfEdgeGraphMarkSet specialized to manage the masks on individual half edges\n * @internal\n */\nexport class MarkedHalfEdgeSet extends AbstractHalfEdgeGraphMarkSet {\n constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\n super(graph, mask);\n }\n /** Create a new 'HalfEdgeMarkSet', operating on half edges with only themselves as scope.\n * * Returns undefined if unable to get a mask for the graph.\n * * Undefined return can only happen if the caller is failing to return grabbed masks.\n */\n public static create(graph: HalfEdgeGraph): MarkedHalfEdgeSet | undefined {\n const mask = graph.grabMask();\n if (mask === HalfEdgeMask.NULL_MASK)\n return undefined;\n return new MarkedHalfEdgeSet(graph, mask);\n }\n\n /**\n * * Set mask on candidate's edge.\n * * This overrides the base class implementation.\n */\n protected setMaskInScope(candidate: HalfEdge) {\n candidate.setMask(this._mask);\n }\n\n /**\n * * Clear mask on candidate's edge.\n * * This overrides the base class implementation.\n */\n protected clearMaskInScope(candidate: HalfEdge) {\n candidate.clearMask(this._mask);\n }\n /**\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\n * * This is always 1 for EdgeMarkSet\n * * return 0 for undefined candidate\n * @param candidate\n */\n public countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number {\n if (!candidate)\n return 0;\n return 1;\n }\n}\n\n/**\n * AbstractHalfEdgeGraphMarkSet specialized to manage the mask on both sides of edges.\n * @internal\n */\nexport class MarkedEdgeSet extends AbstractHalfEdgeGraphMarkSet {\n constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\n super(graph, mask);\n }\n /** Create a new 'HalfEdgeMarkSet', operating on half edges with only themselves as scope.\n * * Returns undefined if unable to get a mask for the graph.\n * * Undefined return can only happen if the caller is failing to return grabbed masks.\n */\n public static create(graph: HalfEdgeGraph): MarkedEdgeSet | undefined {\n const mask = graph.grabMask();\n if (mask === HalfEdgeMask.NULL_MASK)\n return undefined;\n return new MarkedEdgeSet(graph, mask);\n }\n\n /**\n * * Set mask on candidate's edge.\n * * This overrides the base class implementation.\n */\n protected setMaskInScope(candidate: HalfEdge) {\n candidate.setMaskAroundEdge(this._mask);\n }\n\n /**\n * * Clear mask on candidate's edge.\n * * This overrides the base class implementation.\n */\n protected clearMaskInScope(candidate: HalfEdge) {\n candidate.clearMaskAroundEdge(this._mask);\n }\n /**\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\n * * This is always 2 for EdgeMarkSet\n * @param candidate\n */\n public countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number {\n if (!candidate)\n return 0;\n return 2;\n }\n}\n\n/**\n * AbstractHalfEdgeGraphMarkSet specialized to manage the mask around faces\n * @internal\n */\nexport class MarkedFaceSet extends AbstractHalfEdgeGraphMarkSet {\n constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\n super(graph, mask);\n }\n /** Create a new 'HalfEdgeMarkSet', operating on half edges with only themselves as scope.\n * * Returns undefined if unable to get a mask for the graph.\n * * Undefined return can only happen if the caller is failing to return grabbed masks.\n */\n public static create(graph: HalfEdgeGraph): MarkedFaceSet | undefined {\n const mask = graph.grabMask();\n if (mask === HalfEdgeMask.NULL_MASK)\n return undefined;\n return new MarkedFaceSet(graph, mask);\n }\n\n /**\n * * Set mask on (all nodes around) candidate's face\n * * This overrides the base class implementation.\n */\n protected setMaskInScope(candidate: HalfEdge) {\n candidate.setMaskAroundFace(this._mask);\n }\n\n /**\n * * Clear mask on (all nodes around) candidate's face.\n * * This overrides the base class implementation.\n */\n protected clearMaskInScope(candidate: HalfEdge) {\n candidate.clearMaskAroundFace(this._mask);\n }\n /**\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\n * * This is the \"aroundFace\" count.\n * @param candidate\n */\n public countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number {\n if (!candidate)\n return 0;\n return candidate.countEdgesAroundFace();\n }\n}\n/**\n * AbstractHalfEdgeGraphMarkSet specialized to manage the mask around faces\n * @internal\n */\nexport class MarkedVertexSet extends AbstractHalfEdgeGraphMarkSet {\n constructor(graph: HalfEdgeGraph, mask: HalfEdgeMask) {\n super(graph, mask);\n }\n /** Create a new 'HalfEdgeMarkSet', operating on half edges with only themselves as scope.\n * * Returns undefined if unable to get a mask for the graph.\n * * Undefined return can only happen if the caller is failing to return grabbed masks.\n */\n public static create(graph: HalfEdgeGraph): MarkedVertexSet | undefined {\n const mask = graph.grabMask();\n if (mask === HalfEdgeMask.NULL_MASK)\n return undefined;\n return new MarkedVertexSet(graph, mask);\n }\n\n /**\n * * Set mask on (all nodes around) candidate's face\n * * This overrides the base class implementation.\n */\n protected setMaskInScope(candidate: HalfEdge) {\n candidate.setMaskAroundVertex(this._mask);\n }\n\n /**\n * * Clear mask on (all nodes around) candidate's face.\n * * This overrides the base class implementation.\n */\n protected clearMaskInScope(candidate: HalfEdge) {\n candidate.clearMaskAroundVertex(this._mask);\n }\n /**\n * Return the number of half edges that would be set/cleared when dealing with this candidate.\n * * This is the \"aroundVertex\" count.\n * @param candidate\n */\n public countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number {\n if (!candidate)\n return 0;\n return candidate.countEdgesAroundVertex();\n }\n}\n\n/**\n * Class to act as an iterator over points in a markSet.\n * * Internal data is:\n * * pointer to the parent markSet\n * * index of index of the next point to read.\n * * the parent markSet class\n */\nclass IterableHalfEdgeMarkSetIterator implements Iterator<HalfEdge> {\n private _markSet: AbstractHalfEdgeGraphMarkSet;\n private _nextReadIndex: number;\n public constructor(markSet: AbstractHalfEdgeGraphMarkSet) {\n this._markSet = markSet;\n this._nextReadIndex = 0;\n }\n public next(): IteratorResult<HalfEdge> {\n const n = this._markSet.getNumCandidates();\n // Walk over candidates that have been quietly de-masked\n while (this._nextReadIndex < n) {\n const p = this._markSet.getAtIndex(this._nextReadIndex++);\n if (p !== undefined)\n return { done: false, value: p };\n }\n return { done: true, value: undefined } as any as IteratorResult<HalfEdge>;\n }\n\n public [Symbol.iterator](): IterableIterator<HalfEdge> { return this; }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgeNodeXYZUV.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeNodeXYZUV.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\nimport { Geometry } from \"../Geometry\";\r\nimport { Point2d } from \"../geometry3d/Point2dVector2d\";\r\nimport { Point3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { Ray3d } from \"../geometry3d/Ray3d\";\r\nimport { HalfEdge } from \"./Graph\";\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n/**\r\n * Reference to a HalfEdge node with extra XYZ and UV data.\r\n * @internal\r\n */\r\nexport class NodeXYZUV {\r\n private _node: HalfEdge;\r\n private _x: number;\r\n private _y: number;\r\n private _z: number;\r\n private _u: number;\r\n private _v: number;\r\n /** Constructor */\r\n private constructor(node: HalfEdge, x: number, y: number, z: number, u: number, v: number) {\r\n this._x = x;\r\n this._y = y;\r\n this._z = z;\r\n this._u = u;\r\n this._v = v;\r\n this._node = node;\r\n }\r\n /**\r\n * Set all content directly from args.\r\n * @returns `this` reference\r\n */\r\n public set(node: HalfEdge, x: number, y: number, z: number, u: number, v: number): NodeXYZUV {\r\n this._x = x;\r\n this._y = y;\r\n this._z = z;\r\n this._u = u;\r\n this._v = v;\r\n this._node = node;\r\n return this;\r\n }\r\n /** Set from `other` */\r\n public setFrom(other: NodeXYZUV): void {\r\n this._x = other.x;\r\n this._y = other.y;\r\n this._z = other.z;\r\n this._u = other.u;\r\n this._v = other.v;\r\n this._node = other.node;\r\n }\r\n /**\r\n * Create a `NodeXYZUV` with:\r\n * * node from the given HalfEdge.\r\n * * x,y,z as the coordinates of `node`.\r\n * * u as the xy dot product of vectorA with `ray.direction`, where vectorA is the vector from ray origin to\r\n * `node` coordinates (z is ignored).\r\n * * v as the xy cross product of `ray.direction` with vectorA.\r\n */\r\n public static createNodeAndRayOrigin(node: HalfEdge, ray: Ray3d, result?: NodeXYZUV): NodeXYZUV {\r\n const x = node.x;\r\n const y = node.y;\r\n const z = node.z;\r\n const dx = x - ray.origin.x;\r\n const dy = y - ray.origin.y;\r\n const u = Geometry.dotProductXYXY(dx, dy, ray.direction.x, ray.direction.y);\r\n const v = Geometry.crossProductXYXY(ray.direction.x, ray.direction.y, dx, dy);\r\n if (result)\r\n return result.set(node, x, y, z, u, v);\r\n return new NodeXYZUV(node, x, y, z, u, v);\r\n }\r\n /** Create a `NodeXYZUV` with explicit `node`, xyz, uv. */\r\n public static create(\r\n node: HalfEdge, x: number = 0, y: number = 0, z: number = 0, u: number = 0, v: number = 0,\r\n ): NodeXYZUV {\r\n return new NodeXYZUV(node, x, y, z, u, v);\r\n }\r\n /** Access the node. */\r\n public get node(): HalfEdge {\r\n return this._node;\r\n }\r\n /** Access the x coordinate. */\r\n public get x(): number {\r\n return this._x;\r\n }\r\n /** Access the y coordinate. */\r\n public get y(): number {\r\n return this._y;\r\n }\r\n /** Access the z coordinate. */\r\n public get z(): number {\r\n return this._z;\r\n }\r\n /** Access the u coordinate. */\r\n public get u(): number {\r\n return this._u;\r\n }\r\n /** Access the v coordinate. */\r\n public get v(): number {\r\n return this._v;\r\n }\r\n /** Access the x,y,z coordinates as Point3d with optional caller-supplied result. */\r\n public getXYZAsPoint3d(result?: Point3d): Point3d {\r\n return Point3d.create(this._x, this._y, this._z, result);\r\n }\r\n /** Access the uv coordinates as Point2d with optional caller-supplied result. */\r\n public getUVAsPoint2d(result?: Point2d): Point2d {\r\n return Point2d.create(this._u, this._v, result);\r\n }\r\n /** Toleranced comparison function for u coordinate */\r\n public classifyU(target: number, tol: number): number {\r\n const delta = this.u - target;\r\n if (Math.abs(delta) <= tol)\r\n return 0;\r\n return delta >= 0 ? 1 : -1;\r\n }\r\n /** Toleranced comparison function for v coordinate */\r\n public classifyV(target: number, tol: number): number {\r\n const delta = target - this._v;\r\n if (Math.abs(delta) <= tol)\r\n return 0;\r\n return delta >= 0 ? 1 : -1;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"HalfEdgeNodeXYZUV.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgeNodeXYZUV.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*--------------------------------------------------------------------------------------------*/\nimport { Geometry } from \"../Geometry\";\nimport { Point2d } from \"../geometry3d/Point2dVector2d\";\nimport { Point3d } from \"../geometry3d/Point3dVector3d\";\nimport { Ray3d } from \"../geometry3d/Ray3d\";\nimport { HalfEdge } from \"./Graph\";\n\n/** @packageDocumentation\n * @module Topology\n */\n/**\n * Reference to a HalfEdge node with extra XYZ and UV data.\n * @internal\n */\nexport class NodeXYZUV {\n private _node: HalfEdge;\n private _x: number;\n private _y: number;\n private _z: number;\n private _u: number;\n private _v: number;\n /** Constructor */\n private constructor(node: HalfEdge, x: number, y: number, z: number, u: number, v: number) {\n this._x = x;\n this._y = y;\n this._z = z;\n this._u = u;\n this._v = v;\n this._node = node;\n }\n /**\n * Set all content directly from args.\n * @returns `this` reference\n */\n public set(node: HalfEdge, x: number, y: number, z: number, u: number, v: number): NodeXYZUV {\n this._x = x;\n this._y = y;\n this._z = z;\n this._u = u;\n this._v = v;\n this._node = node;\n return this;\n }\n /** Set from `other` */\n public setFrom(other: NodeXYZUV): void {\n this._x = other.x;\n this._y = other.y;\n this._z = other.z;\n this._u = other.u;\n this._v = other.v;\n this._node = other.node;\n }\n /**\n * Create a `NodeXYZUV` with:\n * * node from the given HalfEdge.\n * * x,y,z as the coordinates of `node`.\n * * u as the xy dot product of vectorA with `ray.direction`, where vectorA is the vector from ray origin to\n * `node` coordinates (z is ignored).\n * * v as the xy cross product of `ray.direction` with vectorA.\n */\n public static createNodeAndRayOrigin(node: HalfEdge, ray: Ray3d, result?: NodeXYZUV): NodeXYZUV {\n const x = node.x;\n const y = node.y;\n const z = node.z;\n const dx = x - ray.origin.x;\n const dy = y - ray.origin.y;\n const u = Geometry.dotProductXYXY(dx, dy, ray.direction.x, ray.direction.y);\n const v = Geometry.crossProductXYXY(ray.direction.x, ray.direction.y, dx, dy);\n if (result)\n return result.set(node, x, y, z, u, v);\n return new NodeXYZUV(node, x, y, z, u, v);\n }\n /** Create a `NodeXYZUV` with explicit `node`, xyz, uv. */\n public static create(\n node: HalfEdge, x: number = 0, y: number = 0, z: number = 0, u: number = 0, v: number = 0,\n ): NodeXYZUV {\n return new NodeXYZUV(node, x, y, z, u, v);\n }\n /** Access the node. */\n public get node(): HalfEdge {\n return this._node;\n }\n /** Access the x coordinate. */\n public get x(): number {\n return this._x;\n }\n /** Access the y coordinate. */\n public get y(): number {\n return this._y;\n }\n /** Access the z coordinate. */\n public get z(): number {\n return this._z;\n }\n /** Access the u coordinate. */\n public get u(): number {\n return this._u;\n }\n /** Access the v coordinate. */\n public get v(): number {\n return this._v;\n }\n /** Access the x,y,z coordinates as Point3d with optional caller-supplied result. */\n public getXYZAsPoint3d(result?: Point3d): Point3d {\n return Point3d.create(this._x, this._y, this._z, result);\n }\n /** Access the uv coordinates as Point2d with optional caller-supplied result. */\n public getUVAsPoint2d(result?: Point2d): Point2d {\n return Point2d.create(this._u, this._v, result);\n }\n /** Toleranced comparison function for u coordinate */\n public classifyU(target: number, tol: number): number {\n const delta = this.u - target;\n if (Math.abs(delta) <= tol)\n return 0;\n return delta >= 0 ? 1 : -1;\n }\n /** Toleranced comparison function for v coordinate */\n public classifyV(target: number, tol: number): number {\n const delta = target - this._v;\n if (Math.abs(delta) <= tol)\n return 0;\n return delta >= 0 ? 1 : -1;\n }\n}\n"]}