@itwin/core-geometry 5.2.0 → 5.3.0-dev.10

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 (90) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/lib/cjs/curve/Arc3d.d.ts.map +1 -1
  3. package/lib/cjs/curve/Arc3d.js +5 -7
  4. package/lib/cjs/curve/Arc3d.js.map +1 -1
  5. package/lib/cjs/curve/CurveOps.d.ts +2 -5
  6. package/lib/cjs/curve/CurveOps.d.ts.map +1 -1
  7. package/lib/cjs/curve/CurveOps.js +2 -5
  8. package/lib/cjs/curve/CurveOps.js.map +1 -1
  9. package/lib/cjs/curve/Query/PlanarSubdivision.d.ts +50 -15
  10. package/lib/cjs/curve/Query/PlanarSubdivision.d.ts.map +1 -1
  11. package/lib/cjs/curve/Query/PlanarSubdivision.js +102 -84
  12. package/lib/cjs/curve/Query/PlanarSubdivision.js.map +1 -1
  13. package/lib/cjs/curve/RegionOps.d.ts +44 -25
  14. package/lib/cjs/curve/RegionOps.d.ts.map +1 -1
  15. package/lib/cjs/curve/RegionOps.js +74 -39
  16. package/lib/cjs/curve/RegionOps.js.map +1 -1
  17. package/lib/cjs/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  18. package/lib/cjs/curve/RegionOpsClassificationSweeps.js +8 -8
  19. package/lib/cjs/curve/RegionOpsClassificationSweeps.js.map +1 -1
  20. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts +1 -0
  21. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  22. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js +102 -92
  23. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  24. package/lib/cjs/geometry3d/GrowableXYArray.d.ts +2 -1
  25. package/lib/cjs/geometry3d/GrowableXYArray.d.ts.map +1 -1
  26. package/lib/cjs/geometry3d/GrowableXYArray.js +2 -1
  27. package/lib/cjs/geometry3d/GrowableXYArray.js.map +1 -1
  28. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts +2 -1
  29. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  30. package/lib/cjs/geometry3d/GrowableXYZArray.js +2 -1
  31. package/lib/cjs/geometry3d/GrowableXYZArray.js.map +1 -1
  32. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts +9 -16
  33. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  34. package/lib/cjs/geometry3d/IndexedXYZCollection.js +3 -3
  35. package/lib/cjs/geometry3d/IndexedXYZCollection.js.map +1 -1
  36. package/lib/cjs/geometry3d/PolylineOps.d.ts +2 -2
  37. package/lib/cjs/geometry3d/PolylineOps.js +2 -2
  38. package/lib/cjs/geometry3d/PolylineOps.js.map +1 -1
  39. package/lib/cjs/numerics/ClusterableArray.d.ts.map +1 -1
  40. package/lib/cjs/numerics/ClusterableArray.js +2 -2
  41. package/lib/cjs/numerics/ClusterableArray.js.map +1 -1
  42. package/lib/cjs/topology/Merging.d.ts +15 -7
  43. package/lib/cjs/topology/Merging.d.ts.map +1 -1
  44. package/lib/cjs/topology/Merging.js +15 -10
  45. package/lib/cjs/topology/Merging.js.map +1 -1
  46. package/lib/esm/curve/Arc3d.d.ts.map +1 -1
  47. package/lib/esm/curve/Arc3d.js +5 -7
  48. package/lib/esm/curve/Arc3d.js.map +1 -1
  49. package/lib/esm/curve/CurveOps.d.ts +2 -5
  50. package/lib/esm/curve/CurveOps.d.ts.map +1 -1
  51. package/lib/esm/curve/CurveOps.js +2 -5
  52. package/lib/esm/curve/CurveOps.js.map +1 -1
  53. package/lib/esm/curve/Query/PlanarSubdivision.d.ts +50 -15
  54. package/lib/esm/curve/Query/PlanarSubdivision.d.ts.map +1 -1
  55. package/lib/esm/curve/Query/PlanarSubdivision.js +102 -84
  56. package/lib/esm/curve/Query/PlanarSubdivision.js.map +1 -1
  57. package/lib/esm/curve/RegionOps.d.ts +44 -25
  58. package/lib/esm/curve/RegionOps.d.ts.map +1 -1
  59. package/lib/esm/curve/RegionOps.js +72 -37
  60. package/lib/esm/curve/RegionOps.js.map +1 -1
  61. package/lib/esm/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  62. package/lib/esm/curve/RegionOpsClassificationSweeps.js +8 -8
  63. package/lib/esm/curve/RegionOpsClassificationSweeps.js.map +1 -1
  64. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts +1 -0
  65. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  66. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js +102 -92
  67. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  68. package/lib/esm/geometry3d/GrowableXYArray.d.ts +2 -1
  69. package/lib/esm/geometry3d/GrowableXYArray.d.ts.map +1 -1
  70. package/lib/esm/geometry3d/GrowableXYArray.js +2 -1
  71. package/lib/esm/geometry3d/GrowableXYArray.js.map +1 -1
  72. package/lib/esm/geometry3d/GrowableXYZArray.d.ts +2 -1
  73. package/lib/esm/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  74. package/lib/esm/geometry3d/GrowableXYZArray.js +2 -1
  75. package/lib/esm/geometry3d/GrowableXYZArray.js.map +1 -1
  76. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts +9 -16
  77. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  78. package/lib/esm/geometry3d/IndexedXYZCollection.js +3 -3
  79. package/lib/esm/geometry3d/IndexedXYZCollection.js.map +1 -1
  80. package/lib/esm/geometry3d/PolylineOps.d.ts +2 -2
  81. package/lib/esm/geometry3d/PolylineOps.js +2 -2
  82. package/lib/esm/geometry3d/PolylineOps.js.map +1 -1
  83. package/lib/esm/numerics/ClusterableArray.d.ts.map +1 -1
  84. package/lib/esm/numerics/ClusterableArray.js +2 -2
  85. package/lib/esm/numerics/ClusterableArray.js.map +1 -1
  86. package/lib/esm/topology/Merging.d.ts +15 -7
  87. package/lib/esm/topology/Merging.d.ts.map +1 -1
  88. package/lib/esm/topology/Merging.js +15 -10
  89. package/lib/esm/topology/Merging.js.map +1 -1
  90. package/package.json +3 -3
