@itwin/core-geometry 4.2.0-dev.11 → 4.2.0-dev.12

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 (187) hide show
  1. package/lib/cjs/clipping/AlternatingConvexClipTree.d.ts +4 -3
  2. package/lib/cjs/clipping/AlternatingConvexClipTree.d.ts.map +1 -1
  3. package/lib/cjs/clipping/AlternatingConvexClipTree.js +1 -1
  4. package/lib/cjs/clipping/AlternatingConvexClipTree.js.map +1 -1
  5. package/lib/cjs/clipping/BooleanClipNode.d.ts +4 -3
  6. package/lib/cjs/clipping/BooleanClipNode.d.ts.map +1 -1
  7. package/lib/cjs/clipping/BooleanClipNode.js.map +1 -1
  8. package/lib/cjs/clipping/ClipPlane.d.ts +2 -1
  9. package/lib/cjs/clipping/ClipPlane.d.ts.map +1 -1
  10. package/lib/cjs/clipping/ClipPlane.js.map +1 -1
  11. package/lib/cjs/clipping/ClipUtils.d.ts +4 -4
  12. package/lib/cjs/clipping/ClipUtils.d.ts.map +1 -1
  13. package/lib/cjs/clipping/ClipUtils.js +1 -1
  14. package/lib/cjs/clipping/ClipUtils.js.map +1 -1
  15. package/lib/cjs/clipping/ClipVector.d.ts +6 -5
  16. package/lib/cjs/clipping/ClipVector.d.ts.map +1 -1
  17. package/lib/cjs/clipping/ClipVector.js +1 -1
  18. package/lib/cjs/clipping/ClipVector.js.map +1 -1
  19. package/lib/cjs/clipping/ConvexClipPlaneSet.d.ts +3 -2
  20. package/lib/cjs/clipping/ConvexClipPlaneSet.d.ts.map +1 -1
  21. package/lib/cjs/clipping/ConvexClipPlaneSet.js.map +1 -1
  22. package/lib/cjs/clipping/UnionOfConvexClipPlaneSets.d.ts +2 -1
  23. package/lib/cjs/clipping/UnionOfConvexClipPlaneSets.d.ts.map +1 -1
  24. package/lib/cjs/clipping/UnionOfConvexClipPlaneSets.js.map +1 -1
  25. package/lib/cjs/core-geometry.d.ts +0 -2
  26. package/lib/cjs/core-geometry.d.ts.map +1 -1
  27. package/lib/cjs/core-geometry.js +0 -2
  28. package/lib/cjs/core-geometry.js.map +1 -1
  29. package/lib/cjs/curve/Arc3d.d.ts.map +1 -1
  30. package/lib/cjs/curve/Arc3d.js.map +1 -1
  31. package/lib/cjs/curve/CurveCollection.d.ts +1 -1
  32. package/lib/cjs/curve/CurveCollection.d.ts.map +1 -1
  33. package/lib/cjs/curve/CurveCollection.js +1 -3
  34. package/lib/cjs/curve/CurveCollection.js.map +1 -1
  35. package/lib/cjs/curve/CurveCurve.d.ts +38 -26
  36. package/lib/cjs/curve/CurveCurve.d.ts.map +1 -1
  37. package/lib/cjs/curve/CurveCurve.js +70 -40
  38. package/lib/cjs/curve/CurveCurve.js.map +1 -1
  39. package/lib/cjs/curve/CurveLocationDetail.d.ts +12 -1
  40. package/lib/cjs/curve/CurveLocationDetail.d.ts.map +1 -1
  41. package/lib/cjs/curve/CurveLocationDetail.js +13 -2
  42. package/lib/cjs/curve/CurveLocationDetail.js.map +1 -1
  43. package/lib/cjs/curve/{CurveCurveCloseApproachXY.d.ts → internalContexts/CurveCurveCloseApproachXY.d.ts} +89 -48
  44. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.d.ts.map +1 -0
  45. package/lib/cjs/curve/{CurveCurveCloseApproachXY.js → internalContexts/CurveCurveCloseApproachXY.js} +196 -155
  46. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -0
  47. package/lib/{esm/curve → cjs/curve/internalContexts}/CurveCurveIntersectXY.d.ts +14 -27
  48. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -0
  49. package/lib/cjs/curve/{CurveCurveIntersectXY.js → internalContexts/CurveCurveIntersectXY.js} +19 -32
  50. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -0
  51. package/lib/cjs/curve/{CurveCurveIntersectXYZ.d.ts → internalContexts/CurveCurveIntersectXYZ.d.ts} +11 -12
  52. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXYZ.d.ts.map +1 -0
  53. package/lib/cjs/curve/{CurveCurveIntersectXYZ.js → internalContexts/CurveCurveIntersectXYZ.js} +12 -14
  54. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXYZ.js.map +1 -0
  55. package/lib/cjs/geometry3d/BarycentricTriangle.d.ts +1 -0
  56. package/lib/cjs/geometry3d/BarycentricTriangle.d.ts.map +1 -1
  57. package/lib/cjs/geometry3d/BarycentricTriangle.js +1 -0
  58. package/lib/cjs/geometry3d/BarycentricTriangle.js.map +1 -1
  59. package/lib/cjs/geometry3d/FrameBuilder.d.ts +28 -11
  60. package/lib/cjs/geometry3d/FrameBuilder.d.ts.map +1 -1
  61. package/lib/cjs/geometry3d/FrameBuilder.js +57 -45
  62. package/lib/cjs/geometry3d/FrameBuilder.js.map +1 -1
  63. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts +0 -8
  64. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  65. package/lib/cjs/geometry3d/GrowableXYZArray.js +0 -16
  66. package/lib/cjs/geometry3d/GrowableXYZArray.js.map +1 -1
  67. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts +4 -4
  68. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  69. package/lib/cjs/geometry3d/IndexedXYZCollection.js +12 -0
  70. package/lib/cjs/geometry3d/IndexedXYZCollection.js.map +1 -1
  71. package/lib/cjs/geometry3d/Point3dArrayCarrier.d.ts.map +1 -1
  72. package/lib/cjs/geometry3d/Point3dArrayCarrier.js.map +1 -1
  73. package/lib/cjs/geometry3d/PolygonOps.d.ts +1 -1
  74. package/lib/cjs/geometry3d/PolygonOps.d.ts.map +1 -1
  75. package/lib/cjs/geometry3d/PolygonOps.js.map +1 -1
  76. package/lib/cjs/geometry3d/Ray3d.d.ts +3 -1
  77. package/lib/cjs/geometry3d/Ray3d.d.ts.map +1 -1
  78. package/lib/cjs/geometry3d/Ray3d.js +4 -3
  79. package/lib/cjs/geometry3d/Ray3d.js.map +1 -1
  80. package/lib/cjs/geometry3d/ReusableObjectCache.d.ts +2 -1
  81. package/lib/cjs/geometry3d/ReusableObjectCache.d.ts.map +1 -1
  82. package/lib/cjs/geometry3d/ReusableObjectCache.js +1 -1
  83. package/lib/cjs/geometry3d/ReusableObjectCache.js.map +1 -1
  84. package/lib/cjs/numerics/Polynomials.d.ts +2 -2
  85. package/lib/cjs/numerics/Polynomials.d.ts.map +1 -1
  86. package/lib/cjs/numerics/Polynomials.js +2 -2
  87. package/lib/cjs/numerics/Polynomials.js.map +1 -1
  88. package/lib/esm/clipping/AlternatingConvexClipTree.d.ts +4 -3
  89. package/lib/esm/clipping/AlternatingConvexClipTree.d.ts.map +1 -1
  90. package/lib/esm/clipping/AlternatingConvexClipTree.js +1 -1
  91. package/lib/esm/clipping/AlternatingConvexClipTree.js.map +1 -1
  92. package/lib/esm/clipping/BooleanClipNode.d.ts +4 -3
  93. package/lib/esm/clipping/BooleanClipNode.d.ts.map +1 -1
  94. package/lib/esm/clipping/BooleanClipNode.js.map +1 -1
  95. package/lib/esm/clipping/ClipPlane.d.ts +2 -1
  96. package/lib/esm/clipping/ClipPlane.d.ts.map +1 -1
  97. package/lib/esm/clipping/ClipPlane.js.map +1 -1
  98. package/lib/esm/clipping/ClipUtils.d.ts +4 -4
  99. package/lib/esm/clipping/ClipUtils.d.ts.map +1 -1
  100. package/lib/esm/clipping/ClipUtils.js +1 -1
  101. package/lib/esm/clipping/ClipUtils.js.map +1 -1
  102. package/lib/esm/clipping/ClipVector.d.ts +6 -5
  103. package/lib/esm/clipping/ClipVector.d.ts.map +1 -1
  104. package/lib/esm/clipping/ClipVector.js +1 -1
  105. package/lib/esm/clipping/ClipVector.js.map +1 -1
  106. package/lib/esm/clipping/ConvexClipPlaneSet.d.ts +3 -2
  107. package/lib/esm/clipping/ConvexClipPlaneSet.d.ts.map +1 -1
  108. package/lib/esm/clipping/ConvexClipPlaneSet.js.map +1 -1
  109. package/lib/esm/clipping/UnionOfConvexClipPlaneSets.d.ts +2 -1
  110. package/lib/esm/clipping/UnionOfConvexClipPlaneSets.d.ts.map +1 -1
  111. package/lib/esm/clipping/UnionOfConvexClipPlaneSets.js.map +1 -1
  112. package/lib/esm/core-geometry.d.ts +0 -2
  113. package/lib/esm/core-geometry.d.ts.map +1 -1
  114. package/lib/esm/core-geometry.js +0 -2
  115. package/lib/esm/core-geometry.js.map +1 -1
  116. package/lib/esm/curve/Arc3d.d.ts.map +1 -1
  117. package/lib/esm/curve/Arc3d.js.map +1 -1
  118. package/lib/esm/curve/CurveCollection.d.ts +1 -1
  119. package/lib/esm/curve/CurveCollection.d.ts.map +1 -1
  120. package/lib/esm/curve/CurveCollection.js +1 -3
  121. package/lib/esm/curve/CurveCollection.js.map +1 -1
  122. package/lib/esm/curve/CurveCurve.d.ts +38 -26
  123. package/lib/esm/curve/CurveCurve.d.ts.map +1 -1
  124. package/lib/esm/curve/CurveCurve.js +70 -40
  125. package/lib/esm/curve/CurveCurve.js.map +1 -1
  126. package/lib/esm/curve/CurveLocationDetail.d.ts +12 -1
  127. package/lib/esm/curve/CurveLocationDetail.d.ts.map +1 -1
  128. package/lib/esm/curve/CurveLocationDetail.js +11 -1
  129. package/lib/esm/curve/CurveLocationDetail.js.map +1 -1
  130. package/lib/esm/curve/{CurveCurveCloseApproachXY.d.ts → internalContexts/CurveCurveCloseApproachXY.d.ts} +89 -48
  131. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.d.ts.map +1 -0
  132. package/lib/esm/curve/{CurveCurveCloseApproachXY.js → internalContexts/CurveCurveCloseApproachXY.js} +196 -155
  133. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -0
  134. package/lib/{cjs/curve → esm/curve/internalContexts}/CurveCurveIntersectXY.d.ts +14 -27
  135. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -0
  136. package/lib/esm/curve/{CurveCurveIntersectXY.js → internalContexts/CurveCurveIntersectXY.js} +18 -30
  137. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -0
  138. package/lib/esm/curve/{CurveCurveIntersectXYZ.d.ts → internalContexts/CurveCurveIntersectXYZ.d.ts} +11 -12
  139. package/lib/esm/curve/internalContexts/CurveCurveIntersectXYZ.d.ts.map +1 -0
  140. package/lib/esm/curve/{CurveCurveIntersectXYZ.js → internalContexts/CurveCurveIntersectXYZ.js} +11 -13
  141. package/lib/esm/curve/internalContexts/CurveCurveIntersectXYZ.js.map +1 -0
  142. package/lib/esm/geometry3d/BarycentricTriangle.d.ts +1 -0
  143. package/lib/esm/geometry3d/BarycentricTriangle.d.ts.map +1 -1
  144. package/lib/esm/geometry3d/BarycentricTriangle.js +1 -0
  145. package/lib/esm/geometry3d/BarycentricTriangle.js.map +1 -1
  146. package/lib/esm/geometry3d/FrameBuilder.d.ts +28 -11
  147. package/lib/esm/geometry3d/FrameBuilder.d.ts.map +1 -1
  148. package/lib/esm/geometry3d/FrameBuilder.js +57 -45
  149. package/lib/esm/geometry3d/FrameBuilder.js.map +1 -1
  150. package/lib/esm/geometry3d/GrowableXYZArray.d.ts +0 -8
  151. package/lib/esm/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  152. package/lib/esm/geometry3d/GrowableXYZArray.js +0 -16
  153. package/lib/esm/geometry3d/GrowableXYZArray.js.map +1 -1
  154. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts +4 -4
  155. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  156. package/lib/esm/geometry3d/IndexedXYZCollection.js +12 -0
  157. package/lib/esm/geometry3d/IndexedXYZCollection.js.map +1 -1
  158. package/lib/esm/geometry3d/Point3dArrayCarrier.d.ts.map +1 -1
  159. package/lib/esm/geometry3d/Point3dArrayCarrier.js.map +1 -1
  160. package/lib/esm/geometry3d/PolygonOps.d.ts +1 -1
  161. package/lib/esm/geometry3d/PolygonOps.d.ts.map +1 -1
  162. package/lib/esm/geometry3d/PolygonOps.js.map +1 -1
  163. package/lib/esm/geometry3d/Ray3d.d.ts +3 -1
  164. package/lib/esm/geometry3d/Ray3d.d.ts.map +1 -1
  165. package/lib/esm/geometry3d/Ray3d.js +4 -3
  166. package/lib/esm/geometry3d/Ray3d.js.map +1 -1
  167. package/lib/esm/geometry3d/ReusableObjectCache.d.ts +2 -1
  168. package/lib/esm/geometry3d/ReusableObjectCache.d.ts.map +1 -1
  169. package/lib/esm/geometry3d/ReusableObjectCache.js +1 -1
  170. package/lib/esm/geometry3d/ReusableObjectCache.js.map +1 -1
  171. package/lib/esm/numerics/Polynomials.d.ts +2 -2
  172. package/lib/esm/numerics/Polynomials.d.ts.map +1 -1
  173. package/lib/esm/numerics/Polynomials.js +2 -2
  174. package/lib/esm/numerics/Polynomials.js.map +1 -1
  175. package/package.json +3 -3
  176. package/lib/cjs/curve/CurveCurveCloseApproachXY.d.ts.map +0 -1
  177. package/lib/cjs/curve/CurveCurveCloseApproachXY.js.map +0 -1
  178. package/lib/cjs/curve/CurveCurveIntersectXY.d.ts.map +0 -1
  179. package/lib/cjs/curve/CurveCurveIntersectXY.js.map +0 -1
  180. package/lib/cjs/curve/CurveCurveIntersectXYZ.d.ts.map +0 -1
  181. package/lib/cjs/curve/CurveCurveIntersectXYZ.js.map +0 -1
  182. package/lib/esm/curve/CurveCurveCloseApproachXY.d.ts.map +0 -1
  183. package/lib/esm/curve/CurveCurveCloseApproachXY.js.map +0 -1
  184. package/lib/esm/curve/CurveCurveIntersectXY.d.ts.map +0 -1
  185. package/lib/esm/curve/CurveCurveIntersectXY.js.map +0 -1
  186. package/lib/esm/curve/CurveCurveIntersectXYZ.d.ts.map +0 -1
  187. package/lib/esm/curve/CurveCurveIntersectXYZ.js.map +0 -1
