@itwin/ecschema-rpcinterface-tests 5.9.0-dev.7 → 5.9.0-dev.9

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.
@@ -35656,6 +35656,7 @@ __webpack_require__.r(__webpack_exports__);
35656
35656
  /* harmony export */ CloudSqliteError: () => (/* binding */ CloudSqliteError),
35657
35657
  /* harmony export */ EditTxnError: () => (/* binding */ EditTxnError),
35658
35658
  /* harmony export */ ITwinSettingsError: () => (/* binding */ ITwinSettingsError),
35659
+ /* harmony export */ ServerBasedLocksError: () => (/* binding */ ServerBasedLocksError),
35659
35660
  /* harmony export */ SqliteError: () => (/* binding */ SqliteError),
35660
35661
  /* harmony export */ ViewStoreError: () => (/* binding */ ViewStoreError),
35661
35662
  /* harmony export */ WorkspaceError: () => (/* binding */ WorkspaceError)
@@ -35778,6 +35779,24 @@ var EditTxnError;
35778
35779
  }
35779
35780
  EditTxnError.isError = isError;
35780
35781
  })(EditTxnError || (EditTxnError = {}));
35782
+ /** Errors originating from the server-based implementation of the [LockControl]($backend) interface.
35783
+ * @beta
35784
+ */
35785
+ var ServerBasedLocksError;
35786
+ (function (ServerBasedLocksError) {
35787
+ /** the ITwinError scope for `ServerBasedLocksError`s. */
35788
+ ServerBasedLocksError.scope = "itwin-ServerBasedLocks";
35789
+ /** Instantiate and throw a ServerBasedLocksError */
35790
+ function throwError(key, message) {
35791
+ _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.ITwinError.throwError({ iTwinErrorId: { scope: ServerBasedLocksError.scope, key }, message });
35792
+ }
35793
+ ServerBasedLocksError.throwError = throwError;
35794
+ /** Determine whether an error object is a ServerBasedLocksError */
35795
+ function isError(error, key) {
35796
+ return _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.ITwinError.isError(error, ServerBasedLocksError.scope, key);
35797
+ }
35798
+ ServerBasedLocksError.isError = isError;
35799
+ })(ServerBasedLocksError || (ServerBasedLocksError = {}));
35781
35800
 
35782
35801
 
35783
35802
  /***/ }),
@@ -45664,6 +45683,7 @@ __webpack_require__.r(__webpack_exports__);
45664
45683
  /* harmony export */ Run: () => (/* reexport safe */ _annotation_TextBlock__WEBPACK_IMPORTED_MODULE_3__.Run),
45665
45684
  /* harmony export */ SchemaState: () => (/* reexport safe */ _BriefcaseTypes__WEBPACK_IMPORTED_MODULE_13__.SchemaState),
45666
45685
  /* harmony export */ SectionType: () => (/* reexport safe */ _ElementProps__WEBPACK_IMPORTED_MODULE_32__.SectionType),
45686
+ /* harmony export */ ServerBasedLocksError: () => (/* reexport safe */ _ITwinCoreErrors__WEBPACK_IMPORTED_MODULE_73__.ServerBasedLocksError),
45667
45687
  /* harmony export */ ServerError: () => (/* reexport safe */ _IModelError__WEBPACK_IMPORTED_MODULE_71__.ServerError),
45668
45688
  /* harmony export */ ServerTimeoutError: () => (/* reexport safe */ _IModelError__WEBPACK_IMPORTED_MODULE_71__.ServerTimeoutError),
45669
45689
  /* harmony export */ SilhouetteEdgeArgs: () => (/* reexport safe */ _internal_cross_package__WEBPACK_IMPORTED_MODULE_164__.SilhouetteEdgeArgs),
@@ -83000,6 +83020,23 @@ class BriefcaseTxns extends BriefcaseNotificationHandler {
83000
83020
  async reverseSingleTxn() {
83001
83021
  return this.reverseTxns(1);
83002
83022
  }
83023
+ /** Reverse (undo) the most recent operation to this briefcase in the current session. By default, this method also
83024
+ * abandons the locks that were acquired for that operation.
83025
+ * @beta
83026
+ * @note This method will also abandon locks associated with any later, reversed Txns, if they have not
83027
+ * already been abandoned. For example, if a call to [[reverseTxns]] reverses Txn 2 without abandoning
83028
+ * its locks, and then this method is called to reverse Txn 1, it will abandon the locks associated
83029
+ * with _both_ Txn 1 and Txn 2.
83030
+ * @note If there are any outstanding uncommitted changes, they are reversed.
83031
+ * @note The term "operation" is used rather than Txn, since multiple Txns can be grouped together via [TxnManager.beginMultiTxnOperation]($backend). So,
83032
+ * even though this method reverses only one operation, multiple Txns may be reversed if they were grouped together when they were made.
83033
+ * @note If there are no reversible operations, this method does nothing and returns Success.
83034
+ * @param args Optional arguments to control the behavior of the reverse operation, such as whether to retain locks.
83035
+ * @returns A Promise that resolves to success if the transactions were reversed, or rejects with an IModelError otherwise.
83036
+ */
83037
+ async reverseSingleTxnAsync(args) {
83038
+ await this.reverseTxnsAsync(1, args);
83039
+ }
83003
83040
  /** Reverse (undo) the most recent operation(s) to the briefcase in the current session.
83004
83041
  * @param numOperations the number of operations to reverse. If this is greater than 1, the entire set of operations will
83005
83042
  * be reinstated together when/if [[reinstateTxn]] is called.
@@ -83011,6 +83048,26 @@ class BriefcaseTxns extends BriefcaseNotificationHandler {
83011
83048
  async reverseTxns(numOperations) {
83012
83049
  return _IpcApp__WEBPACK_IMPORTED_MODULE_3__.IpcApp.appFunctionIpc.reverseTxns(this._iModel.key, numOperations);
83013
83050
  }
83051
+ /** Reverse (undo) the most recent operation(s) to the briefcase in the current session. By default, this method also
83052
+ * abandons the locks that were acquired for those operations.
83053
+ * @beta
83054
+ * @note This method will also abandon locks associated with any later, reversed Txns, if they have not
83055
+ * already been abandoned. For example, if a call to [[reverseTxns]] reverses Txn 2 without abandoning
83056
+ * its locks, and then this method is called to reverse Txn 1, it will abandon the locks associated
83057
+ * with _both_ Txn 1 and Txn 2.
83058
+ * @note If you do not want to abandon any locks, set [ReverseTxnArgs.retainLocks]($common) to true.
83059
+ * @note If there are any outstanding uncommitted changes, they are reversed.
83060
+ * @note The term "operation" is used rather than Txn, since multiple Txns can be grouped together via [[beginMultiTxnOperation]]. So,
83061
+ * even if numOperations is 1, multiple Txns may be reversed if they were grouped together when they were made.
83062
+ * @note If numOperations is too large only the operations are reversible are reversed.
83063
+ * @param numOperations the number of operations to reverse. If this is greater than 1, the entire set of operations will
83064
+ * be reinstated together when/if ReinstateTxn is called.
83065
+ * @param args Optional arguments to control the behavior of the reverse operation, such as whether to retain locks.
83066
+ * @returns A Promise that resolves to success if the transactions were reversed, or rejects with an IModelError otherwise.
83067
+ */
83068
+ async reverseTxnsAsync(numOperations, args) {
83069
+ return _IpcApp__WEBPACK_IMPORTED_MODULE_3__.IpcApp.appFunctionIpc.reverseTxnsAsync(this._iModel.key, numOperations, args);
83070
+ }
83014
83071
  /** Reverse (undo) all changes back to the beginning of the session.
83015
83072
  * @see [[reinstateTxn]] to redo changes.
83016
83073
  * @see [[reverseSingleTxn]] to undo only the most recent operation.
@@ -83019,6 +83076,21 @@ class BriefcaseTxns extends BriefcaseNotificationHandler {
83019
83076
  async reverseAll() {
83020
83077
  return _IpcApp__WEBPACK_IMPORTED_MODULE_3__.IpcApp.appFunctionIpc.reverseAllTxn(this._iModel.key);
83021
83078
  }
83079
+ /** Reverse (undo) all operations back to the beginning of the session. By default, this method also
83080
+ * abandons the locks that were acquired for those operations.
83081
+ * @beta
83082
+ * @note This method will also abandon locks associated with any later, reversed Txns, if they have not
83083
+ * already been abandoned. For example, if a call to [[reverseTxns]] reverses Txn 2 without abandoning
83084
+ * its locks, and then this method is called to reverse Txn 1, it will abandon the locks associated
83085
+ * with _both_ Txn 1 and Txn 2.
83086
+ * @note If there are any outstanding uncommitted changes, they are reversed.
83087
+ * @note If there are no reversible operations, this method does nothing and returns Success.
83088
+ * @param args Optional arguments to control the behavior of the reverse operation, such as whether to retain locks.
83089
+ * @returns A Promise that resolves to success if the transactions were reversed, or rejects with an IModelError otherwise.
83090
+ */
83091
+ async reverseAllTxnsAsync(args) {
83092
+ return _IpcApp__WEBPACK_IMPORTED_MODULE_3__.IpcApp.appFunctionIpc.reverseAllTxnsAsync(this._iModel.key, args);
83093
+ }
83022
83094
  /** Reinstate (redo) the most recently reversed transaction. Since at any time multiple transactions can be reversed, it
83023
83095
  * may take multiple calls to this method to reinstate all reversed operations.
83024
83096
  * @returns Success if a reversed transaction was reinstated, error status otherwise.
@@ -83029,6 +83101,19 @@ class BriefcaseTxns extends BriefcaseNotificationHandler {
83029
83101
  async reinstateTxn() {
83030
83102
  return _IpcApp__WEBPACK_IMPORTED_MODULE_3__.IpcApp.appFunctionIpc.reinstateTxn(this._iModel.key);
83031
83103
  }
83104
+ /** Reinstate (redo) the most recently reversed transaction. Since at any time multiple transactions can be reversed, it
83105
+ * may take multiple calls to this method to reinstate all reversed operations. This method also
83106
+ * re-acquires the locks that were abandoned when those operations were reversed.
83107
+ * @beta
83108
+ * @param args Optional arguments to control the behavior of the reinstate operation.
83109
+ * @returns Success if a reversed transaction was reinstated, error status otherwise.
83110
+ * @note If there are any outstanding uncommitted changes, they are canceled before the Txn is reinstated.
83111
+ * @see [[isRedoPossible]] to determine if any reinstatable operations exist.
83112
+ * @see [[reverseSingleTxn]] or [[reverseAll]] to undo changes.
83113
+ */
83114
+ async reinstateTxnAsync(args) {
83115
+ return _IpcApp__WEBPACK_IMPORTED_MODULE_3__.IpcApp.appFunctionIpc.reinstateTxnAsync(this._iModel.key, args);
83116
+ }
83032
83117
  /** Restart the current TxnManager session. This causes all Txns in the current session to no longer be undoable (as if the file was closed
83033
83118
  * and reopened.)
83034
83119
  * @note This can be quite disconcerting to the user expecting to be able to undo previously made changes. It should only be used
@@ -184054,7 +184139,7 @@ class ToolAdmin {
184054
184139
  const imodel = _IModelApp__WEBPACK_IMPORTED_MODULE_5__.IModelApp.viewManager.selectedView?.view.iModel;
184055
184140
  if (undefined === imodel || imodel.isReadonly || !imodel.isBriefcaseConnection())
184056
184141
  return false;
184057
- return (_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.Success === await imodel.txns.reverseSingleTxn() ? true : false);
184142
+ return imodel.txns.reverseSingleTxnAsync().then(() => true).catch(() => false);
184058
184143
  }
184059
184144
  /** Called to redo previous data button for primitive tools or undo last write operation. */
184060
184145
  async doRedoOperation() {
@@ -184067,7 +184152,7 @@ class ToolAdmin {
184067
184152
  const imodel = _IModelApp__WEBPACK_IMPORTED_MODULE_5__.IModelApp.viewManager.selectedView?.view.iModel;
184068
184153
  if (undefined === imodel || imodel.isReadonly || !imodel.isBriefcaseConnection())
184069
184154
  return false;
184070
- return (_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.Success === await imodel.txns.reinstateTxn() ? true : false);
184155
+ return imodel.txns.reinstateTxnAsync().then(() => true).catch(() => false);
184071
184156
  }
184072
184157
  onActiveToolChanged(tool, start) {
184073
184158
  this.clearMotionPromises();
@@ -189026,18 +189111,18 @@ __webpack_require__.r(__webpack_exports__);
189026
189111
  */
189027
189112
  var AxisOrder;
189028
189113
  (function (AxisOrder) {
189029
- /** Right handed system, X then Y then Z */
189114
+ /** Right-handed system, X then Y then Z. */
189030
189115
  // eslint-disable-next-line @typescript-eslint/no-shadow
189031
189116
  AxisOrder[AxisOrder["XYZ"] = 0] = "XYZ";
189032
- /** Right handed system, Y then Z then X */
189117
+ /** Right-handed system, Y then Z then X. */
189033
189118
  AxisOrder[AxisOrder["YZX"] = 1] = "YZX";
189034
- /** Right handed system, Z then X then Y */
189119
+ /** Right-handed system, Z then X then Y. */
189035
189120
  AxisOrder[AxisOrder["ZXY"] = 2] = "ZXY";
189036
- /** Left handed system, X then Z then Y */
189121
+ /** Left-handed system, X then Z then Y. For a right-handed alternative, swap the first two axes and use `AxisOrder.ZXY`. */
189037
189122
  AxisOrder[AxisOrder["XZY"] = 4] = "XZY";
189038
- /** Left handed system, Y then X then Z */
189123
+ /** Left-handed system, Y then X then Z. For a right-handed alternative, swap the first two axes and use `AxisOrder.XYZ`.*/
189039
189124
  AxisOrder[AxisOrder["YXZ"] = 5] = "YXZ";
189040
- /** Left handed system, Z then Y then X */
189125
+ /** Left-handed system, Z then Y then X. For a right-handed alternative, swap the first two axes and use `AxisOrder.YZX`.*/
189041
189126
  AxisOrder[AxisOrder["ZYX"] = 6] = "ZYX";
189042
189127
  })(AxisOrder || (AxisOrder = {}));
189043
189128
  /**
@@ -189137,6 +189222,8 @@ class Geometry {
189137
189222
  static smallAngleSeconds = 2e-7;
189138
189223
  /** Numeric value that may be considered zero for fractions between 0 and 1. */
189139
189224
  static smallFraction = 1.0e-10;
189225
+ /** Relative fraction tolerance for Newton iterations. */
189226
+ static smallNewtonStep = 1.0e-11;
189140
189227
  /** Tight tolerance near machine precision (unitless). Useful for snapping values, e.g., to 0 or 1. */
189141
189228
  static smallFloatingPoint = 1.0e-15;
189142
189229
  /** Radians value for full circle 2PI radians minus [[smallAngleRadians]]. */
@@ -201815,6 +201902,7 @@ __webpack_require__.r(__webpack_exports__);
201815
201902
  /* harmony export */ TriangularFacetLocationDetail: () => (/* reexport safe */ _polyface_FacetLocationDetail__WEBPACK_IMPORTED_MODULE_115__.TriangularFacetLocationDetail),
201816
201903
  /* harmony export */ UVSelect: () => (/* reexport safe */ _bspline_BSplineSurface__WEBPACK_IMPORTED_MODULE_108__.UVSelect),
201817
201904
  /* harmony export */ UVSurfaceOps: () => (/* reexport safe */ _geometry3d_UVSurfaceOps__WEBPACK_IMPORTED_MODULE_34__.UVSurfaceOps),
201905
+ /* harmony export */ UniformStrokeCollector: () => (/* reexport safe */ _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_8__.UniformStrokeCollector),
201818
201906
  /* harmony export */ UnionOfConvexClipPlaneSets: () => (/* reexport safe */ _clipping_UnionOfConvexClipPlaneSets__WEBPACK_IMPORTED_MODULE_42__.UnionOfConvexClipPlaneSets),
201819
201907
  /* harmony export */ UnionRegion: () => (/* reexport safe */ _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_88__.UnionRegion),
201820
201908
  /* harmony export */ UnivariateBezier: () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_52__.UnivariateBezier),
@@ -202908,6 +202996,17 @@ class Arc3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePrimitive
202908
202996
  startPoint(result) {
202909
202997
  return this.fractionToPoint(0.0, result);
202910
202998
  }
202999
+ /**
203000
+ * Whether the start and end points are defined and within tolerance.
203001
+ * * Does not check for degeneracy.
203002
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
203003
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
203004
+ */
203005
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallMetricDistance, xyOnly = false) {
203006
+ if (this.sweep.isFullCircle)
203007
+ return true;
203008
+ return super.isPhysicallyClosedCurve(tolerance, xyOnly);
203009
+ }
202911
203010
  /**
202912
203011
  * Return the end point of the arc.
202913
203012
  * @param result optional preallocated result.
@@ -205103,32 +205202,42 @@ class CurveChainWithDistanceIndex extends _curve_CurvePrimitive__WEBPACK_IMPORTE
205103
205202
  }
205104
205203
  return undefined;
205105
205204
  }
205205
+ /**
205206
+ * Given a parent chain, convert the corresponding child detail in the specified pair.
205207
+ * * Converted details refer to the chain's global parameterization instead of the child's.
205208
+ * * It is assumed that `pair.detailA.curve` is a child of chainA (similarly for chainB).
205209
+ * @param pair detail pair to convert in place
205210
+ * @param chainA convert pair.detailA to the global parameterization of chainA
205211
+ * @param chainB convert pair.detailB to the global parameterization of chainB
205212
+ * @return the converted pair
205213
+ */
205214
+ static convertChildDetailToChainDetailSingle(pair, chainA, chainB) {
205215
+ if (chainA) {
205216
+ const chainDetail = chainA.computeChainDetail(pair.detailA);
205217
+ if (chainDetail)
205218
+ pair.detailA = chainDetail;
205219
+ }
205220
+ if (chainB) {
205221
+ const chainDetail = chainB.computeChainDetail(pair.detailB);
205222
+ if (chainDetail)
205223
+ pair.detailB = chainDetail;
205224
+ }
205225
+ return pair;
205226
+ }
205106
205227
  /**
205107
205228
  * Given a parent chain, convert the corresponding child details in the specified pairs.
205108
205229
  * * Converted details refer to the chain's global parameterization instead of the child's.
205109
205230
  * * It is assumed that for all i >= index0, `pairs[i].detailA.curve` is a child of chainA (similarly for chainB).
205110
- * @param pairs array to mutate
205231
+ * @param pairs array of pairs to convert in place
205111
205232
  * @param index0 convert details of pairs in the tail of the array, starting at index0
205112
205233
  * @param chainA convert each specified detailA to the global parameterization of chainA
205113
205234
  * @param chainB convert each specified detailB to the global parameterization of chainB
205114
205235
  * @param compressAdjacent whether to remove adjacent duplicate pairs after conversion
205115
205236
  * @return the converted array
205116
- * @internal
205117
205237
  */
205118
205238
  static convertChildDetailToChainDetail(pairs, index0, chainA, chainB, compressAdjacent) {
205119
- for (let i = index0; i < pairs.length; ++i) {
205120
- const childDetailPair = pairs[i];
205121
- if (chainA) {
205122
- const chainDetail = chainA.computeChainDetail(childDetailPair.detailA);
205123
- if (chainDetail)
205124
- childDetailPair.detailA = chainDetail;
205125
- }
205126
- if (chainB) {
205127
- const chainDetail = chainB.computeChainDetail(childDetailPair.detailB);
205128
- if (chainDetail)
205129
- childDetailPair.detailB = chainDetail;
205130
- }
205131
- }
205239
+ for (let i = index0; i < pairs.length; ++i)
205240
+ pairs[i] = this.convertChildDetailToChainDetailSingle(pairs[i], chainA, chainB);
205132
205241
  if (compressAdjacent)
205133
205242
  pairs = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.removeAdjacentDuplicates(pairs, index0);
205134
205243
  return pairs;
@@ -205397,25 +205506,34 @@ class CurveCollection extends _GeometryQuery__WEBPACK_IMPORTED_MODULE_1__.Geomet
205397
205506
  return this.isAnyRegionType;
205398
205507
  }
205399
205508
  /**
205400
- * Return true for a `Path`, i.e. a chain of curves joined head-to-tail
205401
- * @see isPath
205509
+ * Return true for a `Path`, i.e. a chain of curves joined head-to-tail.
205510
+ * * This is NOT a test for (lack of) physical closure.
205511
+ * @see [[isPath]], [[CurveChain.isPhysicallyClosedCurve]]
205402
205512
  */
205403
205513
  get isOpenPath() {
205404
205514
  return this.dgnBoundaryType() === 1;
205405
205515
  }
205406
- /** Type guard for Path */
205516
+ /**
205517
+ * Type guard for Path.
205518
+ * * This is NOT a test for (lack of) physical closure.
205519
+ * @see [[CurveChain.isPhysicallyClosedCurve]]
205520
+ */
205407
205521
  isPath() {
205408
205522
  return this.isOpenPath;
205409
205523
  }
205410
205524
  /**
205411
205525
  * Return true for a single-loop planar region type, i.e. `Loop`.
205412
- * * This is NOT a test for physical closure of a `Path`.
205413
- * @see isLoop
205526
+ * * This is NOT a test for physical closure.
205527
+ * @see [[isLoop]], [[CurveChain.isPhysicallyClosedCurve]]
205414
205528
  */
205415
205529
  get isClosedPath() {
205416
205530
  return this.dgnBoundaryType() === 2;
205417
205531
  }
205418
- /** Type guard for Loop */
205532
+ /**
205533
+ * Type guard for Loop.
205534
+ * * This is NOT a test for physical closure.
205535
+ * @see [[CurveChain.isPhysicallyClosedCurve]]
205536
+ */
205419
205537
  isLoop() {
205420
205538
  return this.isClosedPath;
205421
205539
  }
@@ -205835,7 +205953,7 @@ class CurveCurve {
205835
205953
  * * If more than one approach is returned, one of them is the closest approach.
205836
205954
  * * If an input curve is a `CurveCollection`, then close approaches are computed to each `CurvePrimitive` child.
205837
205955
  * This can lead to many returned pairs, especially when both inputs are `CurveCollection`s. If an input curve is
205838
- * an `AnyRegion` then close approaches are computed only to the boundary curves, not to the interior.
205956
+ * an `AnyRegion`, then close approaches are computed only to the defining curves, not to the area they enclose.
205839
205957
  * @param curveA first curve
205840
205958
  * @param curveB second curve
205841
205959
  * @param maxDistance maximum xy-distance to consider between the curves.
@@ -205868,6 +205986,7 @@ class CurveCurve {
205868
205986
  let iMin = 0;
205869
205987
  let minDistXY = 2 * maxDistance;
205870
205988
  for (let i = 0; i < closeApproaches.length; ++i) {
205989
+ // TODO: this distance should already be in detail.a. Verify this, then just use it instead of recomputing below.
205871
205990
  const distXY = closeApproaches[i].detailA.point.distanceXY(closeApproaches[i].detailB.point);
205872
205991
  if (distXY < minDistXY) {
205873
205992
  iMin = i;
@@ -206947,8 +207066,9 @@ __webpack_require__.r(__webpack_exports__);
206947
207066
  /* harmony export */ CurveLocationDetailPair: () => (/* binding */ CurveLocationDetailPair),
206948
207067
  /* harmony export */ CurveSearchStatus: () => (/* binding */ CurveSearchStatus)
206949
207068
  /* harmony export */ });
206950
- /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
206951
- /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
207069
+ /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
207070
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
207071
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
206952
207072
  /*---------------------------------------------------------------------------------------------
206953
207073
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
206954
207074
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -206958,6 +207078,7 @@ __webpack_require__.r(__webpack_exports__);
206958
207078
  */
206959
207079
 
206960
207080
 
207081
+
206961
207082
  /**
206962
207083
  * An enumeration of special conditions being described by a CurveLocationDetail.
206963
207084
  * @public
@@ -207038,9 +207159,9 @@ class CurveLocationDetail {
207038
207159
  pointQ;
207039
207160
  /** Constructor */
207040
207161
  constructor() {
207041
- this.pointQ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.createZero();
207162
+ this.pointQ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.createZero();
207042
207163
  this.fraction = 0;
207043
- this.point = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.createZero();
207164
+ this.point = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.createZero();
207044
207165
  this.a = 0.0;
207045
207166
  }
207046
207167
  /** Set the (optional) intervalRole field. */
@@ -207187,7 +207308,7 @@ class CurveLocationDetail {
207187
207308
  static createConditionalMoveSignedDistance(allowExtension, curve, startFraction, endFraction, requestedSignedDistance, result) {
207188
207309
  let a = requestedSignedDistance;
207189
207310
  let status = CurveSearchStatus.success;
207190
- if (!allowExtension && !_Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isIn01(endFraction)) {
207311
+ if (!allowExtension && !_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isIn01(endFraction)) {
207191
207312
  // cap the movement at the endpoint
207192
207313
  if (endFraction < 0.0) {
207193
207314
  a = -curve.curveLengthBetweenFractions(startFraction, 0.0);
@@ -207298,7 +207419,7 @@ class CurveLocationDetail {
207298
207419
  inverseInterpolateFraction(f, defaultFraction = 0) {
207299
207420
  if (this.fraction1 === undefined)
207300
207421
  return defaultFraction;
207301
- const a = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.inverseInterpolate01(this.fraction, this.fraction1, f);
207422
+ const a = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.inverseInterpolate01(this.fraction, this.fraction1, f);
207302
207423
  if (a === undefined)
207303
207424
  return defaultFraction;
207304
207425
  return a;
@@ -207321,7 +207442,7 @@ class CurveLocationDetail {
207321
207442
  * @param fractionTol optional relative tolerance for comparing fractions with [[Geometry.isAlmostEqualNumber]].
207322
207443
  */
207323
207444
  isSameCurveAndFraction(other, fractionTol) {
207324
- return this.curve === other.curve && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isAlmostEqualNumber(this.fraction, other.fraction, fractionTol);
207445
+ return this.curve === other.curve && _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isAlmostEqualNumber(this.fraction, other.fraction, fractionTol);
207325
207446
  }
207326
207447
  /**
207327
207448
  * Transform the detail in place.
@@ -207457,6 +207578,64 @@ class CurveLocationDetailPair {
207457
207578
  tryTransformInPlace(transform) {
207458
207579
  return this.detailA.tryTransformInPlace(transform) && this.detailB.tryTransformInPlace(transform);
207459
207580
  }
207581
+ /**
207582
+ * Return a pair comparator useful for sorting an array of detail pairs by their fractions.
207583
+ * * Comparison assumes detailA curves are the same and detailB curves are the same.
207584
+ * * Comparison checks for equality of pair fractions, then of pair points, then sorts by detailA.fraction, then detailB.fraction.
207585
+ * @param fractionTol tolerance for comparing fractions. Default value [[Geometry.smallFraction]].
207586
+ * @param pointTol tolerance for comparing points, used if fractions are distinct. Default value [[Geometry.smallMetricDistance]].
207587
+ * @param xyOnly whether to perform point comparisons in xy only. Default is false (compare 3D points).
207588
+ * @param equateClosedCurveFractions whether to equate fractions 0 and 1 for physically closed curves. Default is false.
207589
+ */
207590
+ static comparePairsByFractions(fractionTol = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallFraction, pointTol = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance, xyOnly = false, equateClosedCurveFractions = false) {
207591
+ return (p0, p1) => {
207592
+ (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(() => p0.detailA.curve === p1.detailA.curve && p0.detailB.curve === p1.detailB.curve, "pairs are compatible");
207593
+ const curveA = p0.detailA.curve;
207594
+ const curveB = p0.detailB.curve;
207595
+ let fraction0A = p0.detailA.fraction;
207596
+ let fraction0B = p0.detailB.fraction;
207597
+ let fraction1A = p1.detailA.fraction;
207598
+ let fraction1B = p1.detailB.fraction;
207599
+ if (equateClosedCurveFractions) {
207600
+ if (curveA?.isPhysicallyClosedCurve(pointTol, xyOnly)) {
207601
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isAlmostEqualEitherNumber(p0.detailA.fraction, 0, 1, fractionTol))
207602
+ fraction0A = 0;
207603
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isAlmostEqualEitherNumber(p1.detailA.fraction, 0, 1, fractionTol))
207604
+ fraction1A = 0;
207605
+ }
207606
+ if (curveB?.isPhysicallyClosedCurve(pointTol, xyOnly)) {
207607
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isAlmostEqualEitherNumber(p0.detailB.fraction, 0, 1, fractionTol))
207608
+ fraction0B = 0;
207609
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isAlmostEqualEitherNumber(p1.detailB.fraction, 0, 1, fractionTol))
207610
+ fraction1B = 0;
207611
+ }
207612
+ }
207613
+ const sameFractionsA = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isAlmostEqualNumber(fraction0A, fraction1A, fractionTol);
207614
+ if (sameFractionsA && _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isAlmostEqualNumber(fraction0B, fraction1B, fractionTol))
207615
+ return 0;
207616
+ const samePointsA = xyOnly ? p0.detailA.point.isAlmostEqualXY(p1.detailA.point, pointTol) : p0.detailA.point.isAlmostEqual(p1.detailA.point, pointTol);
207617
+ if (samePointsA && (xyOnly ? p0.detailB.point.isAlmostEqualXY(p1.detailB.point, pointTol) : p0.detailB.point.isAlmostEqual(p1.detailB.point, pointTol)))
207618
+ return 0;
207619
+ return sameFractionsA ? fraction0B - fraction1B : fraction0A - fraction1A;
207620
+ };
207621
+ }
207622
+ /**
207623
+ * Return a pair comparator useful for sorting an array of detail pairs by their points.
207624
+ * * Comparison sorts the points lexicographically, `detailA.point` first, then `detailB.point`.
207625
+ * @param pointTol tolerance for comparing points. Default value [[Geometry.smallMetricDistance]].
207626
+ * @param xyOnly whether to perform point comparisons in xy only. Default is false (compare 3D points).
207627
+ */
207628
+ static comparePairsByPoints(pointTol = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance, xyOnly = false) {
207629
+ return (p0, p1) => {
207630
+ const comparePoints = xyOnly ? _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.compareXY(pointTol) : _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.compareXYZ(pointTol);
207631
+ const compareA = comparePoints(p0.detailA.point, p1.detailA.point);
207632
+ const compareB = comparePoints(p0.detailB.point, p1.detailB.point);
207633
+ const samePointsA = compareA === 0;
207634
+ if (samePointsA && compareB === 0)
207635
+ return 0;
207636
+ return samePointsA ? compareB : compareA;
207637
+ };
207638
+ }
207460
207639
  }
207461
207640
  /**
207462
207641
  * Data bundle for a pair of arrays of CurveLocationDetail structures.
@@ -208410,11 +208589,11 @@ class CurvePrimitive extends _GeometryQuery__WEBPACK_IMPORTED_MODULE_1__.Geometr
208410
208589
  }
208411
208590
  /**
208412
208591
  * Attach StrokeCountMap structure to this primitive (and recursively to any children)
208413
- * * Base class implementation (here) gets the simple count from computeStrokeCountForOptions and attaches it.
208414
- * * LineString3d, arc3d, BezierCurve3d, BezierCurve3dH accept that default.
208415
- * * Subdivided primitives (linestring, bspline curve) implement themselves and attach a StrokeCountMap containing the
208592
+ * * Base class implementation (here) gets the simple count from [[computeStrokeCountForOptions]] and attaches it.
208593
+ * * [[LineString3d]], [[Arc3d]], [[BezierCurve3d]], [[BezierCurve3dH]] accept that default.
208594
+ * * Subdivided primitives ([[LineString3d]], [[BSplineCurve3d]]) implement themselves and attach a StrokeCountMap containing the
208416
208595
  * total count, and also containing an array of StrokeCountMap per component.
208417
- * * For CurvePrimitiveWithDistanceIndex, the top level gets (only) a total count, and each child gets
208596
+ * * For [[CurveChainWithDistanceIndex]], the top level gets (only) a total count, and each child gets
208418
208597
  * its own StrokeCountMap with appropriate structure.
208419
208598
  * @param options StrokeOptions that determine count
208420
208599
  * @param parentStrokeMap optional map from parent. Its count, curveLength, and a1 values are increased with count
@@ -208428,11 +208607,11 @@ class CurvePrimitive extends _GeometryQuery__WEBPACK_IMPORTED_MODULE_1__.Geometr
208428
208607
  }
208429
208608
  /**
208430
208609
  * Evaluate strokes at fractions indicated in a StrokeCountMap.
208431
- * * Base class implementation (here) gets the simple count from computeStrokeCountForOptions and strokes at
208610
+ * * Base class implementation (here) gets the simple count from [[computeStrokeCountForOptions]] and strokes at
208432
208611
  * uniform fractions.
208433
- * * LineString3d, arc3d, BezierCurve3d, BezierCurve3dH accept that default.
208434
- * * Subdivided primitives (linestring, bspline curve) implement themselves and evaluate within components.
208435
- * * CurvePrimitiveWithDistanceIndex recurses to its children.
208612
+ * * [[LineString3d]], [[Arc3d]], [[BezierCurve3d]], [[BezierCurve3dH]] accept that default.
208613
+ * * Subdivided primitives ([[LineString3d]], [[BSplineCurve3d]]) implement themselves and evaluate within components.
208614
+ * * [[CurveChainWithDistanceIndex]] recurses to its children.
208436
208615
  * * if packedFraction and packedDerivative arrays are present in the LineString3d, fill them.
208437
208616
  * @param map = stroke count data.
208438
208617
  * @param linestring = receiver linestring.
@@ -208463,7 +208642,7 @@ class CurvePrimitive extends _GeometryQuery__WEBPACK_IMPORTED_MODULE_1__.Geometr
208463
208642
  * Return an array containing only the curve primitives.
208464
208643
  * * This DEFAULT implementation simply pushes `this` to the collectorArray.
208465
208644
  * @param collectorArray array to receive primitives (pushed -- the array is not cleared)
208466
- * @param smallestPossiblePrimitives if true, a [[CurvePrimitiveWithDistanceIndex]] recurses on its (otherwise hidden)
208645
+ * @param smallestPossiblePrimitives if true, a [[CurveChainWithDistanceIndex]] recurses on its (otherwise hidden)
208467
208646
  * children. If false, it returns only itself.
208468
208647
  * @param explodeLinestrings if true, push a [[LineSegment3d]] for each segment of a [[LineString3d]]. If false,
208469
208648
  * push only the [[LineString3d]].
@@ -208476,8 +208655,9 @@ class CurvePrimitive extends _GeometryQuery__WEBPACK_IMPORTED_MODULE_1__.Geometr
208476
208655
  * * This DEFAULT implementation captures the optional collector and calls [[collectCurvePrimitivesGo]].
208477
208656
  * @param collectorArray optional array to receive primitives. If present, new primitives are ADDED (without
208478
208657
  * clearing the array.)
208479
- * @param smallestPossiblePrimitives if false, CurvePrimitiveWithDistanceIndex returns only itself. If true,
208480
- * it recurses to its (otherwise hidden) children.
208658
+ * @param smallestPossiblePrimitives if false (default), a [[CurveChainWithDistanceIndex]] returns only itself;
208659
+ * otherwise, it recurses to its (otherwise hidden) children.
208660
+ * @param explodeLinestrings whether to return [[LineSegment3d]]s for a [[LineString3d]] (default false).
208481
208661
  */
208482
208662
  collectCurvePrimitives(collectorArray, smallestPossiblePrimitives = false, explodeLinestrings = false) {
208483
208663
  const results = collectorArray === undefined ? [] : collectorArray;
@@ -213612,9 +213792,9 @@ __webpack_require__.r(__webpack_exports__);
213612
213792
  /* harmony import */ var _geometry3d_IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../geometry3d/IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
213613
213793
  /* harmony import */ var _geometry3d_Point3dArrayCarrier__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../geometry3d/Point3dArrayCarrier */ "../../core/geometry/lib/esm/geometry3d/Point3dArrayCarrier.js");
213614
213794
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
213615
- /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
213795
+ /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
213616
213796
  /* harmony import */ var _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../geometry3d/PolylineCompressionByEdgeOffset */ "../../core/geometry/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js");
213617
- /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
213797
+ /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
213618
213798
  /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
213619
213799
  /* harmony import */ var _geometry3d_SortablePolygon__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../geometry3d/SortablePolygon */ "../../core/geometry/lib/esm/geometry3d/SortablePolygon.js");
213620
213800
  /* harmony import */ var _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../geometry3d/Transform */ "../../core/geometry/lib/esm/geometry3d/Transform.js");
@@ -213622,18 +213802,19 @@ __webpack_require__.r(__webpack_exports__);
213622
213802
  /* harmony import */ var _polyface_PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../polyface/PolyfaceBuilder */ "../../core/geometry/lib/esm/polyface/PolyfaceBuilder.js");
213623
213803
  /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
213624
213804
  /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
213625
- /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
213805
+ /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
213626
213806
  /* harmony import */ var _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../topology/Triangulation */ "../../core/geometry/lib/esm/topology/Triangulation.js");
213627
213807
  /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
213628
- /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
213808
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
213809
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
213629
213810
  /* harmony import */ var _CurveOps__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./CurveOps */ "../../core/geometry/lib/esm/curve/CurveOps.js");
213630
213811
  /* harmony import */ var _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
213631
213812
  /* harmony import */ var _CurveWireMomentsXYZ__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./CurveWireMomentsXYZ */ "../../core/geometry/lib/esm/curve/CurveWireMomentsXYZ.js");