@@ -265,7 +265,9 @@ class CurveCurveIntersectXY extends GeometryHandler_1.RecurseToCurvesGeometryHan
265
265
  // The fraction and extend parameters allow all combinations to be passed in.
266
266
  dispatchSegmentArc(cpA, extendA0, pointA0, fractionA0, pointA1, fractionA1, extendA1, arc, extendB0, extendB1, reversed) {
267
267
  const tol2 = this._coincidentGeometryContext.tolerance * this._coincidentGeometryContext.tolerance;
268
- let dist2;
268
+ const cosines = new GrowableFloat64Array_1.GrowableFloat64Array(2);
269
+ const sines = new GrowableFloat64Array_1.GrowableFloat64Array(2);
270
+ const radians = new GrowableFloat64Array_1.GrowableFloat64Array(2);
269
271
  // Arc: X = C + cU + sV
270
272
  // Line: contains points A0,A1
271
273
  // Arc point colinear with line if det (A0, A1, X) = 0
@@ -285,27 +287,30 @@ class CurveCurveIntersectXY extends GeometryHandler_1.RecurseToCurvesGeometryHan
285
287
  const alpha = Geometry_1.Geometry.tripleProductPoint4dXYW(pointA0H, pointA1H, data.center);
286
288
  const beta = Geometry_1.Geometry.tripleProductPoint4dXYW(pointA0H, pointA1H, data.vector0);
287
289
  const gamma = Geometry_1.Geometry.tripleProductPoint4dXYW(pointA0H, pointA1H, data.vector90);
288
- const cosines = new GrowableFloat64Array_1.GrowableFloat64Array(2);
289
- const sines = new GrowableFloat64Array_1.GrowableFloat64Array(2);
290
- const radians = new GrowableFloat64Array_1.GrowableFloat64Array(2);
291
- const numRoots = Polynomials_1.AnalyticRoots.appendImplicitLineUnitCircleIntersections(alpha, beta, gamma, cosines, sines, radians);
292
- if (numRoots <= 0)
293
- return;
290
+ let numRoots = Polynomials_1.AnalyticRoots.appendImplicitLineUnitCircleIntersections(alpha, beta, gamma, cosines, sines, radians);
291
+ const closeApproach = (0 === numRoots);
292
+ if (closeApproach)
293
+ numRoots = 1; // we returned the arc's closest approach as the first "root"; if within tolerance and at endpoints, we record it
294
+ const acceptSolution = (iRoot, checkOnlyEndPointDistance = false) => {
295
+ const arcPoint = data.center.plus2Scaled(data.vector0, cosines.atUncheckedIndex(iRoot), data.vector90, sines.atUncheckedIndex(iRoot));
296
+ let fArc = data.sweep.radiansToSignedFraction(radians.atUncheckedIndex(iRoot), extendB0);
297
+ let fLine = SmallSystem_1.SmallSystem.lineSegment3dHXYClosestPointUnbounded(pointA0H, pointA1H, arcPoint);
298
+ if (fLine === undefined)
299
+ return undefined;
300
+ if (!checkOnlyEndPointDistance && this.acceptFraction(extendA0, fLine, extendA1) && this.acceptFraction(extendB0, fArc, extendB1))
301
+ return { fLine, fArc };
302
+ // check for an endpoint intersection that is beyond parametric tolerance but within point tolerance
303
+ fLine = fLine < 0.5 ? 0 : 1;
304
+ fArc = data.sweep.fractionToSignedPeriodicFraction(fArc) < 0.5 ? 0 : 1;
305
+ const pointAH = fLine ? pointA1H : pointA0H;
306
+ const pointBH = fArc ? pointB1H : pointB0H;
307
+ const dist2 = pointAH.realDistanceSquaredXY(pointBH);
308
+ return (dist2 !== undefined && Geometry_1.Geometry.isDistanceWithinTol(dist2, tol2)) ? { fLine, fArc } : undefined;
309
+ };
294
310
  for (let i = 0; i < numRoots; i++) {
295
- const arcPoint = data.center.plus2Scaled(data.vector0, cosines.atUncheckedIndex(i), data.vector90, sines.atUncheckedIndex(i));
296
- let arcFraction = data.sweep.radiansToSignedFraction(radians.atUncheckedIndex(i), extendB0);
297
- const lineFraction = SmallSystem_1.SmallSystem.lineSegment3dHXYClosestPointUnbounded(pointA0H, pointA1H, arcPoint);
298
- if (lineFraction !== undefined) {
299
- if (this.acceptFraction(extendA0, lineFraction, extendA1) && this.acceptFraction(extendB0, arcFraction, extendB1)) {
300
- this.recordPointWithLocalFractions(lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed);
301
- }
302
- else { // check for endpoint intersections beyond parametric tolerance but within point tolerance
303
- const pointAH = lineFraction < 0.5 ? pointA0H : pointA1H;
304
- const pointBH = (arcFraction = data.sweep.fractionToSignedPeriodicFraction(arcFraction)) < 0.5 ? pointB0H : pointB1H;
305
- if ((dist2 = pointAH.realDistanceSquaredXY(pointBH)) !== undefined && Geometry_1.Geometry.isDistanceWithinTol(dist2, tol2))
306
- this.recordPointWithLocalFractions(lineFraction < 0.5 ? 0 : 1, cpA, fractionA0, fractionA1, arcFraction < 0.5 ? 0 : 1, arc, 0, 1, reversed);
307
- }
308
- }
311
+ const result = acceptSolution(i, closeApproach);
312
+ if (result)
313
+ this.recordPointWithLocalFractions(result.fLine, cpA, fractionA0, fractionA1, result.fArc, arc, 0, 1, reversed);
309
314
  }
310
315
  }