@@ -8,32 +8,34 @@ exports.CurveCurveCloseApproachXY = void 0;
8
8
  /** @packageDocumentation
9
9
  * @module Curve
10
10
  */
11
- const BSplineCurve_1 = require("../bspline/BSplineCurve");
12
- const Geometry_1 = require("../Geometry");
13
- const GeometryHandler_1 = require("../geometry3d/GeometryHandler");
14
- const GrowableFloat64Array_1 = require("../geometry3d/GrowableFloat64Array");
15
- const Point3dVector3d_1 = require("../geometry3d/Point3dVector3d");
16
- const Range_1 = require("../geometry3d/Range");
17
- const Polynomials_1 = require("../numerics/Polynomials");
18
- const Arc3d_1 = require("./Arc3d");
19
- const CurveLocationDetail_1 = require("./CurveLocationDetail");
20
- const LineSegment3d_1 = require("./LineSegment3d");
21
- const LineString3d_1 = require("./LineString3d");
11
+ const BSplineCurve_1 = require("../../bspline/BSplineCurve");
12
+ const Geometry_1 = require("../../Geometry");
13
+ const GeometryHandler_1 = require("../../geometry3d/GeometryHandler");
14
+ const GrowableFloat64Array_1 = require("../../geometry3d/GrowableFloat64Array");
15
+ const Point3dVector3d_1 = require("../../geometry3d/Point3dVector3d");
16
+ const Range_1 = require("../../geometry3d/Range");
17
+ const Polynomials_1 = require("../../numerics/Polynomials");
18
+ const Arc3d_1 = require("../Arc3d");
19
+ const CurveCollection_1 = require("../CurveCollection");
20
+ const CurveLocationDetail_1 = require("../CurveLocationDetail");
21
+ const LineSegment3d_1 = require("../LineSegment3d");
22
+ const LineString3d_1 = require("../LineString3d");
22
23
  // cspell:word XYRR