213632
- /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
213813
+ /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
213633
213814
  /* harmony import */ var _internalContexts_ChainCollectorContext__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./internalContexts/ChainCollectorContext */ "../../core/geometry/lib/esm/curve/internalContexts/ChainCollectorContext.js");
213634
213815
  /* harmony import */ var _internalContexts_PolygonOffsetContext__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./internalContexts/PolygonOffsetContext */ "../../core/geometry/lib/esm/curve/internalContexts/PolygonOffsetContext.js");
213635
- /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
213636
- /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
213816
+ /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
213817
+ /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
213637
213818
  /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
213638
213819
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
213639
213820
  /* harmony import */ var _OffsetOptions__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./OffsetOptions */ "../../core/geometry/lib/esm/curve/OffsetOptions.js");
@@ -213692,6 +213873,7 @@ __webpack_require__.r(__webpack_exports__);
213692
213873
 
213693
213874
 
213694
213875
 
213876
+
213695
213877
 
213696
213878
 
213697
213879
  /**
@@ -214391,27 +214573,113 @@ class RegionOps {
214391
214573
  }
214392
214574
  return _geometry3d_SortablePolygon__WEBPACK_IMPORTED_MODULE_33__.SortablePolygon.sortAsAnyRegion(loopAndArea);
214393
214575
  }
214576
+ /**
214577
+ * Simplify the graph by removing bridge edges that do not serve to connect inner and outer loops.
214578
+ * * If edgeTags are `CurveLocationDetail`s, e.g., as set by `PlanarSubdivision.assembleHalfEdgeGraph`, attempt to heal edges split by removed bridge edges.
214579
+ * @param graph half edges to process.
214580
+ * @param isBridgeEdge optional function to identify a bridge edge. Default looks for `HalfEdgeMask.BRIDGE_EDGE`.
214581
+ * @param faceToArea optional function to compute face area. Default is `HalfEdgeGraphSearch.signedFaceArea`.
214582
+ * @returns the number of extraneous bridge edges removed from the graph.
214583
+ * @internal
214584
+ */
214585
+ static removeExtraneousBridgeEdges(graph, isBridgeEdge, faceToArea) {
214586
+ const toHeal = [];
214587
+ const interiorBridges = [];
214588
+ if (!faceToArea)
214589
+ faceToArea = (node) => _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeGraphSearch.signedFaceArea(node);
214590
+ if (!isBridgeEdge)
214591
+ isBridgeEdge = (node) => node.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE);
214592
+ // isolate dangling bridges, bridges separating different faces, and "exterior" bridges in the negative area face
214593
+ graph.announceEdges((_g, node) => {
214594
+ if (isBridgeEdge(node)) {
214595
+ if (node.isDangling || node.edgeMate.isDangling || !node.findAroundFace(node.edgeMate) || faceToArea(node) < 0.0) {
214596
+ toHeal.push(node.vertexSuccessor);
214597
+ toHeal.push(node.edgeMate.vertexSuccessor);
214598
+ node.isolateEdge();
214599
+ }
214600
+ else {
214601
+ interiorBridges.push(node);
214602
+ }
214603
+ }
214604
+ return true;
214605
+ });
214606
+ // Relies only on face loop orientation. Doesn't use static HalfEdgeMasks!
214607
+ const isBoundaryEdge = (node) => {
214608
+ if (faceToArea(node) < 0.0)
214609
+ return true; // exterior face
214610
+ if (node.findAroundFace(node.edgeMate))
214611
+ return false; // interior washer face
214612
+ return faceToArea(node.edgeMate) < 0.0; // adjacent to exterior face
214613
+ };
214614
+ // All bridges in the negative area face were isolated, but this may have promoted other bridges to the
214615
+ // negative area face. Keep isolating these bridge edges until none remain.
214616
+ let numIsolatedThisPass;
214617
+ do {
214618
+ numIsolatedThisPass = 0;
214619
+ for (const node of interiorBridges) {
214620
+ if (!node.isIsolatedEdge && isBoundaryEdge(node)) {
214621
+ toHeal.push(node.vertexSuccessor);
214622
+ toHeal.push(node.edgeMate.vertexSuccessor);
214623
+ node.isolateEdge();
214624
+ numIsolatedThisPass++;
214625
+ }
214626
+ }
214627
+ } while (numIsolatedThisPass > 0);
214628
+ // lambda to extend the detail interval on a side of a healed edge
214629
+ const mergeDetails = (he, newFraction, newPoint) => {
214630
+ if (he && he.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_34__.CurveLocationDetail && he.sortData !== undefined && newFraction !== undefined && newPoint) {
214631
+ if (he.sortData > 0)
214632
+ he.edgeTag.captureFraction1Point1(newFraction, newPoint);
214633
+ else
214634
+ he.edgeTag.captureFractionPoint(newFraction, newPoint);
214635
+ }
214636
+ };
214637
+ // At this point all removable bridges are isolated. Clean up their original vertex loops, if possible.
214638
+ for (const doomedA of toHeal) {
214639
+ const doomedB = doomedA.vertexSuccessor;
214640
+ if ( // are the geometries mergeable?
214641
+ doomedA !== doomedB &&
214642
+ doomedA.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_34__.CurveLocationDetail && doomedA.sortData !== undefined &&
214643
+ doomedB.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_34__.CurveLocationDetail && doomedB.sortData !== undefined &&
214644
+ doomedA.edgeTag.curve === doomedB.edgeTag.curve &&
214645
+ doomedA.edgeTag.isInterval() && doomedB.edgeTag.isInterval() &&
214646
+ doomedA.sortData * doomedB.sortData < 0 &&
214647
+ ((doomedA.sortData > 0 && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSmallRelative(doomedA.edgeTag.fraction - doomedB.edgeTag.fraction1)) ||
214648
+ (doomedA.sortData < 0 && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSmallRelative(doomedA.edgeTag.fraction1 - doomedB.edgeTag.fraction)))) {
214649
+ const survivorA = _topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdge.healEdge(doomedA, false);
214650
+ if (survivorA) {
214651
+ const endFractionA = (doomedA.sortData > 0) ? doomedA.edgeTag.fraction1 : doomedA.edgeTag.fraction;
214652
+ const endPointA = (doomedA.sortData > 0) ? doomedA.edgeTag.point1 : doomedA.edgeTag.point;
214653
+ mergeDetails(survivorA, endFractionA, endPointA);
214654
+ const endFractionB = (doomedB.sortData > 0) ? doomedB.edgeTag.fraction1 : doomedB.edgeTag.fraction;
214655
+ const endPointB = (doomedB.sortData > 0) ? doomedB.edgeTag.point1 : doomedB.edgeTag.point;
214656
+ mergeDetails(survivorA.edgeMate, endFractionB, endPointB);
214657
+ }
214658
+ }
214659
+ }
214660
+ return graph.deleteIsolatedEdges();
214661
+ }
214394
214662
  /**
214395
214663
  * Collect inputs that are nominally closed: regions, and physically closed curves.
214396
214664
  * * Physically closed input curves are each returned wrapped in a Loop to facilitate xy-algorithms,
214397
214665
  * but outside this limited context, these Loops only makes sense if they are planar.
214666
+ * @param curves inputs
214667
+ * @param openCurves optional array to receive open input curves that were not returned as regions.
214668
+ * @param tolerance optional distance tolerance for determining physical closure. Default is [[Geometry.smallMetricDistance]].
214398
214669
  */
214399
- static collectRegionsAndClosedPrimitives(curves, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
214670
+ static collectRegionsAndClosedPrimitives(curves, openCurves, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
214400
214671
  const regions = [];
214401
214672
  if (!Array.isArray(curves))
214402
214673
  curves = [curves];
214403
214674
  for (const curve of curves) {
214404
- if (curve instanceof _Loop__WEBPACK_IMPORTED_MODULE_8__.Loop || curve instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_9__.ParityRegion || curve instanceof _UnionRegion__WEBPACK_IMPORTED_MODULE_14__.UnionRegion) {
214675
+ if (curve instanceof _Loop__WEBPACK_IMPORTED_MODULE_8__.Loop || curve instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_9__.ParityRegion || curve instanceof _UnionRegion__WEBPACK_IMPORTED_MODULE_14__.UnionRegion)
214405
214676
  regions.push(curve);
214406
- }
214407
- else if (curve instanceof _Path__WEBPACK_IMPORTED_MODULE_24__.Path) {
214408
- if (curve.isPhysicallyClosedCurve(tolerance))
214409
- regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(...curve.children));
214410
- }
214411
- else if (curve instanceof _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__.CurvePrimitive) {
214412
- if (curve.isPhysicallyClosedCurve(tolerance))
214413
- regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(curve));
214414
- }
214677
+ else if (curve instanceof _Path__WEBPACK_IMPORTED_MODULE_24__.Path && curve.isPhysicallyClosedCurve(tolerance))
214678
+ regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(...curve.children));
214679
+ else if (curve instanceof _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__.CurvePrimitive && curve.isPhysicallyClosedCurve(tolerance))
214680
+ regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(curve));
214681
+ else if (openCurves)
214682
+ openCurves.push(curve);
214415
214683
  }
214416
214684
  return regions;
214417
214685
  }
