@itwin/rpcinterface-full-stack-tests 5.1.0-dev.52 → 5.1.0-dev.54

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");
@@ -101774,7 +101780,15 @@ class ECSchemaRpcLocater {
101774
101780
  * @param matchType The match type to use when locating the schema
101775
101781
  */
101776
101782
  async getSchemaInfo(schemaKey, matchType, context) {
101777
- const schemaJson = await _ECSchemaRpcInterface__WEBPACK_IMPORTED_MODULE_1__.ECSchemaRpcInterface.getClient().getSchemaJSON(this.token, schemaKey.name);
101783
+ let schemaJson;
101784
+ try {
101785
+ schemaJson = await _ECSchemaRpcInterface__WEBPACK_IMPORTED_MODULE_1__.ECSchemaRpcInterface.getClient().getSchemaJSON(this.token, schemaKey.name);
101786
+ }
101787
+ catch (e) {
101788
+ if (e.message && e.message === "schema not found")
101789
+ return undefined;
101790
+ throw (e);
101791
+ }
101778
101792
  const schemaInfo = await _itwin_ecschema_metadata__WEBPACK_IMPORTED_MODULE_0__.Schema.startLoadingFromJson(schemaJson, context || new _itwin_ecschema_metadata__WEBPACK_IMPORTED_MODULE_0__.SchemaContext());
101779
101793
  if (schemaInfo !== undefined && schemaInfo.schemaKey.matches(schemaKey, matchType)) {
101780
101794
  return schemaInfo;
@@ -114814,20 +114828,52 @@ class SnapshotConnection extends IModelConnection {
114814
114828
  /** The collection of [[CodeSpec]] entities for an [[IModelConnection]]. */
114815
114829
  class CodeSpecs {
114816
114830
  _iModel;
114817
- _loaded;
114818
114831
  /** @internal */
114819
114832
  constructor(_iModel) {
114820
114833
  this._iModel = _iModel;
114821
114834
  }
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));
114835
+ _isCodeSpecProperties(x) {
114836
+ if (!x || !x.scopeSpec || !Object.values(_itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.CodeScopeSpec.Type).includes(x.scopeSpec.type))
114837
+ return false;
114838
+ if (typeof x.scopeSpec.fGuidRequired !== "boolean" && typeof x.scopeSpec.fGuidRequired !== "undefined")
114839
+ return false;
114840
+ if (typeof x.scopeSpec.relationship !== "string" && typeof x.scopeSpec.relationship !== "undefined")
114841
+ return false;
114842
+ if (typeof x.spec?.isManagedWithDgnDb !== "boolean" && typeof x.spec?.isManagedWithDgnDb !== "undefined")
114843
+ return false;
114844
+ if (typeof x.version !== "string" && typeof x.version !== "undefined")
114845
+ return false;
114846
+ return true;
114847
+ }
114848
+ async _loadCodeSpec(identifier) {
114849
+ const isNameDefined = identifier.name !== undefined;
114850
+ const query = `
114851
+ SELECT ECInstanceId AS Id, Name, JsonProperties
114852
+ FROM BisCore.CodeSpec
114853
+ WHERE ${isNameDefined ? `Name=:name` : `Id=:id`}`;
114854
+ const params = new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.QueryBinder();
114855
+ if (isNameDefined) {
114856
+ params.bindString("name", identifier.name);
114857
+ }
114858
+ else {
114859
+ params.bindId("id", identifier.id);
114830
114860
  }
114861
+ const queryReader = this._iModel.createQueryReader(query, params, {
114862
+ rowFormat: _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.QueryRowFormat.UseECSqlPropertyNames,
114863
+ });
114864
+ const queryResult = await queryReader.next();
114865
+ if (queryResult.done)
114866
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
114867
+ const codeSpecResult = queryResult.value;
114868
+ if (typeof codeSpecResult.Id !== "string" ||
114869
+ typeof codeSpecResult.Name !== "string" ||
114870
+ typeof codeSpecResult.JsonProperties !== "string")
114871
+ throw new Error("Invalid CodeSpec was returned");
114872
+ const jsonProperties = JSON.parse(codeSpecResult.JsonProperties);
114873
+ if (!this._isCodeSpecProperties(jsonProperties))
114874
+ throw new Error("Invalid CodeSpecProperties returned in the CodeSpec");
114875
+ 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);
114876
+ return codeSpec;
114831
114877
  }
114832
114878
  /** Look up a CodeSpec by Id.
114833
114879
  * @param codeSpecId The Id of the CodeSpec to load
@@ -114835,13 +114881,11 @@ class SnapshotConnection extends IModelConnection {
114835
114881
  * @throws [[IModelError]] if the Id is invalid or if no CodeSpec with that Id could be found.
114836
114882
  */
114837
114883
  async getById(codeSpecId) {
114884
+ if (codeSpecId === "")
114885
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
114838
114886
  if (!_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Id64.isValid(codeSpecId))
114839
114887
  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;
114888
+ return this._loadCodeSpec({ id: codeSpecId });
114845
114889
  }
114846
114890
  /** Look up a CodeSpec by name.
114847
114891
  * @param name The name of the CodeSpec to load
@@ -114849,11 +114893,9 @@ class SnapshotConnection extends IModelConnection {
114849
114893
  * @throws [[IModelError]] if no CodeSpec with the specified name could be found.
114850
114894
  */
114851
114895
  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)
114896
+ if (name === "")
114855
114897
  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;
114898
+ return this._loadCodeSpec({ name });
114857
114899
  }
114858
114900
  }
114859
114901
  IModelConnection.CodeSpecs = CodeSpecs;
