@itwin/core-geometry 4.10.0-dev.26 → 4.10.0-dev.28

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 (117) hide show
  1. package/lib/cjs/core-geometry.d.ts +1 -1
  2. package/lib/cjs/core-geometry.d.ts.map +1 -1
  3. package/lib/cjs/core-geometry.js +1 -1
  4. package/lib/cjs/core-geometry.js.map +1 -1
  5. package/lib/cjs/curve/Arc3d.d.ts.map +1 -1
  6. package/lib/cjs/curve/Arc3d.js +2 -1
  7. package/lib/cjs/curve/Arc3d.js.map +1 -1
  8. package/lib/cjs/curve/CurveFactory.d.ts +1 -1
  9. package/lib/cjs/curve/CurveFactory.d.ts.map +1 -1
  10. package/lib/cjs/curve/CurveFactory.js +3 -3
  11. package/lib/cjs/curve/CurveFactory.js.map +1 -1
  12. package/lib/cjs/curve/LineSegment3d.js +2 -2
  13. package/lib/cjs/curve/LineSegment3d.js.map +1 -1
  14. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.d.ts.map +1 -1
  15. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.js +3 -2
  16. package/lib/cjs/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -1
  17. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  18. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js +7 -6
  19. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  20. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXYZ.d.ts.map +1 -1
  21. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXYZ.js +3 -2
  22. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXYZ.js.map +1 -1
  23. package/lib/cjs/geometry3d/BilinearPatch.js +4 -4
  24. package/lib/cjs/geometry3d/BilinearPatch.js.map +1 -1
  25. package/lib/cjs/geometry3d/Matrix3d.d.ts +26 -16
  26. package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
  27. package/lib/cjs/geometry3d/Matrix3d.js +34 -16
  28. package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
  29. package/lib/cjs/geometry3d/Ray3d.js +2 -2
  30. package/lib/cjs/geometry3d/Ray3d.js.map +1 -1
  31. package/lib/cjs/geometry4d/Point4d.d.ts.map +1 -1
  32. package/lib/cjs/geometry4d/Point4d.js +2 -1
  33. package/lib/cjs/geometry4d/Point4d.js.map +1 -1
  34. package/lib/cjs/numerics/Newton.d.ts +3 -0
  35. package/lib/cjs/numerics/Newton.d.ts.map +1 -1
  36. package/lib/cjs/numerics/Newton.js +2 -5
  37. package/lib/cjs/numerics/Newton.js.map +1 -1
  38. package/lib/cjs/numerics/Polynomials.d.ts +22 -178
  39. package/lib/cjs/numerics/Polynomials.d.ts.map +1 -1
  40. package/lib/cjs/numerics/Polynomials.js +62 -360
  41. package/lib/cjs/numerics/Polynomials.js.map +1 -1
  42. package/lib/cjs/numerics/SmallSystem.d.ts +164 -0
  43. package/lib/cjs/numerics/SmallSystem.d.ts.map +1 -0
  44. package/lib/cjs/numerics/SmallSystem.js +321 -0
  45. package/lib/cjs/numerics/SmallSystem.js.map +1 -0
  46. package/lib/cjs/polyface/multiclip/OffsetMeshContext.d.ts +1 -1
  47. package/lib/cjs/polyface/multiclip/OffsetMeshContext.d.ts.map +1 -1
  48. package/lib/cjs/polyface/multiclip/OffsetMeshContext.js +7 -7
  49. package/lib/cjs/polyface/multiclip/OffsetMeshContext.js.map +1 -1
  50. package/lib/cjs/topology/Graph.d.ts.map +1 -1
  51. package/lib/cjs/topology/Graph.js +2 -2
  52. package/lib/cjs/topology/Graph.js.map +1 -1
  53. package/lib/cjs/topology/InsertAndRetriangulateContext.js +2 -2
  54. package/lib/cjs/topology/InsertAndRetriangulateContext.js.map +1 -1
  55. package/lib/cjs/topology/Merging.d.ts +1 -1
  56. package/lib/cjs/topology/Merging.d.ts.map +1 -1
  57. package/lib/cjs/topology/Merging.js +2 -2
  58. package/lib/cjs/topology/Merging.js.map +1 -1
  59. package/lib/esm/core-geometry.d.ts +1 -1
  60. package/lib/esm/core-geometry.d.ts.map +1 -1
  61. package/lib/esm/core-geometry.js +1 -1
  62. package/lib/esm/core-geometry.js.map +1 -1
  63. package/lib/esm/curve/Arc3d.d.ts.map +1 -1
  64. package/lib/esm/curve/Arc3d.js +2 -1
  65. package/lib/esm/curve/Arc3d.js.map +1 -1
  66. package/lib/esm/curve/CurveFactory.d.ts +1 -1
  67. package/lib/esm/curve/CurveFactory.d.ts.map +1 -1
  68. package/lib/esm/curve/CurveFactory.js +1 -1
  69. package/lib/esm/curve/CurveFactory.js.map +1 -1
  70. package/lib/esm/curve/LineSegment3d.js +1 -1
  71. package/lib/esm/curve/LineSegment3d.js.map +1 -1
  72. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.d.ts.map +1 -1
  73. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.js +2 -1
  74. package/lib/esm/curve/internalContexts/CurveCurveCloseApproachXY.js.map +1 -1
  75. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  76. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js +2 -1
  77. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  78. package/lib/esm/curve/internalContexts/CurveCurveIntersectXYZ.d.ts.map +1 -1
  79. package/lib/esm/curve/internalContexts/CurveCurveIntersectXYZ.js +2 -1
  80. package/lib/esm/curve/internalContexts/CurveCurveIntersectXYZ.js.map +1 -1
  81. package/lib/esm/geometry3d/BilinearPatch.js +1 -1
  82. package/lib/esm/geometry3d/BilinearPatch.js.map +1 -1
  83. package/lib/esm/geometry3d/Matrix3d.d.ts +26 -16
  84. package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
  85. package/lib/esm/geometry3d/Matrix3d.js +34 -16
  86. package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
  87. package/lib/esm/geometry3d/Ray3d.js +1 -1
  88. package/lib/esm/geometry3d/Ray3d.js.map +1 -1
  89. package/lib/esm/geometry4d/Point4d.d.ts.map +1 -1
  90. package/lib/esm/geometry4d/Point4d.js +2 -1
  91. package/lib/esm/geometry4d/Point4d.js.map +1 -1
  92. package/lib/esm/numerics/Newton.d.ts +3 -0
  93. package/lib/esm/numerics/Newton.d.ts.map +1 -1
  94. package/lib/esm/numerics/Newton.js +1 -4
  95. package/lib/esm/numerics/Newton.js.map +1 -1
  96. package/lib/esm/numerics/Polynomials.d.ts +22 -178
  97. package/lib/esm/numerics/Polynomials.d.ts.map +1 -1
  98. package/lib/esm/numerics/Polynomials.js +62 -359
  99. package/lib/esm/numerics/Polynomials.js.map +1 -1
  100. package/lib/esm/numerics/SmallSystem.d.ts +164 -0
  101. package/lib/esm/numerics/SmallSystem.d.ts.map +1 -0
  102. package/lib/esm/numerics/SmallSystem.js +317 -0
  103. package/lib/esm/numerics/SmallSystem.js.map +1 -0
  104. package/lib/esm/polyface/multiclip/OffsetMeshContext.d.ts +1 -1
  105. package/lib/esm/polyface/multiclip/OffsetMeshContext.d.ts.map +1 -1
  106. package/lib/esm/polyface/multiclip/OffsetMeshContext.js +4 -4
  107. package/lib/esm/polyface/multiclip/OffsetMeshContext.js.map +1 -1
  108. package/lib/esm/topology/Graph.d.ts.map +1 -1
  109. package/lib/esm/topology/Graph.js +1 -1
  110. package/lib/esm/topology/Graph.js.map +1 -1
  111. package/lib/esm/topology/InsertAndRetriangulateContext.js +1 -1
  112. package/lib/esm/topology/InsertAndRetriangulateContext.js.map +1 -1
  113. package/lib/esm/topology/Merging.d.ts +1 -1
  114. package/lib/esm/topology/Merging.d.ts.map +1 -1
  115. package/lib/esm/topology/Merging.js +1 -1
  116. package/lib/esm/topology/Merging.js.map +1 -1
  117. package/package.json +3 -3