23
24
  /**
24
25
  * Handler class for XY close approach between _geometryB and another geometry.
25
- * * Approach means the distance between _geometryB and another geometry.
26
- * * **NOTE:** GeometryQuery input (_geometryB) should really be AnyCurve.
26
+ * * Approach means the XY distance (z is ignored) between _geometryB and another geometry.
27
27
  * * Closest approach is a measure of the proximity of one curve to another. It's the length of the shortest line
28
28
  * segment perpendicular to both curves; if the curves intersect, the closest approach is zero. In the context of
29
29
  * this class, z-coordinates are ignored, so the closest approach is as seen in the top view. If you have coplanar
30
- * input curves, rotate them first into a plane parallel to the xy-plane, then afterward, you should rotate the
31
- * results back as required.
30
+ * input curves and want to find closest approach in their plane, rotate them first into a plane parallel to the
31
+ * xy-plane, then afterward, rotate the results back as required.
32
+ * * Close approach can also be from a curve endpoint perpendicular to another curve or from a curve endpoint to
33
+ * another curve endpoint.
32
34
  * * Instances are initialized and called from CurveCurve.
33
35
  * * geometryB is saved for later reference.
34
36
  * @internal
35
37
  */
36
- class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
38
+ class CurveCurveCloseApproachXY extends GeometryHandler_1.RecurseToCurvesGeometryHandler {
37
39
  setGeometryB(geometryB) {
38
40
  this._geometryB = geometryB;
39
41
  this._circularArcB = undefined;
@@ -59,13 +61,13 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
59
61
  this._maxDistanceSquared = Geometry_1.Geometry.smallMetricDistanceSquared;
60
62
  this.reinitialize();
61
63
  }
62
- /** Set the (possibly undefined) max distance to accept. */
64
+ /** Set the (possibly undefined) max XY distance (z is ignored) to accept. */
63
65
  set maxDistanceToAccept(value) {
64
66
  this._maxDistanceToAccept = value;
65
67
  if (this._maxDistanceToAccept !== undefined && this._maxDistanceToAccept > 0)
66
68
  this._maxDistanceSquared = this._maxDistanceToAccept * this._maxDistanceToAccept;
67
69
  }
68
- /** Access the (possibly undefined) max distance to accept. */
70
+ /** Access the (possibly undefined) max XY distance (z is ignored) to accept. */
69
71
  get maxDistanceToAccept() {
70
72
  return this._maxDistanceToAccept;
71
73
  }
@@ -99,6 +101,10 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
99
101
  sameCurveAndFraction(cp, fraction, detail) {
100
102
  return cp === detail.curve && Geometry_1.Geometry.isAlmostEqualNumber(fraction, detail.fraction);
101
103
  }
104
+ /**
105
+ * If distance between pointA and pointB is less than maxDistance, record CurveLocationDetailPair which is
106
+ * the approach from pointA to pointB.
107
+ */
102
108
  testAndRecordPointPairApproach(cpA, fA, pointA, cpB, fB, pointB, reversed) {
103
109
  const d2 = pointA.distanceSquaredXY(pointB);
104
110
  if (d2 < this._maxDistanceSquared) {
@@ -111,12 +117,19 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
111
117
  }
112
118
  }
113
119
  /**
114
- * Compute intersection of two line segments.
115
- * Filter by extension rules.
116
- * Record with fraction mapping.
120
+ * Create a close approach pair if XY distance is within maxDistance.
121
+ * @param localFractionA a fraction on first curve
122
+ * @param cpA the first curve
123
+ * @param fractionA0 start of the first curve
124
+ * @param fractionA1 end of the first curve
125
+ * @param localFractionB a fraction on second curve
126
+ * @param cpB the second curve
127
+ * @param fractionB0 start of the second curve
128
+ * @param fractionB1 end of the second curve
129
+ * @param reversed true to have order reversed in final structures
130
+ * @param intervalDetails optional CurveLocationDetailPair
117
131
  */
118
- recordPointWithLocalFractions(localFractionA, cpA, fractionA0, fractionA1, localFractionB, // Computed intersection fraction
119
- cpB, fractionB0, fractionB1, reversed, intervalDetails) {
132
+ recordPointWithLocalFractions(localFractionA, cpA, fractionA0, fractionA1, localFractionB, cpB, fractionB0, fractionB1, reversed, intervalDetails) {
120
133
  let globalFractionA, globalFractionB;
121
134
  let globalFractionA1, globalFractionB1;
122
135
  const isInterval = intervalDetails !== undefined &&
@@ -132,7 +145,7 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
132
145
  globalFractionA = globalFractionA1 = Geometry_1.Geometry.interpolate(fractionA0, localFractionA, fractionA1);
133
146
  globalFractionB = globalFractionB1 = Geometry_1.Geometry.interpolate(fractionB0, localFractionB, fractionB1);
134
147
  }
135
- // ignore duplicate of most recent point . ..
148
+ // ignore duplicate of most recent approach
136
149
  const numPrevious = this._results.length;
137
150
  if (numPrevious > 0 && !isInterval) {
138
151
  const oldDetailA = this._results[numPrevious - 1].detailA;
@@ -155,6 +168,9 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
155
168
  detailB.captureFraction1Point1(globalFractionB1, cpB.fractionToPoint(globalFractionB1));
156
169
  }
157
170
  else {
171
+ const d2 = detailA.point.distanceSquaredXY(detailB.point);
172
+ if (d2 > this._maxDistanceSquared)
173
+ return;
158
174
  detailA.setIntervalRole(CurveLocationDetail_1.CurveIntervalRole.isolated);
159
175
  detailB.setIntervalRole(CurveLocationDetail_1.CurveIntervalRole.isolated);
160
176
  }
@@ -167,12 +183,21 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
167
183
  }
168
184
  /**
169
185
  * Capture a close approach pair that has point and local fraction but not curve.
170
- * Record with fraction mapping.
186
+ * * Record the pair, each detail modified with global fraction and input curve.
187
+ * * Pair is neither modified nor recorded if it would be a duplicate of the last recorded pair.
188
+ * @param pair details computed with local fractions
189
+ * @param cpA curveA
190
+ * @param fractionA0 global start fraction on curveA
191
+ * @param fractionA1 global end fraction on curveA
192
+ * @param cpB curveB
193
+ * @param fractionB0 global start fraction on curveB
194
+ * @param fractionB1 global end fraction on curveB
195
+ * @param reversed whether to reverse the details in the pair
171
196
  */
172
197
  capturePairWithLocalFractions(pair, cpA, fractionA0, fractionA1, cpB, fractionB0, fractionB1, reversed) {
173
198
  const globalFractionA = Geometry_1.Geometry.interpolate(fractionA0, pair.detailA.fraction, fractionA1);
174
199
  const globalFractionB = Geometry_1.Geometry.interpolate(fractionB0, pair.detailB.fraction, fractionB1);
175
- // ignore duplicate of most recent point . ..
200
+ // ignore duplicate of most recent pair
176
201
  const numPrevious = this._results.length;
177
202
  if (numPrevious > 0) {
178
203
  const oldDetailA = this._results[numPrevious - 1].detailA;
@@ -188,18 +213,17 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
188
213
  return;
189
214
  }
190
215
  }
216
+ if (reversed)
217
+ pair.swapDetails();
218
+ // recompute the points just in case
219
+ CurveLocationDetail_1.CurveLocationDetail.createCurveEvaluatedFraction(cpA, globalFractionA, pair.detailA);
220
+ CurveLocationDetail_1.CurveLocationDetail.createCurveEvaluatedFraction(cpB, globalFractionB, pair.detailB);
191
221
  pair.detailA.setIntervalRole(CurveLocationDetail_1.CurveIntervalRole.isolated);
192
222
  pair.detailB.setIntervalRole(CurveLocationDetail_1.CurveIntervalRole.isolated);
193
- if (reversed) {
194
- this._results.push(pair);
195
- }
196
- else {
197
- pair.swapDetails();
198
- this._results.push(pair);
199
- }
223
+ this._results.push(pair);
200
224
  }