311
316
  else {
@@ -323,27 +328,30 @@ class CurveCurveIntersectXY extends GeometryHandler_1.RecurseToCurvesGeometryHan
323
328
  const alpha = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.center, 1);
324
329
  const beta = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.vector0, 0);
325
330
  const gamma = Geometry_1.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.vector90, 0);
326
- const cosines = new GrowableFloat64Array_1.GrowableFloat64Array(2);
327
- const sines = new GrowableFloat64Array_1.GrowableFloat64Array(2);
328
- const radians = new GrowableFloat64Array_1.GrowableFloat64Array(2);
329
- const numRoots = Polynomials_1.AnalyticRoots.appendImplicitLineUnitCircleIntersections(alpha, beta, gamma, cosines, sines, radians);
330
- if (numRoots <= 0)
331
- return;
331
+ let numRoots = Polynomials_1.AnalyticRoots.appendImplicitLineUnitCircleIntersections(alpha, beta, gamma, cosines, sines, radians);
332
+ const closeApproach = (0 === numRoots);
333
+ if (closeApproach)
334
+ numRoots = 1; // we returned the arc's closest approach as the first "root"; if within tolerance and at endpoints, we record it
335
+ const acceptSolution = (iRoot, checkOnlyEndPointDistance = false) => {
336
+ const arcPoint = data.center.plus2Scaled(data.vector0, cosines.atUncheckedIndex(iRoot), data.vector90, sines.atUncheckedIndex(iRoot));
337
+ let fArc = data.sweep.radiansToSignedFraction(radians.atUncheckedIndex(iRoot), extendB0);
338
+ let fLine = SmallSystem_1.SmallSystem.lineSegment3dXYClosestPointUnbounded(pointA0Local, pointA1Local, arcPoint);
339
+ if (fLine === undefined)
340
+ return undefined;
341
+ if (!checkOnlyEndPointDistance && this.acceptFraction(extendA0, fLine, extendA1) && this.acceptFraction(extendB0, fArc, extendB1))
342
+ return { fLine, fArc };
343
+ // check for an endpoint intersection that is beyond parametric tolerance but within point tolerance
344
+ fLine = fLine < 0.5 ? 0 : 1;
345
+ fArc = data.sweep.fractionToSignedPeriodicFraction(fArc) < 0.5 ? 0 : 1;
346
+ const pointALocal = fLine ? pointA1Local : pointA0Local;
347
+ const pointBLocal = fArc ? pointB1Local : pointB0Local;
348
+ const dist2 = pointALocal.distanceSquaredXY(pointBLocal);
349
+ return Geometry_1.Geometry.isDistanceWithinTol(dist2, tol2) ? { fLine, fArc } : undefined;
350
+ };
332
351
  for (let i = 0; i < numRoots; i++) {
333
- const arcPoint = data.center.plus2Scaled(data.vector0, cosines.atUncheckedIndex(i), data.vector90, sines.atUncheckedIndex(i));
334
- let arcFraction = data.sweep.radiansToSignedFraction(radians.atUncheckedIndex(i), extendB0);
335
- const lineFraction = SmallSystem_1.SmallSystem.lineSegment3dXYClosestPointUnbounded(pointA0Local, pointA1Local, arcPoint);
336
- if (lineFraction !== undefined) {
337
- if (this.acceptFraction(extendA0, lineFraction, extendA1) && this.acceptFraction(extendB0, arcFraction, extendB1)) {
338
- this.recordPointWithLocalFractions(lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed);
339
- }
340
- else { // check for endpoint intersections beyond parametric tolerance but within point tolerance
341
- const pointALocal = lineFraction < 0.5 ? pointA0Local : pointA1Local;
342
- const pointBLocal = (arcFraction = data.sweep.fractionToSignedPeriodicFraction(arcFraction)) < 0.5 ? pointB0Local : pointB1Local;
343
- if ((dist2 = pointALocal.distanceSquaredXY(pointBLocal)) !== undefined && Geometry_1.Geometry.isDistanceWithinTol(dist2, tol2))
344
- this.recordPointWithLocalFractions(lineFraction < 0.5 ? 0 : 1, cpA, fractionA0, fractionA1, arcFraction < 0.5 ? 0 : 1, arc, 0, 1, reversed);
345
- }
346
- }
352
+ const result = acceptSolution(i, closeApproach);
353
+ if (result)
354
+ this.recordPointWithLocalFractions(result.fLine, cpA, fractionA0, fractionA1, result.fArc, arc, 0, 1, reversed);
347
355
  }
