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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43182,7 +43182,8 @@ class WhiteOnWhiteReversalSettings {
43182
43182
  "use strict";
43183
43183
  __webpack_require__.r(__webpack_exports__);
43184
43184
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
43185
- /* harmony export */ TextAnnotation: () => (/* binding */ TextAnnotation)
43185
+ /* harmony export */ TextAnnotation: () => (/* binding */ TextAnnotation),
43186
+ /* harmony export */ textAnnotationFrameShapes: () => (/* binding */ textAnnotationFrameShapes)
43186
43187
  /* harmony export */ });
43187
43188
  /* harmony import */ var _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-geometry */ "../../core/geometry/lib/esm/core-geometry.js");
43188
43189
  /* harmony import */ var _TextBlock__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TextBlock */ "../../core/common/lib/esm/annotation/TextBlock.js");
@@ -43195,6 +43196,10 @@ __webpack_require__.r(__webpack_exports__);
43195
43196
  */
43196
43197
 
43197
43198
 
43199
+ /** Set of predefined shapes that can be computed and drawn around the margins of a [[TextBlock]]
43200
+ * @beta
43201
+ */
43202
+ const textAnnotationFrameShapes = ["none", "line", "rectangle", "circle", "equilateralTriangle", "diamond", "square", "pentagon", "hexagon", "octagon", "capsule", "roundedRectangle"];
43198
43203
  /**
43199
43204
  * Represents a formatted block of text positioned in 2d or 3d space.
43200
43205
  * [TextAnnotation2d]($backend) and [TextAnnotation3d]($backend) elements store a single TextAnnotation from which their geometric representation is generated.
@@ -44353,6 +44358,7 @@ __webpack_require__.r(__webpack_exports__);
44353
44358
  /* harmony export */ readElementMeshes: () => (/* reexport safe */ _ElementMesh__WEBPACK_IMPORTED_MODULE_29__.readElementMeshes),
44354
44359
  /* harmony export */ readTileContentDescription: () => (/* reexport safe */ _tile_TileMetadata__WEBPACK_IMPORTED_MODULE_157__.readTileContentDescription),
44355
44360
  /* harmony export */ rpcOverIpcStrings: () => (/* reexport safe */ _ipc_IpcSession__WEBPACK_IMPORTED_MODULE_75__.rpcOverIpcStrings),
44361
+ /* harmony export */ textAnnotationFrameShapes: () => (/* reexport safe */ _annotation_TextAnnotation__WEBPACK_IMPORTED_MODULE_2__.textAnnotationFrameShapes),
44356
44362
  /* harmony export */ tileFormatFromNumber: () => (/* reexport safe */ _tile_TileIO__WEBPACK_IMPORTED_MODULE_156__.tileFormatFromNumber)
44357
44363
  /* harmony export */ });
44358
44364
  /* harmony import */ var _AmbientOcclusion__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AmbientOcclusion */ "../../core/common/lib/esm/AmbientOcclusion.js");
@@ -85179,20 +85185,52 @@ class SnapshotConnection extends IModelConnection {
85179
85185
  /** The collection of [[CodeSpec]] entities for an [[IModelConnection]]. */
85180
85186
  class CodeSpecs {
85181
85187
  _iModel;
85182
- _loaded;
85183
85188
  /** @internal */
85184
85189
  constructor(_iModel) {
85185
85190
  this._iModel = _iModel;
85186
85191
  }
85187
- /** Loads all CodeSpec from the remote IModelDb. */
85188
- async _loadAllCodeSpecs() {
85189
- if (this._loaded)
85190
- return;
85191
- this._loaded = [];
85192
- const codeSpecArray = await _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getAllCodeSpecs(this._iModel.getRpcProps());
85193
- for (const codeSpec of codeSpecArray) {
85194
- 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));
85192
+ _isCodeSpecProperties(x) {
85193
+ if (!x || !x.scopeSpec || !Object.values(_itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.CodeScopeSpec.Type).includes(x.scopeSpec.type))
85194
+ return false;
85195
+ if (typeof x.scopeSpec.fGuidRequired !== "boolean" && typeof x.scopeSpec.fGuidRequired !== "undefined")
85196
+ return false;
85197
+ if (typeof x.scopeSpec.relationship !== "string" && typeof x.scopeSpec.relationship !== "undefined")
85198
+ return false;
85199
+ if (typeof x.spec?.isManagedWithDgnDb !== "boolean" && typeof x.spec?.isManagedWithDgnDb !== "undefined")
85200
+ return false;
85201
+ if (typeof x.version !== "string" && typeof x.version !== "undefined")
85202
+ return false;
85203
+ return true;
85204
+ }
85205
+ async _loadCodeSpec(identifier) {
85206
+ const isNameDefined = identifier.name !== undefined;
85207
+ const query = `
85208
+ SELECT ECInstanceId AS Id, Name, JsonProperties
85209
+ FROM BisCore.CodeSpec
85210
+ WHERE ${isNameDefined ? `Name=:name` : `Id=:id`}`;
85211
+ const params = new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.QueryBinder();
85212
+ if (isNameDefined) {
85213
+ params.bindString("name", identifier.name);
85214
+ }
85215
+ else {
85216
+ params.bindId("id", identifier.id);
85195
85217
  }
85218
+ const queryReader = this._iModel.createQueryReader(query, params, {
85219
+ rowFormat: _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.QueryRowFormat.UseECSqlPropertyNames,
85220
+ });
85221
+ const queryResult = await queryReader.next();
85222
+ if (queryResult.done)
85223
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
85224
+ const codeSpecResult = queryResult.value;
85225
+ if (typeof codeSpecResult.Id !== "string" ||
85226
+ typeof codeSpecResult.Name !== "string" ||
85227
+ typeof codeSpecResult.JsonProperties !== "string")
85228
+ throw new Error("Invalid CodeSpec was returned");
85229
+ const jsonProperties = JSON.parse(codeSpecResult.JsonProperties);
85230
+ if (!this._isCodeSpecProperties(jsonProperties))
85231
+ throw new Error("Invalid CodeSpecProperties returned in the CodeSpec");
85232
+ 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);
85233
+ return codeSpec;
85196
85234
  }
85197
85235
  /** Look up a CodeSpec by Id.
85198
85236
  * @param codeSpecId The Id of the CodeSpec to load
@@ -85200,13 +85238,11 @@ class SnapshotConnection extends IModelConnection {
85200
85238
  * @throws [[IModelError]] if the Id is invalid or if no CodeSpec with that Id could be found.
85201
85239
  */
85202
85240
  async getById(codeSpecId) {
85241
+ if (codeSpecId === "")
85242
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
85203
85243
  if (!_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Id64.isValid(codeSpecId))
85204
85244
  throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.InvalidId, "Invalid codeSpecId", () => ({ codeSpecId }));
85205
- await this._loadAllCodeSpecs(); // ensure all codeSpecs have been downloaded
85206
- const found = this._loaded.find((codeSpec) => codeSpec.id === codeSpecId);
85207
- if (!found)
85208
- throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
85209
- return found;
85245
+ return this._loadCodeSpec({ id: codeSpecId });
85210
85246
  }
85211
85247
  /** Look up a CodeSpec by name.
85212
85248
  * @param name The name of the CodeSpec to load
@@ -85214,11 +85250,9 @@ class SnapshotConnection extends IModelConnection {
85214
85250
  * @throws [[IModelError]] if no CodeSpec with the specified name could be found.
85215
85251
  */
85216
85252
  async getByName(name) {
85217
- await this._loadAllCodeSpecs(); // ensure all codeSpecs have been downloaded
85218
- const found = this._loaded.find((codeSpec) => codeSpec.name === name);
85219
- if (!found)
85253
+ if (name === "")
85220
85254
  throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.IModelStatus.NotFound, "CodeSpec not found");
85221
- return found;
85255
+ return this._loadCodeSpec({ name });
85222
85256
  }
85223
85257
  }
85224
85258
  IModelConnection.CodeSpecs = CodeSpecs;
@@ -186382,7 +186416,6 @@ class BSplineSurface3d extends BSpline2dNd {
186382
186416
  getPointGridJSON() {
186383
186417
  const result = {
186384
186418
  points: _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_7__.Point3dArray.unpackNumbersToNestedArraysIJK(this.coffs, 3, this.numPolesUV(0)),
186385
- weighStyle: WeightStyle.WeightsAlreadyAppliedToCoordinates, // @deprecated in 4.x - will not be removed until after 2026-06-13. Use weightStyle instead.
186386
186419
  weightStyle: WeightStyle.UnWeighted,
186387
186420
  numCartesianDimensions: 3,
186388
186421
  };
@@ -186795,7 +186828,6 @@ class BSplineSurface3dH extends BSpline2dNd {
186795
186828
  const result = {
186796
186829
  points: _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_7__.Point3dArray.unpackNumbersToNestedArraysIJK(this.coffs, 4, this.numPolesUV(0)),
186797
186830
  numCartesianDimensions: 3,
186798
- weighStyle: WeightStyle.WeightsAlreadyAppliedToCoordinates, // @deprecated in 4.x - will not be removed until after 2026-06-13. Use weightStyle instead.
186799
186831
  weightStyle: WeightStyle.WeightsAlreadyAppliedToCoordinates,
186800
186832
  };
186801
186833
  return result;
@@ -197809,6 +197841,17 @@ class CurveChain extends CurveCollection {
197809
197841
  else
197810
197842
  return undefined;
197811
197843
  }
197844
+ /**
197845
+ * Whether the chain start and end points are defined and within tolerance.
197846
+ * * Does not check for planarity or degeneracy.
197847
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
197848
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
197849
+ */
197850
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallMetricDistance, xyOnly = false) {
197851
+ const p0 = this.startPoint();
197852
+ const p1 = this.endPoint();
197853
+ return p0 !== undefined && p1 !== undefined && (xyOnly ? p0.isAlmostEqualXY(p1, tolerance) : p0.isAlmostEqual(p1, tolerance));
197854
+ }
197812
197855
  /**
197813
197856
  * Return the start point and derivative of the first child of the curve chain.
197814
197857
  * * For queries interior to the chain, use [[CurveChainWithDistanceIndex.fractionToPointAndDerivative]].
@@ -198539,11 +198582,12 @@ class CurveFactory {
198539
198582
  * * This only succeeds if the two arcs are part of identical complete arcs and end of `arcA` matches the beginning of `arcB`.
198540
198583
  * @param arcA first arc, modified in place.
198541
198584
  * @param arcB second arc, unmodified.
198542
- * @param allowReversed whether to consolidate even when second arc is reversed.
198585
+ * @param allowReversed whether to consolidate even when second arc is reversed (default is `false`).
198586
+ * @param tolerance optional coordinate tolerance for point equality (default is `Geometry.smallMetricDistance`).
198543
198587
  * @returns whether `arcA` was modified.
198544
198588
  */
198545
- static appendToArcInPlace(arcA, arcB, allowReverse = false) {
198546
- if (arcA.center.isAlmostEqual(arcB.center)) {
198589
+ static appendToArcInPlace(arcA, arcB, allowReverse = false, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
198590
+ if (arcA.center.isAlmostEqual(arcB.center, tolerance)) {
198547
198591
  const sweepSign = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.split3WaySign(arcA.sweep.sweepRadians * arcB.sweep.sweepRadians, -1, 0, 1);
198548
198592
  // evaluate derivatives wrt radians (not fraction!), but adjust direction for sweep signs
198549
198593
  const endA = arcA.angleToPointAndDerivative(arcA.sweep.fractionToAngle(1.0));
@@ -198552,14 +198596,14 @@ class CurveFactory {
198552
198596
  const startB = arcB.angleToPointAndDerivative(arcB.sweep.fractionToAngle(0.0));
198553
198597
  if (arcB.sweep.sweepRadians < 0)
198554
198598
  startB.direction.scaleInPlace(-1.0);
198555
- if (endA.isAlmostEqual(startB)) {
198599
+ if (endA.isAlmostEqual(startB, tolerance)) {
198556
198600
  arcA.sweep.setStartEndRadians(arcA.sweep.startRadians, arcA.sweep.startRadians + arcA.sweep.sweepRadians + sweepSign * arcB.sweep.sweepRadians);
198557
198601
  return true;
198558
198602
  }
198559
198603
  // Also ok if negated tangent
198560
198604
  if (allowReverse) {
198561
198605
  startB.direction.scaleInPlace(-1.0);
198562
- if (endA.isAlmostEqual(startB)) {
198606
+ if (endA.isAlmostEqual(startB, tolerance)) {
198563
198607
  arcA.sweep.setStartEndRadians(arcA.sweep.startRadians, arcA.sweep.startRadians + arcA.sweep.sweepRadians - sweepSign * arcB.sweep.sweepRadians);
198564
198608
  return true;
198565
198609
  }
@@ -199106,7 +199150,12 @@ class CurveLocationDetail {
199106
199150
  setIntervalRole(value) {
199107
199151
  this.intervalRole = value;
199108
199152
  }
199109
- /** Set the (optional) fraction1 and point1, using direct assignment (capture!) to point1. */
199153
+ /** Set the `fraction` and `point`, using direct assignment (capture!) to `point`. */
199154
+ captureFractionPoint(fraction, point) {
199155
+ this.fraction = fraction;
199156
+ this.point = point;
199157
+ }
199158
+ /** Set the (optional) `fraction1` and `point1`, using direct assignment (capture!) to `point1`. */
199110
199159
  captureFraction1Point1(fraction1, point1) {
199111
199160
  this.fraction1 = fraction1;
199112
199161
  this.point1 = point1;
@@ -200326,6 +200375,17 @@ class CurvePrimitive extends _GeometryQuery__WEBPACK_IMPORTED_MODULE_1__.Geometr
200326
200375
  endPoint(result) {
200327
200376
  return this.fractionToPoint(1.0, result);
200328
200377
  }
200378
+ /**
200379
+ * Whether the start and end points are defined and within tolerance.
200380
+ * * Does not check for planarity or degeneracy.
200381
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
200382
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
200383
+ */
200384
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance, xyOnly = false) {
200385
+ const p0 = this.startPoint();
200386
+ const p1 = this.endPoint();
200387
+ return p0 !== undefined && p1 !== undefined && (xyOnly ? p0.isAlmostEqualXY(p1, tolerance) : p0.isAlmostEqual(p1, tolerance));
200388
+ }
200329
200389
  /**
200330
200390
  * Attach StrokeCountMap structure to this primitive (and recursively to any children)
200331
200391
  * * Base class implementation (here) gets the simple count from computeStrokeCountForOptions and attaches it.
@@ -200813,6 +200873,10 @@ class LineSegment3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePr
200813
200873
  get point1Ref() {
200814
200874
  return this._point1;
200815
200875
  }
200876
+ /** Return a copy of the start and end points in an array. */
200877
+ get points() {
200878
+ return [this._point0.clone(), this._point1.clone()];
200879
+ }
200816
200880
  /** A LineSegment3d extends along its infinite line. */
200817
200881
  get isExtensibleFractionSpace() {
200818
200882
  return true;
@@ -202593,8 +202657,7 @@ class LineString3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePri
202593
202657
  this.addResolvedPoint(localA.index, localA.fraction, result._points);
202594
202658
  for (let index = index0; index <= index1; index++) {
202595
202659
  if (this._points.isIndexValid(index)) {
202596
- this._points.getPoint3dAtUncheckedPointIndex(index, LineString3d._workPointA);
202597
- result._points.push(LineString3d._workPointA);
202660
+ result._points.pushFromGrowableXYZArray(this._points, index);
202598
202661
  }
202599
202662
  }
202600
202663
  this.addResolvedPoint(localB.index, localB.fraction, result._points);
@@ -202606,9 +202669,22 @@ class LineString3d extends _CurvePrimitive__WEBPACK_IMPORTED_MODULE_1__.CurvePri
202606
202669
  return _LineSegment3d__WEBPACK_IMPORTED_MODULE_15__.LineSegment3d.create(this._points.getPoint3dAtCheckedPointIndex(index), this._points.getPoint3dAtCheckedPointIndex(index + 1), result);
202607
202670
  return undefined;
202608
202671
  }
202672
+ /**
202673
+ * Whether the start and end points are defined and within tolerance.
202674
+ * * Does not check for planarity or degeneracy.
202675
+ * @param tolerance optional distance tolerance (default is [[Geometry.smallMetricDistance]])
202676
+ * @param xyOnly if true, ignore z coordinate (default is `false`)
202677
+ */
202678
+ isPhysicallyClosedCurve(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance, xyOnly = false) {
202679
+ if (!this._points.length)
202680
+ return false;
202681
+ if (xyOnly)
202682
+ return this._points.almostEqualXYIndexIndex(0, this._points.length - 1, tolerance); // we know the indices are valid
202683
+ return this._points.almostEqualIndexIndex(0, this._points.length - 1, tolerance);
202684
+ }
202609
202685
  /** Returns true if first and last points are within metric tolerance. */
202610
202686
  get isPhysicallyClosed() {
202611
- return this._points.length > 0 && _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.isSmallMetricDistance(this._points.distanceIndexIndex(0, this._points.length - 1));
202687
+ return this.isPhysicallyClosedCurve();
202612
202688
  }
202613
202689
  /**
202614
202690
  * Evaluate strokes at fractions indicated in a StrokeCountMap.
@@ -203789,7 +203865,7 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
203789
203865
  const numOriginal = children.length;
203790
203866
  const points = [];
203791
203867
  let numAccept = 0;
203792
- // i0 <=i < i1 is a range of child indices.
203868
+ // i0 <= i < i1 is a range of child indices.
203793
203869
  // numAccept is the number of children accepted (contiguously at front of children)
203794
203870
  for (let i0 = 0; i0 < numOriginal;) {
203795
203871
  const basePrimitive = g.children[i0];
@@ -203847,7 +203923,7 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
203847
203923
  const nextPrimitive = g.children[i0];
203848
203924
  if (!(nextPrimitive instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d))
203849
203925
  break;
203850
- if (!_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(basePrimitive, nextPrimitive)) // TODO: use this._options.duplicatePointTolerance
203926
+ if (!_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(basePrimitive, nextPrimitive, false, this._options.duplicatePointTolerance))
203851
203927
  break;
203852
203928
  }
203853
203929
  // i0 has already advanced
@@ -203860,8 +203936,32 @@ class ConsolidateAdjacentCurvePrimitivesContext extends _geometry3d_GeometryHand
203860
203936
  }
203861
203937
  g.children.length = numAccept;
203862
203938
  }
203863
- handlePath(g) { return this.handleCurveChain(g); }
203864
- handleLoop(g) { return this.handleCurveChain(g); }
203939
+ handlePath(g) {
203940
+ return this.handleCurveChain(g);
203941
+ }
203942
+ handleLoop(g) {
203943
+ this.handleCurveChain(g);
203944
+ if (g.children.length > 1 && this._options.consolidateLoopSeam) {
203945
+ const lastChild = g.children[g.children.length - 1];
203946
+ const firstChild = g.children[0];
203947
+ 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)) {
203948
+ if (this._options.consolidateLinearGeometry && !this._options.disableLinearCompression) {
203949
+ const lastPoints = lastChild.points;
203950
+ lastPoints.pop(); // the original start point survives as an interior point in the new first primitive
203951
+ g.children[0] = _LineString3d__WEBPACK_IMPORTED_MODULE_3__.LineString3d.createPoints([...lastPoints, ...firstChild.points]);
203952
+ g.children.pop();
203953
+ }
203954
+ }
203955
+ else if (lastChild instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d && firstChild instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_7__.Arc3d) {
203956
+ if (this._options.consolidateCompatibleArcs) {
203957
+ if (_CurveFactory__WEBPACK_IMPORTED_MODULE_8__.CurveFactory.appendToArcInPlace(lastChild, firstChild, false, this._options.duplicatePointTolerance)) {
203958
+ g.children[0] = lastChild;
203959
+ g.children.pop();
203960
+ }
203961
+ }
203962
+ }
203963
+ }
203964
+ }
203865
203965
  handleParityRegion(g) {
203866
203966
  for (const child of g.children)
203867
203967
  child.dispatchToGeometryHandler(this);
@@ -204290,16 +204390,19 @@ __webpack_require__.r(__webpack_exports__);
204290
204390
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
204291
204391
  /* harmony export */ PlanarSubdivision: () => (/* binding */ PlanarSubdivision)
204292
204392
  /* harmony export */ });
204293
- /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
204294
- /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
204295
- /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
204296
- /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
204297
- /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
204298
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
204299
- /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
204300
- /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
204301
- /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
204302
- /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
204393
+ /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
204394
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
204395
+ /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
204396
+ /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
204397
+ /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
204398
+ /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
204399
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
204400
+ /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
204401
+ /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
204402
+ /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
204403
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
204404
+ /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
204405
+ /* harmony import */ var _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../RegionOpsClassificationSweeps */ "../../core/geometry/lib/esm/curve/RegionOpsClassificationSweeps.js");
204303
204406
  /*---------------------------------------------------------------------------------------------
204304
204407
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
204305
204408
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -204314,6 +204417,9 @@ __webpack_require__.r(__webpack_exports__);
204314
204417
 
204315
204418
 
204316
204419
 
204420
+
204421
+
204422
+
204317
204423
  /** @packageDocumentation
204318
204424
  * @module Curve
204319
204425
  */
@@ -204356,19 +204462,19 @@ class MapCurvePrimitiveToCurveLocationDetailPairArray {
204356
204462
  * added to the graph because it isn't in the `primitiveToPair` map. By splitting such a missing primitive in two, we
204357
204463
  * introduce two intersections for each half, which allows the primitive to be represented in the map.
204358
204464
  */
204359
- splitAndAppendMissingClosedPrimitives(primitives, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
204465
+ splitAndAppendMissingClosedPrimitives(primitives, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
204360
204466
  for (const p of primitives) {
204361
204467
  let closedCurveSplitCandidate = false;
204362
- if (p instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_1__.Arc3d)
204468
+ if (p instanceof _Arc3d__WEBPACK_IMPORTED_MODULE_2__.Arc3d)
204363
204469
  closedCurveSplitCandidate = p.sweep.isFullCircle;
204364
- 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.
204470
+ 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.
204365
204471
  closedCurveSplitCandidate = p.startPoint().isAlmostEqualXY(p.endPoint(), tolerance);
204366
204472
  if (closedCurveSplitCandidate && !this.primitiveToPair.has(p)) {
204367
204473
  const p0 = p.clonePartialCurve(0.0, 0.5);
204368
204474
  const p1 = p.clonePartialCurve(0.5, 1.0);
204369
204475
  if (p0 && p1) {
204370
- 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)));
204371
- 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)));
204476
+ 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)));
204477
+ 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)));
204372
204478
  }
204373
204479
  }