201
225
  /**
202
- * Emit recordPoint for multiple pairs (on full curve!)
226
+ * Emit recordPoint for multiple pairs (on full curve) if within maxDistance.
203
227
  * @param cpA first curve primitive (possibly different from curve in detailA, but fraction compatible)
204
228
  * @param cpB second curve primitive (possibly different from curve in detailA, but fraction compatible)
205
229
  * @param pairs array of pairs
@@ -221,44 +245,40 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
221
245
  captureDetailPair(detailA, detailB, reversed) {
222
246
  if (detailA && detailB) {
223
247
  if (reversed) {
224
- this._results.push(CurveLocationDetail_1.CurveLocationDetailPair.createCapture(detailA, detailB));
248
+ this._results.push(CurveLocationDetail_1.CurveLocationDetailPair.createCapture(detailB, detailA));
225
249
  }
226
250
  else {
227
- this._results.push(CurveLocationDetail_1.CurveLocationDetailPair.createCapture(detailB, detailA));
251
+ this._results.push(CurveLocationDetail_1.CurveLocationDetailPair.createCapture(detailA, detailB));
228
252
  }
229
253
  }
230
254
  }
231
- static updatePointToSegmentDistance(fractionA, pointA, pointB0, pointB1, fractionB, minDistanceSquared, closestApproach) {
255
+ static updatePointToSegmentDistance(fractionA, pointA, pointB0, pointB1, fractionB, maxDistanceSquared, closestApproach) {
256
+ let updated = false;
232
257
  if (fractionB < 0)
233
258
  fractionB = 0;
234
259
  else if (fractionB > 1)
235
260
  fractionB = 1;
236
261
  this._workPointB = pointB0.interpolate(fractionB, pointB1, this._workPointB);
237
262
  const distanceSquared = this._workPointB.distanceSquaredXY(pointA);
238
- if (distanceSquared < minDistanceSquared) {
239
- if (closestApproach === undefined || distanceSquared < closestApproach.detailA.a) {
240
- if (closestApproach === undefined)
241
- closestApproach = CurveLocationDetail_1.CurveLocationDetailPair.createCapture(CurveLocationDetail_1.CurveLocationDetail.create(), CurveLocationDetail_1.CurveLocationDetail.create());
242
- closestApproach.detailA.setFP(fractionA, pointA);
243
- closestApproach.detailA.a = distanceSquared;
244
- closestApproach.detailB.setFP(fractionB, this._workPointB);
245
- closestApproach.detailA.a = distanceSquared;
246
- }
263
+ if (distanceSquared < Math.min(maxDistanceSquared, closestApproach.detailA.a)) {
264
+ closestApproach.detailA.setFP(fractionA, pointA, undefined, distanceSquared);
265
+ closestApproach.detailB.setFP(fractionB, this._workPointB, undefined, distanceSquared);
266
+ updated = true;
247
267
  }
248
- return closestApproach;
268
+ return updated;
249
269
  }
250
270
  /**
251
- * Return fractions of close approach within minDistance between two line segments (a0,a1) and (b0, b1).
252
- * * minDistanceSquared is assumed positive.
253
- * Return the fractional (not xy) coordinates in result.x, result.y
271
+ * Return fractions of close approach within maxDistance between two line segments (a0,a1) and (b0,b1).
272
+ * * Math details can be found at docs/learning/geometry/CurveCurve.md
254
273
  * @param a0 start point of line a
255
- * @param a1 end point of line a
256
- * @param b0 start point of line b
274
+ * @param a1 end point of line a
275
+ * @param b0 start point of line b
257
276
  * @param b1 end point of line b
258
- * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y
259
- * is fraction on line b.
277
+ * @param maxDistanceSquared maximum distance squared (assumed to be positive)
278
+ * @returns the fractional (not xy) coordinates in result.x and result.y. result.x is fraction on line a.
279
+ * result.y is fraction on line b.
260
280
  */
