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