@@ -5,17 +5,16 @@
5
5
  /** @packageDocumentation
6
6
  * @module Numerics
7
7
  */
8
+ import { assert } from "@itwin/core-bentley";
8
9
  import { Geometry } from "../Geometry";
9
10
  import { Angle } from "../geometry3d/Angle";
10
11
  import { AngleSweep } from "../geometry3d/AngleSweep";
11
12
  import { GrowableFloat64Array } from "../geometry3d/GrowableFloat64Array";
12
13
  import { LongitudeLatitudeNumber } from "../geometry3d/LongitudeLatitudeAltitude";
13
- import { Point2d, Vector2d } from "../geometry3d/Point2dVector2d";
14
+ import { Point2d } from "../geometry3d/Point2dVector2d";
14
15
  import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d";
15
16
  import { Range1d, Range3d } from "../geometry3d/Range";
16
- // cspell:word Cardano
17
- // cspell:word CCminusSS
18
- /* eslint-disable @typescript-eslint/naming-convention */
17
+ // cspell:words Cardano internaldocs
19
18
  /**
20
19
  * degree 2 (quadratic) polynomial in for y = c0 + c1*x + c2*x^2
21
20
  * @internal
@@ -676,8 +675,8 @@ export class AnalyticRoots {
676
675
  return;
677
676
  }
678
677
  else if (D > 0) {
679
- const sqrt_D = Math.sqrt(D);
680
- this.append2Solutions(sqrt_D - p, -sqrt_D - p, values);
678
+ const sqrtD = Math.sqrt(D);
679
+ this.append2Solutions(sqrtD - p, -sqrtD - p, values);
681
680
  return;
682
681
  }
683
682
  return;
@@ -743,7 +742,7 @@ export class AnalyticRoots {
743
742
  */