261
- static segmentSegmentBoundedApproach(a0, a1, b0, b1, minDistanceSquared) {
281
+ static segmentSegmentBoundedApproach(a0, a1, b0, b1, maxDistanceSquared) {
262
282
  const ux = a1.x - a0.x;
263
283
  const uy = a1.y - a0.y;
264
284
  const vx = b1.x - b0.x;
@@ -269,41 +289,60 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
269
289
  const e01y = b1.y - a0.y;
270
290
  const e10x = b0.x - a1.x;
271
291
  const e10y = b0.y - a1.y;
272
- const e11x = b1.x - a1.x;
273
- const e11y = b1.y - a1.y;
274
292
  const hab0 = Geometry_1.Geometry.crossProductXYXY(ux, uy, e00x, e00y);
275
293
  const hab1 = Geometry_1.Geometry.crossProductXYXY(ux, uy, e01x, e01y);
276
294
  const hba0 = -Geometry_1.Geometry.crossProductXYXY(vx, vy, e00x, e00y);
277
- const hba1 = -Geometry_1.Geometry.crossProductXYXY(vx, vy, e11x, e11y);
278
- if (hab0 * hab1 < 0.0 && hba0 * hba1 < 0.0) {
279
- // true intersection, strictly within both segments !!!
295
+ const hba1 = -Geometry_1.Geometry.crossProductXYXY(vx, vy, e10x, e10y);
296
+ if (hab0 * hab1 < 0.0 && hba0 * hba1 < 0.0) { // true intersection, strictly within both segments
280
297
  const fractionA = -hba0 / (hba1 - hba0);
281
298
  const fractionB = -hab0 / (hab1 - hab0);
282
299
  return CurveLocationDetail_1.CurveLocationDetailPair.createCapture(CurveLocationDetail_1.CurveLocationDetail.createCurveFractionPoint(undefined, fractionA, a0.interpolate(fractionA, a1)), CurveLocationDetail_1.CurveLocationDetail.createCurveFractionPoint(undefined, fractionB, b0.interpolate(fractionB, b1)));
283
300
  }
284
- let closestApproach;
301
+ // there's no intersection, so find the closest approach within maxDistance from an endpoint
302
+ const closestApproach = new CurveLocationDetail_1.CurveLocationDetailPair();
303
+ closestApproach.detailA.a = 2 * maxDistanceSquared; // init to an approach that's too far away
304
+ let reversed = false;
285
305
  const uu = Geometry_1.Geometry.hypotenuseSquaredXY(ux, uy);
286
- if (hab0 * hab0 < minDistanceSquared * uu)
287
- closestApproach = this.updatePointToSegmentDistance(0, b0, a0, a1, Geometry_1.Geometry.dotProductXYXY(ux, uy, e00x, e00y) / uu, minDistanceSquared, closestApproach);
288
- if (hab1 * hab1 < minDistanceSquared * uu)
289
- closestApproach = this.updatePointToSegmentDistance(1, b1, a0, a1, Geometry_1.Geometry.dotProductXYXY(ux, uy, e01x, e01y) / uu, minDistanceSquared, closestApproach);
306
+ if (hab0 * hab0 < maxDistanceSquared * uu) { // test distance of b0 to u
307
+ const fractionA = Geometry_1.Geometry.dotProductXYXY(ux, uy, e00x, e00y) / uu;
308
+ if (this.updatePointToSegmentDistance(0, b0, a0, a1, fractionA, maxDistanceSquared, closestApproach))
309
+ reversed = true;
310
+ }
311
+ if (hab1 * hab1 < maxDistanceSquared * uu) { // test distance of b1 to u
312
+ const fractionA = Geometry_1.Geometry.dotProductXYXY(ux, uy, e01x, e01y) / uu;
313
+ if (this.updatePointToSegmentDistance(1, b1, a0, a1, fractionA, maxDistanceSquared, closestApproach))
314
+ reversed = true;
315
+ }
290
316
  const vv = Geometry_1.Geometry.hypotenuseSquaredXY(vx, vy);
291
- if (hba0 * hba0 < minDistanceSquared * vv)
292
- closestApproach = this.updatePointToSegmentDistance(0, a0, b0, b1, -Geometry_1.Geometry.dotProductXYXY(vx, vy, e00x, e00y) / vv, minDistanceSquared, closestApproach);
293
- if (hba1 * hba1 < minDistanceSquared * vv)
294
- closestApproach = this.updatePointToSegmentDistance(1, a1, b0, b1, -Geometry_1.Geometry.dotProductXYXY(vx, vy, e10x, e10y) / vv, minDistanceSquared, closestApproach);
317
+ if (hba0 * hba0 < maxDistanceSquared * vv) { // test distance of a0 to v
318
+ const fractionB = -Geometry_1.Geometry.dotProductXYXY(vx, vy, e00x, e00y) / vv;
319
+ if (this.updatePointToSegmentDistance(0, a0, b0, b1, fractionB, maxDistanceSquared, closestApproach))
320
+ reversed = false;
321
+ }
322
+ if (hba1 * hba1 < maxDistanceSquared * vv) { // test distance of a1 to v
323
+ const fractionB = -Geometry_1.Geometry.dotProductXYXY(vx, vy, e10x, e10y) / vv;
324
+ if (this.updatePointToSegmentDistance(1, a1, b0, b1, fractionB, maxDistanceSquared, closestApproach))
325
+ reversed = false;
326
+ }
327
+ if (closestApproach.detailA.a > maxDistanceSquared)
328
+ return undefined;
329
+ if (reversed)
330
+ closestApproach.swapDetails();
295
331
  return closestApproach;
296
332
  }
297
333
  /**
298
- * Return fractions of close approach within minDistance between two line segments( a0,a1) and (b0, b1)
299
- * * minDistance is assumed positive
300
- * Return the fractional (not xy) coordinates in result.x, result.y
301
- * @param a0 start point of line a
302
- * @param a1 end point of line a
303
- * @param b0 start point of line b
304
- * @param b1 end point of line b
305
- * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y
306
- * is fraction on line b.
334
+ * Check different combination of fractions on curveA and curveB. If distance between points at 2 fractions
335
+ * is less than maxDistance, record CurveLocationDetailPair which is the approach between the 2 points.
336
+ * Optionally, record close approaches of one curve's points if they fall between the other curve's points.
337
+ * @param cpA curveA
338
+ * @param fA0 fraction0 on curveA
339
+ * @param fA1 fraction1 on curveA
340
+ * @param testProjectionOnA whether to record projections of the given curveB points onto curveA
341
+ * @param cpB curveB
342
+ * @param fB0 fraction0 on curveB
343
+ * @param fB1 fraction0 on curveB
344
+ * @param testProjectionOnB whether to record projections of the given curveA points onto curveB
345
+ * @param reversed true to have order reversed in final structures.
307
346
  */
308
347
  testAndRecordFractionalPairApproach(cpA, fA0, fA1, testProjectionOnA, cpB, fB0, fB1, testProjectionOnB, reversed) {
309
348
  const pointA0 = cpA.fractionToPoint(fA0);
@@ -323,12 +362,13 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
323
362
  this.testAndRecordProjection(cpB, fB1, pointB1, cpA, fA0, fA1, !reversed);
324
363
  }
325
364
  }
365
+ /** Find the closest approach between pointA and cpB. Add the approach if it's within fB0 and fB1. */
326
366
  testAndRecordProjection(cpA, fA, pointA, cpB, fB0, fB1, reversed) {
327
367
  // NO NO NO -- this is 3D closest point --- need 2d !!
328
368
  const detail = cpB.closestPoint(pointA, false);
329
369
  if (detail) {
330
370
  const fB = Geometry_1.Geometry.restrictToInterval(detail.fraction, fB0, fB1);
331
- if (fB === detail.fraction) {
371
+ if (fB === detail.fraction) { // if fraction is within fB0 and fB1
332
372
  this.testAndRecordPointPairApproach(cpA, fA, pointA, cpB, detail.fraction, detail.point, reversed);
333
373
  }
334
374
  }
@@ -340,53 +380,69 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
340
380
  * * The fraction mappings allow portions of a linestring to be passed here.
341
381
  */
342
382
  computeSegmentSegment3D(cpA, pointA0, fractionA0, pointA1, fractionA1, cpB, pointB0, fractionB0, pointB1, fractionB1, reversed) {
383
+ // compute a pair with fractions local to segments
343
384
  const approach = CurveCurveCloseApproachXY.segmentSegmentBoundedApproach(pointA0, pointA1, pointB0, pointB1, this._maxDistanceSquared);
344
- if (approach)
385
+ // adjust the pair to refer to input curves and global fractions, then record it if new
386
+ if (approach) {
387
+ approach.detailA.setCurve(cpA);
388
+ approach.detailB.setCurve(cpB);
345
389
  this.capturePairWithLocalFractions(approach, cpA, fractionA0, fractionA1, cpB, fractionB0, fractionB1, reversed);
390
+ }
346
391
  }
347
- // Caller accesses data from a line segment and passes to here.
348
- // (The line segment in question might be (a) a full line segment or (b) a fragment within a linestring.
349
- // The fraction and extend parameters allow all combinations to be passed in)
350
- // This method applies transform.
392
+ /** Low level dispatch of segment with segment. */
351
393
  dispatchSegmentSegment(cpA, pointA0, fractionA0, pointA1, fractionA1, cpB, pointB0, fractionB0, pointB1, fractionB1, reversed) {
352
394
  this.computeSegmentSegment3D(cpA, pointA0, fractionA0, pointA1, fractionA1, cpB, pointB0, fractionB0, pointB1, fractionB1, reversed);
353
395
  }
354
- // Caller accesses data from a linestring or segment and passes it here.
355
- // (The line segment in question might be (a) a full line segment or (b) a fragment within a linestring.
356
- // The fraction and extend parameters allow all combinations to be passed in)
396
+ /**
397
+ * Low level dispatch of segment with arc.
398
+ * Find close approaches within maxDistance between a line segments (pointA0, pointA1) and an arc.
399
+ * To consider:
400
+ * 1) arc endpoints to segment endpoints or arc endpoints projection to the segment.
401
+ * 2) intersection between arc and segment.
402
+ * 3) line parallel to arc tangent.
403
+ * @param cpA the segment
404
+ * @param pointA0 start point of the segment
405
+ * @param fractionA0 fraction of the start of the segment
406
+ * @param pointA1 end point of the segment
407
+ * @param fractionA1 fraction of the end of the segment
408
+ * @param arc the arc
409
+ * @param reversed true to have order reversed in final structures
410
+ */
357
411
  dispatchSegmentArc(cpA, pointA0, fractionA0, pointA1, fractionA1, arc, reversed) {
358
- // To consider:
359
- // 1) endpoint to endpoint or projection
360
- // 2) true intersection
361
- // 3) line parallel to arc tangent.
412
+ // 1) arc endpoints to segment endpoints or arc endpoints projection to the segment
362
413
  this.testAndRecordFractionalPairApproach(cpA, 0, 1, true, arc, 0, 1, false, reversed);
363
- // Arc: X = C + cU + sV
364
- // Line: contains points A0,A1
365
- // Arc point colinear with line if det (A0, A1, X) = 0
366
- // with homogeneous xyw points and vectors.
367
- // With equational X: det (A0, A1, C) + c det (A0, A1,U) + s det (A0, A1, V) = 0.
414
+ // 2) intersection between arc and segment
415
+ // Suppose:
416
+ // Arc: X = C + cU + sV where c = cos(theta) and s = sin(theta)
417
+ // Line: contains points A0 and A1
418
+ // The arc intersects the line at point X if det(A0, A1, X) = 0 with homogeneous xyw points and vectors.
419
+ // With equational X: det(A0, A1, C) + c*det(A0, A1, U) + s*det(A0, A1, V) = 0.
368
420
  // solve for theta.
369
421
  // evaluate points.
370
422
  // project back to line.
371
423
  const data = arc.toTransformedVectors();
372
424
  const pointA0Local = pointA0;
373
425
  const pointA1Local = pointA1;
374
- const alpha = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.center, 1);
375
- const beta = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.vector0, 0);
376
- const gamma = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.vector90, 0);
426
+ const alpha = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.center, 1); // det(A0, A1, C)
427
+ const beta = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.vector0, 0); // det(A0, A1, U)
428
+ const gamma = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.vector90, 0); // det(A0, A1, V)
377
429
  const cosines = new GrowableFloat64Array_1.GrowableFloat64Array(2);