204374
204480
  }
@@ -204382,7 +204488,7 @@ class PlanarSubdivision {
204382
204488
  * Create a graph from an array of curves, and an array of the curves' precomputed intersections.
204383
204489
  * Z-coordinates are ignored.
204384
204490
  */
204385
- static assembleHalfEdgeGraph(primitives, allPairs, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
204491
+ static assembleHalfEdgeGraph(primitives, allPairs, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
204386
204492
  // map from key CurvePrimitive to CurveLocationDetailPair
204387
204493
  const detailByPrimitive = new MapCurvePrimitiveToCurveLocationDetailPairArray();
204388
204494
  for (const pair of allPairs)
@@ -204391,7 +204497,7 @@ class PlanarSubdivision {
204391
204497
  // otherwise, these single-primitive loops are missing from the graph
204392
204498
  detailByPrimitive.splitAndAppendMissingClosedPrimitives(primitives, mergeTolerance);
204393
204499
  }
204394
- const graph = new _topology_Graph__WEBPACK_IMPORTED_MODULE_5__.HalfEdgeGraph();
204500
+ const graph = new _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraph();
204395
204501
  for (const entry of detailByPrimitive.primitiveToPair.entries()) {
204396
204502
  const p = entry[0];
204397
204503
  // convert each interval intersection into two isolated intersections
@@ -204399,12 +204505,12 @@ class PlanarSubdivision {
204399
204505
  if (!detailPair.detailA.hasFraction1)
204400
204506
  return [...accumulator, detailPair];
204401
204507
  const detail = getDetailOnCurve(detailPair, p);
204402
- const detail0 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction, detail.point);
204403
- const detail1 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction1, detail.point1);
204508
+ const detail0 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction, detail.point);
204509
+ const detail1 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveFractionPoint(p, detail.fraction1, detail.point1);
204404
204510
  return [
204405
204511
  ...accumulator,
204406
- _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(detail0, detail0),
204407
- _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetailPair.createCapture(detail1, detail1),
204512
+ _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(detail0, detail0),
204513
+ _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetailPair.createCapture(detail1, detail1),
204408
204514
  ];
204409
204515
  }, []);
204410
204516
  // lexical sort on p intersection fraction
@@ -204416,12 +204522,12 @@ class PlanarSubdivision {
204416
204522
  let last = { point: p.startPoint(), fraction: 0.0 };
204417
204523
  for (const detailPair of details) {
204418
204524
  const detail = getDetailOnCurve(detailPair, p);
204419
- const detailFraction = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.restrictToInterval(detail.fraction, 0, 1); // truncate fraction, but don't snap point; clustering happens later
204525
+ const detailFraction = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.restrictToInterval(detail.fraction, 0, 1); // truncate fraction, but don't snap point; clustering happens later
204420
204526
  last = this.addHalfEdge(graph, p, last.point, last.fraction, detail.point, detailFraction, mergeTolerance);
204421
204527
  }
204422
204528
  this.addHalfEdge(graph, p, last.point, last.fraction, p.endPoint(), 1.0, mergeTolerance);
204423
204529
  }
204424
- _topology_Merging__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraphMerge.clusterAndMergeXYTheta(graph, (he) => he.sortAngle);
204530
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.clusterAndMergeXYTheta(graph, (he) => he.sortAngle);
204425
204531
  return graph;
204426
204532
  }
204427
204533
  /**
@@ -204435,11 +204541,13 @@ class PlanarSubdivision {
204435
204541
  * @param fraction1 end fraction
204436
204542
  * @returns end point and fraction, or start point and fraction if no action
204437
204543
  */
204438
- static addHalfEdge(graph, p, point0, fraction0, point1, fraction1, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.smallMetricDistance) {
204544
+ static addHalfEdge(graph, p, point0, fraction0, point1, fraction1, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
204439
204545
  if (point0.isAlmostEqualXY(point1, mergeTolerance))
204440
204546
  return { point: point0, fraction: fraction0 };
204441
204547
  const halfEdge = graph.createEdgeXYAndZ(point0, 0, point1, 0);
204442
- const detail01 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_4__.CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1);
204548
+ if (p.parent && p.parent instanceof _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__.RegionGroupMember && p.parent.parentGroup.groupOpType === _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_8__.RegionGroupOpType.NonBounding)
204549
+ halfEdge.setMaskAroundEdge(_topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.BRIDGE_EDGE);
204550
+ const detail01 = _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1);
204443
204551
  const mate = halfEdge.edgeMate;
204444
204552
  halfEdge.edgeTag = detail01;
204445
204553
  halfEdge.sortData = 1.0;