@@ -216017,7 +216059,6 @@ class BSplineSurface3d extends BSpline2dNd {
216017
216059
  getPointGridJSON() {
216018
216060
  const result = {
216019
216061
  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
216062
  weightStyle: WeightStyle.UnWeighted,
216022
216063
  numCartesianDimensions: 3,
216023
216064
  };
@@ -216430,7 +216471,6 @@ class BSplineSurface3dH extends BSpline2dNd {
216430
216471
  const result = {
216431
216472
  points: _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_7__.Point3dArray.unpackNumbersToNestedArraysIJK(this.coffs, 4, this.numPolesUV(0)),
216432
216473
  numCartesianDimensions: 3,
216433
- weighStyle: WeightStyle.WeightsAlreadyAppliedToCoordinates, // @deprecated in 4.x - will not be removed until after 2026-06-13. Use weightStyle instead.
216434
216474
  weightStyle: WeightStyle.WeightsAlreadyAppliedToCoordinates,
216435
216475
  };
216436
216476
  return result;
@@ -227444,6 +227484,17 @@ class CurveChain extends CurveCollection {
227444
227484
  else
227445
227485
  return undefined;
227446
227486
  }
227487
+ /**
227488
+ * Whether the chain start and end points are defined and within tolerance.
227489
+ * * Does not check for planarity or degeneracy.
227490
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
227491
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
227492
+ */
227493
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallMetricDistance, xyOnly = false) {
227494
+ const p0 = this.startPoint();
227495
+ const p1 = this.endPoint();
227496
+ return p0 !== undefined && p1 !== undefined && (xyOnly ? p0.isAlmostEqualXY(p1, tolerance) : p0.isAlmostEqual(p1, tolerance));
227497
+ }
227447
227498
  /**
227448
227499
  * Return the start point and derivative of the first child of the curve chain.
227449
227500
  * * For queries interior to the chain, use [[CurveChainWithDistanceIndex.fractionToPointAndDerivative]].
@@ -228174,11 +228225,12 @@ class CurveFactory {
228174
228225
  * * This only succeeds if the two arcs are part of identical complete arcs and end of `arcA` matches the beginning of `arcB`.
228175
228226
  * @param arcA first arc, modified in place.
228176
228227
  * @param arcB second arc, unmodified.
228177
- * @param allowReversed whether to consolidate even when second arc is reversed.
228228
+ * @param allowReversed whether to consolidate even when second arc is reversed (default is `false`).
228229
+ * @param tolerance optional coordinate tolerance for point equality (default is `Geometry.smallMetricDistance`).
228178
228230
  * @returns whether `arcA` was modified.
228179
228231
  */
228180
- static appendToArcInPlace(arcA, arcB, allowReverse = false) {
228181
- if (arcA.center.isAlmostEqual(arcB.center)) {
228232
+ static appendToArcInPlace(arcA, arcB, allowReverse = false, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
228233
+ if (arcA.center.isAlmostEqual(arcB.center, tolerance)) {
228182
228234
  const sweepSign = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.split3WaySign(arcA.sweep.sweepRadians * arcB.sweep.sweepRadians, -1, 0, 1);
228183
228235
  // evaluate derivatives wrt radians (not fraction!), but adjust direction for sweep signs
228184
228236
  const endA = arcA.angleToPointAndDerivative(arcA.sweep.fractionToAngle(1.0));
@@ -228187,14 +228239,14 @@ class CurveFactory {
228187
228239
  const startB = arcB.angleToPointAndDerivative(arcB.sweep.fractionToAngle(0.0));
228188
228240
  if (arcB.sweep.sweepRadians < 0)
228189
228241
  startB.direction.scaleInPlace(-1.0);
228190
- if (endA.isAlmostEqual(startB)) {
228242
+ if (endA.isAlmostEqual(startB, tolerance)) {
228191
228243
  arcA.sweep.setStartEndRadians(arcA.sweep.startRadians, arcA.sweep.startRadians + arcA.sweep.sweepRadians + sweepSign * arcB.sweep.sweepRadians);
228192
228244
  return true;
228193
228245
  }
228194
228246
  // Also ok if negated tangent
228195
228247
  if (allowReverse) {
228196
228248
  startB.direction.scaleInPlace(-1.0);
228197
- if (endA.isAlmostEqual(startB)) {
228249
+ if (endA.isAlmostEqual(startB, tolerance)) {
228198
228250
  arcA.sweep.setStartEndRadians(arcA.sweep.startRadians, arcA.sweep.startRadians + arcA.sweep.sweepRadians - sweepSign * arcB.sweep.sweepRadians);
228199
228251
  return true;
228200
228252
  }
@@ -228741,7 +228793,12 @@ class CurveLocationDetail {
228741
228793
  setIntervalRole(value) {
228742
228794
  this.intervalRole = value;
228743
228795
  }
228744
- /** Set the (optional) fraction1 and point1, using direct assignment (capture!) to point1. */
228796
+ /** Set the `fraction` and `point`, using direct assignment (capture!) to `point`. */
228797
+ captureFractionPoint(fraction, point) {
228798
+ this.fraction = fraction;
228799
+ this.point = point;
228800
+ }
228801
+ /** Set the (optional) `fraction1` and `point1`, using direct assignment (capture!) to `point1`. */
228745
228802
  captureFraction1Point1(fraction1, point1) {
228746
228803
  this.fraction1 = fraction1;
228747
228804
  this.point1 = point1;
@@ -229961,6 +230018,17 @@ class CurvePrimitive extends _GeometryQuery__WEBPACK_IMPORTED_MODULE_1__.Geometr
229961
230018
  endPoint(result) {
229962
230019
  return this.fractionToPoint(1.0, result);
229963
230020
  }
230021
+ /**
230022
+ * Whether the start and end points are defined and within tolerance.
230023
+ * * Does not check for planarity or degeneracy.
230024
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
230025
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
230026
+ */
230027
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance, xyOnly = false) {
230028
+ const p0 = this.startPoint();
230029
+ const p1 = this.endPoint();
230030
+ return p0 !== undefined && p1 !== undefined && (xyOnly ? p0.isAlmostEqualXY(p1, tolerance) : p0.isAlmostEqual(p1, tolerance));
230031
+ }
229964
230032
  /**
229965
230033
  * Attach StrokeCountMap structure to this primitive (and recursively to any children)
229966
230034
  * * Base class implementation (here) gets the simple count from computeStrokeCountForOptions and attaches it.
@@ -230448,6 +230516,10 @@ class LineSegment3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePr
230448
230516
  get point1Ref() {
230449
230517
  return this._point1;
230450
230518
  }
230519
+ /** Return a copy of the start and end points in an array. */
230520
+ get points() {
230521
+ return [this._point0.clone(), this._point1.clone()];
230522
+ }
230451
230523
  /** A LineSegment3d extends along its infinite line. */
230452
230524
  get isExtensibleFractionSpace() {
230453
230525
  return true;
@@ -232228,8 +232300,7 @@ class LineString3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePri
232228
232300
  this.addResolvedPoint(localA.index, localA.fraction, result._points);
232229
232301
  for (let index = index0; index <= index1; index++) {
232230
232302
  if (this._points.isIndexValid(index)) {
232231
- this._points.getPoint3dAtUncheckedPointIndex(index, LineString3d._workPointA);
232232
- result._points.push(LineString3d._workPointA);
232303
+ result._points.pushFromGrowableXYZArray(this._points, index);
232233
232304
  }
232234
232305
  }
232235
232306
  this.addResolvedPoint(localB.index, localB.fraction, result._points);
@@ -232241,9 +232312,22 @@ class LineString3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePri
232241
232312
  return _LineSegment3d__WEBPACK_IMPORTED_MODULE_15__.LineSegment3d.create(this._points.getPoint3dAtCheckedPointIndex(index), this._points.getPoint3dAtCheckedPointIndex(index + 1), result);
232242
232313
  return undefined;
232243
232314
  }
232315
+ /**
232316
+ * Whether the start and end points are defined and within tolerance.
232317
+ * * Does not check for planarity or degeneracy.
232318
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
232319
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
232320
+ */
232321
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance, xyOnly = false) {
232322
+ if (!this._points.length)
232323
+ return false;
232324
+ if (xyOnly)
232325
+ return this._points.almostEqualXYIndexIndex(0, this._points.length - 1, tolerance); // we know the indices are valid
232326
+ return this._points.almostEqualIndexIndex(0, this._points.length - 1, tolerance);
232327
+ }
232244
232328
  /** Returns true if first and last points are within metric tolerance. */
232245
232329
  get isPhysicallyClosed() {
232246
- return this._points.length > 0 && _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.isSmallMetricDistance(this._points.distanceIndexIndex(0, this._points.length - 1));
232330
+ return this.isPhysicallyClosedCurve();
232247
232331
  }
232248
232332
  /**
232249
232333
  * Evaluate strokes at fractions indicated in a StrokeCountMap.
@@ -233424,7 +233508,7 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
233424
233508
  const numOriginal = children.length;
233425
233509
  const points = [];
233426
233510
  let numAccept = 0;
233427
- // i0 <=i < i1 is a range of child indices.
233511
+ // i0 <= i < i1 is a range of child indices.
233428
233512
  // numAccept is the number of children accepted (contiguously at front of children)
233429
233513
  for (let i0 = 0; i0 < numOriginal;) {
233430
233514
  const basePrimitive = g.children[i0];
@@ -233482,7 +233566,7 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
233482
233566
  const nextPrimitive = g.children[i0];
233483
233567
  if (!(nextPrimitive instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d))
233484
233568
  break;
233485
- if (!_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(basePrimitive, nextPrimitive)) // TODO: use this._options.duplicatePointTolerance
233569
+ if (!_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(basePrimitive, nextPrimitive, false, this._options.duplicatePointTolerance))
233486
233570
  break;
233487
233571
  }
233488
233572
  // i0 has already advanced
@@ -233495,8 +233579,32 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
233495
233579
  }
233496
233580
  g.children.length = numAccept;
233497
233581
  }
233498
- handlePath(g) { return this.handleCurveChain(g); }
233499
- handleLoop(g) { return this.handleCurveChain(g); }
233582
+ handlePath(g) {
233583
+ return this.handleCurveChain(g);
233584
+ }
233585
+ handleLoop(g) {
233586
+ this.handleCurveChain(g);
233587
+ if (g.children.length > 1 && this._options.consolidateLoopSeam) {
233588
+ const lastChild = g.children[g.children.length - 1];
233589
+ const firstChild = g.children[0];
233590
+ 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)) {
233591
+ if (this._options.consolidateLinearGeometry && !this._options.disableLinearCompression) {
233592
+ const lastPoints = lastChild.points;
233593
+ lastPoints.pop(); // the original start point survives as an interior point in the new first primitive
233594
+ g.children[0] = _LineString3d__WEBPACK_IMPORTED_MODULE_3__.LineString3d.createPoints([...lastPoints, ...firstChild.points]);
233595
+ g.children.pop();
233596
+ }
233597
+ }
233598
+ else if (lastChild instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d && firstChild instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d) {
233599
+ if (this._options.consolidateCompatibleArcs) {
233600
+ if (_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(lastChild, firstChild, false, this._options.duplicatePointTolerance)) {
233601
+ g.children[0] = lastChild;
233602
+ g.children.pop();
233603
+ }
233604
+ }
233605
+ }
233606
+ }
233607
+ }
233500
233608
  handleParityRegion(g) {
233501
233609
  for (const child of g.children)
233502
233610
  child.dispatchToGeometryHandler(this);
@@ -233925,16 +234033,19 @@ __webpack_require__.r(__webpack_exports__);
233925
234033
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
233926
234034
  /* harmony export */ PlanarSubdivision: () => (/* binding */ PlanarSubdivision)
233927
234035
  /* 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");
234036
+ /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
234037
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
234038
+ /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
234039
+ /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
234040
+ /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
234041
+ /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
234042
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
234043
+ /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
234044
+ /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
234045
+ /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
234046
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
234047
+ /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
234048
+ /* harmony import */ var _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../RegionOpsClassificationSweeps */ "../../core/geometry/lib/esm/curve/RegionOpsClassificationSweeps.js");
233938
234049
  /*---------------------------------------------------------------------------------------------
233939
234050
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
233940
234051
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -233949,6 +234060,9 @@ __webpack_require__.r(__webpack_exports__);
233949
234060
 
233950
234061
 
233951
234062
 
234063
+
234064
+
234065
+
233952
234066
  /** @packageDocumentation
233953
234067
  * @module Curve
233954
234068
  */
@@ -233991,19 +234105,19 @@ class MapCurvePrimitiveToCurveLocationDetailPairArray {
233991
234105
  * added to the graph because it isn't in the `primitiveToPair` map. By splitting such a missing primitive in two, we
233992
234106
  * introduce two intersections for each half, which allows the primitive to be represented in the map.
233993
234107
  */
233994
- splitAndAppendMissingClosedPrimitives(primitives, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
234108
+ splitAndAppendMissingClosedPrimitives(primitives, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
233995
234109
  for (const p of primitives) {
233996
234110
  let closedCurveSplitCandidate = false;
233997
- if (p instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_1__.Arc3d)
234111
+ if (p instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_2__.Arc3d)
233998
234112
  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.
234113
+ 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
234114
  closedCurveSplitCandidate = p.startPoint().isAlmostEqualXY(p.endPoint(), tolerance);
234001
234115
  if (closedCurveSplitCandidate && !this.primitiveToPair.has(p)) {
234002
234116
  const p0 = p.clonePartialCurve(0.0, 0.5);
234003
234117
  const p1 = p.clonePartialCurve(0.5, 1.0);
234004
234118
  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)));
234119
+ 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)));
234120
+ 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
234121
  }
234008
234122
  }
234009
234123
  }
@@ -234017,7 +234131,7 @@ class PlanarSubdivision {
234017
234131
  * Create a graph from an array of curves, and an array of the curves' precomputed intersections.
234018
234132
  * Z-coordinates are ignored.
234019
234133
  */
234020
- static assembleHalfEdgeGraph(primitives, allPairs, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
234134
+ static assembleHalfEdgeGraph(primitives, allPairs, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
234021
234135
  // map from key CurvePrimitive to CurveLocationDetailPair
234022
234136
  const detailByPrimitive = new MapCurvePrimitiveToCurveLocationDetailPairArray();
234023
234137
  for (const pair of allPairs)
@@ -234026,7 +234140,7 @@ class PlanarSubdivision {
234026
234140
  // otherwise, these single-primitive loops are missing from the graph
234027
234141
  detailByPrimitive.splitAndAppendMissingClosedPrimitives(primitives, mergeTolerance);
234028
234142
  }
234029
- const graph = new _topology_Graph__WEBPACK_IMPORTED_MODULE_5__.HalfEdgeGraph();
234143
+ const graph = new _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraph();
234030
234144
  for (const entry of detailByPrimitive.primitiveToPair.entries()) {
234031
234145
  const p = entry[0];
234032
234146
  // convert each interval intersection into two isolated intersections
@@ -234034,12 +234148,12 @@ class PlanarSubdivision {
234034
234148
  if (!detailPair.detailA.hasFraction1)
234035
234149
  return [...accumulator, detailPair];
234036
234150
  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);
234151
+ const detail0 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction, detail.point);
234152
+ const detail1 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction1, detail.point1);
234039
234153
  return [
234040
234154
  ...accumulator,
234041
- _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(detail0, detail0),
234042
- _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(detail1, detail1),
234155
+ _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(detail0, detail0),
234156
+ _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(detail1, detail1),
234043
234157
  ];
234044
234158
  }, []);
234045
234159
  // lexical sort on p intersection fraction
@@ -234051,12 +234165,12 @@ class PlanarSubdivision {
234051
234165
  let last = { point: p.startPoint(), fraction: 0.0 };
234052
234166
  for (const detailPair of details) {
234053
234167
  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
234168
+ const detailFraction = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.restrictToInterval(detail.fraction, 0, 1); // truncate fraction, but don't snap point; clustering happens later
234055
234169
  last = this.addHalfEdge(graph, p, last.point, last.fraction, detail.point, detailFraction, mergeTolerance);
234056
234170
  }
234057
234171
  this.addHalfEdge(graph, p, last.point, last.fraction, p.endPoint(), 1.0, mergeTolerance);
234058
234172
  }
234059
- _topology_Merging__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraphMerge.clusterAndMergeXYTheta(graph, (he) => he.sortAngle);
234173
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.clusterAndMergeXYTheta(graph, (he) => he.sortAngle);
234060
234174
  return graph;
234061
234175
  }
234062
234176
  /**
@@ -234070,11 +234184,13 @@ class PlanarSubdivision {
234070
234184
  * @param fraction1 end fraction
234071
234185
  * @returns end point and fraction, or start point and fraction if no action
234072
234186
  */
234073
- static addHalfEdge(graph, p, point0, fraction0, point1, fraction1, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
234187
+ static addHalfEdge(graph, p, point0, fraction0, point1, fraction1, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
234074
234188
  if (point0.isAlmostEqualXY(point1, mergeTolerance))
234075
234189
  return { point: point0, fraction: fraction0 };
234076
234190
  const halfEdge = graph.createEdgeXYAndZ(point0, 0, point1, 0);
234077
- const detail01 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1);
234191
+ if (p.parent && p.parent instanceof _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__.RegionGroupMember && p.parent.parentGroup.groupOpType === _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__.RegionGroupOpType.NonBounding)
234192
+ halfEdge.setMaskAroundEdge(_topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.BRIDGE_EDGE);
234193
+ const detail01 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1);
234078
234194
  const mate = halfEdge.edgeMate;
234079
234195
  halfEdge.edgeTag = detail01;
234080
234196
  halfEdge.sortData = 1.0;
@@ -234092,7 +234208,7 @@ class PlanarSubdivision {
234092
234208
  * @returns the area (forced to zero if within tolerance)
234093
234209
  */
234094
234210
  static collectSignedLoop(loop, outLoops, zeroAreaTolerance = 1.0e-10, isSliverFace) {
234095
- let area = isSliverFace ? 0.0 : _RegionOps__WEBPACK_IMPORTED_MODULE_7__.RegionOps.computeXYArea(loop);
234211
+ let area = isSliverFace ? 0.0 : _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.computeXYArea(loop);
234096
234212
  if (area === undefined)
234097
234213
  area = 0;
234098
234214
  if (Math.abs(area) < zeroAreaTolerance)
@@ -234106,41 +234222,115 @@ class PlanarSubdivision {
234106
234222
  outLoops.slivers.push(loop);
234107
234223
  return area;
234108
234224
  }
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);
234225
+ /** Extract geometric info from a topological edge. */
234226
+ static extractGeometryFromEdge(edge) {
234227
+ if (edge.sortData !== undefined && edge.edgeTag && edge.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail) {
234228
+ const detail = edge.edgeTag;
234229
+ if (detail.curve && detail.fraction1 !== undefined) {
234230
+ const reversed = edge.sortData < 0;
234231
+ return { detail, reversed };
234232
+ }
234233
+ }
234234
+ return undefined;
234235
+ }
234236
+ /** Create the geometry for a topological edge. */
234237
+ static createCurveInEdge(edge) {
234238
+ const info = this.extractGeometryFromEdge(edge);
234239
+ if (info) {
234240
+ if (info.reversed)
234241
+ return info.detail.curve.clonePartialCurve(info.detail.fraction1, info.detail.fraction);
234242
+ return info.detail.curve.clonePartialCurve(info.detail.fraction, info.detail.fraction1);
234243
+ }
234244
+ return undefined;
234245
+ }
234246
+ /**
234247
+ * Create a [[Loop]] for the given face or super face.
234248
+ * @param face a node in the face loop, or an array of HalfEdges that comprise a loop (e.g., a super face).
234249
+ * @param announce optional callback invoked on each edge/curve of the face/Loop.
234250
+ * @param compress whether to consolidate adjacent curves in the output Loop (default `false`).
234251
+ * If `announce` is provided, no compression is performed, as edges and curves would no longer be in 1-1 correspondence.
234252
+ */
234253
+ static createLoopInFace(face, announce, compress = false) {
234254
+ if (announce)
234255
+ compress = false;
234256
+ const loop = _Loop__WEBPACK_IMPORTED_MODULE_10__.Loop.create();
234257
+ const addEdgeCurve = (he) => {
234258
+ const curve = this.createCurveInEdge(he);
234259
+ if (curve) {
234260
+ announce?.(he, curve, loop);
234261
+ loop.tryAddChild(curve);
234262
+ }
234263
+ };
234264
+ if (Array.isArray(face))
234265
+ face.forEach(addEdgeCurve);
234266
+ else
234267
+ face.announceEdgesInFace(addEdgeCurve);
234268
+ if (compress) {
234269
+ const options = new _RegionOps__WEBPACK_IMPORTED_MODULE_9__.ConsolidateAdjacentCurvePrimitivesOptions();
234270
+ options.consolidateLoopSeam = true;
234271
+ _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.consolidateAdjacentPrimitives(loop, options);
234272
+ }
234273
+ if (loop.isPhysicallyClosedCurve(undefined, true))
234274
+ return loop;
234275
+ (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(false, "createLoopInFace: face is not physically closed");
234276
+ return undefined;
234277
+ }
234278
+ /**
234279
+ * Create a [[Loop]] or [[ParityRegion]] for the given face.
234280
+ * * A ParityRegion is created for a split-washer type face by removing bridge edges.
234281
+ * @param face a node in the face loop.
234282
+ * @param bridgeMask mask preset on bridge edges (default is `HalfEdgeMask.BRIDGE_EDGE`).
234283
+ * @param visitMask mask to use for visiting edges in the face loop (default is `HalfEdgeMask.VISITED`).
234284
+ */
234285
+ static createLoopOrParityRegionInFace(face, bridgeMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.BRIDGE_EDGE, visitMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.VISITED) {
234286
+ let region;
234287
+ if (face.isSplitWasherFace(bridgeMask)) {
234288
+ const loops = [];
234289
+ const loopEdges = [];
234290
+ const bridgeStack = [face.findMaskAroundFace(bridgeMask, true)];
234291
+ const announceEdge = (he) => { he.setMask(visitMask); loopEdges.push(he); };
234292
+ const announceBridge = (he) => { if (!he.isMaskSet(visitMask))
234293
+ bridgeStack.push(he); };
234294
+ face.clearMaskAroundFace(visitMask);
234295
+ let bridge;
234296
+ while (undefined !== (bridge = bridgeStack.pop())) {
234297
+ bridge.setMask(visitMask);
234298
+ const loopSeed = bridge.findMaskAroundFace(bridgeMask, false); // advance to next loop
234299
+ if (loopSeed) {
234300
+ if (loopSeed.isMaskSet(visitMask))
234301
+ continue;
234302
+ loopEdges.length = 0;
234303
+ if (loopSeed.announceEdgesInSuperFace(bridgeMask, announceEdge, announceBridge)) {
234304
+ const loop = this.createLoopInFace(loopEdges, undefined, true);
234305
+ if (loop) {
234306
+ loops.push(loop);
234307
+ continue;
234308
+ }
234309
+ }
234124
234310
  }
234125
234311
  }
234126
- he = he.faceSuccessor;
234127
- } while (he !== faceSeed);
234128
- return loop;
234312
+ region = _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.sortOuterAndHoleLoopsXY(loops);
234313
+ region = _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.simplifyRegion(region);
234314
+ }
234315
+ else {
234316
+ region = this.createLoopInFace(face, undefined, true);
234317
+ }
234318
+ return (region && (region instanceof _Loop__WEBPACK_IMPORTED_MODULE_10__.Loop || region instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_11__.ParityRegion)) ? region : undefined;
234129
234319
  }
234130
- // Return true if there are only two edges in the face loop, and their start curvatures are the same.
234320
+ /** Return true if there are only two edges in the face loop, and their start curvatures are the same. */
234131
234321
  static isNullFace(he) {
234132
234322
  const faceHasTwoEdges = (he.faceSuccessor.faceSuccessor === he);
234133
234323
  let faceIsBanana = false;
234134
234324
  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!
234325
+ const c0 = _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.curvatureSortKey(he);
234326
+ const c1 = _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.curvatureSortKey(he.faceSuccessor.edgeMate);
234327
+ if (!_Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(c0, c1)) // default tol!
234138
234328
  faceIsBanana = true; // heuristic: we could also check end curvatures, and/or higher derivatives...
234139
234329
  }
234140
234330
  return faceHasTwoEdges && !faceIsBanana;
234141
234331
  }
234142
- // Look across edge mates (possibly several) for a nonnull mate face.
234143
- static nonNullEdgeMate(_graph, e) {
234332
+ /** Look across edge mates (possibly several) for a non-null mate face. */
234333
+ static getNonNullEdgeMate(_graph, e) {
234144
234334
  if (this.isNullFace(e))
234145
234335
  return undefined;
234146
234336
  let e1 = e.edgeMate;
@@ -234152,7 +234342,7 @@ class PlanarSubdivision {
234152
234342
  return e1;
234153
234343
  }
234154
234344
  static collectSignedLoopSetsInHalfEdgeGraph(graph, zeroAreaTolerance = 1.0e-10) {
234155
- const q = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_9__.HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, undefined);
234345
+ const q = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_12__.HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, undefined);
234156
234346
  const result = [];
234157
234347
  const edgeMap = new Map();
234158
234348
  for (const faceSeeds of q) {
@@ -234162,15 +234352,15 @@ class PlanarSubdivision {
234162
234352
  const isNullFace = this.isNullFace(faceSeed);
234163
234353
  const loop = this.createLoopInFace(faceSeed, (he, curveC, loopC) => {
234164
234354
  if (!isNullFace) {
234165
- const mate = this.nonNullEdgeMate(graph, he);
234355
+ const mate = this.getNonNullEdgeMate(graph, he);
234166
234356
  if (mate !== undefined) {
234167
234357
  const e = edgeMap.get(mate);
234168
234358
  if (e === undefined) {
234169
234359
  // 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);
234360
+ const e1 = new _Loop__WEBPACK_IMPORTED_MODULE_10__.LoopCurveLoopCurve(loopC, curveC, undefined, undefined);
234171
234361
  edgeMap.set(he, e1);
234172
234362
  }
234173
- else if (e instanceof _Loop__WEBPACK_IMPORTED_MODULE_8__.LoopCurveLoopCurve) {
234363
+ else if (e instanceof _Loop__WEBPACK_IMPORTED_MODULE_10__.LoopCurveLoopCurve) {
234174
234364
  e.setB(loopC, curveC);
234175
234365
  edges.push(e);
234176
234366
  edgeMap.delete(mate);
@@ -234178,7 +234368,8 @@ class PlanarSubdivision {
234178
234368
  }
234179
234369
  }
234180
234370
  });
234181
- this.collectSignedLoop(loop, componentAreas, zeroAreaTolerance, isNullFace);
234371
+ if (loop)
234372
+ this.collectSignedLoop(loop, componentAreas, zeroAreaTolerance, isNullFace);
234182
234373
  }
234183
234374
  componentAreas.edges = edges;
234184
234375
  result.push(componentAreas);
@@ -234226,11 +234417,12 @@ __webpack_require__.r(__webpack_exports__);
234226
234417
  /* harmony export */ StrokeCountSection: () => (/* binding */ StrokeCountSection)
234227
234418
  /* harmony export */ });
234228
234419
  /* 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");
234420
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
234421
+ /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
234231
234422
  /* 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");
234423
+ /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
234424
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
234425
+ /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
234234
234426
  /* harmony import */ var _StrokeCountMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./StrokeCountMap */ "../../core/geometry/lib/esm/curve/Query/StrokeCountMap.js");
234235
234427
  /*---------------------------------------------------------------------------------------------
234236
234428
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
@@ -234246,6 +234438,7 @@ __webpack_require__.r(__webpack_exports__);
234246
234438
 
234247
234439
 
234248
234440
 
234441
+
234249
234442
  // cspell:word remapa
234250
234443
  /**
234251
234444
  * abstract methods for callbacks during sweeps of collections of StrokeCount Structures.
@@ -234376,6 +234569,7 @@ class StrokeCountMapVisitorApplyMaxCurveLength extends StrokeCountMapMultipassVi
234376
234569
  * * `parent` = parent CurveCollection.
234377
234570
  *
234378
234571
  * An instance is normally created with either a `Path` or `Loop` as the parent.
234572
+ * @internal
234379
234573
  */
234380
234574
  class StrokeCountChain {
234381
234575
  maps;
@@ -234391,7 +234585,7 @@ class StrokeCountChain {
234391
234585
  this.maps = [];
234392
234586
  this.options = options;
234393
234587
  }
234394
- static createForCurveChain(chain, options) {
234588
+ static create(chain, options) {
234395
234589
  const result = new StrokeCountChain(chain, options);
234396
234590
  result.parent = chain;
234397
234591
  // A chain can only contain primitives !!!!
@@ -234462,16 +234656,24 @@ class StrokeCountSection {
234462
234656
  * construct array of arrays of `StrokeCountMap`s
234463
234657
  * @param parent
234464
234658
  */
234465
- static createForParityRegionOrChain(parent, options) {
234659
+ static create(parent, options) {
234466
234660
  const result = new StrokeCountSection(parent);
234467
- if (parent instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
234661
+ const appendCurveChain = (chain) => result.chains.push(StrokeCountChain.create(chain, options));
234662
+ const appendParityRegion = (region) => { for (const child of region.children)
234663
+ appendCurveChain(child); };
234664
+ if (parent instanceof _UnionRegion__WEBPACK_IMPORTED_MODULE_3__.UnionRegion) {
234468
234665
  for (const child of parent.children) {
234469
- const p = StrokeCountChain.createForCurveChain(child, options);
234470
- result.chains.push(p);
234666
+ if (child instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion)
234667
+ appendParityRegion(child);
234668
+ else
234669
+ appendCurveChain(child);
234471
234670
  }
234472
234671
  }
234473
- else if (parent instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
234474
- result.chains.push(StrokeCountChain.createForCurveChain(parent, options));
234672
+ else if (parent instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
234673
+ appendParityRegion(parent);
234674
+ }
234675
+ else if (parent instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
234676
+ appendCurveChain(parent);
234475
234677
  }
234476
234678
  return result;
234477
234679
  }
@@ -234550,11 +234752,12 @@ class StrokeCountSection {
234550
234752
  for (let chainIndex = 0; chainIndex < numChainPerSection; chainIndex++) {
234551
234753
  const numPrimitive = sections[0].chains[chainIndex].maps.length;
234552
234754
  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++)
234755
+ const numComponent = sections[0].chains[chainIndex].maps[primitiveIndex].componentData?.length ?? 0;
234756
+ if (numComponent > 0) {
234757
+ for (let i = 0; i < numComponent; i++) {
234556
234758
  if (!this.applyMultipassVisitorCallbackNoComponents(sections, chainIndex, primitiveIndex, i, callback))
234557
234759
  return false;
234760
+ }
234558
234761
  }
234559
234762
  else {
234560
234763
  if (!this.applyMultipassVisitorCallbackNoComponents(sections, chainIndex, primitiveIndex, undefined, callback))
@@ -234602,11 +234805,11 @@ class StrokeCountSection {
234602
234805
  return this.chains[0].getStrokes();
234603
234806
  }
234604
234807
  else {
234605
- const region = _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion.create();
234808
+ const region = _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion.create();
234606
234809
  for (const c of this.chains) {
234607
234810
  const strokes = c.getStrokes();
234608
234811
  if (strokes instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_2__.LineString3d)
234609
- region.tryAddChild(_Loop__WEBPACK_IMPORTED_MODULE_5__.Loop.create(strokes));
234812
+ region.tryAddChild(_Loop__WEBPACK_IMPORTED_MODULE_6__.Loop.create(strokes));
234610
234813
  }
234611
234814
  return region;
234612
234815
  }
@@ -234628,8 +234831,8 @@ class StrokeCountSection {
234628
234831
  if (strokeB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_2__.LineString3d) {
234629
234832
  if (strokeA.numPoints() === strokeB.numPoints()) {
234630
234833
  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();
234834
+ const pointA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
234835
+ const pointB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
234633
234836
  const allPointA = strokeA.packedPoints;
234634
234837
  const allPointB = strokeB.packedPoints;
234635
234838
  for (let i = 0; i < n; i++) {
@@ -234641,8 +234844,8 @@ class StrokeCountSection {
234641
234844
  }
234642
234845
  }
234643
234846
  }
234644
- else if (strokeA instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
234645
- if (strokeB instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
234847
+ else if (strokeA instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
234848
+ if (strokeB instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
234646
234849
  const childrenA = strokeA.children;
234647
234850
  const childrenB = strokeB.children;
234648
234851
  const n = childrenA.length;
@@ -234655,8 +234858,8 @@ class StrokeCountSection {
234655
234858
  }
234656
234859
  }
234657
234860
  }
234658
- else if (strokeA instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
234659
- if (strokeB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
234861
+ else if (strokeA instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
234862
+ if (strokeB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
234660
234863
  const childrenA = strokeA.children;
234661
234864
  const childrenB = strokeB.children;
234662
234865
  const n = childrenA.length;
@@ -234859,10 +235062,11 @@ __webpack_require__.r(__webpack_exports__);
234859
235062
  /* harmony import */ var _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/GeometryHandler */ "../../core/geometry/lib/esm/geometry3d/GeometryHandler.js");
234860
235063
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
234861
235064
  /* 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");
235065
+ /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
234863
235066
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
235067
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
234864
235068
  /* 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");
235069
+ /* harmony import */ var _StrokeOptions__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
234866
235070
  /*---------------------------------------------------------------------------------------------
234867
235071
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
234868
235072
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -234875,6 +235079,7 @@ __webpack_require__.r(__webpack_exports__);
234875
235079
 
234876
235080
 
234877
235081
 
235082
+
234878
235083
  /**
234879
235084
  * Implementation class for computing XY area moments.
234880
235085
  * @internal
@@ -234930,7 +235135,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234930
235135
  segment.endPoint(this._point1);
234931
235136
  momentData.accumulateTriangleMomentsXY(undefined, this._point0, this._point1);
234932
235137
  }
234933
- /** Accumulate integrals from origin to all primitives in the chain. */
235138
+ /** Accumulate integrals from origin to all primitives in the loop. */
234934
235139
  handleLoop(loop) {
234935
235140
  const momentData = this._activeMomentData = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_3__.MomentData.create();
234936
235141
  momentData.needOrigin = false;
@@ -234940,7 +235145,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234940
235145
  return momentData;
234941
235146
  }
234942
235147
  handleAnyRegion(region) {
234943
- // guarantee there is no overlapping children
235148
+ // guarantee there are no overlapping children and parity loops have been properly oriented
234944
235149
  const merged = _RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.regionBooleanXY(region, undefined, _RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionBinaryOpType.Union);
234945
235150
  if (!merged)
234946
235151
  return undefined;
@@ -234950,7 +235155,9 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234950
235155
  for (const child of merged.children) {
234951
235156
  const childMoments = child.dispatchToGeometryHandler(this);
234952
235157
  if (childMoments) {
234953
- const sign0 = childMoments.signFactor(1.0);
235158
+ // parity region hole sums subtract; all other regions add
235159
+ const scale = (merged instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_6__.ParityRegion && childMoments.quantitySum < 0) ? -1.0 : 1.0;
235160
+ const sign0 = childMoments.signFactor(scale);
234954
235161
  summedMoments.accumulateProducts(childMoments, sign0);
234955
235162
  }
234956
235163
  }
@@ -234968,7 +235175,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234968
235175
  getStrokeOptions() {
234969
235176
  if (this._strokeOptions)
234970
235177
  return this._strokeOptions;
234971
- const options = _StrokeOptions__WEBPACK_IMPORTED_MODULE_6__.StrokeOptions.createForCurves();
235178
+ const options = _StrokeOptions__WEBPACK_IMPORTED_MODULE_7__.StrokeOptions.createForCurves();
234972
235179
  // this is unusually fine for stroking, but appropriate for sum.
234973
235180
  options.angleTol = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_2__.Angle.createDegrees(5.0);
234974
235181
  this._strokeOptions = options;
@@ -234979,7 +235186,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
234979
235186
  * * Stroke the curve and accumulate stroke array.
234980
235187
  */
234981
235188
  handleCurvePrimitive(cp) {
234982
- const strokes = _LineString3d__WEBPACK_IMPORTED_MODULE_7__.LineString3d.create();
235189
+ const strokes = _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.create();
234983
235190
  const options = this.getStrokeOptions();
234984
235191
  cp.emitStrokes(strokes, options);
234985
235192
  this.handleLineString3d(strokes);
@@ -235021,27 +235228,28 @@ __webpack_require__.r(__webpack_exports__);
235021
235228
  /* harmony import */ var _geometry3d_IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../geometry3d/IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
235022
235229
  /* harmony import */ var _geometry3d_Point3dArrayCarrier__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../geometry3d/Point3dArrayCarrier */ "../../core/geometry/lib/esm/geometry3d/Point3dArrayCarrier.js");
235023
235230
  /* 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");
235231
+ /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
235025
235232
  /* 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");
235233
+ /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
235027
235234
  /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
235028
235235
  /* harmony import */ var _geometry3d_SortablePolygon__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../geometry3d/SortablePolygon */ "../../core/geometry/lib/esm/geometry3d/SortablePolygon.js");
235029
235236
  /* harmony import */ var _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../geometry3d/Transform */ "../../core/geometry/lib/esm/geometry3d/Transform.js");
235030
235237
  /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
235031
235238
  /* 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");
235239
+ /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
235240
+ /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
235241
+ /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
235035
235242
  /* harmony import */ var _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../topology/Triangulation */ "../../core/geometry/lib/esm/topology/Triangulation.js");
235036
235243
  /* 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");
235244
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
235038
235245
  /* harmony import */ var _CurveOps__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./CurveOps */ "../../core/geometry/lib/esm/curve/CurveOps.js");
235039
235246
  /* harmony import */ var _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
235040
235247
  /* 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");
235248
+ /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
235042
235249
  /* harmony import */ var _internalContexts_ChainCollectorContext__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./internalContexts/ChainCollectorContext */ "../../core/geometry/lib/esm/curve/internalContexts/ChainCollectorContext.js");
235043
235250
  /* harmony import */ var _internalContexts_PolygonOffsetContext__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./internalContexts/PolygonOffsetContext */ "../../core/geometry/lib/esm/curve/internalContexts/PolygonOffsetContext.js");
235044
235251
  /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
235252
+ /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
235045
235253
  /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
235046
235254
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
235047
235255
  /* harmony import */ var _OffsetOptions__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./OffsetOptions */ "../../core/geometry/lib/esm/curve/OffsetOptions.js");
@@ -235050,7 +235258,7 @@ __webpack_require__.r(__webpack_exports__);
235050
235258
  /* harmony import */ var _Query_ConsolidateAdjacentPrimitivesContext__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./Query/ConsolidateAdjacentPrimitivesContext */ "../../core/geometry/lib/esm/curve/Query/ConsolidateAdjacentPrimitivesContext.js");
235051
235259
  /* harmony import */ var _Query_CurveSplitContext__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./Query/CurveSplitContext */ "../../core/geometry/lib/esm/curve/Query/CurveSplitContext.js");
235052
235260
  /* 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");
235261
+ /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
235054
235262
  /* harmony import */ var _RegionMomentsXY__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RegionMomentsXY */ "../../core/geometry/lib/esm/curve/RegionMomentsXY.js");
235055
235263
  /* harmony import */ var _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./RegionOpsClassificationSweeps */ "../../core/geometry/lib/esm/curve/RegionOpsClassificationSweeps.js");
235056
235264
  /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
@@ -235099,6 +235307,7 @@ __webpack_require__.r(__webpack_exports__);
235099
235307
 
235100
235308
 
235101
235309
 
235310
+
235102
235311
 
235103
235312
 
235104
235313
  /**
@@ -235400,16 +235609,17 @@ class RegionOps {
235400
235609
  * @param loopsB second set of loops (treated as a union)
235401
235610
  * @param operation indicates Union, Intersection, Parity, AMinusB, or BMinusA
235402
235611
  * @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.
235612
+ * @returns a region resulting from merging input loops and the boolean operation.
235405
235613
  */
235406
235614
  static regionBooleanXY(loopsA, loopsB, operation, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
235407
- let result;
235615
+ const result = _UnionRegion__WEBPACK_IMPORTED_MODULE_14__.UnionRegion.create();
235408
235616
  const context = _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionBooleanContext.create(_RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union);
235409
235617
  context.addMembers(loopsA, loopsB);
235410
235618
  context.annotateAndMergeCurvesInGraph(mergeTolerance);
235619
+ const visitMask = context.graph.grabMask(false);
235411
235620
  const range = context.groupA.range().union(context.groupB.range());
235412
235621
  const areaTol = this.computeXYAreaTolerance(range, mergeTolerance);
235622
+ const bridgeMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE;
235413
235623
  context.runClassificationSweep(operation, (_graph, face, faceType, area) => {
235414
235624
  // ignore danglers and null faces, but not 2-edge "banana" faces with nonzero area
235415
235625
  if (face.countEdgesAroundFace() < 2)
@@ -235417,15 +235627,13 @@ class RegionOps {
235417
235627
  if (Math.abs(area) < areaTol)
235418
235628
  return;
235419
235629
  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
- }
235630
+ const loopOrParityRegion = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.createLoopOrParityRegionInFace(face, bridgeMask, visitMask);
235631
+ if (loopOrParityRegion)
235632
+ result.tryAddChild(loopOrParityRegion);
235426
235633
  }
235427
235634
  });
235428
- return result ? this.simplifyRegion(result) : undefined;
235635
+ context.graph.dropMask(visitMask);
235636
+ return this.simplifyRegion(result);
235429
235637
  }
235430
235638
  /**
235431
235639
  * Return a polyface whose facets are a boolean operation between the input regions.
@@ -235458,7 +235666,7 @@ class RegionOps {
235458
235666
  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
235667
  if (!graph)
235460
235668
  return undefined;
235461
- const loopEdges = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_16__.HalfEdgeGraphSearch.collectExtendedBoundaryLoopsInGraph(graph, _topology_Graph__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeMask.EXTERIOR);
235669
+ const loopEdges = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeGraphSearch.collectExtendedBoundaryLoopsInGraph(graph, _topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.EXTERIOR);
235462
235670
  const allLoops = [];
235463
235671
  for (const graphLoop of loopEdges) {
235464
235672
  const points = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray();
@@ -235740,19 +235948,45 @@ class RegionOps {
235740
235948
  }
235741
235949
  return _geometry3d_SortablePolygon__WEBPACK_IMPORTED_MODULE_33__.SortablePolygon.sortAsAnyRegion(loopAndArea);
235742
235950
  }
235951
+ /**
235952
+ * Collect inputs that are nominally closed: regions, and physically closed curves.
235953
+ * * Physically closed input curves are each returned wrapped in a Loop to facilitate xy-algorithms,
235954
+ * but outside this limited context, these Loops only makes sense if they are planar.
235955
+ */
235956
+ static collectRegionsAndClosedPrimitives(curves, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
235957
+ const regions = [];
235958
+ if (!Array.isArray(curves))
235959
+ curves = [curves];
235960
+ for (const curve of curves) {
235961
+ 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) {
235962
+ regions.push(curve);
235963
+ }
235964
+ else if (curve instanceof _Path__WEBPACK_IMPORTED_MODULE_24__.Path) {
235965
+ if (curve.isPhysicallyClosedCurve(tolerance))
235966
+ regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(...curve.children));
235967
+ }
235968
+ else if (curve instanceof _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__.CurvePrimitive) {
235969
+ if (curve.isPhysicallyClosedCurve(tolerance))
235970
+ regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(curve));
235971
+ }
235972
+ }
235973
+ return regions;
235974
+ }
235743
235975
  /**
235744
235976
  * Find all xy-areas bounded by the unstructured, possibly intersecting curves.
235745
235977
  * * 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.
235978
+ * * "Holes" implied/bounded by inputs are _not_ preserved/discovered in output; in particular [[ParityRegion]]
235979
+ * hole loops are treated like any other positive area loops.
235980
+ * * A common use case of this method is to assemble the bounding negative-area "exterior" loop for each connected
235981
+ * component of input curves. Passing `addBridges = true` decreases the number of connected components for nested
235982
+ * input [[Loop]]s, and thus increases the likelihood of returning exactly one exterior loop. (This is why the
235983
+ * default value for `addBridges` is `true`.)
235984
+ * @param curvesAndRegions Any collection of curves. Each [[AnyRegion]] contributes its children _stripped of
235985
+ * parity context_.
235754
235986
  * @param tolerance optional distance tolerance for coincidence.
235755
- * @returns array of [[SignedLoops]], each entry of which describes the faces in a single connected component:
235987
+ * @param addBridges whether to add line segments to connect nested input [[Loop]]s (default is `true`). When `false`,
235988
+ * no line segments are added to the input curves, but the number of output components may be greater than expected.
235989
+ * @returns array of [[SignedLoops]], each entry of which describes the areas bounded by a single connected component:
235756
235990
  * * `positiveAreaLoops` contains "interior" loops, _including holes in ParityRegion input_. These loops have
235757
235991
  * positive area and counterclockwise orientation.
235758
235992
  * * `negativeAreaLoops` contains (probably just one) "exterior" loop which is ordered clockwise.
@@ -235760,14 +235994,25 @@ class RegionOps {
235760
235994
  * * `edges` contains a [[LoopCurveLoopCurve]] object for each component edge, collecting both loops adjacent
235761
235995
  * to the edge and a constituent curve in each.
235762
235996
  */
235763
- static constructAllXYRegionLoops(curvesAndRegions, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
235997
+ static constructAllXYRegionLoops(curvesAndRegions, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance, addBridges = true) {
235764
235998
  let primitives = RegionOps.collectCurvePrimitives(curvesAndRegions, undefined, true, true);
235765
235999
  primitives = _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_34__.TransferWithSplitArcs.clone(_CurveCollection__WEBPACK_IMPORTED_MODULE_25__.BagOfCurves.create(...primitives)).children;
235766
236000
  const range = this.curveArrayRange(primitives);
235767
236001
  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);
236002
+ if (addBridges) { // generate a temp graph to extract its bridge edges
236003
+ const context = _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionBooleanContext.create(_RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union);
236004
+ const regions = this.collectRegionsAndClosedPrimitives(curvesAndRegions, tolerance);
236005
+ context.addMembers(regions, undefined);
236006
+ context.annotateAndMergeCurvesInGraph(tolerance);
236007
+ context.graph.announceEdges((_graph, edge) => {
236008
+ if (edge.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE))
236009
+ primitives.push(_LineSegment3d__WEBPACK_IMPORTED_MODULE_35__.LineSegment3d.create(edge.getPoint3d(), edge.faceSuccessor.getPoint3d()));
236010
+ return true;
236011
+ });
236012
+ }
236013
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_36__.CurveCurve.allIntersectionsAmongPrimitivesXY(primitives, tolerance);
236014
+ const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.assembleHalfEdgeGraph(primitives, intersections, tolerance);
236015
+ return _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.collectSignedLoopSetsInHalfEdgeGraph(graph, areaTol);
235771
236016
  }
235772
236017
  /**
235773
236018
  * Collect all `CurvePrimitives` in loosely typed input.
@@ -235823,12 +236068,12 @@ class RegionOps {
235823
236068
  * @param worldToLocal transform to apply to data before computing its range
235824
236069
  */
235825
236070
  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)
236071
+ const range = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_37__.Range3d.create();
236072
+ if (data instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__.GeometryQuery)
235828
236073
  data.extendRange(range, worldToLocal);
235829
236074
  else if (Array.isArray(data)) {
235830
236075
  for (const c of data) {
235831
- if (c instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_37__.GeometryQuery)
236076
+ if (c instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__.GeometryQuery)
235832
236077
  c.extendRange(range, worldToLocal);
235833
236078
  else if (c instanceof _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d)
235834
236079
  range.extendPoint(c, worldToLocal);
@@ -235864,7 +236109,7 @@ class RegionOps {
235864
236109
  for (const polygon of polygons)
235865
236110
  writablePolygons.push(_geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray.create(polygon));
235866
236111
  }
235867
- const sortedPolygons = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_38__.PolygonOps.sortOuterAndHoleLoopsXY(writablePolygons);
236112
+ const sortedPolygons = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_39__.PolygonOps.sortOuterAndHoleLoopsXY(writablePolygons);
235868
236113
  if (sortedPolygons.length === 1) { // below requires exactly one outer loop!
235869
236114
  if (graph = _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__.Triangulator.createTriangulatedGraphFromLoops(sortedPolygons[0]))
235870
236115
  _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__.Triangulator.flipTriangles(graph);
@@ -235947,7 +236192,7 @@ class RegionOps {
235947
236192
  if (!graph)
235948
236193
  return undefined;
235949
236194
  if (options?.maximizeConvexFacets)
235950
- _topology_Merging__WEBPACK_IMPORTED_MODULE_39__.HalfEdgeGraphOps.expandConvexFaces(graph);
236195
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_40__.HalfEdgeGraphOps.expandConvexFaces(graph);
235951
236196
  return _polyface_PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_12__.PolyfaceBuilder.graphToPolyface(graph, options);
235952
236197
  }
235953
236198
  /**
@@ -235961,10 +236206,10 @@ class RegionOps {
235961
236206
  if (!graph)
235962
236207
  return undefined;
235963
236208
  if (maximize)
235964
- _topology_Merging__WEBPACK_IMPORTED_MODULE_39__.HalfEdgeGraphOps.expandConvexFaces(graph);
236209
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_40__.HalfEdgeGraphOps.expandConvexFaces(graph);
235965
236210
  const convexPolygons = [];
235966
236211
  graph.announceFaceLoops((_graph, seed) => {
235967
- if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeMask.EXTERIOR))
236212
+ if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.EXTERIOR))
235968
236213
  convexPolygons.push(_geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray.create(seed.collectAroundFace((node) => { return node.getPoint3d(); })));
235969
236214
  return true;
235970
236215
  });
@@ -235989,9 +236234,11 @@ class ConsolidateAdjacentCurvePrimitivesOptions {
235989
236234
  consolidateLinearGeometry = true;
235990
236235
  /** True to consolidate contiguous compatible arcs into a single Arc3d. */
235991
236236
  consolidateCompatibleArcs = true;
236237
+ /** True to consolidate the first and last primitives of a [[Loop]], allowing the start/end point to change. */
236238
+ consolidateLoopSeam = false;
235992
236239
  /** Disable LineSegment3d and LineString3d point compression. */
235993
236240
  disableLinearCompression = false;
235994
- /** Tolerance for collapsing identical points (if `!disableLinearCompression`). */
236241
+ /** Tolerance for detecting identical points. */
235995
236242
  duplicatePointTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance;
235996
236243
  /** Tolerance for removing interior colinear points (if `!disableLinearCompression`). */
235997
236244
  colinearPointTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance;
@@ -236013,6 +236260,7 @@ __webpack_require__.r(__webpack_exports__);
236013
236260
  /* harmony export */ GraphComponentArray: () => (/* binding */ GraphComponentArray),
236014
236261
  /* harmony export */ RegionBooleanContext: () => (/* binding */ RegionBooleanContext),
236015
236262
  /* harmony export */ RegionGroup: () => (/* binding */ RegionGroup),
236263
+ /* harmony export */ RegionGroupMember: () => (/* binding */ RegionGroupMember),
236016
236264
  /* harmony export */ RegionGroupOpType: () => (/* binding */ RegionGroupOpType),
236017
236265
  /* harmony export */ RegionOpsFaceToFaceSearch: () => (/* binding */ RegionOpsFaceToFaceSearch)
236018
236266
  /* harmony export */ });
@@ -236025,15 +236273,15 @@ __webpack_require__.r(__webpack_exports__);
236025
236273
  /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
236026
236274
  /* harmony import */ var _topology_RegularizeFace__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../topology/RegularizeFace */ "../../core/geometry/lib/esm/topology/RegularizeFace.js");
236027
236275
  /* 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");
236276
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
236277
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
236030
236278
  /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
236031
236279
  /* harmony import */ var _internalContexts_PlaneAltitudeRangeContext__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./internalContexts/PlaneAltitudeRangeContext */ "../../core/geometry/lib/esm/curve/internalContexts/PlaneAltitudeRangeContext.js");
236032
236280
  /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
236033
236281
  /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
236034
236282
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
236035
236283
  /* 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");
236284
+ /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
236037
236285
  /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
236038
236286
  /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
236039
236287
  /*---------------------------------------------------------------------------------------------
@@ -236537,6 +236785,94 @@ class RegionBooleanContext {
236537
236785
  this.extraGeometry.addMember(bridgeLine, true);
236538
236786
  }
236539
236787
  }
236788
+ /**
236789
+ * Simplify the graph by removing bridge edges that do not serve to connect inner and outer loops, i.e.:
236790
+ * * the bridge edge is dangling
236791
+ * * the bridge edge is adjacent to multiple faces
236792
+ * * the bridge edge is adjacent to a negative area face
236793
+ * @returns the number of extraneous bridge edges removed from the graph.
236794
+ */
236795
+ removeExtraneousBridgeEdges() {
236796
+ const toHeal = [];
236797
+ const interiorBridges = [];
236798
+ // lambda test for boundary edge. Relies only on face loop orientation. Doesn't use HalfEdgeMasks!
236799
+ const isExteriorEdge = (node) => {
236800
+ if (this.faceAreaFunction(node) < 0.0)
236801
+ return true;
236802
+ if (!node.findAroundFace(node.edgeMate))
236803
+ return this.faceAreaFunction(node.edgeMate) < 0.0;
236804
+ return false;
236805
+ };
236806
+ // isolate dangling bridges, bridges separating different faces, and "exterior" bridges in the negative area face
236807
+ this.graph.announceEdges((_graph, node) => {
236808
+ if (node.edgeTag !== undefined) {
236809
+ if (node.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail) {
236810
+ if (node.edgeTag.curve) {
236811
+ if (node.edgeTag.curve.parent instanceof RegionGroupMember) {
236812
+ if (node.edgeTag.curve.parent.parentGroup === this.extraGeometry) {
236813
+ if (node.isDangling || node.edgeMate.isDangling || !node.findAroundFace(node.edgeMate) || this.faceAreaFunction(node) < 0.0) {
236814
+ toHeal.push(node.vertexSuccessor);
236815
+ toHeal.push(node.edgeMate.vertexSuccessor);
236816
+ node.isolateEdge();
236817
+ }
236818
+ else {
236819
+ interiorBridges.push(node);
236820
+ }
236821
+ }
236822
+ }
236823
+ }
236824
+ }
236825
+ }
236826
+ return true;
236827
+ });
236828
+ // At this point, all bridges that were exterior are isolated, but this may have caused formerly
236829
+ // interior bridges to become exterior. Now we successively isolate exterior bridges until none remain.
236830
+ let numIsolatedThisPass;
236831
+ do {
236832
+ numIsolatedThisPass = 0;
236833
+ for (const node of interiorBridges) {
236834
+ if (!node.isIsolatedEdge && isExteriorEdge(node)) {
236835
+ toHeal.push(node.vertexSuccessor);
236836
+ toHeal.push(node.edgeMate.vertexSuccessor);
236837
+ node.isolateEdge();
236838
+ numIsolatedThisPass++;
236839
+ }
236840
+ }
236841
+ } while (numIsolatedThisPass > 0);
236842
+ // lambda to extend the detail interval on a side of a healed edge
236843
+ const mergeDetails = (he, newFraction, newPoint) => {
236844
+ if (he && he.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && he.sortData !== undefined && newFraction !== undefined && newPoint) {
236845
+ if (he.sortData > 0)
236846
+ he.edgeTag.captureFraction1Point1(newFraction, newPoint);
236847
+ else
236848
+ he.edgeTag.captureFractionPoint(newFraction, newPoint);
236849
+ }
236850
+ };
236851
+ // At this point all removable bridges are isolated. Clean up their original vertex loops, if possible.
236852
+ for (const doomedA of toHeal) {
236853
+ const doomedB = doomedA.vertexSuccessor;
236854
+ if ( // are the geometries mergeable?
236855
+ doomedA !== doomedB &&
236856
+ doomedA.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && doomedA.sortData !== undefined &&
236857
+ doomedB.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && doomedB.sortData !== undefined &&
236858
+ doomedA.edgeTag.curve === doomedB.edgeTag.curve &&
236859
+ doomedA.edgeTag.hasFraction1 && doomedB.edgeTag.hasFraction1 &&
236860
+ doomedA.sortData * doomedB.sortData < 0 &&
236861
+ ((doomedA.sortData > 0 && _Geometry__WEBPACK_IMPORTED_MODULE_7__.Geometry.isSmallRelative(doomedA.edgeTag.fraction - doomedB.edgeTag.fraction1)) ||
236862
+ (doomedA.sortData < 0 && _Geometry__WEBPACK_IMPORTED_MODULE_7__.Geometry.isSmallRelative(doomedA.edgeTag.fraction1 - doomedB.edgeTag.fraction)))) {
236863
+ const survivorA = _topology_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdge.healEdge(doomedA, false);
236864
+ if (survivorA) {
236865
+ const endFractionA = (doomedA.sortData > 0) ? doomedA.edgeTag.fraction1 : doomedA.edgeTag.fraction;
236866
+ const endPointA = (doomedA.sortData > 0) ? doomedA.edgeTag.point1 : doomedA.edgeTag.point;
236867
+ mergeDetails(survivorA, endFractionA, endPointA);
236868
+ const endFractionB = (doomedB.sortData > 0) ? doomedB.edgeTag.fraction1 : doomedB.edgeTag.fraction;
236869
+ const endPointB = (doomedB.sortData > 0) ? doomedB.edgeTag.point1 : doomedB.edgeTag.point;
236870
+ mergeDetails(survivorA.edgeMate, endFractionB, endPointB);
236871
+ }
236872
+ }
236873
+ }
236874
+ return this.graph.deleteIsolatedEdges();
236875
+ }
236540
236876
  /**
236541
236877
  * Markup and assembly steps for geometry in the RegionGroups.
236542
236878
  * * Annotate connection from group to curves.
@@ -236558,10 +236894,11 @@ class RegionBooleanContext {
236558
236894
  }
236559
236895
  }
236560
236896
  }
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);
236897
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_17__.CurveCurve.allIntersectionsAmongPrimitivesXY(allPrimitives, mergeTolerance);
236898
+ const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_18__.PlanarSubdivision.assembleHalfEdgeGraph(allPrimitives, intersections, mergeTolerance);
236563
236899
  this.graph = graph;
236564
236900
  this.faceAreaFunction = faceAreaFromCurvedEdgeData;
236901
+ this.removeExtraneousBridgeEdges();
236565
236902
  }
236566
236903
  _announceFaceFunction;
236567
236904
  /**
@@ -236649,7 +236986,7 @@ class RegionBooleanContext {
236649
236986
  const data = node.edgeTag;
236650
236987
  if (data instanceof RegionGroupMember)
236651
236988
  return updateRegionGroupMemberState(data);
236652
- if (data instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_18__.CurveLocationDetail) {
236989
+ if (data instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail) {
236653
236990
  // We trust that the caller has linked from the graph node to a curve which has a RegionGroupMember as its parent.
236654
236991
  const member = data.curve.parent;
236655
236992
  if (member instanceof RegionGroupMember)
@@ -238419,23 +238756,23 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
238419
238756
  let reversed = false;
238420
238757
  const uu = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.hypotenuseSquaredXY(ux, uy);
238421
238758
  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;
238759
+ const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e00x, e00y), uu, 0.0);
238423
238760
  if (this.updatePointToSegmentDistance(0, b0, a0, a1, fractionA, maxDistanceSquared, closestApproach))
238424
238761
  reversed = true;
238425
238762
  }
238426
238763
  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;
238764
+ const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e01x, e01y), uu, 0.0);
238428
238765
  if (this.updatePointToSegmentDistance(1, b1, a0, a1, fractionA, maxDistanceSquared, closestApproach))
238429
238766
  reversed = true;
238430
238767
  }
238431
238768
  const vv = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.hypotenuseSquaredXY(vx, vy);
238432
238769
  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;
238770
+ const fractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(-_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e00x, e00y), vv, 0.0);
238434
238771
  if (this.updatePointToSegmentDistance(0, a0, b0, b1, fractionB, maxDistanceSquared, closestApproach))
238435
238772
  reversed = false;
238436
238773
  }
238437
238774
  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;
238775
+ const fractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(-_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e10x, e10y), vv, 0.0);
238439
238776
  if (this.updatePointToSegmentDistance(1, a1, b0, b1, fractionB, maxDistanceSquared, closestApproach))
238440
238777
  reversed = false;
238441
238778
  }
@@ -238513,7 +238850,7 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
238513
238850
  return undefined;
238514
238851
  }
238515
238852
  /**
238516
- * Find the closest approach between `pointA` and `cpB`. Add the approach if it's within `fB0` and `fB1`.
238853
+ * Find the closest xy approach between `pointA` and `cpB`. Add the approach if it's within `fB0` and `fB1`.
238517
238854
  * * Does not test the endpoints of `cpB`.
238518
238855
  * * The only types supported for `cpB` are Arc3d, LineSegment3d, and LineString3d.
238519
238856
  * * If `cpB` is a LineString3d, then the interval `[fB0, fB1]` must correspond to a segment of the line string.
@@ -238538,7 +238875,7 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
238538
238875
  }
238539
238876
  }
238540
238877
  /**
238541
- * Compute intersection of two line segments.
238878
+ * Compute closest xy approach of two line segments.
238542
238879
  * Filter by extension rules.
238543
238880
  * Record with fraction mapping.
238544
238881
  * * The fraction mappings allow portions of a linestring to be passed here.
@@ -246814,7 +247151,7 @@ class AngleSweep {
246814
247151
  result.setStartEndRadians(startRadians, endRadians);
246815
247152
  return result;
246816
247153
  }
246817
- /** Return the angle obtained by subtracting radians from this angle. */
247154
+ /** Return the AngleSweep obtained by subtracting radians from the start and end angles of this sweep. */
246818
247155
  cloneMinusRadians(radians) {
246819
247156
  return new AngleSweep(this._radians0 - radians, this._radians1 - radians);
246820
247157
  }
@@ -248505,7 +248842,7 @@ __webpack_require__.r(__webpack_exports__);
248505
248842
  * For the equator circle, phi=0, cos(phi) = 1, sin(phi)=0
248506
248843
  * f = u * cos(theta) + v * sin(theta).
248507
248844
  * with derivative
248508
- * df / dTheta = = u * sin(theta) + v * cos(theta)
248845
+ * df / dTheta = - u * sin(theta) + v * cos(theta)
248509
248846
  * whose zero is tan(theta) = v/u
248510
248847
  * (and that has two solutions 180 degrees apart)
248511
248848
  * Then with that theta let A = u * cos(theta) + v * sin(theta)
@@ -253161,6 +253498,7 @@ class IndexedXYZCollection {
253161
253498
  * @param index0 index of first point
253162
253499
  * @param index1 index of second point
253163
253500
  * @param tolerance max coordinate difference to be considered equal. For exact test, pass 0. Defaults to `Geometry.smallMetricDistance`.
253501
+ * @returns whether the points are equal within tolerance, or `undefined` if either index is invalid.
253164
253502
  */
253165
253503
  almostEqualIndexIndex(index0, index1, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
253166
253504
  if (index0 < 0 || index0 >= this.length || index1 < 0 || index1 >= this.length)
@@ -253169,6 +253507,19 @@ class IndexedXYZCollection {
253169
253507
  && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getYAtUncheckedPointIndex(index0), this.getYAtUncheckedPointIndex(index1), tolerance)
253170
253508
  && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getZAtUncheckedPointIndex(index0), this.getZAtUncheckedPointIndex(index1), tolerance);
253171
253509
  }
253510
+ /**
253511
+ * Test whether the xy-coordinates of the indexed points are equal within tolerance. The z-coordinates are ignored.
253512
+ * @param index0 index of first point
253513
+ * @param index1 index of second point
253514
+ * @param tolerance max coordinate difference to be considered equal. For exact test, pass 0. Defaults to `Geometry.smallMetricDistance`.
253515
+ * @returns whether the xy-coordinates of the points are equal within tolerance, or `undefined` if either index is invalid.
253516
+ */
253517
+ almostEqualXYIndexIndex(index0, index1, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
253518
+ if (index0 < 0 || index0 >= this.length || index1 < 0 || index1 >= this.length)
253519
+ return undefined;
253520
+ return _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getXAtUncheckedPointIndex(index0), this.getXAtUncheckedPointIndex(index1), tolerance)
253521
+ && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getYAtUncheckedPointIndex(index0), this.getYAtUncheckedPointIndex(index1), tolerance);
253522
+ }
253172
253523
  }
253173
253524
  /**
253174
253525
  * abstract base class extends IndexedXYZCollection, adding methods to push, peek, and pop, and rewrite.
@@ -265707,13 +266058,11 @@ class Ray3d {
265707
266058
  return new Ray3d(_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.createZero(), _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.createZero());
265708
266059
  }
265709
266060
  /**
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.
266061
+ * Test for nearly equal Ray3d objects by comparing their origin and direction members.
266062
+ * @see [[isAlmostEqualPointSet]] to test for rays on the same infinite line.
265714
266063
  */
265715
- isAlmostEqual(other) {
265716
- return this.origin.isAlmostEqual(other.origin) && this.direction.isAlmostEqual(other.direction);
266064
+ isAlmostEqual(other, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
266065
+ return this.origin.isAlmostEqual(other.origin, tolerance) && this.direction.isAlmostEqual(other.direction, tolerance);
265717
266066
  }
265718
266067
  /**
265719
266068
  * Return the dot product of the ray's direction vector with a vector from the ray origin
@@ -265741,27 +266090,19 @@ class Ray3d {
265741
266090
  return this.origin.plusScaled(this.direction, this.pointToFraction(spacePoint));
265742
266091
  }
265743
266092
  /**
265744
- * Test for nearly equal rays, allowing origin float and direction scaling.
265745
- * * Use [[isAlmostEqual]] to require member-by-member comparison.
266093
+ * Test for rays that describe the same infinite line.
266094
+ * @see [[isAlmostEqual]] for member-by-member comparison.
265746
266095
  */
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))
266096
+ isAlmostEqualPointSet(other, options) {
266097
+ if (!this.direction.isParallelTo(other.direction, true, false, options))
265754
266098
  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
- */
266099
+ const tol2 = options?.distanceSquaredTol ?? _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistanceSquared;
266100
+ // theoretically, one test below is sufficient, but perform both in case the first passes because of round-off
265760
266101
  let workPoint = this.projectPointToRay(other.origin);
265761
- if (!other.origin.isAlmostEqualMetric(workPoint))
266102
+ if (other.origin.distanceSquared(workPoint) > tol2)
265762
266103
  return false;
265763
266104
  workPoint = other.projectPointToRay(this.origin);
265764
- if (!this.origin.isAlmostEqualMetric(workPoint))
266105
+ if (this.origin.distanceSquared(workPoint) > tol2)
265765
266106
  return false;
265766
266107
  return true;
265767
266108
  }
@@ -266456,19 +266797,25 @@ __webpack_require__.r(__webpack_exports__);
266456
266797
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
266457
266798
  /* harmony export */ SortablePolygon: () => (/* binding */ SortablePolygon)
266458
266799
  /* 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");
266800
+ /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
266801
+ /* harmony import */ var _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../curve/CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
266802
+ /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
266803
+ /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
266804
+ /* harmony import */ var _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../curve/ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
266805
+ /* harmony import */ var _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../curve/RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
266806
+ /* harmony import */ var _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../curve/UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
266807
+ /* harmony import */ var _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
266808
+ /* harmony import */ var _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
266809
+ /* harmony import */ var _PolygonOps__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
266810
+ /* harmony import */ var _Ray3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
266468
266811
  /*---------------------------------------------------------------------------------------------
266469
266812
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
266470
266813
  * See LICENSE.md in the project root for license terms and full copyright notice.
266471
266814
  *--------------------------------------------------------------------------------------------*/
266815
+ /** @packageDocumentation
266816
+ * @module CartesianGeometry
266817
+ */
266818
+
266472
266819
 
266473
266820
 
266474
266821
 
@@ -266478,14 +266825,37 @@ __webpack_require__.r(__webpack_exports__);
266478
266825
 
266479
266826
 
266480
266827
 
266481
- /** abstract base class for area-related queries of a loop.
266482
- * * subclasses have particular logic for `Loop` and polygon data.
266828
+
266829
+ /** Abstract base class for area-related queries of an xy-loop.
266830
+ * * Subclasses have particular logic for `Loop` and polygon data.
266483
266831
  * @internal
266484
266832
  */
266485
266833
  class SimpleRegionCarrier {
266834
+ /** Fractions for interior point search. */
266835
+ searchFractions = [0.2349, 0.4142, 0.6587, 0.8193];
266836
+ /**
266837
+ * Given a region boundary tangent, construct a point interior to the region.
266838
+ * @param ray point and tangent on an edge of the region (modified on return)
266839
+ */
266840
+ constructInteriorPoint(ray) {
266841
+ ray.direction.z = 0.0;
266842
+ if (!ray.direction.normalizeInPlace())
266843
+ return undefined; // loop has zero length edge, or a vertical (gap) edge
266844
+ ray.direction.rotate90CCWXY(ray.direction);
266845
+ if (this.signedArea < 0.0)
266846
+ ray.direction.scaleInPlace(-1.0); // aim toward the region interior
266847
+ const refDistance = Math.sqrt(Math.abs(this.signedArea));
266848
+ const candidatePoint = _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
266849
+ for (let fraction = 1.0e-5; fraction < 3; fraction *= 5.0) {
266850
+ ray.fractionToPoint(fraction * refDistance, candidatePoint);
266851
+ if (1 === this.classifyPointXY(candidatePoint))
266852
+ return candidatePoint;
266853
+ }
266854
+ return undefined;
266855
+ }
266486
266856
  }
266487
266857
  /**
266488
- * Implement `LoopCarrier` queries with the area as a polygon carried in an `IndexedReadWriteXYZCollection`
266858
+ * Implement `SimpleRegionCarrier` queries with the area as a polygon carried in an `IndexedReadWriteXYZCollection`.
266489
266859
  */
266490
266860
  class PolygonCarrier extends SimpleRegionCarrier {
266491
266861
  data;
@@ -266494,7 +266864,7 @@ class PolygonCarrier extends SimpleRegionCarrier {
266494
266864
  constructor(data) {
266495
266865
  super();
266496
266866
  this.data = data;
266497
- this._signedArea = _PolygonOps__WEBPACK_IMPORTED_MODULE_0__.PolygonOps.areaXY(data);
266867
+ this._signedArea = _PolygonOps__WEBPACK_IMPORTED_MODULE_1__.PolygonOps.areaXY(data);
266498
266868
  }
266499
266869
  /**
266500
266870
  * classify xy parts of point wrt this loop.
@@ -266502,22 +266872,22 @@ class PolygonCarrier extends SimpleRegionCarrier {
266502
266872
  * @internal
266503
266873
  */
266504
266874
  classifyPointXY(xy) {
266505
- return _PolygonOps__WEBPACK_IMPORTED_MODULE_0__.PolygonOps.classifyPointInPolygonXY(xy.x, xy.y, this.data);
266875
+ return _PolygonOps__WEBPACK_IMPORTED_MODULE_1__.PolygonOps.classifyPointInPolygonXY(xy.x, xy.y, this.data);
266506
266876
  }
266507
- /** Return some point "inside"
266508
- * NEEDS WORK: this returns a point ON --
266509
- */
266877
+ /** Return some point "inside". */
266510
266878
  getAnyInteriorPoint() {
266511
266879
  for (let childIndex = 0; childIndex < this.data.length; childIndex++) {
266512
- const q = this.constructInteriorPointNearEdge(childIndex, 0.2349);
266513
- if (q !== undefined)
266514
- return q;
266880
+ for (const fraction of this.searchFractions) {
266881
+ const q = this.constructInteriorPointNearEdge(childIndex, fraction);
266882
+ if (q !== undefined)
266883
+ return q;
266884
+ }
266515
266885
  }
266516
266886
  return undefined;
266517
266887
  }
266518
266888
  grabPolygon() { return this.data; }
266519
266889
  grabLoop() {
266520
- return _curve_Loop__WEBPACK_IMPORTED_MODULE_1__.Loop.createPolygon(this.data);
266890
+ return _curve_Loop__WEBPACK_IMPORTED_MODULE_2__.Loop.createPolygon(this.data);
266521
266891
  }
266522
266892
  reverseForAreaSign(targetSign) {
266523
266893
  if (targetSign * this._signedArea < 0.0) {
@@ -266527,27 +266897,14 @@ class PolygonCarrier extends SimpleRegionCarrier {
266527
266897
  }
266528
266898
  constructInteriorPointNearEdge(edgeIndex, fractionAlong) {
266529
266899
  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
- }
266900
+ const ray = _Ray3d__WEBPACK_IMPORTED_MODULE_3__.Ray3d.createCapture(this.data.interpolateIndexIndex(edgeIndex, fractionAlong, edgeIndex + 1), this.data.vectorIndexIndex(edgeIndex, edgeIndex + 1));
266901
+ return this.constructInteriorPoint(ray);
266545
266902
  }
266546
266903
  return undefined;
266547
266904
  }
266548
266905
  }
266549
266906
  /**
266550
- * Implement `LoopCarrier` queries with the area as a strongly typed `Loop`
266907
+ * Implement `SimpleRegionCarrier` queries with the area as a strongly typed `Loop`.
266551
266908
  */
266552
266909
  class LoopCarrier extends SimpleRegionCarrier {
266553
266910
  data;
@@ -266556,7 +266913,7 @@ class LoopCarrier extends SimpleRegionCarrier {
266556
266913
  constructor(data) {
266557
266914
  super();
266558
266915
  this.data = data;
266559
- const areaMoments = _curve_RegionOps__WEBPACK_IMPORTED_MODULE_2__.RegionOps.computeXYAreaMoments(data);
266916
+ const areaMoments = _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.computeXYAreaMoments(data);
266560
266917
  this._signedArea = areaMoments !== undefined ? areaMoments.quantitySum : 0.0;
266561
266918
  }
266562
266919
  /**
@@ -266565,41 +266922,32 @@ class LoopCarrier extends SimpleRegionCarrier {
266565
266922
  * @internal
266566
266923
  */
266567
266924
  classifyPointXY(xy) {
266568
- return _curve_RegionOps__WEBPACK_IMPORTED_MODULE_2__.RegionOps.testPointInOnOutRegionXY(this.data, xy.x, xy.y);
266925
+ return _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.testPointInOnOutRegionXY(this.data, xy.x, xy.y);
266569
266926
  }
266570
266927
  constructInteriorPointNearChild(childIndex, fractionAlong) {
266571
266928
  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
- }
266929
+ const ray = this.data.children[childIndex].fractionToPointAndDerivative(fractionAlong);
266930
+ return this.constructInteriorPoint(ray);
266583
266931
  }
266584
266932
  return undefined;
266585
266933
  }
266586
- /** Return some point "inside"
266587
- * NEEDS WORK: this returns a point ON --
266588
- */
266934
+ /** Return some point "inside". */
266589
266935
  getAnyInteriorPoint() {
266590
266936
  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;
266937
+ for (const fraction of this.searchFractions) {
266938
+ const q = this.constructInteriorPointNearChild(childIndex, fraction);
266939
+ if (q !== undefined)
266940
+ return q;
266941
+ }
266594
266942
  }
266595
266943
  return undefined;
266596
266944
  }
266597
266945
  grabPolygon() {
266598
266946
  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();
266947
+ if (strokes instanceof _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
266948
+ const linestring = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_6__.LineString3d.create();
266601
266949
  for (const child of strokes.children) {
266602
- if (child instanceof _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_5__.CurvePrimitive) {
266950
+ if (child instanceof _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_7__.CurvePrimitive) {
266603
266951
  child.emitStrokes(linestring);
266604
266952
  }
266605
266953
  }
@@ -266618,7 +266966,7 @@ class LoopCarrier extends SimpleRegionCarrier {
266618
266966
  }
266619
266967
  }
266620
266968
  /**
266621
- * A `SortablePolygon` carries a (single) loop with data useful for sorting for inner-outer structure.
266969
+ * A `SortablePolygon` carries a (single) xy-loop with data useful for sorting for inner-outer structure.
266622
266970
  * @internal
266623
266971
  */
266624
266972
  class SortablePolygon {
@@ -266634,7 +266982,7 @@ class SortablePolygon {
266634
266982
  * @param loop Loop to capture.
266635
266983
  */
266636
266984
  constructor(loop, range) {
266637
- if (loop instanceof _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_6__.IndexedReadWriteXYZCollection)
266985
+ if (loop instanceof _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_8__.IndexedReadWriteXYZCollection)
266638
266986
  this._loopCarrier = new PolygonCarrier(loop);
266639
266987
  else
266640
266988
  this._loopCarrier = new LoopCarrier(loop);
@@ -266739,7 +267087,7 @@ class SortablePolygon {
266739
267087
  const childData = loops[childIndex];
266740
267088
  if (childData.parentIndex === candidateIndex) {
266741
267089
  if (candidateParityRegion === undefined) {
266742
- candidateParityRegion = _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_7__.ParityRegion.create();
267090
+ candidateParityRegion = _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_9__.ParityRegion.create();
266743
267091
  candidateParityRegion.tryAddChild(candidateLoop);
266744
267092
  childData._loopCarrier.reverseForAreaSign(-1.0);
266745
267093
  candidateParityRegion.tryAddChild(childData._loopCarrier.grabLoop());
@@ -266764,7 +267112,7 @@ class SortablePolygon {
266764
267112
  if (regions.length === 1)
266765
267113
  return regions[0];
266766
267114
  else {
266767
- const unionRegion = _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_8__.UnionRegion.create();
267115
+ const unionRegion = _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_10__.UnionRegion.create();
266768
267116
  for (const region of regions)
266769
267117
  unionRegion.tryAddChild(region);
266770
267118
  return unionRegion;
@@ -280449,7 +280797,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
280449
280797
  /** Construct facets for a rotational sweep. */
280450
280798
  addRotationalSweep(surface) {
280451
280799
  const contour = surface.getSweepContourRef();
280452
- const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour.getCurves(), this._options);
280800
+ const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour.getCurves(), this._options);
280453
280801
  const baseStrokes = section0.getStrokes();
280454
280802
  // ensure sweep is positive for buildRotationalNormalsInLineStrings
280455
280803
  const axis = surface.cloneAxisRay();
@@ -280599,7 +280947,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
280599
280947
  /** Add facets from the linear sweep. */
280600
280948
  addLinearSweep(surface) {
280601
280949
  const contour = surface.getCurvesRef();
280602
- const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour, this._options);
280950
+ const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour, this._options);
280603
280951
  const stroke0 = section0.getStrokes();
280604
280952
  const sweepVector = surface.cloneSweepVector();
280605
280953
  const sweepTransform = _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_9__.Transform.createTranslation(sweepVector);
@@ -280621,7 +280969,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
280621
280969
  let stroke1;
280622
280970
  const sectionMaps = [];
280623
280971
  for (const contour of contours)
280624
- sectionMaps.push(_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour.curves, this._options));
280972
+ sectionMaps.push(_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour.curves, this._options));
280625
280973
  if (_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.enforceStrokeCountCompatibility(sectionMaps)) {
280626
280974
  _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.enforceCompatibleDistanceSums(sectionMaps);
280627
280975
  for (let i = 0; i < contours.length; i++) {
@@ -302156,7 +302504,7 @@ class Sphere extends _SolidPrimitive__WEBPACK_IMPORTED_MODULE_0__.SolidPrimitive
302156
302504
  const sinTheta = Math.sin(thetaRadians);
302157
302505
  const sinPhi = Math.sin(phiRadians);
302158
302506
  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.
302507
+ 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
302508
  this._localToWorld.matrix.multiplyXYZ(-fPhi * cosTheta * sinPhi, -fPhi * sinTheta * sinPhi, fPhi * cosPhi), result);
302161
302509
  }
302162
302510
  /**
@@ -302411,7 +302759,7 @@ class SweepContour {
302411
302759
  /**
302412
302760
  * Emit facets to a function.
302413
302761
  * This method may cache and reuse facets over multiple calls.
302414
- * @param announce callback to receive the facet set.
302762
+ * @param announce callback to receive the facet set. Called only once (if facets exist).
302415
302763
  * @param options how to stroke the contour.
302416
302764
  */
302417
302765
  announceFacets(announce, options) {
@@ -303177,13 +303525,14 @@ __webpack_require__.r(__webpack_exports__);
303177
303525
  /* harmony export */ HalfEdgeGraph: () => (/* binding */ HalfEdgeGraph),
303178
303526
  /* harmony export */ HalfEdgeMask: () => (/* binding */ HalfEdgeMask)
303179
303527
  /* 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");
303528
+ /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
303529
+ /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
303530
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
303531
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
303532
+ /* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
303533
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
303534
+ /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
303535
+ /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
303187
303536
  /*---------------------------------------------------------------------------------------------
303188
303537
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
303189
303538
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -303198,9 +303547,9 @@ __webpack_require__.r(__webpack_exports__);
303198
303547
 
303199
303548
 
303200
303549
 
303550
+
303201
303551
  // import { GraphChecker } from "../test/topology/Graph.test"; // used for debugging
303202
303552
  /* eslint-disable @typescript-eslint/no-this-alias */
303203
- // cspell:word CONSTU CONSTV USEAM VSEAM internaldocs
303204
303553
  /**
303205
303554
  * * Each node of the graph has a mask member.
303206
303555
  * * The mask member is a number which is used as set of single bit boolean values.
@@ -303215,14 +303564,6 @@ __webpack_require__.r(__webpack_exports__);
303215
303564
  */
303216
303565
  var HalfEdgeMask;
303217
303566
  (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
303567
  /**
303227
303568
  * Mask commonly set consistently around exterior faces.
303228
303569
  * * A boundary edge with interior to one side, exterior to the other, will have EXTERIOR only on the outside.
@@ -303245,22 +303586,22 @@ var HalfEdgeMask;
303245
303586
  * BOUNDARY_EDGE nor EXTERIOR_EDGE.
303246
303587
  */
303247
303588
  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";
303589
+ /** Mask set on both sides of a bridge edge added by algorithms to join loops. */
303590
+ HalfEdgeMask[HalfEdgeMask["BRIDGE_EDGE"] = 8] = "BRIDGE_EDGE";
303591
+ /** Mask set on both sides of an edge added during graph regularization. */
303592
+ HalfEdgeMask[HalfEdgeMask["REGULARIZED_EDGE"] = 16] = "REGULARIZED_EDGE";
303250
303593
  /** Mask applied to triangles by earcut triangulator. */
303251
303594
  HalfEdgeMask[HalfEdgeMask["TRIANGULATED_FACE"] = 256] = "TRIANGULATED_FACE";
303252
303595
  /** Mask applied in a face with 2 edges. */
303253
303596
  HalfEdgeMask[HalfEdgeMask["NULL_FACE"] = 512] = "NULL_FACE";
303597
+ /** Temporary mask used for low level searches to identify previously-visited nodes. */
303598
+ HalfEdgeMask[HalfEdgeMask["VISITED"] = 65536] = "VISITED";
303254
303599
  /** No mask bits. */
303255
303600
  HalfEdgeMask[HalfEdgeMask["NULL_MASK"] = 0] = "NULL_MASK";
303256
303601
  /** The "upper 12" bits of 32 bit integer reserved for grab/drop. */
303257
303602
  HalfEdgeMask[HalfEdgeMask["ALL_GRAB_DROP_MASKS"] = 4293918720] = "ALL_GRAB_DROP_MASKS";
303258
303603
  /** All mask bits */
303259
303604
  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
303605
  })(HalfEdgeMask || (HalfEdgeMask = {}));
303265
303606
  /**
303266
303607
  * A HalfEdge is "one side of an edge" in a structure of faces, edges and vertices. From a node there are
@@ -303456,6 +303797,37 @@ class HalfEdge {
303456
303797
  }
303457
303798
  return newA;
303458
303799
  }
303800
+ /**
303801
+ * Reverse of [[splitEdge]]: remove the vertex at `doomed` and merge its two incident edges.
303802
+ * @param doomed one of two nodes added by [[splitEdge]]. These nodes should form a vertex loop of two nodes.
303803
+ * On successful return this node and its mate are isolated.
303804
+ * @param checkParallel whether to check that the doomed edge and the preceding edge in its face loop are parallel.
303805
+ * When passing `true` the assumption is that edge geometry is linear. If nonlinear edge geometry is attached, the
303806
+ * caller should a) verify that the geometry on either side of the doomed vertex can be merged, and if so, they
303807
+ * should b) call this method passing `false`, and c) adjust the geometry of the returned edge and its edge mate
303808
+ * as appropriate.
303809
+ * @returns the former (surviving) face predecessor of `doomed`, or undefined if the edge can't be healed.
303810
+ */
303811
+ static healEdge(doomed, checkParallel = true) {
303812
+ if (doomed.isIsolatedEdge)
303813
+ return undefined;
303814
+ const doomed1 = doomed.vertexSuccessor;
303815
+ if (doomed1.vertexSuccessor !== doomed)
303816
+ return undefined; // v-loop not a 2-cycle
303817
+ if (checkParallel && !doomed.vectorToFaceSuccessor().isParallelTo(doomed.facePredecessor.vectorToFaceSuccessor(), false, true))
303818
+ return undefined; // removing this vertex does not leave a straight edge behind
303819
+ const fPred = doomed.facePredecessor;
303820
+ const fSucc = doomed.faceSuccessor;
303821
+ const fPred1 = doomed1.facePredecessor;
303822
+ const fSucc1 = doomed1.faceSuccessor;
303823
+ this.setFaceLinks(fPred, fSucc);
303824
+ this.setFaceLinks(fPred1, fSucc1);
303825
+ this.setEdgeMates(fPred, fPred1);
303826
+ this.setFaceLinks(doomed, doomed1);
303827
+ this.setFaceLinks(doomed1, doomed);
303828
+ this.setEdgeMates(doomed, doomed1);
303829
+ return fPred;
303830
+ }
303459
303831
  /**
303460
303832
  * Create a new sliver face "inside" an existing edge.
303461
303833
  * * This creates two nodes that are each face predecessor and successor to the other.
@@ -303483,14 +303855,14 @@ class HalfEdge {
303483
303855
  newB.copyDataFrom(baseB, true, true, false, false);
303484
303856
  return newA;
303485
303857
  }
303486
- /** Edge property masks. */
303858
+ /** Masks copied when an edge is split. */
303487
303859
  static _edgePropertyMasks = [
303488
- HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.NULL_FACE,
303860
+ HalfEdgeMask.EXTERIOR, HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.BRIDGE_EDGE, HalfEdgeMask.REGULARIZED_EDGE, HalfEdgeMask.NULL_FACE
303489
303861
  ];
303490
303862
  /**
303491
303863
  * Copy "edge based" content of `fromNode` to `toNode`:
303492
303864
  * * edgeTag
303493
- * * masks EXTERIOR, BOUNDARY_EDGE, NULL_FACE, PRIMARY_EDGE
303865
+ * * edge masks
303494
303866
  */
303495
303867
  static transferEdgeProperties(fromNode, toNode) {
303496
303868
  toNode.edgeTag = fromNode.edgeTag;
@@ -303663,7 +304035,7 @@ class HalfEdge {
303663
304035
  /**
303664
304036
  * Returns the number of nodes that match (or do not match) the given mask value around this face loop.
303665
304037
  * @param mask the mask to check.
303666
- * @param value true for mask match and false for mask not match.
304038
+ * @param value true for mask match and false for mask not match. Default is `true`.
303667
304039
  */
303668
304040
  countMaskAroundFace(mask, value = true) {
303669
304041
  let count = 0;
@@ -303710,16 +304082,17 @@ class HalfEdge {
303710
304082
  }
303711
304083
  /**
303712
304084
  * 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.
304085
+ * with the instance node and proceeding via `vertexSuccessor`.
303714
304086
  * @param mask the mask to check.
303715
- * @param value true for mask match and false for mask not match.
304087
+ * @param value true for mask match and false for mask not match. Default is `true`.
304088
+ * @param reverse if true, search in reverse order via `vertexPredecessor`. Default is `false`.
303716
304089
  */
303717
- findMaskAroundVertex(mask, value = true) {
304090
+ findMaskAroundVertex(mask, value = true, reverse = false) {
303718
304091
  let node = this;
303719
304092
  do {
303720
304093
  if (node.isMaskSet(mask) === value)
303721
304094
  return node;
303722
- node = node.vertexSuccessor;
304095
+ node = reverse ? node.vertexPredecessor : node.vertexSuccessor;
303723
304096
  } while (node !== this);
303724
304097
  return undefined;
303725
304098
  }
@@ -303727,7 +304100,7 @@ class HalfEdge {
303727
304100
  * Returns the first node that matches (or does not match) the given mask value around this face loop, starting
303728
304101
  * with the instance node and proceeding via face successors.
303729
304102
  * @param mask the mask to check.
303730
- * @param value true for mask match and false for mask not match.
304103
+ * @param value true for mask match and false for mask not match. Default is `true`.
303731
304104
  */
303732
304105
  findMaskAroundFace(mask, value = true) {
303733
304106
  let node = this;
@@ -303839,6 +304212,10 @@ class HalfEdge {
303839
304212
  predA._faceSuccessor = nodeB;
303840
304213
  }
303841
304214
  }
304215
+ /** Return whether the edge is dangling at its base. */
304216
+ get isDangling() {
304217
+ return this.edgeMate.faceSuccessor === this;
304218
+ }
303842
304219
  /**
303843
304220
  * Pinch this half edge out of its base vertex loop.
303844
304221
  * @return the surviving HalfEdge in the vertex loop or `undefined` if the instance HalfEdge is already dangling.
@@ -303908,17 +304285,17 @@ class HalfEdge {
303908
304285
  }
303909
304286
  /** Return Vector2d from `this` to face successor (with only xy coordinates). */
303910
304287
  vectorToFaceSuccessorXY(result) {
303911
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create(this.faceSuccessor.x - this.x, this.faceSuccessor.y - this.y, result);
304288
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create(this.faceSuccessor.x - this.x, this.faceSuccessor.y - this.y, result);
303912
304289
  }
303913
304290
  /** Return Vector3d from `this` to face successor. */
303914
304291
  vectorToFaceSuccessor(result) {
303915
304292
  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);
304293
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
303917
304294
  }
303918
304295
  /** Return Vector3d from `this` to face successor. */
303919
304296
  vectorToFacePredecessor(result) {
303920
304297
  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);
304298
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
303922
304299
  }
303923
304300
  /**
303924
304301
  * Test if `spaceNode` is in the sector of `sectorNode`.
@@ -303969,15 +304346,15 @@ class HalfEdge {
303969
304346
  }
303970
304347
  /** Returns 2D cross product of vectors from `base` to `targetA` and from `base` to `targetB`. */
303971
304348
  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);
304349
+ 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
304350
  }
303974
304351
  /** Returns 2D dot product of vectors from `baseA` to `targetA` and from `baseB` to `targetB`. */
303975
304352
  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);
304353
+ 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
304354
  }
303978
304355
  /** Return 2D cross product of vectors from `nodeA` to `nodeB` and from `nodeB` to `nodeC`. */
303979
304356
  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);
304357
+ 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
304358
  }
303982
304359
  /**
303983
304360
  * Compute whether the sector defined by the chain of nodes is convex.
@@ -304014,7 +304391,7 @@ class HalfEdge {
304014
304391
  */
304015
304392
  isSectorConvex(signedAreaTol) {
304016
304393
  if (signedAreaTol === undefined)
304017
- signedAreaTol = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistanceSquared * this.signedFaceArea();
304394
+ signedAreaTol = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistanceSquared * this.signedFaceArea();
304018
304395
  return HalfEdge.isSectorConvex(this.facePredecessor, this, this.faceSuccessor, signedAreaTol);
304019
304396
  }
304020
304397
  /**
@@ -304026,7 +304403,7 @@ class HalfEdge {
304026
304403
  * `Geometry.smallMetricDistanceSquared`. Pass 0 to skip toleranced computation.
304027
304404
  * @returns true iff this face is convex.
304028
304405
  */
304029
- isFaceConvex(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistanceSquared) {
304406
+ isFaceConvex(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistanceSquared) {
304030
304407
  let node = this;
304031
304408
  const signedAreaTol = tolerance > 0.0 ? tolerance * node.signedFaceArea() : 0.0;
304032
304409
  do {
@@ -304042,7 +304419,10 @@ class HalfEdge {
304042
304419
  this.yankFromVertexLoop();
304043
304420
  mate.yankFromVertexLoop();
304044
304421
  }
304045
- /** Specify whether this edge is isolated from the rest of the graph. */
304422
+ /**
304423
+ * Specify whether this edge is isolated from the rest of the graph.
304424
+ * * Both edge mates of an isolated edge return true for [[isDangling]].
304425
+ */
304046
304426
  get isIsolatedEdge() {
304047
304427
  return this === this.vertexSuccessor && this.edgeMate === this.edgeMate.vertexSuccessor;
304048
304428
  }
@@ -304072,7 +304452,7 @@ class HalfEdge {
304072
304452
  static sectorSweepRadiansXYZ(node, normal) {
304073
304453
  const suc = node.faceSuccessor;
304074
304454
  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);
304455
+ 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
304456
  }
304077
304457
  /** Returns true if the face has positive area in xy parts. */
304078
304458
  static testFacePositiveAreaXY(node) {
@@ -304084,11 +304464,76 @@ class HalfEdge {
304084
304464
  }
304085
304465
  /** Return distance between xy coordinates of `this` and `other` node. */
304086
304466
  distanceXY(other) {
304087
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.distanceXYXY(this.x, this.y, other.x, other.y);
304467
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.distanceXYXY(this.x, this.y, other.x, other.y);
304088
304468
  }
304089
304469
  /** Return distance between xyz coordinates of `this` and `other` node. */
304090
304470
  distanceXYZ(other) {
304091
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.distanceXYZXYZ(this.x, this.y, this.z, other.x, other.y, other.z);
304471
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.distanceXYZXYZ(this.x, this.y, this.z, other.x, other.y, other.z);
304472
+ }
304473
+ /**
304474
+ * Search around the instance's face loop for nodes with the specified mask value.
304475
+ * * Returned nodes satisfy `node.isMaskSet(mask) === value`.
304476
+ * @param mask target mask.
304477
+ * @param value target boolean value for mask on half edges (default `true`).
304478
+ * @param result optional array to be cleared, populated with masked nodes, and returned.
304479
+ * @return array of masked half edges
304480
+ */
304481
+ collectMaskedEdgesAroundFace(mask, value = true, result) {
304482
+ if (result === undefined)
304483
+ result = [];
304484
+ else
304485
+ result.length = 0;
304486
+ let node = this;
304487
+ do {
304488
+ if (node.isMaskSet(mask) === value)
304489
+ result.push(node);
304490
+ node = node.faceSuccessor;
304491
+ } while (node !== this);
304492
+ return result;
304493
+ }
304494
+ /**
304495
+ * Announce edges in the face loop, starting with the instance and proceeding in a `faceSuccessor` traversal.
304496
+ * @param announceEdge function to call at each edge
304497
+ */
304498
+ announceEdgesInFace(announceEdge) {
304499
+ let node = this;
304500
+ do {
304501
+ announceEdge(node);
304502
+ node = node.faceSuccessor;
304503
+ } while (node !== this);
304504
+ }
304505
+ /**
304506
+ * Announce edges in the super face loop, starting with the instance.
304507
+ * * 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.
304508
+ * @param skipMask mask on edges to skip.
304509
+ * @param announceEdge function to call at each edge that is not skipped.
304510
+ * @param announceSkipped optional function to call at each edge that is skipped.
304511
+ * @return whether a super face was found. Specifically, if a vertex loop has all edges with `skipMask` set, the return value is `false`.
304512
+ */
304513
+ announceEdgesInSuperFace(skipMask, announceEdge, announceSkipped) {
304514
+ const maxIter = 1000; // safeguard against infinite loops
304515
+ let iter = 0;
304516
+ const findNextNodeAroundVertex = (he) => {
304517
+ let vNode = he;
304518
+ do {
304519
+ if (!vNode.isMaskSet(skipMask))
304520
+ return vNode;
304521
+ announceSkipped?.(vNode);
304522
+ vNode = vNode.vertexPredecessor;
304523
+ } while (vNode !== he);
304524
+ return undefined;
304525
+ };
304526
+ const firstNode = findNextNodeAroundVertex(this);
304527
+ if (!firstNode)
304528
+ return false;
304529
+ let node = firstNode;
304530
+ do {
304531
+ announceEdge(node);
304532
+ node = findNextNodeAroundVertex(node.faceSuccessor);
304533
+ if (!node)
304534
+ return false;
304535
+ } while (node !== firstNode && iter++ < maxIter);
304536
+ return iter < maxIter;
304092
304537
  }
304093
304538
  /**
304094
304539
  * Evaluate `f(node)` at each node around `this` node's face loop. Collect the function values.
@@ -304229,7 +304674,7 @@ class HalfEdge {
304229
304674
  */
304230
304675
  fractionToPoint2d(fraction, result) {
304231
304676
  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);
304677
+ 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
304678
  }
304234
304679
  /**
304235
304680
  * Interpolate xyz coordinates between `this` node and its face successor.
@@ -304238,7 +304683,7 @@ class HalfEdge {
304238
304683
  */
304239
304684
  fractionToPoint3d(fraction, result) {
304240
304685
  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);
304686
+ 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
304687
  }
304243
304688
  /**
304244
304689
  * Interpolate xy coordinates at `fractionAlong` between this node and its face successor. Then shift perpendicular
@@ -304251,25 +304696,25 @@ class HalfEdge {
304251
304696
  const suc = this.faceSuccessor;
304252
304697
  const dx = suc.x - this.x;
304253
304698
  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);
304699
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(this.x + dx * fractionAlong - dy * fractionPerpendicular, this.y + dy * fractionAlong + dx * fractionPerpendicular, result);
304255
304700
  }
304256
304701
  /** Return the 3d coordinates at this half edge. */
304257
304702
  getPoint3d(result) {
304258
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(this.x, this.y, this.z, result);
304703
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Point3d.create(this.x, this.y, this.z, result);
304259
304704
  }
304260
304705
  /** Return the 2d coordinates at this half edge. */
304261
304706
  getPoint2d(result) {
304262
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Point2d.create(this.x, this.y, result);
304707
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(this.x, this.y, result);
304263
304708
  }
304264
304709
  /** Return a 3d vector from start to end of this half edge. */
304265
304710
  getVector3dAlongEdge(result) {
304266
304711
  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);
304712
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(suc.x - this.x, suc.y - this.y, suc.z - this.z, result);
304268
304713
  }
304269
304714
  /** Return a 2d vector from start to end of this half edge. */
304270
304715
  getVector2dAlongEdge(result) {
304271
304716
  const suc = this.faceSuccessor;
304272
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create(suc.x - this.x, suc.y - this.y, result);
304717
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create(suc.x - this.x, suc.y - this.y, result);
304273
304718
  }
304274
304719
  /**
304275
304720
  * Return the interpolated x coordinate between `this` node and its face successor.
@@ -304307,12 +304752,12 @@ class HalfEdge {
304307
304752
  const nodeA1 = nodeA0.faceSuccessor;
304308
304753
  const nodeB1 = nodeB0.faceSuccessor;
304309
304754
  if (!result)
304310
- result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create();
304755
+ result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create();
304311
304756
  // To find the fraction of intersection (ta,tb), you need to solve these 2 equations:
304312
304757
  // (nodeA1.x - nodeA0.x)ta + (nodeB0.x - nodeB1.x)tb = nodeB0.x - nodeA0.x
304313
304758
  // (nodeA1.y - nodeA0.y)ta + (nodeB0.y - nodeB1.y)tb = nodeB0.y - nodeA0.y
304314
304759
  // 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))
304760
+ 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
304761
  return result;
304317
304762
  return undefined;
304318
304763
  }
@@ -304326,13 +304771,13 @@ class HalfEdge {
304326
304771
  static horizontalScanFraction(node0, y) {
304327
304772
  const node1 = node0.faceSuccessor;
304328
304773
  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))
304774
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node1.y))
304330
304775
  return node0;
304331
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(dy, 0.0))
304776
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(dy, 0.0))
304332
304777
  return undefined;
304333
304778
  // parametric equation of line is (1-t)y0 + ty1 which is equal to y at the intersection so
304334
304779
  // (1-t)y0 + ty1 = y or t = (y-y0)/(y1-y0)
304335
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.conditionalDivideFraction(y - node0.y, dy);
304780
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.conditionalDivideFraction(y - node0.y, dy);
304336
304781
  }
304337
304782
  /**
304338
304783
  * Compute fractional position (inside 0..1) of the intersection of a horizontal line with an edge.
@@ -304344,11 +304789,11 @@ class HalfEdge {
304344
304789
  static horizontalScanFraction01(node0, y) {
304345
304790
  const node1 = node0.faceSuccessor;
304346
304791
  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))
304792
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node1.y))
304348
304793
  return undefined;
304349
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(dy, 0.0))
304794
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(dy, 0.0))
304350
304795
  return undefined;
304351
- const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.conditionalDivideFraction(y - node0.y, dy);
304796
+ const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.conditionalDivideFraction(y - node0.y, dy);
304352
304797
  if (fraction !== undefined && fraction >= 0.0 && fraction <= 1.0)
304353
304798
  return fraction;
304354
304799
  return undefined;
@@ -304367,16 +304812,37 @@ class HalfEdge {
304367
304812
  this.y = source.y;
304368
304813
  this.z = source.z;
304369
304814
  }
304370
- if (copyVertexData) {
304815
+ if (copyVertexData)
304371
304816
  this.i = source.i;
304372
- }
304373
- if (copyEdgeData) {
304817
+ if (copyEdgeData)
304374
304818
  HalfEdge.transferEdgeProperties(source, this);
304375
- this.edgeTag = source.edgeTag;
304376
- }
304377
- if (copyFaceData) {
304819
+ if (copyFaceData)
304378
304820
  this.faceTag = source.faceTag;
304821
+ }
304822
+ /**
304823
+ * Is the instance's face loop a split-washer type face?
304824
+ * * A split-washer face contains at least one bridge edge.
304825
+ * * A bridge edge and its edge mate have the same `bridgeMask` and live in the same face loop.
304826
+ * * By connecting hole/outer loops with bridge edges, a split-washer face can represent a parity region.
304827
+ * @param bridgeMask mask preset on bridge edges (default is [[HalfEdgeMask.BRIDGE_EDGE]]).
304828
+ */
304829
+ isSplitWasherFace(bridgeMask = HalfEdgeMask.BRIDGE_EDGE) {
304830
+ if (!this.countMaskAroundFace(HalfEdgeMask.BRIDGE_EDGE))
304831
+ return false;
304832
+ const bridges = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.OrderedSet((a, b) => a.id - b.id);
304833
+ let node = this;
304834
+ do {
304835
+ if (node.isMaskSet(bridgeMask))
304836
+ bridges.add(node);
304837
+ node = node.faceSuccessor;
304838
+ } while (node !== this);
304839
+ if (bridges.size === 0)
304840
+ return false;
304841
+ for (const bridge of bridges) {
304842
+ if (!bridges.has(bridge.edgeMate) || !bridge.edgeMate.isMaskSet(bridgeMask))
304843
+ return false;
304379
304844
  }
304845
+ return true;
304380
304846
  }
304381
304847
  }
304382
304848
  /**
@@ -304392,11 +304858,11 @@ class HalfEdgeGraph {
304392
304858
  _numNodesCreated = 0;
304393
304859
  constructor() {
304394
304860
  this.allHalfEdges = [];
304395
- this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_5__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
304861
+ this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_6__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
304396
304862
  }
304397
304863
  /**
304398
304864
  * Ask for a mask (from the graph's free pool) for caller's use.
304399
- * * Optionally clear the mask throughout the graph.
304865
+ * @param clearInAllHalfEdges optionally clear the mask throughout the graph (default `true`).
304400
304866
  */
304401
304867
  grabMask(clearInAllHalfEdges = true) {
304402
304868
  const mask = this._maskManager.grabMask();
@@ -304562,7 +305028,7 @@ class HalfEdgeGraph {
304562
305028
  const segments = [];
304563
305029
  for (const node of this.allHalfEdges) {
304564
305030
  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)));
305031
+ 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
305032
  }
304567
305033
  return segments;
304568
305034
  }
@@ -305050,8 +305516,8 @@ class HalfEdgeGraphSearch {
305050
305516
  * pattern starting at the seed face, with each successive concentric ring of faces at constant topological
305051
305517
  * distance from the seed face receiving the opposite parity state of the previous ring.
305052
305518
  * @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.
305519
+ * first face, as determined by the parity rule. If this is `NULL_MASK` (default), there is no record of parity.
305520
+ * If (non-null) parity mask is given, on return it is entirely set or entirely clear around each face.
305055
305521
  * @returns the components of the graph, each component represented by an array of nodes, one node per face
305056
305522
  * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.
305057
305523
  */
@@ -307809,8 +308275,9 @@ class RegularizationContext {
307809
308275
  if (nodeA1 !== undefined && nodeB1 !== undefined) {
307810
308276
  _Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(nodeA1, nodeC);
307811
308277
  _Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(nodeB1, nodeC.edgeMate);
308278
+ nodeC.setMaskAroundEdge(_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.REGULARIZED_EDGE);
307812
308279
  if (RegularizationContext.announceEdge)
307813
- RegularizationContext.announceEdge(this.graph, nodeA, nodeB, direction);
308280
+ RegularizationContext.announceEdge(this.graph, nodeC, nodeC.edgeMate, direction);
307814
308281
  return nodeC;
307815
308282
  }
307816
308283
  return undefined;
@@ -331034,18 +331501,18 @@ class Settings {
331034
331501
  }
331035
331502
  }
331036
331503
  toString() {
331037
- return `Configurations:
331038
- backend location: ${this.Backend.location},
331039
- backend name: ${this.Backend.name},
331040
- backend version: ${this.Backend.version},
331041
- oidc client id: ${this.oidcClientId},
331042
- oidc scopes: ${this.oidcScopes},
331043
- applicationId: ${this.gprid},
331044
- log level: ${this.logLevel},
331045
- testing iModelTileRpcTests: ${this.runiModelTileRpcTests},
331046
- testing PresentationRpcTest: ${this.runPresentationRpcTests},
331047
- testing iModelReadRpcTests: ${this.runiModelReadRpcTests},
331048
- testing DevToolsRpcTests: ${this.runDevToolsRpcTests},
331504
+ return `Configurations:
331505
+ backend location: ${this.Backend.location},
331506
+ backend name: ${this.Backend.name},
331507
+ backend version: ${this.Backend.version},
331508
+ oidc client id: ${this.oidcClientId},
331509
+ oidc scopes: ${this.oidcScopes},
331510
+ applicationId: ${this.gprid},
331511
+ log level: ${this.logLevel},
331512
+ testing iModelTileRpcTests: ${this.runiModelTileRpcTests},
331513
+ testing PresentationRpcTest: ${this.runPresentationRpcTests},
331514
+ testing iModelReadRpcTests: ${this.runiModelReadRpcTests},
331515
+ testing DevToolsRpcTests: ${this.runDevToolsRpcTests},
331049
331516
  testing iModelWriteRpcTests: ${this.runiModelWriteRpcTests}`;
331050
331517
  }
331051
331518
  }
@@ -331259,7 +331726,7 @@ class TestContext {
331259
331726
  this.initializeRpcInterfaces({ title: this.settings.Backend.name, version: this.settings.Backend.version });
331260
331727
  const iModelClient = new imodels_client_management_1.IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } });
331261
331728
  await core_frontend_1.NoRenderApp.startup({
331262
- applicationVersion: "5.1.0-dev.52",
331729
+ applicationVersion: "5.1.0-dev.54",
331263
331730
  applicationId: this.settings.gprid,
331264
331731
  authorizationClient: new frontend_1.TestFrontendAuthorizationClient(this.serviceAuthToken),
331265
331732
  hubAccess: new imodels_access_frontend_1.FrontendIModelsAccess(iModelClient),
@@ -356346,7 +356813,7 @@ var loadLanguages = instance.loadLanguages;
356346
356813
  /***/ ((module) => {
356347
356814
 
356348
356815
  "use strict";
356349
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.1.0-dev.52","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"}}');
356816
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.1.0-dev.54","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
356817
 
356351
356818
  /***/ }),
356352
356819
 
@@ -357429,62 +357896,6 @@ describe("DevTools", () => {
357429
357896
 
357430
357897
  })();
357431
357898
 
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
357899
  // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
357489
357900
  (() => {
357490
357901
  "use strict";