@@ -214421,9 +214689,9 @@ class RegionOps {
214421
214689
  * * "Holes" implied/bounded by inputs are _not_ preserved/discovered in output; in particular [[ParityRegion]]
214422
214690
  * hole loops are treated like any other positive area loops.
214423
214691
  * * A common use case of this method is to assemble the bounding negative-area "exterior" loop for each connected
214424
- * component of input curves. Passing `addBridges = true` decreases the number of connected components for nested
214425
- * input [[Loop]]s, and thus increases the likelihood of returning exactly one exterior loop. (This is why the
214426
- * default value for `addBridges` is `true`.)
214692
+ * component of input curves. Passing addBridges = true adds "bridge" segments to connect unconnected input [[Loops]]s
214693
+ * and thereby increases the likelihood that a single connected component is returned. (This is why the default value
214694
+ * for addBridges is true.)
214427
214695
  * @param curvesAndRegions Any collection of curves. Each [[AnyRegion]] contributes its children _stripped of
214428
214696
  * parity context_.
214429
214697
  * @param tolerance optional distance tolerance for coincidence. Default is [[Geometry.smallMetricDistance]].
@@ -214439,24 +214707,33 @@ class RegionOps {
214439
214707
  */
214440
214708
  static constructAllXYRegionLoops(curvesAndRegions, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance, addBridges = true) {
214441
214709
  let primitives = RegionOps.collectCurvePrimitives(curvesAndRegions, undefined, true, true);
214442
- primitives = _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_34__.TransferWithSplitArcs.clone(_CurveCollection__WEBPACK_IMPORTED_MODULE_25__.BagOfCurves.create(...primitives)).children;
214710
+ primitives = _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_35__.TransferWithSplitArcs.clone(_CurveCollection__WEBPACK_IMPORTED_MODULE_25__.BagOfCurves.create(...primitives)).children;
214443
214711
  const range = this.curveArrayRange(primitives);
214444
214712
  const areaTol = this.computeXYAreaTolerance(range, tolerance);
214445
- if (addBridges) { // generate a temp graph to extract its bridge edges
214713
+ let hasOpenCurve = false;
214714
+ if (addBridges) { // generate a temp graph from ONLY the closed inputs to extract its bridge edges
214446
214715
  const context = _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionBooleanContext.create(_RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union);
214447
- const regions = this.collectRegionsAndClosedPrimitives(curvesAndRegions, tolerance);
214716
+ const openCurves = [];
214717
+ const regions = this.collectRegionsAndClosedPrimitives(curvesAndRegions, openCurves, tolerance);
214718
+ hasOpenCurve = openCurves.length > 0;
214448
214719
  if (regions.length > 0) {
214449
214720
  context.addMembers(regions, undefined);
214450
214721
  context.annotateAndMergeCurvesInGraph(tolerance);
214451
214722
  context.graph.announceEdges((_graph, edge) => {
214452
- if (edge.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE))
214453
- primitives.push(_LineSegment3d__WEBPACK_IMPORTED_MODULE_35__.LineSegment3d.create(edge.getPoint3d(), edge.faceSuccessor.getPoint3d()));
214723
+ if (edge.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE)) {
214724
+ // ensure the bridge edge roundtrips thru assembleHalfEdgeGraph so that we can filter it later if necessary
214725
+ const bridgeSegment = _LineSegment3d__WEBPACK_IMPORTED_MODULE_36__.LineSegment3d.create(edge.getPoint3d(), edge.faceSuccessor.getPoint3d());
214726
+ bridgeSegment.parent = new _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupMember(bridgeSegment, context.extraGeometry);
214727
+ primitives.push(bridgeSegment);
214728
+ }
214454
214729
  return true;
214455
214730
  });
214456
214731
  }
214457
214732
  }
214458
- const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_36__.CurveCurve.allIntersectionsAmongPrimitivesXY(primitives, tolerance);
214733
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_37__.CurveCurve.allIntersectionsAmongPrimitivesXY(primitives, tolerance);
214459
214734
  const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.assembleHalfEdgeGraph(primitives, intersections, tolerance);
214735
+ if (addBridges && hasOpenCurve)
214736
+ RegionOps.removeExtraneousBridgeEdges(graph);
214460
214737
  return _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.collectSignedLoopSetsInHalfEdgeGraph(graph, areaTol);
214461
214738
  }
214462
214739
  /**
@@ -214513,12 +214790,12 @@ class RegionOps {
214513
214790
  * @param worldToLocal transform to apply to data before computing its range
214514
214791
  */
214515
214792
  static curveArrayRange(data, worldToLocal) {
214516
- const range = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_37__.Range3d.create();
214517
- if (data instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__.GeometryQuery)
214793
+ const range = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_38__.Range3d.create();
214794
+ if (data instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_39__.GeometryQuery)
214518
214795
  data.extendRange(range, worldToLocal);
214519
214796
  else if (Array.isArray(data)) {
214520
214797
  for (const c of data) {
214521
- if (c instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__.GeometryQuery)
214798
+ if (c instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_39__.GeometryQuery)
214522
214799
  c.extendRange(range, worldToLocal);
214523
214800
  else if (c instanceof _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d)
214524
214801
  range.extendPoint(c, worldToLocal);
@@ -214554,7 +214831,7 @@ class RegionOps {
214554
214831
  for (const polygon of polygons)
214555
214832
  writablePolygons.push(_geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray.create(polygon));
214556
214833
  }
214557
- const sortedPolygons = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_39__.PolygonOps.sortOuterAndHoleLoopsXY(writablePolygons);
214834
+ const sortedPolygons = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_40__.PolygonOps.sortOuterAndHoleLoopsXY(writablePolygons);
214558
214835
  if (sortedPolygons.length === 1) { // below requires exactly one outer loop!
214559
214836
  if (graph = _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__.Triangulator.createTriangulatedGraphFromLoops(sortedPolygons[0]))
214560
214837
  _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__.Triangulator.flipTriangles(graph);
@@ -214637,7 +214914,7 @@ class RegionOps {
214637
214914
  if (!graph)
214638
214915
  return undefined;
214639
214916
  if (options?.maximizeConvexFacets)
214640
- _topology_Merging__WEBPACK_IMPORTED_MODULE_40__.HalfEdgeGraphOps.expandConvexFaces(graph);
214917
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_41__.HalfEdgeGraphOps.expandConvexFaces(graph);
214641
214918
  return _polyface_PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_12__.PolyfaceBuilder.graphToPolyface(graph, options);
214642
214919
  }
214643
214920
  /**
@@ -214651,7 +214928,7 @@ class RegionOps {
214651
214928
  if (!graph)
214652
214929
  return undefined;
214653
214930
  if (maximize)
214654
- _topology_Merging__WEBPACK_IMPORTED_MODULE_40__.HalfEdgeGraphOps.expandConvexFaces(graph);
214931
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_41__.HalfEdgeGraphOps.expandConvexFaces(graph);
214655
214932
  const convexPolygons = [];
214656
214933
  graph.announceFaceLoops((_graph, seed) => {
214657
214934
  if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.EXTERIOR))
@@ -214700,15 +214977,15 @@ __webpack_require__.r(__webpack_exports__);
214700
214977
  /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
214701
214978
  /* harmony import */ var _topology_RegularizeFace__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../topology/RegularizeFace */ "../../core/geometry/lib/esm/topology/RegularizeFace.js");
214702
214979
  /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
214703
- /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
214704
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
214980
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
214981
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
214705
214982
  /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
214706
214983
  /* harmony import */ var _internalContexts_PlaneAltitudeRangeContext__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./internalContexts/PlaneAltitudeRangeContext */ "../../core/geometry/lib/esm/curve/internalContexts/PlaneAltitudeRangeContext.js");
214707
214984
  /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
214708
214985
  /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
214709
214986
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
214710
214987
  /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
214711
- /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
214988
+ /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
214712
214989
  /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
214713
214990
  /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
214714
214991
  /*---------------------------------------------------------------------------------------------
@@ -215213,94 +215490,6 @@ class RegionBooleanContext {
215213
215490
  this.extraGeometry.addMember(bridgeLine, true);
215214
215491
  }
215215
215492
  }
215216
- /**
215217
- * Simplify the graph by removing bridge edges that do not serve to connect inner and outer loops, i.e.:
215218
- * * the bridge edge is dangling
215219
- * * the bridge edge is adjacent to multiple faces
215220
- * * the bridge edge is adjacent to a negative area face
215221
- * @returns the number of extraneous bridge edges removed from the graph.
215222
- */
215223
- removeExtraneousBridgeEdges() {
215224
- const toHeal = [];
215225
- const interiorBridges = [];
215226
- // lambda test for boundary edge. Relies only on face loop orientation. Doesn't use HalfEdgeMasks!
215227
- const isExteriorEdge = (node) => {
215228
- if (this.faceAreaFunction(node) < 0.0)
215229
- return true;
215230
- if (!node.findAroundFace(node.edgeMate))
215231
- return this.faceAreaFunction(node.edgeMate) < 0.0;
215232
- return false;
215233
- };
215234
- // isolate dangling bridges, bridges separating different faces, and "exterior" bridges in the negative area face
215235
- this.graph.announceEdges((_graph, node) => {
215236
- if (node.edgeTag !== undefined) {
215237
- if (node.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail) {
215238
- if (node.edgeTag.curve) {
215239
- if (node.edgeTag.curve.parent instanceof RegionGroupMember) {
215240
- if (node.edgeTag.curve.parent.parentGroup === this.extraGeometry) {
215241
- if (node.isDangling || node.edgeMate.isDangling || !node.findAroundFace(node.edgeMate) || this.faceAreaFunction(node) < 0.0) {
215242
- toHeal.push(node.vertexSuccessor);
215243
- toHeal.push(node.edgeMate.vertexSuccessor);
215244
- node.isolateEdge();
215245
- }
215246
- else {
215247
- interiorBridges.push(node);
215248
- }
215249
- }
215250
- }
215251
- }
215252
- }
215253
- }
215254
- return true;
215255
- });
215256
- // At this point, all bridges that were exterior are isolated, but this may have caused formerly
215257
- // interior bridges to become exterior. Now we successively isolate exterior bridges until none remain.
215258
- let numIsolatedThisPass;
215259
- do {
215260
- numIsolatedThisPass = 0;
215261
- for (const node of interiorBridges) {
215262
- if (!node.isIsolatedEdge && isExteriorEdge(node)) {
215263
- toHeal.push(node.vertexSuccessor);
215264
- toHeal.push(node.edgeMate.vertexSuccessor);
215265
- node.isolateEdge();
215266
- numIsolatedThisPass++;
215267
- }
215268
- }
215269
- } while (numIsolatedThisPass > 0);
215270
- // lambda to extend the detail interval on a side of a healed edge
215271
- const mergeDetails = (he, newFraction, newPoint) => {
215272
- if (he && he.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && he.sortData !== undefined && newFraction !== undefined && newPoint) {
215273
- if (he.sortData > 0)
215274
- he.edgeTag.captureFraction1Point1(newFraction, newPoint);
215275
- else
215276
- he.edgeTag.captureFractionPoint(newFraction, newPoint);
215277
- }
215278
- };
215279
- // At this point all removable bridges are isolated. Clean up their original vertex loops, if possible.
215280
- for (const doomedA of toHeal) {
215281
- const doomedB = doomedA.vertexSuccessor;
215282
- if ( // are the geometries mergeable?
215283
- doomedA !== doomedB &&
215284
- doomedA.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && doomedA.sortData !== undefined &&
215285
- doomedB.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && doomedB.sortData !== undefined &&
215286
- doomedA.edgeTag.curve === doomedB.edgeTag.curve &&
215287
- doomedA.edgeTag.isInterval() && doomedB.edgeTag.isInterval() &&
215288
- doomedA.sortData * doomedB.sortData < 0 &&
215289
- ((doomedA.sortData > 0 && _Geometry__WEBPACK_IMPORTED_MODULE_7__.Geometry.isSmallRelative(doomedA.edgeTag.fraction - doomedB.edgeTag.fraction1)) ||
215290
- (doomedA.sortData < 0 && _Geometry__WEBPACK_IMPORTED_MODULE_7__.Geometry.isSmallRelative(doomedA.edgeTag.fraction1 - doomedB.edgeTag.fraction)))) {
215291
- const survivorA = _topology_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdge.healEdge(doomedA, false);
215292
- if (survivorA) {
215293
- const endFractionA = (doomedA.sortData > 0) ? doomedA.edgeTag.fraction1 : doomedA.edgeTag.fraction;
215294
- const endPointA = (doomedA.sortData > 0) ? doomedA.edgeTag.point1 : doomedA.edgeTag.point;
215295
- mergeDetails(survivorA, endFractionA, endPointA);
215296
- const endFractionB = (doomedB.sortData > 0) ? doomedB.edgeTag.fraction1 : doomedB.edgeTag.fraction;
215297
- const endPointB = (doomedB.sortData > 0) ? doomedB.edgeTag.point1 : doomedB.edgeTag.point;
215298
- mergeDetails(survivorA.edgeMate, endFractionB, endPointB);
215299
- }
215300
- }
215301
- }
215302
- return this.graph.deleteIsolatedEdges();
215303
- }
215304
215493
  /**
215305
215494
  * Markup and assembly steps for geometry in the RegionGroups.
215306
215495
  * * Annotate connection from group to curves.
@@ -215322,11 +215511,9 @@ class RegionBooleanContext {
215322
215511
  }
215323
215512
  }
215324
215513
  }
215325
- const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_17__.CurveCurve.allIntersectionsAmongPrimitivesXY(allPrimitives, mergeTolerance);
215326
- const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_18__.PlanarSubdivision.assembleHalfEdgeGraph(allPrimitives, intersections, mergeTolerance);
215327
- this.graph = graph;
215328
- this.faceAreaFunction = faceAreaFromCurvedEdgeData;
215329
- this.removeExtraneousBridgeEdges();
215514
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_16__.CurveCurve.allIntersectionsAmongPrimitivesXY(allPrimitives, mergeTolerance);
215515
+ const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_17__.PlanarSubdivision.assembleHalfEdgeGraph(allPrimitives, intersections, mergeTolerance);
215516
+ _RegionOps__WEBPACK_IMPORTED_MODULE_1__.RegionOps.removeExtraneousBridgeEdges(this.graph = graph, undefined, this.faceAreaFunction = faceAreaFromCurvedEdgeData);
215330
215517
  }
215331
215518
  _announceFaceFunction;
215332
215519
  /**
@@ -215412,7 +215599,7 @@ class RegionBooleanContext {
215412
215599
  const data = node.edgeTag;
215413
215600
  if (data instanceof RegionGroupMember)
215414
215601
  return updateRegionGroupMemberState(data);
215415
- if (data instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && data.curve) {
215602
+ if (data instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_18__.CurveLocationDetail && data.curve) {
215416
215603
  // We trust that the caller has linked from the graph node to a curve which has a RegionGroupMember as its parent.
215417
215604
  const member = data.curve.parent;
215418
215605
  if (member instanceof RegionGroupMember)
@@ -215523,7 +215710,7 @@ class GraphComponent {
215523
215710
  f.sumAroundFace(vertexFunction);
215524
215711
  }
215525
215712
  this.faceAreas.length = 0;
215526
- if (faceAreaFunction === faceAreaFromCurvedEdgeData && !this.faces.every((he) => he.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail))
215713
+ if (faceAreaFunction === faceAreaFromCurvedEdgeData && !this.faces.every((he) => he.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_18__.CurveLocationDetail))
215527
215714
  faceAreaFunction = undefined; // prerequisite CurveLocationDetails are absent, fall through to default
215528
215715
  if (!faceAreaFunction)
215529
215716
  faceAreaFunction = (node) => _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_4__.HalfEdgeGraphSearch.signedFaceArea(node); // polygon area
@@ -215591,14 +215778,21 @@ __webpack_require__.r(__webpack_exports__);
215591
215778
  * * Nearly all stroke and facet use cases will apply an angle tolerance.
215592
215779
  * * For curves, 15 degrees is typical
215593
215780
  * * For facets, 22.5 degrees is typical.
215594
- * * Halving the angle tolerance will (roughly) make curves get twice as many strokes, and surfaces get 4 times as many facets.
215595
- * * The angle tolerance has the useful property that its effect is independent of scale of that data. If data is suddenly scaled into millimeters rather than meters, the facet counts remain the same.
215781
+ * * Halving the angle tolerance will (roughly) make curves get twice as many strokes, and surfaces get 4 times as
215782
+ * many facets.
215783
+ * * The angle tolerance has the useful property that its effect is independent of scale of that data. If data is
215784
+ * suddenly scaled into millimeters rather than meters, the facet counts remain the same.
215596
215785
  * * When creating output for devices such as 3D printing will want a chord tolerance.
215597
- * * For graphics display, use an angle tolerance of around 15 degrees and an chord tolerance which is the size of several pixels.
215786
+ * * For graphics display, use an angle tolerance of around 15 degrees and an chord tolerance which is the size of
215787
+ * several pixels.
215598
215788
  * * Analysis meshes (e.g. Finite Elements) commonly need to apply maxEdgeLength.
215599
- * * Using maxEdgeLength for graphics probably produces too many facets. For example, it causes long cylinders to get many nearly-square facets instead of the small number of long quads usually used for graphics.
215600
- * * Facet tolerances are, as the Pirates' Code, guidelines, not absolute rules. Facet and stroke code may ignore tolerances in awkward situations.
215601
- * * If multiple tolerances are in effect, the actual count will usually be based on the one that demands the most strokes or facets, unless it is so high that it violates some upper limit on the number of facets on an arc or a section of a curve.
215789
+ * * Using maxEdgeLength for graphics probably produces too many facets. For example, it causes long cylinders to
215790
+ * get many nearly-square facets instead of the small number of long quads usually used for graphics.
215791
+ * * Facet tolerances are, as the Pirates' Code, guidelines, not absolute rules. Facet and stroke code may ignore
215792
+ * tolerances in awkward situations.
215793
+ * * If multiple tolerances are in effect, the actual count will usually be based on the one that demands the most
215794
+ * strokes or facets, unless it is so high that it violates some upper limit on the number of facets on an arc or a
215795
+ * section of a curve.
215602
215796
  * @public
215603
215797
  */
215604
215798
  class StrokeOptions {
@@ -215919,9 +216113,8 @@ __webpack_require__.r(__webpack_exports__);
215919
216113
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
215920
216114
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
215921
216115
  /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
215922
- /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
215923
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
215924
- /* harmony import */ var _NewtonRtoRStrokeHandler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./NewtonRtoRStrokeHandler */ "../../core/geometry/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js");
216116
+ /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
216117
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
215925
216118
  /*---------------------------------------------------------------------------------------------
215926
216119
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
215927
216120
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -215935,12 +216128,11 @@ __webpack_require__.r(__webpack_exports__);
215935
216128
 
215936
216129
 
215937
216130
 
215938
-
215939
216131
  /**
215940
216132
  * Context for searching for the tangent(s) to a CurvePrimitive.
215941
216133
  * @internal
215942
216134
  */
215943
- class AnnounceTangentStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMPORTED_MODULE_1__.NewtonRtoRStrokeHandler {
216135
+ class AnnounceTangentStrokeHandler extends _numerics_Newton__WEBPACK_IMPORTED_MODULE_1__.NewtonRtoRStrokeHandler {
215944
216136
  _curve;
215945
216137
  _announceTangent;
215946
216138
  _spacePoint;
@@ -215970,7 +216162,7 @@ class AnnounceTangentStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMP
215970
216162
  this._distanceTolSquared = this._distanceTol * this._distanceTol;
215971
216163
  this._workRay = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_4__.Ray3d.createZero();
215972
216164
  this.startCurvePrimitive(undefined);
215973
- this._newtonSolver = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_5__.Newton1dUnboundedApproximateDerivative(this);
216165
+ this._newtonSolver = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_1__.Newton1dUnboundedApproximateDerivative(this);
215974
216166
  }
215975
216167
  /** Specified by IStrokeHandler. */
215976
216168
  needPrimaryGeometryForStrokes() {
@@ -216003,7 +216195,7 @@ class AnnounceTangentStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMP
216003
216195
  cp = this._parentCurvePrimitive;
216004
216196
  if (this._curveMRU === cp && _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isAlmostEqualOptional(this._fractionMRU, fraction, _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallFloatingPoint))
216005
216197
  return; // avoid announcing duplicate tangents in succession (e.g., at interior stroke point)
216006
- this._workDetail = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_6__.CurveLocationDetail.createCurveFractionPoint(cp, fraction, point, this._workDetail);
216198
+ this._workDetail = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(cp, fraction, point, this._workDetail);
216007
216199
  this._announceTangent(this._workDetail);
216008
216200
  this._fractionMRU = fraction;
216009
216201
  this._curveMRU = cp;
@@ -216116,12 +216308,11 @@ __webpack_require__.r(__webpack_exports__);
216116
216308
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
216117
216309
  /* harmony export */ AppendPlaneIntersectionStrokeHandler: () => (/* binding */ AppendPlaneIntersectionStrokeHandler)
216118
216310
  /* harmony export */ });
216119
- /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
216311
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
216120
216312
  /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
216121
- /* harmony import */ var _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../numerics/BezierPolynomials */ "../../core/geometry/lib/esm/numerics/BezierPolynomials.js");
216122
- /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
216123
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
216124
- /* harmony import */ var _NewtonRtoRStrokeHandler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./NewtonRtoRStrokeHandler */ "../../core/geometry/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js");
216313
+ /* harmony import */ var _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../numerics/BezierPolynomials */ "../../core/geometry/lib/esm/numerics/BezierPolynomials.js");
216314
+ /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
216315
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
216125
216316
  /*---------------------------------------------------------------------------------------------
216126
216317
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
216127
216318
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -216134,12 +216325,11 @@ __webpack_require__.r(__webpack_exports__);
216134
216325
 
216135
216326
 
216136
216327
 
216137
-
216138
216328
  /**
216139
216329
  * Context for computing intersections of a CurvePrimitive with a plane.
216140
216330
  * @internal
216141
216331
  */
216142
- class AppendPlaneIntersectionStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMPORTED_MODULE_0__.NewtonRtoRStrokeHandler {
216332
+ class AppendPlaneIntersectionStrokeHandler extends _numerics_Newton__WEBPACK_IMPORTED_MODULE_0__.NewtonRtoRStrokeHandler {
216143
216333
  _curve;
216144
216334
  _plane;
216145
216335
  _intersections;
@@ -216168,7 +216358,7 @@ class AppendPlaneIntersectionStrokeHandler extends _NewtonRtoRStrokeHandler__WEB
216168
216358
  this._intersections = intersections;
216169
216359
  this.startCurvePrimitive(undefined);
216170
216360
  this._ray = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_1__.Ray3d.createZero();
216171
- this._newtonSolver = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_2__.Newton1dUnboundedApproximateDerivative(this);
216361
+ this._newtonSolver = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_0__.Newton1dUnboundedApproximateDerivative(this);
216172
216362
  }
216173
216363
  startCurvePrimitive(curve) {
216174
216364
  this._curve = curve;
@@ -216185,7 +216375,7 @@ class AppendPlaneIntersectionStrokeHandler extends _NewtonRtoRStrokeHandler__WEB
216185
216375
  numStrokes = 1;
216186
216376
  const df = 1.0 / numStrokes;
216187
216377
  for (let i = 0; i <= numStrokes; i++) {
216188
- const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.interpolate(fraction0, i * df, fraction1);
216378
+ const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.interpolate(fraction0, i * df, fraction1);
216189
216379
  cp.fractionToPointAndDerivative(fraction, this._ray);
216190
216380
  this.announcePointTangent(this._ray.origin, fraction, this._ray.direction);
216191
216381
  }
@@ -216195,11 +216385,11 @@ class AppendPlaneIntersectionStrokeHandler extends _NewtonRtoRStrokeHandler__WEB
216195
216385
  const h1 = this._plane.altitude(point1);
216196
216386
  if (h0 * h1 > 0.0)
216197
216387
  return;
216198
- const fraction01 = _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_4__.Order2Bezier.solveCoffs(h0, h1);
216388
+ const fraction01 = _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_3__.Order2Bezier.solveCoffs(h0, h1);
216199
216389
  // let numIntersection = 0;
216200
216390
  if (fraction01 !== undefined) {
216201
216391
  // numIntersection++;
216202
- const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.interpolate(fraction0, fraction01, fraction1);
216392
+ const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.interpolate(fraction0, fraction01, fraction1);
216203
216393
  this._newtonSolver.setX(fraction);
216204
216394
  if (this._newtonSolver.runIterations()) {
216205
216395
  this.announceSolutionFraction(this._newtonSolver.getX());
@@ -216211,7 +216401,7 @@ class AppendPlaneIntersectionStrokeHandler extends _NewtonRtoRStrokeHandler__WEB
216211
216401
  const curve = this.effectiveCurve();
216212
216402
  if (curve) {
216213
216403
  this._ray = curve.fractionToPointAndDerivative(fraction, this._ray);
216214
- this._intersections.push(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(curve, fraction, this._ray.origin));
216404
+ this._intersections.push(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPoint(curve, fraction, this._ray.origin));
216215
216405
  }
216216
216406
  }
216217
216407
  evaluate(fraction) {
@@ -216234,7 +216424,7 @@ class AppendPlaneIntersectionStrokeHandler extends _NewtonRtoRStrokeHandler__WEB
216234
216424
  if (this._functionB === 0)
216235
216425
  this.announceSolutionFraction(this._fractionB);
216236
216426
  if (this._functionA * this._functionB < 0) {
216237
- const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.inverseInterpolate(this._fractionA, this._functionA, this._fractionB, this._functionB);
216427
+ const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.inverseInterpolate(this._fractionA, this._functionA, this._fractionB, this._functionB);
216238
216428
  if (fraction) {
216239
216429
  this._newtonSolver.setX(fraction);
216240
216430
  if (this._newtonSolver.runIterations())
@@ -216617,11 +216807,10 @@ __webpack_require__.r(__webpack_exports__);
216617
216807
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
216618
216808
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
216619
216809
  /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
216620
- /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
216621
- /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
216622
- /* harmony import */ var _CurveExtendMode__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../CurveExtendMode */ "../../core/geometry/lib/esm/curve/CurveExtendMode.js");
216623
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
216624
- /* harmony import */ var _NewtonRtoRStrokeHandler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./NewtonRtoRStrokeHandler */ "../../core/geometry/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js");
216810
+ /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
216811
+ /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
216812
+ /* harmony import */ var _CurveExtendMode__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveExtendMode */ "../../core/geometry/lib/esm/curve/CurveExtendMode.js");
216813
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
216625
216814
  /*---------------------------------------------------------------------------------------------
216626
216815
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
216627
216816
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -216637,12 +216826,11 @@ __webpack_require__.r(__webpack_exports__);
216637
216826
 
216638
216827
 
216639
216828
 
216640
-
216641
216829
  /**
216642
216830
  * Context for searching for the closest point to a CurvePrimitive.
216643
216831
  * @internal
216644
216832
  */
216645
- class ClosestPointStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMPORTED_MODULE_1__.NewtonRtoRStrokeHandler {
216833
+ class ClosestPointStrokeHandler extends _numerics_Newton__WEBPACK_IMPORTED_MODULE_1__.NewtonRtoRStrokeHandler {
216646
216834
  _curve;
216647
216835
  _closestPoint;
216648
216836
  _spacePoint;
@@ -216671,7 +216859,7 @@ class ClosestPointStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMPORT
216671
216859
  this._extend = extend ?? false;
216672
216860
  this._xyOnly = xyOnly ?? false;
216673
216861
  this.startCurvePrimitive(undefined);
216674
- this._newtonSolver = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_5__.Newton1dUnboundedApproximateDerivative(this);
216862
+ this._newtonSolver = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_1__.Newton1dUnboundedApproximateDerivative(this);
216675
216863
  }
216676
216864
  claimResult() {
216677
216865
  if (this._closestPoint) {
@@ -216679,7 +216867,7 @@ class ClosestPointStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMPORT
216679
216867
  this._curve = this._closestPoint.curve;
216680
216868
  if (this._newtonSolver.runIterations()) {
216681
216869
  let fraction = this._newtonSolver.getX();
216682
- fraction = _CurveExtendMode__WEBPACK_IMPORTED_MODULE_6__.CurveExtendOptions.correctFraction(this._extend, fraction);
216870
+ fraction = _CurveExtendMode__WEBPACK_IMPORTED_MODULE_5__.CurveExtendOptions.correctFraction(this._extend, fraction);
216683
216871
  this.announceSolutionFraction(fraction);
216684
216872
  }
216685
216873
  }
@@ -216713,7 +216901,7 @@ class ClosestPointStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMPORT
216713
216901
  const distance = this._xyOnly ? this._spacePoint.distanceXY(point) : this._spacePoint.distance(point);
216714
216902
  if (this._closestPoint && distance > this._closestPoint.a)
216715
216903
  return;
216716
- this._closestPoint = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveLocationDetail.createCurveFractionPoint(cp, fraction, point, this._closestPoint);
216904
+ this._closestPoint = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_6__.CurveLocationDetail.createCurveFractionPoint(cp, fraction, point, this._closestPoint);
216717
216905
  this._closestPoint.a = distance;
216718
216906
  if (this._parentCurvePrimitive !== undefined)
216719
216907
  this._closestPoint.curve = this._parentCurvePrimitive;
@@ -216721,13 +216909,13 @@ class ClosestPointStrokeHandler extends _NewtonRtoRStrokeHandler__WEBPACK_IMPORT
216721
216909
  announceSegmentInterval(cp, point0, point1, _numStrokes, fraction0, fraction1) {
216722
216910
  let localFraction = 0;
216723
216911
  if (this._xyOnly)
216724
- localFraction = _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_8__.SmallSystem.lineSegment3dXYClosestPointUnbounded(point0, point1, this._spacePoint) ?? 0;
216912
+ localFraction = _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.lineSegment3dXYClosestPointUnbounded(point0, point1, this._spacePoint) ?? 0;
216725
216913
  else
216726
216914
  localFraction = this._spacePoint.fractionOfProjectionToLine(point0, point1, 0.0);
216727
216915
  // only consider segment extension at a parent curve endpoint, i.e. when fraction0 is 0 or fraction1 is 1
216728
- const extend0 = (fraction0 === 0) ? _CurveExtendMode__WEBPACK_IMPORTED_MODULE_6__.CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(this._extend, 0) : _CurveExtendMode__WEBPACK_IMPORTED_MODULE_6__.CurveExtendMode.None;
216729
- const extend1 = (fraction1 === 1) ? _CurveExtendMode__WEBPACK_IMPORTED_MODULE_6__.CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(this._extend, 1) : _CurveExtendMode__WEBPACK_IMPORTED_MODULE_6__.CurveExtendMode.None;
216730
- localFraction = _CurveExtendMode__WEBPACK_IMPORTED_MODULE_6__.CurveExtendOptions.correctFraction([extend0, extend1], localFraction);
216916
+ const extend0 = (fraction0 === 0) ? _CurveExtendMode__WEBPACK_IMPORTED_MODULE_5__.CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(this._extend, 0) : _CurveExtendMode__WEBPACK_IMPORTED_MODULE_5__.CurveExtendMode.None;
216917
+ const extend1 = (fraction1 === 1) ? _CurveExtendMode__WEBPACK_IMPORTED_MODULE_5__.CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(this._extend, 1) : _CurveExtendMode__WEBPACK_IMPORTED_MODULE_5__.CurveExtendMode.None;
216918
+ localFraction = _CurveExtendMode__WEBPACK_IMPORTED_MODULE_5__.CurveExtendOptions.correctFraction([extend0, extend1], localFraction);
216731
216919
  this._workPoint = point0.interpolate(localFraction, point1);
216732
216920
  const globalFraction = _Geometry__WEBPACK_IMPORTED_MODULE_4__.Geometry.interpolate(fraction0, localFraction, fraction1);
216733
216921
  this.announceCandidate(cp, globalFraction, this._workPoint);
@@ -216874,21 +217062,25 @@ __webpack_require__.r(__webpack_exports__);
216874
217062
  /* harmony export */ CurveCurveCloseApproachXY: () => (/* binding */ CurveCurveCloseApproachXY)
216875
217063
  /* harmony export */ });
216876
217064
  /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
216877
- /* harmony import */ var _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../bspline/BSplineCurve */ "../../core/geometry/lib/esm/bspline/BSplineCurve.js");
217065
+ /* harmony import */ var _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../../bspline/BSplineCurve */ "../../core/geometry/lib/esm/bspline/BSplineCurve.js");
216878
217066
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
216879
217067
  /* harmony import */ var _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../geometry3d/GeometryHandler */ "../../core/geometry/lib/esm/geometry3d/GeometryHandler.js");
216880
- /* harmony import */ var _geometry3d_GrowableFloat64Array__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../geometry3d/GrowableFloat64Array */ "../../core/geometry/lib/esm/geometry3d/GrowableFloat64Array.js");
217068
+ /* harmony import */ var _geometry3d_GrowableFloat64Array__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../geometry3d/GrowableFloat64Array */ "../../core/geometry/lib/esm/geometry3d/GrowableFloat64Array.js");
216881
217069
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
216882
- /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
216883
- /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
216884
- /* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
216885
- /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
216886
- /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
216887
- /* harmony import */ var _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../CurveChainWithDistanceIndex */ "../../core/geometry/lib/esm/curve/CurveChainWithDistanceIndex.js");
216888
- /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
216889
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
216890
- /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
216891
- /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
217070
+ /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
217071
+ /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
217072
+ /* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
217073
+ /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
217074
+ /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
217075
+ /* harmony import */ var _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../CurveChainWithDistanceIndex */ "../../core/geometry/lib/esm/curve/CurveChainWithDistanceIndex.js");
217076
+ /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
217077
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
217078
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
217079
+ /* harmony import */ var _CurvePrimitive__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
217080
+ /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
217081
+ /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
217082
+ /* harmony import */ var _ProxyCurve__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../ProxyCurve */ "../../core/geometry/lib/esm/curve/ProxyCurve.js");
217083
+ /* harmony import */ var _spiral_TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../spiral/TransitionSpiral3d */ "../../core/geometry/lib/esm/curve/spiral/TransitionSpiral3d.js");
216892
217084
  /*---------------------------------------------------------------------------------------------
216893
217085
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
216894
217086
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -216912,6 +217104,10 @@ __webpack_require__.r(__webpack_exports__);
216912
217104
 
216913
217105
 
216914
217106
 
217107
+
217108
+
217109
+
217110
+
216915
217111
  // cspell:word XYRR currentdFdX
216916
217112
  /**
216917
217113
  * Handler class for XY close approach between _geometryB and another geometry.
@@ -216929,9 +217125,6 @@ __webpack_require__.r(__webpack_exports__);
216929
217125
  */