@@ -204457,7 +204565,7 @@ class PlanarSubdivision {
204457
204565
  * @returns the area (forced to zero if within tolerance)
204458
204566
  */
204459
204567
  static collectSignedLoop(loop, outLoops, zeroAreaTolerance = 1.0e-10, isSliverFace) {
204460
- let area = isSliverFace ? 0.0 : _RegionOps__WEBPACK_IMPORTED_MODULE_7__.RegionOps.computeXYArea(loop);
204568
+ let area = isSliverFace ? 0.0 : _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.computeXYArea(loop);
204461
204569
  if (area === undefined)
204462
204570
  area = 0;
204463
204571
  if (Math.abs(area) < zeroAreaTolerance)
@@ -204471,41 +204579,115 @@ class PlanarSubdivision {
204471
204579
  outLoops.slivers.push(loop);
204472
204580
  return area;
204473
204581
  }
204474
- static createLoopInFace(faceSeed, announce) {
204475
- let he = faceSeed;
204476
- const loop = _Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create();
204477
- do {
204478
- const detail = he.edgeTag;
204479
- if (detail) {
204480
- let curve;
204481
- if (he.sortData > 0)
204482
- curve = detail.curve.clonePartialCurve(detail.fraction, detail.fraction1);
204483
- else
204484
- curve = detail.curve.clonePartialCurve(detail.fraction1, detail.fraction);
204485
- if (curve) {
204486
- if (announce !== undefined)
204487
- announce(he, curve, loop);
204488
- loop.tryAddChild(curve);
204582
+ /** Extract geometric info from a topological edge. */
204583
+ static extractGeometryFromEdge(edge) {
204584
+ if (edge.sortData !== undefined && edge.edgeTag && edge.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_5__.CurveLocationDetail) {
204585
+ const detail = edge.edgeTag;
204586
+ if (detail.curve && detail.fraction1 !== undefined) {
204587
+ const reversed = edge.sortData < 0;
204588
+ return { detail, reversed };
204589
+ }
204590
+ }
204591
+ return undefined;
204592
+ }
204593
+ /** Create the geometry for a topological edge. */
204594
+ static createCurveInEdge(edge) {
204595
+ const info = this.extractGeometryFromEdge(edge);
204596
+ if (info) {
204597
+ if (info.reversed)
204598
+ return info.detail.curve.clonePartialCurve(info.detail.fraction1, info.detail.fraction);
204599
+ return info.detail.curve.clonePartialCurve(info.detail.fraction, info.detail.fraction1);
204600
+ }
204601
+ return undefined;
204602
+ }
204603
+ /**
204604
+ * Create a [[Loop]] for the given face or super face.
204605
+ * @param face a node in the face loop, or an array of HalfEdges that comprise a loop (e.g., a super face).
204606
+ * @param announce optional callback invoked on each edge/curve of the face/Loop.
204607
+ * @param compress whether to consolidate adjacent curves in the output Loop (default `false`).
204608
+ * If `announce` is provided, no compression is performed, as edges and curves would no longer be in 1-1 correspondence.
204609
+ */
204610
+ static createLoopInFace(face, announce, compress = false) {
204611
+ if (announce)
204612
+ compress = false;
204613
+ const loop = _Loop__WEBPACK_IMPORTED_MODULE_10__.Loop.create();
204614
+ const addEdgeCurve = (he) => {
204615
+ const curve = this.createCurveInEdge(he);
204616
+ if (curve) {
204617
+ announce?.(he, curve, loop);
204618
+ loop.tryAddChild(curve);
204619
+ }
204620
+ };
204621
+ if (Array.isArray(face))
204622
+ face.forEach(addEdgeCurve);
204623
+ else
204624
+ face.announceEdgesInFace(addEdgeCurve);
204625
+ if (compress) {
204626
+ const options = new _RegionOps__WEBPACK_IMPORTED_MODULE_9__.ConsolidateAdjacentCurvePrimitivesOptions();
204627
+ options.consolidateLoopSeam = true;
204628
+ _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.consolidateAdjacentPrimitives(loop, options);
204629
+ }
204630
+ if (loop.isPhysicallyClosedCurve(undefined, true))
204631
+ return loop;
204632
+ (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(false, "createLoopInFace: face is not physically closed");
204633
+ return undefined;
204634
+ }
204635
+ /**
204636
+ * Create a [[Loop]] or [[ParityRegion]] for the given face.
204637
+ * * A ParityRegion is created for a split-washer type face by removing bridge edges.
204638
+ * @param face a node in the face loop.
204639
+ * @param bridgeMask mask preset on bridge edges (default is `HalfEdgeMask.BRIDGE_EDGE`).
204640
+ * @param visitMask mask to use for visiting edges in the face loop (default is `HalfEdgeMask.VISITED`).
204641
+ */
204642
+ static createLoopOrParityRegionInFace(face, bridgeMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.BRIDGE_EDGE, visitMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeMask.VISITED) {
204643
+ let region;
204644
+ if (face.isSplitWasherFace(bridgeMask)) {
204645
+ const loops = [];
204646
+ const loopEdges = [];
204647
+ const bridgeStack = [face.findMaskAroundFace(bridgeMask, true)];
204648
+ const announceEdge = (he) => { he.setMask(visitMask); loopEdges.push(he); };
204649
+ const announceBridge = (he) => { if (!he.isMaskSet(visitMask))
204650
+ bridgeStack.push(he); };
204651
+ face.clearMaskAroundFace(visitMask);
204652
+ let bridge;
204653
+ while (undefined !== (bridge = bridgeStack.pop())) {
204654
+ bridge.setMask(visitMask);
204655
+ const loopSeed = bridge.findMaskAroundFace(bridgeMask, false); // advance to next loop
204656
+ if (loopSeed) {
204657
+ if (loopSeed.isMaskSet(visitMask))
204658
+ continue;
204659
+ loopEdges.length = 0;
204660
+ if (loopSeed.announceEdgesInSuperFace(bridgeMask, announceEdge, announceBridge)) {
204661
+ const loop = this.createLoopInFace(loopEdges, undefined, true);
204662
+ if (loop) {
204663
+ loops.push(loop);
204664
+ continue;
204665
+ }
204666
+ }
204489
204667
  }
204490
204668
  }
204491
- he = he.faceSuccessor;
204492
- } while (he !== faceSeed);
204493
- return loop;
204669
+ region = _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.sortOuterAndHoleLoopsXY(loops);
204670
+ region = _RegionOps__WEBPACK_IMPORTED_MODULE_9__.RegionOps.simplifyRegion(region);
204671
+ }
204672
+ else {
204673
+ region = this.createLoopInFace(face, undefined, true);
204674
+ }
204675
+ return (region && (region instanceof _Loop__WEBPACK_IMPORTED_MODULE_10__.Loop || region instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_11__.ParityRegion)) ? region : undefined;
204494
204676
  }
204495
- // Return true if there are only two edges in the face loop, and their start curvatures are the same.
204677
+ /** Return true if there are only two edges in the face loop, and their start curvatures are the same. */
204496
204678
  static isNullFace(he) {
204497
204679
  const faceHasTwoEdges = (he.faceSuccessor.faceSuccessor === he);
204498
204680
  let faceIsBanana = false;
204499
204681
  if (faceHasTwoEdges) {
204500
- const c0 = _topology_Merging__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraphMerge.curvatureSortKey(he);
204501
- const c1 = _topology_Merging__WEBPACK_IMPORTED_MODULE_6__.HalfEdgeGraphMerge.curvatureSortKey(he.faceSuccessor.edgeMate);
204502
- if (!_Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.isSameCoordinate(c0, c1)) // default tol!
204682
+ const c0 = _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.curvatureSortKey(he);
204683
+ const c1 = _topology_Merging__WEBPACK_IMPORTED_MODULE_7__.HalfEdgeGraphMerge.curvatureSortKey(he.faceSuccessor.edgeMate);
204684
+ if (!_Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(c0, c1)) // default tol!
204503
204685
  faceIsBanana = true; // heuristic: we could also check end curvatures, and/or higher derivatives...
204504
204686
  }
204505
204687
  return faceHasTwoEdges && !faceIsBanana;
204506
204688
  }
204507
- // Look across edge mates (possibly several) for a nonnull mate face.
204508
- static nonNullEdgeMate(_graph, e) {
204689
+ /** Look across edge mates (possibly several) for a non-null mate face. */
204690
+ static getNonNullEdgeMate(_graph, e) {
204509
204691
  if (this.isNullFace(e))
204510
204692
  return undefined;
204511
204693
  let e1 = e.edgeMate;
@@ -204517,7 +204699,7 @@ class PlanarSubdivision {
204517
204699
  return e1;
204518
204700
  }
204519
204701
  static collectSignedLoopSetsInHalfEdgeGraph(graph, zeroAreaTolerance = 1.0e-10) {
204520
- const q = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_9__.HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, undefined);
204702
+ const q = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_12__.HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, undefined);
204521
204703
  const result = [];
204522
204704
  const edgeMap = new Map();
204523
204705
  for (const faceSeeds of q) {
@@ -204527,15 +204709,15 @@ class PlanarSubdivision {
204527
204709
  const isNullFace = this.isNullFace(faceSeed);
204528
204710
  const loop = this.createLoopInFace(faceSeed, (he, curveC, loopC) => {
204529
204711
  if (!isNullFace) {
204530
- const mate = this.nonNullEdgeMate(graph, he);
204712
+ const mate = this.getNonNullEdgeMate(graph, he);
204531
204713
  if (mate !== undefined) {
204532
204714
  const e = edgeMap.get(mate);
204533
204715
  if (e === undefined) {
204534
204716
  // Record this as loopA,edgeA of a shared edge to be completed later from the other side of the edge
204535
- const e1 = new _Loop__WEBPACK_IMPORTED_MODULE_8__.LoopCurveLoopCurve(loopC, curveC, undefined, undefined);
204717
+ const e1 = new _Loop__WEBPACK_IMPORTED_MODULE_10__.LoopCurveLoopCurve(loopC, curveC, undefined, undefined);
204536
204718
  edgeMap.set(he, e1);
204537
204719
  }
204538
- else if (e instanceof _Loop__WEBPACK_IMPORTED_MODULE_8__.LoopCurveLoopCurve) {
204720
+ else if (e instanceof _Loop__WEBPACK_IMPORTED_MODULE_10__.LoopCurveLoopCurve) {
204539
204721
  e.setB(loopC, curveC);
204540
204722
  edges.push(e);
204541
204723
  edgeMap.delete(mate);
@@ -204543,7 +204725,8 @@ class PlanarSubdivision {
204543
204725
  }
204544
204726
  }
204545
204727
  });
204546
- this.collectSignedLoop(loop, componentAreas, zeroAreaTolerance, isNullFace);
204728
+ if (loop)
204729
+ this.collectSignedLoop(loop, componentAreas, zeroAreaTolerance, isNullFace);
204547
204730
  }
204548
204731
  componentAreas.edges = edges;
204549
204732
  result.push(componentAreas);
@@ -204591,11 +204774,12 @@ __webpack_require__.r(__webpack_exports__);
204591
204774
  /* harmony export */ StrokeCountSection: () => (/* binding */ StrokeCountSection)
204592
204775
  /* harmony export */ });
204593
204776
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
204594
- /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
204595
- /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
204777
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
204778
+ /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
204596
204779
  /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
204597
- /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
204598
- /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
204780
+ /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
204781
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
204782
+ /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
204599
204783
  /* harmony import */ var _StrokeCountMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./StrokeCountMap */ "../../core/geometry/lib/esm/curve/Query/StrokeCountMap.js");
204600
204784
  /*---------------------------------------------------------------------------------------------
204601
204785
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
@@ -204611,6 +204795,7 @@ __webpack_require__.r(__webpack_exports__);
204611
204795
 
204612
204796
 
204613
204797
 
204798
+
204614
204799
  // cspell:word remapa
204615
204800
  /**
204616
204801
  * abstract methods for callbacks during sweeps of collections of StrokeCount Structures.
@@ -204741,6 +204926,7 @@ class StrokeCountMapVisitorApplyMaxCurveLength extends StrokeCountMapMultipassVi
204741
204926
  * * `parent` = parent CurveCollection.
204742
204927
  *
204743
204928
  * An instance is normally created with either a `Path` or `Loop` as the parent.
204929
+ * @internal
204744
204930
  */
204745
204931
  class StrokeCountChain {
204746
204932
  maps;
@@ -204756,7 +204942,7 @@ class StrokeCountChain {
204756
204942
  this.maps = [];
204757
204943
  this.options = options;
204758
204944
  }
204759
- static createForCurveChain(chain, options) {
204945
+ static create(chain, options) {
204760
204946
  const result = new StrokeCountChain(chain, options);
204761
204947
  result.parent = chain;
204762
204948
  // A chain can only contain primitives !!!!
@@ -204827,16 +205013,24 @@ class StrokeCountSection {
204827
205013
  * construct array of arrays of `StrokeCountMap`s
204828
205014
  * @param parent
204829
205015
  */
204830
- static createForParityRegionOrChain(parent, options) {
205016
+ static create(parent, options) {
204831
205017
  const result = new StrokeCountSection(parent);
204832
- if (parent instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
205018
+ const appendCurveChain = (chain) => result.chains.push(StrokeCountChain.create(chain, options));
205019
+ const appendParityRegion = (region) => { for (const child of region.children)
205020
+ appendCurveChain(child); };
205021
+ if (parent instanceof _UnionRegion__WEBPACK_IMPORTED_MODULE_3__.UnionRegion) {
204833
205022
  for (const child of parent.children) {
204834
- const p = StrokeCountChain.createForCurveChain(child, options);
204835
- result.chains.push(p);
205023
+ if (child instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion)
205024
+ appendParityRegion(child);
205025
+ else
205026
+ appendCurveChain(child);
204836
205027
  }
204837
205028
  }
204838
- else if (parent instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
204839
- result.chains.push(StrokeCountChain.createForCurveChain(parent, options));
205029
+ else if (parent instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
205030
+ appendParityRegion(parent);
205031
+ }
205032
+ else if (parent instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
205033
+ appendCurveChain(parent);
204840
205034
  }
204841
205035
  return result;
204842
205036
  }
@@ -204915,11 +205109,12 @@ class StrokeCountSection {
204915
205109
  for (let chainIndex = 0; chainIndex < numChainPerSection; chainIndex++) {
204916
205110
  const numPrimitive = sections[0].chains[chainIndex].maps.length;
204917
205111
  for (let primitiveIndex = 0; primitiveIndex < numPrimitive; primitiveIndex++) {
204918
- if (sections[0].chains[chainIndex].maps[primitiveIndex].componentData) {
204919
- const numComponent = sections[0].chains[chainIndex].maps[primitiveIndex].componentData.length;
204920
- for (let i = 0; i < numComponent; i++)
205112
+ const numComponent = sections[0].chains[chainIndex].maps[primitiveIndex].componentData?.length ?? 0;
205113
+ if (numComponent > 0) {
205114
+ for (let i = 0; i < numComponent; i++) {
204921
205115
  if (!this.applyMultipassVisitorCallbackNoComponents(sections, chainIndex, primitiveIndex, i, callback))
204922
205116
  return false;
205117
+ }
204923
205118
  }
204924
205119
  else {
204925
205120
  if (!this.applyMultipassVisitorCallbackNoComponents(sections, chainIndex, primitiveIndex, undefined, callback))
@@ -204967,11 +205162,11 @@ class StrokeCountSection {
204967
205162
  return this.chains[0].getStrokes();
204968
205163
  }
204969
205164
  else {
204970
- const region = _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion.create();
205165
+ const region = _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion.create();
204971
205166
  for (const c of this.chains) {
204972
205167
  const strokes = c.getStrokes();
204973
205168
  if (strokes instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_2__.LineString3d)
204974
- region.tryAddChild(_Loop__WEBPACK_IMPORTED_MODULE_5__.Loop.create(strokes));
205169
+ region.tryAddChild(_Loop__WEBPACK_IMPORTED_MODULE_6__.Loop.create(strokes));
204975
205170
  }
204976
205171
  return region;
204977
205172
  }
@@ -204993,8 +205188,8 @@ class StrokeCountSection {
204993
205188
  if (strokeB instanceof _LineString3d__WEBPACK_IMPORTED_MODULE_2__.LineString3d) {
204994
205189
  if (strokeA.numPoints() === strokeB.numPoints()) {
204995
205190
  const n = strokeA.numPoints();
204996
- const pointA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
204997
- const pointB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
205191
+ const pointA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
205192
+ const pointB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
204998
205193
  const allPointA = strokeA.packedPoints;
204999
205194
  const allPointB = strokeB.packedPoints;
205000
205195
  for (let i = 0; i < n; i++) {
@@ -205006,8 +205201,8 @@ class StrokeCountSection {
205006
205201
  }
205007
205202
  }
205008
205203
  }
205009
- else if (strokeA instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
205010
- if (strokeB instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_3__.ParityRegion) {
205204
+ else if (strokeA instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
205205
+ if (strokeB instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_4__.ParityRegion) {
205011
205206
  const childrenA = strokeA.children;
205012
205207
  const childrenB = strokeB.children;
205013
205208
  const n = childrenA.length;
@@ -205020,8 +205215,8 @@ class StrokeCountSection {
205020
205215
  }
205021
205216
  }
205022
205217
  }
205023
- else if (strokeA instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
205024
- if (strokeB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_4__.CurveChain) {
205218
+ else if (strokeA instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
205219
+ if (strokeB instanceof _CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
205025
205220
  const childrenA = strokeA.children;
205026
205221
  const childrenB = strokeB.children;
205027
205222
  const n = childrenA.length;
@@ -205224,10 +205419,11 @@ __webpack_require__.r(__webpack_exports__);
205224
205419
  /* harmony import */ var _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/GeometryHandler */ "../../core/geometry/lib/esm/geometry3d/GeometryHandler.js");
205225
205420
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
205226
205421
  /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
205227
- /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
205422
+ /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
205228
205423
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
205424
+ /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
205229
205425
  /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
205230
- /* harmony import */ var _StrokeOptions__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
205426
+ /* harmony import */ var _StrokeOptions__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
205231
205427
  /*---------------------------------------------------------------------------------------------
205232
205428
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
205233
205429
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -205240,6 +205436,7 @@ __webpack_require__.r(__webpack_exports__);
205240
205436
 
205241
205437
 
205242
205438
 
205439
+
205243
205440
  /**
205244
205441
  * Implementation class for computing XY area moments.
205245
205442
  * @internal
@@ -205295,7 +205492,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
205295
205492
  segment.endPoint(this._point1);
205296
205493
  momentData.accumulateTriangleMomentsXY(undefined, this._point0, this._point1);
205297
205494
  }
205298
- /** Accumulate integrals from origin to all primitives in the chain. */
205495
+ /** Accumulate integrals from origin to all primitives in the loop. */
205299
205496
  handleLoop(loop) {
205300
205497
  const momentData = this._activeMomentData = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_3__.MomentData.create();
205301
205498
  momentData.needOrigin = false;
@@ -205305,7 +205502,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
205305
205502
  return momentData;
205306
205503
  }
205307
205504
  handleAnyRegion(region) {
205308
- // guarantee there is no overlapping children
205505
+ // guarantee there are no overlapping children and parity loops have been properly oriented
205309
205506
  const merged = _RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.regionBooleanXY(region, undefined, _RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionBinaryOpType.Union);
205310
205507
  if (!merged)
205311
205508
  return undefined;
@@ -205315,7 +205512,9 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
205315
205512
  for (const child of merged.children) {
205316
205513
  const childMoments = child.dispatchToGeometryHandler(this);
205317
205514
  if (childMoments) {
205318
- const sign0 = childMoments.signFactor(1.0);
205515
+ // parity region hole sums subtract; all other regions add
205516
+ const scale = (merged instanceof _ParityRegion__WEBPACK_IMPORTED_MODULE_6__.ParityRegion && childMoments.quantitySum < 0) ? -1.0 : 1.0;
205517
+ const sign0 = childMoments.signFactor(scale);
205319
205518
  summedMoments.accumulateProducts(childMoments, sign0);
205320
205519
  }
205321
205520
  }
@@ -205333,7 +205532,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
205333
205532
  getStrokeOptions() {
205334
205533
  if (this._strokeOptions)
205335
205534
  return this._strokeOptions;
205336
- const options = _StrokeOptions__WEBPACK_IMPORTED_MODULE_6__.StrokeOptions.createForCurves();
205535
+ const options = _StrokeOptions__WEBPACK_IMPORTED_MODULE_7__.StrokeOptions.createForCurves();
205337
205536
  // this is unusually fine for stroking, but appropriate for sum.
205338
205537
  options.angleTol = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_2__.Angle.createDegrees(5.0);
205339
205538
  this._strokeOptions = options;
@@ -205344,7 +205543,7 @@ class RegionMomentsXY extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
205344
205543
  * * Stroke the curve and accumulate stroke array.
205345
205544
  */
205346
205545
  handleCurvePrimitive(cp) {
205347
- const strokes = _LineString3d__WEBPACK_IMPORTED_MODULE_7__.LineString3d.create();
205546
+ const strokes = _LineString3d__WEBPACK_IMPORTED_MODULE_8__.LineString3d.create();
205348
205547
  const options = this.getStrokeOptions();
205349
205548
  cp.emitStrokes(strokes, options);
205350
205549
  this.handleLineString3d(strokes);
@@ -205386,27 +205585,28 @@ __webpack_require__.r(__webpack_exports__);
205386
205585
  /* harmony import */ var _geometry3d_IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../geometry3d/IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
205387
205586
  /* harmony import */ var _geometry3d_Point3dArrayCarrier__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../geometry3d/Point3dArrayCarrier */ "../../core/geometry/lib/esm/geometry3d/Point3dArrayCarrier.js");
205388
205587
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
205389
- /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
205588
+ /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
205390
205589
  /* harmony import */ var _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../geometry3d/PolylineCompressionByEdgeOffset */ "../../core/geometry/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js");
205391
- /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
205590
+ /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
205392
205591
  /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
205393
205592
  /* harmony import */ var _geometry3d_SortablePolygon__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../geometry3d/SortablePolygon */ "../../core/geometry/lib/esm/geometry3d/SortablePolygon.js");
205394
205593
  /* harmony import */ var _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../geometry3d/Transform */ "../../core/geometry/lib/esm/geometry3d/Transform.js");
205395
205594
  /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
205396
205595
  /* harmony import */ var _polyface_PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../polyface/PolyfaceBuilder */ "../../core/geometry/lib/esm/polyface/PolyfaceBuilder.js");
205397
- /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
205398
- /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
205399
- /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
205596
+ /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
205597
+ /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
205598
+ /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
205400
205599
  /* harmony import */ var _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../topology/Triangulation */ "../../core/geometry/lib/esm/topology/Triangulation.js");
205401
205600
  /* harmony import */ var _CurveCollection__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
205402
- /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
205601
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
205403
205602
  /* harmony import */ var _CurveOps__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./CurveOps */ "../../core/geometry/lib/esm/curve/CurveOps.js");
205404
205603
  /* harmony import */ var _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
205405
205604
  /* harmony import */ var _CurveWireMomentsXYZ__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./CurveWireMomentsXYZ */ "../../core/geometry/lib/esm/curve/CurveWireMomentsXYZ.js");
205406
- /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
205605
+ /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
205407
205606
  /* harmony import */ var _internalContexts_ChainCollectorContext__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./internalContexts/ChainCollectorContext */ "../../core/geometry/lib/esm/curve/internalContexts/ChainCollectorContext.js");
205408
205607
  /* harmony import */ var _internalContexts_PolygonOffsetContext__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./internalContexts/PolygonOffsetContext */ "../../core/geometry/lib/esm/curve/internalContexts/PolygonOffsetContext.js");
205409
205608
  /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
205609
+ /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
205410
205610
  /* harmony import */ var _LineString3d__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
205411
205611
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
205412
205612
  /* harmony import */ var _OffsetOptions__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./OffsetOptions */ "../../core/geometry/lib/esm/curve/OffsetOptions.js");
@@ -205415,7 +205615,7 @@ __webpack_require__.r(__webpack_exports__);
205415
205615
  /* harmony import */ var _Query_ConsolidateAdjacentPrimitivesContext__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./Query/ConsolidateAdjacentPrimitivesContext */ "../../core/geometry/lib/esm/curve/Query/ConsolidateAdjacentPrimitivesContext.js");
205416
205616
  /* harmony import */ var _Query_CurveSplitContext__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./Query/CurveSplitContext */ "../../core/geometry/lib/esm/curve/Query/CurveSplitContext.js");
205417
205617
  /* harmony import */ var _Query_InOutTests__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./Query/InOutTests */ "../../core/geometry/lib/esm/curve/Query/InOutTests.js");
205418
- /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
205618
+ /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
205419
205619
  /* harmony import */ var _RegionMomentsXY__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RegionMomentsXY */ "../../core/geometry/lib/esm/curve/RegionMomentsXY.js");
205420
205620
  /* harmony import */ var _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./RegionOpsClassificationSweeps */ "../../core/geometry/lib/esm/curve/RegionOpsClassificationSweeps.js");
205421
205621
  /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
@@ -205464,6 +205664,7 @@ __webpack_require__.r(__webpack_exports__);
205464
205664
 
205465
205665
 
205466
205666
 
205667
+
205467
205668
 
205468
205669
 
205469
205670
  /**
@@ -205765,16 +205966,17 @@ class RegionOps {
205765
205966
  * @param loopsB second set of loops (treated as a union)
205766
205967
  * @param operation indicates Union, Intersection, Parity, AMinusB, or BMinusA
205767
205968
  * @param mergeTolerance absolute distance tolerance for merging loops
205768
- * @returns a region resulting from merging input loops and the boolean operation. May contain bridge edges added
205769
- * to connect interior loops to exterior loops.
205969
+ * @returns a region resulting from merging input loops and the boolean operation.
205770
205970
  */
205771
205971
  static regionBooleanXY(loopsA, loopsB, operation, mergeTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
205772
- let result;
205972
+ const result = _UnionRegion__WEBPACK_IMPORTED_MODULE_14__.UnionRegion.create();
205773
205973
  const context = _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionBooleanContext.create(_RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union);
205774
205974
  context.addMembers(loopsA, loopsB);
205775
205975
  context.annotateAndMergeCurvesInGraph(mergeTolerance);
205976
+ const visitMask = context.graph.grabMask(false);
205776
205977
  const range = context.groupA.range().union(context.groupB.range());
205777
205978
  const areaTol = this.computeXYAreaTolerance(range, mergeTolerance);
205979
+ const bridgeMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE;
205778
205980
  context.runClassificationSweep(operation, (_graph, face, faceType, area) => {
205779
205981
  // ignore danglers and null faces, but not 2-edge "banana" faces with nonzero area
205780
205982
  if (face.countEdgesAroundFace() < 2)
@@ -205782,15 +205984,13 @@ class RegionOps {
205782
205984
  if (Math.abs(area) < areaTol)
205783
205985
  return;
205784
205986
  if (faceType === 1) {
205785
- const loop = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_15__.PlanarSubdivision.createLoopInFace(face);
205786
- if (loop) {
205787
- if (!result)
205788
- result = _UnionRegion__WEBPACK_IMPORTED_MODULE_14__.UnionRegion.create();
205789
- result.tryAddChild(loop);
205790
- }
205987
+ const loopOrParityRegion = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.createLoopOrParityRegionInFace(face, bridgeMask, visitMask);
205988
+ if (loopOrParityRegion)
205989
+ result.tryAddChild(loopOrParityRegion);
205791
205990
  }
205792
205991
  });
205793
- return result ? this.simplifyRegion(result) : undefined;
205992
+ context.graph.dropMask(visitMask);
205993
+ return this.simplifyRegion(result);
205794
205994
  }
205795
205995
  /**
205796
205996
  * Return a polyface whose facets are a boolean operation between the input regions.
@@ -205823,7 +206023,7 @@ class RegionOps {
205823
206023
  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);
205824
206024
  if (!graph)
205825
206025
  return undefined;
205826
- const loopEdges = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_16__.HalfEdgeGraphSearch.collectExtendedBoundaryLoopsInGraph(graph, _topology_Graph__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeMask.EXTERIOR);
206026
+ const loopEdges = _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeGraphSearch.collectExtendedBoundaryLoopsInGraph(graph, _topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.EXTERIOR);
205827
206027
  const allLoops = [];
205828
206028
  for (const graphLoop of loopEdges) {
205829
206029
  const points = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray();
@@ -206105,19 +206305,45 @@ class RegionOps {
206105
206305
  }
206106
206306
  return _geometry3d_SortablePolygon__WEBPACK_IMPORTED_MODULE_33__.SortablePolygon.sortAsAnyRegion(loopAndArea);
206107
206307
  }
206308
+ /**
206309
+ * Collect inputs that are nominally closed: regions, and physically closed curves.
206310
+ * * Physically closed input curves are each returned wrapped in a Loop to facilitate xy-algorithms,
206311
+ * but outside this limited context, these Loops only makes sense if they are planar.
206312
+ */
206313
+ static collectRegionsAndClosedPrimitives(curves, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
206314
+ const regions = [];
206315
+ if (!Array.isArray(curves))
206316
+ curves = [curves];
206317
+ for (const curve of curves) {
206318
+ 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) {
206319
+ regions.push(curve);
206320
+ }
206321
+ else if (curve instanceof _Path__WEBPACK_IMPORTED_MODULE_24__.Path) {
206322
+ if (curve.isPhysicallyClosedCurve(tolerance))
206323
+ regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(...curve.children));
206324
+ }
206325
+ else if (curve instanceof _CurvePrimitive__WEBPACK_IMPORTED_MODULE_27__.CurvePrimitive) {
206326
+ if (curve.isPhysicallyClosedCurve(tolerance))
206327
+ regions.push(_Loop__WEBPACK_IMPORTED_MODULE_8__.Loop.create(curve));
206328
+ }
206329
+ }
206330
+ return regions;
206331
+ }
206108
206332
  /**
206109
206333
  * Find all xy-areas bounded by the unstructured, possibly intersecting curves.
206110
206334
  * * For best results, input curves should be parallel to the xy-plane, as z-coordinates are ignored.
206111
- * * A common use case of this method is to assemble the bounding "exterior" loop (or loops) containing the
206112
- * input curves. Note that "holes" implied by inputs are _not_ preserved in output.
206113
- * * This method does not add bridge edges to connect outer loops to inner loops. Each disconnected loop,
206114
- * regardless of its containment, is returned as its own SignedLoops object. Pre-process with [[regionBooleanXY]]
206115
- * to add bridge edges so that [[constructAllXYRegionLoops]] will return outer and inner loops in the same
206116
- * SignedLoops object.
206117
- * @param curvesAndRegions Any collection of curves. Each Loop/ParityRegion/UnionRegion contributes its curve
206118
- * primitives, stripped of parity context. This means holes are _not_ preserved in output.
206335
+ * * "Holes" implied/bounded by inputs are _not_ preserved/discovered in output; in particular [[ParityRegion]]
206336
+ * hole loops are treated like any other positive area loops.
206337
+ * * A common use case of this method is to assemble the bounding negative-area "exterior" loop for each connected
206338
+ * component of input curves. Passing `addBridges = true` decreases the number of connected components for nested
206339
+ * input [[Loop]]s, and thus increases the likelihood of returning exactly one exterior loop. (This is why the
206340
+ * default value for `addBridges` is `true`.)
206341
+ * @param curvesAndRegions Any collection of curves. Each [[AnyRegion]] contributes its children _stripped of
206342
+ * parity context_.
206119
206343
  * @param tolerance optional distance tolerance for coincidence.
206120
- * @returns array of [[SignedLoops]], each entry of which describes the faces in a single connected component:
206344
+ * @param addBridges whether to add line segments to connect nested input [[Loop]]s (default is `true`). When `false`,
206345
+ * no line segments are added to the input curves, but the number of output components may be greater than expected.
206346
+ * @returns array of [[SignedLoops]], each entry of which describes the areas bounded by a single connected component:
206121
206347
  * * `positiveAreaLoops` contains "interior" loops, _including holes in ParityRegion input_. These loops have
206122
206348
  * positive area and counterclockwise orientation.
206123
206349
  * * `negativeAreaLoops` contains (probably just one) "exterior" loop which is ordered clockwise.
@@ -206125,14 +206351,25 @@ class RegionOps {
206125
206351
  * * `edges` contains a [[LoopCurveLoopCurve]] object for each component edge, collecting both loops adjacent
206126
206352
  * to the edge and a constituent curve in each.
206127
206353
  */
206128
- static constructAllXYRegionLoops(curvesAndRegions, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance) {
206354
+ static constructAllXYRegionLoops(curvesAndRegions, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance, addBridges = true) {
206129
206355
  let primitives = RegionOps.collectCurvePrimitives(curvesAndRegions, undefined, true, true);
206130
206356
  primitives = _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_34__.TransferWithSplitArcs.clone(_CurveCollection__WEBPACK_IMPORTED_MODULE_25__.BagOfCurves.create(...primitives)).children;
206131
206357
  const range = this.curveArrayRange(primitives);
206132
206358
  const areaTol = this.computeXYAreaTolerance(range, tolerance);
206133
- const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_35__.CurveCurve.allIntersectionsAmongPrimitivesXY(primitives, tolerance);
206134
- const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_15__.PlanarSubdivision.assembleHalfEdgeGraph(primitives, intersections, tolerance);
206135
- return _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_15__.PlanarSubdivision.collectSignedLoopSetsInHalfEdgeGraph(graph, areaTol);
206359
+ if (addBridges) { // generate a temp graph to extract its bridge edges
206360
+ const context = _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionBooleanContext.create(_RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union, _RegionOpsClassificationSweeps__WEBPACK_IMPORTED_MODULE_13__.RegionGroupOpType.Union);
206361
+ const regions = this.collectRegionsAndClosedPrimitives(curvesAndRegions, tolerance);
206362
+ context.addMembers(regions, undefined);
206363
+ context.annotateAndMergeCurvesInGraph(tolerance);
206364
+ context.graph.announceEdges((_graph, edge) => {
206365
+ if (edge.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.BRIDGE_EDGE))
206366
+ primitives.push(_LineSegment3d__WEBPACK_IMPORTED_MODULE_35__.LineSegment3d.create(edge.getPoint3d(), edge.faceSuccessor.getPoint3d()));
206367
+ return true;
206368
+ });
206369
+ }
206370
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_36__.CurveCurve.allIntersectionsAmongPrimitivesXY(primitives, tolerance);
206371
+ const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.assembleHalfEdgeGraph(primitives, intersections, tolerance);
206372
+ return _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_16__.PlanarSubdivision.collectSignedLoopSetsInHalfEdgeGraph(graph, areaTol);
206136
206373
  }
206137
206374
  /**
206138
206375
  * Collect all `CurvePrimitives` in loosely typed input.
@@ -206188,12 +206425,12 @@ class RegionOps {
206188
206425
  * @param worldToLocal transform to apply to data before computing its range
206189
206426
  */
206190
206427
  static curveArrayRange(data, worldToLocal) {
206191
- const range = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_36__.Range3d.create();
206192
- if (data instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_37__.GeometryQuery)
206428
+ const range = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_37__.Range3d.create();
206429
+ if (data instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__.GeometryQuery)
206193
206430
  data.extendRange(range, worldToLocal);
206194
206431
  else if (Array.isArray(data)) {
206195
206432
  for (const c of data) {
206196
- if (c instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_37__.GeometryQuery)
206433
+ if (c instanceof _GeometryQuery__WEBPACK_IMPORTED_MODULE_38__.GeometryQuery)
206197
206434
  c.extendRange(range, worldToLocal);
206198
206435
  else if (c instanceof _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d)
206199
206436
  range.extendPoint(c, worldToLocal);
@@ -206229,7 +206466,7 @@ class RegionOps {
206229
206466
  for (const polygon of polygons)
206230
206467
  writablePolygons.push(_geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray.create(polygon));
206231
206468
  }
206232
- const sortedPolygons = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_38__.PolygonOps.sortOuterAndHoleLoopsXY(writablePolygons);
206469
+ const sortedPolygons = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_39__.PolygonOps.sortOuterAndHoleLoopsXY(writablePolygons);
206233
206470
  if (sortedPolygons.length === 1) { // below requires exactly one outer loop!
206234
206471
  if (graph = _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__.Triangulator.createTriangulatedGraphFromLoops(sortedPolygons[0]))
206235
206472
  _topology_Triangulation__WEBPACK_IMPORTED_MODULE_11__.Triangulator.flipTriangles(graph);
@@ -206312,7 +206549,7 @@ class RegionOps {
206312
206549
  if (!graph)
206313
206550
  return undefined;
206314
206551
  if (options?.maximizeConvexFacets)
206315
- _topology_Merging__WEBPACK_IMPORTED_MODULE_39__.HalfEdgeGraphOps.expandConvexFaces(graph);
206552
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_40__.HalfEdgeGraphOps.expandConvexFaces(graph);
206316
206553
  return _polyface_PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_12__.PolyfaceBuilder.graphToPolyface(graph, options);
206317
206554
  }
206318
206555
  /**
@@ -206326,10 +206563,10 @@ class RegionOps {
206326
206563
  if (!graph)
206327
206564
  return undefined;
206328
206565
  if (maximize)
206329
- _topology_Merging__WEBPACK_IMPORTED_MODULE_39__.HalfEdgeGraphOps.expandConvexFaces(graph);
206566
+ _topology_Merging__WEBPACK_IMPORTED_MODULE_40__.HalfEdgeGraphOps.expandConvexFaces(graph);
206330
206567
  const convexPolygons = [];
206331
206568
  graph.announceFaceLoops((_graph, seed) => {
206332
- if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_17__.HalfEdgeMask.EXTERIOR))
206569
+ if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_15__.HalfEdgeMask.EXTERIOR))
206333
206570
  convexPolygons.push(_geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_18__.GrowableXYZArray.create(seed.collectAroundFace((node) => { return node.getPoint3d(); })));
206334
206571
  return true;
206335
206572
  });
@@ -206354,9 +206591,11 @@ class ConsolidateAdjacentCurvePrimitivesOptions {
206354
206591
  consolidateLinearGeometry = true;
206355
206592
  /** True to consolidate contiguous compatible arcs into a single Arc3d. */
206356
206593
  consolidateCompatibleArcs = true;
206594
+ /** True to consolidate the first and last primitives of a [[Loop]], allowing the start/end point to change. */
206595
+ consolidateLoopSeam = false;
206357
206596
  /** Disable LineSegment3d and LineString3d point compression. */
206358
206597
  disableLinearCompression = false;
206359
- /** Tolerance for collapsing identical points (if `!disableLinearCompression`). */
206598
+ /** Tolerance for detecting identical points. */
206360
206599
  duplicatePointTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance;
206361
206600
  /** Tolerance for removing interior colinear points (if `!disableLinearCompression`). */
206362
206601
  colinearPointTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistance;
@@ -206378,6 +206617,7 @@ __webpack_require__.r(__webpack_exports__);
206378
206617
  /* harmony export */ GraphComponentArray: () => (/* binding */ GraphComponentArray),
206379
206618
  /* harmony export */ RegionBooleanContext: () => (/* binding */ RegionBooleanContext),
206380
206619
  /* harmony export */ RegionGroup: () => (/* binding */ RegionGroup),
206620
+ /* harmony export */ RegionGroupMember: () => (/* binding */ RegionGroupMember),
206381
206621
  /* harmony export */ RegionGroupOpType: () => (/* binding */ RegionGroupOpType),
206382
206622
  /* harmony export */ RegionOpsFaceToFaceSearch: () => (/* binding */ RegionOpsFaceToFaceSearch)
206383
206623
  /* harmony export */ });
@@ -206390,15 +206630,15 @@ __webpack_require__.r(__webpack_exports__);
206390
206630
  /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
206391
206631
  /* harmony import */ var _topology_RegularizeFace__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../topology/RegularizeFace */ "../../core/geometry/lib/esm/topology/RegularizeFace.js");
206392
206632
  /* harmony import */ var _Arc3d__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./Arc3d */ "../../core/geometry/lib/esm/curve/Arc3d.js");
206393
- /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
206394
- /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
206633
+ /* harmony import */ var _CurveCurve__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./CurveCurve */ "../../core/geometry/lib/esm/curve/CurveCurve.js");
206634
+ /* harmony import */ var _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./CurveLocationDetail */ "../../core/geometry/lib/esm/curve/CurveLocationDetail.js");
206395
206635
  /* harmony import */ var _GeometryQuery__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./GeometryQuery */ "../../core/geometry/lib/esm/curve/GeometryQuery.js");
206396
206636
  /* harmony import */ var _internalContexts_PlaneAltitudeRangeContext__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./internalContexts/PlaneAltitudeRangeContext */ "../../core/geometry/lib/esm/curve/internalContexts/PlaneAltitudeRangeContext.js");
206397
206637
  /* harmony import */ var _internalContexts_TransferWithSplitArcs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./internalContexts/TransferWithSplitArcs */ "../../core/geometry/lib/esm/curve/internalContexts/TransferWithSplitArcs.js");
206398
206638
  /* harmony import */ var _LineSegment3d__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
206399
206639
  /* harmony import */ var _Loop__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
206400
206640
  /* harmony import */ var _ParityRegion__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
206401
- /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
206641
+ /* harmony import */ var _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./Query/PlanarSubdivision */ "../../core/geometry/lib/esm/curve/Query/PlanarSubdivision.js");
206402
206642
  /* harmony import */ var _RegionOps__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
206403
206643
  /* harmony import */ var _UnionRegion__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
206404
206644
  /*---------------------------------------------------------------------------------------------
@@ -206902,6 +207142,94 @@ class RegionBooleanContext {
206902
207142
  this.extraGeometry.addMember(bridgeLine, true);
206903
207143
  }
206904
207144
  }
207145
+ /**
207146
+ * Simplify the graph by removing bridge edges that do not serve to connect inner and outer loops, i.e.:
207147
+ * * the bridge edge is dangling
207148
+ * * the bridge edge is adjacent to multiple faces
207149
+ * * the bridge edge is adjacent to a negative area face
207150
+ * @returns the number of extraneous bridge edges removed from the graph.
207151
+ */
207152
+ removeExtraneousBridgeEdges() {
207153
+ const toHeal = [];
207154
+ const interiorBridges = [];
207155
+ // lambda test for boundary edge. Relies only on face loop orientation. Doesn't use HalfEdgeMasks!
207156
+ const isExteriorEdge = (node) => {
207157
+ if (this.faceAreaFunction(node) < 0.0)
207158
+ return true;
207159
+ if (!node.findAroundFace(node.edgeMate))
207160
+ return this.faceAreaFunction(node.edgeMate) < 0.0;
207161
+ return false;
207162
+ };
207163
+ // isolate dangling bridges, bridges separating different faces, and "exterior" bridges in the negative area face
207164
+ this.graph.announceEdges((_graph, node) => {
207165
+ if (node.edgeTag !== undefined) {
207166
+ if (node.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail) {
207167
+ if (node.edgeTag.curve) {
207168
+ if (node.edgeTag.curve.parent instanceof RegionGroupMember) {
207169
+ if (node.edgeTag.curve.parent.parentGroup === this.extraGeometry) {
207170
+ if (node.isDangling || node.edgeMate.isDangling || !node.findAroundFace(node.edgeMate) || this.faceAreaFunction(node) < 0.0) {
207171
+ toHeal.push(node.vertexSuccessor);
207172
+ toHeal.push(node.edgeMate.vertexSuccessor);
207173
+ node.isolateEdge();
207174
+ }
207175
+ else {
207176
+ interiorBridges.push(node);
207177
+ }
207178
+ }
207179
+ }
207180
+ }
207181
+ }
207182
+ }
207183
+ return true;
207184
+ });
207185
+ // At this point, all bridges that were exterior are isolated, but this may have caused formerly
207186
+ // interior bridges to become exterior. Now we successively isolate exterior bridges until none remain.
207187
+ let numIsolatedThisPass;
207188
+ do {
207189
+ numIsolatedThisPass = 0;
207190
+ for (const node of interiorBridges) {
207191
+ if (!node.isIsolatedEdge && isExteriorEdge(node)) {
207192
+ toHeal.push(node.vertexSuccessor);
207193
+ toHeal.push(node.edgeMate.vertexSuccessor);
207194
+ node.isolateEdge();
207195
+ numIsolatedThisPass++;
207196
+ }
207197
+ }
207198
+ } while (numIsolatedThisPass > 0);
207199
+ // lambda to extend the detail interval on a side of a healed edge
207200
+ const mergeDetails = (he, newFraction, newPoint) => {
207201
+ if (he && he.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && he.sortData !== undefined && newFraction !== undefined && newPoint) {
207202
+ if (he.sortData > 0)
207203
+ he.edgeTag.captureFraction1Point1(newFraction, newPoint);
207204
+ else
207205
+ he.edgeTag.captureFractionPoint(newFraction, newPoint);
207206
+ }
207207
+ };
207208
+ // At this point all removable bridges are isolated. Clean up their original vertex loops, if possible.
207209
+ for (const doomedA of toHeal) {
207210
+ const doomedB = doomedA.vertexSuccessor;
207211
+ if ( // are the geometries mergeable?
207212
+ doomedA !== doomedB &&
207213
+ doomedA.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && doomedA.sortData !== undefined &&
207214
+ doomedB.edgeTag instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail && doomedB.sortData !== undefined &&
207215
+ doomedA.edgeTag.curve === doomedB.edgeTag.curve &&
207216
+ doomedA.edgeTag.hasFraction1 && doomedB.edgeTag.hasFraction1 &&
207217
+ doomedA.sortData * doomedB.sortData < 0 &&
207218
+ ((doomedA.sortData > 0 && _Geometry__WEBPACK_IMPORTED_MODULE_7__.Geometry.isSmallRelative(doomedA.edgeTag.fraction - doomedB.edgeTag.fraction1)) ||
207219
+ (doomedA.sortData < 0 && _Geometry__WEBPACK_IMPORTED_MODULE_7__.Geometry.isSmallRelative(doomedA.edgeTag.fraction1 - doomedB.edgeTag.fraction)))) {
207220
+ const survivorA = _topology_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdge.healEdge(doomedA, false);
207221
+ if (survivorA) {
207222
+ const endFractionA = (doomedA.sortData > 0) ? doomedA.edgeTag.fraction1 : doomedA.edgeTag.fraction;
207223
+ const endPointA = (doomedA.sortData > 0) ? doomedA.edgeTag.point1 : doomedA.edgeTag.point;
207224
+ mergeDetails(survivorA, endFractionA, endPointA);
207225
+ const endFractionB = (doomedB.sortData > 0) ? doomedB.edgeTag.fraction1 : doomedB.edgeTag.fraction;
207226
+ const endPointB = (doomedB.sortData > 0) ? doomedB.edgeTag.point1 : doomedB.edgeTag.point;
207227
+ mergeDetails(survivorA.edgeMate, endFractionB, endPointB);
207228
+ }
207229
+ }
207230
+ }
207231
+ return this.graph.deleteIsolatedEdges();
207232
+ }
206905
207233
  /**
206906
207234
  * Markup and assembly steps for geometry in the RegionGroups.
206907
207235
  * * Annotate connection from group to curves.
@@ -206923,10 +207251,11 @@ class RegionBooleanContext {
206923
207251
  }
206924
207252
  }
206925
207253
  }
206926
- const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_16__.CurveCurve.allIntersectionsAmongPrimitivesXY(allPrimitives, mergeTolerance);
206927
- const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_17__.PlanarSubdivision.assembleHalfEdgeGraph(allPrimitives, intersections, mergeTolerance);
207254
+ const intersections = _CurveCurve__WEBPACK_IMPORTED_MODULE_17__.CurveCurve.allIntersectionsAmongPrimitivesXY(allPrimitives, mergeTolerance);
207255
+ const graph = _Query_PlanarSubdivision__WEBPACK_IMPORTED_MODULE_18__.PlanarSubdivision.assembleHalfEdgeGraph(allPrimitives, intersections, mergeTolerance);
206928
207256
  this.graph = graph;
206929
207257
  this.faceAreaFunction = faceAreaFromCurvedEdgeData;
207258
+ this.removeExtraneousBridgeEdges();
206930
207259
  }
206931
207260
  _announceFaceFunction;
206932
207261
  /**
@@ -207014,7 +207343,7 @@ class RegionBooleanContext {
207014
207343
  const data = node.edgeTag;
207015
207344
  if (data instanceof RegionGroupMember)
207016
207345
  return updateRegionGroupMemberState(data);
207017
- if (data instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_18__.CurveLocationDetail) {
207346
+ if (data instanceof _CurveLocationDetail__WEBPACK_IMPORTED_MODULE_16__.CurveLocationDetail) {
207018
207347
  // We trust that the caller has linked from the graph node to a curve which has a RegionGroupMember as its parent.
207019
207348
  const member = data.curve.parent;
207020
207349
  if (member instanceof RegionGroupMember)
@@ -208784,23 +209113,23 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
208784
209113
  let reversed = false;
208785
209114
  const uu = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.hypotenuseSquaredXY(ux, uy);
208786
209115
  if (hab0 * hab0 <= maxDistanceSquared * uu) { // test distance of b0 to u
208787
- const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e00x, e00y) / uu;
209116
+ const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e00x, e00y), uu, 0.0);
208788
209117
  if (this.updatePointToSegmentDistance(0, b0, a0, a1, fractionA, maxDistanceSquared, closestApproach))
208789
209118
  reversed = true;
208790
209119
  }
208791
209120
  if (hab1 * hab1 <= maxDistanceSquared * uu) { // test distance of b1 to u
208792
- const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e01x, e01y) / uu;
209121
+ const fractionA = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(ux, uy, e01x, e01y), uu, 0.0);
208793
209122
  if (this.updatePointToSegmentDistance(1, b1, a0, a1, fractionA, maxDistanceSquared, closestApproach))
208794
209123
  reversed = true;
208795
209124
  }
208796
209125
  const vv = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.hypotenuseSquaredXY(vx, vy);
208797
209126
  if (hba0 * hba0 <= maxDistanceSquared * vv) { // test distance of a0 to v
208798
- const fractionB = -_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e00x, e00y) / vv;
209127
+ const fractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(-_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e00x, e00y), vv, 0.0);
208799
209128
  if (this.updatePointToSegmentDistance(0, a0, b0, b1, fractionB, maxDistanceSquared, closestApproach))
208800
209129
  reversed = false;
208801
209130
  }
208802
209131
  if (hba1 * hba1 <= maxDistanceSquared * vv) { // test distance of a1 to v
208803
- const fractionB = -_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e10x, e10y) / vv;
209132
+ const fractionB = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.safeDivideFraction(-_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(vx, vy, e10x, e10y), vv, 0.0);
208804
209133
  if (this.updatePointToSegmentDistance(1, a1, b0, b1, fractionB, maxDistanceSquared, closestApproach))
208805
209134
  reversed = false;
208806
209135
  }
@@ -208878,7 +209207,7 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
208878
209207
  return undefined;
208879
209208
  }
208880
209209
  /**
208881
- * Find the closest approach between `pointA` and `cpB`. Add the approach if it's within `fB0` and `fB1`.
209210
+ * Find the closest xy approach between `pointA` and `cpB`. Add the approach if it's within `fB0` and `fB1`.
208882
209211
  * * Does not test the endpoints of `cpB`.
208883
209212
  * * The only types supported for `cpB` are Arc3d, LineSegment3d, and LineString3d.
208884
209213
  * * If `cpB` is a LineString3d, then the interval `[fB0, fB1]` must correspond to a segment of the line string.
@@ -208903,7 +209232,7 @@ class CurveCurveCloseApproachXY extends _geometry3d_GeometryHandler__WEBPACK_IMP
208903
209232
  }
208904
209233
  }
208905
209234
  /**
208906
- * Compute intersection of two line segments.
209235
+ * Compute closest xy approach of two line segments.
208907
209236
  * Filter by extension rules.
208908
209237
  * Record with fraction mapping.
208909
209238
  * * The fraction mappings allow portions of a linestring to be passed here.
@@ -217179,7 +217508,7 @@ class AngleSweep {
217179
217508
  result.setStartEndRadians(startRadians, endRadians);
217180
217509
  return result;
217181
217510
  }
217182
- /** Return the angle obtained by subtracting radians from this angle. */
217511
+ /** Return the AngleSweep obtained by subtracting radians from the start and end angles of this sweep. */
217183
217512
  cloneMinusRadians(radians) {
217184
217513
  return new AngleSweep(this._radians0 - radians, this._radians1 - radians);
217185
217514
  }
@@ -218870,7 +219199,7 @@ __webpack_require__.r(__webpack_exports__);
218870
219199
  * For the equator circle, phi=0, cos(phi) = 1, sin(phi)=0
218871
219200
  * f = u * cos(theta) + v * sin(theta).
218872
219201
  * with derivative
218873
- * df / dTheta = = u * sin(theta) + v * cos(theta)
219202
+ * df / dTheta = - u * sin(theta) + v * cos(theta)
218874
219203
  * whose zero is tan(theta) = v/u
218875
219204
  * (and that has two solutions 180 degrees apart)
218876
219205
  * Then with that theta let A = u * cos(theta) + v * sin(theta)
@@ -223526,6 +223855,7 @@ class IndexedXYZCollection {
223526
223855
  * @param index0 index of first point
223527
223856
  * @param index1 index of second point
223528
223857
  * @param tolerance max coordinate difference to be considered equal. For exact test, pass 0. Defaults to `Geometry.smallMetricDistance`.
223858
+ * @returns whether the points are equal within tolerance, or `undefined` if either index is invalid.
223529
223859
  */
223530
223860
  almostEqualIndexIndex(index0, index1, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
223531
223861
  if (index0 < 0 || index0 >= this.length || index1 < 0 || index1 >= this.length)
@@ -223534,6 +223864,19 @@ class IndexedXYZCollection {
223534
223864
  && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getYAtUncheckedPointIndex(index0), this.getYAtUncheckedPointIndex(index1), tolerance)
223535
223865
  && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getZAtUncheckedPointIndex(index0), this.getZAtUncheckedPointIndex(index1), tolerance);
223536
223866
  }
223867
+ /**
223868
+ * Test whether the xy-coordinates of the indexed points are equal within tolerance. The z-coordinates are ignored.
223869
+ * @param index0 index of first point
223870
+ * @param index1 index of second point
223871
+ * @param tolerance max coordinate difference to be considered equal. For exact test, pass 0. Defaults to `Geometry.smallMetricDistance`.
223872
+ * @returns whether the xy-coordinates of the points are equal within tolerance, or `undefined` if either index is invalid.
223873
+ */
223874
+ almostEqualXYIndexIndex(index0, index1, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
223875
+ if (index0 < 0 || index0 >= this.length || index1 < 0 || index1 >= this.length)
223876
+ return undefined;
223877
+ return _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getXAtUncheckedPointIndex(index0), this.getXAtUncheckedPointIndex(index1), tolerance)
223878
+ && _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isSameCoordinate(this.getYAtUncheckedPointIndex(index0), this.getYAtUncheckedPointIndex(index1), tolerance);
223879
+ }
223537
223880
  }
223538
223881
  /**
223539
223882
  * abstract base class extends IndexedXYZCollection, adding methods to push, peek, and pop, and rewrite.
@@ -236072,13 +236415,11 @@ class Ray3d {
236072
236415
  return new Ray3d(_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.createZero(), _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.createZero());
236073
236416
  }
236074
236417
  /**
236075
- * Test for nearly equal Ray3d objects.
236076
- * * This tests for near equality of origin and direction -- i.e. member-by-member comparison.
236077
- * * Use [[isAlmostEqualPointSet]] to allow origins to be anywhere along the common ray and to have to allow the
236078
- * directions to be scaled or opposing.
236418
+ * Test for nearly equal Ray3d objects by comparing their origin and direction members.
236419
+ * @see [[isAlmostEqualPointSet]] to test for rays on the same infinite line.
236079
236420
  */
236080
- isAlmostEqual(other) {
236081
- return this.origin.isAlmostEqual(other.origin) && this.direction.isAlmostEqual(other.direction);
236421
+ isAlmostEqual(other, tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistance) {
236422
+ return this.origin.isAlmostEqual(other.origin, tolerance) && this.direction.isAlmostEqual(other.direction, tolerance);
236082
236423
  }
236083
236424
  /**
236084
236425
  * Return the dot product of the ray's direction vector with a vector from the ray origin
@@ -236106,27 +236447,19 @@ class Ray3d {
236106
236447
  return this.origin.plusScaled(this.direction, this.pointToFraction(spacePoint));
236107
236448
  }
236108
236449
  /**
236109
- * Test for nearly equal rays, allowing origin float and direction scaling.
236110
- * * Use [[isAlmostEqual]] to require member-by-member comparison.
236450
+ * Test for rays that describe the same infinite line.
236451
+ * @see [[isAlmostEqual]] for member-by-member comparison.
236111
236452
  */
236112
- isAlmostEqualPointSet(other) {
236113
- /**
236114
- * This function tests two rays to determine if they define the same infinite lines.
236115
- * So the origins can be different as long as they are on the infinite line (they can
236116
- * "float") but the directions must be parallel or antiparallel.
236117
- */
236118
- if (!this.direction.isParallelTo(other.direction, true))
236453
+ isAlmostEqualPointSet(other, options) {
236454
+ if (!this.direction.isParallelTo(other.direction, true, false, options))
236119
236455
  return false;
236120
- /**
236121
- * In exact math, we consider a ray to have an infinite line as direction (not a finite vector).
236122
- * Therefore, in exact math it is not possible for one origin to be on the other ray but not vice
236123
- * versa. However, we test both ways because first check may pass due to round-off errors.
236124
- */
236456
+ const tol2 = options?.distanceSquaredTol ?? _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.smallMetricDistanceSquared;
236457
+ // theoretically, one test below is sufficient, but perform both in case the first passes because of round-off
236125
236458
  let workPoint = this.projectPointToRay(other.origin);
236126
- if (!other.origin.isAlmostEqualMetric(workPoint))
236459
+ if (other.origin.distanceSquared(workPoint) > tol2)
236127
236460
  return false;
236128
236461
  workPoint = other.projectPointToRay(this.origin);
236129
- if (!this.origin.isAlmostEqualMetric(workPoint))
236462
+ if (this.origin.distanceSquared(workPoint) > tol2)
236130
236463
  return false;
236131
236464
  return true;
236132
236465
  }
@@ -236821,19 +237154,26 @@ __webpack_require__.r(__webpack_exports__);
236821
237154
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
236822
237155
  /* harmony export */ SortablePolygon: () => (/* binding */ SortablePolygon)
236823
237156
  /* harmony export */ });
236824
- /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
236825
- /* harmony import */ var _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../curve/CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
236826
- /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
236827
- /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
236828
- /* harmony import */ var _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../curve/ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
236829
- /* harmony import */ var _curve_RegionOps__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
236830
- /* harmony import */ var _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../curve/UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
236831
- /* harmony import */ var _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
236832
- /* harmony import */ var _PolygonOps__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
237157
+ /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
237158
+ /* harmony import */ var _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../curve/CurvePrimitive */ "../../core/geometry/lib/esm/curve/CurvePrimitive.js");
237159
+ /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
237160
+ /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
237161
+ /* harmony import */ var _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../curve/ParityRegion */ "../../core/geometry/lib/esm/curve/ParityRegion.js");
237162
+ /* harmony import */ var _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../curve/RegionOps */ "../../core/geometry/lib/esm/curve/RegionOps.js");
237163
+ /* harmony import */ var _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../curve/UnionRegion */ "../../core/geometry/lib/esm/curve/UnionRegion.js");
237164
+ /* harmony import */ var _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./IndexedXYZCollection */ "../../core/geometry/lib/esm/geometry3d/IndexedXYZCollection.js");
237165
+ /* harmony import */ var _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
237166
+ /* harmony import */ var _PolygonOps__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
237167
+ /* harmony import */ var _Ray3d__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
236833
237168
  /*---------------------------------------------------------------------------------------------
236834
237169
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
236835
237170
  * See LICENSE.md in the project root for license terms and full copyright notice.
236836
237171
  *--------------------------------------------------------------------------------------------*/
