@itwin/rpcinterface-full-stack-tests 5.1.0-dev.51 → 5.1.0-dev.53

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.
@@ -72817,7 +72817,8 @@ class WhiteOnWhiteReversalSettings {
72817
72817
  "use strict";
72818
72818
  __webpack_require__.r(__webpack_exports__);
72819
72819
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
72820
- /* harmony export */ TextAnnotation: () => (/* binding */ TextAnnotation)
72820
+ /* harmony export */ TextAnnotation: () => (/* binding */ TextAnnotation),
72821
+ /* harmony export */ textAnnotationFrameShapes: () => (/* binding */ textAnnotationFrameShapes)
72821
72822
  /* harmony export */ });
72822
72823
  /* harmony import */ var _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-geometry */ "../../core/geometry/lib/esm/core-geometry.js");
72823
72824
  /* harmony import */ var _TextBlock__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TextBlock */ "../../core/common/lib/esm/annotation/TextBlock.js");
@@ -72830,6 +72831,10 @@ __webpack_require__.r(__webpack_exports__);
72830
72831
  */
72831
72832
 
72832
72833
 
72834
+ /** Set of predefined shapes that can be computed and drawn around the margins of a [[TextBlock]]
72835
+ * @beta
72836
+ */
72837
+ const textAnnotationFrameShapes = ["none", "line", "rectangle", "circle", "equilateralTriangle", "diamond", "square", "pentagon", "hexagon", "octagon", "capsule", "roundedRectangle"];
72833
72838
  /**
72834
72839
  * Represents a formatted block of text positioned in 2d or 3d space.
72835
72840
  * [TextAnnotation2d]($backend) and [TextAnnotation3d]($backend) elements store a single TextAnnotation from which their geometric representation is generated.
@@ -73988,6 +73993,7 @@ __webpack_require__.r(__webpack_exports__);
73988
73993
  /* harmony export */ readElementMeshes: () => (/* reexport safe */ _ElementMesh__WEBPACK_IMPORTED_MODULE_29__.readElementMeshes),
73989
73994
  /* harmony export */ readTileContentDescription: () => (/* reexport safe */ _tile_TileMetadata__WEBPACK_IMPORTED_MODULE_157__.readTileContentDescription),
73990
73995
  /* harmony export */ rpcOverIpcStrings: () => (/* reexport safe */ _ipc_IpcSession__WEBPACK_IMPORTED_MODULE_75__.rpcOverIpcStrings),
73996
+ /* harmony export */ textAnnotationFrameShapes: () => (/* reexport safe */ _annotation_TextAnnotation__WEBPACK_IMPORTED_MODULE_2__.textAnnotationFrameShapes),
73991
73997
  /* harmony export */ tileFormatFromNumber: () => (/* reexport safe */ _tile_TileIO__WEBPACK_IMPORTED_MODULE_156__.tileFormatFromNumber)
73992
73998
  /* harmony export */ });
73993
73999
  /* harmony import */ var _AmbientOcclusion__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AmbientOcclusion */ "../../core/common/lib/esm/AmbientOcclusion.js");