744
743
  /*
745
744
  private static _appendCubicRootsUnsorted(c: Float64Array | number[], results: GrowableFloat64Array) {
746
- let sq_A: number;
745
+ let AA: number;
747
746
  let p: number;
748
747
  let q: number;
749
748
 
@@ -764,9 +763,9 @@ export class AnalyticRoots {
764
763
  // f' = 3y^2 + p
765
764
  // local min/max at Y = +-sqrt (-p)
766
765
  // f(+Y) = -p sqrt(-p) + 3p sqrt (-p) + 2q = 2 p sqrt (-p) + 2q
767
- sq_A = A * A;
768
- p = (3.0 * B - sq_A) / 9.0;
769
- q = 1.0 / 2 * (2.0 / 27 * A * sq_A - 1.0 / 3 * A * B + C);
766
+ AA = A * A;
767
+ p = (3.0 * B - AA) / 9.0;
768
+ q = 1.0 / 2 * (2.0 / 27 * A * AA - 1.0 / 3 * A * B + C);
770
769
 
771
770
  // Use Cardano formula
772
771
  const cb_p: number = p * p * p;
@@ -804,9 +803,9 @@ export class AnalyticRoots {
804
803
 
805
804
  return;
806
805
  } else { // One real solution
807
- const sqrt_D = Math.sqrt(D);
808
- const u = this.cbrt(sqrt_D - q);
809
- const v = -(this.cbrt(sqrt_D + q));
806
+ const sqrtD = Math.sqrt(D);
807
+ const u = this.cbrt(sqrtD - q);
808
+ const v = -(this.cbrt(sqrtD + q));
810
809
  results.push(origin + u + v);
811
810
  this.improveRoots(c, 3, results, false);
812
811
  return;
@@ -847,10 +846,10 @@ export class AnalyticRoots {
847
846
  const D = c[0] * coffScale[0];
848
847
  const origin = -0.25 * A;
849
848
  // substitute x = y - A/4 to eliminate cubic term: y^4 + py^2 + qy + r = 0
850
- const sq_A = A * A;
851
- const p = -0.375 * sq_A + B;
852
- const q = 0.125 * sq_A * A - 0.5 * A * B + C;
853
- const r = -0.01171875 * sq_A * sq_A + 0.0625 * sq_A * B - 0.25 * A * C + D;
849
+ const AA = A * A;
850
+ const p = -0.375 * AA + B;
851
+ const q = 0.125 * AA * A - 0.5 * A * B + C;
852
+ const r = -0.01171875 * AA * AA + 0.0625 * AA * B - 0.25 * A * C + D;
854
853
  const cubicSolutions = new GrowableFloat64Array();
855
854
  if (this.isZero(r)) { // no absolute term: y(y^3 + py + q) = 0
856
855
  coffs[0] = q;
@@ -1029,17 +1028,16 @@ export class PowerPolynomial {
1029
1028
  */
1030
1029
  export class TrigPolynomial {
1031
1030
  /**
1032
- * Solve a polynomial created from trigonometric condition using Trig.S, Trig.C, Trig.W.
1033
- * * Polynomial is of degree 4:
1034
- * `p(t) = coff[0] + coff[1] * t + coff[2] * t^2 + coff[3] * t^3 + coff[4] * t^4`
1035
- * * Solution logic includes inferring angular roots corresponding zero leading coefficients
1036
- * (roots at infinity).
1037
- * @param coff coefficients.
1038
- * @param nominalDegree degree of the polynomial under most complex root case. If there are
1039
- * any zero coefficients up to this degree, a single root "at infinity" is recorded as its
1040
- * corresponding angular parameter at negative pi/2.
1041
- * @param referenceCoefficient a number which represents the size of coefficients at various
1042
- * stages of computation. A small fraction of this will be used as a zero tolerance
1031
+ * Find the roots of a univariate polynomial created from substituting the rational parameterization of the unit
1032
+ * circle into a trigonometric polynomial. Roots are returned as radian angles.
1033
+ * * Currently implemented for polynomials of degree <= 4.
1034
+ * * For example, the ellipse-ellipse intersection problem reduces to finding the roots of a quartic polynomial:
1035
+ * `p(t) = coff[0] + coff[1] t + coff[2] t^2 + coff[3] t^3 + coff[4] t^4`.
1036
+ * * Particular care is given to report a root at t = +/-infinity, which corresponds to the returned angle -pi/2.
1037
+ * @param coff coefficients in the power basis
1038
+ * @param nominalDegree degree of the polynomial under the most complex root case.
1039
+ * @param referenceCoefficient a number which represents the size of coefficients at various stages of computation.
1040
+ * A small fraction of this number will be used as a zero tolerance.
1043
1041
  * @param radians roots are placed here.
1044
1042
  * @return false if equation is all zeros. This usually means any angle is a solution.
1045
1043
  */
@@ -1079,34 +1077,35 @@ export class TrigPolynomial {
1079
1077
  }
1080
1078
  else {
1081
1079
  // TODO: WORK WITH BEZIER SOLVER
1080
+ assert(false, "Unimplemented degree in trig solver");
1082
1081
  }
1083
1082
  if (roots.length > 0) {
1084
- // Each solution t represents an angle with Math.Cos(theta) = C(t)/W(t) and sin(theta) = S(t)/W(t)
1085
- // Division by W has no effect on atan2 calculations, so we just compute S(t),C(t)
1083
+ // each solution t represents an angle with Math.Cos(theta) = C(t)/W(t) and sin(theta) = S(t)/W(t)
1084
+ // division by W has no effect on atan2 calculations, so we just compute S(t),C(t)
1086
1085
  for (let i = 0; i < roots.length; i++) {
1087
1086
  const ss = PowerPolynomial.evaluate(this.S, roots.atUncheckedIndex(i));
1088
1087
  const cc = PowerPolynomial.evaluate(this.C, roots.atUncheckedIndex(i));
1089
1088
  radians.push(Math.atan2(ss, cc));
1090
1089
  }
1091
- // each leading zero at the front of the coefficient array corresponds to a root at -PI/2.
1092
- // only make one entry because we don't report multiplicity.
1093
- if (degree < nominalDegree)
1094
- radians.push(-0.5 * Math.PI);
1095
1090
  }
1091
+ // If the tail of the coff array is zero, we solved a polynomial of lesser degree above, and
1092
+ // we report the skipped "root at infinity" as the corresponding angle -pi/2 (without multiplicity).
1093
+ // See core\geometry\internaldocs\unitCircleEllipseIntersection.md for details.
1094
+ if (degree < nominalDegree)
1095
+ radians.push(-0.5 * Math.PI);
1096
1096
  }