348
356
  }
349
357
  }
@@ -366,12 +374,23 @@ class CurveCurveIntersectXY extends GeometryHandler_1.RecurseToCurvesGeometryHan
366
374
  localB.coffs[0], localB.coffs[3], localB.coffs[6], // vector0 xyw
367
375
  localB.coffs[1], localB.coffs[4], localB.coffs[7], // vector90 xyw
368
376
  ellipseRadians, circleRadians);
377
+ const tol2 = this._coincidentGeometryContext.tolerance * this._coincidentGeometryContext.tolerance;
369
378
  // the intersections are transform-invariant, so the solution angles apply directly to the input arcs
370
379
  for (let i = 0; i < ellipseRadians.length; i++) {
371
- const fractionA = cpA.sweep.radiansToSignedFraction(circleRadians[i], extendA0);
372
- const fractionB = cpB.sweep.radiansToSignedFraction(ellipseRadians[i], extendB0);
373
- if (this.acceptFraction(extendA0, fractionA, extendA1) && this.acceptFraction(extendB0, fractionB, extendB1))
380
+ let fractionA = cpA.sweep.radiansToSignedFraction(circleRadians[i], extendA0);
381
+ let fractionB = cpB.sweep.radiansToSignedFraction(ellipseRadians[i], extendB0);
382
+ if (this.acceptFraction(extendA0, fractionA, extendA1) && this.acceptFraction(extendB0, fractionB, extendB1)) {
374
383
  this.recordPointWithLocalFractions(fractionA, cpA, 0, 1, fractionB, cpB, 0, 1, reversed);
384
+ }
385
+ else { // check for endpoint intersection beyond angular tolerance but within point tolerance
386
+ fractionA = cpA.sweep.fractionToSignedPeriodicFraction(fractionA) < 0.5 ? 0 : 1;
387
+ fractionB = cpB.sweep.fractionToSignedPeriodicFraction(fractionB) < 0.5 ? 0 : 1;
388
+ const endPointA = cpA.fractionToPoint(fractionA, CurveCurveIntersectXY._workPointAA0);
389
+ const endPointB = cpB.fractionToPoint(fractionB, CurveCurveIntersectXY._workPointBB0);
390
+ const dist2 = endPointA.distanceSquaredXY(endPointB);
391
+ if (Geometry_1.Geometry.isDistanceWithinTol(dist2, tol2))
392
+ this.recordPointWithLocalFractions(fractionA, cpA, 0, 1, fractionB, cpB, 0, 1, reversed);
393
+ }
375
394
  }