237172
+ /** @packageDocumentation
237173
+ * @module CartesianGeometry
237174
+ */
237175
+
237176
+
236837
237177
 
236838
237178
 
236839
237179
 
@@ -236843,14 +237183,36 @@ __webpack_require__.r(__webpack_exports__);
236843
237183
 
236844
237184
 
236845
237185
 
236846
- /** abstract base class for area-related queries of a loop.
236847
- * * subclasses have particular logic for `Loop` and polygon data.
237186
+ /** Abstract base class for area-related queries of an xy-loop.
237187
+ * * Subclasses have particular logic for `Loop` and polygon data.
236848
237188
  * @internal
236849
237189
  */
236850
237190
  class SimpleRegionCarrier {
237191
+ /** Fractions for interior point search. */
237192
+ searchFractions = [0.2349, 0.4142, 0.6587, 0.8193];
237193
+ /**
237194
+ * Given a region boundary tangent, construct a point interior to the region.
237195
+ * @param ray point and tangent on an edge of the region (modified on return)
237196
+ */
237197
+ constructInteriorPoint(ray) {
237198
+ ray.direction.z = 0.0;
237199
+ if (!ray.direction.normalizeInPlace())
237200
+ return undefined; // loop has zero length edge, or a vertical (gap) edge
237201
+ ray.direction.rotate90CCWXY(ray.direction);
237202
+ if (this.signedArea < 0.0)
237203
+ ray.direction.scaleInPlace(-1.0); // aim toward the region interior
237204
+ const refDistance = Math.sqrt(Math.abs(this.signedArea));
237205
+ const candidatePoint = _Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
237206
+ for (let fraction = 1.0e-5; fraction < 3; fraction *= 5.0) {
237207
+ ray.fractionToPoint(fraction * refDistance, candidatePoint);
237208
+ if (1 === this.classifyPointXY(candidatePoint))
237209
+ return candidatePoint;
237210
+ }
237211
+ return undefined;
237212
+ }
236851
237213
  }