@@ -114814,20 +114820,52 @@ class SnapshotConnection extends IModelConnection {
114814
114820
  /** The collection of [[CodeSpec]] entities for an [[IModelConnection]]. */
114815
114821
  class CodeSpecs {
114816
114822
  _iModel;
114817
- _loaded;
114818
114823
  /** @internal */
114819
114824
  constructor(_iModel) {
114820
114825
  this._iModel = _iModel;
114821
114826
  }
114822
- /** Loads all CodeSpec from the remote IModelDb. */
114823
- async _loadAllCodeSpecs() {
114824
- if (this._loaded)
114825
- return;
114826
- this._loaded = [];
114827
- const codeSpecArray = await _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getAllCodeSpecs(this._iModel.getRpcProps());
114828
- for (const codeSpec of codeSpecArray) {
114829
- this._loaded.push(_itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.CodeSpec.createFromJson(this._iModel, _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Id64.fromString(codeSpec.id), codeSpec.name, codeSpec.jsonProperties));
114827
+ _isCodeSpecProperties(x) {
114828
+ if (!x || !x.scopeSpec || !Object.values(_itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.CodeScopeSpec.Type).includes(x.scopeSpec.type))
114829
+ return false;
114830
+ if (typeof x.scopeSpec.fGuidRequired !== "boolean" && typeof x.scopeSpec.fGuidRequired !== "undefined")
114831
+ return false;
114832
+ if (typeof x.scopeSpec.relationship !== "string" && typeof x.scopeSpec.relationship !== "undefined")
114833
+ return false;
114834
+ if (typeof x.spec?.isManagedWithDgnDb !== "boolean" && typeof x.spec?.isManagedWithDgnDb !== "undefined")
114835
+ return false;
114836
+ if (typeof x.version !== "string" && typeof x.version !== "undefined")
114837
+ return false;
114838
+ return true;
114839
+ }
114840
+ async _loadCodeSpec(identifier) {
114841
+ const isNameDefined = identifier.name !== undefined;
114842
+ const query = `
114843
+ SELECT ECInstanceId AS Id, Name, JsonProperties
114844
+ FROM BisCore.CodeSpec
114845
+ WHERE ${isNameDefined ? `Name=:name` : `Id=:id`}`;
114846
+ const params = new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.QueryBinder();
114847
+ if (isNameDefined) {
114848
+ params.bindString("name", identifier.name);
114849
+ }
114850
+ else {
114851
+ params.bindId("id", identifier.id);
114830
114852
  }
114853
+ const queryReader = this._iModel.createQueryReader(query, params, {
114854
+ rowFormat: _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.QueryRowFormat.UseECSqlPropertyNames,
114855
+ });
114856
+ const queryResult = await queryReader.next();
114857
+ if (queryResult.done)
114858
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
114859
+ const codeSpecResult = queryResult.value;
114860
+ if (typeof codeSpecResult.Id !== "string" ||
114861
+ typeof codeSpecResult.Name !== "string" ||
114862
+ typeof codeSpecResult.JsonProperties !== "string")
114863
+ throw new Error("Invalid CodeSpec was returned");
114864
+ const jsonProperties = JSON.parse(codeSpecResult.JsonProperties);
114865
+ if (!this._isCodeSpecProperties(jsonProperties))
114866
+ throw new Error("Invalid CodeSpecProperties returned in the CodeSpec");
114867
+ const codeSpec = _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.CodeSpec.createFromJson(this._iModel, _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Id64.fromString(codeSpecResult.Id), codeSpecResult.Name, jsonProperties);
114868
+ return codeSpec;
114831
114869
  }
114832
114870
  /** Look up a CodeSpec by Id.
114833
114871
  * @param codeSpecId The Id of the CodeSpec to load
@@ -114835,13 +114873,11 @@ class SnapshotConnection extends IModelConnection {
114835
114873
  * @throws [[IModelError]] if the Id is invalid or if no CodeSpec with that Id could be found.
114836
114874
  */
114837
114875
  async getById(codeSpecId) {
114876
+ if (codeSpecId === "")
114877
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
114838
114878
  if (!_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Id64.isValid(codeSpecId))
114839
114879
  throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.InvalidId, "Invalid codeSpecId", () => ({ codeSpecId }));
114840
- await this._loadAllCodeSpecs(); // ensure all codeSpecs have been downloaded
114841
- const found = this._loaded.find((codeSpec) => codeSpec.id === codeSpecId);
114842
- if (!found)
114843
- throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
114844
- return found;
114880
+ return this._loadCodeSpec({ id: codeSpecId });
114845
114881
  }
114846
114882
  /** Look up a CodeSpec by name.
114847
114883
  * @param name The name of the CodeSpec to load
@@ -114849,11 +114885,9 @@ class SnapshotConnection extends IModelConnection {
114849
114885
  * @throws [[IModelError]] if no CodeSpec with the specified name could be found.
114850
114886
  */
114851
114887
  async getByName(name) {
114852
- await this._loadAllCodeSpecs(); // ensure all codeSpecs have been downloaded
114853
- const found = this._loaded.find((codeSpec) => codeSpec.name === name);
114854
- if (!found)
114888
+ if (name === "")
114855
114889
  throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
114856
- return found;
114890
+ return this._loadCodeSpec({ name });
114857
114891
  }
114858
114892
  }
114859
114893
  IModelConnection.CodeSpecs = CodeSpecs;
@@ -216017,7 +216051,6 @@ class BSplineSurface3d extends BSpline2dNd {
216017
216051
  getPointGridJSON() {
216018
216052
  const result = {
216019
216053
  points: _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_7__.Point3dArray.unpackNumbersToNestedArraysIJK(this.coffs, 3, this.numPolesUV(0)),
216020
- weighStyle: WeightStyle.WeightsAlreadyAppliedToCoordinates, // @deprecated in 4.x - will not be removed until after 2026-06-13. Use weightStyle instead.
216021
216054
  weightStyle: WeightStyle.UnWeighted,
216022
216055
  numCartesianDimensions: 3,
216023
216056
  };
@@ -216430,7 +216463,6 @@ class BSplineSurface3dH extends BSpline2dNd {
216430
216463
  const result = {
216431
216464
  points: _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_7__.Point3dArray.unpackNumbersToNestedArraysIJK(this.coffs, 4, this.numPolesUV(0)),
216432
216465
  numCartesianDimensions: 3,
216433
- weighStyle: WeightStyle.WeightsAlreadyAppliedToCoordinates, // @deprecated in 4.x - will not be removed until after 2026-06-13. Use weightStyle instead.
216434
216466
  weightStyle: WeightStyle.WeightsAlreadyAppliedToCoordinates,
216435
216467
  };
216436
216468
  return result;
@@ -227444,6 +227476,17 @@ class CurveChain extends CurveCollection {
227444
227476
  else
227445
227477
  return undefined;
227446
227478
  }
227479
+ /**
227480
+ * Whether the chain start and end points are defined and within tolerance.
227481
+ * * Does not check for planarity or degeneracy.
227482
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
227483
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
227484
+ */
227485
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallMetricDistance, xyOnly = false) {
227486
+ const p0 = this.startPoint();
227487
+ const p1 = this.endPoint();
227488
+ return p0 !== undefined && p1 !== undefined && (xyOnly ? p0.isAlmostEqualXY(p1, tolerance) : p0.isAlmostEqual(p1, tolerance));
227489
+ }
227447
227490
  /**
227448
227491
  * Return the start point and derivative of the first child of the curve chain.
227449
227492
  * * For queries interior to the chain, use [[CurveChainWithDistanceIndex.fractionToPointAndDerivative]].
@@ -228174,11 +228217,12 @@ class CurveFactory {
228174
228217
  * * This only succeeds if the two arcs are part of identical complete arcs and end of `arcA` matches the beginning of `arcB`.
228175
228218
  * @param arcA first arc, modified in place.
228176
228219
  * @param arcB second arc, unmodified.
228177
- * @param allowReversed whether to consolidate even when second arc is reversed.
228220
+ * @param allowReversed whether to consolidate even when second arc is reversed (default is `false`).
228221
+ * @param tolerance optional coordinate tolerance for point equality (default is `Geometry.smallMetricDistance`).
228178
228222
  * @returns whether `arcA` was modified.
228179
228223
  */
228180
- static appendToArcInPlace(arcA, arcB, allowReverse = false) {
228181
- if (arcA.center.isAlmostEqual(arcB.center)) {
228224
+ static appendToArcInPlace(arcA, arcB, allowReverse = false, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
228225
+ if (arcA.center.isAlmostEqual(arcB.center, tolerance)) {
228182
228226
  const sweepSign = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.split3WaySign(arcA.sweep.sweepRadians * arcB.sweep.sweepRadians, -1, 0, 1);
228183
228227
  // evaluate derivatives wrt radians (not fraction!), but adjust direction for sweep signs
228184
228228
  const endA = arcA.angleToPointAndDerivative(arcA.sweep.fractionToAngle(1.0));
@@ -228187,14 +228231,14 @@ class CurveFactory {
228187
228231
  const startB = arcB.angleToPointAndDerivative(arcB.sweep.fractionToAngle(0.0));
228188
228232
  if (arcB.sweep.sweepRadians < 0)
228189
228233
  startB.direction.scaleInPlace(-1.0);
228190
- if (endA.isAlmostEqual(startB)) {
228234
+ if (endA.isAlmostEqual(startB, tolerance)) {
228191
228235
  arcA.sweep.setStartEndRadians(arcA.sweep.startRadians, arcA.sweep.startRadians + arcA.sweep.sweepRadians + sweepSign * arcB.sweep.sweepRadians);
228192
228236
  return true;
228193
228237
  }
228194
228238
  // Also ok if negated tangent
228195
228239
  if (allowReverse) {
228196
228240
  startB.direction.scaleInPlace(-1.0);
228197
- if (endA.isAlmostEqual(startB)) {
228241
+ if (endA.isAlmostEqual(startB, tolerance)) {
228198
228242
  arcA.sweep.setStartEndRadians(arcA.sweep.startRadians, arcA.sweep.startRadians + arcA.sweep.sweepRadians - sweepSign * arcB.sweep.sweepRadians);
228199
228243
  return true;
228200
228244
  }
@@ -228741,7 +228785,12 @@ class CurveLocationDetail {
228741
228785
  setIntervalRole(value) {
228742
228786
  this.intervalRole = value;
228743
228787
  }
228744
- /** Set the (optional) fraction1 and point1, using direct assignment (capture!) to point1. */
228788
+ /** Set the `fraction` and `point`, using direct assignment (capture!) to `point`. */
228789
+ captureFractionPoint(fraction, point) {
228790
+ this.fraction = fraction;
228791
+ this.point = point;
228792
+ }
228793
+ /** Set the (optional) `fraction1` and `point1`, using direct assignment (capture!) to `point1`. */
228745
228794
  captureFraction1Point1(fraction1, point1) {
228746
228795
  this.fraction1 = fraction1;
228747
228796
  this.point1 = point1;
@@ -229961,6 +230010,17 @@ class CurvePrimitive extends _GeometryQuery__WEBPACK_IMPORTED_MODULE_1__.Geometr
229961
230010
  endPoint(result) {
229962
230011
  return this.fractionToPoint(1.0, result);
229963
230012
  }
230013
+ /**
230014
+ * Whether the start and end points are defined and within tolerance.
230015
+ * * Does not check for planarity or degeneracy.
230016
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
230017
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
230018
+ */
230019
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance, xyOnly = false) {
230020
+ const p0 = this.startPoint();
230021
+ const p1 = this.endPoint();
230022
+ return p0 !== undefined && p1 !== undefined && (xyOnly ? p0.isAlmostEqualXY(p1, tolerance) : p0.isAlmostEqual(p1, tolerance));
230023
+ }
229964
230024
  /**
229965
230025
  * Attach StrokeCountMap structure to this primitive (and recursively to any children)
229966
230026
  * * Base class implementation (here) gets the simple count from computeStrokeCountForOptions and attaches it.
@@ -230448,6 +230508,10 @@ class LineSegment3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePr
230448
230508
  get point1Ref() {
230449
230509
  return this._point1;
230450
230510
  }
230511
+ /** Return a copy of the start and end points in an array. */
230512
+ get points() {
230513
+ return [this._point0.clone(), this._point1.clone()];
230514
+ }
230451
230515
  /** A LineSegment3d extends along its infinite line. */
230452
230516
  get isExtensibleFractionSpace() {
230453
230517
  return true;
@@ -232228,8 +232292,7 @@ class LineString3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePri
232228
232292
  this.addResolvedPoint(localA.index, localA.fraction, result._points);
232229
232293
  for (let index = index0; index <= index1; index++) {
232230
232294
  if (this._points.isIndexValid(index)) {
232231
- this._points.getPoint3dAtUncheckedPointIndex(index, LineString3d._workPointA);
232232
- result._points.push(LineString3d._workPointA);
232295
+ result._points.pushFromGrowableXYZArray(this._points, index);
232233
232296
  }
232234
232297
  }
232235
232298
  this.addResolvedPoint(localB.index, localB.fraction, result._points);
@@ -232241,9 +232304,22 @@ class LineString3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePri
232241
232304
  return _LineSegment3d__WEBPACK_IMPORTED_MODULE_15__.LineSegment3d.create(this._points.getPoint3dAtCheckedPointIndex(index), this._points.getPoint3dAtCheckedPointIndex(index + 1), result);
232242
232305
  return undefined;
232243
232306
  }
232307
+ /**
232308
+ * Whether the start and end points are defined and within tolerance.
232309
+ * * Does not check for planarity or degeneracy.
232310
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
232311
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
232312
+ */
232313
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance, xyOnly = false) {
232314
+ if (!this._points.length)
232315
+ return false;
232316
+ if (xyOnly)
232317
+ return this._points.almostEqualXYIndexIndex(0, this._points.length - 1, tolerance); // we know the indices are valid
232318
+ return this._points.almostEqualIndexIndex(0, this._points.length - 1, tolerance);
232319
+ }
232244
232320
  /** Returns true if first and last points are within metric tolerance. */
232245
232321
  get isPhysicallyClosed() {
232246
- return this._points.length > 0 && _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.isSmallMetricDistance(this._points.distanceIndexIndex(0, this._points.length - 1));
232322
+ return this.isPhysicallyClosedCurve();
232247
232323
  }
232248
232324
  /**
232249
232325
  * Evaluate strokes at fractions indicated in a StrokeCountMap.
@@ -233424,7 +233500,7 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
233424
233500
  const numOriginal = children.length;
233425
233501
  const points = [];
233426
233502
  let numAccept = 0;
233427
- // i0 <=i < i1 is a range of child indices.
233503
+ // i0 <= i < i1 is a range of child indices.
233428
233504
  // numAccept is the number of children accepted (contiguously at front of children)
233429
233505
  for (let i0 = 0; i0 < numOriginal;) {
233430
233506
  const basePrimitive = g.children[i0];
@@ -233482,7 +233558,7 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
233482
233558
  const nextPrimitive = g.children[i0];
233483
233559
  if (!(nextPrimitive instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d))
233484
233560
  break;
233485
- if (!_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(basePrimitive, nextPrimitive)) // TODO: use this._options.duplicatePointTolerance
233561
+ if (!_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(basePrimitive, nextPrimitive, false, this._options.duplicatePointTolerance))
233486
233562
  break;
233487
233563
  }
233488
233564
  // i0 has already advanced
@@ -233495,8 +233571,32 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
233495
233571
  }
233496
233572
  g.children.length = numAccept;
233497
233573
  }
233498
- handlePath(g) { return this.handleCurveChain(g); }
233499
- handleLoop(g) { return this.handleCurveChain(g); }
233574
+ handlePath(g) {
233575
+ return this.handleCurveChain(g);
233576
+ }
233577
+ handleLoop(g) {
233578
+ this.handleCurveChain(g);
233579
+ if (g.children.length > 1 && this._options.consolidateLoopSeam) {
233580
+ const lastChild = g.children[g.children.length - 1];
233581
+ const firstChild = g.children[0];
233582
+ if ((lastChild instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_2__.LineSegment3d || lastChild instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_3__.LineString3d) && (firstChild instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_2__.LineSegment3d || firstChild instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_3__.LineString3d)) {
233583
+ if (this._options.consolidateLinearGeometry && !this._options.disableLinearCompression) {
233584
+ const lastPoints = lastChild.points;
233585
+ lastPoints.pop(); // the original start point survives as an interior point in the new first primitive
233586
+ g.children[0] = _LineString3d__WEBPACK_IMPORTED_MODULE_3__.LineString3d.createPoints([...lastPoints, ...firstChild.points]);
233587
+ g.children.pop();
233588
+ }
233589
+ }
233590
+ else if (lastChild instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d && firstChild instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d) {
233591
+ if (this._options.consolidateCompatibleArcs) {
233592
+ if (_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(lastChild, firstChild, false, this._options.duplicatePointTolerance)) {
233593
+ g.children[0] = lastChild;
233594
+ g.children.pop();
233595
+ }
233596
+ }
233597
+ }
233598
+ }
233599
+ }
233500
233600
  handleParityRegion(g) {
233501
233601
  for (const child of g.children)
233502
233602
  child.dispatchToGeometryHandler(this);
@@ -233925,16 +234025,19 @@ __webpack_require__.r(__webpack_exports__);
233925
234025
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
233926
234026
  /* harmony export */ PlanarSubdivision: () => (/* binding */ PlanarSubdivision)
233927
234027
  /* harmony export */ });
233928
- /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
233929
- /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
233930
- /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
233931
- /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
233932
- /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
233933
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
233934
- /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
233935
- /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
233936
- /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
233937
- /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
234028
+ /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
234029
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
234030
+ /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
234031
+ /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
234032
+ /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
234033
+ /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
234034
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
234035
+ /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
234036
+ /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
234037
+ /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
234038
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
234039
+ /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
234040
+ /* harmony import */ var _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../RegionOpsClassificationSweeps */ "../../core/geometry/lib/esm/curve/RegionOpsClassificationSweeps.js");
233938
234041
  /*---------------------------------------------------------------------------------------------
233939
234042
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
233940
234043
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -233949,6 +234052,9 @@ __webpack_require__.r(__webpack_exports__);
233949
234052
 
233950
234053
 
233951
234054
 
234055
+
234056
+
234057
+
233952
234058
  /** @packageDocumentation
233953
234059
  * @module Curve
233954
234060
  */
@@ -233991,19 +234097,19 @@ class MapCurvePrimitiveToCurveLocationDetailPairArray {
233991
234097
  * added to the graph because it isn't in the `primitiveToPair` map. By splitting such a missing primitive in two, we
233992
234098
  * introduce two intersections for each half, which allows the primitive to be represented in the map.
233993
234099
  */
233994
- splitAndAppendMissingClosedPrimitives(primitives, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
234100
+ splitAndAppendMissingClosedPrimitives(primitives, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
233995
234101
  for (const p of primitives) {
233996
234102
  let closedCurveSplitCandidate = false;
233997
- if (p instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_1__.Arc3d)
234103
+ if (p instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_2__.Arc3d)
233998
234104
  closedCurveSplitCandidate = p.sweep.isFullCircle;
233999
- else if (!(p instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_2__.LineSegment3d) && !(p instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_3__.LineString3d)) // TODO: probably should do this for all types. Lots of spline-type primitives can be closed.
234105
+ else if (!(p instanceof _LineSegment3d__WEBPACK_IMPORTED_MODULE_3__.LineSegment3d) && !(p instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_4__.LineString3d)) // TODO: probably should do this for all types. Lots of spline-type primitives can be closed.
234000
234106
  closedCurveSplitCandidate = p.startPoint().isAlmostEqualXY(p.endPoint(), tolerance);
234001
234107
  if (closedCurveSplitCandidate && !this.primitiveToPair.has(p)) {
234002
234108
  const p0 = p.clonePartialCurve(0.0, 0.5);
234003
234109
  const p1 = p.clonePartialCurve(0.5, 1.0);
234004
234110
  if (p0 && p1) {
234005
- this.insertPair(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFraction(p0, 0.0), _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFraction(p1, 1.0)));
234006
- this.insertPair(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFraction(p0, 1.0), _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFraction(p1, 0.0)));
234111
+ this.insertPair(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveEvaluatedFraction(p0, 0.0), _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveEvaluatedFraction(p1, 1.0)));
234112
+ this.insertPair(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(_CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveEvaluatedFraction(p0, 1.0), _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveEvaluatedFraction(p1, 0.0)));
234007
234113
  }
234008
234114
  }
234009
234115
  }
@@ -234017,7 +234123,7 @@ class PlanarSubdivision {
234017
234123
  * Create a graph from an array of curves, and an array of the curves' precomputed intersections.
234018
234124
  * Z-coordinates are ignored.
234019
234125
  */
234020
- static assembleHalfEdgeGraph(primitives, allPairs, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
234126
+ static assembleHalfEdgeGraph(primitives, allPairs, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
234021
234127
  // map from key CurvePrimitive to CurveLocationDetailPair
234022
234128
  const detailByPrimitive = new MapCurvePrimitiveToCurveLocationDetailPairArray();
234023
234129
  for (const pair of allPairs)
@@ -234026,7 +234132,7 @@ class PlanarSubdivision {
234026
234132
  // otherwise, these single-primitive loops are missing from the graph
234027
234133
  detailByPrimitive.splitAndAppendMissingClosedPrimitives(primitives, mergeTolerance);
234028
234134
  }
234029
- const graph = new _topology_Graph__WEBPACK_IMPORTED_MODULE_5__.HalfEdgeGraph();
234135
+ const graph = new _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraph();
234030
234136
  for (const entry of detailByPrimitive.primitiveToPair.entries()) {
234031
234137
  const p = entry[0];
234032
234138
  // convert each interval intersection into two isolated intersections
@@ -234034,12 +234140,12 @@ class PlanarSubdivision {
234034
234140
  if (!detailPair.detailA.hasFraction1)
234035
234141
  return [...accumulator, detailPair];
234036
234142
  const detail = getDetailOnCurve(detailPair, p);
234037
- const detail0 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction, detail.point);
234038
- const detail1 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction1, detail.point1);
234143
+ const detail0 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction, detail.point);
234144
+ const detail1 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction1, detail.point1);
234039
234145
  return [
234040
234146
  ...accumulator,
234041
- _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(detail0, detail0),
234042
- _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(detail1, detail1),
234147
+ _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(detail0, detail0),
234148
+ _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(detail1, detail1),
234043
234149
  ];
234044
234150
  }, []);
234045
234151
  // lexical sort on p intersection fraction
@@ -234051,12 +234157,12 @@ class PlanarSubdivision {
234051
234157
  let last = { point: p.startPoint(), fraction: 0.0 };
234052
234158
  for (const detailPair of details) {
234053
234159
  const detail = getDetailOnCurve(detailPair, p);
234054
- const detailFraction = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.restrictToInterval(detail.fraction, 0, 1); // truncate fraction, but don't snap point; clustering happens later
234160
+ const detailFraction = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.restrictToInterval(detail.fraction, 0, 1); // truncate fraction, but don't snap point; clustering happens later
234055
234161
  last = this.addHalfEdge(graph, p, last.point, last.fraction, detail.point, detailFraction, mergeTolerance);
234056
234162
  }
234057
234163
  this.addHalfEdge(graph, p, last.point, last.fraction, p.endPoint(), 1.0, mergeTolerance);
234058
234164
  }
234059
- _topology_Merging__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraphMerge.clusterAndMergeXYTheta(graph, (he) => he.sortAngle);
234165
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.clusterAndMergeXYTheta(graph, (he) => he.sortAngle);
234060
234166
  return graph;
234061
234167
  }
234062
234168
  /**
@@ -234070,11 +234176,13 @@ class PlanarSubdivision {
234070
234176
  * @param fraction1 end fraction
234071
234177
  * @returns end point and fraction, or start point and fraction if no action
234072
234178
  */
234073
- static addHalfEdge(graph, p, point0, fraction0, point1, fraction1, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
234179
+ static addHalfEdge(graph, p, point0, fraction0, point1, fraction1, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
234074
234180
  if (point0.isAlmostEqualXY(point1, mergeTolerance))
234075
234181
  return { point: point0, fraction: fraction0 };
234076
234182
  const halfEdge = graph.createEdgeXYAndZ(point0, 0, point1, 0);
234077
- const detail01 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1);
234183
+ if (p.parent && p.parent instanceof _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__.RegionGroupMember && p.parent.parentGroup.groupOpType === _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__.RegionGroupOpType.NonBounding)
234184
+ halfEdge.setMaskAroundEdge(_topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.BRIDGE_EDGE);
234185
+ const detail01 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1);
234078
234186
  const mate = halfEdge.edgeMate;
234079
234187
  halfEdge.edgeTag = detail01;
234080
234188
  halfEdge.sortData = 1.0;
@@ -234092,7 +234200,7 @@ class PlanarSubdivision {
234092
234200
  * @returns the area (forced to zero if within tolerance)
234093
234201
  */
234094
234202
  static collectSignedLoop(loop, outLoops, zeroAreaTolerance = 1.0e-10, isSliverFace) {
234095
- let area = isSliverFace ? 0.0 : _RegionOps__WEBPACK_IMPORTED_MODULE_7__.RegionOps.computeXYArea(loop);
234203
+ let area = isSliverFace ? 0.0 : _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.computeXYArea(loop);
234096
234204
  if (area === undefined)
234097
234205
  area = 0;
234098
234206
  if (Math.abs(area) < zeroAreaTolerance)
@@ -234106,41 +234214,115 @@ class PlanarSubdivision {
234106
234214
  outLoops.slivers.push(loop);
234107
234215
  return area;
234108
234216
  }
234109
- static createLoopInFace(faceSeed, announce) {
234110
- let he = faceSeed;
234111
- const loop = _Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create();
234112
- do {
234113
- const detail = he.edgeTag;
234114
- if (detail) {
234115
- let curve;
234116
- if (he.sortData > 0)
234117
- curve = detail.curve.clonePartialCurve(detail.fraction, detail.fraction1);
234118
- else
234119
- curve = detail.curve.clonePartialCurve(detail.fraction1, detail.fraction);
234120
- if (curve) {
234121
- if (announce !== undefined)
234122
- announce(he, curve, loop);
234123
- loop.tryAddChild(curve);
234217
+ /** Extract geometric info from a topological edge. */
234218
+ static extractGeometryFromEdge(edge) {
234219
+ if (edge.sortData !== undefined && edge.edgeTag && edge.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail) {
234220
+ const detail = edge.edgeTag;
234221
+ if (detail.curve && detail.fraction1 !== undefined) {
234222
+ const reversed = edge.sortData < 0;
234223
+ return { detail, reversed };
234224
+ }
234225
+ }
234226
+ return undefined;
234227
+ }
234228
+ /** Create the geometry for a topological edge. */
234229
+ static createCurveInEdge(edge) {
234230
+ const info = this.extractGeometryFromEdge(edge);
234231
+ if (info) {
234232
+ if (info.reversed)
234233
+ return info.detail.curve.clonePartialCurve(info.detail.fraction1, info.detail.fraction);
234234
+ return info.detail.curve.clonePartialCurve(info.detail.fraction, info.detail.fraction1);
234235
+ }
234236
+ return undefined;
234237
+ }
234238
+ /**
234239
+ * Create a [[Loop]] for the given face or super face.
234240
+ * @param face a node in the face loop, or an array of HalfEdges that comprise a loop (e.g., a super face).
234241
+ * @param announce optional callback invoked on each edge/curve of the face/Loop.
234242
+ * @param compress whether to consolidate adjacent curves in the output Loop (default `false`).
234243
+ * If `announce` is provided, no compression is performed, as edges and curves would no longer be in 1-1 correspondence.
234244
+ */
234245
+ static createLoopInFace(face, announce, compress = false) {
234246
+ if (announce)
234247
+ compress = false;
234248
+ const loop = _Loop__WEBPACK_IMPORTED_MODULE_10__.Loop.create();
234249
+ const addEdgeCurve = (he) => {
234250
+ const curve = this.createCurveInEdge(he);
234251
+ if (curve) {
234252
+ announce?.(he, curve, loop);
234253
+ loop.tryAddChild(curve);
234254
+ }
234255
+ };
234256
+ if (Array.isArray(face))
234257
+ face.forEach(addEdgeCurve);
234258
+ else
234259
+ face.announceEdgesInFace(addEdgeCurve);
234260
+ if (compress) {
234261
+ const options = new _RegionOps__WEBPACK_IMPORTED_MODULE_9__.ConsolidateAdjacentCurvePrimitivesOptions();
234262
+ options.consolidateLoopSeam = true;
234263
+ _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.consolidateAdjacentPrimitives(loop, options);
234264
+ }
234265
+ if (loop.isPhysicallyClosedCurve(undefined, true))
234266
+ return loop;
234267
+ (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(false, "createLoopInFace: face is not physically closed");
234268
+ return undefined;
234269
+ }
234270
+ /**
234271
+ * Create a [[Loop]] or [[ParityRegion]] for the given face.
234272
+ * * A ParityRegion is created for a split-washer type face by removing bridge edges.
234273
+ * @param face a node in the face loop.
234274
+ * @param bridgeMask mask preset on bridge edges (default is `HalfEdgeMask.BRIDGE_EDGE`).
234275
+ * @param visitMask mask to use for visiting edges in the face loop (default is `HalfEdgeMask.VISITED`).
234276
+ */
234277
+ static createLoopOrParityRegionInFace(face, bridgeMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.BRIDGE_EDGE, visitMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.VISITED) {
234278
+ let region;
234279
+ if (face.isSplitWasherFace(bridgeMask)) {
234280
+ const loops = [];
234281
+ const loopEdges = [];
234282
+ const bridgeStack = [face.findMaskAroundFace(bridgeMask, true)];
234283
+ const announceEdge = (he) => { he.setMask(visitMask); loopEdges.push(he); };
234284
+ const announceBridge = (he) => { if (!he.isMaskSet(visitMask))
234285
+ bridgeStack.push(he); };
234286
+ face.clearMaskAroundFace(visitMask);
234287
+ let bridge;
234288
+ while (undefined !== (bridge = bridgeStack.pop())) {
234289
+ bridge.setMask(visitMask);
234290
+ const loopSeed = bridge.findMaskAroundFace(bridgeMask, false); // advance to next loop
234291
+ if (loopSeed) {
234292
+ if (loopSeed.isMaskSet(visitMask))
234293
+ continue;
234294
+ loopEdges.length = 0;
234295
+ if (loopSeed.announceEdgesInSuperFace(bridgeMask, announceEdge, announceBridge)) {
234296
+ const loop = this.createLoopInFace(loopEdges, undefined, true);
234297
+ if (loop) {
234298
+ loops.push(loop);
234299
+ continue;
234300
+ }
234301
+ }
234124
234302
  }
234125
234303
  }
234126
- he = he.faceSuccessor;
234127
- } while (he !== faceSeed);
234128
- return loop;
234304
+ region = _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.sortOuterAndHoleLoopsXY(loops);
234305
+ region = _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.simplifyRegion(region);
234306
+ }
234307
+ else {
234308
+ region = this.createLoopInFace(face, undefined, true);
234309
+ }
234310
+ return (region && (region instanceof _Loop__WEBPACK_IMPORTED_MODULE_10__.Loop || region instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_11__.ParityRegion)) ? region : undefined;
234129
234311
  }
234130
- // Return true if there are only two edges in the face loop, and their start curvatures are the same.
234312
+ /** Return true if there are only two edges in the face loop, and their start curvatures are the same. */
234131
234313
  static isNullFace(he) {
234132
234314
  const faceHasTwoEdges = (he.faceSuccessor.faceSuccessor === he);
234133
234315
  let faceIsBanana = false;
234134
234316
  if (faceHasTwoEdges) {
234135
- const c0 = _topology_Merging__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraphMerge.curvatureSortKey(he);
234136
- const c1 = _topology_Merging__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraphMerge.curvatureSortKey(he.faceSuccessor.edgeMate);
234137
- if (!_Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.isSameCoordinate(c0, c1)) // default tol!
234317
+ const c0 = _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.curvatureSortKey(he);
234318
+ const c1 = _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.curvatureSortKey(he.faceSuccessor.edgeMate);
234319
+ if (!_Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(c0, c1)) // default tol!
234138
234320
  faceIsBanana = true; // heuristic: we could also check end curvatures, and/or higher derivatives...
234139
234321
  }
234140
234322
  return faceHasTwoEdges && !faceIsBanana;
234141
234323
  }
234142
- // Look across edge mates (possibly several) for a nonnull mate face.
234143
- static nonNullEdgeMate(_graph, e) {
234324
+ /** Look across edge mates (possibly several) for a non-null mate face. */
234325
+ static getNonNullEdgeMate(_graph, e) {
234144
234326
  if (this.isNullFace(e))
234145
234327
  return undefined;
234146
234328
  let e1 = e.edgeMate;
@@ -234152,7 +234334,7 @@ class PlanarSubdivision {
234152
234334
  return e1;
234153
234335
  }
234154
234336
  static collectSignedLoopSetsInHalfEdgeGraph(graph, zeroAreaTolerance = 1.0e-10) {
234155
- const q = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_9__.HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, undefined);
234337
+ const q = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_12__.HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, undefined);
234156
234338
  const result = [];
234157
234339
  const edgeMap = new Map();
234158
234340
  for (const faceSeeds of q) {
@@ -234162,15 +234344,15 @@ class PlanarSubdivision {
234162
234344
  const isNullFace = this.isNullFace(faceSeed);
234163
234345
  const loop = this.createLoopInFace(faceSeed, (he, curveC, loopC) => {
234164
234346
  if (!isNullFace) {
234165
- const mate = this.nonNullEdgeMate(graph, he);
234347
+ const mate = this.getNonNullEdgeMate(graph, he);
234166
234348
  if (mate !== undefined) {
234167
234349
  const e = edgeMap.get(mate);
234168
234350
  if (e === undefined) {
234169
234351
  // Record this as loopA,edgeA of a shared edge to be completed later from the other side of the edge
234170
- const e1 = new _Loop__WEBPACK_IMPORTED_MODULE_8__.LoopCurveLoopCurve(loopC, curveC, undefined, undefined);
234352
+ const e1 = new _Loop__WEBPACK_IMPORTED_MODULE_10__.LoopCurveLoopCurve(loopC, curveC, undefined, undefined);
234171
234353
  edgeMap.set(he, e1);
234172
234354
  }
234173
- else if (e instanceof _Loop__WEBPACK_IMPORTED_MODULE_8__.LoopCurveLoopCurve) {
234355
+ else if (e instanceof _Loop__WEBPACK_IMPORTED_MODULE_10__.LoopCurveLoopCurve) {
234174
234356
  e.setB(loopC, curveC);
234175
234357
  edges.push(e);
234176
234358
  edgeMap.delete(mate);
@@ -234178,7 +234360,8 @@ class PlanarSubdivision {
234178
234360
  }
234179
234361
  }
234180
234362
  });
234181
- this.collectSignedLoop(loop, componentAreas, zeroAreaTolerance, isNullFace);
234363
+ if (loop)
234364
+ this.collectSignedLoop(loop, componentAreas, zeroAreaTolerance, isNullFace);
234182
234365
  }
234183
234366
  componentAreas.edges = edges;
234184
234367
  result.push(componentAreas);
@@ -234226,11 +234409,12 @@ __webpack_require__.r(__webpack_exports__);
234226
234409
  /* harmony export */ StrokeCountSection: () => (/* binding */ StrokeCountSection)
234227
234410
  /* harmony export */ });
234228
234411
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
234229
- /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
234230
- /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
234412
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
234413
+ /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
234231
234414
  /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
234232
- /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
234233
- /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
234415
+ /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
234416
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
234417
+ /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
234234
234418
  /* harmony import */ var _StrokeCountMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./StrokeCountMap */ "../../core/geometry/lib/esm/curve/Query/StrokeCountMap.js");
234235
234419
  /*---------------------------------------------------------------------------------------------
234236
234420
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
@@ -234246,6 +234430,7 @@ __webpack_require__.r(__webpack_exports__);
234246
234430
 
234247
234431
 
234248
234432
 
234433
+
234249
234434
  // cspell:word remapa
234250
234435
  /**
234251
234436
  * abstract methods for callbacks during sweeps of collections of StrokeCount Structures.
@@ -234376,6 +234561,7 @@ class StrokeCountMapVisitorApplyMaxCurveLength extends StrokeCountMapMultipassVi
234376
234561
  * * `parent` = parent CurveCollection.
234377
234562
  *
234378
234563
  * An instance is normally created with either a `Path` or `Loop` as the parent.
234564
+ * @internal
234379
234565
  */
234380
234566
  class StrokeCountChain {
234381
234567
  maps;
@@ -234391,7 +234577,7 @@ class StrokeCountChain {
234391
234577
  this.maps = [];
234392
234578
  this.options = options;
234393
234579
  }
234394
- static createForCurveChain(chain, options) {
234580
+ static create(chain, options) {
234395
234581
  const result = new StrokeCountChain(chain, options);
234396
234582
  result.parent = chain;
234397
234583
  // A chain can only contain primitives !!!!
@@ -234462,16 +234648,24 @@ class StrokeCountSection {
234462
234648
  * construct array of arrays of `StrokeCountMap`s
234463
234649
  * @param parent
234464
234650
  */
234465
- static createForParityRegionOrChain(parent, options) {
234651
+ static create(parent, options) {
234466
234652
  const result = new StrokeCountSection(parent);
234467
- if (parent instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
234653
+ const appendCurveChain = (chain) => result.chains.push(StrokeCountChain.create(chain, options));
234654
+ const appendParityRegion = (region) => { for (const child of region.children)
234655
+ appendCurveChain(child); };
234656
+ if (parent instanceof _UnionRegion__WEBPACK_IMPORTED_MODULE_3__.UnionRegion) {
234468
234657
  for (const child of parent.children) {
234469
- const p = StrokeCountChain.createForCurveChain(child, options);
234470
- result.chains.push(p);
234658
+ if (child instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion)
234659
+ appendParityRegion(child);
234660
+ else
234661
+ appendCurveChain(child);
234471
234662
  }
234472
234663
  }
234473
- else if (parent instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
234474
- result.chains.push(StrokeCountChain.createForCurveChain(parent, options));
234664
+ else if (parent instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
234665
+ appendParityRegion(parent);
234666
+ }
234667
+ else if (parent instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
234668
+ appendCurveChain(parent);
234475
234669
  }
234476
234670
  return result;
234477
234671
  }
@@ -234550,11 +234744,12 @@ class StrokeCountSection {
234550
234744
  for (let chainIndex = 0; chainIndex < numChainPerSection; chainIndex++) {
234551
234745
  const numPrimitive = sections[0].chains[chainIndex].maps.length;
234552
234746
  for (let primitiveIndex = 0; primitiveIndex < numPrimitive; primitiveIndex++) {
234553
- if (sections[0].chains[chainIndex].maps[primitiveIndex].componentData) {
234554
- const numComponent = sections[0].chains[chainIndex].maps[primitiveIndex].componentData.length;
234555
- for (let i = 0; i < numComponent; i++)
234747
+ const numComponent = sections[0].chains[chainIndex].maps[primitiveIndex].componentData?.length ?? 0;
234748
+ if (numComponent > 0) {
234749
+ for (let i = 0; i < numComponent; i++) {
234556
234750
  if (!this.applyMultipassVisitorCallbackNoComponents(sections, chainIndex, primitiveIndex, i, callback))
234557
234751
  return false;
234752
+ }
234558
234753
  }
234559
234754
  else {
234560
234755
  if (!this.applyMultipassVisitorCallbackNoComponents(sections, chainIndex, primitiveIndex, undefined, callback))
@@ -234602,11 +234797,11 @@ class StrokeCountSection {
234602
234797
  return this.chains[0].getStrokes();
234603
234798
  }
234604
234799
  else {
234605
- const region = _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion.create();
234800
+ const region = _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion.create();
234606
234801
  for (const c of this.chains) {
234607
234802
  const strokes = c.getStrokes();
234608
234803
  if (strokes instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_2__.LineString3d)
234609
- region.tryAddChild(_Loop__WEBPACK_IMPORTED_MODULE_5__.Loop.create(strokes));
234804
+ region.tryAddChild(_Loop__WEBPACK_IMPORTED_MODULE_6__.Loop.create(strokes));
234610
234805
  }
234611
234806
  return region;
234612
234807
  }
@@ -234628,8 +234823,8 @@ class StrokeCountSection {
234628
234823
  if (strokeB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_2__.LineString3d) {
234629
234824
  if (strokeA.numPoints() === strokeB.numPoints()) {
234630
234825
  const n = strokeA.numPoints();
234631
- const pointA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
234632
- const pointB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
234826
+ const pointA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
234827
+ const pointB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
234633
234828
  const allPointA = strokeA.packedPoints;
234634
234829
  const allPointB = strokeB.packedPoints;
234635
234830
  for (let i = 0; i < n; i++) {
@@ -234641,8 +234836,8 @@ class StrokeCountSection {
234641
234836
  }
234642
234837
  }
234643
234838
  }
234644
- else if (strokeA instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
234645
- if (strokeB instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
234839
+ else if (strokeA instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
234840
+ if (strokeB instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
234646
234841
  const childrenA = strokeA.children;
234647
234842
  const childrenB = strokeB.children;
234648
234843
  const n = childrenA.length;
@@ -234655,8 +234850,8 @@ class StrokeCountSection {
234655
234850
  }
234656
234851
  }
234657
234852
  }
234658
- else if (strokeA instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
234659
- if (strokeB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
234853
+ else if (strokeA instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
234854
+ if (strokeB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
234660
234855
  const childrenA = strokeA.children;
234661
234856
  const childrenB = strokeB.children;
234662
234857
  const n = childrenA.length;
@@ -234859,10 +235054,11 @@ __webpack_require__.r(__webpack_exports__);
234859
235054
  /* harmony import */ var _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/GeometryHandler */ "../../core/geometry/lib/esm/geometry3d/GeometryHandler.js");
234860
235055
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
234861
235056
  /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
234862
- /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
235057
+ /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
234863
235058
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
235059
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
234864
235060
  /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
234865
- /* harmony import */ var _StrokeOptions__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
235061
+ /* harmony import */ var _StrokeOptions__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
234866
235062
  /*---------------------------------------------------------------------------------------------
234867
235063
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
234868
235064
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -234875,6 +235071,7 @@ __webpack_require__.r(__webpack_exports__);
234875
235071
 
234876
235072
 
234877
235073
 
235074
+
234878
235075
  /**
234879
235076
  * Implementation class for computing XY area moments.
234880
235077
  * @internal
@@ -234930,7 +235127,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234930
235127
  segment.endPoint(this._point1);
234931
235128
  momentData.accumulateTriangleMomentsXY(undefined, this._point0, this._point1);
234932
235129
  }
234933
- /** Accumulate integrals from origin to all primitives in the chain. */
235130
+ /** Accumulate integrals from origin to all primitives in the loop. */
234934
235131
  handleLoop(loop) {
234935
235132
  const momentData = this._activeMomentData = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_3__.MomentData.create();
234936
235133
  momentData.needOrigin = false;
@@ -234940,7 +235137,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234940
235137
  return momentData;
234941
235138
  }
234942
235139
  handleAnyRegion(region) {
234943
- // guarantee there is no overlapping children
235140
+ // guarantee there are no overlapping children and parity loops have been properly oriented
234944
235141
  const merged = _RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.regionBooleanXY(region, undefined, _RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionBinaryOpType.Union);
234945
235142
  if (!merged)
234946
235143
  return undefined;
@@ -234950,7 +235147,9 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234950
235147
  for (const child of merged.children) {
234951
235148
  const childMoments = child.dispatchToGeometryHandler(this);
234952
235149
  if (childMoments) {
234953
- const sign0 = childMoments.signFactor(1.0);
235150
+ // parity region hole sums subtract; all other regions add
235151
+ const scale = (merged instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_6__.ParityRegion && childMoments.quantitySum < 0) ? -1.0 : 1.0;
235152
+ const sign0 = childMoments.signFactor(scale);
234954
235153
  summedMoments.accumulateProducts(childMoments, sign0);
234955
235154
  }
234956
235155
  }
@@ -234968,7 +235167,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234968
235167
  getStrokeOptions() {
234969
235168
  if (this._strokeOptions)
234970
235169
  return this._strokeOptions;
234971
- const options = _StrokeOptions__WEBPACK_IMPORTED_MODULE_6__.StrokeOptions.createForCurves();
235170
+ const options = _StrokeOptions__WEBPACK_IMPORTED_MODULE_7__.StrokeOptions.createForCurves();
234972
235171
  // this is unusually fine for stroking, but appropriate for sum.
234973
235172
  options.angleTol = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_2__.Angle.createDegrees(5.0);
234974
235173
  this._strokeOptions = options;
@@ -234979,7 +235178,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234979
235178
  * * Stroke the curve and accumulate stroke array.
234980
235179
  */
234981
235180
  handleCurvePrimitive(cp) {
234982
- const strokes = _LineString3d__WEBPACK_IMPORTED_MODULE_7__.LineString3d.create();
235181
+ const strokes = _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.create();
234983
235182
  const options = this.getStrokeOptions();
234984
235183
  cp.emitStrokes(strokes, options);
234985
235184
  this.handleLineString3d(strokes);
@@ -235021,27 +235220,28 @@ __webpack_require__.r(__webpack_exports__);
235021
235220
  /* harmony import */ var _geometry3d_IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../geometry3d/IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
235022
235221
  /* harmony import */ var _geometry3d_Point3dArrayCarrier__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../geometry3d/Point3dArrayCarrier */ "../../core/geometry/lib/esm/geometry3d/Point3dArrayCarrier.js");
235023
235222
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
235024
- /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
235223
+ /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
235025
235224
  /* harmony import */ var _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../geometry3d/PolylineCompressionByEdgeOffset */ "../../core/geometry/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js");
235026
- /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
235225
+ /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
235027
235226
  /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
235028
235227
  /* harmony import */ var _geometry3d_SortablePolygon__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../geometry3d/SortablePolygon */ "../../core/geometry/lib/esm/geometry3d/SortablePolygon.js");
235029
235228
  /* harmony import */ var _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../geometry3d/Transform */ "../../core/geometry/lib/esm/geometry3d/Transform.js");
235030
235229
  /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
235031
235230
  /* harmony import */ var _polyface_PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../polyface/PolyfaceBuilder */ "../../core/geometry/lib/esm/polyface/PolyfaceBuilder.js");
235032
- /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
235033
- /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
235034
- /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
235231
+ /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
235232
+ /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
235233
+ /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
235035
235234
  /* harmony import */ var _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../topology/Triangulation */ "../../core/geometry/lib/esm/topology/Triangulation.js");
235036
235235
  /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
235037
- /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
235236
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
235038
235237
  /* harmony import */ var _CurveOps__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./CurveOps */ "../../core/geometry/lib/esm/curve/CurveOps.js");
235039
235238
  /* harmony import */ var _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
235040
235239
  /* harmony import */ var _CurveWireMomentsXYZ__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./CurveWireMomentsXYZ */ "../../core/geometry/lib/esm/curve/CurveWireMomentsXYZ.js");
235041
- /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
235240
+ /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
235042
235241
  /* harmony import */ var _internalContexts_ChainCollectorContext__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./internalContexts/ChainCollectorContext */ "../../core/geometry/lib/esm/curve/internalContexts/ChainCollectorContext.js");
235043
235242
  /* harmony import */ var _internalContexts_PolygonOffsetContext__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./internalContexts/PolygonOffsetContext */ "../../core/geometry/lib/esm/curve/internalContexts/PolygonOffsetContext.js");
235044
235243
  /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
235244
+ /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
235045
235245
  /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
235046
235246
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
235047
235247
  /* harmony import */ var _OffsetOptions__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./OffsetOptions */ "../../core/geometry/lib/esm/curve/OffsetOptions.js");
@@ -235050,7 +235250,7 @@ __webpack_require__.r(__webpack_exports__);
235050
235250
  /* harmony import */ var _Query_ConsolidateAdjacentPrimitivesContext__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./Query/ConsolidateAdjacentPrimitivesContext */ "../../core/geometry/lib/esm/curve/Query/ConsolidateAdjacentPrimitivesContext.js");
235051
235251
  /* harmony import */ var _Query_CurveSplitContext__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./Query/CurveSplitContext */ "../../core/geometry/lib/esm/curve/Query/CurveSplitContext.js");
235052
235252
  /* harmony import */ var _Query_InOutTests__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./Query/InOutTests */ "../../core/geometry/lib/esm/curve/Query/InOutTests.js");
235053
- /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
235253
+ /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
235054
235254
  /* harmony import */ var _RegionMomentsXY__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RegionMomentsXY */ "../../core/geometry/lib/esm/curve/RegionMomentsXY.js");
235055
235255
  /* harmony import */ var _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./RegionOpsClassificationSweeps */ "../../core/geometry/lib/esm/curve/RegionOpsClassificationSweeps.js");
235056
235256
  /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
@@ -235099,6 +235299,7 @@ __webpack_require__.r(__webpack_exports__);
235099
235299
 
235100
235300
 
235101
235301
 
235302
+
235102
235303
 
235103
235304
 
235104
235305
  /**
@@ -235400,16 +235601,17 @@ class RegionOps {
235400
235601
  * @param loopsB second set of loops (treated as a union)
235401
235602
  * @param operation indicates Union, Intersection, Parity, AMinusB, or BMinusA
235402
235603
  * @param mergeTolerance absolute distance tolerance for merging loops
235403
- * @returns a region resulting from merging input loops and the boolean operation. May contain bridge edges added
235404
- * to connect interior loops to exterior loops.
235604
+ * @returns a region resulting from merging input loops and the boolean operation.
235405
235605
  */
235406
235606
  static regionBooleanXY(loopsA, loopsB, operation, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
235407
- let result;
235607
+ const result = _UnionRegion__WEBPACK_IMPORTED_MODULE_14__.UnionRegion.create();
235408
235608
  const context = _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionBooleanContext.create(_RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union);
235409
235609
  context.addMembers(loopsA, loopsB);
235410
235610
  context.annotateAndMergeCurvesInGraph(mergeTolerance);
235611
+ const visitMask = context.graph.grabMask(false);
235411
235612
  const range = context.groupA.range().union(context.groupB.range());
235412
235613
  const areaTol = this.computeXYAreaTolerance(range, mergeTolerance);
235614
+ const bridgeMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE;
235413
235615
  context.runClassificationSweep(operation, (_graph, face, faceType, area) => {
235414
235616
  // ignore danglers and null faces, but not 2-edge "banana" faces with nonzero area
235415
235617
  if (face.countEdgesAroundFace() < 2)
@@ -235417,15 +235619,13 @@ class RegionOps {
235417
235619
  if (Math.abs(area) < areaTol)
235418
235620
  return;
235419
235621
  if (faceType === 1) {
235420
- const loop = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_15__.PlanarSubdivision.createLoopInFace(face);
235421
- if (loop) {
235422
- if (!result)
235423
- result = _UnionRegion__WEBPACK_IMPORTED_MODULE_14__.UnionRegion.create();
235424
- result.tryAddChild(loop);
235425
- }
235622
+ const loopOrParityRegion = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.createLoopOrParityRegionInFace(face, bridgeMask, visitMask);
235623
+ if (loopOrParityRegion)
235624
+ result.tryAddChild(loopOrParityRegion);
235426
235625
  }
235427
235626
  });
235428
- return result ? this.simplifyRegion(result) : undefined;
235627
+ context.graph.dropMask(visitMask);
235628
+ return this.simplifyRegion(result);
235429
235629
  }
235430
235630
  /**
235431
235631
  * Return a polyface whose facets are a boolean operation between the input regions.
@@ -235458,7 +235658,7 @@ class RegionOps {
235458
235658
  const graph = _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionOpsFaceToFaceSearch.doBinaryBooleanBetweenMultiLoopInputs(inputA, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, operation, inputB, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, true);
235459
235659
  if (!graph)
235460
235660
  return undefined;
235461
- const loopEdges = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_16__.HalfEdgeGraphSearch.collectExtendedBoundaryLoopsInGraph(graph, _topology_Graph__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeMask.EXTERIOR);
235661
+ const loopEdges = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeGraphSearch.collectExtendedBoundaryLoopsInGraph(graph, _topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.EXTERIOR);
235462
235662
  const allLoops = [];
235463
235663
  for (const graphLoop of loopEdges) {
235464
235664
  const points = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray();
@@ -235740,19 +235940,45 @@ class RegionOps {
235740
235940
  }
235741
235941
  return _geometry3d_SortablePolygon__WEBPACK_IMPORTED_MODULE_33__.SortablePolygon.sortAsAnyRegion(loopAndArea);
235742
235942
  }
235943
+ /**
235944
+ * Collect inputs that are nominally closed: regions, and physically closed curves.
235945
+ * * Physically closed input curves are each returned wrapped in a Loop to facilitate xy-algorithms,
235946
+ * but outside this limited context, these Loops only makes sense if they are planar.
235947
+ */
235948
+ static collectRegionsAndClosedPrimitives(curves, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
235949
+ const regions = [];
235950
+ if (!Array.isArray(curves))
235951
+ curves = [curves];
235952
+ for (const curve of curves) {
235953
+ 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) {
235954
+ regions.push(curve);
235955
+ }
235956
+ else if (curve instanceof _Path__WEBPACK_IMPORTED_MODULE_24__.Path) {
235957
+ if (curve.isPhysicallyClosedCurve(tolerance))
235958
+ regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(...curve.children));
235959
+ }
235960
+ else if (curve instanceof _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__.CurvePrimitive) {
235961
+ if (curve.isPhysicallyClosedCurve(tolerance))
235962
+ regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(curve));
235963
+ }
235964
+ }
235965
+ return regions;
235966
+ }
235743
235967
  /**
235744
235968
  * Find all xy-areas bounded by the unstructured, possibly intersecting curves.
235745
235969
  * * For best results, input curves should be parallel to the xy-plane, as z-coordinates are ignored.
235746
- * * A common use case of this method is to assemble the bounding "exterior" loop (or loops) containing the
235747
- * input curves. Note that "holes" implied by inputs are _not_ preserved in output.
235748
- * * This method does not add bridge edges to connect outer loops to inner loops. Each disconnected loop,
235749
- * regardless of its containment, is returned as its own SignedLoops object. Pre-process with [[regionBooleanXY]]
235750
- * to add bridge edges so that [[constructAllXYRegionLoops]] will return outer and inner loops in the same
235751
- * SignedLoops object.
235752
- * @param curvesAndRegions Any collection of curves. Each Loop/ParityRegion/UnionRegion contributes its curve
235753
- * primitives, stripped of parity context. This means holes are _not_ preserved in output.
235970
+ * * "Holes" implied/bounded by inputs are _not_ preserved/discovered in output; in particular [[ParityRegion]]
235971
+ * hole loops are treated like any other positive area loops.
235972
+ * * A common use case of this method is to assemble the bounding negative-area "exterior" loop for each connected
235973
+ * component of input curves. Passing `addBridges = true` decreases the number of connected components for nested
235974
+ * input [[Loop]]s, and thus increases the likelihood of returning exactly one exterior loop. (This is why the
235975
+ * default value for `addBridges` is `true`.)
235976
+ * @param curvesAndRegions Any collection of curves. Each [[AnyRegion]] contributes its children _stripped of
235977
+ * parity context_.
235754
235978
  * @param tolerance optional distance tolerance for coincidence.
235755
- * @returns array of [[SignedLoops]], each entry of which describes the faces in a single connected component:
235979
+ * @param addBridges whether to add line segments to connect nested input [[Loop]]s (default is `true`). When `false`,
235980
+ * no line segments are added to the input curves, but the number of output components may be greater than expected.
235981
+ * @returns array of [[SignedLoops]], each entry of which describes the areas bounded by a single connected component:
235756
235982
  * * `positiveAreaLoops` contains "interior" loops, _including holes in ParityRegion input_. These loops have
235757
235983
  * positive area and counterclockwise orientation.
235758
235984
  * * `negativeAreaLoops` contains (probably just one) "exterior" loop which is ordered clockwise.
@@ -235760,14 +235986,25 @@ class RegionOps {
235760
235986
  * * `edges` contains a [[LoopCurveLoopCurve]] object for each component edge, collecting both loops adjacent
235761
235987
  * to the edge and a constituent curve in each.
235762
235988
  */
235763
- static constructAllXYRegionLoops(curvesAndRegions, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
235989
+ static constructAllXYRegionLoops(curvesAndRegions, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance, addBridges = true) {
235764
235990
  let primitives = RegionOps.collectCurvePrimitives(curvesAndRegions, undefined, true, true);
235765
235991
  primitives = _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_34__.TransferWithSplitArcs.clone(_CurveCollection__WEBPACK_IMPORTED_MODULE_25__.BagOfCurves.create(...primitives)).children;
235766
235992
  const range = this.curveArrayRange(primitives);
235767
235993
  const areaTol = this.computeXYAreaTolerance(range, tolerance);
235768
- const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_35__.CurveCurve.allIntersectionsAmongPrimitivesXY(primitives, tolerance);
235769
- const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_15__.PlanarSubdivision.assembleHalfEdgeGraph(primitives, intersections, tolerance);
235770
- return _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_15__.PlanarSubdivision.collectSignedLoopSetsInHalfEdgeGraph(graph, areaTol);
235994
+ if (addBridges) { // generate a temp graph to extract its bridge edges
235995
+ const context = _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionBooleanContext.create(_RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union);
235996
+ const regions = this.collectRegionsAndClosedPrimitives(curvesAndRegions, tolerance);
235997
+ context.addMembers(regions, undefined);
235998
+ context.annotateAndMergeCurvesInGraph(tolerance);
235999
+ context.graph.announceEdges((_graph, edge) => {
236000
+ if (edge.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE))
236001
+ primitives.push(_LineSegment3d__WEBPACK_IMPORTED_MODULE_35__.LineSegment3d.create(edge.getPoint3d(), edge.faceSuccessor.getPoint3d()));
236002
+ return true;
236003
+ });
236004
+ }
236005
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_36__.CurveCurve.allIntersectionsAmongPrimitivesXY(primitives, tolerance);
236006
+ const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.assembleHalfEdgeGraph(primitives, intersections, tolerance);
236007
+ return _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.collectSignedLoopSetsInHalfEdgeGraph(graph, areaTol);
235771
236008
  }
235772
236009
  /**
235773
236010
  * Collect all `CurvePrimitives` in loosely typed input.
@@ -235823,12 +236060,12 @@ class RegionOps {
235823
236060
  * @param worldToLocal transform to apply to data before computing its range
235824
236061
  */
235825
236062
  static curveArrayRange(data, worldToLocal) {
235826
- const range = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_36__.Range3d.create();
235827
- if (data instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_37__.GeometryQuery)
236063
+ const range = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_37__.Range3d.create();
236064
+ if (data instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__.GeometryQuery)
235828
236065
  data.extendRange(range, worldToLocal);
235829
236066
  else if (Array.isArray(data)) {
235830
236067
  for (const c of data) {
235831
- if (c instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_37__.GeometryQuery)
236068
+ if (c instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__.GeometryQuery)
235832
236069
  c.extendRange(range, worldToLocal);
235833
236070
  else if (c instanceof _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d)
235834
236071
  range.extendPoint(c, worldToLocal);
@@ -235864,7 +236101,7 @@ class RegionOps {
235864
236101
  for (const polygon of polygons)
235865
236102
  writablePolygons.push(_geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray.create(polygon));
235866
236103
  }
235867
- const sortedPolygons = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_38__.PolygonOps.sortOuterAndHoleLoopsXY(writablePolygons);
236104
+ const sortedPolygons = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_39__.PolygonOps.sortOuterAndHoleLoopsXY(writablePolygons);
235868
236105
  if (sortedPolygons.length === 1) { // below requires exactly one outer loop!
235869
236106
  if (graph = _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__.Triangulator.createTriangulatedGraphFromLoops(sortedPolygons[0]))
235870
236107
  _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__.Triangulator.flipTriangles(graph);
@@ -235947,7 +236184,7 @@ class RegionOps {
235947
236184
  if (!graph)
235948
236185
  return undefined;
235949
236186
  if (options?.maximizeConvexFacets)
235950
- _topology_Merging__WEBPACK_IMPORTED_MODULE_39__.HalfEdgeGraphOps.expandConvexFaces(graph);
236187
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_40__.HalfEdgeGraphOps.expandConvexFaces(graph);
235951
236188
  return _polyface_PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_12__.PolyfaceBuilder.graphToPolyface(graph, options);
235952
236189
  }
235953
236190
  /**
@@ -235961,10 +236198,10 @@ class RegionOps {
235961
236198
  if (!graph)
235962
236199
  return undefined;
235963
236200
  if (maximize)
235964
- _topology_Merging__WEBPACK_IMPORTED_MODULE_39__.HalfEdgeGraphOps.expandConvexFaces(graph);
236201
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_40__.HalfEdgeGraphOps.expandConvexFaces(graph);
235965
236202
  const convexPolygons = [];
235966
236203
  graph.announceFaceLoops((_graph, seed) => {
235967
- if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeMask.EXTERIOR))
236204
+ if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.EXTERIOR))
235968
236205
  convexPolygons.push(_geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray.create(seed.collectAroundFace((node) => { return node.getPoint3d(); })));
235969
236206
  return true;
235970
236207
  });
@@ -235989,9 +236226,11 @@ class ConsolidateAdjacentCurvePrimitivesOptions {
235989
236226
  consolidateLinearGeometry = true;
235990
236227
  /** True to consolidate contiguous compatible arcs into a single Arc3d. */
235991
236228
  consolidateCompatibleArcs = true;
236229
+ /** True to consolidate the first and last primitives of a [[Loop]], allowing the start/end point to change. */
236230
+ consolidateLoopSeam = false;
235992
236231
  /** Disable LineSegment3d and LineString3d point compression. */
235993
236232
  disableLinearCompression = false;
235994
- /** Tolerance for collapsing identical points (if `!disableLinearCompression`). */
236233
+ /** Tolerance for detecting identical points. */
235995
236234
  duplicatePointTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance;
235996
236235
  /** Tolerance for removing interior colinear points (if `!disableLinearCompression`). */
235997
236236
  colinearPointTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance;
@@ -236013,6 +236252,7 @@ __webpack_require__.r(__webpack_exports__);
236013
236252
  /* harmony export */ GraphComponentArray: () => (/* binding */ GraphComponentArray),
236014
236253
  /* harmony export */ RegionBooleanContext: () => (/* binding */ RegionBooleanContext),
236015
236254
  /* harmony export */ RegionGroup: () => (/* binding */ RegionGroup),
236255
+ /* harmony export */ RegionGroupMember: () => (/* binding */ RegionGroupMember),
236016
236256
  /* harmony export */ RegionGroupOpType: () => (/* binding */ RegionGroupOpType),
236017
236257
  /* harmony export */ RegionOpsFaceToFaceSearch: () => (/* binding */ RegionOpsFaceToFaceSearch)
236018
236258
  /* harmony export */ });
@@ -236025,15 +236265,15 @@ __webpack_require__.r(__webpack_exports__);
236025
236265
  /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
236026
236266
  /* harmony import */ var _topology_RegularizeFace__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../topology/RegularizeFace */ "../../core/geometry/lib/esm/topology/RegularizeFace.js");
236027
236267
  /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
236028
- /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
236029
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
236268
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
236269
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
236030
236270
  /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
236031
236271
  /* harmony import */ var _internalContexts_PlaneAltitudeRangeContext__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./internalContexts/PlaneAltitudeRangeContext */ "../../core/geometry/lib/esm/curve/internalContexts/PlaneAltitudeRangeContext.js");
236032
236272
  /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
236033
236273
  /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
236034
236274
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
236035
236275
  /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
236036
- /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
236276
+ /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
236037
236277
  /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
236038
236278
  /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
236039
236279
  /*---------------------------------------------------------------------------------------------
@@ -236537,6 +236777,94 @@ class RegionBooleanContext {
236537
236777
  this.extraGeometry.addMember(bridgeLine, true);
236538
236778
  }
236539
236779
  }
236780
+ /**
236781
+ * Simplify the graph by removing bridge edges that do not serve to connect inner and outer loops, i.e.:
236782
+ * * the bridge edge is dangling
236783
+ * * the bridge edge is adjacent to multiple faces
236784
+ * * the bridge edge is adjacent to a negative area face
236785
+ * @returns the number of extraneous bridge edges removed from the graph.
236786
+ */
236787
+ removeExtraneousBridgeEdges() {
236788
+ const toHeal = [];
236789
+ const interiorBridges = [];
236790
+ // lambda test for boundary edge. Relies only on face loop orientation. Doesn't use HalfEdgeMasks!
236791
+ const isExteriorEdge = (node) => {
236792
+ if (this.faceAreaFunction(node) < 0.0)
236793
+ return true;
236794
+ if (!node.findAroundFace(node.edgeMate))
236795
+ return this.faceAreaFunction(node.edgeMate) < 0.0;
236796
+ return false;
236797
+ };
236798
+ // isolate dangling bridges, bridges separating different faces, and "exterior" bridges in the negative area face
236799
+ this.graph.announceEdges((_graph, node) => {
236800
+ if (node.edgeTag !== undefined) {
236801
+ if (node.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail) {
236802
+ if (node.edgeTag.curve) {
236803
+ if (node.edgeTag.curve.parent instanceof RegionGroupMember) {
236804
+ if (node.edgeTag.curve.parent.parentGroup === this.extraGeometry) {
236805
+ if (node.isDangling || node.edgeMate.isDangling || !node.findAroundFace(node.edgeMate) || this.faceAreaFunction(node) < 0.0) {
236806
+ toHeal.push(node.vertexSuccessor);
236807
+ toHeal.push(node.edgeMate.vertexSuccessor);
236808
+ node.isolateEdge();
236809
+ }
236810
+ else {
236811
+ interiorBridges.push(node);
236812
+ }
236813
+ }
236814
+ }
236815
+ }
236816
+ }
236817
+ }
236818
+ return true;
236819
+ });
236820
+ // At this point, all bridges that were exterior are isolated, but this may have caused formerly
236821
+ // interior bridges to become exterior. Now we successively isolate exterior bridges until none remain.
236822
+ let numIsolatedThisPass;
236823
+ do {
236824
+ numIsolatedThisPass = 0;
236825
+ for (const node of interiorBridges) {
236826
+ if (!node.isIsolatedEdge && isExteriorEdge(node)) {
236827
+ toHeal.push(node.vertexSuccessor);
236828
+ toHeal.push(node.edgeMate.vertexSuccessor);
236829
+ node.isolateEdge();
236830
+ numIsolatedThisPass++;
236831
+ }
236832
+ }
236833
+ } while (numIsolatedThisPass > 0);
236834
+ // lambda to extend the detail interval on a side of a healed edge
236835
+ const mergeDetails = (he, newFraction, newPoint) => {
236836
+ if (he && he.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && he.sortData !== undefined && newFraction !== undefined && newPoint) {
236837
+ if (he.sortData > 0)
236838
+ he.edgeTag.captureFraction1Point1(newFraction, newPoint);
236839
+ else
236840
+ he.edgeTag.captureFractionPoint(newFraction, newPoint);
236841
+ }
236842
+ };
236843
+ // At this point all removable bridges are isolated. Clean up their original vertex loops, if possible.
236844
+ for (const doomedA of toHeal) {
236845
+ const doomedB = doomedA.vertexSuccessor;
236846
+ if ( // are the geometries mergeable?
236847
+ doomedA !== doomedB &&
236848
+ doomedA.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && doomedA.sortData !== undefined &&
236849
+ doomedB.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && doomedB.sortData !== undefined &&
236850
+ doomedA.edgeTag.curve === doomedB.edgeTag.curve &&
236851
+ doomedA.edgeTag.hasFraction1 && doomedB.edgeTag.hasFraction1 &&
236852
+ doomedA.sortData * doomedB.sortData < 0 &&
236853
+ ((doomedA.sortData > 0 && _Geometry__WEBPACK_IMPORTED_MODULE_7__.Geometry.isSmallRelative(doomedA.edgeTag.fraction - doomedB.edgeTag.fraction1)) ||
236854
+ (doomedA.sortData < 0 && _Geometry__WEBPACK_IMPORTED_MODULE_7__.Geometry.isSmallRelative(doomedA.edgeTag.fraction1 - doomedB.edgeTag.fraction)))) {
236855
+ const survivorA = _topology_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdge.healEdge(doomedA, false);
236856
+ if (survivorA) {
236857
+ const endFractionA = (doomedA.sortData > 0) ? doomedA.edgeTag.fraction1 : doomedA.edgeTag.fraction;
236858
+ const endPointA = (doomedA.sortData > 0) ? doomedA.edgeTag.point1 : doomedA.edgeTag.point;
236859
+ mergeDetails(survivorA, endFractionA, endPointA);
236860
+ const endFractionB = (doomedB.sortData > 0) ? doomedB.edgeTag.fraction1 : doomedB.edgeTag.fraction;
236861
+ const endPointB = (doomedB.sortData > 0) ? doomedB.edgeTag.point1 : doomedB.edgeTag.point;
236862
+ mergeDetails(survivorA.edgeMate, endFractionB, endPointB);
236863
+ }
236864
+ }
236865
+ }
236866
+ return this.graph.deleteIsolatedEdges();
236867
+ }
236540
236868
  /**
236541
236869
  * Markup and assembly steps for geometry in the RegionGroups.
236542
236870
  * * Annotate connection from group to curves.
@@ -236558,10 +236886,11 @@ class RegionBooleanContext {
236558
236886
  }
236559
236887
  }
236560
236888
  }
236561
- const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_16__.CurveCurve.allIntersectionsAmongPrimitivesXY(allPrimitives, mergeTolerance);
236562
- const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_17__.PlanarSubdivision.assembleHalfEdgeGraph(allPrimitives, intersections, mergeTolerance);
236889
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_17__.CurveCurve.allIntersectionsAmongPrimitivesXY(allPrimitives, mergeTolerance);
236890
+ const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_18__.PlanarSubdivision.assembleHalfEdgeGraph(allPrimitives, intersections, mergeTolerance);
236563
236891
  this.graph = graph;
236564
236892
  this.faceAreaFunction = faceAreaFromCurvedEdgeData;
236893
+ this.removeExtraneousBridgeEdges();
236565
236894
  }
236566
236895
  _announceFaceFunction;
236567
236896
  /**
@@ -236649,7 +236978,7 @@ class RegionBooleanContext {
236649
236978
  const data = node.edgeTag;
236650
236979
  if (data instanceof RegionGroupMember)
236651
236980
  return updateRegionGroupMemberState(data);
236652
- if (data instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_18__.CurveLocationDetail) {
236981
+ if (data instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail) {
236653
236982
  // We trust that the caller has linked from the graph node to a curve which has a RegionGroupMember as its parent.
236654
236983
  const member = data.curve.parent;
236655
236984
  if (member instanceof RegionGroupMember)
@@ -238419,23 +238748,23 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
238419
238748
  let reversed = false;
238420
238749
  const uu = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.hypotenuseSquaredXY(ux, uy);
238421
238750
  if (hab0 * hab0 <= maxDistanceSquared * uu) { // test distance of b0 to u
238422
- const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e00x, e00y) / uu;
238751
+ const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e00x, e00y), uu, 0.0);
238423
238752
  if (this.updatePointToSegmentDistance(0, b0, a0, a1, fractionA, maxDistanceSquared, closestApproach))
238424
238753
  reversed = true;
238425
238754
  }
238426
238755
  if (hab1 * hab1 <= maxDistanceSquared * uu) { // test distance of b1 to u
238427
- const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e01x, e01y) / uu;
238756
+ const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e01x, e01y), uu, 0.0);
238428
238757
  if (this.updatePointToSegmentDistance(1, b1, a0, a1, fractionA, maxDistanceSquared, closestApproach))
238429
238758
  reversed = true;
238430
238759
  }
238431
238760
  const vv = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.hypotenuseSquaredXY(vx, vy);
238432
238761
  if (hba0 * hba0 <= maxDistanceSquared * vv) { // test distance of a0 to v
238433
- const fractionB = -_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e00x, e00y) / vv;
238762
+ const fractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(-_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e00x, e00y), vv, 0.0);
238434
238763
  if (this.updatePointToSegmentDistance(0, a0, b0, b1, fractionB, maxDistanceSquared, closestApproach))
238435
238764
  reversed = false;
238436
238765
  }
238437
238766
  if (hba1 * hba1 <= maxDistanceSquared * vv) { // test distance of a1 to v
238438
- const fractionB = -_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e10x, e10y) / vv;
238767
+ const fractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(-_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e10x, e10y), vv, 0.0);
238439
238768
  if (this.updatePointToSegmentDistance(1, a1, b0, b1, fractionB, maxDistanceSquared, closestApproach))
238440
238769
  reversed = false;
238441
238770
  }
@@ -238513,7 +238842,7 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
238513
238842
  return undefined;
238514
238843
  }
238515
238844
  /**
238516
- * Find the closest approach between `pointA` and `cpB`. Add the approach if it's within `fB0` and `fB1`.
238845
+ * Find the closest xy approach between `pointA` and `cpB`. Add the approach if it's within `fB0` and `fB1`.
238517
238846
  * * Does not test the endpoints of `cpB`.
238518
238847
  * * The only types supported for `cpB` are Arc3d, LineSegment3d, and LineString3d.
238519
238848
  * * If `cpB` is a LineString3d, then the interval `[fB0, fB1]` must correspond to a segment of the line string.
@@ -238538,7 +238867,7 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
238538
238867
  }
238539
238868
  }
238540
238869
  /**
238541
- * Compute intersection of two line segments.
238870
+ * Compute closest xy approach of two line segments.
238542
238871
  * Filter by extension rules.
238543
238872
  * Record with fraction mapping.
238544
238873
  * * The fraction mappings allow portions of a linestring to be passed here.
@@ -246814,7 +247143,7 @@ class AngleSweep {
246814
247143
  result.setStartEndRadians(startRadians, endRadians);
246815
247144
  return result;
246816
247145
  }
246817
- /** Return the angle obtained by subtracting radians from this angle. */
247146
+ /** Return the AngleSweep obtained by subtracting radians from the start and end angles of this sweep. */
246818
247147
  cloneMinusRadians(radians) {
246819
247148
  return new AngleSweep(this._radians0 - radians, this._radians1 - radians);
246820
247149
  }
@@ -248505,7 +248834,7 @@ __webpack_require__.r(__webpack_exports__);
248505
248834
  * For the equator circle, phi=0, cos(phi) = 1, sin(phi)=0
248506
248835
  * f = u * cos(theta) + v * sin(theta).
248507
248836
  * with derivative
248508
- * df / dTheta = = u * sin(theta) + v * cos(theta)
248837
+ * df / dTheta = - u * sin(theta) + v * cos(theta)
248509
248838
  * whose zero is tan(theta) = v/u
248510
248839
  * (and that has two solutions 180 degrees apart)
248511
248840
  * Then with that theta let A = u * cos(theta) + v * sin(theta)
@@ -253161,6 +253490,7 @@ class IndexedXYZCollection {
253161
253490
  * @param index0 index of first point
253162
253491
  * @param index1 index of second point
253163
253492
  * @param tolerance max coordinate difference to be considered equal. For exact test, pass 0. Defaults to `Geometry.smallMetricDistance`.
253493
+ * @returns whether the points are equal within tolerance, or `undefined` if either index is invalid.
253164
253494
  */
253165
253495
  almostEqualIndexIndex(index0, index1, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
253166
253496
  if (index0 < 0 || index0 >= this.length || index1 < 0 || index1 >= this.length)
@@ -253169,6 +253499,19 @@ class IndexedXYZCollection {
253169
253499
  && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getYAtUncheckedPointIndex(index0), this.getYAtUncheckedPointIndex(index1), tolerance)
253170
253500
  && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getZAtUncheckedPointIndex(index0), this.getZAtUncheckedPointIndex(index1), tolerance);
253171
253501
  }
253502
+ /**
253503
+ * Test whether the xy-coordinates of the indexed points are equal within tolerance. The z-coordinates are ignored.
253504
+ * @param index0 index of first point
253505
+ * @param index1 index of second point
253506
+ * @param tolerance max coordinate difference to be considered equal. For exact test, pass 0. Defaults to `Geometry.smallMetricDistance`.
253507
+ * @returns whether the xy-coordinates of the points are equal within tolerance, or `undefined` if either index is invalid.
253508
+ */
253509
+ almostEqualXYIndexIndex(index0, index1, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
253510
+ if (index0 < 0 || index0 >= this.length || index1 < 0 || index1 >= this.length)
253511
+ return undefined;
253512
+ return _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getXAtUncheckedPointIndex(index0), this.getXAtUncheckedPointIndex(index1), tolerance)
253513
+ && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getYAtUncheckedPointIndex(index0), this.getYAtUncheckedPointIndex(index1), tolerance);
253514
+ }
253172
253515
  }
253173
253516
  /**
253174
253517
  * abstract base class extends IndexedXYZCollection, adding methods to push, peek, and pop, and rewrite.
@@ -265707,13 +266050,11 @@ class Ray3d {
265707
266050
  return new Ray3d(_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.createZero(), _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.createZero());
265708
266051
  }
265709
266052
  /**
265710
- * Test for nearly equal Ray3d objects.
265711
- * * This tests for near equality of origin and direction -- i.e. member-by-member comparison.
265712
- * * Use [[isAlmostEqualPointSet]] to allow origins to be anywhere along the common ray and to have to allow the
265713
- * directions to be scaled or opposing.
266053
+ * Test for nearly equal Ray3d objects by comparing their origin and direction members.
266054
+ * @see [[isAlmostEqualPointSet]] to test for rays on the same infinite line.
265714
266055
  */
265715
- isAlmostEqual(other) {
265716
- return this.origin.isAlmostEqual(other.origin) && this.direction.isAlmostEqual(other.direction);
266056
+ isAlmostEqual(other, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
266057
+ return this.origin.isAlmostEqual(other.origin, tolerance) && this.direction.isAlmostEqual(other.direction, tolerance);
265717
266058
  }
265718
266059
  /**
265719
266060
  * Return the dot product of the ray's direction vector with a vector from the ray origin
@@ -265741,27 +266082,19 @@ class Ray3d {
265741
266082
  return this.origin.plusScaled(this.direction, this.pointToFraction(spacePoint));
265742
266083
  }
265743
266084
  /**
265744
- * Test for nearly equal rays, allowing origin float and direction scaling.
265745
- * * Use [[isAlmostEqual]] to require member-by-member comparison.
266085
+ * Test for rays that describe the same infinite line.
266086
+ * @see [[isAlmostEqual]] for member-by-member comparison.
265746
266087
  */
265747
- isAlmostEqualPointSet(other) {
265748
- /**
265749
- * This function tests two rays to determine if they define the same infinite lines.
265750
- * So the origins can be different as long as they are on the infinite line (they can
265751
- * "float") but the directions must be parallel or antiparallel.
265752
- */
265753
- if (!this.direction.isParallelTo(other.direction, true))
266088
+ isAlmostEqualPointSet(other, options) {
266089
+ if (!this.direction.isParallelTo(other.direction, true, false, options))
265754
266090
  return false;
265755
- /**
265756
- * In exact math, we consider a ray to have an infinite line as direction (not a finite vector).
265757
- * Therefore, in exact math it is not possible for one origin to be on the other ray but not vice
265758
- * versa. However, we test both ways because first check may pass due to round-off errors.
265759
- */
266091
+ const tol2 = options?.distanceSquaredTol ?? _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistanceSquared;
266092
+ // theoretically, one test below is sufficient, but perform both in case the first passes because of round-off
265760
266093
  let workPoint = this.projectPointToRay(other.origin);
265761
- if (!other.origin.isAlmostEqualMetric(workPoint))
266094
+ if (other.origin.distanceSquared(workPoint) > tol2)
265762
266095
  return false;
265763
266096
  workPoint = other.projectPointToRay(this.origin);
265764
- if (!this.origin.isAlmostEqualMetric(workPoint))
266097
+ if (this.origin.distanceSquared(workPoint) > tol2)
265765
266098
  return false;
265766
266099
  return true;
265767
266100
  }
@@ -266456,19 +266789,25 @@ __webpack_require__.r(__webpack_exports__);
266456
266789
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
266457
266790
  /* harmony export */ SortablePolygon: () => (/* binding */ SortablePolygon)
266458
266791
  /* harmony export */ });
266459
- /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
266460
- /* harmony import */ var _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../curve/CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
266461
- /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
266462
- /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
266463
- /* harmony import */ var _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../curve/ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
266464
- /* harmony import */ var _curve_RegionOps__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
266465
- /* harmony import */ var _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../curve/UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
266466
- /* harmony import */ var _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
266467
- /* harmony import */ var _PolygonOps__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
266792
+ /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
266793
+ /* harmony import */ var _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../curve/CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
266794
+ /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
266795
+ /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
266796
+ /* harmony import */ var _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../curve/ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
266797
+ /* harmony import */ var _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../curve/RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
266798
+ /* harmony import */ var _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../curve/UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
266799
+ /* harmony import */ var _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
266800
+ /* harmony import */ var _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
266801
+ /* harmony import */ var _PolygonOps__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
266802
+ /* harmony import */ var _Ray3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
266468
266803
  /*---------------------------------------------------------------------------------------------
266469
266804
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
266470
266805
  * See LICENSE.md in the project root for license terms and full copyright notice.
266471
266806
  *--------------------------------------------------------------------------------------------*/
266807
+ /** @packageDocumentation
266808
+ * @module CartesianGeometry
266809
+ */
266810
+
266472
266811
 
266473
266812
 
266474
266813
 
@@ -266478,14 +266817,37 @@ __webpack_require__.r(__webpack_exports__);
266478
266817
 
266479
266818
 
266480
266819
 
266481
- /** abstract base class for area-related queries of a loop.
266482
- * * subclasses have particular logic for `Loop` and polygon data.
266820
+
266821
+ /** Abstract base class for area-related queries of an xy-loop.
266822
+ * * Subclasses have particular logic for `Loop` and polygon data.
266483
266823
  * @internal
266484
266824
  */
266485
266825
  class SimpleRegionCarrier {
266826
+ /** Fractions for interior point search. */
266827
+ searchFractions = [0.2349, 0.4142, 0.6587, 0.8193];
266828
+ /**
266829
+ * Given a region boundary tangent, construct a point interior to the region.
266830
+ * @param ray point and tangent on an edge of the region (modified on return)
266831
+ */
266832
+ constructInteriorPoint(ray) {
266833
+ ray.direction.z = 0.0;
266834
+ if (!ray.direction.normalizeInPlace())
266835
+ return undefined; // loop has zero length edge, or a vertical (gap) edge
266836
+ ray.direction.rotate90CCWXY(ray.direction);
266837
+ if (this.signedArea < 0.0)
266838
+ ray.direction.scaleInPlace(-1.0); // aim toward the region interior
266839
+ const refDistance = Math.sqrt(Math.abs(this.signedArea));
266840
+ const candidatePoint = _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
266841
+ for (let fraction = 1.0e-5; fraction < 3; fraction *= 5.0) {
266842
+ ray.fractionToPoint(fraction * refDistance, candidatePoint);
266843
+ if (1 === this.classifyPointXY(candidatePoint))
266844
+ return candidatePoint;
266845
+ }
266846
+ return undefined;
266847
+ }
266486
266848
  }
266487
266849
  /**
266488
- * Implement `LoopCarrier` queries with the area as a polygon carried in an `IndexedReadWriteXYZCollection`
266850
+ * Implement `SimpleRegionCarrier` queries with the area as a polygon carried in an `IndexedReadWriteXYZCollection`.
266489
266851
  */
266490
266852
  class PolygonCarrier extends SimpleRegionCarrier {
266491
266853
  data;
@@ -266494,7 +266856,7 @@ class PolygonCarrier extends SimpleRegionCarrier {
266494
266856
  constructor(data) {
266495
266857
  super();
266496
266858
  this.data = data;
266497
- this._signedArea = _PolygonOps__WEBPACK_IMPORTED_MODULE_0__.PolygonOps.areaXY(data);
266859
+ this._signedArea = _PolygonOps__WEBPACK_IMPORTED_MODULE_1__.PolygonOps.areaXY(data);
266498
266860
  }
266499
266861
  /**
266500
266862
  * classify xy parts of point wrt this loop.
@@ -266502,22 +266864,22 @@ class PolygonCarrier extends SimpleRegionCarrier {
266502
266864
  * @internal
266503
266865
  */
266504
266866
  classifyPointXY(xy) {
266505
- return _PolygonOps__WEBPACK_IMPORTED_MODULE_0__.PolygonOps.classifyPointInPolygonXY(xy.x, xy.y, this.data);
266867
+ return _PolygonOps__WEBPACK_IMPORTED_MODULE_1__.PolygonOps.classifyPointInPolygonXY(xy.x, xy.y, this.data);
266506
266868
  }
266507
- /** Return some point "inside"
266508
- * NEEDS WORK: this returns a point ON --
266509
- */
266869
+ /** Return some point "inside". */
266510
266870
  getAnyInteriorPoint() {
266511
266871
  for (let childIndex = 0; childIndex < this.data.length; childIndex++) {
266512
- const q = this.constructInteriorPointNearEdge(childIndex, 0.2349);
266513
- if (q !== undefined)
266514
- return q;
266872
+ for (const fraction of this.searchFractions) {
266873
+ const q = this.constructInteriorPointNearEdge(childIndex, fraction);
266874
+ if (q !== undefined)
266875
+ return q;
266876
+ }
266515
266877
  }
266516
266878
  return undefined;
266517
266879
  }
266518
266880
  grabPolygon() { return this.data; }
266519
266881
  grabLoop() {
266520
- return _curve_Loop__WEBPACK_IMPORTED_MODULE_1__.Loop.createPolygon(this.data);
266882
+ return _curve_Loop__WEBPACK_IMPORTED_MODULE_2__.Loop.createPolygon(this.data);
266521
266883
  }
266522
266884
  reverseForAreaSign(targetSign) {
266523
266885
  if (targetSign * this._signedArea < 0.0) {
@@ -266527,27 +266889,14 @@ class PolygonCarrier extends SimpleRegionCarrier {
266527
266889
  }
266528
266890
  constructInteriorPointNearEdge(edgeIndex, fractionAlong) {
266529
266891
  if (edgeIndex + 1 < this.data.length) {
266530
- const point0 = this.data.getPoint3dAtUncheckedPointIndex(edgeIndex);
266531
- const point1 = this.data.getPoint3dAtUncheckedPointIndex(edgeIndex + 1);
266532
- const vector = point0.vectorTo(point1);
266533
- const point = point0.interpolate(fractionAlong, point1);
266534
- vector.rotate90CCWXY(vector);
266535
- if (vector.normalizeInPlace()) {
266536
- if (this._signedArea < 0)
266537
- vector.scaleInPlace(-1.0);
266538
- const refDistance = Math.sqrt(Math.abs(this._signedArea));
266539
- for (let fraction = 1.0e-5; fraction < 3; fraction *= 5.0) {
266540
- const candidatePoint = point.plusScaled(vector, fraction * refDistance);
266541
- if (1 === this.classifyPointXY(candidatePoint))
266542
- return candidatePoint;
266543
- }
266544
- }
266892
+ const ray = _Ray3d__WEBPACK_IMPORTED_MODULE_3__.Ray3d.createCapture(this.data.interpolateIndexIndex(edgeIndex, fractionAlong, edgeIndex + 1), this.data.vectorIndexIndex(edgeIndex, edgeIndex + 1));
266893
+ return this.constructInteriorPoint(ray);
266545
266894
  }
266546
266895
  return undefined;
266547
266896
  }
266548
266897
  }
266549
266898
  /**
266550
- * Implement `LoopCarrier` queries with the area as a strongly typed `Loop`
266899
+ * Implement `SimpleRegionCarrier` queries with the area as a strongly typed `Loop`.
266551
266900
  */
266552
266901
  class LoopCarrier extends SimpleRegionCarrier {
266553
266902
  data;
@@ -266556,7 +266905,7 @@ class LoopCarrier extends SimpleRegionCarrier {
266556
266905
  constructor(data) {
266557
266906
  super();
266558
266907
  this.data = data;
266559
- const areaMoments = _curve_RegionOps__WEBPACK_IMPORTED_MODULE_2__.RegionOps.computeXYAreaMoments(data);
266908
+ const areaMoments = _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.computeXYAreaMoments(data);
266560
266909
  this._signedArea = areaMoments !== undefined ? areaMoments.quantitySum : 0.0;
266561
266910
  }
266562
266911
  /**
@@ -266565,41 +266914,32 @@ class LoopCarrier extends SimpleRegionCarrier {
266565
266914
  * @internal
266566
266915
  */
266567
266916
  classifyPointXY(xy) {
266568
- return _curve_RegionOps__WEBPACK_IMPORTED_MODULE_2__.RegionOps.testPointInOnOutRegionXY(this.data, xy.x, xy.y);
266917
+ return _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.testPointInOnOutRegionXY(this.data, xy.x, xy.y);
266569
266918
  }
266570
266919
  constructInteriorPointNearChild(childIndex, fractionAlong) {
266571
266920
  if (childIndex < this.data.children.length) {
266572
- const primitive = this.data.children[childIndex];
266573
- const ray = primitive.fractionToPointAndUnitTangent(fractionAlong);
266574
- ray.direction.rotate90CCWXY(ray.direction);
266575
- if (this._signedArea < 0.0)
266576
- ray.direction.scaleInPlace(-1.0);
266577
- const refDistance = Math.sqrt(Math.abs(this._signedArea));
266578
- for (let fraction = 1.0e-5; fraction < 3; fraction *= 5.0) {
266579
- const candidatePoint = ray.fractionToPoint(fraction * refDistance);
266580
- if (1 === this.classifyPointXY(candidatePoint))
266581
- return candidatePoint;
266582
- }
266921
+ const ray = this.data.children[childIndex].fractionToPointAndDerivative(fractionAlong);
266922
+ return this.constructInteriorPoint(ray);
266583
266923
  }
266584
266924
  return undefined;
266585
266925
  }
266586
- /** Return some point "inside"
266587
- * NEEDS WORK: this returns a point ON --
266588
- */
266926
+ /** Return some point "inside". */
266589
266927
  getAnyInteriorPoint() {
266590
266928
  for (let childIndex = 0; childIndex < this.data.children.length; childIndex++) {
266591
- const q = this.constructInteriorPointNearChild(childIndex, 0.2349);
266592
- if (q !== undefined)
266593
- return q;
266929
+ for (const fraction of this.searchFractions) {
266930
+ const q = this.constructInteriorPointNearChild(childIndex, fraction);
266931
+ if (q !== undefined)
266932
+ return q;
266933
+ }
266594
266934
  }
266595
266935
  return undefined;
266596
266936
  }
266597
266937
  grabPolygon() {
266598
266938
  const strokes = this.data.cloneStroked();
266599
- if (strokes instanceof _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.CurveChain) {
266600
- const linestring = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_4__.LineString3d.create();
266939
+ if (strokes instanceof _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
266940
+ const linestring = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_6__.LineString3d.create();
266601
266941
  for (const child of strokes.children) {
266602
- if (child instanceof _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_5__.CurvePrimitive) {
266942
+ if (child instanceof _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_7__.CurvePrimitive) {
266603
266943
  child.emitStrokes(linestring);
266604
266944
  }
266605
266945
  }
@@ -266618,7 +266958,7 @@ class LoopCarrier extends SimpleRegionCarrier {
266618
266958
  }
266619
266959
  }
266620
266960
  /**
266621
- * A `SortablePolygon` carries a (single) loop with data useful for sorting for inner-outer structure.
266961
+ * A `SortablePolygon` carries a (single) xy-loop with data useful for sorting for inner-outer structure.
266622
266962
  * @internal
266623
266963
  */
266624
266964
  class SortablePolygon {
@@ -266634,7 +266974,7 @@ class SortablePolygon {
266634
266974
  * @param loop Loop to capture.
266635
266975
  */
266636
266976
  constructor(loop, range) {
266637
- if (loop instanceof _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_6__.IndexedReadWriteXYZCollection)
266977
+ if (loop instanceof _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_8__.IndexedReadWriteXYZCollection)
266638
266978
  this._loopCarrier = new PolygonCarrier(loop);
266639
266979
  else
266640
266980
  this._loopCarrier = new LoopCarrier(loop);
@@ -266739,7 +267079,7 @@ class SortablePolygon {
266739
267079
  const childData = loops[childIndex];
266740
267080
  if (childData.parentIndex === candidateIndex) {
266741
267081
  if (candidateParityRegion === undefined) {
266742
- candidateParityRegion = _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_7__.ParityRegion.create();
267082
+ candidateParityRegion = _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_9__.ParityRegion.create();
266743
267083
  candidateParityRegion.tryAddChild(candidateLoop);
266744
267084
  childData._loopCarrier.reverseForAreaSign(-1.0);
266745
267085
  candidateParityRegion.tryAddChild(childData._loopCarrier.grabLoop());
@@ -266764,7 +267104,7 @@ class SortablePolygon {
266764
267104
  if (regions.length === 1)
266765
267105
  return regions[0];
266766
267106
  else {
266767
- const unionRegion = _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_8__.UnionRegion.create();
267107
+ const unionRegion = _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_10__.UnionRegion.create();
266768
267108
  for (const region of regions)
266769
267109
  unionRegion.tryAddChild(region);
266770
267110
  return unionRegion;
@@ -280449,7 +280789,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
280449
280789
  /** Construct facets for a rotational sweep. */
280450
280790
  addRotationalSweep(surface) {
280451
280791
  const contour = surface.getSweepContourRef();
280452
- const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour.getCurves(), this._options);
280792
+ const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour.getCurves(), this._options);
280453
280793
  const baseStrokes = section0.getStrokes();
280454
280794
  // ensure sweep is positive for buildRotationalNormalsInLineStrings
280455
280795
  const axis = surface.cloneAxisRay();
@@ -280599,7 +280939,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
280599
280939
  /** Add facets from the linear sweep. */
280600
280940
  addLinearSweep(surface) {
280601
280941
  const contour = surface.getCurvesRef();
280602
- const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour, this._options);
280942
+ const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour, this._options);
280603
280943
  const stroke0 = section0.getStrokes();
280604
280944
  const sweepVector = surface.cloneSweepVector();
280605
280945
  const sweepTransform = _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_9__.Transform.createTranslation(sweepVector);
@@ -280621,7 +280961,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
280621
280961
  let stroke1;
280622
280962
  const sectionMaps = [];
280623
280963
  for (const contour of contours)
280624
- sectionMaps.push(_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour.curves, this._options));
280964
+ sectionMaps.push(_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour.curves, this._options));
280625
280965
  if (_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.enforceStrokeCountCompatibility(sectionMaps)) {
280626
280966
  _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.enforceCompatibleDistanceSums(sectionMaps);
280627
280967
  for (let i = 0; i < contours.length; i++) {
@@ -302156,7 +302496,7 @@ class Sphere extends _SolidPrimitive__WEBPACK_IMPORTED_MODULE_0__.SolidPrimitive
302156
302496
  const sinTheta = Math.sin(thetaRadians);
302157
302497
  const sinPhi = Math.sin(phiRadians);
302158
302498
  const cosPhi = Math.cos(phiRadians);
302159
- return _geometry3d_Plane3dByOriginAndVectors__WEBPACK_IMPORTED_MODULE_11__.Plane3dByOriginAndVectors.createOriginAndVectors(this._localToWorld.multiplyXYZ(cosTheta * cosPhi, sinTheta * cosPhi, sinPhi), this._localToWorld.matrix.multiplyXYZ(-fTheta * sinTheta, fTheta * cosTheta, 0), // !!! note cosTheta term is omitted -- scale is wrong, but remains non-zero at poles.
302499
+ return _geometry3d_Plane3dByOriginAndVectors__WEBPACK_IMPORTED_MODULE_11__.Plane3dByOriginAndVectors.createOriginAndVectors(this._localToWorld.multiplyXYZ(cosTheta * cosPhi, sinTheta * cosPhi, sinPhi), this._localToWorld.matrix.multiplyXYZ(-fTheta * sinTheta, fTheta * cosTheta, 0), // NOTE: cosPhi scale is omitted, so the u-derivative scale is wrong but at least at the poles it's nonzero
302160
302500
  this._localToWorld.matrix.multiplyXYZ(-fPhi * cosTheta * sinPhi, -fPhi * sinTheta * sinPhi, fPhi * cosPhi), result);
302161
302501
  }
302162
302502
  /**
@@ -302411,7 +302751,7 @@ class SweepContour {
302411
302751
  /**
302412
302752
  * Emit facets to a function.
302413
302753
  * This method may cache and reuse facets over multiple calls.
302414
- * @param announce callback to receive the facet set.
302754
+ * @param announce callback to receive the facet set. Called only once (if facets exist).
302415
302755
  * @param options how to stroke the contour.
302416
302756
  */
302417
302757
  announceFacets(announce, options) {
@@ -303177,13 +303517,14 @@ __webpack_require__.r(__webpack_exports__);
303177
303517
  /* harmony export */ HalfEdgeGraph: () => (/* binding */ HalfEdgeGraph),
303178
303518
  /* harmony export */ HalfEdgeMask: () => (/* binding */ HalfEdgeMask)
303179
303519
  /* harmony export */ });
303180
- /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
303181
- /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
303182
- /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
303183
- /* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
303184
- /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
303185
- /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
303186
- /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
303520
+ /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
303521
+ /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
303522
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
303523
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
303524
+ /* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
303525
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
303526
+ /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
303527
+ /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
303187
303528
  /*---------------------------------------------------------------------------------------------
303188
303529
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
303189
303530
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -303198,9 +303539,9 @@ __webpack_require__.r(__webpack_exports__);
303198
303539
 
303199
303540
 
303200
303541
 
303542
+
303201
303543
  // import { GraphChecker } from "../test/topology/Graph.test"; // used for debugging
303202
303544
  /* eslint-disable @typescript-eslint/no-this-alias */
303203
- // cspell:word CONSTU CONSTV USEAM VSEAM internaldocs
303204
303545
  /**
303205
303546
  * * Each node of the graph has a mask member.
303206
303547
  * * The mask member is a number which is used as set of single bit boolean values.
@@ -303215,14 +303556,6 @@ __webpack_require__.r(__webpack_exports__);
303215
303556
  */
303216
303557
  var HalfEdgeMask;
303217
303558
  (function (HalfEdgeMask) {
303218
- // REMARK: Various mask names are COMMENTED here for reference to native legacy code.
303219
- // CONSTU_MASK = 0x00000004,
303220
- // CONSTV_MASK = 0x00000008,
303221
- // USEAM_MASK = 0x00000010,
303222
- // VSEAM_MASK = 0x00000020,
303223
- // BOUNDARY_VERTEX_MASK = 0x00000040,
303224
- // PRIMARY_VERTEX_MASK = 0x00000080,
303225
- // DIRECTED_EDGE_MASK = 0x00000100,
303226
303559
  /**
303227
303560
  * Mask commonly set consistently around exterior faces.
303228
303561
  * * A boundary edge with interior to one side, exterior to the other, will have EXTERIOR only on the outside.
@@ -303245,22 +303578,22 @@ var HalfEdgeMask;
303245
303578
  * BOUNDARY_EDGE nor EXTERIOR_EDGE.
303246
303579
  */
303247
303580
  HalfEdgeMask[HalfEdgeMask["PRIMARY_EDGE"] = 4] = "PRIMARY_EDGE";
303248
- /** Mask used for low level searches to identify previously-visited nodes. */
303249
- HalfEdgeMask[HalfEdgeMask["VISITED"] = 16] = "VISITED";
303581
+ /** Mask set on both sides of a bridge edge added by algorithms to join loops. */
303582
+ HalfEdgeMask[HalfEdgeMask["BRIDGE_EDGE"] = 8] = "BRIDGE_EDGE";
303583
+ /** Mask set on both sides of an edge added during graph regularization. */
303584
+ HalfEdgeMask[HalfEdgeMask["REGULARIZED_EDGE"] = 16] = "REGULARIZED_EDGE";
303250
303585
  /** Mask applied to triangles by earcut triangulator. */
303251
303586
  HalfEdgeMask[HalfEdgeMask["TRIANGULATED_FACE"] = 256] = "TRIANGULATED_FACE";
303252
303587
  /** Mask applied in a face with 2 edges. */
303253
303588
  HalfEdgeMask[HalfEdgeMask["NULL_FACE"] = 512] = "NULL_FACE";
303589
+ /** Temporary mask used for low level searches to identify previously-visited nodes. */
303590
+ HalfEdgeMask[HalfEdgeMask["VISITED"] = 65536] = "VISITED";
303254
303591
  /** No mask bits. */
303255
303592
  HalfEdgeMask[HalfEdgeMask["NULL_MASK"] = 0] = "NULL_MASK";
303256
303593
  /** The "upper 12" bits of 32 bit integer reserved for grab/drop. */
303257
303594
  HalfEdgeMask[HalfEdgeMask["ALL_GRAB_DROP_MASKS"] = 4293918720] = "ALL_GRAB_DROP_MASKS";
303258
303595
  /** All mask bits */
303259
303596
  HalfEdgeMask[HalfEdgeMask["ALL_MASK"] = 4294967295] = "ALL_MASK";
303260
- // informal convention on preassigned mask bit numbers:
303261
- // byte0 (EXTERIOR, BOUNDARY_EDGE, PRIMARY_EDGE) -- edge properties
303262
- // byte1 (VISITED, VISIT_A, WORK_MASK0, WORK_MASK1) -- temp masks for algorithms.
303263
- // byte2 (TRIANGULATED_FACE, NULL_FACE) -- face properties.
303264
303597
  })(HalfEdgeMask || (HalfEdgeMask = {}));
303265
303598
  /**
303266
303599
  * A HalfEdge is "one side of an edge" in a structure of faces, edges and vertices. From a node there are
@@ -303456,6 +303789,37 @@ class HalfEdge {
303456
303789
  }
303457
303790
  return newA;
303458
303791
  }
303792
+ /**
303793
+ * Reverse of [[splitEdge]]: remove the vertex at `doomed` and merge its two incident edges.
303794
+ * @param doomed one of two nodes added by [[splitEdge]]. These nodes should form a vertex loop of two nodes.
303795
+ * On successful return this node and its mate are isolated.
303796
+ * @param checkParallel whether to check that the doomed edge and the preceding edge in its face loop are parallel.
303797
+ * When passing `true` the assumption is that edge geometry is linear. If nonlinear edge geometry is attached, the
303798
+ * caller should a) verify that the geometry on either side of the doomed vertex can be merged, and if so, they
303799
+ * should b) call this method passing `false`, and c) adjust the geometry of the returned edge and its edge mate
303800
+ * as appropriate.
303801
+ * @returns the former (surviving) face predecessor of `doomed`, or undefined if the edge can't be healed.
303802
+ */
303803
+ static healEdge(doomed, checkParallel = true) {
303804
+ if (doomed.isIsolatedEdge)
303805
+ return undefined;
303806
+ const doomed1 = doomed.vertexSuccessor;
303807
+ if (doomed1.vertexSuccessor !== doomed)
303808
+ return undefined; // v-loop not a 2-cycle
303809
+ if (checkParallel && !doomed.vectorToFaceSuccessor().isParallelTo(doomed.facePredecessor.vectorToFaceSuccessor(), false, true))
303810
+ return undefined; // removing this vertex does not leave a straight edge behind
303811
+ const fPred = doomed.facePredecessor;
303812
+ const fSucc = doomed.faceSuccessor;
303813
+ const fPred1 = doomed1.facePredecessor;
303814
+ const fSucc1 = doomed1.faceSuccessor;
303815
+ this.setFaceLinks(fPred, fSucc);
303816
+ this.setFaceLinks(fPred1, fSucc1);
303817
+ this.setEdgeMates(fPred, fPred1);
303818
+ this.setFaceLinks(doomed, doomed1);
303819
+ this.setFaceLinks(doomed1, doomed);
303820
+ this.setEdgeMates(doomed, doomed1);
303821
+ return fPred;
303822
+ }
303459
303823
  /**
303460
303824
  * Create a new sliver face "inside" an existing edge.
303461
303825
  * * This creates two nodes that are each face predecessor and successor to the other.
@@ -303483,14 +303847,14 @@ class HalfEdge {
303483
303847
  newB.copyDataFrom(baseB, true, true, false, false);
303484
303848
  return newA;
303485
303849
  }
303486
- /** Edge property masks. */
303850
+ /** Masks copied when an edge is split. */
303487
303851
  static _edgePropertyMasks = [
303488
- HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.NULL_FACE,
303852
+ HalfEdgeMask.EXTERIOR, HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.BRIDGE_EDGE, HalfEdgeMask.REGULARIZED_EDGE, HalfEdgeMask.NULL_FACE
303489
303853
  ];
303490
303854
  /**
303491
303855
  * Copy "edge based" content of `fromNode` to `toNode`:
303492
303856
  * * edgeTag
303493
- * * masks EXTERIOR, BOUNDARY_EDGE, NULL_FACE, PRIMARY_EDGE
303857
+ * * edge masks
303494
303858
  */
303495
303859
  static transferEdgeProperties(fromNode, toNode) {
303496
303860
  toNode.edgeTag = fromNode.edgeTag;
@@ -303663,7 +304027,7 @@ class HalfEdge {
303663
304027
  /**
303664
304028
  * Returns the number of nodes that match (or do not match) the given mask value around this face loop.
303665
304029
  * @param mask the mask to check.
303666
- * @param value true for mask match and false for mask not match.
304030
+ * @param value true for mask match and false for mask not match. Default is `true`.
303667
304031
  */
303668
304032
  countMaskAroundFace(mask, value = true) {
303669
304033
  let count = 0;
@@ -303710,16 +304074,17 @@ class HalfEdge {
303710
304074
  }
303711
304075
  /**
303712
304076
  * Returns the first node that matches (or does not match) the given mask value around this vertex loop, starting
303713
- * with the instance node and proceeding via vertex successors.
304077
+ * with the instance node and proceeding via `vertexSuccessor`.
303714
304078
  * @param mask the mask to check.
303715
- * @param value true for mask match and false for mask not match.
304079
+ * @param value true for mask match and false for mask not match. Default is `true`.
304080
+ * @param reverse if true, search in reverse order via `vertexPredecessor`. Default is `false`.
303716
304081
  */
303717
- findMaskAroundVertex(mask, value = true) {
304082
+ findMaskAroundVertex(mask, value = true, reverse = false) {
303718
304083
  let node = this;
303719
304084
  do {
303720
304085
  if (node.isMaskSet(mask) === value)
303721
304086
  return node;
303722
- node = node.vertexSuccessor;
304087
+ node = reverse ? node.vertexPredecessor : node.vertexSuccessor;
303723
304088
  } while (node !== this);
303724
304089
  return undefined;
303725
304090
  }
@@ -303727,7 +304092,7 @@ class HalfEdge {
303727
304092
  * Returns the first node that matches (or does not match) the given mask value around this face loop, starting
303728
304093
  * with the instance node and proceeding via face successors.
303729
304094
  * @param mask the mask to check.
303730
- * @param value true for mask match and false for mask not match.
304095
+ * @param value true for mask match and false for mask not match. Default is `true`.
303731
304096
  */
303732
304097
  findMaskAroundFace(mask, value = true) {
303733
304098
  let node = this;
@@ -303839,6 +304204,10 @@ class HalfEdge {
303839
304204
  predA._faceSuccessor = nodeB;
303840
304205
  }
303841
304206
  }
304207
+ /** Return whether the edge is dangling at its base. */
304208
+ get isDangling() {
304209
+ return this.edgeMate.faceSuccessor === this;
304210
+ }
303842
304211
  /**
303843
304212
  * Pinch this half edge out of its base vertex loop.
303844
304213
  * @return the surviving HalfEdge in the vertex loop or `undefined` if the instance HalfEdge is already dangling.
@@ -303908,17 +304277,17 @@ class HalfEdge {
303908
304277
  }
303909
304278
  /** Return Vector2d from `this` to face successor (with only xy coordinates). */
303910
304279
  vectorToFaceSuccessorXY(result) {
303911
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create(this.faceSuccessor.x - this.x, this.faceSuccessor.y - this.y, result);
304280
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create(this.faceSuccessor.x - this.x, this.faceSuccessor.y - this.y, result);
303912
304281
  }
303913
304282
  /** Return Vector3d from `this` to face successor. */
303914
304283
  vectorToFaceSuccessor(result) {
303915
304284
  const other = this.faceSuccessor;
303916
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
304285
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
303917
304286
  }
303918
304287
  /** Return Vector3d from `this` to face successor. */
303919
304288
  vectorToFacePredecessor(result) {
303920
304289
  const other = this.facePredecessor;
303921
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
304290
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
303922
304291
  }
303923
304292
  /**
303924
304293
  * Test if `spaceNode` is in the sector of `sectorNode`.
@@ -303969,15 +304338,15 @@ class HalfEdge {
303969
304338
  }
303970
304339
  /** Returns 2D cross product of vectors from `base` to `targetA` and from `base` to `targetB`. */
303971
304340
  static crossProductXYToTargets(base, targetA, targetB) {
303972
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.crossProductXYXY(targetA.x - base.x, targetA.y - base.y, targetB.x - base.x, targetB.y - base.y);
304341
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.crossProductXYXY(targetA.x - base.x, targetA.y - base.y, targetB.x - base.x, targetB.y - base.y);
303973
304342
  }
303974
304343
  /** Returns 2D dot product of vectors from `baseA` to `targetA` and from `baseB` to `targetB`. */
303975
304344
  static dotProductNodeToNodeVectorsXY(baseA, targetA, baseB, targetB) {
303976
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.dotProductXYXY(targetA.x - baseA.x, targetA.y - baseA.y, targetB.x - baseB.x, targetB.y - baseB.y);
304345
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(targetA.x - baseA.x, targetA.y - baseA.y, targetB.x - baseB.x, targetB.y - baseB.y);
303977
304346
  }
303978
304347
  /** Return 2D cross product of vectors from `nodeA` to `nodeB` and from `nodeB` to `nodeC`. */
303979
304348
  static crossProductXYAlongChain(nodeA, nodeB, nodeC) {
303980
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.crossProductXYXY(nodeB.x - nodeA.x, nodeB.y - nodeA.y, nodeC.x - nodeB.x, nodeC.y - nodeB.y);
304349
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.crossProductXYXY(nodeB.x - nodeA.x, nodeB.y - nodeA.y, nodeC.x - nodeB.x, nodeC.y - nodeB.y);
303981
304350
  }
303982
304351
  /**
303983
304352
  * Compute whether the sector defined by the chain of nodes is convex.
@@ -304014,7 +304383,7 @@ class HalfEdge {
304014
304383
  */
304015
304384
  isSectorConvex(signedAreaTol) {
304016
304385
  if (signedAreaTol === undefined)
304017
- signedAreaTol = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistanceSquared * this.signedFaceArea();
304386
+ signedAreaTol = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistanceSquared * this.signedFaceArea();
304018
304387
  return HalfEdge.isSectorConvex(this.facePredecessor, this, this.faceSuccessor, signedAreaTol);
304019
304388
  }
304020
304389
  /**
@@ -304026,7 +304395,7 @@ class HalfEdge {
304026
304395
  * `Geometry.smallMetricDistanceSquared`. Pass 0 to skip toleranced computation.
304027
304396
  * @returns true iff this face is convex.
304028
304397
  */
304029
- isFaceConvex(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistanceSquared) {
304398
+ isFaceConvex(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistanceSquared) {
304030
304399
  let node = this;
304031
304400
  const signedAreaTol = tolerance > 0.0 ? tolerance * node.signedFaceArea() : 0.0;
304032
304401
  do {
@@ -304042,7 +304411,10 @@ class HalfEdge {
304042
304411
  this.yankFromVertexLoop();
304043
304412
  mate.yankFromVertexLoop();
304044
304413
  }
304045
- /** Specify whether this edge is isolated from the rest of the graph. */
304414
+ /**
304415
+ * Specify whether this edge is isolated from the rest of the graph.
304416
+ * * Both edge mates of an isolated edge return true for [[isDangling]].
304417
+ */
304046
304418
  get isIsolatedEdge() {
304047
304419
  return this === this.vertexSuccessor && this.edgeMate === this.edgeMate.vertexSuccessor;
304048
304420
  }
@@ -304072,7 +304444,7 @@ class HalfEdge {
304072
304444
  static sectorSweepRadiansXYZ(node, normal) {
304073
304445
  const suc = node.faceSuccessor;
304074
304446
  const pred = node.facePredecessor;
304075
- return _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.orientedRadiansBetweenVectorsXYZ(suc.x - node.x, suc.y - node.y, suc.z - node.z, pred.x - node.x, pred.y - node.y, pred.z - node.z, normal.x, normal.y, normal.z, true);
304447
+ return _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_4__.Angle.orientedRadiansBetweenVectorsXYZ(suc.x - node.x, suc.y - node.y, suc.z - node.z, pred.x - node.x, pred.y - node.y, pred.z - node.z, normal.x, normal.y, normal.z, true);
304076
304448
  }
304077
304449
  /** Returns true if the face has positive area in xy parts. */
304078
304450
  static testFacePositiveAreaXY(node) {
@@ -304084,11 +304456,76 @@ class HalfEdge {
304084
304456
  }
304085
304457
  /** Return distance between xy coordinates of `this` and `other` node. */
304086
304458
  distanceXY(other) {
304087
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.distanceXYXY(this.x, this.y, other.x, other.y);
304459
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.distanceXYXY(this.x, this.y, other.x, other.y);
304088
304460
  }
304089
304461
  /** Return distance between xyz coordinates of `this` and `other` node. */
304090
304462
  distanceXYZ(other) {
304091
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.distanceXYZXYZ(this.x, this.y, this.z, other.x, other.y, other.z);
304463
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.distanceXYZXYZ(this.x, this.y, this.z, other.x, other.y, other.z);
304464
+ }
304465
+ /**
304466
+ * Search around the instance's face loop for nodes with the specified mask value.
304467
+ * * Returned nodes satisfy `node.isMaskSet(mask) === value`.
304468
+ * @param mask target mask.
304469
+ * @param value target boolean value for mask on half edges (default `true`).
304470
+ * @param result optional array to be cleared, populated with masked nodes, and returned.
304471
+ * @return array of masked half edges
304472
+ */
304473
+ collectMaskedEdgesAroundFace(mask, value = true, result) {
304474
+ if (result === undefined)
304475
+ result = [];
304476
+ else
304477
+ result.length = 0;
304478
+ let node = this;
304479
+ do {
304480
+ if (node.isMaskSet(mask) === value)
304481
+ result.push(node);
304482
+ node = node.faceSuccessor;
304483
+ } while (node !== this);
304484
+ return result;
304485
+ }
304486
+ /**
304487
+ * Announce edges in the face loop, starting with the instance and proceeding in a `faceSuccessor` traversal.
304488
+ * @param announceEdge function to call at each edge
304489
+ */
304490
+ announceEdgesInFace(announceEdge) {
304491
+ let node = this;
304492
+ do {
304493
+ announceEdge(node);
304494
+ node = node.faceSuccessor;
304495
+ } while (node !== this);
304496
+ }
304497
+ /**
304498
+ * Announce edges in the super face loop, starting with the instance.
304499
+ * * A super face admits a `faceSuccessor` traversal, where the next edge at the far vertex is the first one lacking `skipMask` in a `vertexPredecessor` traversal.
304500
+ * @param skipMask mask on edges to skip.
304501
+ * @param announceEdge function to call at each edge that is not skipped.
304502
+ * @param announceSkipped optional function to call at each edge that is skipped.
304503
+ * @return whether a super face was found. Specifically, if a vertex loop has all edges with `skipMask` set, the return value is `false`.
304504
+ */
304505
+ announceEdgesInSuperFace(skipMask, announceEdge, announceSkipped) {
304506
+ const maxIter = 1000; // safeguard against infinite loops
304507
+ let iter = 0;
304508
+ const findNextNodeAroundVertex = (he) => {
304509
+ let vNode = he;
304510
+ do {
304511
+ if (!vNode.isMaskSet(skipMask))
304512
+ return vNode;
304513
+ announceSkipped?.(vNode);
304514
+ vNode = vNode.vertexPredecessor;
304515
+ } while (vNode !== he);
304516
+ return undefined;
304517
+ };
304518
+ const firstNode = findNextNodeAroundVertex(this);
304519
+ if (!firstNode)
304520
+ return false;
304521
+ let node = firstNode;
304522
+ do {
304523
+ announceEdge(node);
304524
+ node = findNextNodeAroundVertex(node.faceSuccessor);
304525
+ if (!node)
304526
+ return false;
304527
+ } while (node !== firstNode && iter++ < maxIter);
304528
+ return iter < maxIter;
304092
304529
  }
304093
304530
  /**
304094
304531
  * Evaluate `f(node)` at each node around `this` node's face loop. Collect the function values.
@@ -304229,7 +304666,7 @@ class HalfEdge {
304229
304666
  */
304230
304667
  fractionToPoint2d(fraction, result) {
304231
304668
  const suc = this.faceSuccessor;
304232
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Point2d.create(this.x + (suc.x - this.x) * fraction, this.y + (suc.y - this.y) * fraction, result);
304669
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(this.x + (suc.x - this.x) * fraction, this.y + (suc.y - this.y) * fraction, result);
304233
304670
  }
304234
304671
  /**
304235
304672
  * Interpolate xyz coordinates between `this` node and its face successor.
@@ -304238,7 +304675,7 @@ class HalfEdge {
304238
304675
  */
304239
304676
  fractionToPoint3d(fraction, result) {
304240
304677
  const suc = this.faceSuccessor;
304241
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(this.x + (suc.x - this.x) * fraction, this.y + (suc.y - this.y) * fraction, this.z + (suc.z - this.z) * fraction, result);
304678
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Point3d.create(this.x + (suc.x - this.x) * fraction, this.y + (suc.y - this.y) * fraction, this.z + (suc.z - this.z) * fraction, result);
304242
304679
  }
304243
304680
  /**
304244
304681
  * Interpolate xy coordinates at `fractionAlong` between this node and its face successor. Then shift perpendicular
@@ -304251,25 +304688,25 @@ class HalfEdge {
304251
304688
  const suc = this.faceSuccessor;
304252
304689
  const dx = suc.x - this.x;
304253
304690
  const dy = suc.y - this.y;
304254
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Point2d.create(this.x + dx * fractionAlong - dy * fractionPerpendicular, this.y + dy * fractionAlong + dx * fractionPerpendicular, result);
304691
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(this.x + dx * fractionAlong - dy * fractionPerpendicular, this.y + dy * fractionAlong + dx * fractionPerpendicular, result);
304255
304692
  }
304256
304693
  /** Return the 3d coordinates at this half edge. */
304257
304694
  getPoint3d(result) {
304258
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(this.x, this.y, this.z, result);
304695
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Point3d.create(this.x, this.y, this.z, result);
304259
304696
  }
304260
304697
  /** Return the 2d coordinates at this half edge. */
304261
304698
  getPoint2d(result) {
304262
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Point2d.create(this.x, this.y, result);
304699
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(this.x, this.y, result);
304263
304700
  }
304264
304701
  /** Return a 3d vector from start to end of this half edge. */
304265
304702
  getVector3dAlongEdge(result) {
304266
304703
  const suc = this.faceSuccessor;
304267
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(suc.x - this.x, suc.y - this.y, suc.z - this.z, result);
304704
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(suc.x - this.x, suc.y - this.y, suc.z - this.z, result);
304268
304705
  }
304269
304706
  /** Return a 2d vector from start to end of this half edge. */
304270
304707
  getVector2dAlongEdge(result) {
304271
304708
  const suc = this.faceSuccessor;
304272
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create(suc.x - this.x, suc.y - this.y, result);
304709
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create(suc.x - this.x, suc.y - this.y, result);
304273
304710
  }
304274
304711
  /**
304275
304712
  * Return the interpolated x coordinate between `this` node and its face successor.
@@ -304307,12 +304744,12 @@ class HalfEdge {
304307
304744
  const nodeA1 = nodeA0.faceSuccessor;
304308
304745
  const nodeB1 = nodeB0.faceSuccessor;
304309
304746
  if (!result)
304310
- result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create();
304747
+ result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create();
304311
304748
  // To find the fraction of intersection (ta,tb), you need to solve these 2 equations:
304312
304749
  // (nodeA1.x - nodeA0.x)ta + (nodeB0.x - nodeB1.x)tb = nodeB0.x - nodeA0.x
304313
304750
  // (nodeA1.y - nodeA0.y)ta + (nodeB0.y - nodeB1.y)tb = nodeB0.y - nodeA0.y
304314
304751
  // Proof can be found at geometry/internaldocs/Graph.md
304315
- if (_numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_4__.SmallSystem.linearSystem2d(nodeA1.x - nodeA0.x, nodeB0.x - nodeB1.x, nodeA1.y - nodeA0.y, nodeB0.y - nodeB1.y, nodeB0.x - nodeA0.x, nodeB0.y - nodeA0.y, result))
304752
+ if (_numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_5__.SmallSystem.linearSystem2d(nodeA1.x - nodeA0.x, nodeB0.x - nodeB1.x, nodeA1.y - nodeA0.y, nodeB0.y - nodeB1.y, nodeB0.x - nodeA0.x, nodeB0.y - nodeA0.y, result))
304316
304753
  return result;
304317
304754
  return undefined;
304318
304755
  }
@@ -304326,13 +304763,13 @@ class HalfEdge {
304326
304763
  static horizontalScanFraction(node0, y) {
304327
304764
  const node1 = node0.faceSuccessor;
304328
304765
  const dy = node1.y - node0.y;
304329
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(y, node1.y))
304766
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node1.y))
304330
304767
  return node0;
304331
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(dy, 0.0))
304768
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(dy, 0.0))
304332
304769
  return undefined;
304333
304770
  // parametric equation of line is (1-t)y0 + ty1 which is equal to y at the intersection so
304334
304771
  // (1-t)y0 + ty1 = y or t = (y-y0)/(y1-y0)
304335
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.conditionalDivideFraction(y - node0.y, dy);
304772
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.conditionalDivideFraction(y - node0.y, dy);
304336
304773
  }
304337
304774
  /**
304338
304775
  * Compute fractional position (inside 0..1) of the intersection of a horizontal line with an edge.
@@ -304344,11 +304781,11 @@ class HalfEdge {
304344
304781
  static horizontalScanFraction01(node0, y) {
304345
304782
  const node1 = node0.faceSuccessor;
304346
304783
  const dy = node1.y - node0.y;
304347
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(y, node1.y))
304784
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node1.y))
304348
304785
  return undefined;
304349
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(dy, 0.0))
304786
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(dy, 0.0))
304350
304787
  return undefined;
304351
- const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.conditionalDivideFraction(y - node0.y, dy);
304788
+ const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.conditionalDivideFraction(y - node0.y, dy);
304352
304789
  if (fraction !== undefined && fraction >= 0.0 && fraction <= 1.0)
304353
304790
  return fraction;
304354
304791
  return undefined;
@@ -304367,16 +304804,37 @@ class HalfEdge {
304367
304804
  this.y = source.y;
304368
304805
  this.z = source.z;
304369
304806
  }
304370
- if (copyVertexData) {
304807
+ if (copyVertexData)
304371
304808
  this.i = source.i;
304372
- }
304373
- if (copyEdgeData) {
304809
+ if (copyEdgeData)
304374
304810
  HalfEdge.transferEdgeProperties(source, this);
304375
- this.edgeTag = source.edgeTag;
304376
- }
304377
- if (copyFaceData) {
304811
+ if (copyFaceData)
304378
304812
  this.faceTag = source.faceTag;
304813
+ }
304814
+ /**
304815
+ * Is the instance's face loop a split-washer type face?
304816
+ * * A split-washer face contains at least one bridge edge.
304817
+ * * A bridge edge and its edge mate have the same `bridgeMask` and live in the same face loop.
304818
+ * * By connecting hole/outer loops with bridge edges, a split-washer face can represent a parity region.
304819
+ * @param bridgeMask mask preset on bridge edges (default is [[HalfEdgeMask.BRIDGE_EDGE]]).
304820
+ */
304821
+ isSplitWasherFace(bridgeMask = HalfEdgeMask.BRIDGE_EDGE) {
304822
+ if (!this.countMaskAroundFace(HalfEdgeMask.BRIDGE_EDGE))
304823
+ return false;
304824
+ const bridges = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.OrderedSet((a, b) => a.id - b.id);
304825
+ let node = this;
304826
+ do {
304827
+ if (node.isMaskSet(bridgeMask))
304828
+ bridges.add(node);
304829
+ node = node.faceSuccessor;
304830
+ } while (node !== this);
304831
+ if (bridges.size === 0)
304832
+ return false;
304833
+ for (const bridge of bridges) {
304834
+ if (!bridges.has(bridge.edgeMate) || !bridge.edgeMate.isMaskSet(bridgeMask))
304835
+ return false;
304379
304836
  }
304837
+ return true;
304380
304838
  }
304381
304839
  }
304382
304840
  /**
@@ -304392,11 +304850,11 @@ class HalfEdgeGraph {
304392
304850
  _numNodesCreated = 0;
304393
304851
  constructor() {
304394
304852
  this.allHalfEdges = [];
304395
- this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_5__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
304853
+ this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_6__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
304396
304854
  }
304397
304855
  /**
304398
304856
  * Ask for a mask (from the graph's free pool) for caller's use.
304399
- * * Optionally clear the mask throughout the graph.
304857
+ * @param clearInAllHalfEdges optionally clear the mask throughout the graph (default `true`).
304400
304858
  */
304401
304859
  grabMask(clearInAllHalfEdges = true) {
304402
304860
  const mask = this._maskManager.grabMask();
@@ -304562,7 +305020,7 @@ class HalfEdgeGraph {
304562
305020
  const segments = [];
304563
305021
  for (const node of this.allHalfEdges) {
304564
305022
  if (node.id < node.edgeMate.id)
304565
- segments.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__.LineSegment3d.create(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(node.x, node.y), _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(node.faceSuccessor.x, node.faceSuccessor.y)));
305023
+ segments.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_7__.LineSegment3d.create(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Point3d.create(node.x, node.y), _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Point3d.create(node.faceSuccessor.x, node.faceSuccessor.y)));
304566
305024
  }
304567
305025
  return segments;
304568
305026
  }
@@ -305050,8 +305508,8 @@ class HalfEdgeGraphSearch {
305050
305508
  * pattern starting at the seed face, with each successive concentric ring of faces at constant topological
305051
305509
  * distance from the seed face receiving the opposite parity state of the previous ring.
305052
305510
  * @param parityMask (optional) mask to apply to the first face and faces that share the same parity as the
305053
- * first face, as determined by the parity rule. If this is `NULL_MASK`, there is no record of parity. If
305054
- * (non-null) parity mask is given, on return it is entirely set or entirely clear around each face.
305511
+ * first face, as determined by the parity rule. If this is `NULL_MASK` (default), there is no record of parity.
305512
+ * If (non-null) parity mask is given, on return it is entirely set or entirely clear around each face.
305055
305513
  * @returns the components of the graph, each component represented by an array of nodes, one node per face
305056
305514
  * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.
305057
305515
  */
@@ -307809,8 +308267,9 @@ class RegularizationContext {
307809
308267
  if (nodeA1 !== undefined && nodeB1 !== undefined) {
307810
308268
  _Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(nodeA1, nodeC);
307811
308269
  _Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(nodeB1, nodeC.edgeMate);
308270
+ nodeC.setMaskAroundEdge(_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.REGULARIZED_EDGE);
307812
308271
  if (RegularizationContext.announceEdge)
307813
- RegularizationContext.announceEdge(this.graph, nodeA, nodeB, direction);
308272
+ RegularizationContext.announceEdge(this.graph, nodeC, nodeC.edgeMate, direction);
307814
308273
  return nodeC;
307815
308274
  }
307816
308275
  return undefined;
@@ -331259,7 +331718,7 @@ class TestContext {
331259
331718
  this.initializeRpcInterfaces({ title: this.settings.Backend.name, version: this.settings.Backend.version });
331260
331719
  const iModelClient = new imodels_client_management_1.IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } });
331261
331720
  await core_frontend_1.NoRenderApp.startup({
331262
- applicationVersion: "5.1.0-dev.51",
331721
+ applicationVersion: "5.1.0-dev.53",
331263
331722
  applicationId: this.settings.gprid,
331264
331723
  authorizationClient: new frontend_1.TestFrontendAuthorizationClient(this.serviceAuthToken),
331265
331724
  hubAccess: new imodels_access_frontend_1.FrontendIModelsAccess(iModelClient),
@@ -356346,7 +356805,7 @@ var loadLanguages = instance.loadLanguages;
356346
356805
  /***/ ((module) => {
356347
356806
 
356348
356807
  "use strict";
356349
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.1.0-dev.51","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","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","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","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","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":{"@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/eslint-plugin":"5.0.0-dev.1","@types/chai-as-promised":"^7","@types/sinon":"^17.0.2","@vitest/browser":"^3.0.6","@vitest/coverage-v8":"^3.0.6","cpx2":"^8.0.0","eslint":"^9.13.0","glob":"^10.3.12","playwright":"~1.47.1","rimraf":"^6.0.1","sinon":"^17.0.2","source-map-loader":"^5.0.0","typescript":"~5.6.2","typemoq":"^2.1.0","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/cloud-agnostic-core":"^2.2.4","@itwin/object-storage-core":"^2.3.0","@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
356808
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.1.0-dev.53","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","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","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","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","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":{"@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/eslint-plugin":"5.0.0-dev.1","@types/chai-as-promised":"^7","@types/sinon":"^17.0.2","@vitest/browser":"^3.0.6","@vitest/coverage-v8":"^3.0.6","cpx2":"^8.0.0","eslint":"^9.13.0","glob":"^10.3.12","playwright":"~1.47.1","rimraf":"^6.0.1","sinon":"^17.0.2","source-map-loader":"^5.0.0","typescript":"~5.6.2","typemoq":"^2.1.0","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/cloud-agnostic-core":"^2.2.4","@itwin/object-storage-core":"^2.3.0","@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
356350
356809
 
356351
356810
  /***/ }),
356352
356811
 
@@ -357429,62 +357888,6 @@ describe("DevTools", () => {
357429
357888
 
357430
357889
  })();
357431
357890
 
357432
- // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
357433
- (() => {
357434
- "use strict";
357435
- var exports = {};
357436
- /*!****************************************!*\
357437
- !*** ./lib/frontend/CodeSpecs.test.js ***!
357438
- \****************************************/
357439
-
357440
- /*---------------------------------------------------------------------------------------------
357441
- * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
357442
- * See LICENSE.md in the project root for license terms and full copyright notice.
357443
- *--------------------------------------------------------------------------------------------*/
357444
- Object.defineProperty(exports, "__esModule", ({ value: true }));
357445
- const chai = __webpack_require__(/*! chai */ "../../common/temp/node_modules/.pnpm/chai@4.3.10/node_modules/chai/index.js");
357446
- const core_common_1 = __webpack_require__(/*! @itwin/core-common */ "../../core/common/lib/esm/core-common.js");
357447
- const TestContext_1 = __webpack_require__(/*! ./setup/TestContext */ "./lib/frontend/setup/TestContext.js");
357448
- const expect = chai.expect;
357449
- describe("Get Code Specs", () => {
357450
- let testContext;
357451
- before(async function () {
357452
- testContext = await TestContext_1.TestContext.instance();
357453
- if (!testContext.settings.runiModelReadRpcTests)
357454
- this.skip();
357455
- });
357456
- const existing = {
357457
- name: core_common_1.BisCodeSpec.subject,
357458
- id: "0x1f",
357459
- };
357460
- /** verify that given codespec has expected properties */
357461
- function verifyCodeSpec(codeSpec, requestedIModel, requestedName, requestedId) {
357462
- expect(codeSpec).to.exist;
357463
- expect(codeSpec.id).to.exist;
357464
- expect(codeSpec.id).to.equal(requestedId);
357465
- expect(codeSpec.name).to.exist;
357466
- expect(codeSpec.name).to.equal(requestedName);
357467
- expect(codeSpec.iModel).to.exist;
357468
- expect(codeSpec.iModel.name).to.equal(requestedIModel.name);
357469
- }
357470
- it("should return code spec by name", async () => {
357471
- const iModel = await testContext.iModelWithChangesets.getConnection();
357472
- const codeSpecName = existing.name;
357473
- const codeSpecId = existing.id;
357474
- const codeSpec = await iModel.codeSpecs.getByName(codeSpecName);
357475
- verifyCodeSpec(codeSpec, iModel, codeSpecName, codeSpecId);
357476
- });
357477
- it("should return code spec by id", async () => {
357478
- const iModel = await testContext.iModelWithChangesets.getConnection();
357479
- const codeSpecName = existing.name;
357480
- const codeSpecId = existing.id;
357481
- const codeSpec = await iModel.codeSpecs.getById(codeSpecId);
357482
- verifyCodeSpec(codeSpec, iModel, codeSpecName, codeSpecId);
357483
- });
357484
- });
357485
-
357486
- })();
357487
-
357488
357891
  // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
357489
357892
  (() => {
357490
357893
  "use strict";