378
430
  const sines = new GrowableFloat64Array_1.GrowableFloat64Array(2);
379
431
  const radians = new GrowableFloat64Array_1.GrowableFloat64Array(2);
380
- const numRoots = Polynomials_1.AnalyticRoots.appendImplicitLineUnitCircleIntersections(alpha, beta, gamma, cosines, sines, radians);
432
+ const numRoots = Polynomials_1.AnalyticRoots.appendImplicitLineUnitCircleIntersections(// solve the equation
433
+ alpha, beta, gamma, cosines, sines, radians);
381
434
  for (let i = 0; i < numRoots; i++) {
382
435
  const arcPoint = data.center.plus2Scaled(data.vector0, cosines.atUncheckedIndex(i), data.vector90, sines.atUncheckedIndex(i));
383
436
  const arcFraction = data.sweep.radiansToSignedPeriodicFraction(radians.atUncheckedIndex(i));
384
437
  const lineFraction = Polynomials_1.SmallSystem.lineSegment3dXYClosestPointUnbounded(pointA0Local, pointA1Local, arcPoint);
438
+ // only add if the point is within the start and end fractions of both line segment and arc
385
439
  if (lineFraction !== undefined && this.acceptFraction(lineFraction) && this.acceptFraction(arcFraction)) {
386
440
  this.recordPointWithLocalFractions(lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed);
387
441
  }
388
442
  }