216930
217126
  class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_1__.RecurseToCurvesGeometryHandler {
216931
217127
  _geometryB;
216932
- setGeometryB(geometryB) {
216933
- this._geometryB = geometryB;
216934
- }
216935
217128
  /**
216936
217129
  * Maximum XY distance (z is ignored). Approach larger than this is not interesting.
216937
217130
  * This is caller defined and can be undefined.
@@ -216939,6 +217132,8 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
216939
217132
  _maxDistanceToAccept;
216940
217133
  /** Squared max distance. Default is [[Geometry.smallMetricDistanceSquared]]. */
216941
217134
  _maxDistanceSquared;
217135
+ _xyTolerance;
217136
+ _newtonTolerance;
216942
217137
  /**
216943
217138
  * Start and end points of line segments that meet closest approach criteria, i.e., they are perpendicular to
216944
217139
  * both curves and their length is smaller than _maxDistanceToAccept.
@@ -216952,18 +217147,28 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
216952
217147
  /**
216953
217148
  * Constructor.
216954
217149
  * @param geometryB second curve for intersection. Saved for reference by specific handler methods.
217150
+ * @param xyTolerance optional tolerance for comparing xy points (default [[Geometry.smallMetricDistance]]).
217151
+ * @param newtonTolerance optional relative fraction tolerance for Newton iteration (default [[Geometry.smallNewtonStep]]).
216955
217152
  */
216956
- constructor(geometryB) {
217153
+ constructor(geometryB, xyTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance, newtonTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallNewtonStep) {
216957
217154
  super();
216958
- this.setGeometryB(geometryB);
217155
+ this._geometryB = geometryB instanceof _ProxyCurve__WEBPACK_IMPORTED_MODULE_4__.ProxyCurve ? geometryB.proxyCurve : geometryB;
216959
217156
  this._maxDistanceSquared = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistanceSquared;
216960
- this._results = [];
217157
+ this._xyTolerance = xyTolerance;
217158
+ this._newtonTolerance = newtonTolerance;
217159
+ const compare = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.comparePairsByPoints(xyTolerance, true);
217160
+ this._results = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.SortedArray(compare, _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.DuplicatePolicy.Retain);
216961
217161
  }
216962
217162
  /** Set the (possibly undefined) max XY distance (z is ignored) to accept. */
216963
217163
  set maxDistanceToAccept(value) {
216964
- this._maxDistanceToAccept = value;
216965
- if (this._maxDistanceToAccept !== undefined && this._maxDistanceToAccept > 0)
216966
- this._maxDistanceSquared = this._maxDistanceToAccept * this._maxDistanceToAccept;
217164
+ if (value === undefined) {
217165
+ this._maxDistanceToAccept = undefined;
217166
+ this._maxDistanceSquared = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistanceSquared;
217167
+ }
217168
+ else {
217169
+ this._maxDistanceToAccept = Math.abs(value);
217170
+ this._maxDistanceSquared = value * value;
217171
+ }
216967
217172
  }
216968
217173
  /** Access the (possibly undefined) max XY distance (z is ignored) to accept. */
216969
217174
  get maxDistanceToAccept() {
@@ -216973,9 +217178,14 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
216973
217178
  get isMaxDistanceSet() {
216974
217179
  return this._maxDistanceToAccept !== undefined && this._maxDistanceToAccept > 0;
216975
217180
  }
216976
- /** Reset the geometry and flags, leaving all other parts unchanged (and preserving accumulated intersections) */
217181
+ /**
217182
+ * Reset the geometry.
217183
+ * * Undefined inputs are ignored.
217184
+ * * All other instance data is unchanged, including accumulated intersections.
217185
+ */
216977
217186
  resetGeometry(geometryB) {
216978
- this.setGeometryB(geometryB);
217187
+ if (geometryB)
217188
+ this._geometryB = geometryB;
216979
217189
  }
216980
217190
  /** returns true if `fraction` is in [0,1] within tolerance */
216981
217191
  acceptFraction(fraction, fractionTol = 1.0e-12) {
@@ -216985,131 +217195,103 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
216985
217195
  return false;
216986
217196
  return true;
216987
217197
  }
216988
- /**
216989
- * Return the results structure for the intersection calculation, structured as an array of CurveLocationDetailPair.
216990
- * @param reinitialize if true, a new results structure is created for use by later calls.
216991
- */
216992
- grabPairedResults(reinitialize = false) {
216993
- const result = this._results;
216994
- if (reinitialize)
216995
- this._results = [];
216996
- return result;
216997
- }
216998
- /**
216999
- * If distance between pointA and pointB is less than maxDistance, record CurveLocationDetailPair which is
217000
- * the approach from pointA to pointB.
217001
- */
217002
- testAndRecordPointPairApproach(cpA, fA, pointA, cpB, fB, pointB, reversed) {
217198
+ /** Extract (and clear) the results, structured as an array of CurveLocationDetailPair. */
217199
+ grabPairedResults() {
217200
+ return this._results.extractArray();
217201
+ }
217202
+ /**
217203
+ * Create and record a close-approach pair from raw curve/fraction/point data.
217204
+ * * If points are undefined, they are computed from the fractions via `fractionToPoint`.
217205
+ * * Fractions are global (i.e., relative to the full curve, not a sub-segment).
217206
+ * * The pair is recorded only if the XY distance is within `_maxDistanceSquared`.
217207
+ * @param cpA first curve
217208
+ * @param fA global fraction on cpA
217209
+ * @param pointA point on cpA at fA, or undefined to compute from fA
217210
+ * @param cpB second curve
217211
+ * @param fB global fraction on cpB
217212
+ * @param pointB point on cpB at fB, or undefined to compute from fB
217213
+ * @param reversed if true, swap detailA and detailB before recording
217214
+ */
217215
+ testAndRecordPointPair(cpA, fA, pointA, cpB, fB, pointB, reversed) {
217216
+ if (!pointA)
217217
+ pointA = cpA.fractionToPoint(fA);
217218
+ if (!pointB)
217219
+ pointB = cpB.fractionToPoint(fB);
217003
217220
  const d2 = pointA.distanceSquaredXY(pointB);
217004
- if (d2 < this._maxDistanceSquared) {
217221
+ if (d2 <= this._maxDistanceSquared) {
217005
217222
  const d = Math.sqrt(d2);
217006
- const detailA = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPointDistance(cpA, fA, pointA, d);
217007
- const detailB = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPointDistance(cpB, fB, pointB, d);
217008
- const pair = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(detailA, detailB);
217223
+ const detailA = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPointDistance(cpA, fA, pointA, d);
217224
+ const detailB = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPointDistance(cpB, fB, pointB, d);
217225
+ detailA.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveIntervalRole.isolated);
217226
+ detailB.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveIntervalRole.isolated);
217227
+ const pair = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(detailA, detailB);
217009
217228
  if (reversed)
217010
217229
  pair.swapDetails();
217011
- this._results.push(pair);
217230
+ this._results.insert(pair);
217012
217231
  }
217013
217232
  }
217014
217233
  /**
217015
- * Create a close approach pair if XY distance is within maxDistance.
217016
- * @param localFractionA a fraction on first curve
217017
- * @param cpA the first curve
217018
- * @param fractionA0 start of the first curve
217019
- * @param fractionA1 end of the first curve
217020
- * @param localFractionB a fraction on second curve
217021
- * @param cpB the second curve
217022
- * @param fractionB0 start of the second curve
217023
- * @param fractionB1 end of the second curve
217024
- * @param reversed whether to reverse the details in the pair (e.g., so that detailB refers to geometryB).
217234
+ * Record a pre-built close-approach pair with global fractions already set.
217235
+ * * Computes and stores the XY distance on both details.
217236
+ * * The pair is recorded only if the XY distance is within `_maxDistanceSquared`.
217237
+ * @param pair details with global fractions and points already set; modified in place
217238
+ * @param reversed if true, swap detailA and detailB before recording
217025
217239
  */
217026
- recordPointWithLocalFractions(localFractionA, cpA, fractionA0, fractionA1, localFractionB, cpB, fractionB0, fractionB1, reversed) {
217027
- const globalFractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.interpolate(fractionA0, localFractionA, fractionA1);
217028
- const globalFractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.interpolate(fractionB0, localFractionB, fractionB1);
217029
- // ignore duplicate of most recent approach
217030
- const numPrevious = this._results.length;
217031
- if (numPrevious > 0) {
217032
- const oldDetailA = this._results[numPrevious - 1].detailA;
217033
- const oldDetailB = this._results[numPrevious - 1].detailB;
217034
- if (reversed) {
217035
- if (oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) &&
217036
- oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }))
217037
- return;
217038
- }
217039
- else {
217040
- if (oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) &&
217041
- oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }))
217042
- return;
217043
- }
217044
- }
217045
- const pointA = cpA.fractionToPoint(globalFractionA);
217046
- const pointB = cpB.fractionToPoint(globalFractionB);
217047
- const d2 = pointA.distanceSquaredXY(pointB);
217240
+ testAndRecordPair(pair, reversed) {
217241
+ const d2 = pair.detailA.point.distanceSquaredXY(pair.detailB.point);
217048
217242
  if (d2 > this._maxDistanceSquared)
217049
217243
  return;
217050
217244
  const d = Math.sqrt(d2);
217051
- const detailA = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPointDistance(cpA, globalFractionA, pointA, d);
217052
- const detailB = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPointDistance(cpB, globalFractionB, pointB, d);
217053
- detailA.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveIntervalRole.isolated);
217054
- detailB.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveIntervalRole.isolated);
217245
+ pair.detailA.a = pair.detailB.a = d;
217246
+ pair.detailA.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveIntervalRole.isolated);
217247
+ pair.detailB.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveIntervalRole.isolated);
217055
217248
  if (reversed)
217056
- this._results.push(new _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair(detailB, detailA));
217057
- else
217058
- this._results.push(new _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair(detailA, detailB));
217059
- }
217060
- /**
217061
- * Capture a close approach pair that has point and local fraction but not curve.
217062
- * * Record the pair, each detail modified with global fraction and input curve.
217063
- * * Pair is neither modified nor recorded if it would be a duplicate of the last recorded pair.
217064
- * @param pair details computed with local fractions
217065
- * @param cpA curveA
217066
- * @param fractionA0 global start fraction on curveA
217067
- * @param fractionA1 global end fraction on curveA
217068
- * @param cpB curveB
217069
- * @param fractionB0 global start fraction on curveB
217070
- * @param fractionB1 global end fraction on curveB
217071
- * @param reversed whether to reverse the details in the pair (e.g., so that detailB refers to geometryB).
217072
- */
217073
- capturePairWithLocalFractions(pair, cpA, fractionA0, fractionA1, cpB, fractionB0, fractionB1, reversed) {
217249
+ pair.swapDetails();
217250
+ this._results.insert(pair);
217251
+ }
217252
+ /**
217253
+ * Convert a close-approach pair from local (sub-segment) fractions to global fractions, then record it.
217254
+ * * Local fractions in the pair are interpolated into the global fraction ranges.
217255
+ * * Points are recomputed from the parent curves at the global fractions.
217256
+ * * The pair is recorded only if the XY distance is within `_maxDistanceSquared`.
217257
+ * @param pair local details (curve unspecified); modified in place with global fractions, curves, and points
217258
+ * @param cpA parent curve A
217259
+ * @param fractionA0 global fraction corresponding to local fraction 0 on curve A
217260
+ * @param fractionA1 global fraction corresponding to local fraction 1 on curve A
217261
+ * @param cpB parent curve B
217262
+ * @param fractionB0 global fraction corresponding to local fraction 0 on curve B
217263
+ * @param fractionB1 global fraction corresponding to local fraction 1 on curve B
217264
+ * @param reversed if true, swap detailA and detailB before recording
217265
+ */
217266
+ testAndRecordLocalPair(pair, cpA, fractionA0, fractionA1, cpB, fractionB0, fractionB1, reversed) {
217074
217267
  const globalFractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.interpolate(fractionA0, pair.detailA.fraction, fractionA1);
217075
217268
  const globalFractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.interpolate(fractionB0, pair.detailB.fraction, fractionB1);
217076
- // ignore duplicate of most recent pair
217077
- const numPrevious = this._results.length;
217078
- if (numPrevious > 0) {
217079
- const oldDetailA = this._results[numPrevious - 1].detailA;
217080
- const oldDetailB = this._results[numPrevious - 1].detailB;
217081
- if (reversed) {
217082
- if (oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) &&
217083
- oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }))
217084
- return;
217085
- }
217086
- else {
217087
- if (oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) &&
217088
- oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }))
217089
- return;
217090
- }
217091
- }
217092
- // recompute the points just in case
217093
- _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFraction(cpA, globalFractionA, pair.detailA);
217094
- _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFraction(cpB, globalFractionB, pair.detailB);
217095
- pair.detailA.a = pair.detailB.a = pair.detailA.point.distanceXY(pair.detailB.point);
217096
- pair.detailA.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveIntervalRole.isolated);
217097
- pair.detailB.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveIntervalRole.isolated);
217269
+ const pointA = cpA.fractionToPoint(globalFractionA);
217270
+ const pointB = cpB.fractionToPoint(globalFractionB);
217271
+ const d2 = pointA.distanceSquaredXY(pointB);
217272
+ if (d2 > this._maxDistanceSquared)
217273
+ return;
217274
+ const d = Math.sqrt(d2);
217275
+ _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPointDistance(cpA, globalFractionA, pointA, d, pair.detailA);
217276
+ _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPointDistance(cpB, globalFractionB, pointB, d, pair.detailB);
217277
+ pair.detailA.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveIntervalRole.isolated);
217278
+ pair.detailB.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveIntervalRole.isolated);
217098
217279
  if (reversed)
217099
217280
  pair.swapDetails();
217100
- this._results.push(pair);
217281
+ this._results.insert(pair);
217101
217282
  }
217102
- static updatePointToSegmentDistance(fractionA, pointA, pointB0, pointB1, fractionB, maxDistanceSquared, closestApproach) {
217283
+ /** Modify the current closest approach if the inputs are closer. */
217284
+ static updatePointToSegmentDistance(closestApproach, fractionA, pointA, fractionB, pointB0, pointB1, maxDistanceSquared) {
217103
217285
  let updated = false;
217104
217286
  if (fractionB < 0)
217105
217287
  fractionB = 0;
217106
217288
  else if (fractionB > 1)
217107
217289
  fractionB = 1;
217108
- this._workPointB = pointB0.interpolate(fractionB, pointB1, this._workPointB);
217109
- const distanceSquared = this._workPointB.distanceSquaredXY(pointA);
217290
+ const pointB = pointB0.interpolate(fractionB, pointB1, this._workPointB);
217291
+ const distanceSquared = pointB.distanceSquaredXY(pointA);
217110
217292
  if (distanceSquared <= Math.min(maxDistanceSquared, closestApproach.detailA.a)) {
217111
217293
  closestApproach.detailA.setFP(fractionA, pointA, undefined, distanceSquared);
217112
- closestApproach.detailB.setFP(fractionB, this._workPointB, undefined, distanceSquared);
217294
+ closestApproach.detailB.setFP(fractionB, pointB, undefined, distanceSquared);
217113
217295
  updated = true;
217114
217296
  }
217115
217297
  return updated;
@@ -217122,8 +217304,9 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217122
217304
  * @param b0 start point of line b
217123
217305
  * @param b1 end point of line b
217124
217306
  * @param maxDistanceSquared maximum distance squared (assumed to be positive)
217125
- * @returns the fractional (not xy) coordinates in result.x and result.y. result.x is fraction on line a.
217126
- * result.y is fraction on line b.
217307
+ * @returns a pair of details for the closest approach, or `undefined` if no approach is within `maxDistanceSquared`.
217308
+ * `detailA.fraction` is the fraction on segment a; `detailB.fraction` is the fraction on segment b. Returned
217309
+ * details store the *squared* distance in the `a` property.
217127
217310
  */
217128
217311
  static segmentSegmentBoundedApproach(a0, a1, b0, b1, maxDistanceSquared) {
217129
217312
  const ux = a1.x - a0.x;
@@ -217143,32 +217326,32 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217143
217326
  if (hab0 * hab1 < 0.0 && hba0 * hba1 < 0.0) { // true intersection, strictly within both segments
217144
217327
  const fractionA = -hba0 / (hba1 - hba0);
217145
217328
  const fractionB = -hab0 / (hab1 - hab0);
217146
- return _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPoint(undefined, fractionA, a0.interpolate(fractionA, a1)), _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPoint(undefined, fractionB, b0.interpolate(fractionB, b1)));
217329
+ return _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(undefined, fractionA, a0.interpolate(fractionA, a1)), _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(undefined, fractionB, b0.interpolate(fractionB, b1)));
217147
217330
  }
217148
217331
  // there's no intersection, so find the closest approach within maxDistance from an endpoint
217149
- const closestApproach = new _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair();
217332
+ const closestApproach = new _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair();
217150
217333
  closestApproach.detailA.a = 2 * maxDistanceSquared; // init to an approach that's too far away
217151
217334
  let reversed = false;
217152
217335
  const uu = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.hypotenuseSquaredXY(ux, uy);
217153
217336
  if (hab0 * hab0 <= maxDistanceSquared * uu) { // test distance of b0 to u
217154
217337
  const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e00x, e00y), uu, 0.0);
217155
- if (this.updatePointToSegmentDistance(0, b0, a0, a1, fractionA, maxDistanceSquared, closestApproach))
217338
+ if (this.updatePointToSegmentDistance(closestApproach, 0, b0, fractionA, a0, a1, maxDistanceSquared))
217156
217339
  reversed = true;
217157
217340
  }
217158
217341
  if (hab1 * hab1 <= maxDistanceSquared * uu) { // test distance of b1 to u
217159
217342
  const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e01x, e01y), uu, 0.0);
217160
- if (this.updatePointToSegmentDistance(1, b1, a0, a1, fractionA, maxDistanceSquared, closestApproach))
217343
+ if (this.updatePointToSegmentDistance(closestApproach, 1, b1, fractionA, a0, a1, maxDistanceSquared))
217161
217344
  reversed = true;
217162
217345
  }
217163
217346
  const vv = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.hypotenuseSquaredXY(vx, vy);
217164
217347
  if (hba0 * hba0 <= maxDistanceSquared * vv) { // test distance of a0 to v
217165
217348
  const fractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(-_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e00x, e00y), vv, 0.0);
217166
- if (this.updatePointToSegmentDistance(0, a0, b0, b1, fractionB, maxDistanceSquared, closestApproach))
217349
+ if (this.updatePointToSegmentDistance(closestApproach, 0, a0, fractionB, b0, b1, maxDistanceSquared))
217167
217350
  reversed = false;
217168
217351
  }
217169
217352
  if (hba1 * hba1 <= maxDistanceSquared * vv) { // test distance of a1 to v
217170
217353
  const fractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(-_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e10x, e10y), vv, 0.0);
217171
- if (this.updatePointToSegmentDistance(1, a1, b0, b1, fractionB, maxDistanceSquared, closestApproach))
217354
+ if (this.updatePointToSegmentDistance(closestApproach, 1, a1, fractionB, b0, b1, maxDistanceSquared))
217172
217355
  reversed = false;
217173
217356
  }
217174
217357
  if (closestApproach.detailA.a > maxDistanceSquared)
@@ -217178,160 +217361,81 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217178
217361
  return closestApproach;
217179
217362
  }