236852
237214
  /**
236853
- * Implement `LoopCarrier` queries with the area as a polygon carried in an `IndexedReadWriteXYZCollection`
237215
+ * Implement `SimpleRegionCarrier` queries with the area as a polygon carried in an `IndexedReadWriteXYZCollection`.
236854
237216
  */
236855
237217
  class PolygonCarrier extends SimpleRegionCarrier {
236856
237218
  data;
@@ -236859,7 +237221,7 @@ class PolygonCarrier extends SimpleRegionCarrier {
236859
237221
  constructor(data) {
236860
237222
  super();
236861
237223
  this.data = data;
236862
- this._signedArea = _PolygonOps__WEBPACK_IMPORTED_MODULE_0__.PolygonOps.areaXY(data);
237224
+ this._signedArea = _PolygonOps__WEBPACK_IMPORTED_MODULE_1__.PolygonOps.areaXY(data);
236863
237225
  }
236864
237226
  /**
236865
237227
  * classify xy parts of point wrt this loop.
@@ -236867,22 +237229,22 @@ class PolygonCarrier extends SimpleRegionCarrier {
236867
237229
  * @internal
236868
237230
  */
236869
237231
  classifyPointXY(xy) {
236870
- return _PolygonOps__WEBPACK_IMPORTED_MODULE_0__.PolygonOps.classifyPointInPolygonXY(xy.x, xy.y, this.data);
237232
+ return _PolygonOps__WEBPACK_IMPORTED_MODULE_1__.PolygonOps.classifyPointInPolygonXY(xy.x, xy.y, this.data);
236871
237233
  }
236872
- /** Return some point "inside"
236873
- * NEEDS WORK: this returns a point ON --
236874
- */
237234
+ /** Return some point "inside". */
236875
237235
  getAnyInteriorPoint() {
236876
237236
  for (let childIndex = 0; childIndex < this.data.length; childIndex++) {
236877
- const q = this.constructInteriorPointNearEdge(childIndex, 0.2349);
236878
- if (q !== undefined)
236879
- return q;
237237
+ for (const fraction of this.searchFractions) {
237238
+ const q = this.constructInteriorPointNearEdge(childIndex, fraction);
237239
+ if (q !== undefined)
237240
+ return q;
237241
+ }
236880
237242
  }
236881
237243
  return undefined;
236882
237244
  }
236883
237245
  grabPolygon() { return this.data; }
236884
237246
  grabLoop() {
236885
- return _curve_Loop__WEBPACK_IMPORTED_MODULE_1__.Loop.createPolygon(this.data);
237247
+ return _curve_Loop__WEBPACK_IMPORTED_MODULE_2__.Loop.createPolygon(this.data);
236886
237248
  }
236887
237249
  reverseForAreaSign(targetSign) {
236888
237250
  if (targetSign * this._signedArea < 0.0) {
@@ -236892,27 +237254,14 @@ class PolygonCarrier extends SimpleRegionCarrier {
236892
237254
  }
236893
237255
  constructInteriorPointNearEdge(edgeIndex, fractionAlong) {
236894
237256
  if (edgeIndex + 1 < this.data.length) {
236895
- const point0 = this.data.getPoint3dAtUncheckedPointIndex(edgeIndex);
236896
- const point1 = this.data.getPoint3dAtUncheckedPointIndex(edgeIndex + 1);
236897
- const vector = point0.vectorTo(point1);
236898
- const point = point0.interpolate(fractionAlong, point1);
236899
- vector.rotate90CCWXY(vector);
236900
- if (vector.normalizeInPlace()) {
236901
- if (this._signedArea < 0)
236902
- vector.scaleInPlace(-1.0);
236903
- const refDistance = Math.sqrt(Math.abs(this._signedArea));
236904
- for (let fraction = 1.0e-5; fraction < 3; fraction *= 5.0) {
236905
- const candidatePoint = point.plusScaled(vector, fraction * refDistance);
236906
- if (1 === this.classifyPointXY(candidatePoint))
236907
- return candidatePoint;
236908
- }
236909
- }
237257
+ const ray = _Ray3d__WEBPACK_IMPORTED_MODULE_3__.Ray3d.createCapture(this.data.interpolateIndexIndex(edgeIndex, fractionAlong, edgeIndex + 1), this.data.vectorIndexIndex(edgeIndex, edgeIndex + 1));
237258
+ return this.constructInteriorPoint(ray);
236910
237259
  }
236911
237260
  return undefined;
236912
237261
  }
236913
237262
  }
236914
237263
  /**
236915
- * Implement `LoopCarrier` queries with the area as a strongly typed `Loop`
237264
+ * Implement `SimpleRegionCarrier` queries with the area as a strongly typed `Loop`.
236916
237265
  */
236917
237266
  class LoopCarrier extends SimpleRegionCarrier {
236918
237267
  data;
@@ -236921,7 +237270,7 @@ class LoopCarrier extends SimpleRegionCarrier {
236921
237270
  constructor(data) {
236922
237271
  super();
236923
237272
  this.data = data;
236924
- const areaMoments = _curve_RegionOps__WEBPACK_IMPORTED_MODULE_2__.RegionOps.computeXYAreaMoments(data);
237273
+ const areaMoments = _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.computeXYAreaMoments(data);
236925
237274
  this._signedArea = areaMoments !== undefined ? areaMoments.quantitySum : 0.0;
236926
237275
  }
236927
237276
  /**
@@ -236930,41 +237279,32 @@ class LoopCarrier extends SimpleRegionCarrier {
236930
237279
  * @internal
236931
237280
  */
236932
237281
  classifyPointXY(xy) {
236933
- return _curve_RegionOps__WEBPACK_IMPORTED_MODULE_2__.RegionOps.testPointInOnOutRegionXY(this.data, xy.x, xy.y);
237282
+ return _curve_RegionOps__WEBPACK_IMPORTED_MODULE_4__.RegionOps.testPointInOnOutRegionXY(this.data, xy.x, xy.y);
236934
237283
  }
236935
237284
  constructInteriorPointNearChild(childIndex, fractionAlong) {
236936
237285
  if (childIndex < this.data.children.length) {
236937
- const primitive = this.data.children[childIndex];
236938
- const ray = primitive.fractionToPointAndUnitTangent(fractionAlong);
236939
- ray.direction.rotate90CCWXY(ray.direction);
236940
- if (this._signedArea < 0.0)
236941
- ray.direction.scaleInPlace(-1.0);
236942
- const refDistance = Math.sqrt(Math.abs(this._signedArea));
236943
- for (let fraction = 1.0e-5; fraction < 3; fraction *= 5.0) {
236944
- const candidatePoint = ray.fractionToPoint(fraction * refDistance);
236945
- if (1 === this.classifyPointXY(candidatePoint))
236946
- return candidatePoint;
236947
- }
237286
+ const ray = this.data.children[childIndex].fractionToPointAndDerivative(fractionAlong);
237287
+ return this.constructInteriorPoint(ray);
236948
237288
  }
236949
237289
  return undefined;
236950
237290
  }
236951
- /** Return some point "inside"
236952
- * NEEDS WORK: this returns a point ON --
236953
- */
237291
+ /** Return some point "inside". */
236954
237292
  getAnyInteriorPoint() {
236955
237293
  for (let childIndex = 0; childIndex < this.data.children.length; childIndex++) {
236956
- const q = this.constructInteriorPointNearChild(childIndex, 0.2349);
236957
- if (q !== undefined)
236958
- return q;
237294
+ for (const fraction of this.searchFractions) {
237295
+ const q = this.constructInteriorPointNearChild(childIndex, fraction);
237296
+ if (q !== undefined)
237297
+ return q;
237298
+ }
236959
237299
  }
236960
237300
  return undefined;
236961
237301
  }
236962
237302
  grabPolygon() {
236963
237303
  const strokes = this.data.cloneStroked();
236964
- if (strokes instanceof _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.CurveChain) {
236965
- const linestring = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_4__.LineString3d.create();
237304
+ if (strokes instanceof _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_5__.CurveChain) {
237305
+ const linestring = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_6__.LineString3d.create();
236966
237306
  for (const child of strokes.children) {
236967
- if (child instanceof _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_5__.CurvePrimitive) {
237307
+ if (child instanceof _curve_CurvePrimitive__WEBPACK_IMPORTED_MODULE_7__.CurvePrimitive) {
236968
237308
  child.emitStrokes(linestring);
236969
237309
  }
236970
237310
  }
@@ -236983,7 +237323,7 @@ class LoopCarrier extends SimpleRegionCarrier {
236983
237323
  }
236984
237324
  }
236985
237325
  /**
236986
- * A `SortablePolygon` carries a (single) loop with data useful for sorting for inner-outer structure.
237326
+ * A `SortablePolygon` carries a (single) xy-loop with data useful for sorting for inner-outer structure.
236987
237327
  * @internal
236988
237328
  */
236989
237329
  class SortablePolygon {
@@ -236999,7 +237339,7 @@ class SortablePolygon {
236999
237339
  * @param loop Loop to capture.
237000
237340
  */
237001
237341
  constructor(loop, range) {
237002
- if (loop instanceof _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_6__.IndexedReadWriteXYZCollection)
237342
+ if (loop instanceof _IndexedXYZCollection__WEBPACK_IMPORTED_MODULE_8__.IndexedReadWriteXYZCollection)
237003
237343
  this._loopCarrier = new PolygonCarrier(loop);
237004
237344
  else
237005
237345
  this._loopCarrier = new LoopCarrier(loop);
@@ -237104,7 +237444,7 @@ class SortablePolygon {
237104
237444
  const childData = loops[childIndex];
237105
237445
  if (childData.parentIndex === candidateIndex) {
237106
237446
  if (candidateParityRegion === undefined) {
237107
- candidateParityRegion = _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_7__.ParityRegion.create();
237447
+ candidateParityRegion = _curve_ParityRegion__WEBPACK_IMPORTED_MODULE_9__.ParityRegion.create();
237108
237448
  candidateParityRegion.tryAddChild(candidateLoop);
237109
237449
  childData._loopCarrier.reverseForAreaSign(-1.0);
237110
237450
  candidateParityRegion.tryAddChild(childData._loopCarrier.grabLoop());
@@ -237129,7 +237469,7 @@ class SortablePolygon {
237129
237469
  if (regions.length === 1)
237130
237470
  return regions[0];
237131
237471
  else {
237132
- const unionRegion = _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_8__.UnionRegion.create();
237472
+ const unionRegion = _curve_UnionRegion__WEBPACK_IMPORTED_MODULE_10__.UnionRegion.create();
237133
237473
  for (const region of regions)
237134
237474
  unionRegion.tryAddChild(region);
237135
237475
  return unionRegion;
@@ -250814,7 +251154,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
250814
251154
  /** Construct facets for a rotational sweep. */
250815
251155
  addRotationalSweep(surface) {
250816
251156
  const contour = surface.getSweepContourRef();
250817
- const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour.getCurves(), this._options);
251157
+ const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour.getCurves(), this._options);
250818
251158
  const baseStrokes = section0.getStrokes();
250819
251159
  // ensure sweep is positive for buildRotationalNormalsInLineStrings
250820
251160
  const axis = surface.cloneAxisRay();
@@ -250964,7 +251304,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
250964
251304
  /** Add facets from the linear sweep. */
250965
251305
  addLinearSweep(surface) {
250966
251306
  const contour = surface.getCurvesRef();
250967
- const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour, this._options);
251307
+ const section0 = _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour, this._options);
250968
251308
  const stroke0 = section0.getStrokes();
250969
251309
  const sweepVector = surface.cloneSweepVector();
250970
251310
  const sweepTransform = _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_9__.Transform.createTranslation(sweepVector);
@@ -250986,7 +251326,7 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
250986
251326
  let stroke1;
250987
251327
  const sectionMaps = [];
250988
251328
  for (const contour of contours)
250989
- sectionMaps.push(_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.createForParityRegionOrChain(contour.curves, this._options));
251329
+ sectionMaps.push(_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.create(contour.curves, this._options));
250990
251330
  if (_curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.enforceStrokeCountCompatibility(sectionMaps)) {
250991
251331
  _curve_Query_StrokeCountChain__WEBPACK_IMPORTED_MODULE_16__.StrokeCountSection.enforceCompatibleDistanceSums(sectionMaps);
250992
251332
  for (let i = 0; i < contours.length; i++) {
@@ -272521,7 +272861,7 @@ class Sphere extends _SolidPrimitive__WEBPACK_IMPORTED_MODULE_0__.SolidPrimitive
272521
272861
  const sinTheta = Math.sin(thetaRadians);
272522
272862
  const sinPhi = Math.sin(phiRadians);
272523
272863
  const cosPhi = Math.cos(phiRadians);
272524
- 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.
272864
+ 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
272525
272865
  this._localToWorld.matrix.multiplyXYZ(-fPhi * cosTheta * sinPhi, -fPhi * sinTheta * sinPhi, fPhi * cosPhi), result);
272526
272866
  }
272527
272867
  /**
@@ -272776,7 +273116,7 @@ class SweepContour {
272776
273116
  /**
272777
273117
  * Emit facets to a function.
272778
273118
  * This method may cache and reuse facets over multiple calls.
272779
- * @param announce callback to receive the facet set.
273119
+ * @param announce callback to receive the facet set. Called only once (if facets exist).
272780
273120
  * @param options how to stroke the contour.
272781
273121
  */
272782
273122
  announceFacets(announce, options) {
@@ -273542,13 +273882,14 @@ __webpack_require__.r(__webpack_exports__);
273542
273882
  /* harmony export */ HalfEdgeGraph: () => (/* binding */ HalfEdgeGraph),
273543
273883
  /* harmony export */ HalfEdgeMask: () => (/* binding */ HalfEdgeMask)
273544
273884
  /* harmony export */ });
273545
- /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
273546
- /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
273547
- /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
273548
- /* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
273549
- /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
273550
- /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
273551
- /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
273885
+ /* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
273886
+ /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
273887
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
273888
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
273889
+ /* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
273890
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
273891
+ /* harmony import */ var _numerics_SmallSystem__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../numerics/SmallSystem */ "../../core/geometry/lib/esm/numerics/SmallSystem.js");
273892
+ /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
273552
273893
  /*---------------------------------------------------------------------------------------------
273553
273894
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
273554
273895
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -273563,9 +273904,9 @@ __webpack_require__.r(__webpack_exports__);
273563
273904
 
273564
273905
 
273565
273906
 
273907
+
273566
273908
  // import { GraphChecker } from "../test/topology/Graph.test"; // used for debugging
273567
273909
  /* eslint-disable @typescript-eslint/no-this-alias */
273568
- // cspell:word CONSTU CONSTV USEAM VSEAM internaldocs
273569
273910
  /**
273570
273911
  * * Each node of the graph has a mask member.
273571
273912
  * * The mask member is a number which is used as set of single bit boolean values.
@@ -273580,14 +273921,6 @@ __webpack_require__.r(__webpack_exports__);
273580
273921
  */
273581
273922
  var HalfEdgeMask;
273582
273923
  (function (HalfEdgeMask) {
273583
- // REMARK: Various mask names are COMMENTED here for reference to native legacy code.
273584
- // CONSTU_MASK = 0x00000004,
273585
- // CONSTV_MASK = 0x00000008,
273586
- // USEAM_MASK = 0x00000010,
273587
- // VSEAM_MASK = 0x00000020,
273588
- // BOUNDARY_VERTEX_MASK = 0x00000040,
273589
- // PRIMARY_VERTEX_MASK = 0x00000080,
273590
- // DIRECTED_EDGE_MASK = 0x00000100,
273591
273924
  /**
273592
273925
  * Mask commonly set consistently around exterior faces.
273593
273926
  * * A boundary edge with interior to one side, exterior to the other, will have EXTERIOR only on the outside.
@@ -273610,22 +273943,22 @@ var HalfEdgeMask;
273610
273943
  * BOUNDARY_EDGE nor EXTERIOR_EDGE.
273611
273944
  */
273612
273945
  HalfEdgeMask[HalfEdgeMask["PRIMARY_EDGE"] = 4] = "PRIMARY_EDGE";
273613
- /** Mask used for low level searches to identify previously-visited nodes. */
273614
- HalfEdgeMask[HalfEdgeMask["VISITED"] = 16] = "VISITED";
273946
+ /** Mask set on both sides of a bridge edge added by algorithms to join loops. */
273947
+ HalfEdgeMask[HalfEdgeMask["BRIDGE_EDGE"] = 8] = "BRIDGE_EDGE";
273948
+ /** Mask set on both sides of an edge added during graph regularization. */
273949
+ HalfEdgeMask[HalfEdgeMask["REGULARIZED_EDGE"] = 16] = "REGULARIZED_EDGE";
273615
273950
  /** Mask applied to triangles by earcut triangulator. */
273616
273951
  HalfEdgeMask[HalfEdgeMask["TRIANGULATED_FACE"] = 256] = "TRIANGULATED_FACE";
273617
273952
  /** Mask applied in a face with 2 edges. */
273618
273953
  HalfEdgeMask[HalfEdgeMask["NULL_FACE"] = 512] = "NULL_FACE";
273954
+ /** Temporary mask used for low level searches to identify previously-visited nodes. */
273955
+ HalfEdgeMask[HalfEdgeMask["VISITED"] = 65536] = "VISITED";
273619
273956
  /** No mask bits. */
273620
273957
  HalfEdgeMask[HalfEdgeMask["NULL_MASK"] = 0] = "NULL_MASK";
273621
273958
  /** The "upper 12" bits of 32 bit integer reserved for grab/drop. */
273622
273959
  HalfEdgeMask[HalfEdgeMask["ALL_GRAB_DROP_MASKS"] = 4293918720] = "ALL_GRAB_DROP_MASKS";
273623
273960
  /** All mask bits */
273624
273961
  HalfEdgeMask[HalfEdgeMask["ALL_MASK"] = 4294967295] = "ALL_MASK";
273625
- // informal convention on preassigned mask bit numbers:
273626
- // byte0 (EXTERIOR, BOUNDARY_EDGE, PRIMARY_EDGE) -- edge properties
273627
- // byte1 (VISITED, VISIT_A, WORK_MASK0, WORK_MASK1) -- temp masks for algorithms.
273628
- // byte2 (TRIANGULATED_FACE, NULL_FACE) -- face properties.
273629
273962
  })(HalfEdgeMask || (HalfEdgeMask = {}));
273630
273963
  /**
273631
273964
  * A HalfEdge is "one side of an edge" in a structure of faces, edges and vertices. From a node there are
@@ -273821,6 +274154,37 @@ class HalfEdge {
273821
274154
  }
273822
274155
  return newA;
273823
274156
  }
274157
+ /**
274158
+ * Reverse of [[splitEdge]]: remove the vertex at `doomed` and merge its two incident edges.
274159
+ * @param doomed one of two nodes added by [[splitEdge]]. These nodes should form a vertex loop of two nodes.
274160
+ * On successful return this node and its mate are isolated.
274161
+ * @param checkParallel whether to check that the doomed edge and the preceding edge in its face loop are parallel.
274162
+ * When passing `true` the assumption is that edge geometry is linear. If nonlinear edge geometry is attached, the
274163
+ * caller should a) verify that the geometry on either side of the doomed vertex can be merged, and if so, they
274164
+ * should b) call this method passing `false`, and c) adjust the geometry of the returned edge and its edge mate
274165
+ * as appropriate.
274166
+ * @returns the former (surviving) face predecessor of `doomed`, or undefined if the edge can't be healed.
274167
+ */
274168
+ static healEdge(doomed, checkParallel = true) {
274169
+ if (doomed.isIsolatedEdge)
274170
+ return undefined;
274171
+ const doomed1 = doomed.vertexSuccessor;
274172
+ if (doomed1.vertexSuccessor !== doomed)
274173
+ return undefined; // v-loop not a 2-cycle
274174
+ if (checkParallel && !doomed.vectorToFaceSuccessor().isParallelTo(doomed.facePredecessor.vectorToFaceSuccessor(), false, true))
274175
+ return undefined; // removing this vertex does not leave a straight edge behind
274176
+ const fPred = doomed.facePredecessor;
274177
+ const fSucc = doomed.faceSuccessor;
274178
+ const fPred1 = doomed1.facePredecessor;
274179
+ const fSucc1 = doomed1.faceSuccessor;
274180
+ this.setFaceLinks(fPred, fSucc);
274181
+ this.setFaceLinks(fPred1, fSucc1);
274182
+ this.setEdgeMates(fPred, fPred1);
274183
+ this.setFaceLinks(doomed, doomed1);
274184
+ this.setFaceLinks(doomed1, doomed);
274185
+ this.setEdgeMates(doomed, doomed1);
274186
+ return fPred;
274187
+ }
273824
274188
  /**
273825
274189
  * Create a new sliver face "inside" an existing edge.
273826
274190
  * * This creates two nodes that are each face predecessor and successor to the other.
@@ -273848,14 +274212,14 @@ class HalfEdge {
273848
274212
  newB.copyDataFrom(baseB, true, true, false, false);
273849
274213
  return newA;
273850
274214
  }
273851
- /** Edge property masks. */
274215
+ /** Masks copied when an edge is split. */
273852
274216
  static _edgePropertyMasks = [
273853
- HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.NULL_FACE,
274217
+ HalfEdgeMask.EXTERIOR, HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.BRIDGE_EDGE, HalfEdgeMask.REGULARIZED_EDGE, HalfEdgeMask.NULL_FACE
273854
274218
  ];
273855
274219
  /**
273856
274220
  * Copy "edge based" content of `fromNode` to `toNode`:
273857
274221
  * * edgeTag
273858
- * * masks EXTERIOR, BOUNDARY_EDGE, NULL_FACE, PRIMARY_EDGE
274222
+ * * edge masks
273859
274223
  */
273860
274224
  static transferEdgeProperties(fromNode, toNode) {
273861
274225
  toNode.edgeTag = fromNode.edgeTag;
@@ -274028,7 +274392,7 @@ class HalfEdge {
274028
274392
  /**
274029
274393
  * Returns the number of nodes that match (or do not match) the given mask value around this face loop.
274030
274394
  * @param mask the mask to check.
274031
- * @param value true for mask match and false for mask not match.
274395
+ * @param value true for mask match and false for mask not match. Default is `true`.
274032
274396
  */
274033
274397
  countMaskAroundFace(mask, value = true) {
274034
274398
  let count = 0;
@@ -274075,16 +274439,17 @@ class HalfEdge {
274075
274439
  }
274076
274440
  /**
274077
274441
  * Returns the first node that matches (or does not match) the given mask value around this vertex loop, starting
274078
- * with the instance node and proceeding via vertex successors.
274442
+ * with the instance node and proceeding via `vertexSuccessor`.
274079
274443
  * @param mask the mask to check.
274080
- * @param value true for mask match and false for mask not match.
274444
+ * @param value true for mask match and false for mask not match. Default is `true`.
274445
+ * @param reverse if true, search in reverse order via `vertexPredecessor`. Default is `false`.
274081
274446
  */
274082
- findMaskAroundVertex(mask, value = true) {
274447
+ findMaskAroundVertex(mask, value = true, reverse = false) {
274083
274448
  let node = this;
274084
274449
  do {
274085
274450
  if (node.isMaskSet(mask) === value)
274086
274451
  return node;
274087
- node = node.vertexSuccessor;
274452
+ node = reverse ? node.vertexPredecessor : node.vertexSuccessor;
274088
274453
  } while (node !== this);
274089
274454
  return undefined;
274090
274455
  }
@@ -274092,7 +274457,7 @@ class HalfEdge {
274092
274457
  * Returns the first node that matches (or does not match) the given mask value around this face loop, starting
274093
274458
  * with the instance node and proceeding via face successors.
274094
274459
  * @param mask the mask to check.
274095
- * @param value true for mask match and false for mask not match.
274460
+ * @param value true for mask match and false for mask not match. Default is `true`.
274096
274461
  */
274097
274462
  findMaskAroundFace(mask, value = true) {
274098
274463
  let node = this;
@@ -274204,6 +274569,10 @@ class HalfEdge {
274204
274569
  predA._faceSuccessor = nodeB;
274205
274570
  }
274206
274571
  }
274572
+ /** Return whether the edge is dangling at its base. */
274573
+ get isDangling() {
274574
+ return this.edgeMate.faceSuccessor === this;
274575
+ }
274207
274576
  /**
274208
274577
  * Pinch this half edge out of its base vertex loop.
274209
274578
  * @return the surviving HalfEdge in the vertex loop or `undefined` if the instance HalfEdge is already dangling.
@@ -274273,17 +274642,17 @@ class HalfEdge {
274273
274642
  }
274274
274643
  /** Return Vector2d from `this` to face successor (with only xy coordinates). */
274275
274644
  vectorToFaceSuccessorXY(result) {
274276
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create(this.faceSuccessor.x - this.x, this.faceSuccessor.y - this.y, result);
274645
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create(this.faceSuccessor.x - this.x, this.faceSuccessor.y - this.y, result);
274277
274646
  }
274278
274647
  /** Return Vector3d from `this` to face successor. */
274279
274648
  vectorToFaceSuccessor(result) {
274280
274649
  const other = this.faceSuccessor;
274281
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
274650
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
274282
274651
  }
274283
274652
  /** Return Vector3d from `this` to face successor. */
274284
274653
  vectorToFacePredecessor(result) {
274285
274654
  const other = this.facePredecessor;
274286
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
274655
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
274287
274656
  }
274288
274657
  /**
274289
274658
  * Test if `spaceNode` is in the sector of `sectorNode`.
@@ -274334,15 +274703,15 @@ class HalfEdge {
274334
274703
  }
274335
274704
  /** Returns 2D cross product of vectors from `base` to `targetA` and from `base` to `targetB`. */
274336
274705
  static crossProductXYToTargets(base, targetA, targetB) {
274337
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.crossProductXYXY(targetA.x - base.x, targetA.y - base.y, targetB.x - base.x, targetB.y - base.y);
274706
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.crossProductXYXY(targetA.x - base.x, targetA.y - base.y, targetB.x - base.x, targetB.y - base.y);
274338
274707
  }
274339
274708
  /** Returns 2D dot product of vectors from `baseA` to `targetA` and from `baseB` to `targetB`. */
274340
274709
  static dotProductNodeToNodeVectorsXY(baseA, targetA, baseB, targetB) {
274341
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.dotProductXYXY(targetA.x - baseA.x, targetA.y - baseA.y, targetB.x - baseB.x, targetB.y - baseB.y);
274710
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.dotProductXYXY(targetA.x - baseA.x, targetA.y - baseA.y, targetB.x - baseB.x, targetB.y - baseB.y);
274342
274711
  }
274343
274712
  /** Return 2D cross product of vectors from `nodeA` to `nodeB` and from `nodeB` to `nodeC`. */
274344
274713
  static crossProductXYAlongChain(nodeA, nodeB, nodeC) {
274345
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.crossProductXYXY(nodeB.x - nodeA.x, nodeB.y - nodeA.y, nodeC.x - nodeB.x, nodeC.y - nodeB.y);
274714
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.crossProductXYXY(nodeB.x - nodeA.x, nodeB.y - nodeA.y, nodeC.x - nodeB.x, nodeC.y - nodeB.y);
274346
274715
  }
274347
274716
  /**
274348
274717
  * Compute whether the sector defined by the chain of nodes is convex.
@@ -274379,7 +274748,7 @@ class HalfEdge {
274379
274748
  */
274380
274749
  isSectorConvex(signedAreaTol) {
274381
274750
  if (signedAreaTol === undefined)
274382
- signedAreaTol = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistanceSquared * this.signedFaceArea();
274751
+ signedAreaTol = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistanceSquared * this.signedFaceArea();
274383
274752
  return HalfEdge.isSectorConvex(this.facePredecessor, this, this.faceSuccessor, signedAreaTol);
274384
274753
  }
274385
274754
  /**
@@ -274391,7 +274760,7 @@ class HalfEdge {
274391
274760
  * `Geometry.smallMetricDistanceSquared`. Pass 0 to skip toleranced computation.
274392
274761
  * @returns true iff this face is convex.
274393
274762
  */
274394
- isFaceConvex(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistanceSquared) {
274763
+ isFaceConvex(tolerance = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.smallMetricDistanceSquared) {
274395
274764
  let node = this;
274396
274765
  const signedAreaTol = tolerance > 0.0 ? tolerance * node.signedFaceArea() : 0.0;
274397
274766
  do {
@@ -274407,7 +274776,10 @@ class HalfEdge {
274407
274776
  this.yankFromVertexLoop();
274408
274777
  mate.yankFromVertexLoop();
274409
274778
  }
274410
- /** Specify whether this edge is isolated from the rest of the graph. */
274779
+ /**
274780
+ * Specify whether this edge is isolated from the rest of the graph.
274781
+ * * Both edge mates of an isolated edge return true for [[isDangling]].
274782
+ */
274411
274783
  get isIsolatedEdge() {
274412
274784
  return this === this.vertexSuccessor && this.edgeMate === this.edgeMate.vertexSuccessor;
274413
274785
  }
@@ -274437,7 +274809,7 @@ class HalfEdge {
274437
274809
  static sectorSweepRadiansXYZ(node, normal) {
274438
274810
  const suc = node.faceSuccessor;
274439
274811
  const pred = node.facePredecessor;
274440
- 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);
274812
+ 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);
274441
274813
  }
274442
274814
  /** Returns true if the face has positive area in xy parts. */
274443
274815
  static testFacePositiveAreaXY(node) {
@@ -274449,11 +274821,76 @@ class HalfEdge {
274449
274821
  }
274450
274822
  /** Return distance between xy coordinates of `this` and `other` node. */
274451
274823
  distanceXY(other) {
274452
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.distanceXYXY(this.x, this.y, other.x, other.y);
274824
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.distanceXYXY(this.x, this.y, other.x, other.y);
274453
274825
  }
274454
274826
  /** Return distance between xyz coordinates of `this` and `other` node. */
274455
274827
  distanceXYZ(other) {
274456
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.distanceXYZXYZ(this.x, this.y, this.z, other.x, other.y, other.z);
274828
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.distanceXYZXYZ(this.x, this.y, this.z, other.x, other.y, other.z);
274829
+ }
274830
+ /**
274831
+ * Search around the instance's face loop for nodes with the specified mask value.
274832
+ * * Returned nodes satisfy `node.isMaskSet(mask) === value`.
274833
+ * @param mask target mask.
274834
+ * @param value target boolean value for mask on half edges (default `true`).
274835
+ * @param result optional array to be cleared, populated with masked nodes, and returned.
274836
+ * @return array of masked half edges
274837
+ */
274838
+ collectMaskedEdgesAroundFace(mask, value = true, result) {
274839
+ if (result === undefined)
274840
+ result = [];
274841
+ else
274842
+ result.length = 0;
274843
+ let node = this;
274844
+ do {
274845
+ if (node.isMaskSet(mask) === value)
274846
+ result.push(node);
274847
+ node = node.faceSuccessor;
274848
+ } while (node !== this);
274849
+ return result;
274850
+ }
274851
+ /**
274852
+ * Announce edges in the face loop, starting with the instance and proceeding in a `faceSuccessor` traversal.
274853
+ * @param announceEdge function to call at each edge
274854
+ */
274855
+ announceEdgesInFace(announceEdge) {
274856
+ let node = this;
274857
+ do {
274858
+ announceEdge(node);
274859
+ node = node.faceSuccessor;
274860
+ } while (node !== this);
274861
+ }
274862
+ /**
274863
+ * Announce edges in the super face loop, starting with the instance.
274864
+ * * 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.
274865
+ * @param skipMask mask on edges to skip.
274866
+ * @param announceEdge function to call at each edge that is not skipped.
274867
+ * @param announceSkipped optional function to call at each edge that is skipped.
274868
+ * @return whether a super face was found. Specifically, if a vertex loop has all edges with `skipMask` set, the return value is `false`.
274869
+ */
274870
+ announceEdgesInSuperFace(skipMask, announceEdge, announceSkipped) {
274871
+ const maxIter = 1000; // safeguard against infinite loops
274872
+ let iter = 0;
274873
+ const findNextNodeAroundVertex = (he) => {
274874
+ let vNode = he;
274875
+ do {
274876
+ if (!vNode.isMaskSet(skipMask))
274877
+ return vNode;
274878
+ announceSkipped?.(vNode);
274879
+ vNode = vNode.vertexPredecessor;
274880
+ } while (vNode !== he);
274881
+ return undefined;
274882
+ };
274883
+ const firstNode = findNextNodeAroundVertex(this);
274884
+ if (!firstNode)
274885
+ return false;
274886
+ let node = firstNode;
274887
+ do {
274888
+ announceEdge(node);
274889
+ node = findNextNodeAroundVertex(node.faceSuccessor);
274890
+ if (!node)
274891
+ return false;
274892
+ } while (node !== firstNode && iter++ < maxIter);
274893
+ return iter < maxIter;
274457
274894
  }
274458
274895
  /**
274459
274896
  * Evaluate `f(node)` at each node around `this` node's face loop. Collect the function values.
@@ -274594,7 +275031,7 @@ class HalfEdge {
274594
275031
  */
274595
275032
  fractionToPoint2d(fraction, result) {
274596
275033
  const suc = this.faceSuccessor;
274597
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Point2d.create(this.x + (suc.x - this.x) * fraction, this.y + (suc.y - this.y) * fraction, result);
275034
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(this.x + (suc.x - this.x) * fraction, this.y + (suc.y - this.y) * fraction, result);
274598
275035
  }
274599
275036
  /**
274600
275037
  * Interpolate xyz coordinates between `this` node and its face successor.
@@ -274603,7 +275040,7 @@ class HalfEdge {
274603
275040
  */
274604
275041
  fractionToPoint3d(fraction, result) {
274605
275042
  const suc = this.faceSuccessor;
274606
- 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);
275043
+ 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);
274607
275044
  }
274608
275045
  /**
274609
275046
  * Interpolate xy coordinates at `fractionAlong` between this node and its face successor. Then shift perpendicular
@@ -274616,25 +275053,25 @@ class HalfEdge {
274616
275053
  const suc = this.faceSuccessor;
274617
275054
  const dx = suc.x - this.x;
274618
275055
  const dy = suc.y - this.y;
274619
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Point2d.create(this.x + dx * fractionAlong - dy * fractionPerpendicular, this.y + dy * fractionAlong + dx * fractionPerpendicular, result);
275056
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(this.x + dx * fractionAlong - dy * fractionPerpendicular, this.y + dy * fractionAlong + dx * fractionPerpendicular, result);
274620
275057
  }
274621
275058
  /** Return the 3d coordinates at this half edge. */
274622
275059
  getPoint3d(result) {
274623
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(this.x, this.y, this.z, result);
275060
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Point3d.create(this.x, this.y, this.z, result);
274624
275061
  }
274625
275062
  /** Return the 2d coordinates at this half edge. */
274626
275063
  getPoint2d(result) {
274627
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Point2d.create(this.x, this.y, result);
275064
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(this.x, this.y, result);
274628
275065
  }
274629
275066
  /** Return a 3d vector from start to end of this half edge. */
274630
275067
  getVector3dAlongEdge(result) {
274631
275068
  const suc = this.faceSuccessor;
274632
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(suc.x - this.x, suc.y - this.y, suc.z - this.z, result);
275069
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_2__.Vector3d.create(suc.x - this.x, suc.y - this.y, suc.z - this.z, result);
274633
275070
  }
274634
275071
  /** Return a 2d vector from start to end of this half edge. */
274635
275072
  getVector2dAlongEdge(result) {
274636
275073
  const suc = this.faceSuccessor;
274637
- return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create(suc.x - this.x, suc.y - this.y, result);
275074
+ return _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create(suc.x - this.x, suc.y - this.y, result);
274638
275075
  }
274639
275076
  /**
274640
275077
  * Return the interpolated x coordinate between `this` node and its face successor.
@@ -274672,12 +275109,12 @@ class HalfEdge {
274672
275109
  const nodeA1 = nodeA0.faceSuccessor;
274673
275110
  const nodeB1 = nodeB0.faceSuccessor;
274674
275111
  if (!result)
274675
- result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create();
275112
+ result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_1__.Vector2d.create();
274676
275113
  // To find the fraction of intersection (ta,tb), you need to solve these 2 equations:
274677
275114
  // (nodeA1.x - nodeA0.x)ta + (nodeB0.x - nodeB1.x)tb = nodeB0.x - nodeA0.x
274678
275115
  // (nodeA1.y - nodeA0.y)ta + (nodeB0.y - nodeB1.y)tb = nodeB0.y - nodeA0.y
274679
275116
  // Proof can be found at geometry/internaldocs/Graph.md
274680
- 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))
275117
+ 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))
274681
275118
  return result;
274682
275119
  return undefined;
274683
275120
  }
@@ -274691,13 +275128,13 @@ class HalfEdge {
274691
275128
  static horizontalScanFraction(node0, y) {
274692
275129
  const node1 = node0.faceSuccessor;
274693
275130
  const dy = node1.y - node0.y;
274694
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(y, node1.y))
275131
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node1.y))
274695
275132
  return node0;
274696
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(dy, 0.0))
275133
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(dy, 0.0))
274697
275134
  return undefined;
274698
275135
  // parametric equation of line is (1-t)y0 + ty1 which is equal to y at the intersection so
274699
275136
  // (1-t)y0 + ty1 = y or t = (y-y0)/(y1-y0)
274700
- return _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.conditionalDivideFraction(y - node0.y, dy);
275137
+ return _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.conditionalDivideFraction(y - node0.y, dy);
274701
275138
  }
274702
275139
  /**
274703
275140
  * Compute fractional position (inside 0..1) of the intersection of a horizontal line with an edge.
@@ -274709,11 +275146,11 @@ class HalfEdge {
274709
275146
  static horizontalScanFraction01(node0, y) {
274710
275147
  const node1 = node0.faceSuccessor;
274711
275148
  const dy = node1.y - node0.y;
274712
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(y, node1.y))
275149
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node0.y) && _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(y, node1.y))
274713
275150
  return undefined;
274714
- if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.isSameCoordinate(dy, 0.0))
275151
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.isSameCoordinate(dy, 0.0))
274715
275152
  return undefined;
274716
- const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.conditionalDivideFraction(y - node0.y, dy);
275153
+ const fraction = _Geometry__WEBPACK_IMPORTED_MODULE_3__.Geometry.conditionalDivideFraction(y - node0.y, dy);
274717
275154
  if (fraction !== undefined && fraction >= 0.0 && fraction <= 1.0)
274718
275155
  return fraction;
274719
275156
  return undefined;
@@ -274732,16 +275169,37 @@ class HalfEdge {
274732
275169
  this.y = source.y;
274733
275170
  this.z = source.z;
274734
275171
  }
274735
- if (copyVertexData) {
275172
+ if (copyVertexData)
274736
275173
  this.i = source.i;
274737
- }
274738
- if (copyEdgeData) {
275174
+ if (copyEdgeData)
274739
275175
  HalfEdge.transferEdgeProperties(source, this);
274740
- this.edgeTag = source.edgeTag;
274741
- }
274742
- if (copyFaceData) {
275176
+ if (copyFaceData)
274743
275177
  this.faceTag = source.faceTag;
275178
+ }
275179
+ /**
275180
+ * Is the instance's face loop a split-washer type face?
275181
+ * * A split-washer face contains at least one bridge edge.
275182
+ * * A bridge edge and its edge mate have the same `bridgeMask` and live in the same face loop.
275183
+ * * By connecting hole/outer loops with bridge edges, a split-washer face can represent a parity region.
275184
+ * @param bridgeMask mask preset on bridge edges (default is [[HalfEdgeMask.BRIDGE_EDGE]]).
275185
+ */
275186
+ isSplitWasherFace(bridgeMask = HalfEdgeMask.BRIDGE_EDGE) {
275187
+ if (!this.countMaskAroundFace(HalfEdgeMask.BRIDGE_EDGE))
275188
+ return false;
275189
+ const bridges = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.OrderedSet((a, b) => a.id - b.id);
275190
+ let node = this;
275191
+ do {
275192
+ if (node.isMaskSet(bridgeMask))
275193
+ bridges.add(node);
275194
+ node = node.faceSuccessor;
275195
+ } while (node !== this);
275196
+ if (bridges.size === 0)
275197
+ return false;
275198
+ for (const bridge of bridges) {
275199
+ if (!bridges.has(bridge.edgeMate) || !bridge.edgeMate.isMaskSet(bridgeMask))
275200
+ return false;
274744
275201
  }
275202
+ return true;
274745
275203
  }
274746
275204
  }
274747
275205
  /**
@@ -274757,11 +275215,11 @@ class HalfEdgeGraph {
274757
275215
  _numNodesCreated = 0;
274758
275216
  constructor() {
274759
275217
  this.allHalfEdges = [];
274760
- this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_5__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
275218
+ this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_6__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
274761
275219
  }
274762
275220
  /**
274763
275221
  * Ask for a mask (from the graph's free pool) for caller's use.
274764
- * * Optionally clear the mask throughout the graph.
275222
+ * @param clearInAllHalfEdges optionally clear the mask throughout the graph (default `true`).
274765
275223
  */
274766
275224
  grabMask(clearInAllHalfEdges = true) {
274767
275225
  const mask = this._maskManager.grabMask();
@@ -274927,7 +275385,7 @@ class HalfEdgeGraph {
274927
275385
  const segments = [];
274928
275386
  for (const node of this.allHalfEdges) {
274929
275387
  if (node.id < node.edgeMate.id)
274930
- 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)));
275388
+ 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)));
274931
275389
  }
274932
275390
  return segments;
274933
275391
  }
@@ -275415,8 +275873,8 @@ class HalfEdgeGraphSearch {
275415
275873
  * pattern starting at the seed face, with each successive concentric ring of faces at constant topological
275416
275874
  * distance from the seed face receiving the opposite parity state of the previous ring.
275417
275875
  * @param parityMask (optional) mask to apply to the first face and faces that share the same parity as the
275418
- * first face, as determined by the parity rule. If this is `NULL_MASK`, there is no record of parity. If
275419
- * (non-null) parity mask is given, on return it is entirely set or entirely clear around each face.
275876
+ * first face, as determined by the parity rule. If this is `NULL_MASK` (default), there is no record of parity.
275877
+ * If (non-null) parity mask is given, on return it is entirely set or entirely clear around each face.
275420
275878
  * @returns the components of the graph, each component represented by an array of nodes, one node per face
275421
275879
  * of the component. In other words, entry [i][j] is a HalfEdge in the j_th face loop of the i_th component.
275422
275880
  */
@@ -278174,8 +278632,9 @@ class RegularizationContext {
278174
278632
  if (nodeA1 !== undefined && nodeB1 !== undefined) {
278175
278633
  _Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(nodeA1, nodeC);
278176
278634
  _Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(nodeB1, nodeC.edgeMate);
278635
+ nodeC.setMaskAroundEdge(_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.REGULARIZED_EDGE);
278177
278636
  if (RegularizationContext.announceEdge)
278178
- RegularizationContext.announceEdge(this.graph, nodeA, nodeB, direction);
278637
+ RegularizationContext.announceEdge(this.graph, nodeC, nodeC.edgeMate, direction);
278179
278638
  return nodeC;
278180
278639
  }
278181
278640
  return undefined;
@@ -314171,7 +314630,7 @@ var loadLanguages = instance.loadLanguages;
314171
314630
  /***/ ((module) => {
314172
314631
 
314173
314632
  "use strict";
314174
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.1.0-dev.51","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s webpackWorkers && npm run -s copy:workers","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:workers":"cpx \\"./lib/workers/webpack/parse-imdl-worker.js\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run webpackTestWorker && vitest --run","cover":"npm run webpackTestWorker && vitest --run","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2 && npm run -s webpackTestWorker","webpackTestWorker":"webpack --config ./src/test/worker/webpack.config.js 1>&2 && cpx \\"./lib/test/test-worker.js\\" ./lib/test","webpackWorkers":"webpack --config ./src/workers/ImdlParser/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/eslint-plugin":"5.0.0-dev.1","@types/chai-as-promised":"^7","@types/sinon":"^17.0.2","@vitest/browser":"^3.0.6","@vitest/coverage-v8":"^3.0.6","cpx2":"^8.0.0","eslint":"^9.13.0","glob":"^10.3.12","playwright":"~1.47.1","rimraf":"^6.0.1","sinon":"^17.0.2","source-map-loader":"^5.0.0","typescript":"~5.6.2","typemoq":"^2.1.0","vitest":"^3.0.6","vite-multiple-assets":"^1.3.1","vite-plugin-static-copy":"2.2.0","webpack":"^5.97.1"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/cloud-agnostic-core":"^2.2.4","@itwin/object-storage-core":"^2.3.0","@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
314633
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.1.0-dev.53","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s webpackWorkers && npm run -s copy:workers","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:workers":"cpx \\"./lib/workers/webpack/parse-imdl-worker.js\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run webpackTestWorker && vitest --run","cover":"npm run webpackTestWorker && vitest --run","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2 && npm run -s webpackTestWorker","webpackTestWorker":"webpack --config ./src/test/worker/webpack.config.js 1>&2 && cpx \\"./lib/test/test-worker.js\\" ./lib/test","webpackWorkers":"webpack --config ./src/workers/ImdlParser/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/eslint-plugin":"5.0.0-dev.1","@types/chai-as-promised":"^7","@types/sinon":"^17.0.2","@vitest/browser":"^3.0.6","@vitest/coverage-v8":"^3.0.6","cpx2":"^8.0.0","eslint":"^9.13.0","glob":"^10.3.12","playwright":"~1.47.1","rimraf":"^6.0.1","sinon":"^17.0.2","source-map-loader":"^5.0.0","typescript":"~5.6.2","typemoq":"^2.1.0","vitest":"^3.0.6","vite-multiple-assets":"^1.3.1","vite-plugin-static-copy":"2.2.0","webpack":"^5.97.1"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/cloud-agnostic-core":"^2.2.4","@itwin/object-storage-core":"^2.3.0","@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
314175
314634
 
314176
314635
  /***/ })
314177
314636