389
- // line parallel to arc tangent.
443
+ // 3) line parallel to arc tangent.
444
+ // If line does not intersect the arc, then the closest (and/or the furthest) point on arc to the line is a
445
+ // point where the tangent line on arc at that point is parallel to the line.
390
446
  const dotUT = data.vector0.crossProductStartEndXY(pointA0, pointA1);
391
447
  const dotVT = data.vector90.crossProductStartEndXY(pointA0, pointA1);
392
448
  const parallelRadians = Math.atan2(dotVT, dotUT);
@@ -394,6 +450,7 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
394
450
  const arcPoint = data.center.plus2Scaled(data.vector0, Math.cos(radians1), data.vector90, Math.sin(radians1));
395
451
  const arcFraction = data.sweep.radiansToSignedPeriodicFraction(radians1);
396
452
  const lineFraction = Polynomials_1.SmallSystem.lineSegment3dXYClosestPointUnbounded(pointA0Local, pointA1Local, arcPoint);
453
+ // only add if the point is within the start and end fractions of both line segment and arc
397
454
  if (lineFraction !== undefined && this.acceptFraction(lineFraction) && this.acceptFraction(arcFraction)) {
398
455
  this.recordPointWithLocalFractions(lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed);
399
456
  }
@@ -490,63 +547,26 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
490
547
  this.computeLineStringLineString(lsA, lsB, reversed);
491
548
  }
492
549
  /** Low level dispatch of segment with (beziers of) a bspline curve */