217180
217363
  /**
217181
- * Check different combination of fractions on curveA and curveB. If distance between points at 2 fractions
217182
- * is less than maxDistance, record CurveLocationDetailPair which is the approach between the 2 points.
217183
- * Optionally, record close approaches of one curve's points if they fall between the other curve's points.
217184
- * * If an input curve is a LineString3d, then the corresponding fractions must define a segment of the line string.
217364
+ * Compute closest approaches from the endpoints of each curve (if open) to the other curve.
217365
+ * Record a [[CurveLocationDetailPair]] if such a distance is less than [[maxDistance]].
217185
217366
  * @param cpA curveA
217186
- * @param fA0 fraction0 on curveA
217187
- * @param fA1 fraction1 on curveA
217188
- * @param testProjectionOnA whether to record projections of the given curveB points onto curveA
217189
217367
  * @param cpB curveB
217190
- * @param fB0 fraction0 on curveB
217191
- * @param fB1 fraction0 on curveB
217192
- * @param testProjectionOnB whether to record projections of the given curveA points onto curveB
217193
- * @param reversed whether to reverse the details in the pair (e.g., so that detailB refers to geometryB).
217194
- */
217195
- testAndRecordFractionalPairApproach(cpA, fA0, fA1, testProjectionOnA, cpB, fB0, fB1, testProjectionOnB, reversed) {
217196
- const pointA0 = cpA.fractionToPoint(fA0);
217197
- const pointA1 = cpA.fractionToPoint(fA1);
217198
- const pointB0 = cpB.fractionToPoint(fB0);
217199
- const pointB1 = cpB.fractionToPoint(fB1);
217200
- this.testAndRecordPointPairApproach(cpA, fA0, pointA0, cpB, fB0, pointB0, reversed);
217201
- this.testAndRecordPointPairApproach(cpA, fA1, pointA1, cpB, fB0, pointB0, reversed);
217202
- this.testAndRecordPointPairApproach(cpA, fA0, pointA0, cpB, fB1, pointB1, reversed);
217203
- this.testAndRecordPointPairApproach(cpA, fA1, pointA1, cpB, fB1, pointB1, reversed);
217204
- if (testProjectionOnB) {
217205
- this.testAndRecordProjection(cpA, fA0, pointA0, cpB, fB0, fB1, reversed);
217206
- this.testAndRecordProjection(cpA, fA1, pointA1, cpB, fB0, fB1, reversed);
217207
- }
217208
- if (testProjectionOnA) {
217209
- this.testAndRecordProjection(cpB, fB0, pointB0, cpA, fA0, fA1, !reversed);
217210
- this.testAndRecordProjection(cpB, fB1, pointB1, cpA, fA0, fA1, !reversed);
217211
- }
217212
- }
217213
- /**
217214
- * Return XY closest approach between a curve primitive and a point.
217215
- * Currently, this function only supports Arc3d and LineSegment.
217216
- * Note that this function doesn't handle endpoints.
217217
- */
217218
- getPointCurveClosestApproachXYNewton(curveP, pointQ) {
217219
- if (!(curveP instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_5__.Arc3d) && !(curveP instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_6__.LineSegment3d)) {
217220
- (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(false, "getPointCurveClosestApproachXYNewton only supports Arc3d and LineSegment");
217221
- }
217222
- const seeds = [0.2, 0.4, 0.6, 0.8]; // HEURISTIC: arcs have up to 4 perpendiculars; lines have only 1
217223
- const newtonEvaluator = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_7__.CurvePointCloseApproachXYRtoRD(curveP, pointQ);
217224
- const newtonSearcher = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_7__.Newton1dUnbounded(newtonEvaluator, 100); // observed convergence to 1.0e-11 in 66 iters
217225
- let minCloseApproachLength = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.largeCoordinateResult;
217226
- let minCurvePFraction;
217227
- let minPointP;
217228
- for (const seed of seeds) {
217229
- newtonSearcher.setX(seed);
217230
- if (newtonSearcher.runIterations()) {
217231
- const curvePFraction = newtonSearcher.getX();
217232
- if (this.acceptFraction(curvePFraction)) {
217233
- const pointP = curveP.fractionToPoint(curvePFraction);
217234
- const closeApproachLength = pointP.distanceSquaredXY(pointQ);
217235
- if (closeApproachLength < minCloseApproachLength) {
217236
- minCloseApproachLength = closeApproachLength;
217237
- minCurvePFraction = curvePFraction;
217238
- minPointP = pointP;
217239
- }
217240
- }
217241
- }
217242
- }
217243
- if (minCurvePFraction && minPointP)
217244
- return _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPoint(curveP, minCurvePFraction, minPointP);
217245
- return undefined;
217246
- }
217247
- /**
217248
- * Find the closest xy approach between `pointA` and `cpB`. Add the approach if it's within `fB0` and `fB1`.
217249
- * * Does not test the endpoints of `cpB`.
217250
- * * The only types supported for `cpB` are Arc3d, LineSegment3d, and LineString3d.
217251
- * * If `cpB` is a LineString3d, then the interval `[fB0, fB1]` must correspond to a segment of the line string.
217252
- */
217253
- testAndRecordProjection(cpA, fA, pointA, cpB, fB0, fB1, reversed) {
217254
- let detail;
217255
- if (cpB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d) {
217256
- const segParamsB = cpB.globalFractionToSegmentIndexAndLocalFraction(fB0 <= fB1 ? fB0 : fB1);
217257
- const segIndexB = (segParamsB.fraction < 0.999999) ? segParamsB.index : segParamsB.index + 1;
217258
- const segmentB = cpB.getIndexedSegment(segIndexB);
217259
- if (segmentB && (detail = this.getPointCurveClosestApproachXYNewton(segmentB, pointA)))
217260
- _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.convertLocalToGlobalDetail(detail, segIndexB, cpB.numEdges(), cpB);
217368
+ * @param reversed whether to reverse the details in the pair (e.g., so that detailB refers to curveA).
217369
+ */
217370
+ testAndRecordEndPointApproaches(cpA, cpB, reversed) {
217371
+ const pt = CurveCurveCloseApproachXY._workPointB;
217372
+ // in closest approach context, endpoints of full sweep arcs are artificial locations, and thus ignored
217373
+ const isClosedArc = (curve) => curve instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_6__.Arc3d && curve.sweep.isFullCircle;
217374
+ if (!isClosedArc(cpA)) {
217375
+ this.testAndRecordProjection(cpA, 0, cpA.startPoint(pt), cpB, reversed);
217376
+ this.testAndRecordProjection(cpA, 1, cpA.endPoint(pt), cpB, reversed);
217261
217377
  }
217262
- else {
217263
- detail = this.getPointCurveClosestApproachXYNewton(cpB, pointA);
217264
- }
217265
- if (detail) {
217266
- const fB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.restrictToInterval(detail.fraction, fB0, fB1);
217267
- if (fB === detail.fraction) { // if fraction is within fB0 and fB1
217268
- this.testAndRecordPointPairApproach(cpA, fA, pointA, cpB, detail.fraction, detail.point, reversed);
217269
- }
217378
+ if (!isClosedArc(cpB)) {
217379
+ this.testAndRecordProjection(cpB, 0, cpB.startPoint(pt), cpA, !reversed);
217380
+ this.testAndRecordProjection(cpB, 1, cpB.endPoint(pt), cpA, !reversed);
217270
217381
  }
217271
217382
  }
217383
+ /** Find the closest xy approach between `pointA` and `cpB`. */
217384
+ testAndRecordProjection(cpA, fA, pointA, cpB, reversed) {
217385
+ const detail = cpB.closestPointXY(pointA);
217386
+ if (detail)
217387
+ this.testAndRecordPointPair(cpA, fA, pointA, cpB, detail.fraction, detail.point, reversed);
217388
+ }
217272
217389
  /**
217273
217390
  * Compute closest xy approach of two line segments.
217274
217391
  * Filter by extension rules.
217275
217392
  * Record with fraction mapping.
217276
217393
  * * The fraction mappings allow portions of a linestring to be passed here.
217277
217394
  */
217278
- computeSegmentSegment3D(cpA, pointA0, fractionA0, pointA1, fractionA1, cpB, pointB0, fractionB0, pointB1, fractionB1, reversed) {
217395
+ computeSegmentSegment(cpA, pointA0, fractionA0, pointA1, fractionA1, cpB, pointB0, fractionB0, pointB1, fractionB1, reversed) {
217279
217396
  // compute a pair with fractions local to segments
217280
217397
  const approach = CurveCurveCloseApproachXY.segmentSegmentBoundedApproach(pointA0, pointA1, pointB0, pointB1, this._maxDistanceSquared);
217281
217398
  // adjust the pair to refer to input curves and global fractions, then record it if new
217282
217399
  if (approach) {
217283
217400
  approach.detailA.setCurve(cpA);
217284
217401
  approach.detailB.setCurve(cpB);
217285
- this.capturePairWithLocalFractions(approach, cpA, fractionA0, fractionA1, cpB, fractionB0, fractionB1, reversed);
217402
+ this.testAndRecordLocalPair(approach, cpA, fractionA0, fractionA1, cpB, fractionB0, fractionB1, reversed);
217286
217403
  }
217287
217404
  }
217288
- /** Low level dispatch of segment with segment. */
217289
- dispatchSegmentSegment(cpA, pointA0, fractionA0, pointA1, fractionA1, cpB, pointB0, fractionB0, pointB1, fractionB1, reversed) {
217290
- this.computeSegmentSegment3D(cpA, pointA0, fractionA0, pointA1, fractionA1, cpB, pointB0, fractionB0, pointB1, fractionB1, reversed);
217291
- }
217292
217405
  /**
217293
217406
  * Compute the perpendiculars between a line segment and an arc, without extending either curve.
217294
217407
  * * One or two perpendiculars will be found.
217295
217408
  * * Each perpendicular segment starts or ends on the arc where the arc tangent is parallel to the line tangent.
217296
- * * Perpendiculars from an endpoint are not explicitly computed.
217297
- * @param cpA line segment or line string; if it is a line string, then the fractions must specify a segment
217298
- * @param pointA0 start point of the segment
217299
- * @param fractionA0 fraction of the start of the segment
217300
- * @param pointA1 end point of the segment
217301
- * @param fractionA1 fraction of the end of the segment
217302
- * @param arc the arc
217303
- * @param reversed swap the details in the recorded pair (default: false)
217304
- */
217305
- allPerpendicularsSegmentArcBounded(cpA, pointA0, fractionA0, pointA1, fractionA1, arc, reversed = false) {
217306
- const dotUT = arc.vector0.crossProductStartEndXY(pointA0, pointA1);
217307
- const dotVT = arc.vector90.crossProductStartEndXY(pointA0, pointA1);
217409
+ * @param startA line segment start point
217410
+ * @param endA line segment end point
217411
+ * @param arcB the arc
217412
+ * @param announce callback to receive line and arc fractions and optional points of each perpendicular segment computed.
217413
+ */
217414
+ announceAllPerpendicularsSegmentArcBounded(startA, endA, arcB, announce) {
217415
+ const dotUT = arcB.vector0.crossProductStartEndXY(startA, endA);
217416
+ const dotVT = arcB.vector90.crossProductStartEndXY(startA, endA);
217308
217417
  const parallelRadians = Math.atan2(dotVT, dotUT);
217309
217418
  for (const radians1 of [parallelRadians, parallelRadians + Math.PI]) {
217310
- const arcPoint = arc.radiansToPoint(radians1);
217311
- const fArc = arc.sweep.radiansToSignedPeriodicFraction(radians1);
217312
- if (this.acceptFraction(fArc)) { // reject solution outside arc sweep
217313
- const fLine = _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_9__.SmallSystem.lineSegment3dXYClosestPointUnbounded(pointA0, pointA1, arcPoint);
217314
- if (fLine !== undefined && this.acceptFraction(fLine))
217315
- this.recordPointWithLocalFractions(fLine, cpA, fractionA0, fractionA1, fArc, arc, 0, 1, reversed);
217419
+ const arcPoint = arcB.radiansToPoint(radians1);
217420
+ const arcFraction = arcB.sweep.radiansToSignedPeriodicFraction(radians1);
217421
+ if (this.acceptFraction(arcFraction)) { // reject solution outside arc sweep
217422
+ const lineFraction = _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.lineSegment3dXYClosestPointUnbounded(startA, endA, arcPoint);
217423
+ if (lineFraction !== undefined && this.acceptFraction(lineFraction))
217424
+ announce(lineFraction, undefined, arcFraction, arcPoint);
217316
217425
  }
217317
217426
  }
217318
217427
  }
217319
217428
  /**
217320
- * Low level dispatch of line segment with arc.
217321
- * Find close approaches within maxDistance between a line segments (pointA0, pointA1) and an arc.
217429
+ * Find close approaches within maxDistance between a line segment and an arc.
217322
217430
  * To consider:
217323
217431
  * 1) intersection between arc and segment.
217324
- * 2) endpoints to endpoints or endpoints projection to the other curve.
217325
- * 3) arc tangent parallel to line segment (or line string).
217326
- * @param cpA curve A (line segment or line string; if it is a line string, then the fractions must specify a segment)
217327
- * @param pointA0 start point of the segment
217328
- * @param fractionA0 fraction of the start of the segment
217329
- * @param pointA1 end point of the segment
217330
- * @param fractionA1 fraction of the end of the segment
217331
- * @param arc the arc
217332
- * @param reversed whether to reverse the details in the pair (e.g., so that detailB refers to geometryB).
217333
- */
217334
- dispatchSegmentArc(cpA, pointA0, fractionA0, pointA1, fractionA1, arc, reversed) {
217432
+ * 2) endpoints to endpoints, or endpoints projection to the other curve.
217433
+ * 3) arc tangent parallel to line segment
217434
+ * @param lineA the line segment
217435
+ * @param arcB the arc
217436
+ * @param reversed whether to reverse the details in the pair (e.g., so that detailB refers to arcA).
217437
+ */
217438
+ computeSegmentArc(lineA, arcB, reversed) {
217335
217439
  // 1) intersection between arc and line segment (or string).
217336
217440
  // Suppose:
217337
217441
  // Arc: X = C + cU + sV where c = cos(theta) and s = sin(theta)
@@ -217342,56 +217446,56 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217342
217446
  // evaluate points.
217343
217447
  // project back to line.
217344
217448
  let intersectionFound = false;
217345
- const data = arc.toTransformedVectors();
217346
- const pointA0Local = pointA0;
217347
- const pointA1Local = pointA1;
217348
- const alpha = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.center, 1); // det(A0, A1, C)
217349
- const beta = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.vector0, 0); // det(A0, A1, U)
217350
- const gamma = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.tripleProductXYW(pointA0Local, 1, pointA1Local, 1, data.vector90, 0); // det(A0, A1, V)
217351
- const cosines = new _geometry3d_GrowableFloat64Array__WEBPACK_IMPORTED_MODULE_10__.GrowableFloat64Array(2);
217352
- const sines = new _geometry3d_GrowableFloat64Array__WEBPACK_IMPORTED_MODULE_10__.GrowableFloat64Array(2);
217353
- const radians = new _geometry3d_GrowableFloat64Array__WEBPACK_IMPORTED_MODULE_10__.GrowableFloat64Array(2);
217354
- const numRoots = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_11__.AnalyticRoots.appendImplicitLineUnitCircleIntersections(// solve the equation
217355
- alpha, beta, gamma, cosines, sines, radians);
217449
+ const data = arcB.toTransformedVectors();
217450
+ const alpha = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.tripleProductXYW(lineA.point0Ref, 1, lineA.point1Ref, 1, data.center, 1); // det(A0, A1, C)
217451
+ const beta = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.tripleProductXYW(lineA.point0Ref, 1, lineA.point1Ref, 1, data.vector0, 0); // det(A0, A1, U)
217452
+ const gamma = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.tripleProductXYW(lineA.point0Ref, 1, lineA.point1Ref, 1, data.vector90, 0); // det(A0, A1, V)
217453
+ const cosines = new _geometry3d_GrowableFloat64Array__WEBPACK_IMPORTED_MODULE_8__.GrowableFloat64Array(2);
217454
+ const sines = new _geometry3d_GrowableFloat64Array__WEBPACK_IMPORTED_MODULE_8__.GrowableFloat64Array(2);
217455
+ const radians = new _geometry3d_GrowableFloat64Array__WEBPACK_IMPORTED_MODULE_8__.GrowableFloat64Array(2);
217456
+ const numRoots = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_9__.AnalyticRoots.appendImplicitLineUnitCircleIntersections(alpha, beta, gamma, cosines, sines, radians);
217356
217457
  for (let i = 0; i < numRoots; i++) {
217357
217458
  const arcPoint = data.center.plus2Scaled(data.vector0, cosines.atUncheckedIndex(i), data.vector90, sines.atUncheckedIndex(i));
217358
217459
  const arcFraction = data.sweep.radiansToSignedPeriodicFraction(radians.atUncheckedIndex(i));
217359
- const lineFraction = _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_9__.SmallSystem.lineSegment3dXYClosestPointUnbounded(pointA0Local, pointA1Local, arcPoint);
217360
- // only add if the point is within the start and end fractions of both line segment and arc
217361
- if (lineFraction !== undefined && this.acceptFraction(lineFraction) && this.acceptFraction(arcFraction)) {
217362
- this.recordPointWithLocalFractions(lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed);
217363
- intersectionFound = true;
217460
+ if (this.acceptFraction(arcFraction)) { // reject solution outside arc sweep
217461
+ const lineFraction = _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.lineSegment3dXYClosestPointUnbounded(lineA.point0Ref, lineA.point1Ref, arcPoint);
217462
+ if (lineFraction !== undefined && this.acceptFraction(lineFraction)) {
217463
+ this.testAndRecordPointPair(lineA, lineFraction, undefined, arcB, arcFraction, arcPoint, reversed);
217464
+ intersectionFound = true;
217465
+ }
217364
217466
  }
217365
217467
  }
217366
217468
  if (intersectionFound)
217367
217469
  return;
217368
- // 2) endpoints to endpoints or endpoints projection to the other curve.
217369
- this.testAndRecordFractionalPairApproach(cpA, fractionA0, fractionA1, true, arc, 0, 1, true, reversed);
217370
- // 3) arc tangent parallel to line segment (or string).
217470
+ // 2) endpoints to endpoints, or endpoints projection to the other curve.
217471
+ this.testAndRecordEndPointApproaches(lineA, arcB, reversed);
217472
+ // 3) arc tangent parallel to line segment.
217371
217473
  // If line does not intersect the arc, then the closest (and/or the furthest) point on arc to the line is a
217372
217474
  // point where the tangent line on arc at that point is parallel to the line.
217373
- this.allPerpendicularsSegmentArcBounded(cpA, pointA0, fractionA0, pointA1, fractionA1, arc, reversed);
217475
+ this.announceAllPerpendicularsSegmentArcBounded(lineA.point0Ref, lineA.point1Ref, arcB, (lineFraction, linePoint, arcFraction, arcPoint) => this.testAndRecordPointPair(lineA, lineFraction, linePoint, arcB, arcFraction, arcPoint, reversed));
217374
217476
  }
217375
217477
  /**
217376
217478
  * Compute segments perpendicular to two elliptical arcs, without extending either curve.
217377
217479
  * * Perpendiculars from an endpoint are not explicitly computed.
217378
217480
  * * Intersections are also found by this search: they are reported as zero-length segments.
217481
+ * @param arcA first arc
217482
+ * @param arcB second arc
217379
217483
  * @param reversed swap the details in the recorded pair (default: false)
217380
217484
  */
217381
- allPerpendicularsArcArcBounded(arc0, arc1, reversed = false) {
217382
- const newtonEvaluator = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_7__.CurveCurveCloseApproachXYRRtoRRD(arc0, arc1);
217383
- // HEURISTIC: 2 ellipses have up to 8 perpendiculars and up to 4 intersections
217485
+ allPerpendicularsArcArcBounded(arcA, arcB, reversed = false) {
217486
+ const newtonEvaluator = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_10__.CurveCurveCloseApproachXYRRtoRRD(arcA, arcB);
217487
+ // HEURISTIC: 2 ellipses have up to 8 perpendiculars
217384
217488
  const seedDelta = 1 / 10; // denominator 9 fails the unit test
217385
217489
  const seedStart = seedDelta / 2;
217386
- const newtonSearcher = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_7__.Newton2dUnboundedWithDerivative(newtonEvaluator, 100); // observed convergence to 1.0e-11 in 49 iters
217490
+ const newtonSearcher = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_10__.Newton2dUnboundedWithDerivative(newtonEvaluator, 100); // observed convergence to 1.0e-11 in 49 iters
217387
217491
  for (let seedU = seedStart; seedU < 1; seedU += seedDelta) {
217388
217492
  for (let seedV = seedStart; seedV < 1; seedV += seedDelta) {
217389
217493
  newtonSearcher.setUV(seedU, seedV);
217390
217494
  if (newtonSearcher.runIterations()) {
217391
- const frac0 = newtonSearcher.getU();
217392
- const frac1 = newtonSearcher.getV();
217393
- if (this.acceptFraction(frac0) && this.acceptFraction(frac1)) {
217394
- this.recordPointWithLocalFractions(frac0, arc0, 0, 1, frac1, arc1, 0, 1, reversed);
217495
+ const fractionA = newtonSearcher.getU();
217496
+ const fractionB = newtonSearcher.getV();
217497
+ if (this.acceptFraction(fractionA) && this.acceptFraction(fractionB)) {
217498
+ this.testAndRecordPointPair(arcA, fractionA, undefined, arcB, fractionB, undefined, reversed);
217395
217499
  }
217396
217500
  }
217397
217501
  }
@@ -217406,33 +217510,33 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217406
217510
  if (!rangeB.intersectsRangeXY(rangeA))
217407
217511
  return;
217408
217512
  // 1) endpoints to endpoints or endpoints projection to the other curve
217409
- this.testAndRecordFractionalPairApproach(cpA, 0, 1, true, cpB, 0, 1, true, reversed);
217513
+ this.testAndRecordEndPointApproaches(cpA, cpB, reversed);
217410
217514
  // 2) perpendicular line between 2 arcs (includes intersections)
217411
217515
  this.allPerpendicularsArcArcBounded(cpA, cpB, reversed);
217412
217516
  }
217413
217517
  /** Low level dispatch of arc with (beziers of) a bspline curve */
217414
217518
  dispatchArcBsplineCurve3d(cpA, cpB, reversed) {
217415
- const ls = _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.create();
217519
+ const ls = _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d.create();
217416
217520
  cpB.emitStrokes(ls);
217417
217521
  this.computeArcLineString(cpA, ls, reversed);
217418
217522
  }
217419
217523
  /** Low level dispatch of (beziers of) a bspline curve with (beziers of) a bspline curve */
217420
217524
  dispatchBSplineCurve3dBSplineCurve3d(bcurveA, bcurveB, reversed) {
217421
- const lsA = _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.create();
217525
+ const lsA = _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d.create();
217422
217526
  bcurveA.emitStrokes(lsA);
217423
- const lsB = _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.create();
217527
+ const lsB = _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d.create();
217424
217528
  bcurveB.emitStrokes(lsB);
217425
217529
  this.computeLineStringLineString(lsA, lsB, reversed);
217426
217530
  }
217427
217531
  /** Low level dispatch of linestring with (beziers of) a bspline curve */
217428
217532
  dispatchLineStringBSplineCurve(lsA, curveB, reversed) {
217429
- const lsB = _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.create();
217533
+ const lsB = _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d.create();
217430
217534
  curveB.emitStrokes(lsB);
217431
217535
  this.computeLineStringLineString(lsA, lsB, reversed);
217432
217536
  }
217433
217537
  /** Low level dispatch of segment with (beziers of) a bspline curve */
217434
217538
  dispatchSegmentBsplineCurve(segA, curveB, reversed) {
217435
- const lsB = _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.create();
217539
+ const lsB = _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d.create();
217436
217540
  curveB.emitStrokes(lsB);
217437
217541
  this.computeSegmentLineString(segA, lsB, reversed);
217438
217542
  }
@@ -217449,7 +217553,7 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217449
217553
  const fB1 = (i + 1 === numB - 1) ? 1.0 : (i + 1) * deltaFracB; // make sure we nail the end fraction
217450
217554
  lsB.packedPoints.getPoint3dAtUncheckedPointIndex(i, pointB0);
217451
217555
  lsB.packedPoints.getPoint3dAtUncheckedPointIndex(i + 1, pointB1);
217452
- this.dispatchSegmentSegment(segA, pointA0, 0.0, pointA1, 1.0, lsB, pointB0, fB0, pointB1, fB1, reversed);
217556
+ this.computeSegmentSegment(segA, pointA0, 0.0, pointA1, 1.0, lsB, pointB0, fB0, pointB1, fB1, reversed);
217453
217557
  }
217454
217558
  }
217455
217559
  /** Detail computation for arc approaching linestring. */
@@ -217460,71 +217564,27 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217460
217564
  rangeA.expandInPlace(this._maxDistanceToAccept);
217461
217565
  if (!rangeB.intersectsRangeXY(rangeA))
217462
217566
  return;
217463
- const pointB0 = CurveCurveCloseApproachXY._workPointBB0;
217464
- const pointB1 = CurveCurveCloseApproachXY._workPointBB1;
217465
- const numB = lsB.numPoints();
217466
- if (numB > 1) {
217467
- const dfB = 1.0 / (numB - 1);
217468
- let fB0;
217469
- let fB1;
217470
- fB0 = 0.0;
217471
- lsB.pointAt(0, pointB0);
217472
- for (let ib = 1; ib < numB; ib++, pointB0.setFrom(pointB1), fB0 = fB1) {
217473
- lsB.pointAt(ib, pointB1);
217474
- fB1 = ib * dfB;
217475
- this.dispatchSegmentArc(lsB, pointB0, fB0, pointB1, fB1, arcA, !reversed);
217476
- }
217477
- }
217478
- }
217479
- /** Low level dispatch of curve collection. */
217480
- dispatchCurveCollection(geomA, geomAHandler) {
217481
- const geomB = this._geometryB; // save
217482
- if (!geomB || !geomB.children || !(geomB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_12__.CurveCollection))
217483
- return;
217484
- for (const child of geomB.children) {
217485
- this.resetGeometry(child);
217486
- geomAHandler(geomA);
217487
- }
217488
- this._geometryB = geomB; // restore
217489
- }
217490
- /** Low level dispatch to geomA given a CurveChainWithDistanceIndex in geometryB. */
217491
- dispatchCurveChainWithDistanceIndex(geomA, geomAHandler) {
217492
- if (!this._geometryB || !(this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__.CurveChainWithDistanceIndex))
217493
- return;
217494
- if (geomA instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__.CurveChainWithDistanceIndex) {
217495
- (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(false, "call handleCurveChainWithDistanceIndex(geomA) instead");
217496
- }
217497
- const index0 = this._results.length;
217498
- const geomB = this._geometryB; // save
217499
- for (const child of geomB.path.children) {
217500
- this.resetGeometry(child);
217501
- geomAHandler(geomA);
217502
- }
217503
- this.resetGeometry(geomB); // restore
217504
- this._results = _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__.CurveChainWithDistanceIndex.convertChildDetailToChainDetail(this._results, index0, undefined, geomB, true);
217505
- }
217506
- /** Double dispatch handler for strongly typed segment. */
217507
- handleLineSegment3d(segmentA) {
217508
- if (this._geometryB instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_6__.LineSegment3d) {
217509
- const segmentB = this._geometryB;
217510
- this.dispatchSegmentSegment(segmentA, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, segmentB, segmentB.point0Ref, 0.0, segmentB.point1Ref, 1.0, false);
217511
- }
217512
- else if (this._geometryB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d) {
217513
- this.computeSegmentLineString(segmentA, this._geometryB, false);
217514
- }
217515
- else if (this._geometryB instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_5__.Arc3d) {
217516
- this.dispatchSegmentArc(segmentA, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, this._geometryB, false);
217517
- }
217518
- else if (this._geometryB instanceof _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_14__.BSplineCurve3d) {
217519
- this.dispatchSegmentBsplineCurve(segmentA, this._geometryB, false);
217520
- }
217521
- else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_12__.CurveCollection) {
217522
- this.dispatchCurveCollection(segmentA, this.handleLineSegment3d.bind(this));
217523
- }
217524
- else if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__.CurveChainWithDistanceIndex) {
217525
- this.dispatchCurveChainWithDistanceIndex(segmentA, this.handleLineSegment3d.bind(this));
217567
+ const v0 = CurveCurveCloseApproachXY._workPointBB0;
217568
+ const v1 = CurveCurveCloseApproachXY._workPointBB1;
217569
+ // 1. record intersections
217570
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_12__.CurveCurve.intersectionXYPairs(arcA, false, lsB, false, this._xyTolerance);
217571
+ for (const intersection of intersections)
217572
+ this.testAndRecordPair(intersection, reversed);
217573
+ // 2. record linestring interior vertex projections onto arc
217574
+ const fStep = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(1.0, lsB.numEdges(), 0);
217575
+ for (let i = 1; i < lsB.numEdges(); ++i)
217576
+ this.testAndRecordProjection(lsB, i * fStep, lsB.pointAtUnchecked(i, v0), arcA, !reversed);
217577
+ // 3. record arc/linestring endpoint projections onto linestring/arc
217578
+ this.testAndRecordEndPointApproaches(arcA, lsB, reversed);
217579
+ // 4. record perpendiculars from within a segment to the arc
217580
+ lsB.startPoint(v0);
217581
+ for (let iSeg = 0; iSeg < lsB.numEdges(); ++iSeg, v0.setFrom(v1)) {
217582
+ lsB.pointAtUnchecked(iSeg + 1, v1);
217583
+ this.announceAllPerpendicularsSegmentArcBounded(v0, v1, arcA, (lineFraction, linePoint, arcFraction, arcPoint) => {
217584
+ const fLineString = lsB.segmentIndexAndLocalFractionToGlobalFraction(iSeg, lineFraction);
217585
+ this.testAndRecordPointPair(arcA, arcFraction, arcPoint, lsB, fLineString, linePoint, reversed);
217586
+ });
217526
217587
  }
217527
- return undefined;
217528
217588
  }
217529
217589
  /**
217530
217590
  * Set bits for comparison to range xy
@@ -217565,7 +217625,7 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217565
217625
  return;
217566
217626
  let bitB0;
217567
217627
  let bitB1;
217568
- const rangeA1 = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_15__.Range3d.createNull();
217628
+ const rangeA1 = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_13__.Range3d.createNull();
217569
217629
  const pointA0 = CurveCurveCloseApproachXY._workPointAA0;
217570
217630
  const pointA1 = CurveCurveCloseApproachXY._workPointAA1;
217571
217631
  const pointB0 = CurveCurveCloseApproachXY._workPointBB0;
@@ -217598,76 +217658,235 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217598
217658
  // DO NOT study the segment in detail if both bitB bits are on for any of the 4 planes
217599
217659
  // (i.e., no intersection between rangeA1 and the range around line segment [B0,B1])
217600
217660
  if ((bitB0 & bitB1) === 0)
217601
- this.dispatchSegmentSegment(lsA, pointA0, fA0, pointA1, fA1, lsB, pointB0, fB0, pointB1, fB1, reversed);
217661
+ this.computeSegmentSegment(lsA, pointA0, fA0, pointA1, fA1, lsB, pointB0, fB0, pointB1, fB1, reversed);
217602
217662
  }
217603
217663
  }
217604
217664
  }
217605
217665
  }
217606
217666
  }
217667
+ /** Low level dispatch of curve collection. */
217668
+ dispatchCurveCollection(geomA, geomAHandler) {
217669
+ const geomB = this._geometryB; // save
217670
+ if (!geomB || !geomB.children || !(geomB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_14__.CurveCollection))
217671
+ return;
217672
+ for (const child of geomB.children) {
217673
+ this.resetGeometry(child);
217674
+ geomAHandler(geomA);
217675
+ }
217676
+ this._geometryB = geomB; // restore
217677
+ }
217678
+ /** Low level dispatch to geomA given a CurveChainWithDistanceIndex in geometryB. */
217679
+ dispatchCurveChainWithDistanceIndex(geomA, geomAHandler) {
217680
+ if (!this._geometryB || !(this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex))
217681
+ return;
217682
+ if (geomA instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex)
217683
+ (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(false, "call handleCurveChainWithDistanceIndex(geomA) instead");
217684
+ const saveResults = this.grabPairedResults();
217685
+ const geomB = this._geometryB;
217686
+ for (const child of geomB.path.children) {
217687
+ this.resetGeometry(child);
217688
+ geomAHandler(geomA);
217689
+ }
217690
+ this.resetGeometry(geomB);
217691
+ const childResults = this._results.extractArray();
217692
+ childResults.forEach((pair) => {
217693
+ _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex.convertChildDetailToChainDetailSingle(pair, undefined, geomB);
217694
+ this._results.insert(pair);
217695
+ });
217696
+ saveResults.forEach((pair) => this._results.insert(pair));
217697
+ }
217698
+ /** Double dispatch handler for strongly typed segment. */
217699
+ handleLineSegment3d(segmentA) {
217700
+ if (this._geometryB instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_16__.LineSegment3d) {
217701
+ const segmentB = this._geometryB;
217702
+ this.computeSegmentSegment(segmentA, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, segmentB, segmentB.point0Ref, 0.0, segmentB.point1Ref, 1.0, false);
217703
+ }
217704
+ else if (this._geometryB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d) {
217705
+ this.computeSegmentLineString(segmentA, this._geometryB, false);
217706
+ }
217707
+ else if (this._geometryB instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_6__.Arc3d) {
217708
+ this.computeSegmentArc(segmentA, this._geometryB, false);
217709
+ }
217710
+ else if (this._geometryB instanceof _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_17__.BSplineCurve3d) {
217711
+ this.dispatchSegmentBsplineCurve(segmentA, this._geometryB, false);
217712
+ }
217713
+ else if (this._geometryB instanceof _spiral_TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_18__.TransitionSpiral3d) {
217714
+ this.dispatchCurveSpiral(segmentA, this._geometryB, false);
217715
+ }
217716
+ else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_14__.CurveCollection) {
217717
+ this.dispatchCurveCollection(segmentA, this.handleLineSegment3d.bind(this));
217718
+ }
217719
+ else if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex) {
217720
+ this.dispatchCurveChainWithDistanceIndex(segmentA, this.handleLineSegment3d.bind(this));
217721
+ }
217722
+ return undefined;
217723
+ }
217607
217724
  /** Double dispatch handler for strongly typed linestring. */
217608
217725
  handleLineString3d(lsA) {
217609
- if (this._geometryB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d) {
217610
- const lsB = this._geometryB;
217611
- this.computeLineStringLineString(lsA, lsB, false);
217612
- }
217613
- else if (this._geometryB instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_6__.LineSegment3d) {
217726
+ if (this._geometryB instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_16__.LineSegment3d) {
217614
217727
  this.computeSegmentLineString(this._geometryB, lsA, true);
217615
217728
  }
217616
- else if (this._geometryB instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_5__.Arc3d) {
217729
+ else if (this._geometryB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d) {
217730
+ this.computeLineStringLineString(lsA, this._geometryB, false);
217731
+ }
217732
+ else if (this._geometryB instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_6__.Arc3d) {
217617
217733
  this.computeArcLineString(this._geometryB, lsA, true);
217618
217734
  }
217619
- else if (this._geometryB instanceof _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_14__.BSplineCurve3d) {
217735
+ else if (this._geometryB instanceof _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_17__.BSplineCurve3d) {
217620
217736
  this.dispatchLineStringBSplineCurve(lsA, this._geometryB, false);
217621
217737
  }
217622
- else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_12__.CurveCollection) {
217738
+ else if (this._geometryB instanceof _spiral_TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_18__.TransitionSpiral3d) {
217739
+ this.dispatchCurveSpiral(lsA, this._geometryB, false);
217740
+ }
217741
+ else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_14__.CurveCollection) {
217623
217742
  this.dispatchCurveCollection(lsA, this.handleLineString3d.bind(this));
217624
217743
  }
217625
- else if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__.CurveChainWithDistanceIndex) {
217744
+ else if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex) {
217626
217745
  this.dispatchCurveChainWithDistanceIndex(lsA, this.handleLineString3d.bind(this));
217627
217746
  }
217628
217747
  return undefined;
217629
217748
  }
217630
217749
  /** Double dispatch handler for strongly typed arc. */
217631
- handleArc3d(arc0) {
217632
- if (this._geometryB instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_6__.LineSegment3d) {
217633
- this.dispatchSegmentArc(this._geometryB, this._geometryB.point0Ref, 0.0, this._geometryB.point1Ref, 1.0, arc0, true);
217750
+ handleArc3d(arcA) {
217751
+ if (this._geometryB instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_16__.LineSegment3d) {
217752
+ this.computeSegmentArc(this._geometryB, arcA, true);
217634
217753
  }
217635
- else if (this._geometryB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d) {
217636
- this.computeArcLineString(arc0, this._geometryB, false);
217754
+ else if (this._geometryB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d) {
217755
+ this.computeArcLineString(arcA, this._geometryB, false);
217637
217756
  }
217638
- else if (this._geometryB instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_5__.Arc3d) {
217639
- this.dispatchArcArc(arc0, this._geometryB, false);
217757
+ else if (this._geometryB instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_6__.Arc3d) {
217758
+ this.dispatchArcArc(arcA, this._geometryB, false);
217640
217759
  }
217641
- else if (this._geometryB instanceof _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_14__.BSplineCurve3d) {
217642
- this.dispatchArcBsplineCurve3d(arc0, this._geometryB, false);
217760
+ else if (this._geometryB instanceof _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_17__.BSplineCurve3d) {
217761
+ this.dispatchArcBsplineCurve3d(arcA, this._geometryB, false);
217643
217762
  }
217644
- else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_12__.CurveCollection) {
217645
- this.dispatchCurveCollection(arc0, this.handleArc3d.bind(this));
217763
+ else if (this._geometryB instanceof _spiral_TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_18__.TransitionSpiral3d) {
217764
+ this.dispatchCurveSpiral(arcA, this._geometryB, false);
217646
217765
  }
217647
- else if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__.CurveChainWithDistanceIndex) {
217648
- this.dispatchCurveChainWithDistanceIndex(arc0, this.handleArc3d.bind(this));
217766
+ else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_14__.CurveCollection) {
217767
+ this.dispatchCurveCollection(arcA, this.handleArc3d.bind(this));
217768
+ }
217769
+ else if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex) {
217770
+ this.dispatchCurveChainWithDistanceIndex(arcA, this.handleArc3d.bind(this));
217649
217771
  }
217650
217772
  return undefined;
217651
217773
  }
217652
217774
  /** Double dispatch handler for strongly typed bspline curve. */
217653
- handleBSplineCurve3d(curve) {
217654
- if (this._geometryB instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_6__.LineSegment3d) {
217655
- this.dispatchSegmentBsplineCurve(this._geometryB, curve, true);
217775
+ handleBSplineCurve3d(curveA) {
217776
+ if (this._geometryB instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_16__.LineSegment3d) {
217777
+ this.dispatchSegmentBsplineCurve(this._geometryB, curveA, true);
217656
217778
  }
217657
- else if (this._geometryB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d) {
217658
- this.dispatchLineStringBSplineCurve(this._geometryB, curve, true);
217779
+ else if (this._geometryB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d) {
217780
+ this.dispatchLineStringBSplineCurve(this._geometryB, curveA, true);
217659
217781
  }
217660
- else if (this._geometryB instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_5__.Arc3d) {
217661
- this.dispatchArcBsplineCurve3d(this._geometryB, curve, true);
217782
+ else if (this._geometryB instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_6__.Arc3d) {
217783
+ this.dispatchArcBsplineCurve3d(this._geometryB, curveA, true);
217662
217784
  }
217663
- else if (this._geometryB instanceof _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_14__.BSplineCurve3dBase) {
217664
- this.dispatchBSplineCurve3dBSplineCurve3d(curve, this._geometryB, false);
217785
+ else if (this._geometryB instanceof _bspline_BSplineCurve__WEBPACK_IMPORTED_MODULE_17__.BSplineCurve3dBase) {
217786
+ this.dispatchBSplineCurve3dBSplineCurve3d(curveA, this._geometryB, false);
217665
217787
  }
217666
- else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_12__.CurveCollection) {
217667
- this.dispatchCurveCollection(curve, this.handleBSplineCurve3d.bind(this));
217788
+ else if (this._geometryB instanceof _spiral_TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_18__.TransitionSpiral3d) {
217789
+ this.dispatchCurveSpiral(curveA, this._geometryB, false);
217668
217790
  }
217669
- else if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__.CurveChainWithDistanceIndex) {
217670
- this.dispatchCurveChainWithDistanceIndex(curve, this.handleBSplineCurve3d.bind(this));
217791
+ else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_14__.CurveCollection) {
217792
+ this.dispatchCurveCollection(curveA, this.handleBSplineCurve3d.bind(this));
217793
+ }
217794
+ else if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex) {
217795
+ this.dispatchCurveChainWithDistanceIndex(curveA, this.handleBSplineCurve3d.bind(this));
217796
+ }
217797
+ return undefined;
217798
+ }
217799
+ /**
217800
+ * Process seeds for xy close approach between the curve and spiral.
217801
+ * * Refine each result via Newton iteration. If it doesn't converge, remove it.
217802
+ * @param seeds The initial seed results to refine.
217803
+ * @param curveA The other curve primitive. May also be a transition spiral.
217804
+ * @param spiralB The transition spiral.
217805
+ * @param reversed whether `spiralB` data is in `detailA` of each recorded pair, and `curveA` data in `detailB`.
217806
+ */
217807
+ refineSpiralResultsByNewton(seeds, curveA, spiralB, reversed = false) {
217808
+ const xyMatchingFunction = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_10__.CurveCurveCloseApproachXYRRtoRRD(curveA, spiralB);
217809
+ const newtonSearcher = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_10__.Newton2dUnboundedWithDerivative(xyMatchingFunction, 50, this._newtonTolerance); // seen: 47
217810
+ for (const seed of seeds) {
217811
+ const detailA = reversed ? seed.detailB : seed.detailA;
217812
+ const detailB = reversed ? seed.detailA : seed.detailB;
217813
+ (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(detailB.curve instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d, "Caller has discretized the spiral");
217814
+ newtonSearcher.setUV(detailA.fraction, detailB.fraction); // use linestring fraction as spiral param; it generally yields a closer point than fractional length!
217815
+ if (newtonSearcher.runIterations()) {
217816
+ const fractionA = newtonSearcher.getU();
217817
+ const fractionB = newtonSearcher.getV();
217818
+ if (this.acceptFraction(fractionA) && this.acceptFraction(fractionB))
217819
+ this.testAndRecordPointPair(curveA, fractionA, undefined, spiralB, fractionB, undefined, reversed);
217820
+ } // ignore failure to converge
217821
+ }
217822
+ }
217823
+ /**
217824
+ * Append stroke points and return the line string.
217825
+ * * This is a convenient wrapper for [[CurvePrimitive.emitStrokes]] but the analogous instance method cannot be added
217826
+ * to that class due to the ensuing recursion with subclass [[LineString3d]].
217827
+ * @param options options for stroking the instance curve.
217828
+ * @param result object to receive appended stroke points; if omitted, a new object is created, populated, and returned.
217829
+ */
217830
+ strokeCurve(curve, options, result) {
217831
+ const ls = result ? result : _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d.create();
217832
+ curve.emitStrokes(ls, options);
217833
+ return ls;
217834
+ }
217835
+ /** Find and return the close approaches between curveA and the discretization of curveB. */
217836
+ computeDiscreteCloseApproachResults(curveA, lsB, reversed) {
217837
+ const maxDist = this.maxDistanceToAccept;
217838
+ const saveResults = this.grabPairedResults(); // save current results
217839
+ const geomB = this._geometryB;
217840
+ this.maxDistanceToAccept = maxDist ? maxDist * 1.2 : undefined; // HEURISTIC: allow slack for Newton seeds
217841
+ this.resetGeometry(curveA);
217842
+ this.handleLineString3d(lsB); // populate empty results with discrete solutions
217843
+ if (!reversed) {
217844
+ // handleLineString3d put lsB data into detailA, so if we aren't reversing, we need to swap
217845
+ for (const result of this._results)
217846
+ result.swapDetails();
217847
+ }
217848
+ this.resetGeometry(geomB);
217849
+ this.maxDistanceToAccept = maxDist;
217850
+ const discreteResults = this._results.extractArray();
217851
+ saveResults.forEach((pair) => this._results.insert(pair)); // restore current results
217852
+ return discreteResults;
217853
+ }
217854
+ /**
217855
+ * Compute the XY close approach of a curve and a spiral.
217856
+ * @param curveA curve to find its close approach with spiralB. May also be a transition spiral.
217857
+ * @param spiralB transition spiral to find its close approach with curveA.
217858
+ * @param reversed whether `spiralB` data will be recorded in `detailA` of each result, and `curveA` data in `detailB`.
217859
+ */
217860
+ dispatchCurveSpiral(curveA, spiralB, reversed) {
217861
+ // explicit search for intersections (Newton converges too slowly on DirectSpiral3d tangent intersections)
217862
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_12__.CurveCurve.intersectionXYPairs(curveA, false, spiralB, false, this._xyTolerance);
217863
+ for (const intersection of intersections)
217864
+ this.testAndRecordPair(intersection, reversed);
217865
+ // append seeds computed by solving the discretized spiral close approach problem, then refine the seeds via Newton
217866
+ let cpA = curveA;
217867
+ if (curveA instanceof _spiral_TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_18__.TransitionSpiral3d)
217868
+ cpA = this.strokeCurve(curveA);
217869
+ const cpB = this.strokeCurve(spiralB);
217870
+ const seeds = this.computeDiscreteCloseApproachResults(cpA, cpB, reversed);
217871
+ this.refineSpiralResultsByNewton(seeds, curveA, spiralB, reversed);
217872
+ if (curveA instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_11__.LineString3d) { // explicitly test corners (where Newton converges too slowly)
217873
+ const fStep = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(1.0, curveA.numEdges(), 0);
217874
+ const v0 = CurveCurveCloseApproachXY._workPointBB0;
217875
+ for (let i = 1; i < curveA.numEdges(); ++i)
217876
+ this.testAndRecordProjection(curveA, i * fStep, curveA.pointAtUnchecked(i, v0), spiralB, reversed);
217877
+ }
217878
+ this.testAndRecordEndPointApproaches(curveA, spiralB, reversed);
217879
+ }
217880
+ /** Double dispatch handler for strongly typed spiral curve. */
217881
+ handleTransitionSpiral(spiral) {
217882
+ if (this._geometryB instanceof _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex) {
217883
+ this.dispatchCurveChainWithDistanceIndex(spiral, this.handleTransitionSpiral.bind(this));
217884
+ }
217885
+ else if (this._geometryB instanceof _CurvePrimitive__WEBPACK_IMPORTED_MODULE_19__.CurvePrimitive) {
217886
+ this.dispatchCurveSpiral(this._geometryB, spiral, true);
217887
+ }
217888
+ else if (this._geometryB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_14__.CurveCollection) {
217889
+ this.dispatchCurveCollection(spiral, this.handleTransitionSpiral.bind(this));
217671
217890
  }
217672
217891
  return undefined;
217673
217892
  }
@@ -217675,7 +217894,11 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
217675
217894
  handleCurveChainWithDistanceIndex(chain) {
217676
217895
  super.handleCurveChainWithDistanceIndex(chain);
217677
217896
  // if _geometryB is also a CurveChainWithDistanceIndex, it will already have been converted by dispatchCurveChainWithDistanceIndex
217678
- this._results = _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_13__.CurveChainWithDistanceIndex.convertChildDetailToChainDetail(this._results, 0, chain, undefined, true);
217897
+ const childResults = this._results.extractArray();
217898
+ childResults.forEach((pair) => {
217899
+ _CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_15__.CurveChainWithDistanceIndex.convertChildDetailToChainDetailSingle(pair, chain, undefined);
217900
+ this._results.insert(pair);
217901
+ });
217679
217902
  }
217680
217903
  /** Double dispatch handler for strongly typed homogeneous bspline curve .. */
217681
217904
  handleBSplineCurve3dH(_curve) {
@@ -218700,12 +218923,11 @@ class CurveCurveIntersectXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTE
218700
218923
  }
218701
218924
  /**
218702
218925
  * Process tail of `this._results` for xy-intersections between the curve and spiral.
218703
- * * If a result is not already an intersection, refine it via Newton iteration unless it doesn't converge, in which
218704
- * case remove it.
218926
+ * * Refine each result via Newton iteration. If it doesn't converge, remove it.
218705
218927
  * @param curveA The other curve primitive. May also be a transition spiral.
218706
218928
  * @param spiralB The transition spiral.
218707
218929
  * @param index0 index of first entry in tail of `this._results` to refine.
218708
- * @param reversed Whether `spiralB` data is in `detailA` of each recorded pair, and `curveA` data in `detailB`.
218930
+ * @param reversed whether `spiralB` data is in `detailA` of each recorded pair, and `curveA` data in `detailB`.
218709
218931
  */
218710
218932
  refineSpiralResultsByNewton(curveA, spiralB, index0, reversed = false) {
218711
218933
  if (index0 >= this._results.length)
@@ -218715,25 +218937,16 @@ class CurveCurveIntersectXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTE
218715
218937
  const maxIterations = 100; // observed 73 iterations to convergence in tangent case
218716
218938
  const newtonSearcher = new _numerics_Newton__WEBPACK_IMPORTED_MODULE_13__.Newton2dUnboundedWithDerivative(xyMatchingFunction, maxIterations);
218717
218939
  const fractionTol = 2 * newtonSearcher.stepSizeTolerance; // relative cluster diameter for Newton convergence
218718
- const comparePairs = (a, b) => {
218719
- (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(() => a.detailA.curve === b.detailA.curve && a.detailB.curve === b.detailB.curve, "pairs are compatible");
218720
- // sort on either fraction, then on the point, using appropriate tolerances for each
218721
- if (_Geometry__WEBPACK_IMPORTED_MODULE_4__.Geometry.isAlmostEqualNumber(a.detailA.fraction, b.detailA.fraction, fractionTol))
218722
- return 0;
218723
- if (a.detailA.point.isAlmostEqualXY(b.detailA.point, this._coincidentGeometryContext.tolerance))
218724
- return 0;
218725
- return a.detailA.fraction - b.detailA.fraction;
218726
- };
218727
- const myResults = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.SortedArray(comparePairs, _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.DuplicatePolicy.Retain);
218728
- const pushToMyResults = (cpA, fA, cpB, fB) => {
218729
- const detailA = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveLocationDetail.createCurveFractionPoint(cpA, fA, cpA.fractionToPoint(fA));
218730
- const detailB = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveLocationDetail.createCurveFractionPoint(cpB, fB, cpB.fractionToPoint(fB));
218940
+ const compare = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveLocationDetailPair.comparePairsByFractions(fractionTol, this._coincidentGeometryContext.tolerance, true);
218941
+ const myResults = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.SortedArray(compare, _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.DuplicatePolicy.Retain);
218942
+ const pushToMyResults = (cpA, fA, pA, cpB, fB, pB) => {
218943
+ const detailA = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveLocationDetail.createCurveFractionPoint(cpA, fA, pA);
218944
+ const detailB = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveLocationDetail.createCurveFractionPoint(cpB, fB, pB);
218731
218945
  detailA.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveIntervalRole.isolated);
218732
218946
  detailB.setIntervalRole(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveIntervalRole.isolated);
218733
- let pushed = false;
218734
- myResults.insert(new _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveLocationDetailPair(reversed ? detailB : detailA, reversed ? detailA : detailB), () => pushed = true);
218735
- return pushed;
218947
+ myResults.insert(new _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_7__.CurveLocationDetailPair(reversed ? detailB : detailA, reversed ? detailA : detailB));
218736
218948
  };
218949
+ const strictTolerance = this._coincidentGeometryContext.tolerance * 0.0001;
218737
218950
  for (let i = index0; i < this._results.length; i++) {
218738
218951
  const pair = this._results[i];
218739
218952
  const detailA = reversed ? pair.detailB : pair.detailA;
@@ -218742,18 +218955,16 @@ class CurveCurveIntersectXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTE
218742
218955
  const extendA0 = reversed ? this._extendB0 : this._extendA0;
218743
218956
  const extendA1 = reversed ? this._extendB1 : this._extendA1;
218744
218957
  newtonSearcher.setUV(detailA.fraction, detailB.fraction); // use linestring fraction as spiral param; it generally yields a closer point than fractional length!
218745
- if (newtonSearcher.runIterations()) {
218746
- const fractionA = newtonSearcher.getU();
218747
- const fractionB = newtonSearcher.getV();
218748
- if (this.acceptFraction(extendA0, fractionA, extendA1) && this.acceptFraction(false, fractionB, false))
218749
- pushToMyResults(curveA, fractionA, spiralB, fractionB);
218750
- }
218751
- else if (newtonSearcher.numIterations < 10) {
218752
- // if Newton failed early due to vanishing (partial) derivative, check for a root there
218753
- const fractionA = newtonSearcher.getU();
218754
- const fractionB = newtonSearcher.getV();
218755
- if (curveA.fractionToPoint(fractionA).isAlmostEqualXY(spiralB.fractionToPoint(fractionB), this._coincidentGeometryContext.tolerance))
218756
- pushToMyResults(curveA, fractionA, spiralB, fractionB);
218958
+ let converged = newtonSearcher.runIterations();
218959
+ const fractionA = newtonSearcher.getU();
218960
+ const fractionB = newtonSearcher.getV();
218961
+ if (this.acceptFraction(extendA0, fractionA, extendA1) && this.acceptFraction(false, fractionB, false)) {
218962
+ const pointA = curveA.fractionToPoint(fractionA, CurveCurveIntersectXY._workPointA0);
218963
+ const pointB = spiralB.fractionToPoint(fractionB, CurveCurveIntersectXY._workPointB0);
218964
+ if (!converged) // Newton may have found close points even if it didn't converge parametrically
218965
+ converged = pointA.isAlmostEqualXY(pointB, strictTolerance); // we can afford to be choosy
218966
+ if (converged)
218967
+ pushToMyResults(curveA, fractionA, pointA, spiralB, fractionB, pointB);
218757
218968
  }
218758
218969
  }
218759
218970
  this._results.splice(index0, this._results.length - index0, ...myResults.extractArray());
@@ -218798,7 +219009,7 @@ class CurveCurveIntersectXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTE
218798
219009
  */
218799
219010
  appendDiscreteIntersectionResults(curveA, extendA0, extendA1, lsB, reversed) {
218800
219011
  const i0 = this._results.length;
218801
- // handleLineString3d requires us to swap geometries:
219012
+ // handleLineString3d requires us to swap geometries
218802
219013
  const geomB = this._geometryB;
218803
219014
  const extendB0 = this._extendB0;
218804
219015
  const extendB1 = this._extendB1;
@@ -221436,54 +221647,6 @@ class MultiChainCollector {
221436
221647
  }
221437
221648
 
221438
221649
 
221439
- /***/ }),
221440
-
221441
- /***/ "../../core/geometry/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js":
221442
- /*!*************************************************************************************!*\
221443
- !*** ../../core/geometry/lib/esm/curve/internalContexts/NewtonRtoRStrokeHandler.js ***!
221444
- \*************************************************************************************/
221445
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
221446
-
221447
- "use strict";
221448
- __webpack_require__.r(__webpack_exports__);
221449
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
221450
- /* harmony export */ NewtonRtoRStrokeHandler: () => (/* binding */ NewtonRtoRStrokeHandler)
221451
- /* harmony export */ });
221452
- /* harmony import */ var _numerics_Newton__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../numerics/Newton */ "../../core/geometry/lib/esm/numerics/Newton.js");
221453
- /*---------------------------------------------------------------------------------------------
221454
- * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
221455
- * See LICENSE.md in the project root for license terms and full copyright notice.
221456
- *--------------------------------------------------------------------------------------------*/
221457
- /** @packageDocumentation
221458
- * @module Curve
221459
- */
221460
-
221461
- /**
221462
- * Intermediate class for managing the parentCurve announcements from an IStrokeHandler.
221463
- * @internal
221464
- */
221465
- class NewtonRtoRStrokeHandler extends _numerics_Newton__WEBPACK_IMPORTED_MODULE_0__.NewtonEvaluatorRtoR {
221466
- _parentCurvePrimitive;
221467
- constructor() {
221468
- super();
221469
- this._parentCurvePrimitive = undefined;
221470
- }
221471
- /**
221472
- * Retain the parentCurvePrimitive.
221473
- * * Calling this method tells the handler that the parent curve is to be used for detail searches.
221474
- * * Example: Transition spiral search is based on linestring first, then the exact spiral.
221475
- * * Example: CurveChainWithDistanceIndex does NOT do this announcement; the constituents act independently.
221476
- */
221477
- startParentCurvePrimitive(curve) {
221478
- this._parentCurvePrimitive = curve;
221479
- }
221480
- /** Forget the parentCurvePrimitive */
221481
- endParentCurvePrimitive(_curve) {
221482
- this._parentCurvePrimitive = undefined;
221483
- }
221484
- }
221485
-
221486
-
221487
221650
  /***/ }),
221488
221651
 
221489
221652
  /***/ "../../core/geometry/lib/esm/curve/internalContexts/PlaneAltitudeRangeContext.js":
@@ -225493,8 +225656,9 @@ __webpack_require__.r(__webpack_exports__);
225493
225656
  /* harmony export */ });
225494
225657
  /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
225495
225658
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
225659
+ /* harmony import */ var _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../geometry3d/GeometryHandler */ "../../core/geometry/lib/esm/geometry3d/GeometryHandler.js");
225496
225660
  /* harmony import */ var _geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geometry3d/Segment1d */ "../../core/geometry/lib/esm/geometry3d/Segment1d.js");
225497
- /* harmony import */ var _internalContexts_CurveLengthContext__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../internalContexts/CurveLengthContext */ "../../core/geometry/lib/esm/curve/internalContexts/CurveLengthContext.js");
225661
+ /* harmony import */ var _internalContexts_CurveLengthContext__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../internalContexts/CurveLengthContext */ "../../core/geometry/lib/esm/curve/internalContexts/CurveLengthContext.js");
225498
225662
  /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
225499
225663
  /* harmony import */ var _StrokeOptions__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
225500
225664
  /* harmony import */ var _AustralianRailCorpXYEvaluator__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./AustralianRailCorpXYEvaluator */ "../../core/geometry/lib/esm/curve/spiral/AustralianRailCorpXYEvaluator.js");
@@ -225524,6 +225688,7 @@ __webpack_require__.r(__webpack_exports__);
225524
225688
 
225525
225689
 
225526
225690
 
225691
+
225527
225692
  /**
225528
225693
  * DirectSpiral3d acts like a TransitionSpiral3d for serialization purposes, but implements spiral types that have
225529
225694
  * "direct" xy calculations without the integrations required for IntegratedSpiral3d.
@@ -225901,11 +226066,16 @@ class DirectSpiral3d extends _TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_1__.Tr
225901
226066
  }
225902
226067
  /**
225903
226068
  * Add strokes from this spiral to `dest`.
225904
- * * Line strings will usually stroke as just their points.
225905
- * * If maxEdgeLength is given, this will sub-stroke within the linestring -- not what we want.
226069
+ * @param options optional stroking options. Pass `undefined` to return cached strokes.
225906
226070
  */
225907
226071
  emitStrokes(dest, options) {
225908
- this.activeStrokes.emitStrokes(dest, options);
226072
+ if (!options)
226073
+ this.activeStrokes.emitStrokes(dest, options);
226074
+ else {
226075
+ const stroker = new _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_12__.UniformStrokeCollector(this);
226076
+ this.emitStrokableParts(stroker, options);
226077
+ stroker.claimLineString(dest);
226078
+ }
225909
226079
  }
225910
226080
  /** Emit stroke fragments to `dest` handler. */
225911
226081
  emitStrokableParts(dest, options) {
@@ -225915,7 +226085,7 @@ class DirectSpiral3d extends _TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_1__.Tr
225915
226085
  // hack: specify the extended range so we can compute length of an extended spiral
225916
226086
  let globalFraction0 = 0.0;
225917
226087
  let globalFraction1 = 1.0;
225918
- if (dest instanceof _internalContexts_CurveLengthContext__WEBPACK_IMPORTED_MODULE_12__.CurveLengthContext) {
226088
+ if (dest instanceof _internalContexts_CurveLengthContext__WEBPACK_IMPORTED_MODULE_13__.CurveLengthContext) {
225919
226089
  if (dest.getFraction0 < 0.0)
225920
226090
  globalFraction0 = dest.getFraction0;
225921
226091
  if (dest.getFraction1 > 1.0)
@@ -226021,15 +226191,16 @@ __webpack_require__.r(__webpack_exports__);
226021
226191
  /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
226022
226192
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
226023
226193
  /* harmony import */ var _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../geometry3d/AngleSweep */ "../../core/geometry/lib/esm/geometry3d/AngleSweep.js");
226194
+ /* harmony import */ var _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../geometry3d/GeometryHandler */ "../../core/geometry/lib/esm/geometry3d/GeometryHandler.js");
226024
226195
  /* harmony import */ var _geometry3d_Matrix3d__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../geometry3d/Matrix3d */ "../../core/geometry/lib/esm/geometry3d/Matrix3d.js");
226025
- /* harmony import */ var _geometry3d_Plane3dByOriginAndVectors__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../geometry3d/Plane3dByOriginAndVectors */ "../../core/geometry/lib/esm/geometry3d/Plane3dByOriginAndVectors.js");
226196
+ /* harmony import */ var _geometry3d_Plane3dByOriginAndVectors__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../geometry3d/Plane3dByOriginAndVectors */ "../../core/geometry/lib/esm/geometry3d/Plane3dByOriginAndVectors.js");
226026
226197
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
226027
- /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
226198
+ /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
226028
226199
  /* harmony import */ var _geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../geometry3d/Segment1d */ "../../core/geometry/lib/esm/geometry3d/Segment1d.js");