376
395
  }
377
396
  }
@@ -384,6 +403,15 @@ class CurveCurveIntersectXY extends GeometryHandler_1.RecurseToCurvesGeometryHan
384
403
  * 5- Convert intersection angles to fractions and record intersections.
385
404
  */
386
405
  dispatchArcArc(cpA, extendA0, extendA1, cpB, extendB0, extendB1, reversed) {
406
+ // overlap handling. perspective is not handled.
407
+ if (this._coincidentGeometryContext && !this._worldToLocalPerspective && !this._worldToLocalAffine) {
408
+ const pairs = this._coincidentGeometryContext.coincidentArcIntersectionXY(cpA, cpB, true);
409
+ if (pairs) {
410
+ this.recordPairs(cpA, cpB, pairs, reversed);
411
+ return;
412
+ }
413
+ }
414
+ // look for isolated intersections
387
415
  let matrixA;
388
416
  let matrixB;
389
417
  if (this._worldToLocalPerspective) {
@@ -400,27 +428,13 @@ class CurveCurveIntersectXY extends GeometryHandler_1.RecurseToCurvesGeometryHan
400
428
  }
401
429
  const conditionA = matrixA.conditionNumber();
402
430
  const conditionB = matrixB.conditionNumber();
403
- // pick the arc that is closest to circular.
431
+ // order the arcs so that the first one we pass in is closer to circular
404
432
  if (conditionA > conditionB)
405
433
  this.dispatchArcArcThisOrder(cpA, matrixA, extendA0, extendA1, cpB, matrixB, extendB0, extendB1, reversed);
406
434
  else
407
435
  this.dispatchArcArcThisOrder(cpB, matrixB, extendB0, extendB1, cpA, matrixA, extendA0, extendA1, !reversed);
408
- // overlap handling. perspective is not handled.
409
- if (!this._coincidentGeometryContext) {
410
- // do nothing
411
- }
412
- else if (this._worldToLocalPerspective) {
413
- // do nothing
414
- }
415
- else if (this._worldToLocalAffine) {
416
- // do nothing
417
- }
418
- else {
419
- const pairs = this._coincidentGeometryContext.coincidentArcIntersectionXY(cpA, cpB, true);
420
- if (pairs !== undefined)
421
- this.recordPairs(cpA, cpB, pairs, reversed);
422
- }
423
436
  }
437
+ /** Compute the intersection of an arc and a B-spline curve. */
424
438
  dispatchArcBsplineCurve3d(cpA, extendA0, extendA1, cpB, extendB0, extendB1, reversed) {
425
439
  // Arc: X = C + cU + sV
426
440
  // implicitize the arc as viewed. This "3d" matrix is homogeneous "XYW" not "xyz"
@@ -435,8 +449,6 @@ class CurveCurveIntersectXY extends GeometryHandler_1.RecurseToCurvesGeometryHan
435
449
  }
436
450
  // The worldToLocal has moved the arc vectors into local space.
437
451
  // matrixA captures the xyw parts (ignoring z)
438
- // for any point in world space,
439
- // THIS CODE ONLY WORKS FOR
440
452
  const matrixAInverse = matrixA.inverse();