1097
1097
  return radians.length > 0;
1098
1098
  }
1099
1099
  /**
1100
- * Compute intersections of unit circle `x^2 + y^2 = 1` with general quadric
1101
- * `axx * x^2 + axy * x * y + ayy * y^2 + ax * x + ay * y + a = 0`
1102
- * Solutions are returned as angles. Sine and Cosine of the angles are the x, y results.
1100
+ * Compute intersections of the unit circle `x^2 + y^2 = 1` with the general quadric (conic)
1101
+ * `axx x^2 + axy xy + ayy y^2 + ax x + ay y + a = 0`.
1103
1102
  * @param axx coefficient of x^2
1104
1103
  * @param axy coefficient of xy
1105
1104
  * @param ayy coefficient of y^2
1106
1105
  * @param ax coefficient of x
1107
1106
  * @param ay coefficient of y
1108
1107
  * @param a constant coefficient
1109
- * @param radians solution angles
1108
+ * @param radians up to 4 solution angles t in the quadric parameterization: x = cos(t), y = sin(t)
1110
1109
  */
1111
1110
  static solveUnitCircleImplicitQuadricIntersection(axx, axy, ayy, ax, ay, a, radians) {
1112
1111
  const coffs = new Float64Array(5);
@@ -1161,9 +1160,9 @@ export class TrigPolynomial {
1161
1160
  const acs = 2.0 * (ux * vx + uy * vy);
1162
1161
  const ass = vx * vx + vy * vy;
1163
1162
  const ac = 2.0 * (ux * cx + uy * cy);
1164
- const asi = 2.0 * (vx * cx + vy * cy);
1163
+ const as = 2.0 * (vx * cx + vy * cy);
1165
1164
  const a = cx * cx + cy * cy - 1.0;
1166
- const status = this.solveUnitCircleImplicitQuadricIntersection(acc, acs, ass, ac, asi, a, ellipseRadians);
1165
+ const status = this.solveUnitCircleImplicitQuadricIntersection(acc, acs, ass, ac, as, a, ellipseRadians);
1167
1166
  for (const radians of ellipseRadians) {
1168
1167
  const cc = Math.cos(radians);
1169
1168
  const ss = Math.sin(radians);
@@ -1230,307 +1229,42 @@ TrigPolynomial.CC = Float64Array.from([1.0, -4.0, 4.0]);
1230
1229
  /** Standard Basis coefficients for W(t) * W(t). */
1231
1230
  TrigPolynomial.WW = Float64Array.from([1.0, -4.0, 8.0, -8.0, 4.0]);
1232
1231
  /** Standard Basis coefficients for C(t) * C(t) - S(t) * S(t). */
1233
- TrigPolynomial.CCminusSS = Float64Array.from([1.0, -4.0, 0.0, 8.0, -4.0]);
1232
+ TrigPolynomial.CCMinusSS = Float64Array.from([1.0, -4.0, 0.0, 8.0, -4.0]); // eslint-disable-line @typescript-eslint/naming-convention
1234
1233
  TrigPolynomial._coefficientRelTol = 1.0e-12;
1235
1234
  /**
1236
- * static methods for commonly appearing sets of equations in 2 or 3 variables
1237
- * @public
1235
+ * * bilinear expression
1236
+ * * `f(u,v) = a + b * u * c * v + d * u * v`
1237
+ * @internal
1238
1238
  */
1239
- export class SmallSystem {
1240
- /**
1241
- * Return true if lines (a0,a1) to (b0, b1) have a simple intersection.
1242
- * Return the fractional (not xy) coordinates in result.x, result.y
1243
- * @param a0 start point of line a
1244
- * @param a1 end point of line a
1245
- * @param b0 start point of line b
1246
- * @param b1 end point of line b
1247
- * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b.
1248
- */
1249
- static lineSegment2dXYTransverseIntersectionUnbounded(a0, a1, b0, b1, result) {
1250
- const ux = a1.x - a0.x;
1251
- const uy = a1.y - a0.y;
1252
- const vx = b1.x - b0.x;
1253
- const vy = b1.y - b0.y;
1254
- const cx = b0.x - a0.x;
1255
- const cy = b0.y - a0.y;
1256
- const uv = Geometry.crossProductXYXY(ux, uy, vx, vy);
1257
- const cv = Geometry.crossProductXYXY(cx, cy, vx, vy);
1258
- const cu = Geometry.crossProductXYXY(ux, uy, cx, cy);
1259
- const s = Geometry.conditionalDivideFraction(cv, uv);
1260
- const t = Geometry.conditionalDivideFraction(cu, uv);
1261
- if (s !== undefined && t !== undefined) {
1262
- result.set(s, -t);
1263
- return true;
1264
- }
1265
- result.set(0, 0);
1266
- return false;
1267
- }
1268
- /**
1269
- * * (ax0,ay0) to (ax0+ux,ay0+uy) are line A.
1270
- * * (bx0,by0) to (bx0+vx,by0+vy) are lineB.
1271
- * * Return true if the lines have a simple intersection.
1272
- * * Return the fractional (not xy) coordinates in result.x, result.y
1273
- * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b.
1274
- */
1275
- static lineSegmentXYUVTransverseIntersectionUnbounded(ax0, ay0, ux, uy, bx0, by0, vx, vy, result) {
1276
- const cx = bx0 - ax0;
1277
- const cy = by0 - ay0;
1278
- const uv = Geometry.crossProductXYXY(ux, uy, vx, vy);
1279
- const cv = Geometry.crossProductXYXY(cx, cy, vx, vy);
1280
- const cu = Geometry.crossProductXYXY(ux, uy, cx, cy);
1281
- const s = Geometry.conditionalDivideFraction(cv, uv);
1282
- const t = Geometry.conditionalDivideFraction(cu, uv);
1283
- if (s !== undefined && t !== undefined) {
1284
- result.set(s, -t);
1285
- return true;
1286
- }
1287
- result.set(0, 0);
1288
- return false;
1289
- }
1290
- /**
1291
- * Return true if lines (a0,a1) to (b0, b1) have a simple intersection using only xy parts
1292
- * Return the fractional (not xy) coordinates in result.x, result.y
1293
- * @param a0 start point of line a
1294
- * @param a1 end point of line a
1295
- * @param b0 start point of line b
1296
- * @param b1 end point of line b
1297
- * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b.
1298
- */
1299
- static lineSegment3dXYTransverseIntersectionUnbounded(a0, a1, b0, b1, result) {
1300
- const ux = a1.x - a0.x;
1301
- const uy = a1.y - a0.y;
1302
- const vx = b1.x - b0.x;
1303
- const vy = b1.y - b0.y;
1304
- const cx = b0.x - a0.x;
1305
- const cy = b0.y - a0.y;
1306
- const uv = Geometry.crossProductXYXY(ux, uy, vx, vy);
1307
- const cv = Geometry.crossProductXYXY(cx, cy, vx, vy);
1308
- const cu = Geometry.crossProductXYXY(ux, uy, cx, cy);
1309
- const s = Geometry.conditionalDivideFraction(cv, uv);
1310
- const t = Geometry.conditionalDivideFraction(cu, uv);
1311
- if (s !== undefined && t !== undefined) {
1312
- result.set(s, -t);
1313
- return true;
1314
- }
1315
- result.set(0, 0);
1316
- return false;
1317
- }
1318
- /**
1319
- * Return true if lines (a0,a1) to (b0, b1) have a simple intersection using only xy parts of WEIGHTED 4D Points
1320
- * Return the fractional (not xy) coordinates in result.x, result.y
1321
- * @param hA0 homogeneous start point of line a
1322
- * @param hA1 homogeneous end point of line a
1323
- * @param hB0 homogeneous start point of line b
1324
- * @param hB1 homogeneous end point of line b
1325
- * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b.
1326
- */
1327
- static lineSegment3dHXYTransverseIntersectionUnbounded(hA0, hA1, hB0, hB1, result) {
1328
- // Considering only x,y,w parts....
1329
- // Point Q along B is (in full homogeneous) `(1-lambda) B0 + lambda 1`
1330
- // PointQ is colinear with A0,A1 when the determinant det (A0,A1,Q) is zero. (Each column takes xyw parts)
1331
- const alpha0 = Geometry.tripleProduct(hA0.x, hA1.x, hB0.x, hA0.y, hA1.y, hB0.y, hA0.w, hA1.w, hB0.w);
1332
- const alpha1 = Geometry.tripleProduct(hA0.x, hA1.x, hB1.x, hA0.y, hA1.y, hB1.y, hA0.w, hA1.w, hB1.w);
1333
- const fractionB = Geometry.conditionalDivideFraction(-alpha0, alpha1 - alpha0);
1334
- if (fractionB !== undefined) {
1335
- const beta0 = Geometry.tripleProduct(hB0.x, hB1.x, hA0.x, hB0.y, hB1.y, hA0.y, hB0.w, hB1.w, hA0.w);
1336
- const beta1 = Geometry.tripleProduct(hB0.x, hB1.x, hA1.x, hB0.y, hB1.y, hA1.y, hB0.w, hB1.w, hA1.w);
1337
- const fractionA = Geometry.conditionalDivideFraction(-beta0, beta1 - beta0);
1338
- if (fractionA !== undefined)
1339
- return Vector2d.create(fractionA, fractionB, result);
1340
- }
1341
- return undefined;
1342
- }
1343
- /**
1344
- * Return the line fraction at which the (homogeneous) line is closest to a space point as viewed in xy only.
1345
- * @param hA0 homogeneous start point of line a
1346
- * @param hA1 homogeneous end point of line a
1347
- * @param spacePoint homogeneous point in space
1348
- */
1349
- static lineSegment3dHXYClosestPointUnbounded(hA0, hA1, spacePoint) {
1350
- // Considering only x,y,w parts....
1351
- // weighted difference of (A1 w0 - A0 w1) is (cartesian) tangent vector along the line as viewed.
1352
- // The perpendicular (pure vector) W = (-y,x) flip is the direction of projection
1353
- // Point Q along A is (in full homogeneous) `(1-lambda) A0 + lambda 1 A1`
1354
- // PointQ is colinear with spacePoint and and W when the xyw homogeneous determinant | Q W spacePoint | is zero.
1355
- const tx = hA1.x * hA0.w - hA0.x * hA1.w;
1356
- const ty = hA1.y * hA0.w - hA0.y * hA1.w;
1357
- const det0 = Geometry.tripleProduct(hA0.x, -ty, spacePoint.x, hA0.y, tx, spacePoint.y, hA0.w, 0, spacePoint.w);
1358
- const det1 = Geometry.tripleProduct(hA1.x, -ty, spacePoint.x, hA1.y, tx, spacePoint.y, hA1.w, 0, spacePoint.w);
1359
- return Geometry.conditionalDivideFraction(-det0, det1 - det0);
1360
- }
1361
- /**
1362
- * Return the line fraction at which the line is closest to a space point as viewed in xy only.
1363
- * @param pointA0 start point
1364
- * @param pointA1 end point
1365
- * @param spacePoint point in space
1366
- */
1367
- static lineSegment3dXYClosestPointUnbounded(pointA0, pointA1, spacePoint) {
1368
- // Considering only x,y parts....
1369
- const ux = pointA1.x - pointA0.x;
1370
- const uy = pointA1.y - pointA0.y;
1371
- const uu = ux * ux + uy * uy;
1372
- const vx = spacePoint.x - pointA0.x;
1373
- const vy = spacePoint.y - pointA0.y;
1374
- const uv = ux * vx + uy * vy;
1375
- return Geometry.conditionalDivideFraction(uv, uu);
1376
- }
1377
- /**
1378
- * Return the line fraction at which the line is closest to a space point
1379
- * @param pointA0 start point
1380
- * @param pointA1 end point
1381
- * @param spacePoint point in space
1382
- */
1383
- static lineSegment3dClosestPointUnbounded(pointA0, pointA1, spacePoint) {
1384
- const ux = pointA1.x - pointA0.x;
1385
- const uy = pointA1.y - pointA0.y;
1386
- const uz = pointA1.z - pointA0.z;
1387
- const uu = ux * ux + uy * uy + uz * uz;
1388
- const vx = spacePoint.x - pointA0.x;
1389
- const vy = spacePoint.y - pointA0.y;
1390
- const vz = spacePoint.z - pointA0.z;
1391
- const uv = ux * vx + uy * vy + uz * vz;
1392
- return Geometry.conditionalDivideFraction(uv, uu);
1393
- }
1394
- /**
1395
- * Return true if lines (a0,a1) to (b0, b1) have closest approach (go by each other) in 3d
1396
- * Return the fractional (not xy) coordinates in result.x, result.y
1397
- * @param a0 start point of line a
1398
- * @param a1 end point of line a
1399
- * @param b0 start point of line b
1400
- * @param b1 end point of line b
1401
- * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b.
1402
- */
1403
- static lineSegment3dClosestApproachUnbounded(a0, a1, b0, b1, result) {
1404
- return this.ray3dXYZUVWClosestApproachUnbounded(a0.x, a0.y, a0.z, a1.x - a0.x, a1.y - a0.y, a1.z - a0.z, b0.x, b0.y, b0.z, b1.x - b0.x, b1.y - b0.y, b1.z - b0.z, result);
1405
- }
1406
- /**
1407
- * Return true if the given rays have closest approach (go by each other) in 3d
1408
- * Return the fractional (not xy) coordinates as x and y parts of a Point2d.
1409
- * @param ax x-coordinate of the origin of the first ray
1410
- * @param ay y-coordinate of the origin of the first ray
1411
- * @param az z-coordinate of the origin of the first ray
1412
- * @param au x-coordinate of the direction vector of the first ray
1413
- * @param av y-coordinate of the direction vector of the first ray
1414
- * @param aw z-coordinate of the direction vector of the first ray
1415
- * @param bx x-coordinate of the origin of the second ray
1416
- * @param by y-coordinate of the origin of the second ray
1417
- * @param bz z-coordinate of the origin of the second ray
1418
- * @param bu x-coordinate of the direction vector of the second ray
1419
- * @param bv y-coordinate of the direction vector of the second ray
1420
- * @param bw z-coordinate of the direction vector of the second ray
1421
- * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b.
1422
- */
1423
- static ray3dXYZUVWClosestApproachUnbounded(ax, ay, az, au, av, aw, bx, by, bz, bu, bv, bw, result) {
1424
- const cx = bx - ax;
1425
- const cy = by - ay;
1426
- const cz = bz - az;
1427
- const uu = Geometry.hypotenuseSquaredXYZ(au, av, aw);
1428
- const vv = Geometry.hypotenuseSquaredXYZ(bu, bv, bw);
1429
- const uv = Geometry.dotProductXYZXYZ(au, av, aw, bu, bv, bw);
1430
- const cu = Geometry.dotProductXYZXYZ(cx, cy, cz, au, av, aw);
1431
- const cv = Geometry.dotProductXYZXYZ(cx, cy, cz, bu, bv, bw);
1432
- return SmallSystem.linearSystem2d(uu, -uv, uv, -vv, cu, cv, result);
1433
- }
1434
- /**
1435
- * Solve the pair of linear equations
1436
- * * `ux * x + vx * y = cx`
1437
- * * `uy * x + vy * y = cy`
1438
- * @param ux xx coefficient
1439
- * @param vx xy coefficient
1440
- * @param uy yx coefficient
1441
- * @param vy yy coefficient
1442
- * @param cx x right hand side
1443
- * @param cy y right hand side
1444
- * @param result (x,y) solution (MUST be preallocated by caller)
1445
- */
1446
- static linearSystem2d(ux, vx, // first row of matrix
1447
- uy, vy, // second row of matrix
1448
- cx, cy, // right side
1449
- result) {
1450
- const uv = Geometry.crossProductXYXY(ux, uy, vx, vy);
1451
- const cv = Geometry.crossProductXYXY(cx, cy, vx, vy);
1452
- const cu = Geometry.crossProductXYXY(ux, uy, cx, cy);
1453
- const s = Geometry.conditionalDivideFraction(cv, uv);
1454
- const t = Geometry.conditionalDivideFraction(cu, uv);
1455
- if (s !== undefined && t !== undefined) {
1456
- result.set(s, t);
1457
- return true;
1458
- }
1459
- result.set(0, 0);
1460
- return false;
1461
- }
1239
+ export class BilinearPolynomial {
1462
1240
  /**
1463
- * Solve a linear system:
1464
- * * x equation: `axx * u + axy * v + axz * w = cx`
1465
- * * y equation: `ayx * u + ayy * v + ayz * w = cy`
1466
- * * z equation: `azx * u + azy * v + azz * w = cz`
1467
- * @param axx row 0, column 0 coefficient
1468
- * @param axy row 0, column 1 coefficient
1469
- * @param axz row 0, column 1 coefficient
1470
- * @param ayx row 1, column 0 coefficient
1471
- * @param ayy row 1, column 1 coefficient
1472
- * @param ayz row 1, column 2 coefficient
1473
- * @param azx row 2, column 0 coefficient
1474
- * @param azy row 2, column 1 coefficient
1475
- * @param azz row 2, column 2 coefficient
1476
- * @param cx right hand side row 0 coefficient
1477
- * @param cy right hand side row 1 coefficient
1478
- * @param cz right hand side row 2 coefficient
1479
- * @param result optional result.
1480
- * @returns solution vector (u,v,w) or `undefined` if system is singular.
1241
+ *
1242
+ * @param a constant coefficient
1243
+ * @param b `u` coefficient
1244
+ * @param c `v` coefficient
1245
+ * @param d `u*v` coefficient
1481
1246
  */
1482
- static linearSystem3d(axx, axy, axz, // first row of matrix
1483
- ayx, ayy, ayz, // second row of matrix
1484
- azx, azy, azz, // second row of matrix
1485
- cx, cy, cz, // right side
1486
- result) {
1487
- // determinants of various combinations of columns ...
1488
- const detXYZ = Geometry.tripleProduct(axx, ayx, azx, axy, ayy, azy, axz, ayz, azz);
1489
- const detCYZ = Geometry.tripleProduct(cx, cy, cz, axy, ayy, azy, axz, ayz, azz);
1490
- const detXCZ = Geometry.tripleProduct(axx, ayx, azx, cx, cy, cz, axz, ayz, azz);
1491
- const detXYC = Geometry.tripleProduct(axx, ayx, azx, axy, ayy, azy, cx, cy, cz);
1492
- const s = Geometry.conditionalDivideFraction(detCYZ, detXYZ);
1493
- const t = Geometry.conditionalDivideFraction(detXCZ, detXYZ);
1494
- const u = Geometry.conditionalDivideFraction(detXYC, detXYZ);
1495
- if (s !== undefined && t !== undefined && u !== undefined) {
1496
- return Vector3d.create(s, t, u, result);
1497
- }
1498
- return undefined;
1247
+ constructor(a, b, c, d) {
1248
+ this.a = a;
1249
+ this.b = b;
1250
+ this.c = c;
1251
+ this.d = d;
1499
1252
  }
1500
1253
  /**
1501
- * Compute the intersection of three planes.
1502
- * @param xyzA point on the first plane
1503
- * @param normalA normal of the first plane
1504
- * @param xyzB point on the second plane
1505
- * @param normalB normal of the second plane
1506
- * @param xyzC point on the third plane
1507
- * @param normalC normal of the third plane
1508
- * @param result optional result
1509
- * @returns intersection point of the three planes (as a Vector3d), or undefined if at least two planes are parallel.
1254
+ * Evaluate the bilinear expression at u,v
1510
1255
  */
1511
- static intersect3Planes(xyzA, normalA, xyzB, normalB, xyzC, normalC, result) {
1512
- return this.linearSystem3d(normalA.x, normalA.y, normalA.z, normalB.x, normalB.y, normalB.z, normalC.x, normalC.y, normalC.z, Geometry.dotProductXYZXYZ(xyzA.x, xyzA.y, xyzA.z, normalA.x, normalA.y, normalA.z), Geometry.dotProductXYZXYZ(xyzB.x, xyzB.y, xyzB.z, normalB.x, normalB.y, normalB.z), Geometry.dotProductXYZXYZ(xyzC.x, xyzC.y, xyzC.z, normalC.x, normalC.y, normalC.z), result);
1256
+ evaluate(u, v) {
1257
+ return this.a + this.b * u + v * (this.c + this.d * u);
1513
1258
  }
1514
- /**
1515
- * * in rowB, replace `rowB[j] += a * rowB[pivot] * rowA[j] / rowA[pivot]` for `j>pivot`
1516
- * @param rowA row that does not change
1517
- * @param pivotIndex index of pivot (divisor) in rowA.
1518
- * @param rowB row where elimination occurs.
1259
+ /** Create a bilinear polynomial z=f(u,v) given z values at 00, 10, 01, 11.
1519
1260
  */
1520
- static eliminateFromPivot(rowA, pivotIndex, rowB, a) {
1521
- const n = rowA.length;
1522
- let q = Geometry.conditionalDivideFraction(rowB[pivotIndex], rowA[pivotIndex]);
1523
- if (q === undefined)
1524
- return false;
1525
- q *= a;
1526
- for (let j = pivotIndex + 1; j < n; j++)
1527
- rowB[j] += q * rowA[j];
1528
- return true;
1261
+ static createUnitSquareValues(f00, f10, f01, f11) {
1262
+ return new BilinearPolynomial(f00, f10, f10, f11 - f10 - f01);
1529
1263
  }
1530
1264
  /**
1531
1265
  * Solve a pair of bilinear equations
1532
1266
  * * First equation: `a0 + b0 * u + c0 * v + d0 * u * v = 0`
1533
- * * Second equation: `a0 + b0 * u + c0 * v + d0 * u * v = 0`
1267
+ * * Second equation: `a1 + b1 * u + c1 * v + d1 * u * v = 0`
1534
1268
  */
1535
1269
  static solveBilinearPair(a0, b0, c0, d0, a1, b1, c1, d1) {
1536
1270
  // constant linear, and quadratic coefficients for c0 + c1 * u + c2 * u*u = 0
@@ -1551,37 +1285,6 @@ export class SmallSystem {
1551
1285
  }
1552
1286
  return uv;
1553
1287
  }
1554
- }
1555
- /**
1556
- * * bilinear expression
1557
- * * `f(u,v) = a + b * u * c * v + d * u * v`
1558
- * @internal
1559
- */
1560
- export class BilinearPolynomial {
1561
- /**
1562
- *
1563
- * @param a constant coefficient
1564
- * @param b `u` coefficient
1565
- * @param c `v` coefficient
1566
- * @param d `u*v` coefficient
1567
- */
1568
- constructor(a, b, c, d) {
1569
- this.a = a;
1570
- this.b = b;
1571
- this.c = c;
1572
- this.d = d;
1573
- }
1574
- /**
1575
- * Evaluate the bilinear expression at u,v
1576
- */
1577
- evaluate(u, v) {
1578
- return this.a + this.b * u + v * (this.c + this.d * u);
1579
- }
1580
- /** Create a bilinear polynomial z=f(u,v) given z values at 00, 10, 01, 11.
1581
- */
1582
- static createUnitSquareValues(f00, f10, f01, f11) {
1583
- return new BilinearPolynomial(f00, f10, f10, f11 - f10 - f01);
1584
- }
1585
1288
  /**
1586
1289
  * Solve the simultaneous equations
1587
1290
  * * `p(u,v) = pValue`
@@ -1592,7 +1295,7 @@ export class BilinearPolynomial {
1592
1295
  * @param qValue
1593
1296
  */
1594
1297
  static solvePair(p, pValue, q, qValue) {
1595
- return SmallSystem.solveBilinearPair(p.a - pValue, p.b, p.c, p.d, q.a - qValue, q.b, q.c, q.d);
1298
+ return BilinearPolynomial.solveBilinearPair(p.a - pValue, p.b, p.c, p.d, q.a - qValue, q.b, q.c, q.d);
1596
1299
  }
1597
1300
  }
1598
1301
  /**