226029
- /* harmony import */ var _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../geometry3d/Transform */ "../../core/geometry/lib/esm/geometry3d/Transform.js");
226200
+ /* harmony import */ var _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../geometry3d/Transform */ "../../core/geometry/lib/esm/geometry3d/Transform.js");
226030
226201
  /* harmony import */ var _numerics_Quadrature__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../numerics/Quadrature */ "../../core/geometry/lib/esm/numerics/Quadrature.js");
226031
226202
  /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
226032
- /* harmony import */ var _StrokeOptions__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
226203
+ /* harmony import */ var _StrokeOptions__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
226033
226204
  /* harmony import */ var _NormalizedTransition__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./NormalizedTransition */ "../../core/geometry/lib/esm/curve/spiral/NormalizedTransition.js");
226034
226205
  /* harmony import */ var _TransitionConditionalProperties__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./TransitionConditionalProperties */ "../../core/geometry/lib/esm/curve/spiral/TransitionConditionalProperties.js");
226035
226206
  /* harmony import */ var _TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TransitionSpiral3d */ "../../core/geometry/lib/esm/curve/spiral/TransitionSpiral3d.js");
@@ -226055,6 +226226,7 @@ __webpack_require__.r(__webpack_exports__);
226055
226226
 
226056
226227
 