441
453
  if (matrixAInverse) {
442
454
  const orderF = cpB.order; // order of the beziers for simple coordinates
@@ -455,36 +467,34 @@ class CurveCurveIntersectXY extends GeometryHandler_1.RecurseToCurvesGeometryHan
455
467
  const awy = matrixAInverse.at(2, 1);
456
468
  const awz = 0.0;
457
469
  const aww = matrixAInverse.at(2, 2);
458
- if (matrixAInverse) {
459
- let bezier;
460
- for (let spanIndex = 0;; spanIndex++) {
461
- bezier = cpB.getSaturatedBezierSpan3dH(spanIndex, bezier);
462
- if (!bezier)
463
- break;
464
- if (this._worldToLocalPerspective)
465
- bezier.tryMultiplyMatrix4dInPlace(this._worldToLocalPerspective);
466
- else if (this._worldToLocalAffine)
467
- bezier.tryTransformInPlace(this._worldToLocalAffine);
468
- univariateBezierG.zero();
469
- bezier.poleProductsXYZW(coffF, axx, axy, axz, axw);
470
- univariateBezierG.addSquaredSquaredBezier(coffF, 1.0);
471
- bezier.poleProductsXYZW(coffF, ayx, ayy, ayz, ayw);
472
- univariateBezierG.addSquaredSquaredBezier(coffF, 1.0);
473
- bezier.poleProductsXYZW(coffF, awx, awy, awz, aww);
474
- univariateBezierG.addSquaredSquaredBezier(coffF, -1.0);
475
- const roots = univariateBezierG.roots(0.0, true);
476
- if (roots) {
477
- for (const root of roots) {
478
- const fractionB = bezier.fractionToParentFraction(root);
479
- // The univariate bezier (which has been transformed by the view transform) evaluates into xyw space
480
- const bcurvePoint4d = bezier.fractionToPoint4d(root);
481
- const c = bcurvePoint4d.dotProductXYZW(axx, axy, axz, axw);
482
- const s = bcurvePoint4d.dotProductXYZW(ayx, ayy, ayz, ayw);
483
- const arcFraction = cpA.sweep.radiansToSignedFraction(Math.atan2(s, c), extendA0);
484
- if (this.acceptFraction(extendA0, arcFraction, extendA1) &&
485
- this.acceptFraction(extendB0, fractionB, extendB1)) {
486
- this.recordPointWithLocalFractions(arcFraction, cpA, 0, 1, fractionB, cpB, 0, 1, reversed);
487
- }
470
+ let bezier;
471
+ for (let spanIndex = 0;; spanIndex++) {
472
+ bezier = cpB.getSaturatedBezierSpan3dH(spanIndex, bezier);
473
+ if (!bezier)
474
+ break;
475
+ if (this._worldToLocalPerspective)
476
+ bezier.tryMultiplyMatrix4dInPlace(this._worldToLocalPerspective);
477
+ else if (this._worldToLocalAffine)
478
+ bezier.tryTransformInPlace(this._worldToLocalAffine);
479
+ univariateBezierG.zero();
480
+ bezier.poleProductsXYZW(coffF, axx, axy, axz, axw);
481
+ univariateBezierG.addSquaredSquaredBezier(coffF, 1.0);
482
+ bezier.poleProductsXYZW(coffF, ayx, ayy, ayz, ayw);
483
+ univariateBezierG.addSquaredSquaredBezier(coffF, 1.0);
484
+ bezier.poleProductsXYZW(coffF, awx, awy, awz, aww);
485
+ univariateBezierG.addSquaredSquaredBezier(coffF, -1.0);
486
+ const roots = univariateBezierG.roots(0.0, true);
487
+ if (roots) {
488
+ for (const root of roots) {
489
+ const fractionB = bezier.fractionToParentFraction(root);
490
+ // The univariate bezier (which has been transformed by the view transform) evaluates into xyw space
491
+ const bcurvePoint4d = bezier.fractionToPoint4d(root);
492
+ const c = bcurvePoint4d.dotProductXYZW(axx, axy, axz, axw);
493
+ const s = bcurvePoint4d.dotProductXYZW(ayx, ayy, ayz, ayw);
494
+ const arcFraction = cpA.sweep.radiansToSignedFraction(Math.atan2(s, c), extendA0);
495
+ if (this.acceptFraction(extendA0, arcFraction, extendA1) &&
496
+ this.acceptFraction(extendB0, fractionB, extendB1)) {
497
+ this.recordPointWithLocalFractions(arcFraction, cpA, 0, 1, fractionB, cpB, 0, 1, reversed);
488
498
  }
489
499
  }
490
500
  }