493
- dispatchSegmentBsplineCurve(lsA, curveB, reversed) {
550
+ dispatchSegmentBsplineCurve(segA, curveB, reversed) {
494
551
  const lsB = LineString3d_1.LineString3d.create();
495
552
  curveB.emitStrokes(lsB);
496
- this.computeSegmentLineString(lsA, lsB, reversed);
553
+ this.computeSegmentLineString(segA, lsB, reversed);
497
554
  }
498
555
  /** Detail computation for segment approaching linestring. */
499
- computeSegmentLineString(lsA, lsB, reversed) {
500
- const pointA0 = lsA.point0Ref;
501
- const pointA1 = lsA.point1Ref;
502
- let pointB0 = CurveCurveCloseApproachXY._workPointBB0;
503
- let pointB1 = CurveCurveCloseApproachXY._workPointBB1;
504
- let pointB2 = CurveCurveCloseApproachXY._workPointBB2;
505
- let cross0, cross1, cross2;
506
- let dot0, dot1, dot2;
507
- const vectorA = CurveCurveCloseApproachXY._workVectorA;
508
- Point3dVector3d_1.Vector3d.createStartEnd(pointA0, pointA1, vectorA);
509
- const aa = vectorA.magnitudeSquared();
556
+ computeSegmentLineString(segA, lsB, reversed) {
510
557
  const numB = lsB.numPoints();
511
- lsB.packedPoints.getPoint3dAtUncheckedPointIndex(0, pointB0);
512
- lsB.packedPoints.getPoint3dAtUncheckedPointIndex(1, pointB0);
513
- cross0 = vectorA.crossProductStartEndXY(pointA0, pointB0);
514
- cross1 = vectorA.crossProductStartEndXY(pointA0, pointB0);
515
- dot0 = vectorA.dotProductStartEndXY(pointA0, pointB0);
516
- dot1 = vectorA.dotProductStartEndXY(pointA0, pointB1);
517
- for (let iB = 2; iB < numB; iB++) {
518
- // project point B[iB] to segmentA. If within limits, see if it is a local minimum distance . . .
519
- lsB.packedPoints.getPoint3dAtUncheckedPointIndex(iB, pointB1);
520
- cross2 = vectorA.crossProductStartEndXY(pointA0, pointB0);
521
- dot2 = vectorA.dotProductStartEndXY(pointA0, pointB2);
522
- if ((cross0 - cross1) * (cross2 - cross1) <= 0.0) {
523
- // There is a true minimum at point1 ... see if it is within the line
524
- if (dot1 >= 0.0 && dot1 <= aa) {
525
- const fractionA1 = dot1 / aa;
526
- const projection = pointA0.interpolate(dot1 / aa, pointA1);
527
- if (pointB1.distanceXY(projection) < this._maxDistanceToAccept) {
528
- const detailA = CurveLocationDetail_1.CurveLocationDetail.createCurveFractionPoint(lsA, fractionA1, projection);
529
- const detailB = CurveLocationDetail_1.CurveLocationDetail.createCurveFractionPoint(lsB, iB / (numB - 1), pointB2);
530
- const pair = CurveLocationDetail_1.CurveLocationDetailPair.createCaptureOptionalReverse(detailA, detailB, reversed);
531
- this._results.push(pair);
532
- }
533
- }
534
- }
535
- const tempPoint = pointB0;
536
- pointB0 = pointB1;
537
- pointB1 = pointB2;
538
- pointB2 = tempPoint;
539
- const tempCross = cross0;
540
- cross0 = cross1;
541
- cross1 = cross2;
542
- cross2 = tempCross;
543
- const tempDot = dot0;
544
- dot0 = dot1;
545
- dot1 = dot2;
546
- dot2 = tempDot;
547
- }
548
- this.testAndRecordFractionalPairApproach(lsA, 0, 1, true, lsB, 0, 1, false, reversed);
549
- return undefined;
558
+ const deltaFracB = Geometry_1.Geometry.safeDivideFraction(1, numB - 1, 0);
559
+ const pointA0 = segA.point0Ref;
560
+ const pointA1 = segA.point1Ref;
561
+ const pointB0 = CurveCurveCloseApproachXY._workPointBB0;
562
+ const pointB1 = CurveCurveCloseApproachXY._workPointBB1;
563
+ for (let i = 0; i < numB - 1; ++i) {
564
+ const fB0 = i * deltaFracB; // global linestring fractions
565
+ const fB1 = (i + 1 === numB - 1) ? 1.0 : (i + 1) * deltaFracB; // make sure we nail the end fraction
566
+ lsB.packedPoints.getPoint3dAtUncheckedPointIndex(i, pointB0);
567
+ lsB.packedPoints.getPoint3dAtUncheckedPointIndex(i + 1, pointB1);
568
+ this.dispatchSegmentSegment(segA, pointA0, 0.0, pointA1, 1.0, lsB, pointB0, fB0, pointB1, fB1, reversed);
569
+ }
550
570
  }
551
571
  /** Detail computation for arc approaching linestring. */
552
572
  computeArcLineString(arcA, lsB, reversed) {
@@ -567,6 +587,17 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
567
587
  }
568
588
  return undefined;
569
589
  }
590
+ /** Low level dispatch of curve chain. */
591
+ dispatchCurveChain(geomA, geomAHandler) {
592
+ const geomB = this._geometryB; // save
593
+ if (!geomB || !(geomB instanceof CurveCollection_1.CurveChain))
594
+ return;
595
+ for (const child of geomB.children) {
596
+ this.resetGeometry(child);
597
+ geomAHandler(geomA);
598
+ }
599
+ this._geometryB = geomB; // restore
600
+ }
570
601
  /** Double dispatch handler for strongly typed segment. */
571
602
  handleLineSegment3d(segmentA) {
572
603
  if (this._geometryB instanceof LineSegment3d_1.LineSegment3d) {
@@ -582,6 +613,9 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
582
613
  else if (this._geometryB instanceof BSplineCurve_1.BSplineCurve3d) {
583
614
  this.dispatchSegmentBsplineCurve(segmentA, this._geometryB, false);
584
615
  }
616
+ else if (this._geometryB instanceof CurveCollection_1.CurveChain) {
617
+ this.dispatchCurveChain(segmentA, this.handleLineSegment3d.bind(this));
618
+ }
585
619
  }
586
620
  /**
587
621
  * Set bits for comparison to range xy
@@ -665,6 +699,9 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
665
699
  else if (this._geometryB instanceof BSplineCurve_1.BSplineCurve3d) {
666
700
  this.dispatchLineStringBSplineCurve(lsA, this._geometryB, false);
667
701
  }
702
+ else if (this._geometryB instanceof CurveCollection_1.CurveChain) {
703
+ this.dispatchCurveChain(lsA, this.handleLineString3d.bind(this));
704
+ }
668
705
  return undefined;
669
706
  }
670
707
  /** Double dispatch handler for strongly typed arc. */
@@ -681,6 +718,9 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
681
718
  else if (this._geometryB instanceof BSplineCurve_1.BSplineCurve3d) {
682
719
  this.dispatchArcBsplineCurve3d(arc0, this._geometryB, false);
683
720
  }
721
+ else if (this._geometryB instanceof CurveCollection_1.CurveChain) {
722
+ this.dispatchCurveChain(arc0, this.handleArc3d.bind(this));
723
+ }
684
724
  return undefined;
685
725
  }
686
726
  /** Double dispatch handler for strongly typed bspline curve. */
@@ -697,6 +737,9 @@ class CurveCurveCloseApproachXY extends GeometryHandler_1.NullGeometryHandler {
697
737
  else if (this._geometryB instanceof BSplineCurve_1.BSplineCurve3dBase) {
698
738
  this.dispatchBSplineCurve3dBSplineCurve3d(curve, this._geometryB, false);
699
739
  }
740
+ else if (this._geometryB instanceof CurveCollection_1.CurveChain) {
741
+ this.dispatchCurveChain(curve, this.handleBSplineCurve3d.bind(this));
742
+ }
700
743
  return undefined;
701
744
  }
702
745
  /** Double dispatch handler for strongly typed homogeneous bspline curve .. */
@@ -721,8 +764,6 @@ CurveCurveCloseApproachXY._workPointAA0 = Point3dVector3d_1.Point3d.create();
721
764
  CurveCurveCloseApproachXY._workPointAA1 = Point3dVector3d_1.Point3d.create();
722
765
  CurveCurveCloseApproachXY._workPointBB0 = Point3dVector3d_1.Point3d.create();
723
766
  CurveCurveCloseApproachXY._workPointBB1 = Point3dVector3d_1.Point3d.create();
724
- CurveCurveCloseApproachXY._workPointBB2 = Point3dVector3d_1.Point3d.create();
725
- CurveCurveCloseApproachXY._workVectorA = Point3dVector3d_1.Vector3d.create();
726
767
  CurveCurveCloseApproachXY._workPointB = Point3dVector3d_1.Point3d.create();
727
768
  exports.CurveCurveCloseApproachXY = CurveCurveCloseApproachXY;
728
769
  //# sourceMappingURL=CurveCurveCloseApproachXY.js.map