226057
226228
 
226229
+
226058
226230
  /**
226059
226231
  * An IntegratedSpiral3d is a curve defined by integrating its curvature.
226060
226232
  * * The first integral of curvature (with respect to distance along the curve) is the bearing angle (in radians).
@@ -226310,11 +226482,16 @@ class IntegratedSpiral3d extends _TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_1_
226310
226482
  }
226311
226483
  /**
226312
226484
  * Add strokes from this spiral to `dest`.
226313
- * * Linestrings will usually stroke as just their points.
226314
- * * If maxEdgeLength is given, this will sub-stroke within the linestring -- not what we want.
226485
+ * @param options optional stroking options. Pass `undefined` to return cached strokes.
226315
226486
  */
226316
226487
  emitStrokes(dest, options) {
226317
- this.activeStrokes.emitStrokes(dest, options);
226488
+ if (!options)
226489
+ this.activeStrokes.emitStrokes(dest, options);
226490
+ else {
226491
+ const stroker = new _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_11__.UniformStrokeCollector(this);
226492
+ this.emitStrokableParts(stroker, options);
226493
+ stroker.claimLineString(dest);
226494
+ }
226318
226495
  }
226319
226496
  /** Emit stroke fragments to `dest` handler. */
226320
226497
  emitStrokableParts(dest, options) {
@@ -226343,7 +226520,7 @@ class IntegratedSpiral3d extends _TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_1_
226343
226520
  numStroke = options.applyMinStrokesPerPrimitive(numStroke);
226344
226521
  }
226345
226522
  else {
226346
- numStroke = _StrokeOptions__WEBPACK_IMPORTED_MODULE_11__.StrokeOptions.applyAngleTol(undefined, 4, this.bearing01.sweepRadians);
226523
+ numStroke = _StrokeOptions__WEBPACK_IMPORTED_MODULE_12__.StrokeOptions.applyAngleTol(undefined, 4, this.bearing01.sweepRadians);
226347
226524
  }
226348
226525
  return numStroke;
226349
226526
  }
@@ -226401,7 +226578,7 @@ class IntegratedSpiral3d extends _TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_1_
226401
226578
  /** Evaluate curve point and derivative with respect to fraction. */
226402
226579
  fractionToPointAndDerivative(activeFraction, result) {
226403
226580
  const globalFraction = this.activeFractionInterval.fractionToPoint(activeFraction);
226404
- result = result ? result : _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_12__.Ray3d.createZero();
226581
+ result = result ? result : _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_13__.Ray3d.createZero();
226405
226582
  this.fractionToPoint(activeFraction, result.origin);
226406
226583
  const radians = this.globalFractionToBearingRadians(globalFraction);
226407
226584
  const a = this._arcLength01 * this.activeFractionInterval.signedDelta();
@@ -226411,7 +226588,7 @@ class IntegratedSpiral3d extends _TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_1_
226411
226588
  /** Return the frenet frame at fractional position. */
226412
226589
  fractionToFrenetFrame(activeFraction, result) {
226413
226590
  const globalFraction = this.activeFractionInterval.fractionToPoint(activeFraction);
226414
- result = result ? result : _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_13__.Transform.createIdentity();
226591
+ result = result ? result : _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_14__.Transform.createIdentity();
226415
226592
  result.origin.setFrom(this.fractionToPoint(activeFraction));
226416
226593
  _geometry3d_Matrix3d__WEBPACK_IMPORTED_MODULE_5__.Matrix3d.createRigidFromMatrix3d(this.localToWorld.matrix, _Geometry__WEBPACK_IMPORTED_MODULE_10__.AxisOrder.XYZ, result.matrix);
226417
226594
  const radians = this.globalFractionToBearingRadians(globalFraction);
@@ -226433,13 +226610,13 @@ class IntegratedSpiral3d extends _TransitionSpiral3d__WEBPACK_IMPORTED_MODULE_1_
226433
226610
  const radians = this.globalFractionToBearingRadians(globalFraction);
226434
226611
  const c = Math.cos(radians);
226435
226612
  const s = Math.sin(radians);
226436
- const delta = this.activeFractionInterval.signedDelta();
226613
+ const delta = this._arcLength01 * this.activeFractionInterval.signedDelta();
226437
226614
  const a = delta;
226438
226615
  const b = a * delta;
226439
226616
  const vectorX = this.localToWorld.matrix.multiplyXY(a * c, a * s);
226440
226617
  const vectorY = this.localToWorld.matrix.multiplyXY(-b * s, b * c);
226441
226618
  vectorY.scaleInPlace(this.globalFractionToCurvature(globalFraction));
226442
- return _geometry3d_Plane3dByOriginAndVectors__WEBPACK_IMPORTED_MODULE_14__.Plane3dByOriginAndVectors.createCapture(origin, vectorX, vectorY, result);
226619
+ return _geometry3d_Plane3dByOriginAndVectors__WEBPACK_IMPORTED_MODULE_15__.Plane3dByOriginAndVectors.createCapture(origin, vectorX, vectorY, result);
226443
226620
  }
226444
226621
  /** Second step of double dispatch: call `handler.handleTransitionSpiral(this)`. */
226445
226622
  dispatchToGeometryHandler(handler) {
@@ -228150,9 +228327,13 @@ class AngleSweep {
228150
228327
  result.setStartEndRadians(startRadians, endRadians);
228151
228328
  return result;
228152
228329
  }
228153
- /** Return the AngleSweep obtained by subtracting radians from the start and end angles of this sweep. */
228330
+ /** Return the AngleSweep obtained by adding `radians` to the start and end angles of this sweep. */
228331
+ clonePlusRadians(radians) {
228332
+ return new AngleSweep(this._radians0 + radians, this._radians1 + radians);
228333
+ }
228334
+ /** Return the AngleSweep obtained by subtracting `radians` from the start and end angles of this sweep. */
228154
228335
  cloneMinusRadians(radians) {
228155
- return new AngleSweep(this._radians0 - radians, this._radians1 - radians);
228336
+ return this.clonePlusRadians(-radians);
228156
228337
  }
228157
228338
  /** Create an AngleSweep from start and end angles given in degrees. */
228158
228339
  static createStartEndDegrees(startDegrees = 0, endDegrees = 360, result) {
@@ -231517,12 +231698,24 @@ __webpack_require__.r(__webpack_exports__);
231517
231698
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
231518
231699
  /* harmony export */ GeometryHandler: () => (/* binding */ GeometryHandler),
231519
231700
  /* harmony export */ NullGeometryHandler: () => (/* binding */ NullGeometryHandler),
231520
- /* harmony export */ RecurseToCurvesGeometryHandler: () => (/* binding */ RecurseToCurvesGeometryHandler)
231701
+ /* harmony export */ RecurseToCurvesGeometryHandler: () => (/* binding */ RecurseToCurvesGeometryHandler),
231702
+ /* harmony export */ UniformStrokeCollector: () => (/* binding */ UniformStrokeCollector)
231521
231703
  /* harmony export */ });
231704
+ /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
231705
+ /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
231706
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
231707
+ /* harmony import */ var _Point3dVector3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
231522
231708
  /*---------------------------------------------------------------------------------------------
231523
231709
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
231524
231710
  * See LICENSE.md in the project root for license terms and full copyright notice.
231525
231711
  *--------------------------------------------------------------------------------------------*/
231712
+ /** @packageDocumentation
231713
+ * @module ArraysAndInterfaces
231714
+ */
231715
+
231716
+
231717
+
231718
+
231526
231719
  /**
231527
231720
  * `GeometryHandler` defines the base abstract methods for double-dispatch geometry computation.
231528
231721
  * * User code that wants to handle one or all of the commonly known geometry types implements a handler class.
@@ -231795,6 +231988,76 @@ class RecurseToCurvesGeometryHandler extends GeometryHandler {
231795
231988
  return undefined;
231796
231989
  }
231797
231990
  }
231991
+ /**
231992
+ * A handler that generates uniformly distributed fractions for stroking a CurvePrimitive.
231993
+ * * [[claimFractions]] returns the fractions
231994
+ * * [[claimLineString]] returns the strokes
231995
+ * @public
231996
+ */
231997
+ class UniformStrokeCollector {
231998
+ _curve;
231999
+ _fractions;
232000
+ /** Constructor. Curve is optional and not needed for [[claimFractions]]. */
232001
+ constructor(cp, fractionTol = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallFraction) {
232002
+ this._curve = undefined;
232003
+ if (cp)
232004
+ this.startCurvePrimitive(cp);
232005
+ this._fractions = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.OrderedSet((a, b) => (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.compareWithTolerance)(a, b, fractionTol));
232006
+ }
232007
+ /** Announce a parent curve primitive (ignored). */
232008
+ startParentCurvePrimitive(_c) { }
232009
+ /** Announce the curve primitive that will be described in subsequent calls. */
232010
+ startCurvePrimitive(cp) {
232011
+ this._curve = cp;
232012
+ }
232013
+ /** Announce a single fraction. */
232014
+ announcePointTangent(_p, f, _v) {
232015
+ this._fractions.add(f);
232016
+ }
232017
+ /** Announce uniformly distributed fractions in the fractional interval. */
232018
+ announceIntervalForUniformStepStrokes(_c, numStrokes, f0, f1) {
232019
+ if (numStrokes < 1)
232020
+ numStrokes = 1;
232021
+ this._fractions.add(f0);
232022
+ const df = 1.0 / numStrokes;
232023
+ for (let i = 1; i < numStrokes; i++)
232024
+ this._fractions.add(_Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.interpolate(f0, i * df, f1));
232025
+ this._fractions.add(f1);
232026
+ }
232027
+ /** Request primary geometry to avoid cached strokes. */
232028
+ needPrimaryGeometryForStrokes() {
232029
+ return true;
232030
+ }
232031
+ /** Announce the fractional span of the segment. */
232032
+ announceSegmentInterval(_c, _p0, _p1, _numStrokes, f0, f1) {
232033
+ this._fractions.add(f0);
232034
+ this._fractions.add(f1);
232035
+ }
232036
+ /** Announce that all data about the curve has been announced (ignored). */
232037
+ endCurvePrimitive(_c) { }
232038
+ /** Announce that all data about the parent curve has been announced (ignored). */
232039
+ endParentCurvePrimitive(_c) { }
232040
+ /** Retrieve the collected fractions, optionally removing 0 and 1 first. */
232041
+ claimFractions(remove01 = false) {
232042
+ if (remove01) {
232043
+ this._fractions.delete(0);
232044
+ this._fractions.delete(1);
232045
+ }
232046
+ return [...this._fractions];
232047
+ }
232048
+ /** Create a [[LineString3d]] by evaluating the curve at the collected fractions. */
232049
+ claimLineString(result) {
232050
+ if (!this._curve)
232051
+ return undefined;
232052
+ result ??= _curve_LineString3d__WEBPACK_IMPORTED_MODULE_2__.LineString3d.create();
232053
+ const pt = _Point3dVector3d__WEBPACK_IMPORTED_MODULE_3__.Point3d.create();
232054
+ for (const f of this._fractions) {
232055
+ result.addPoint(this._curve.fractionToPoint(f, pt));
232056
+ result.addFraction(f);
232057
+ }
232058
+ return result;
232059
+ }
232060
+ }
231798
232061
 
231799
232062
 
231800
232063
  /***/ }),
@@ -232367,21 +232630,31 @@ class GrowableXYArray extends _IndexedXYCollection__WEBPACK_IMPORTED_MODULE_0__.
232367
232630
  _data;
232368
232631
  /** Number of xy tuples (not floats) in the array. */
232369
232632
  _xyInUse;
232370
- /** Capacity in xy tuples. (not floats). */
232633
+ /** Capacity in xy tuples (not floats). */
232371
232634
  _xyCapacity;
232372
- /** Multiplier used by ensureCapacity to expand requested reallocation size. */
232635
+ /** Multiplier used by [[ensureCapacity]] to expand requested reallocation size. */
232373
232636
  _growthFactor;
232374
232637
  /**
232375
- * Construct a new GrowablePoint2d array.
232376
- * @param numPoints initial capacity in xy tuples (default 8).
232377
- * @param growthFactor used by ensureCapacity to expand requested reallocation size (default 1.5).
232378
- * @param data optional pre-existing Float64Array to use as the backing memory. If supplied, numPoints is ignored.
232638
+ * Construct a new growable array.
232639
+ * @param numPoints initial capacity in xy tuples. Default value is 8.
232640
+ * @param growthFactor used by [[ensureCapacity]] to expand requested reallocation size. Default value is 1.5.
232641
+ * For no expansion, use 1.
232642
+ * @param data optional array to serve as the point source. If `data` is supplied, `numPoints` is reinterpreted as
232643
+ * the initial point count, defaulting to and bounded above by the array's point capacity. If a subsequent [[push]]
232644
+ * would exceed the array's capacity, a new Float64Array of the same buffer type is allocated and filled.
232379
232645
  */
232380
- constructor(numPoints = 8, growthFactor, data) {
232646
+ constructor(numPoints, growthFactor, data) {
232381
232647
  super();
232382
- this._data = data || new Float64Array(numPoints * 2); // 2 values per point
232383
- this._xyInUse = 0;
232384
- this._xyCapacity = data ? data.length / 2 : numPoints;
232648
+ if (data) {
232649
+ this._xyCapacity = data.length / 2;
232650
+ this._xyInUse = Math.min(numPoints ?? Infinity, this._xyCapacity);
232651
+ this._data = data;
232652
+ }
232653
+ else {
232654
+ this._xyCapacity = numPoints ?? 8;
232655
+ this._xyInUse = 0;
232656
+ this._data = new Float64Array(2 * this._xyCapacity); // 2 values per point
232657
+ }
232385
232658
  this._growthFactor = (undefined !== growthFactor && growthFactor >= 1.0) ? growthFactor : 1.5;
232386
232659
  }
232387
232660
  /**
@@ -233105,19 +233378,29 @@ class GrowableXYZArray extends _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_0_
233105
233378
  _xyzInUse;
233106
233379
  /** Capacity in xyz triples (not floats). */
233107
233380
  _xyzCapacity;
233108
- /** Multiplier used by ensureCapacity to expand requested reallocation size. */
233381
+ /** Multiplier used by [[ensureCapacity]] to expand requested reallocation size. */
233109
233382
  _growthFactor;
233110
233383
  /**
233111
- * Construct a new GrowablePoint3d array.
233112
- * @param numPoints initial capacity in xyz triples (default 8).
233113
- * @param growthFactor used by ensureCapacity to expand requested reallocation size (default 1.5).
233114
- * @param data optional pre-existing Float64Array to use as the backing memory. If supplied, numPoints is ignored.
233384
+ * Construct a new growable array.
233385
+ * @param numPoints initial capacity in xyz tuples. Default value is 8.
233386
+ * @param growthFactor used by [[ensureCapacity]] to expand requested reallocation size. Default value is 1.5.
233387
+ * For no expansion, use 1.
233388
+ * @param data optional array to serve as the point source. If `data` is supplied, `numPoints` is reinterpreted as
233389
+ * the initial point count, defaulting to and bounded above by the array's point capacity. If a subsequent [[push]]
233390
+ * would exceed the array's capacity, a new Float64Array of the same buffer type is allocated and filled.
233115
233391
  */
233116
- constructor(numPoints = 8, growthFactor, data) {
233392
+ constructor(numPoints, growthFactor, data) {
233117
233393
  super();
233118
- this._data = data || new Float64Array(numPoints * 3); // 3 values per point
233119
- this._xyzInUse = 0;
233120
- this._xyzCapacity = data ? data.length / 3 : numPoints;
233394
+ if (data) {
233395
+ this._xyzCapacity = data.length / 3;
233396
+ this._xyzInUse = Math.min(numPoints ?? Infinity, this._xyzCapacity);
233397
+ this._data = data;
233398
+ }
233399
+ else {
233400
+ this._xyzCapacity = numPoints ?? 8;
233401
+ this._xyzInUse = 0;
233402
+ this._data = new Float64Array(3 * this._xyzCapacity); // 3 values per point
233403
+ }
233121
233404
  this._growthFactor = (undefined !== growthFactor && growthFactor >= 1.0) ? growthFactor : 1.5;
233122
233405
  }
233123
233406
  /**
@@ -233172,7 +233455,7 @@ class GrowableXYZArray extends _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_0_
233172
233455
  return this._data;
233173
233456
  }
233174
233457
  /**
233175
- * If necessary, increase the capacity to the new number of points. Current coordinates and point count (length) are
233458
+ * If necessary, increase the capacity to the new number of points. Current coordinates and point count (length) are
233176
233459
  * unchanged.
233177
233460
  */
233178
233461
  ensureCapacity(pointCapacity, applyGrowthFactor = true) {
@@ -235606,17 +235889,18 @@ class Matrix3d {
235606
235889
  target.setColumn(_Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.axisOrderToAxis(axisOrder, 0), vectorU);
235607
235890
  target.setColumn(_Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.axisOrderToAxis(axisOrder, 1), vectorV);
235608
235891
  target.setColumn(_Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.axisOrderToAxis(axisOrder, 2), vectorW);
235892
+ target.inverseState = InverseMatrixState.unknown;
235609
235893
  return target;
235610
235894
  }
235611
235895
  /**
235612
235896
  * Create a new orthogonal matrix (perpendicular columns, unit length, transpose is inverse).
235613
- * * `vectorA1 = Normalized vectorA` is placed in the column specified by **first** letter in
235897
+ * * `vectorA1 = Normalized vectorA` is placed in the column specified by the **first** letter in
235614
235898
  * the AxisOrder name.
235615
- * * Normalized `vectorC1 = vectorA1 cross vectorB` is placed in the column specified by **third**
235899
+ * * Normalized `vectorC1 = vectorA1 cross vectorB` is placed in the column specified by the **third**
235616
235900
  * letter in the AxisOrder name.
235617
- * * Normalized `vectorC1 cross vectorA` is placed in the column specified by **second**
235901
+ * * Normalized `vectorC1 cross vectorA` is placed in the column specified by the **second**
235618
235902
  * letter in the AxisOrder name.
235619
- * * This function internally uses createShuffledColumns.
235903
+ * * This function internally uses [[createShuffledColumns]].
235620
235904
  */
235621
235905
  static createRigidFromColumns(vectorA, vectorB, axisOrder, result) {
235622
235906
  const vectorA1 = vectorA.normalize();
@@ -252865,7 +253149,7 @@ class UnivariateBezier extends BezierCoffs {
252865
253149
  * that the final iteration will clean it up to nearly machine precision.
252866
253150
  * @returns final fraction of iteration if converged. undefined if iteration failed to converge.
252867
253151
  */
252868
- runNewton(startFraction, tolerance = 1.0e-11) {
253152
+ runNewton(startFraction, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallNewtonStep) {
252869
253153
  const derivativeFactor = this.order - 1;
252870
253154
  let numConverged = 0;
252871
253155
  let u = startFraction;
@@ -254434,6 +254718,7 @@ __webpack_require__.r(__webpack_exports__);
254434
254718
  /* harmony export */ NewtonEvaluatorRRtoRRD: () => (/* binding */ NewtonEvaluatorRRtoRRD),
254435
254719
  /* harmony export */ NewtonEvaluatorRtoR: () => (/* binding */ NewtonEvaluatorRtoR),
254436
254720
  /* harmony export */ NewtonEvaluatorRtoRD: () => (/* binding */ NewtonEvaluatorRtoRD),
254721
+ /* harmony export */ NewtonRtoRStrokeHandler: () => (/* binding */ NewtonRtoRStrokeHandler),
254437
254722
  /* harmony export */ SimpleNewton: () => (/* binding */ SimpleNewton)
254438
254723
  /* harmony export */ });
254439
254724
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
@@ -254451,6 +254736,12 @@ __webpack_require__.r(__webpack_exports__);
254451
254736
 
254452
254737
 
254453
254738
  // cspell:word currentdFdX XYRR
254739
+ // A note on differences between using derivatives vs. approximate derivatives for Newton:
254740
+ // * Converged values are the same under both schemes.
254741
+ // * With derivatives, Newton convergence is quadratic rather than power 1.62 with approximate derivatives.
254742
+ // * With approximate derivatives:
254743
+ // - the extra iterative cost is incidental for low iteration counts, and may even be offset by simpler computation.
254744
+ // - the step choice is not based on serious analysis, so could be problematic.
254454
254745
  /**
254455
254746
  * Base class for Newton iterations in various dimensions.
254456
254747
  * Dimension-specific classes carry all dimension-related data and answer generalized queries from this base class.
@@ -254464,12 +254755,12 @@ class AbstractNewtonIterator {
254464
254755
  * it is expected that a first "accept" for (say) 10 to 14 digit step will be followed by another
254465
254756
  * iteration. A well behaved newton would then hypothetically double the number of digits to
254466
254757
  * 20 to 28. Since the IEEE double only carries 16 digits, this second-convergence step will
254467
- * typically achieve full precision.
254468
- * @param successiveConvergenceTarget number of successive convergences required for acceptance.
254758
+ * typically achieve full precision. Default [[Geometry.smallNewtonStep]].
254759
+ * @param successiveConvergenceTarget number of successive convergences required for acceptance. Default 2.
254469
254760
  * @param maxIterations max number of iterations. A typical newton step converges in 3 to 6 iterations.
254470
- * Allow 15 to 20 to catch difficult cases.
254761
+ * Allow 15 to 20 to catch difficult cases. Default 15.
254471
254762
  */
254472
- constructor(stepSizeTolerance = 1.0e-11, successiveConvergenceTarget = 2, maxIterations = 15) {
254763
+ constructor(stepSizeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallNewtonStep, successiveConvergenceTarget = 2, maxIterations = 15) {
254473
254764
  this._stepSizeTolerance = stepSizeTolerance;
254474
254765
  this._successiveConvergenceTarget = successiveConvergenceTarget;
254475
254766
  this._maxIterations = maxIterations;
@@ -254484,6 +254775,12 @@ class AbstractNewtonIterator {
254484
254775
  _maxIterations;
254485
254776
  /** Number of iterations (incremented at each step). */
254486
254777
  numIterations = 0;
254778
+ /** Get the relative tolerance for comparing iterations in [[testConvergence]]. */
254779
+ get stepSizeTolerance() {
254780
+ return this._stepSizeTolerance;
254781
+ }
254782
+ /** Smallest iterate size difference in later iterations. */
254783
+ _leastDelta = Number.MAX_VALUE;
254487
254784
  /**
254488
254785
  * Test if a step is converged.
254489
254786
  * * Convergence is accepted with enough (_successiveConvergenceTarget) small steps (according to _stepSizeTolerance)
@@ -254491,6 +254788,10 @@ class AbstractNewtonIterator {
254491
254788
  * @param delta step size as reported by currentStepSize.
254492
254789
  */
254493
254790
  testConvergence(delta) {
254791
+ if (this.cacheCandidate && delta < this._leastDelta && this.numIterations > 0.5 * this._maxIterations) {
254792
+ this._leastDelta = delta;
254793
+ this.cacheCandidate();
254794
+ }
254494
254795
  if (Math.abs(delta) < this._stepSizeTolerance) {
254495
254796
  this._numAccepted++;
254496
254797
  return this._numAccepted >= this._successiveConvergenceTarget;
@@ -254508,13 +254809,16 @@ class AbstractNewtonIterator {
254508
254809
  runIterations() {
254509
254810
  this._numAccepted = 0;
254510
254811
  this.numIterations = 0;
254812
+ this._leastDelta = Number.MAX_VALUE;
254511
254813
  while (this.numIterations++ < this._maxIterations && this.computeStep()) {
254512
- if (this.testConvergence(this.currentStepSize()) && this.applyCurrentStep(true)) {
254513
- // console.log("iter: " + this.numIterations); // print number of Newton iterations for debug
254814
+ if (this.testConvergence(this.currentStepSize())) {
254815
+ this.applyCurrentStep(true);
254514
254816
  return true;
254515
254817
  }
254516
254818
  this.applyCurrentStep(false);
254517
254819
  }
254820
+ if (this.restoreCandidate && this.numIterations >= this._maxIterations && Math.abs(this.currentStepSize()) > this._leastDelta)
254821
+ this.restoreCandidate(); // we may have ended up in a late cycle; return our best guess
254518
254822
  return false;
254519
254823
  }
254520
254824
  }
@@ -254556,7 +254860,6 @@ class Newton1dUnbounded extends AbstractNewtonIterator {
254556
254860
  /** Set the independent variable, i.e., x_n. */
254557
254861
  setX(x) {
254558
254862
  this._currentX = x;
254559
- return true;
254560
254863
  }
254561
254864
  /** Get the independent variable, i.e., x_n. */
254562
254865
  getX() {
@@ -254568,8 +254871,7 @@ class Newton1dUnbounded extends AbstractNewtonIterator {
254568
254871
  }
254569
254872
  /** Move the current X by the just-computed step, i.e., `x_n - dx`. */
254570
254873
  applyCurrentStep() {
254571
- // console.log(this._currentX - this._currentStep); // print approximations for debug
254572
- return this.setX(this._currentX - this._currentStep);
254874
+ this.setX(this._currentX - this._currentStep);
254573
254875
  }
254574
254876
  /** Compute the univariate newton step dx. */
254575
254877
  computeStep() {
@@ -254595,6 +254897,30 @@ class NewtonEvaluatorRtoR {
254595
254897
  /** Most recent function evaluation, i.e., f(x_n). */
254596
254898
  currentF;
254597
254899
  }
254900
+ /**
254901
+ * Intermediate class for managing the parentCurve announcements from an IStrokeHandler.
254902
+ * @internal
254903
+ */
254904
+ class NewtonRtoRStrokeHandler extends NewtonEvaluatorRtoR {
254905
+ _parentCurvePrimitive;
254906
+ constructor() {
254907
+ super();
254908
+ this._parentCurvePrimitive = undefined;
254909
+ }
254910
+ /**
254911
+ * Retain the parentCurvePrimitive.
254912
+ * * Calling this method tells the handler that the parent curve is to be used for detail searches.
254913
+ * * Example: Transition spiral search is based on linestring first, then the exact spiral.
254914
+ * * Example: CurveChainWithDistanceIndex does NOT do this announcement; the constituents act independently.
254915
+ */
254916
+ startParentCurvePrimitive(curve) {
254917
+ this._parentCurvePrimitive = curve;
254918
+ }
254919
+ /** Forget the parentCurvePrimitive */
254920
+ endParentCurvePrimitive(_curve) {
254921
+ this._parentCurvePrimitive = undefined;
254922
+ }
254923
+ }
254598
254924
  /**
254599
254925
  * Newton iteration for a univariate function, using approximate derivatives.
254600
254926
  * To approximate the derivatives we use a small step `h`, i.e., `f'(x_n) = (f(x_n + h) - f(x_n)) / h`.
@@ -254626,7 +254952,6 @@ class Newton1dUnboundedApproximateDerivative extends AbstractNewtonIterator {
254626
254952
  /** Set the independent variable, i.e., x_n. */
254627
254953
  setX(x) {
254628
254954
  this._currentX = x;
254629
- return true;
254630
254955
  }
254631
254956
  /** Get the independent variable, i.e., x_n. */
254632
254957
  getX() {
@@ -254634,8 +254959,7 @@ class Newton1dUnboundedApproximateDerivative extends AbstractNewtonIterator {
254634
254959
  }
254635
254960
  /** Move the current X by the just-computed step, i.e., `x_n - dx`. */
254636
254961
  applyCurrentStep() {
254637
- // console.log(this._currentX - this._currentStep); // print approximations for debug
254638
- return this.setX(this._currentX - this._currentStep);
254962
+ this.setX(this._currentX - this._currentStep);
254639
254963
  }
254640
254964
  /** Univariate newton step dx, computed with approximate derivative. */
254641
254965
  computeStep() {
@@ -254700,9 +255024,11 @@ class Newton2dUnboundedWithDerivative extends AbstractNewtonIterator {
254700
255024
  /**
254701
255025
  * Constructor for 2D newton iteration with derivatives.
254702
255026
  * @param func function that returns both function value and derivative.
255027
+ * @param maxIterations max number of iterations. Default 15.
255028
+ * @param stepSizeTolerance tolerance to consider a single step converged. Default [[Geometry.smallNewtonStep]].
254703
255029
  */
254704
- constructor(func, maxIterations) {
254705
- super(undefined, undefined, maxIterations);
255030
+ constructor(func, maxIterations, stepSizeTolerance) {
255031
+ super(stepSizeTolerance, undefined, maxIterations);
254706
255032
  this._func = func;
254707
255033
  this._currentStep = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_2__.Vector2d.createZero();
254708
255034
  this._currentUV = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_2__.Point2d.createZero();
@@ -254710,7 +255036,6 @@ class Newton2dUnboundedWithDerivative extends AbstractNewtonIterator {
254710
255036
  /** Set the current uv parameters, i.e., `X_n = (u_n, v_n)`. */
254711
255037
  setUV(u, v) {
254712
255038
  this._currentUV.set(u, v);
254713
- return true;
254714
255039
  }
254715
255040
  /** Get the current u parameter of X_n, i.e., u_n. */
254716
255041
  getU() {
@@ -254720,14 +255045,9 @@ class Newton2dUnboundedWithDerivative extends AbstractNewtonIterator {
254720
255045
  getV() {
254721
255046
  return this._currentUV.y;
254722
255047
  }
254723
- /** Get the relative tolerance for comparing iterations in [[testConvergence]]. */
254724
- get stepSizeTolerance() {
254725
- return this._stepSizeTolerance;
254726
- }
254727
255048
  /** Update the current uv parameter by currentStep, i.e., compute `X_{n+1} := X_n - dX = (u_n - du, v_n - dv)`. */
254728
255049
  applyCurrentStep() {
254729
- // console.log("(" + (this._currentUV.x - this._currentStep.x) + "," + (this._currentUV.y - this._currentStep.y) + ")");
254730
- return this.setUV(this._currentUV.x - this._currentStep.x, this._currentUV.y - this._currentStep.y);
255050
+ this.setUV(this._currentUV.x - this._currentStep.x, this._currentUV.y - this._currentStep.y);
254731
255051
  }
254732
255052
  /**
254733
255053
  * Evaluate the functions and derivatives at `X_n = (u_n, v_n)`, and solve the Jacobian matrix equation to
@@ -254751,6 +255071,20 @@ class Newton2dUnboundedWithDerivative extends AbstractNewtonIterator {
254751
255071
  currentStepSize() {
254752
255072
  return _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.maxAbsXY(this._currentStep.x / (1.0 + Math.abs(this._currentUV.x)), this._currentStep.y / (1.0 + Math.abs(this._currentUV.y)));
254753
255073
  }
255074
+ /** Candidate solution cache. */
255075
+ _cachedUV;
255076
+ /** The current late iterate has the least delta encountered. Remember it. */
255077
+ cacheCandidate() {
255078
+ if (this._cachedUV)
255079
+ this._cachedUV.setFrom(this._currentUV);
255080
+ else
255081
+ this._cachedUV = this._currentUV.clone();
255082
+ }
255083
+ /** Set Newton result to the cached candidate. */
255084
+ restoreCandidate() {
255085
+ if (this._cachedUV)
255086
+ this.setUV(this._cachedUV.x, this._cachedUV.y);
255087
+ }
254754
255088
  }
254755
255089
  /**
254756
255090
  * SimpleNewton has static methods for newton methods with evaluated functions presented as immediate arguments
@@ -254770,7 +255104,7 @@ class SimpleNewton {
254770
255104
  static runNewton1D(x, func, derivative, absoluteTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallFloatingPoint) {
254771
255105
  let numConverged = 0;
254772
255106
  let tolerance;
254773
- const relTol = 1.0e-11;
255107
+ const relTol = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallNewtonStep;
254774
255108
  for (let iteration = 0; iteration < 20; iteration++) {
254775
255109
  const f = func(x);
254776
255110
  const df = derivative(x);
@@ -265344,20 +265678,20 @@ class PolyfaceQuery {
265344
265678
  return -2;
265345
265679
  }
265346
265680
  /**
265347
- * Test for convex volume by dihedral angle tests on all edges.
265348
- * * This tests if all dihedral angles of the mesh are positive.
265349
- * * In a closed solid, this is a strong test for overall mesh convexity with outward facing normals.
265350
- * * See [[dihedralAngleSummary]] for the definition of "dihedral angle".
265351
- * * With `ignoreBoundaries` true, this may be a useful test when all the facets are in a single edge-connected
265352
- * component, such as a pyramid with no underside.
265353
- * * It is not a correct test if there are multiple, disjoint components.
265354
- * * Take the above-mentioned pyramid with no underside.
265355
- * * Within the same mesh, have a second pyramid placed to the side, still facing upward.
265356
- * * The angles will pass the dihedral convexity test, but the composite thing surely is not convex.
265357
- * @param source mesh.
265358
- * @param ignoreBoundaries if `true` ignore simple boundary edges, i.e., allow unclosed meshes. Default is `false`.
265359
- * @returns true if all dihedral angles of the mesh are positive.
265360
- */
265681
+ * Test for convex volume by dihedral angle tests on all edges.
265682
+ * * This tests if all dihedral angles of the mesh are positive.
265683
+ * * In a closed solid, this is a strong test for overall mesh convexity with outward facing normals.
265684
+ * * See [[dihedralAngleSummary]] for the definition of "dihedral angle".
265685
+ * * With `ignoreBoundaries` true, this may be a useful test when all the facets are in a single edge-connected
265686
+ * component, such as a pyramid with no underside.
265687
+ * * It is not a correct test if there are multiple, disjoint components.
265688
+ * * Take the above-mentioned pyramid with no underside.
265689
+ * * Within the same mesh, have a second pyramid placed to the side, still facing upward.
265690
+ * * The angles will pass the dihedral convexity test, but the composite thing surely is not convex.
265691
+ * @param source mesh.
265692
+ * @param ignoreBoundaries if `true` ignore simple boundary edges, i.e., allow unclosed meshes. Default is `false`.
265693
+ * @returns true if all dihedral angles of the mesh are positive.
265694
+ */
265361
265695
  static isConvexByDihedralAngleCount(source, ignoreBoundaries = false) {
265362
265696
  return this.dihedralAngleSummary(source, ignoreBoundaries) > 0;
265363
265697
  }
@@ -277047,8 +277381,8 @@ class DgnSpiralTypeQueries {
277047
277381
  [12, "biquadratic"],
277048
277382
  [13, "cosine"],
277049
277383
  [14, "sine"],
277050
- [15, "Viennese"],
277051
- [16, "weightedViennese"],
277384
+ [15, "Viennese"], // not supported
277385
+ [16, "weightedViennese"], // not supported
277052
277386
  [50, "WesternAustralian"],
277053
277387
  [51, "Czech"],
277054
277388
  [52, "AustralianRailCorp"],
@@ -284123,7 +284457,7 @@ class HalfEdge {
284123
284457
  * @param bridgeMask mask preset on bridge edges (default is [[HalfEdgeMask.BRIDGE_EDGE]]).
284124
284458
  */
284125
284459
  isSplitWasherFace(bridgeMask = HalfEdgeMask.BRIDGE_EDGE) {
284126
- if (!this.countMaskAroundFace(HalfEdgeMask.BRIDGE_EDGE))
284460
+ if (!this.countMaskAroundFace(bridgeMask))
284127
284461
  return false;
284128
284462
  const bridges = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.OrderedSet((a, b) => a.id - b.id);
284129
284463
  let node = this;
@@ -325418,7 +325752,7 @@ var loadLanguages = instance.loadLanguages;
325418
325752
  /***/ ((module) => {
325419
325753
 
325420
325754
  "use strict";
325421
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.9.0-dev.7","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s webpackWorkers && npm run -s copy:workers && npm run -s copy:draco","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:workers":"cpx \\"./lib/workers/webpack/parse-imdl-worker.js\\" ./lib/public/scripts","copy:draco":"cpx \\"./node_modules/@loaders.gl/draco/dist/libs/*\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts && npm run -s extract","extract":"betools extract --fileExt=ts --extractFrom=./src/test/example-code --recursive --out=../../generated-docs/extract","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","lint-deprecation":"eslint --fix -f visualstudio --no-inline-config -c ../../common/config/eslint/eslint.config.deprecation-policy.js \\"./src/**/*.ts\\"","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run webpackTestWorker && vitest --run","cover":"npm run webpackTestWorker && vitest --run","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2 && npm run -s webpackTestWorker","webpackTestWorker":"webpack --config ./src/test/worker/webpack.config.js 1>&2 && cpx \\"./lib/test/test-worker.js\\" ./lib/test","webpackWorkers":"webpack --config ./src/workers/ImdlParser/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@bentley/aec-units-schema":"^1.0.3","@bentley/formats-schema":"^1.0.0","@bentley/units-schema":"^1.0.9","@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/object-storage-core":"^3.0.4","@itwin/eslint-plugin":"^6.0.0","@types/chai-as-promised":"^7","@types/draco3d":"^1.4.10","@types/sinon":"^17.0.2","@vitest/browser":"^3.0.6","@vitest/coverage-v8":"^3.0.6","cpx2":"^8.0.0","eslint":"^9.31.0","glob":"^10.5.0","playwright":"~1.56.1","rimraf":"^6.0.1","sinon":"^17.0.2","source-map-loader":"^5.0.0","typescript":"~5.6.2","vitest":"^3.0.6","vite-multiple-assets":"^1.3.1","vite-plugin-static-copy":"2.2.0","webpack":"^5.97.1"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"~4.3.4","@loaders.gl/draco":"~4.3.4","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
325755
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.9.0-dev.9","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s webpackWorkers && npm run -s copy:workers && npm run -s copy:draco","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:workers":"cpx \\"./lib/workers/webpack/parse-imdl-worker.js\\" ./lib/public/scripts","copy:draco":"cpx \\"./node_modules/@loaders.gl/draco/dist/libs/*\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts && npm run -s extract","extract":"betools extract --fileExt=ts --extractFrom=./src/test/example-code --recursive --out=../../generated-docs/extract","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","lint-deprecation":"eslint --fix -f visualstudio --no-inline-config -c ../../common/config/eslint/eslint.config.deprecation-policy.js \\"./src/**/*.ts\\"","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run webpackTestWorker && vitest --run","cover":"npm run webpackTestWorker && vitest --run","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2 && npm run -s webpackTestWorker","webpackTestWorker":"webpack --config ./src/test/worker/webpack.config.js 1>&2 && cpx \\"./lib/test/test-worker.js\\" ./lib/test","webpackWorkers":"webpack --config ./src/workers/ImdlParser/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@bentley/aec-units-schema":"^1.0.3","@bentley/formats-schema":"^1.0.0","@bentley/units-schema":"^1.0.9","@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/object-storage-core":"^3.0.4","@itwin/eslint-plugin":"^6.0.0","@types/chai-as-promised":"^7","@types/draco3d":"^1.4.10","@types/sinon":"^17.0.2","@vitest/browser":"^3.0.6","@vitest/coverage-v8":"^3.0.6","cpx2":"^8.0.0","eslint":"^9.31.0","glob":"^10.5.0","playwright":"~1.56.1","rimraf":"^6.0.1","sinon":"^17.0.2","source-map-loader":"^5.0.0","typescript":"~5.6.2","vitest":"^3.0.6","vite-multiple-assets":"^1.3.1","vite-plugin-static-copy":"2.2.0","webpack":"^5.97.1"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"~4.3.4","@loaders.gl/draco":"~4.3.4","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
325422
325756
 
325423
325757
  /***/ })
325424
325758