@itwin/rpcinterface-full-stack-tests 4.0.0-dev.4 → 4.0.0-dev.7

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.
@@ -137065,15 +137065,6 @@ class Bundle {
137065
137065
  return undefined;
137066
137066
  }
137067
137067
  const colorTextures = [];
137068
- // Check if the system can render to a depth texture without a renderable color texture bound as well.
137069
- // If it cannot, add a renderable color texture to the framebuffer.
137070
- // MacOS Safari exhibited this behavior, which necessitated this code path.
137071
- if (!_System__WEBPACK_IMPORTED_MODULE_13__.System.instance.canRenderDepthWithoutColor) {
137072
- const colTex = _Texture__WEBPACK_IMPORTED_MODULE_14__.TextureHandle.createForAttachment(shadowMapWidth, shadowMapHeight, _GL__WEBPACK_IMPORTED_MODULE_8__.GL.Texture.Format.Rgba, pixelDataType);
137073
- if (undefined === colTex)
137074
- return undefined;
137075
- colorTextures.push(colTex);
137076
- }
137077
137068
  const fbo = _FrameBuffer__WEBPACK_IMPORTED_MODULE_7__.FrameBuffer.create(colorTextures, depthTextureHandle);
137078
137069
  if (undefined === fbo)
137079
137070
  return undefined;
@@ -138108,7 +138099,6 @@ class System extends _RenderSystem__WEBPACK_IMPORTED_MODULE_7__.RenderSystem {
138108
138099
  get maxTextureSize() { return this._capabilities.maxTextureSize; }
138109
138100
  get supportsCreateImageBitmap() { return this._capabilities.supportsCreateImageBitmap; }
138110
138101
  get maxRenderType() { return this._capabilities.maxRenderType; }
138111
- get canRenderDepthWithoutColor() { return this._capabilities.canRenderDepthWithoutColor; }
138112
138102
  get fragDepthDoesNotDisableEarlyZ() { return this._capabilities.driverBugs.fragDepthDoesNotDisableEarlyZ; }
138113
138103
  get maxAntialiasSamples() { return this._capabilities.maxAntialiasSamples; }
138114
138104
  get supportsNonPowerOf2Textures() { return this._capabilities.supportsNonPowerOf2Textures; }
@@ -158348,8 +158338,7 @@ class RealityTileTree extends _internal__WEBPACK_IMPORTED_MODULE_6__.TileTree {
158348
158338
  if (imageryTiles.length)
158349
158339
  this.logTiles("Imagery:", imageryTiles.values());
158350
158340
  }
158351
- if (context.missing.length === 0)
158352
- this.reportTileVisibility(args, selected);
158341
+ this.reportTileVisibility(args, selected);
158353
158342
  _IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.tileAdmin.addTilesForUser(args.context.viewport, selected, args.readyTiles);
158354
158343
  return selected;
158355
158344
  }
@@ -164617,16 +164606,21 @@ class ImageryMapTile extends _internal__WEBPACK_IMPORTED_MODULE_4__.RealityTile
164617
164606
  this.parent.setLeaf(); // Avoid traversing bing branches after no graphics is found.
164618
164607
  this.setIsReady();
164619
164608
  }
164620
- selectCartoDrapeTiles(drapeTiles, rectangleToDrape, drapePixelSize, args) {
164609
+ selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, rectangleToDrape, drapePixelSize, args) {
164621
164610
  // Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly.
164622
164611
  const isSmallerThanDrape = (this.rectangle.xLength() / this.maximumSize) < drapePixelSize;
164623
- if (this.isLeaf // Include leaves so tiles get stretched past max LOD levels.
164612
+ if ((this.isLeaf) // Include leaves so tiles get stretched past max LOD levels. (Only for base imagery layer)
164624
164613
  || isSmallerThanDrape
164625
164614
  || this._anyChildNotFound) {
164626
164615
  if (this.isOutOfLodRange) {
164627
164616
  drapeTiles.push(this);
164628
164617
  this.setIsReady();
164629
164618
  }
164619
+ else if (this.isLeaf && !isSmallerThanDrape && !this._anyChildNotFound) {
164620
+ // These tiles are selected because we are beyond the max LOD of the tile tree,
164621
+ // might be used to display "stretched" tiles instead of having blank.
164622
+ highResolutionReplacementTiles.push(this);
164623
+ }
164630
164624
  else {
164631
164625
  drapeTiles.push(this);
164632
164626
  }
@@ -164641,7 +164635,7 @@ class ImageryMapTile extends _internal__WEBPACK_IMPORTED_MODULE_4__.RealityTile
164641
164635
  for (const child of this.children) {
164642
164636
  const mapChild = child;
164643
164637
  if (mapChild.rectangle.intersectsRange(rectangleToDrape))
164644
- status = mapChild.selectCartoDrapeTiles(drapeTiles, rectangleToDrape, drapePixelSize, args);
164638
+ status = mapChild.selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, rectangleToDrape, drapePixelSize, args);
164645
164639
  if (_internal__WEBPACK_IMPORTED_MODULE_4__.TileTreeLoadStatus.Loaded !== status)
164646
164640
  break;
164647
164641
  }
@@ -164776,12 +164770,12 @@ class ImageryMapTileTree extends _internal__WEBPACK_IMPORTED_MODULE_4__.RealityT
164776
164770
  return [];
164777
164771
  }
164778
164772
  draw(_args) { (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(false); }
164779
- selectCartoDrapeTiles(drapeTiles, tileToDrape, args) {
164773
+ selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, tileToDrape, args) {
164780
164774
  const drapeRectangle = tileToDrape.rectangle.clone(ImageryMapTileTree._scratchDrapeRectangle);
164781
164775
  // Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly.
164782
164776
  const drapePixelSize = 1.05 * tileToDrape.rectangle.xLength() / tileToDrape.maximumSize;
164783
164777
  drapeRectangle.scaleAboutCenterInPlace(ImageryMapTileTree._drapeIntersectionScale); // Contract slightly to avoid draping adjacent or slivers.
164784
- return this.rootTile.selectCartoDrapeTiles(drapeTiles, drapeRectangle, drapePixelSize, args);
164778
+ return this.rootTile.selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, drapeRectangle, drapePixelSize, args);
164785
164779
  }
164786
164780
  cartoRectangleFromQuadId(quadId) { return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); }
164787
164781
  }
@@ -166140,6 +166134,13 @@ class MapTile extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTile {
166140
166134
  * @internal
166141
166135
  */
166142
166136
  get hiddenImageryTiles() { return this._hiddenTiles; }
166137
+ /** List of leafs tiles that have been selected as a replacement for missing high resolution tiles.
166138
+ * When this list is non-empty this means we are past the maximum LOD available of the tile tree.
166139
+ * By using those tiles, you are likely to get a display where tiles looks pixelated..
166140
+ * in some cases this is preferred to have no tile at all.
166141
+ * @internal
166142
+ */
166143
+ get highResolutionReplacementTiles() { return this._highResolutionReplacementTiles; }
166143
166144
  /** @internal */
166144
166145
  getRangeCorners(result) {
166145
166146
  return this._patch instanceof PlanarTilePatch ? this._patch.getRangeCorners(this.heightRange, result) : this.range.corners(result);
@@ -166412,6 +166413,9 @@ class MapTile extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTile {
166412
166413
  if (this._hiddenTiles) {
166413
166414
  this._hiddenTiles = undefined;
166414
166415
  }
166416
+ if (this._highResolutionReplacementTiles) {
166417
+ this._highResolutionReplacementTiles = undefined;
166418
+ }
166415
166419
  }
166416
166420
  /** @internal */
166417
166421
  produceGraphics() {
@@ -166503,12 +166507,26 @@ class MapTile extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTile {
166503
166507
  this.clearImageryTiles();
166504
166508
  this._imageryTiles = new Array();
166505
166509
  this._hiddenTiles = new Array();
166510
+ this._highResolutionReplacementTiles = new Array();
166506
166511
  for (const layerImageryTree of this.mapTree.layerImageryTrees) {
166507
- const tmpTiles = new Array();
166508
- if (_internal__WEBPACK_IMPORTED_MODULE_7__.TileTreeLoadStatus.Loaded !== layerImageryTree.tree.selectCartoDrapeTiles(tmpTiles, this, args)) {
166512
+ let tmpTiles = new Array();
166513
+ const tmpLeafTiles = new Array();
166514
+ if (_internal__WEBPACK_IMPORTED_MODULE_7__.TileTreeLoadStatus.Loaded !== layerImageryTree.tree.selectCartoDrapeTiles(tmpTiles, tmpLeafTiles, this, args)) {
166509
166515
  this._imageryTiles = undefined;
166510
166516
  return;
166511
166517
  }
166518
+ // When the base layer is zoomed-in beyond it's max resolution,
166519
+ // we display leaf tiles and stretched them if needed.
166520
+ // We don't want the same behavior non-base layers, in the case,
166521
+ // the layer will simply disappear past its max resolution.
166522
+ // Note: Replacement leaf tiles are kept as a mean to determine which
166523
+ // imagery tree has reached it's maximum zoom level.
166524
+ if (layerImageryTree.baseImageryLayer) {
166525
+ tmpTiles = [...tmpTiles, ...tmpLeafTiles];
166526
+ }
166527
+ else {
166528
+ this._highResolutionReplacementTiles = [...this._highResolutionReplacementTiles, ...tmpLeafTiles];
166529
+ }
166512
166530
  // MapTileTree might include a non-visible imagery tree, we need to check for that.
166513
166531
  if (layerImageryTree.settings.visible && !layerImageryTree.settings.allSubLayersInvisible) {
166514
166532
  for (const imageryTile of tmpTiles) {
@@ -167166,8 +167184,8 @@ class MapTileTree extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTileTree
167166
167184
  /** Add a new imagery tile tree / map-layer settings pair and initialize the imagery tile tree state.
167167
167185
  * @internal
167168
167186
  */
167169
- addImageryLayer(tree, settings, index) {
167170
- this.layerImageryTrees.push({ tree, settings });
167187
+ addImageryLayer(tree, settings, index, baseImageryLayer) {
167188
+ this.layerImageryTrees.push({ tree, settings, baseImageryLayer });
167171
167189
  this._layerSettings.set(tree.modelId, settings);
167172
167190
  if (!this._imageryTreeState.has(tree.modelId))
167173
167191
  this._imageryTreeState.set(tree.modelId, new _internal__WEBPACK_IMPORTED_MODULE_7__.ImageryTileTreeState());
@@ -167406,15 +167424,19 @@ class MapTileTree extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTileTree
167406
167424
  treeVisibility.reset();
167407
167425
  }
167408
167426
  }
167409
- let allTilesRead = true;
167410
167427
  for (const selectedTile of selected) {
167411
167428
  if (selectedTile instanceof _internal__WEBPACK_IMPORTED_MODULE_7__.MapTile) {
167412
- if (!selectedTile.isReady)
167413
- allTilesRead = false;
167414
167429
  let selectedImageryTiles = selectedTile.imageryTiles;
167415
167430
  if (selectedTile.hiddenImageryTiles) {
167416
167431
  selectedImageryTiles = selectedImageryTiles ? [...selectedImageryTiles, ...selectedTile.hiddenImageryTiles] : selectedTile.hiddenImageryTiles;
167417
167432
  }
167433
+ const leafTiles = selectedTile.highResolutionReplacementTiles;
167434
+ if (leafTiles) {
167435
+ for (const tile of leafTiles) {
167436
+ const treeState = this.getImageryTreeState(tile.tree.id);
167437
+ treeState === null || treeState === void 0 ? void 0 : treeState.setScaleRangeVisibility(false);
167438
+ }
167439
+ }
167418
167440
  if (selectedImageryTiles) {
167419
167441
  for (const selectedImageryTile of selectedImageryTiles) {
167420
167442
  const treeState = this.getImageryTreeState(selectedImageryTile.tree.id);
@@ -167430,8 +167452,6 @@ class MapTileTree extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTileTree
167430
167452
  }
167431
167453
  }
167432
167454
  }
167433
- if (!allTilesRead)
167434
- changes;
167435
167455
  for (const [treeId, prevState] of layersVisibilityBefore) {
167436
167456
  const newState = this.getImageryTreeState(treeId);
167437
167457
  if (newState) {
@@ -167808,8 +167828,9 @@ class MapTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_7__.TileTr
167808
167828
  const layerTree = layerTreeRef.treeOwner.load();
167809
167829
  if (undefined === layerTree)
167810
167830
  return false; // Not loaded yet.
167831
+ const baseImageryLayer = this._baseImageryLayerIncluded && (treeIndex === 0);
167811
167832
  if (layerTree instanceof _internal__WEBPACK_IMPORTED_MODULE_7__.ImageryMapTileTree) {
167812
- tree.addImageryLayer(layerTree, layerTreeRef.layerSettings, treeIndex);
167833
+ tree.addImageryLayer(layerTree, layerTreeRef.layerSettings, treeIndex, baseImageryLayer);
167813
167834
  }
167814
167835
  else if (layerTreeRef instanceof _internal__WEBPACK_IMPORTED_MODULE_7__.ModelMapLayerTileTreeReference)
167815
167836
  tree.addModelLayer(layerTreeRef, context);
@@ -194240,6 +194261,7 @@ __webpack_require__.r(__webpack_exports__);
194240
194261
  /* harmony export */ "NewtonEvaluatorRtoRD": () => (/* reexport safe */ _numerics_Newton__WEBPACK_IMPORTED_MODULE_51__.NewtonEvaluatorRtoRD),
194241
194262
  /* harmony export */ "NullGeometryHandler": () => (/* reexport safe */ _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_8__.NullGeometryHandler),
194242
194263
  /* harmony export */ "NumberArray": () => (/* reexport safe */ _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_23__.NumberArray),
194264
+ /* harmony export */ "OffsetMeshOptions": () => (/* reexport safe */ _polyface_PolyfaceQuery__WEBPACK_IMPORTED_MODULE_116__.OffsetMeshOptions),
194243
194265
  /* harmony export */ "OffsetOptions": () => (/* reexport safe */ _curve_internalContexts_PolygonOffsetContext__WEBPACK_IMPORTED_MODULE_79__.OffsetOptions),
194244
194266
  /* harmony export */ "Order2Bezier": () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_49__.Order2Bezier),
194245
194267
  /* harmony export */ "Order3Bezier": () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_49__.Order3Bezier),
@@ -196637,6 +196659,10 @@ class CurveChainWithDistanceIndex extends _curve_CurvePrimitive__WEBPACK_IMPORTE
196637
196659
  const fragment = this.chainDistanceToFragment(distanceAlongPath, true);
196638
196660
  const curveFraction = fragment.chainDistanceToAccurateChildFraction(distanceAlongPath, true);
196639
196661
  result = fragment.childCurve.fractionToPointAndDerivative(curveFraction, result);
196662
+ // Fractional arc length parameterization for the curve C is f=f(t)=s(t)/L, where
196663
+ // L is total length of C, f'=||C'||/L, and inverse t=t(f), t'=1/f'=L/||C'||.
196664
+ // Then d/df(C(t(f)))=C't'=C'L/||C'||. The fragment gave us C', so the
196665
+ // derivative we seek is just a scale away.
196640
196666
  const a = this._totalLength / result.direction.magnitude();
196641
196667
  result.direction.scaleInPlace(a);
196642
196668
  return result;
@@ -196662,23 +196688,26 @@ class CurveChainWithDistanceIndex extends _curve_CurvePrimitive__WEBPACK_IMPORTE
196662
196688
  * * vectorV is the second derivative, i.e.derivative of vectorU.
196663
196689
  */
196664
196690
  fractionToPointAnd2Derivatives(fraction, result) {
196665
- const totalLength = this._totalLength;
196666
- const distanceAlongPath = fraction * totalLength;
196691
+ const distanceAlongPath = fraction * this._totalLength;
196667
196692
  const fragment = this.chainDistanceToFragment(distanceAlongPath, true);
196668
196693
  const curveFraction = fragment.chainDistanceToAccurateChildFraction(distanceAlongPath, true);
196669
196694
  result = fragment.childCurve.fractionToPointAnd2Derivatives(curveFraction, result);
196670
196695
  if (!result)
196671
196696
  return undefined;
196672
- const dotUU = result.vectorU.magnitudeSquared();
196673
- const magU = Math.sqrt(dotUU);
196697
+ // See fractionToPointAndDerivative for derivation of d/df(C(t(f)))=L C'/||C'||.
196698
+ // For the 2nd deriv, use quotient rule, d/dt||x(t)||=x.x'/||x|| and ||x||^2=x.x :
196699
+ // d/df(C'(t(f))) = L d/df(C'/||C'||)
196700
+ // = L (||C'|| d/df(C') - C' d/df||C'||) / ||C'||^2
196701
+ // = L (||C'|| C" L/||C'|| - C' C'.C"/||C'|| L/||C'||) / ||C'||^2
196702
+ // = (L/||C'||)^2 (C" - C' C'.C"/C'.C' )
196703
+ // We have C' and C" from the fragment.
196704
+ const magU = result.vectorU.magnitude();
196705
+ const dotUU = magU * magU;
196674
196706
  const dotUV = result.vectorU.dotProduct(result.vectorV);
196675
- const duds = 1.0 / magU;
196676
- const a = duds * duds;
196677
- _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_5__.Vector3d.createAdd2Scaled(result.vectorV, a, result.vectorU, -a * dotUV / dotUU, result.vectorV); // IN PLACE update to vectorV.
196678
- result.vectorU.scale(duds);
196679
- // scale for 0..1 parameterization ....
196680
- result.vectorU.scaleInPlace(totalLength);
196681
- result.vectorV.scaleInPlace(totalLength * totalLength);
196707
+ result.vectorV.addScaledInPlace(result.vectorU, -dotUV / dotUU);
196708
+ const scale = this._totalLength / magU;
196709
+ result.vectorU.scaleInPlace(scale);
196710
+ result.vectorV.scaleInPlace(scale * scale);
196682
196711
  return result;
196683
196712
  }
196684
196713
  /** Attempt to transform in place.
@@ -196743,7 +196772,7 @@ class CurveChainWithDistanceIndex extends _curve_CurvePrimitive__WEBPACK_IMPORTE
196743
196772
  numCalls: this._numCalls,
196744
196773
  numTested: this._numTested,
196745
196774
  numAssigned: this._numAssigned,
196746
- numCandidate: this._numCandidate
196775
+ numCandidate: this._numCandidate,
196747
196776
  };
196748
196777
  if (clear) {
196749
196778
  this._numTested = this._numAssigned = this._numCandidate = 0;
@@ -212628,6 +212657,44 @@ class Angle {
212628
212657
  const uDotV = ux * vx + uy * vy + uz * vz;
212629
212658
  return Math.atan2(_Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.crossProductMagnitude(ux, uy, uz, vx, vy, vz), uDotV);
212630
212659
  }
212660
+ /**
212661
+ * * Returns the angle between two vectors, with the vectors given as xyz components, and an up vector to resolve angle to a full 2PI range.
212662
+ * * The returned angle is (-PI < radians <= PI) or (0 <= radians < 2 * PI)
212663
+ * * The angle is in the plane of the U and V vectors.
212664
+ * * The upVector determines a positive side of the plane but need not be strictly perpendicular to the plane.
212665
+ *
212666
+ * @param ux x component of vector u
212667
+ * @param uy y component of vector u
212668
+ * @param uz z component of vector u
212669
+ * @param vx x component of vector v
212670
+ * @param vy y component of vector v
212671
+ * @param vz z component of vector v
212672
+ * @param upVectorX x component of vector to positive side of plane.
212673
+ * @param upVectorY y component of vector to positive side of plane.
212674
+ * @param upVectorZ z component of vector to positive side of plane.
212675
+ * @param adjustToAllPositive if true, return strictly non-negative sweep (0 <= radians < 2*PI). If false, return signed (-PI < radians <= PI)
212676
+ */
212677
+ static orientedRadiansBetweenVectorsXYZ(ux, uy, uz, vx, vy, vz, upVectorX, upVectorY, upVectorZ, adjustToPositive = false) {
212678
+ const uDotV = ux * vx + uy * vy + uz * vz;
212679
+ const wx = uy * vz - uz * vy;
212680
+ const wy = uz * vx - ux * vz;
212681
+ const wz = ux * vy - uy * vx;
212682
+ const upDotW = upVectorX * wx + upVectorY * wy + upVectorZ * wz;
212683
+ const crossMagnitude = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.hypotenuseXYZ(wx, wy, wz);
212684
+ if (upDotW < 0.0) {
212685
+ if (adjustToPositive) {
212686
+ // The turn is greater than 180 degrees. Take a peculiarly oriented atan2 to get the excess-180 part as addition to PI.
212687
+ // This gives the smoothest numerical transition passing PI.
212688
+ return Math.PI + Math.atan2(crossMagnitude, -uDotV);
212689
+ }
212690
+ else {
212691
+ return -Math.atan2(crossMagnitude, uDotV);
212692
+ }
212693
+ }
212694
+ else {
212695
+ return Math.atan2(crossMagnitude, uDotV);
212696
+ }
212697
+ }
212631
212698
  /**
212632
212699
  * Add a multiple of a full circle angle (360 degrees, 2PI) in place.
212633
212700
  * @param multiple multiplier factor
@@ -222328,9 +222395,12 @@ __webpack_require__.r(__webpack_exports__);
222328
222395
  * @module CartesianGeometry
222329
222396
  */
222330
222397
  // cspell:word CWXY
222398
+ // cspell:word arctan
222399
+ // cspell:word Rodrigues
222331
222400
 
222332
222401
 
222333
222402
 
222403
+ // cspell:word CCWXY
222334
222404
  /**
222335
222405
  * * `XYZ` is a minimal object containing x,y,z and operations that are meaningful without change in both point and vector.
222336
222406
  * * `XYZ` is not instantiable.
@@ -223673,18 +223743,17 @@ class Vector3d extends XYZ {
223673
223743
  else
223674
223744
  return theta;
223675
223745
  }
223676
- /**
223677
- * Return the (strongly typed Angle) angle from this vector to vectorB, measured in the plane containing both,
223678
- * with vectorW indicating which side to view to control sign of the angle.
223679
- * * The returned angle can range from negative 180 degrees (negative PI radians) to positive 180 degrees
223680
- * * (positive PI radians), not closed on the negative side.
223681
- * * The returned angle is "in the plane containing the two vectors"
223682
- * * `vectorW` distinguishes between the sides of the plane, but does not have to be perpendicular.
223683
- * * The returned angle has the same sign as vectorW dot product (thisVector cross vectorB)
223684
- * * Use planarRadiansTo to measure the angle between vectors that are projected to another plane.
223685
- * @param vectorB target vector.
223686
- * @param vectorW distinguishes between the sides of the plane.
223687
- */
223746
+ /** Return the (strongly typed Angle) angle from this vector to vectorB, measured in the plane containing both,
223747
+ * with vectorW indicating which side to view to control sign of the angle.
223748
+ * * The returned angle can range from negative 180 degrees (negative PI radians) to positive 180 degrees
223749
+ * * (positive PI radians), not closed on the negative side.
223750
+ * * The returned angle is "in the plane containing the two vectors"
223751
+ * * `vectorW` distinguishes between the sides of the plane, but does not have to be perpendicular.
223752
+ * * The returned angle has the same sign as vectorW dot product (thisVector cross vectorB)
223753
+ * * Use planarRadiansTo to measure the angle between vectors that are projected to another plane.
223754
+ * @param vectorB target vector.
223755
+ * @param vectorW distinguishes between the sides of the plane.
223756
+ */
223688
223757
  signedAngleTo(vectorB, vectorW) {
223689
223758
  return _Angle__WEBPACK_IMPORTED_MODULE_2__.Angle.createRadians(this.signedRadiansTo(vectorB, vectorW));
223690
223759
  }
@@ -236421,6 +236490,20 @@ class SmallSystem {
236421
236490
  }
236422
236491
  return undefined;
236423
236492
  }
236493
+ /**
236494
+ * Compute the intersection of three planes.
236495
+ * @param xyzA point on the first plane
236496
+ * @param normalA normal of the first plane
236497
+ * @param xyzB point on the second plane
236498
+ * @param normalB normal of the second plane
236499
+ * @param xyzC point on the third plane
236500
+ * @param normalC normal of the third plane
236501
+ * @param result optional result
236502
+ * @returns intersection point of the three planes (as a Vector3d), or undefined if at least two planes are parallel.
236503
+ */
236504
+ static intersect3Planes(xyzA, normalA, xyzB, normalB, xyzC, normalC, result) {
236505
+ return this.linearSystem3d(normalA.x, normalA.y, normalA.z, normalB.x, normalB.y, normalB.z, normalC.x, normalC.y, normalC.z, _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzA.x, xyzA.y, xyzA.z, normalA.x, normalA.y, normalA.z), _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzB.x, xyzB.y, xyzB.z, normalB.x, normalB.y, normalB.z), _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzC.x, xyzC.y, xyzC.z, normalC.x, normalC.y, normalC.z), result);
236506
+ }
236424
236507
  /**
236425
236508
  * * in rowB, replace `rowB[j] += a * rowB[pivot] * rowA[j] / rowA[pivot]` for `j>pivot`
236426
236509
  * @param rowA row that does not change
@@ -240532,10 +240615,29 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
240532
240615
  if (sector.uv)
240533
240616
  sector.uvIndex = this._polyface.addParam(sector.uv);
240534
240617
  }
240618
+ addSectorTriangle(sectorA0, sectorA1, sectorA2) {
240619
+ if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz)
240620
+ || sectorA1.xyz.isAlmostEqual(sectorA2.xyz)
240621
+ || sectorA2.xyz.isAlmostEqual(sectorA0.xyz)) {
240622
+ // trivially degenerate triangle !!! skip !!!
240623
+ }
240624
+ else {
240625
+ if (this._options.needNormals)
240626
+ this.addIndexedTriangleNormalIndexes(sectorA0.normalIndex, sectorA1.normalIndex, sectorA2.normalIndex);
240627
+ if (this._options.needParams)
240628
+ this.addIndexedTriangleParamIndexes(sectorA0.uvIndex, sectorA1.uvIndex, sectorA2.uvIndex);
240629
+ this.addIndexedTrianglePointIndexes(sectorA0.xyzIndex, sectorA1.xyzIndex, sectorA2.xyzIndex);
240630
+ this._polyface.terminateFacet();
240631
+ }
240632
+ }
240535
240633
  addSectorQuadA01B01(sectorA0, sectorA1, sectorB0, sectorB1) {
240536
240634
  if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz) && sectorB0.xyz.isAlmostEqual(sectorB1.xyz)) {
240537
240635
  // ignore null quad !!
240538
240636
  }
240637
+ else if (this._options.shouldTriangulate) {
240638
+ this.addSectorTriangle(sectorA0, sectorA1, sectorB1);
240639
+ this.addSectorTriangle(sectorB1, sectorB0, sectorA0);
240640
+ }
240539
240641
  else {
240540
240642
  if (this._options.needNormals)
240541
240643
  this.addIndexedQuadNormalIndexes(sectorA0.normalIndex, sectorA1.normalIndex, sectorB0.normalIndex, sectorB1.normalIndex);
@@ -240612,12 +240714,30 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
240612
240714
  }
240613
240715
  const numPoints = pointA.length;
240614
240716
  for (let i = 1; i < numPoints; i++) {
240615
- if (pointA.atUncheckedIndex(i - 1) !== pointA.atUncheckedIndex(i) || pointB.atUncheckedIndex(i - 1) !== pointB.atUncheckedIndex(i)) {
240616
- this.addIndexedQuadPointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i));
240617
- if (normalA && normalB)
240618
- this.addIndexedQuadNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i));
240619
- if (paramA && paramB)
240620
- this.addIndexedQuadParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i));
240717
+ if (this.options.shouldTriangulate) {
240718
+ if (distinctIndices(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i))) {
240719
+ this.addIndexedTrianglePointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i));
240720
+ if (normalA && normalB)
240721
+ this.addIndexedTriangleNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1));
240722
+ if (paramA && paramB)
240723
+ this.addIndexedTriangleParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1));
240724
+ }
240725
+ if (distinctIndices(pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i - 1))) {
240726
+ this.addIndexedTrianglePointIndexes(pointA.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1));
240727
+ if (normalA && normalB)
240728
+ this.addIndexedTriangleNormalIndexes(normalA.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1));
240729
+ if (paramA && paramB)
240730
+ this.addIndexedTriangleParamIndexes(paramA.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1));
240731
+ }
240732
+ }
240733
+ else {
240734
+ if (pointA.atUncheckedIndex(i - 1) !== pointA.atUncheckedIndex(i) || pointB.atUncheckedIndex(i - 1) !== pointB.atUncheckedIndex(i)) {
240735
+ this.addIndexedQuadPointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i));
240736
+ if (normalA && normalB)
240737
+ this.addIndexedQuadNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i));
240738
+ if (paramA && paramB)
240739
+ this.addIndexedQuadParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i));
240740
+ }
240621
240741
  this._polyface.terminateFacet();
240622
240742
  }
240623
240743
  }
@@ -241614,6 +241734,9 @@ function resolveToIndexedXYZCollectionOrCarrier(points) {
241614
241734
  return points.packedPoints;
241615
241735
  return points;
241616
241736
  }
241737
+ function distinctIndices(i0, i1, i2) {
241738
+ return i0 !== i1 && i1 !== i2 && i2 !== i0;
241739
+ }
241617
241740
 
241618
241741
 
241619
241742
  /***/ }),
@@ -242782,38 +242905,41 @@ function compressUnusedGrowableXYZArray(data: GrowableXYZArray, indices: number[
242782
242905
  __webpack_require__.r(__webpack_exports__);
242783
242906
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
242784
242907
  /* harmony export */ "DuplicateFacetClusterSelector": () => (/* binding */ DuplicateFacetClusterSelector),
242908
+ /* harmony export */ "OffsetMeshOptions": () => (/* binding */ OffsetMeshOptions),
242785
242909
  /* harmony export */ "PolyfaceQuery": () => (/* binding */ PolyfaceQuery)
242786
242910
  /* harmony export */ });
242787
242911
  /* harmony import */ var _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../geometry3d/PointHelpers */ "../../core/geometry/lib/esm/geometry3d/PointHelpers.js");
242788
- /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
242912
+ /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
242789
242913
  /* harmony import */ var _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../curve/internalContexts/MultiChainCollector */ "../../core/geometry/lib/esm/curve/internalContexts/MultiChainCollector.js");
242790
- /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
242791
- /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
242792
- /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
242914
+ /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
242915
+ /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
242916
+ /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
242793
242917
  /* harmony import */ var _curve_StrokeOptions__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../curve/StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
242794
- /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
242795
- /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
242918
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
242919
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
242796
242920
  /* harmony import */ var _geometry3d_FrameBuilder__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../geometry3d/FrameBuilder */ "../../core/geometry/lib/esm/geometry3d/FrameBuilder.js");
242797
- /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
242798
- /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
242921
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
242922
+ /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
242799
242923
  /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
242800
- /* harmony import */ var _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../geometry4d/Matrix4d */ "../../core/geometry/lib/esm/geometry4d/Matrix4d.js");
242801
- /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
242802
- /* harmony import */ var _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../numerics/UnionFind */ "../../core/geometry/lib/esm/numerics/UnionFind.js");
242924
+ /* harmony import */ var _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../geometry4d/Matrix4d */ "../../core/geometry/lib/esm/geometry4d/Matrix4d.js");
242925
+ /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
242926
+ /* harmony import */ var _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../numerics/UnionFind */ "../../core/geometry/lib/esm/numerics/UnionFind.js");
242803
242927
  /* harmony import */ var _topology_ChainMerge__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../topology/ChainMerge */ "../../core/geometry/lib/esm/topology/ChainMerge.js");
242804
242928
  /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
242805
242929
  /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
242806
242930
  /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
242807
- /* harmony import */ var _FacetOrientation__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./FacetOrientation */ "../../core/geometry/lib/esm/polyface/FacetOrientation.js");
242808
- /* harmony import */ var _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./IndexedEdgeMatcher */ "../../core/geometry/lib/esm/polyface/IndexedEdgeMatcher.js");
242931
+ /* harmony import */ var _FacetOrientation__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./FacetOrientation */ "../../core/geometry/lib/esm/polyface/FacetOrientation.js");
242932
+ /* harmony import */ var _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./IndexedEdgeMatcher */ "../../core/geometry/lib/esm/polyface/IndexedEdgeMatcher.js");
242809
242933
  /* harmony import */ var _IndexedPolyfaceVisitor__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./IndexedPolyfaceVisitor */ "../../core/geometry/lib/esm/polyface/IndexedPolyfaceVisitor.js");
242810
- /* harmony import */ var _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./multiclip/BuildAverageNormalsContext */ "../../core/geometry/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js");
242811
- /* harmony import */ var _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./multiclip/SweepLineStringToFacetContext */ "../../core/geometry/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js");
242934
+ /* harmony import */ var _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./multiclip/BuildAverageNormalsContext */ "../../core/geometry/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js");
242935
+ /* harmony import */ var _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./multiclip/SweepLineStringToFacetContext */ "../../core/geometry/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js");
242812
242936
  /* harmony import */ var _multiclip_XYPointBuckets__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./multiclip/XYPointBuckets */ "../../core/geometry/lib/esm/polyface/multiclip/XYPointBuckets.js");
242813
- /* harmony import */ var _Polyface__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Polyface */ "../../core/geometry/lib/esm/polyface/Polyface.js");
242937
+ /* harmony import */ var _Polyface__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Polyface */ "../../core/geometry/lib/esm/polyface/Polyface.js");
242814
242938
  /* harmony import */ var _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./PolyfaceBuilder */ "../../core/geometry/lib/esm/polyface/PolyfaceBuilder.js");
242815
242939
  /* harmony import */ var _RangeLengthData__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./RangeLengthData */ "../../core/geometry/lib/esm/polyface/RangeLengthData.js");
242816
242940
  /* harmony import */ var _topology_SpaceTriangulation__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../topology/SpaceTriangulation */ "../../core/geometry/lib/esm/topology/SpaceTriangulation.js");
242941
+ /* harmony import */ var _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../topology/HalfEdgeGraphFromIndexedLoopsContext */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js");
242942
+ /* harmony import */ var _multiclip_OffsetMeshContext__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./multiclip/OffsetMeshContext */ "../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js");
242817
242943
  /*---------------------------------------------------------------------------------------------
242818
242944
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
242819
242945
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -242853,6 +242979,41 @@ __webpack_require__.r(__webpack_exports__);
242853
242979
 
242854
242980
 
242855
242981
 
242982
+
242983
+
242984
+ /**
242985
+ * Options carrier for [[PolyfaceQuery.cloneOffset]].
242986
+ * * Default options are strongly recommended.
242987
+ * * The option most likely to be changed is chamferTurnAngle
242988
+ * @public
242989
+ */
242990
+ class OffsetMeshOptions {
242991
+ /** Constructor -- CAPTURE parameters ... */
242992
+ constructor(smoothSingleAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(25), smoothAccumulatedAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(60), chamferTurnAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(90)) {
242993
+ this.smoothSingleAngleBetweenNormals = smoothSingleAngleBetweenNormals.clone();
242994
+ this.smoothAccumulatedAngleBetweenNormals = smoothAccumulatedAngleBetweenNormals.clone();
242995
+ this.chamferAngleBetweenNormals = chamferTurnAngle.clone();
242996
+ }
242997
+ /** construct and return an OffsetMeshOptions with given parameters.
242998
+ * * Angles are forced to minimum values.
242999
+ * * Clones of the angles are given to the constructor.
243000
+ * @param smoothSingleRadiansBetweenNormals an angle larger than this (between facets) is considered a sharp edge
243001
+ * @param smoothAccumulatedAngleBetweenNormals angles that sum to this much may be consolidated for average normal
243002
+ * @param chamferTurnAngleBetweenNormals when facets meet with larger angle, a chamfer edge may be added if the angle between facet normals is larger than this.
243003
+ */
243004
+ static create(smoothSingleAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(25), smoothAccumulatedAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(60), chamferTurnAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(120)) {
243005
+ const mySmoothSingleRadiansBetweenNormals = smoothSingleAngleBetweenNormals.clone();
243006
+ const mySmoothAccumulatedRadiansBetweenNormals = smoothAccumulatedAngleBetweenNormals.clone();
243007
+ const myChamferTurnAngleBetweenNormals = chamferTurnAngleBetweenNormals.clone();
243008
+ if (mySmoothSingleRadiansBetweenNormals.degrees < 1)
243009
+ mySmoothAccumulatedRadiansBetweenNormals.setDegrees(1.0);
243010
+ if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 1.0)
243011
+ mySmoothAccumulatedRadiansBetweenNormals.setDegrees(1.0);
243012
+ if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 15.0)
243013
+ mySmoothAccumulatedRadiansBetweenNormals.setDegrees(15.0);
243014
+ return new OffsetMeshOptions(mySmoothSingleRadiansBetweenNormals, mySmoothAccumulatedRadiansBetweenNormals, myChamferTurnAngleBetweenNormals);
243015
+ }
243016
+ }
242856
243017
  /**
242857
243018
  * Enumeration of cases for retaining facets among duplicates
242858
243019
  * @public
@@ -242874,12 +243035,12 @@ var DuplicateFacetClusterSelector;
242874
243035
  class PolyfaceQuery {
242875
243036
  /** copy the points from a visitor into a Linestring3d in a Loop object */
242876
243037
  static visitorToLoop(visitor) {
242877
- const ls = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_0__.LineString3d.createPoints(visitor.point.getPoint3dArray());
242878
- return _curve_Loop__WEBPACK_IMPORTED_MODULE_1__.Loop.create(ls);
243038
+ const ls = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_1__.LineString3d.createPoints(visitor.point.getPoint3dArray());
243039
+ return _curve_Loop__WEBPACK_IMPORTED_MODULE_2__.Loop.create(ls);
242879
243040
  }
242880
243041
  /** Create a linestring loop for each facet of the polyface. */
242881
243042
  static indexedPolyfaceToLoops(polyface) {
242882
- const result = _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_2__.BagOfCurves.create();
243043
+ const result = _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.BagOfCurves.create();
242883
243044
  const visitor = polyface.createVisitor(1);
242884
243045
  while (visitor.moveToNextFacet()) {
242885
243046
  const loop = PolyfaceQuery.visitorToLoop(visitor);
@@ -242893,17 +243054,17 @@ class PolyfaceQuery {
242893
243054
  static sumFacetAreas(source, vectorToEye) {
242894
243055
  let s = 0;
242895
243056
  if (source !== undefined) {
242896
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
243057
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
242897
243058
  return PolyfaceQuery.sumFacetAreas(source.createVisitor(1), vectorToEye);
242898
243059
  let unitVectorToEye;
242899
243060
  if (vectorToEye !== undefined)
242900
243061
  unitVectorToEye = vectorToEye.normalize();
242901
243062
  source.reset();
242902
243063
  while (source.moveToNextFacet()) {
242903
- const scaledNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.areaNormal(source.point.getPoint3dArray());
243064
+ const scaledNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.areaNormal(source.point.getPoint3dArray());
242904
243065
  let area = scaledNormal.magnitude();
242905
243066
  if (unitVectorToEye !== undefined) {
242906
- const scale = _Geometry__WEBPACK_IMPORTED_MODULE_5__.Geometry.conditionalDivideCoordinate(1.0, area);
243067
+ const scale = _Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.conditionalDivideCoordinate(1.0, area);
242907
243068
  if (scale !== undefined)
242908
243069
  area *= scaledNormal.dotProduct(unitVectorToEye) * scale;
242909
243070
  }
@@ -242920,12 +243081,12 @@ class PolyfaceQuery {
242920
243081
  */
242921
243082
  static sumTetrahedralVolumes(source, origin) {
242922
243083
  let s = 0;
242923
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
243084
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
242924
243085
  return PolyfaceQuery.sumTetrahedralVolumes(source.createVisitor(0), origin);
242925
243086
  let myOrigin = origin;
242926
- const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
242927
- const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
242928
- const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
243087
+ const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
243088
+ const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
243089
+ const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
242929
243090
  source.reset();
242930
243091
  while (source.moveToNextFacet()) {
242931
243092
  if (myOrigin === undefined)
@@ -242946,20 +243107,20 @@ class PolyfaceQuery {
242946
243107
  *
242947
243108
  */
242948
243109
  static sumVolumeBetweenFacetsAndPlane(source, plane) {
242949
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
243110
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
242950
243111
  return PolyfaceQuery.sumVolumeBetweenFacetsAndPlane(source.createVisitor(0), plane);
242951
- const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
242952
- const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
242953
- const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
242954
- const triangleNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
243112
+ const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
243113
+ const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
243114
+ const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
243115
+ const triangleNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
242955
243116
  const planeNormal = plane.getNormalRef();
242956
243117
  let h0, hA, hB;
242957
243118
  let signedVolumeSum = 0.0;
242958
243119
  let signedTriangleArea;
242959
243120
  let singleFacetArea;
242960
- const positiveAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.create(undefined, true);
242961
- const negativeAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.create(undefined, true);
242962
- const singleFacetProducts = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_8__.Matrix4d.createZero();
243121
+ const positiveAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.create(undefined, true);
243122
+ const negativeAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.create(undefined, true);
243123
+ const singleFacetProducts = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
242963
243124
  const projectToPlane = plane.getProjectionToPlane();
242964
243125
  source.reset();
242965
243126
  // For each facet ..
@@ -242986,7 +243147,7 @@ class PolyfaceQuery {
242986
243147
  }
242987
243148
  singleFacetProducts.setZero();
242988
243149
  source.point.multiplyTransformInPlace(projectToPlane);
242989
- _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.addSecondMomentAreaProducts(source.point, facetOrigin, singleFacetProducts);
243150
+ _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentAreaProducts(source.point, facetOrigin, singleFacetProducts);
242990
243151
  if (singleFacetArea > 0) {
242991
243152
  positiveAreaMomentSums.accumulateProductsFromOrigin(facetOrigin, singleFacetProducts, 1.0);
242992
243153
  }
@@ -242996,8 +243157,8 @@ class PolyfaceQuery {
242996
243157
  }
242997
243158
  positiveAreaMomentSums.shiftOriginAndSumsToCentroidOfSums();
242998
243159
  negativeAreaMomentSums.shiftOriginAndSumsToCentroidOfSums();
242999
- const positiveAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.inertiaProductsToPrincipalAxes(positiveAreaMomentSums.origin, positiveAreaMomentSums.sums);
243000
- const negativeAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.inertiaProductsToPrincipalAxes(negativeAreaMomentSums.origin, negativeAreaMomentSums.sums);
243160
+ const positiveAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(positiveAreaMomentSums.origin, positiveAreaMomentSums.sums);
243161
+ const negativeAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(negativeAreaMomentSums.origin, negativeAreaMomentSums.sums);
243001
243162
  return {
243002
243163
  volume: signedVolumeSum / 6.0,
243003
243164
  positiveProjectedFacetAreaMoments: positiveAreaMoments,
@@ -243006,23 +243167,23 @@ class PolyfaceQuery {
243006
243167
  }
243007
243168
  /** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all all facets, as viewed from origin. */
243008
243169
  static sumFacetSecondAreaMomentProducts(source, origin) {
243009
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
243170
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
243010
243171
  return PolyfaceQuery.sumFacetSecondAreaMomentProducts(source.createVisitor(0), origin);
243011
- const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_8__.Matrix4d.createZero();
243172
+ const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
243012
243173
  source.reset();
243013
243174
  while (source.moveToNextFacet()) {
243014
- _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.addSecondMomentAreaProducts(source.point, origin, products);
243175
+ _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentAreaProducts(source.point, origin, products);
243015
243176
  }
243016
243177
  return products;
243017
243178
  }
243018
243179
  /** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all tetrahedral volumes from origin */
243019
243180
  static sumFacetSecondVolumeMomentProducts(source, origin) {
243020
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
243181
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
243021
243182
  return PolyfaceQuery.sumFacetSecondVolumeMomentProducts(source.createVisitor(0), origin);
243022
- const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_8__.Matrix4d.createZero();
243183
+ const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
243023
243184
  source.reset();
243024
243185
  while (source.moveToNextFacet()) {
243025
- _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.addSecondMomentVolumeProducts(source.point, origin, products);
243186
+ _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentVolumeProducts(source.point, origin, products);
243026
243187
  }
243027
243188
  return products;
243028
243189
  }
@@ -243036,7 +243197,7 @@ class PolyfaceQuery {
243036
243197
  if (!origin)
243037
243198
  return undefined;
243038
243199
  const inertiaProducts = PolyfaceQuery.sumFacetSecondAreaMomentProducts(source, origin);
243039
- return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
243200
+ return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
243040
243201
  }
243041
243202
  /** Compute area moments for the mesh. In the returned MomentData:
243042
243203
  * * origin is the centroid.
@@ -243050,7 +243211,7 @@ class PolyfaceQuery {
243050
243211
  if (!origin)
243051
243212
  return undefined;
243052
243213
  const inertiaProducts = PolyfaceQuery.sumFacetSecondVolumeMomentProducts(source, origin);
243053
- return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
243214
+ return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
243054
243215
  }
243055
243216
  /**
243056
243217
  * Test for convex volume by dihedral angle tests on all edges.
@@ -243082,14 +243243,14 @@ class PolyfaceQuery {
243082
243243
  * * (but null edges are permitted -- These occur naturally at edges of quads at north or south pole)
243083
243244
  */
243084
243245
  static dihedralAngleSummary(source, ignoreBoundaries = false) {
243085
- const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
243246
+ const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
243086
243247
  const visitor = source.createVisitor(1);
243087
243248
  visitor.reset();
243088
243249
  const centroidNormal = [];
243089
243250
  let normalCounter = 0;
243090
243251
  while (visitor.moveToNextFacet()) {
243091
243252
  const numEdges = visitor.pointCount - 1;
243092
- const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.centroidAreaNormal(visitor.point);
243253
+ const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.centroidAreaNormal(visitor.point);
243093
243254
  if (normal === undefined)
243094
243255
  return 0;
243095
243256
  centroidNormal.push(normal);
@@ -243106,12 +243267,12 @@ class PolyfaceQuery {
243106
243267
  let numPositive = 0;
243107
243268
  let numPlanar = 0;
243108
243269
  let numNegative = 0;
243109
- const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
243270
+ const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
243110
243271
  for (const cluster of manifoldClusters) {
243111
243272
  const sideA = cluster[0];
243112
243273
  const sideB = cluster[1];
243113
- if (sideA instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge
243114
- && sideB instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge
243274
+ if (sideA instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge
243275
+ && sideB instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge
243115
243276
  && source.data.point.vectorIndexIndex(sideA.vertexIndexA, sideA.vertexIndexB, edgeVector)) {
243116
243277
  const dihedralAngle = centroidNormal[sideA.facetIndex].direction.signedAngleTo(centroidNormal[sideB.facetIndex].direction, edgeVector);
243117
243278
  if (dihedralAngle.isAlmostZero)
@@ -243144,7 +243305,7 @@ class PolyfaceQuery {
243144
243305
  * * Any edge with 2 incident facets in the same direction triggers a `false` return.
243145
243306
  */
243146
243307
  static isPolyfaceManifold(source, allowSimpleBoundaries = false) {
243147
- const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
243308
+ const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
243148
243309
  const visitor = source.createVisitor(1);
243149
243310
  visitor.reset();
243150
243311
  while (visitor.moveToNextFacet()) {
@@ -243167,9 +243328,9 @@ class PolyfaceQuery {
243167
243328
  * @returns
243168
243329
  */
243169
243330
  static boundaryEdges(source, includeDanglers = true, includeMismatch = true, includeNull = true) {
243170
- const result = new _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_2__.BagOfCurves();
243331
+ const result = new _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.BagOfCurves();
243171
243332
  const announceEdge = (pointA, pointB, _indexA, _indexB, _readIndex) => {
243172
- result.tryAddChild(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(pointA, pointB));
243333
+ result.tryAddChild(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB));
243173
243334
  };
243174
243335
  PolyfaceQuery.announceBoundaryEdges(source, announceEdge, includeDanglers, includeMismatch, includeNull);
243175
243336
  if (result.children.length === 0)
@@ -243188,8 +243349,8 @@ class PolyfaceQuery {
243188
243349
  static announceBoundaryEdges(source, announceEdge, includeDanglers = true, includeMismatch = true, includeNull = true) {
243189
243350
  if (source === undefined)
243190
243351
  return undefined;
243191
- const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
243192
- const visitor = source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface ? source.createVisitor(1) : source;
243352
+ const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
243353
+ const visitor = source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface ? source.createVisitor(1) : source;
243193
243354
  visitor.setNumWrap(1);
243194
243355
  visitor.reset();
243195
243356
  while (visitor.moveToNextFacet()) {
@@ -243214,7 +243375,7 @@ class PolyfaceQuery {
243214
243375
  const sourcePolyface = visitor.clientPolyface();
243215
243376
  for (const list of badList) {
243216
243377
  for (const e of list) {
243217
- const e1 = e instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge ? e : e[0];
243378
+ const e1 = e instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge ? e : e[0];
243218
243379
  const indexA = e1.vertexIndexA;
243219
243380
  const indexB = e1.vertexIndexB;
243220
243381
  const pointA = sourcePolyface.data.getPoint(indexA);
@@ -243229,7 +243390,7 @@ class PolyfaceQuery {
243229
243390
  * * Facets are ASSUMED to be convex and planar.
243230
243391
  */
243231
243392
  static announceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, announce) {
243232
- const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_11__.SweepLineStringToFacetContext.create(linestringPoints);
243393
+ const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__.SweepLineStringToFacetContext.create(linestringPoints);
243233
243394
  if (context) {
243234
243395
  const visitor = polyface.createVisitor(0);
243235
243396
  for (visitor.reset(); visitor.moveToNextFacet();) {
@@ -243262,7 +243423,7 @@ class PolyfaceQuery {
243262
243423
  * @internal
243263
243424
  */
243264
243425
  static async asyncAnnounceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, announce) {
243265
- const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_11__.SweepLineStringToFacetContext.create(linestringPoints);
243426
+ const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__.SweepLineStringToFacetContext.create(linestringPoints);
243266
243427
  this.awaitBlockCount = 0;
243267
243428
  let workTotal = 0;
243268
243429
  if (context) {
@@ -243282,11 +243443,11 @@ class PolyfaceQuery {
243282
243443
  * * Return array of arrays of facet indices.
243283
243444
  */
243284
243445
  static partitionFacetIndicesByVertexConnectedComponent(polyface) {
243285
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
243446
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
243286
243447
  return this.partitionFacetIndicesByVertexConnectedComponent(polyface.createVisitor(0));
243287
243448
  }
243288
243449
  // The polyface is really a visitor !!!
243289
- const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_12__.UnionFindContext(this.visitorClientPointCount(polyface));
243450
+ const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__.UnionFindContext(this.visitorClientPointCount(polyface));
243290
243451
  for (polyface.reset(); polyface.moveToNextFacet();) {
243291
243452
  const firstVertexIndexOnThisFacet = polyface.pointIndex[0];
243292
243453
  for (const vertexIndex of polyface.pointIndex)
@@ -243319,7 +243480,7 @@ class PolyfaceQuery {
243319
243480
  * * Return array of arrays of facet indices.
243320
243481
  */
243321
243482
  static partitionFacetIndicesByVisibilityVector(polyface, vectorToEye, sideAngleTolerance) {
243322
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
243483
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
243323
243484
  return this.partitionFacetIndicesByVisibilityVector(polyface.createVisitor(0), vectorToEye, sideAngleTolerance);
243324
243485
  }
243325
243486
  const facetsInComponent = [];
@@ -243331,7 +243492,7 @@ class PolyfaceQuery {
243331
243492
  const sideComponent = facetsInComponent[2];
243332
243493
  const radiansTol = Math.max(sideAngleTolerance.radians, 1.0e-8);
243333
243494
  for (polyface.reset(); polyface.moveToNextFacet();) {
243334
- const areaNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.areaNormalGo(polyface.point);
243495
+ const areaNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.areaNormalGo(polyface.point);
243335
243496
  const index = polyface.currentReadIndex();
243336
243497
  if (areaNormal) {
243337
243498
  const angle = areaNormal.angleFromPerpendicular(vectorToEye);
@@ -243358,7 +243519,7 @@ class PolyfaceQuery {
243358
243519
  * @param vectorToEye
243359
243520
  * @param sideAngleTolerance
243360
243521
  */
243361
- static boundaryOfVisibleSubset(polyface, visibilitySelect, vectorToEye, sideAngleTolerance = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_13__.Angle.createDegrees(1.0e-3)) {
243522
+ static boundaryOfVisibleSubset(polyface, visibilitySelect, vectorToEye, sideAngleTolerance = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(1.0e-3)) {
243362
243523
  const partitionedIndices = this.partitionFacetIndicesByVisibilityVector(polyface, vectorToEye, sideAngleTolerance);
243363
243524
  if (partitionedIndices[visibilitySelect].length === 0)
243364
243525
  return undefined;
@@ -243372,8 +243533,8 @@ class PolyfaceQuery {
243372
243533
  * @param mesh
243373
243534
  */
243374
243535
  static announceBoundaryChainsAsLineString3d(mesh, announceLoop) {
243375
- const collector = new _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.MultiChainCollector(_Geometry__WEBPACK_IMPORTED_MODULE_5__.Geometry.smallMetricDistance, 1000);
243376
- PolyfaceQuery.announceBoundaryEdges(mesh, (pointA, pointB, _indexA, _indexB) => collector.captureCurve(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(pointA, pointB)), true, false, false);
243536
+ const collector = new _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.MultiChainCollector(_Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallMetricDistance, 1000);
243537
+ PolyfaceQuery.announceBoundaryEdges(mesh, (pointA, pointB, _indexA, _indexB) => collector.captureCurve(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB)), true, false, false);
243377
243538
  collector.announceChainsAsLineString3d(announceLoop);
243378
243539
  }
243379
243540
  /**
@@ -243384,7 +243545,7 @@ class PolyfaceQuery {
243384
243545
  * @returns
243385
243546
  */
243386
243547
  static cloneWithMaximalPlanarFacets(mesh) {
243387
- if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
243548
+ if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
243388
243549
  return this.cloneWithMaximalPlanarFacets(mesh.createVisitor(0));
243389
243550
  const numFacets = PolyfaceQuery.visitorClientFacetCount(mesh);
243390
243551
  const smoothEdges = PolyfaceQuery.collectEdgesByDihedralAngle(mesh);
@@ -243409,7 +243570,7 @@ class PolyfaceQuery {
243409
243570
  const edges = [];
243410
243571
  const edgeStrings = [];
243411
243572
  PolyfaceQuery.announceBoundaryEdges(fragment, (pointA, pointB, _indexA, _indexB) => {
243412
- edges.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(pointA, pointB));
243573
+ edges.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB));
243413
243574
  edgeStrings.push([pointA.clone(), pointB.clone()]);
243414
243575
  });
243415
243576
  const chains = _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.OffsetHelpers.collectChains(edges, gapTolerance, planarityTolerance);
@@ -243450,7 +243611,7 @@ class PolyfaceQuery {
243450
243611
  * @returns
243451
243612
  */
243452
243613
  static fillSimpleHoles(mesh, options, unfilledChains) {
243453
- if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
243614
+ if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
243454
243615
  return this.fillSimpleHoles(mesh.createVisitor(0), options, unfilledChains);
243455
243616
  const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
243456
243617
  const chains = [];
@@ -243464,7 +243625,7 @@ class PolyfaceQuery {
243464
243625
  rejected = true;
243465
243626
  else if (options.maxPerimeter !== undefined && _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_21__.Point3dArray.sumEdgeLengths(points, false) > options.maxPerimeter)
243466
243627
  rejected = true;
243467
- else if (options.upVector !== undefined && _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.sumTriangleAreasPerpendicularToUpVector(points, options.upVector) <= 0.0)
243628
+ else if (options.upVector !== undefined && _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.sumTriangleAreasPerpendicularToUpVector(points, options.upVector) <= 0.0)
243468
243629
  rejected = true;
243469
243630
  if (!rejected && _topology_SpaceTriangulation__WEBPACK_IMPORTED_MODULE_22__.SpacePolygonTriangulation.triangulateSimplestSpaceLoop(points, (_loop, triangles) => {
243470
243631
  for (const t of triangles)
@@ -243487,7 +243648,7 @@ class PolyfaceQuery {
243487
243648
  *
243488
243649
  */
243489
243650
  static clonePartitions(polyface, partitions) {
243490
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
243651
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
243491
243652
  return this.clonePartitions(polyface.createVisitor(0), partitions);
243492
243653
  }
243493
243654
  polyface.setNumWrap(0);
@@ -243511,7 +243672,7 @@ class PolyfaceQuery {
243511
243672
  /** Clone facets that pass an filter function
243512
243673
  */
243513
243674
  static cloneFiltered(source, filter) {
243514
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
243675
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
243515
243676
  return this.cloneFiltered(source.createVisitor(0), filter);
243516
243677
  }
243517
243678
  source.setNumWrap(0);
@@ -243563,9 +243724,9 @@ class PolyfaceQuery {
243563
243724
  * @return collection of facet index arrays, one array per connected component
243564
243725
  */
243565
243726
  static partitionFacetIndicesBySortableEdgeClusters(edgeClusters, numFacets) {
243566
- const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_12__.UnionFindContext(numFacets);
243727
+ const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__.UnionFindContext(numFacets);
243567
243728
  for (const cluster of edgeClusters) {
243568
- if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge) {
243729
+ if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge) {
243569
243730
  // this edge does not connect anywhere. Ignore it!!
243570
243731
  }
243571
243732
  else {
@@ -243597,11 +243758,11 @@ class PolyfaceQuery {
243597
243758
  * @return collection of facet index arrays, one per connected component
243598
243759
  */
243599
243760
  static partitionFacetIndicesByEdgeConnectedComponent(polyface, stopAtVisibleEdges = false) {
243600
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
243761
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
243601
243762
  return this.partitionFacetIndicesByEdgeConnectedComponent(polyface.createVisitor(0), stopAtVisibleEdges);
243602
243763
  }
243603
243764
  polyface.setNumWrap(1);
243604
- const matcher = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
243765
+ const matcher = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
243605
243766
  polyface.reset();
243606
243767
  let numFacets = 0;
243607
243768
  while (polyface.moveToNextFacet()) {
@@ -243639,7 +243800,7 @@ class PolyfaceQuery {
243639
243800
  static sweepLinestringToFacetsXYReturnLines(linestringPoints, polyface) {
243640
243801
  const drapeGeometry = [];
243641
243802
  this.announceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, (_linestring, _segmentIndex, _polyface, _facetIndex, points, indexA, indexB) => {
243642
- drapeGeometry.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(points[indexA], points[indexB]));
243803
+ drapeGeometry.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(points[indexA], points[indexB]));
243643
243804
  });
243644
243805
  return drapeGeometry;
243645
243806
  }
@@ -243674,7 +243835,7 @@ class PolyfaceQuery {
243674
243835
  * * Return statistical summary of x,y,z ranges.
243675
243836
  */
243676
243837
  static collectRangeLengthData(polyface) {
243677
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
243838
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
243678
243839
  return this.collectRangeLengthData(polyface.createVisitor(0));
243679
243840
  }
243680
243841
  const rangeData = new _RangeLengthData__WEBPACK_IMPORTED_MODULE_25__.RangeLengthData();
@@ -243692,10 +243853,10 @@ class PolyfaceQuery {
243692
243853
  const rangeSearcher = _multiclip_XYPointBuckets__WEBPACK_IMPORTED_MODULE_26__.XYPointBuckets.create(polyface.data.point, 30);
243693
243854
  const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
243694
243855
  const edgeRange = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_27__.Range3d.createNull();
243695
- const point0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
243696
- const point1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
243697
- const spacePoint = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
243698
- const segment = _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(point0, point1);
243856
+ const point0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
243857
+ const point1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
243858
+ const spacePoint = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
243859
+ const segment = _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(point0, point1);
243699
243860
  for (oldFacetVisitor.reset(); oldFacetVisitor.moveToNextFacet();) {
243700
243861
  newFacetVisitor.clearArrays();
243701
243862
  for (let i = 0; i + 1 < oldFacetVisitor.point.length; i++) {
@@ -243704,7 +243865,7 @@ class PolyfaceQuery {
243704
243865
  oldFacetVisitor.point.getPoint3dAtUncheckedPointIndex(i + 1, point1);
243705
243866
  newFacetVisitor.pushDataFrom(oldFacetVisitor, i);
243706
243867
  edgeRange.setNull();
243707
- _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(point0, point1, segment);
243868
+ _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(point0, point1, segment);
243708
243869
  let detailArray;
243709
243870
  edgeRange.extend(point0);
243710
243871
  edgeRange.extend(point1);
@@ -243849,8 +244010,8 @@ class PolyfaceQuery {
243849
244010
  const oldFacetVisitor = polyface.createVisitor(2); // This is to visit the existing facets.
243850
244011
  const newFacetVisitor = polyface.createVisitor(0); // This is to build the new facets.
243851
244012
  const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
243852
- const vector01 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
243853
- const vector12 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
244013
+ const vector01 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
244014
+ const vector12 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
243854
244015
  const numPoint = polyface.data.point.length;
243855
244016
  const pointState = new Int32Array(numPoint);
243856
244017
  // FIRST PASS -- in each sector of each facet, determine if the sector has colinear incoming and outgoing vectors.
@@ -243897,7 +244058,7 @@ class PolyfaceQuery {
243897
244058
  */
243898
244059
  static setEdgeVisibility(polyface, clusters, value) {
243899
244060
  for (const cluster of clusters) {
243900
- if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge) {
244061
+ if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge) {
243901
244062
  this.setSingleEdgeVisibility(polyface, cluster.facetIndex, cluster.vertexIndexA, value);
243902
244063
  }
243903
244064
  else if (Array.isArray(cluster)) {
@@ -243940,9 +244101,9 @@ class PolyfaceQuery {
243940
244101
  * @param polyface a mesh, or a visitor assumed to have numWrap === 1
243941
244102
  */
243942
244103
  static createIndexedEdges(polyface) {
243943
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
244104
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
243944
244105
  return this.createIndexedEdges(polyface.createVisitor(1));
243945
- const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
244106
+ const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
243946
244107
  polyface.reset();
243947
244108
  while (polyface.moveToNextFacet()) {
243948
244109
  const numEdges = polyface.pointCount - 1;
@@ -243961,17 +244122,17 @@ class PolyfaceQuery {
243961
244122
  * @param sharpEdges true to reverse the angle threshold test and return sharp edges; otherwise return smooth edges (default)
243962
244123
  */
243963
244124
  static collectEdgesByDihedralAngle(mesh, maxSmoothEdgeAngle, sharpEdges = false) {
243964
- if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
244125
+ if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
243965
244126
  return this.collectEdgesByDihedralAngle(mesh.createVisitor(1), maxSmoothEdgeAngle, sharpEdges);
243966
244127
  mesh.setNumWrap(1);
243967
244128
  const allEdges = this.createIndexedEdges(mesh);
243968
244129
  const manifoldEdges = [];
243969
244130
  allEdges.sortAndCollectClusters(manifoldEdges);
243970
244131
  if (undefined === maxSmoothEdgeAngle || maxSmoothEdgeAngle.radians < 0)
243971
- maxSmoothEdgeAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_13__.Angle.createRadians(_Geometry__WEBPACK_IMPORTED_MODULE_5__.Geometry.smallAngleRadians);
244132
+ maxSmoothEdgeAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createRadians(_Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallAngleRadians);
243972
244133
  const outEdges = [];
243973
- const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
243974
- const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
244134
+ const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
244135
+ const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
243975
244136
  for (const pair of manifoldEdges) {
243976
244137
  if (Array.isArray(pair) && pair.length === 2) {
243977
244138
  const e0 = pair[0];
@@ -244010,8 +244171,8 @@ class PolyfaceQuery {
244010
244171
  this.markAllEdgeVisibility(mesh, false);
244011
244172
  this.setEdgeVisibility(mesh, boundaryEdges, true);
244012
244173
  if (sharpEdgeAngle !== undefined) {
244013
- const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
244014
- const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
244174
+ const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
244175
+ const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
244015
244176
  for (const pair of pairedEdges) {
244016
244177
  if (Array.isArray(pair) && pair.length === 2) {
244017
244178
  const e0 = pair[0];
@@ -244033,9 +244194,9 @@ class PolyfaceQuery {
244033
244194
  */
244034
244195
  static computeFacetUnitNormal(visitor, facetIndex, result) {
244035
244196
  if (!result)
244036
- result = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
244197
+ result = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
244037
244198
  if (visitor.moveToReadIndex(facetIndex)) {
244038
- if (_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.unitNormal(visitor.point, result))
244199
+ if (_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.unitNormal(visitor.point, result))
244039
244200
  return result;
244040
244201
  }
244041
244202
  return undefined;
@@ -244050,20 +244211,41 @@ class PolyfaceQuery {
244050
244211
  for (let i = 0; i < data.edgeVisible.length; i++)
244051
244212
  data.edgeVisible[i] = value;
244052
244213
  }
244214
+ /**
244215
+ * Create a HalfEdgeGraph with a face for each facet of the IndexedPolyface
244216
+ * @param mesh mesh to convert
244217
+ * @internal
244218
+ */
244219
+ static convertToHalfEdgeGraph(mesh) {
244220
+ const builder = new _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_28__.HalfEdgeGraphFromIndexedLoopsContext();
244221
+ const visitor = mesh.createVisitor(0);
244222
+ for (visitor.reset(); visitor.moveToNextFacet();) {
244223
+ builder.insertLoop(visitor.pointIndex);
244224
+ }
244225
+ const graph = builder.graph;
244226
+ const xyz = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
244227
+ graph.announceNodes((_graph, halfEdge) => {
244228
+ const vertexIndex = halfEdge.i;
244229
+ mesh.data.getPoint(vertexIndex, xyz);
244230
+ halfEdge.setXYZ(xyz);
244231
+ return true;
244232
+ });
244233
+ return graph;
244234
+ }
244053
244235
  /**
244054
244236
  * * Examine adjacent facet orientations throughout the mesh
244055
244237
  * * If possible, reverse a subset to achieve proper pairing.
244056
244238
  * @param mesh
244057
244239
  */
244058
244240
  static reorientVertexOrderAroundFacetsForConsistentOrientation(mesh) {
244059
- return _FacetOrientation__WEBPACK_IMPORTED_MODULE_28__.FacetOrientationFixup.doFixup(mesh);
244241
+ return _FacetOrientation__WEBPACK_IMPORTED_MODULE_29__.FacetOrientationFixup.doFixup(mesh);
244060
244242
  }
244061
244243
  /**
244062
244244
  * Set up indexed normals with one normal in the plane of each facet of the mesh.
244063
244245
  * @param polyface
244064
244246
  */
244065
244247
  static buildPerFaceNormals(polyface) {
244066
- _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_29__.BuildAverageNormalsContext.buildPerFaceNormals(polyface);
244248
+ _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__.BuildAverageNormalsContext.buildPerFaceNormals(polyface);
244067
244249
  }
244068
244250
  /**
244069
244251
  * * At each vertex of the mesh
@@ -244075,8 +244257,21 @@ class PolyfaceQuery {
244075
244257
  * @param polyface polyface to update.
244076
244258
  * @param toleranceAngle averaging is done between normals up to this angle.
244077
244259
  */
244078
- static buildAverageNormals(polyface, toleranceAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_13__.Angle.createDegrees(31.0)) {
244079
- _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_29__.BuildAverageNormalsContext.buildFastAverageNormals(polyface, toleranceAngle);
244260
+ static buildAverageNormals(polyface, toleranceAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(31.0)) {
244261
+ _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__.BuildAverageNormalsContext.buildFastAverageNormals(polyface, toleranceAngle);
244262
+ }
244263
+ /**
244264
+ * Offset the faces of the mesh.
244265
+ * @param source original mesh
244266
+ * @param signedOffsetDistance distance to offset
244267
+ * @param offsetOptions angle options. The default options are recommended.
244268
+ * @returns shifted mesh.
244269
+ */
244270
+ static cloneOffset(source, signedOffsetDistance, offsetOptions = OffsetMeshOptions.create()) {
244271
+ const strokeOptions = _curve_StrokeOptions__WEBPACK_IMPORTED_MODULE_23__.StrokeOptions.createForFacets();
244272
+ const offsetBuilder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create(strokeOptions);
244273
+ _multiclip_OffsetMeshContext__WEBPACK_IMPORTED_MODULE_31__.OffsetMeshContext.buildOffsetMeshWithEdgeChamfers(source, offsetBuilder, signedOffsetDistance, offsetOptions);
244274
+ return offsetBuilder.claimPolyface();
244080
244275
  }
244081
244276
  }
244082
244277
  // amount of computation to do per step of async methods.
@@ -244988,6 +245183,1064 @@ class LinearSearchRange2dArray {
244988
245183
  }
244989
245184
 
244990
245185
 
245186
+ /***/ }),
245187
+
245188
+ /***/ "../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js":
245189
+ /*!***************************************************************************!*\
245190
+ !*** ../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js ***!
245191
+ \***************************************************************************/
245192
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
245193
+
245194
+ "use strict";
245195
+ __webpack_require__.r(__webpack_exports__);
245196
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
245197
+ /* harmony export */ "FacetOffsetProperties": () => (/* binding */ FacetOffsetProperties),
245198
+ /* harmony export */ "OffsetMeshContext": () => (/* binding */ OffsetMeshContext),
245199
+ /* harmony export */ "SectorOffsetProperties": () => (/* binding */ SectorOffsetProperties)
245200
+ /* harmony export */ });
245201
+ /* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
245202
+ /* harmony import */ var _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../geometry3d/GrowableXYZArray */ "../../core/geometry/lib/esm/geometry3d/GrowableXYZArray.js");
245203
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
245204
+ /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
245205
+ /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
245206
+ /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
245207
+ /* harmony import */ var _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphFromIndexedLoopsContext */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js");
245208
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
245209
+ /* harmony import */ var _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../geometry3d/PolylineCompressionByEdgeOffset */ "../../core/geometry/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js");
245210
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
245211
+ /*---------------------------------------------------------------------------------------------
245212
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
245213
+ * See LICENSE.md in the project root for license terms and full copyright notice.
245214
+ *--------------------------------------------------------------------------------------------*/
245215
+ /** @packageDocumentation
245216
+ * @module Polyface
245217
+ */
245218
+
245219
+
245220
+
245221
+
245222
+
245223
+
245224
+
245225
+
245226
+
245227
+
245228
+ function isDefinedAndTrue(value) {
245229
+ if (value === undefined)
245230
+ return false;
245231
+ return value;
245232
+ }
245233
+ class AverageNormalData {
245234
+ constructor() {
245235
+ this.numActiveSectors = 0;
245236
+ this.numInactiveSectors = 0; // exterior and sling.
245237
+ this.averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
245238
+ this.radiansSum = 0.0;
245239
+ this.maxDeviationRadiansFromAverage = 0.0;
245240
+ }
245241
+ clear() {
245242
+ this.numActiveSectors = 0;
245243
+ this.numInactiveSectors = 0; // exterior and sling.
245244
+ this.averageNormal.setZero();
245245
+ this.radiansSum = 0.0;
245246
+ this.maxDeviationRadiansFromAverage = 0.0;
245247
+ }
245248
+ /** Add a normal to the evolving sum, scaled by radians in the corner */
245249
+ accumulateNormal(node, normal, inactiveMask) {
245250
+ if (node.isMaskSet(inactiveMask)) {
245251
+ this.numInactiveSectors++;
245252
+ }
245253
+ else {
245254
+ const sectorSweepRadians = _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.sectorSweepRadiansXYZ(node, normal);
245255
+ this.averageNormal.addScaledInPlace(normal, sectorSweepRadians);
245256
+ this.radiansSum += sectorSweepRadians;
245257
+ this.numActiveSectors++;
245258
+ }
245259
+ }
245260
+ /** normalize the accumulated normals. */
245261
+ finishNormalAveraging() {
245262
+ if (this.numActiveSectors > 0 && this.averageNormal.normalizeInPlace()) {
245263
+ return true;
245264
+ }
245265
+ return false;
245266
+ }
245267
+ /** Compute the deviation from average. update max deviation member */
245268
+ recordDeviation(normal, isActive) {
245269
+ if (isActive) {
245270
+ const radians = this.averageNormal.radiansTo(normal);
245271
+ this.maxDeviationRadiansFromAverage = Math.max(Math.abs(this.maxDeviationRadiansFromAverage), radians);
245272
+ }
245273
+ else {
245274
+ }
245275
+ }
245276
+ /** Return the max deviation as computed on prior calls to recordDeviation */
245277
+ get maxDeviationRadians() { return this.maxDeviationRadiansFromAverage; }
245278
+ }
245279
+ function emitSector(sector) {
245280
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
245281
+ OffsetMeshContext.stringDebugFunction(` Sector xyz ${sector.xyz.x},${sector.xyz.y},${sector.xyz.z} `);
245282
+ OffsetMeshContext.stringDebugFunction(` normal ${sector.normal.x},${sector.normal.y},${sector.normal.z} `);
245283
+ }
245284
+ }
245285
+ // facet properties used during offset.
245286
+ //
245287
+ class FacetOffsetProperties {
245288
+ constructor(facetIndex, normal) {
245289
+ this.facetIndex = facetIndex;
245290
+ this.facetNormal = normal;
245291
+ }
245292
+ }
245293
+ /**
245294
+ * Sector properties during offset.
245295
+ * * this.normal may be initially assigned as the facet normal but can mutate by
245296
+ * averaging with neighbors.
245297
+ * * this.xyz is initially the base mesh xyz but is expected to move along the normal.
245298
+ * * this.count is used locally in computations.
245299
+ */
245300
+ class SectorOffsetProperties {
245301
+ constructor(normal, xyz) {
245302
+ this.xyz = xyz;
245303
+ this.normal = normal;
245304
+ this.count = 0;
245305
+ }
245306
+ /**
245307
+ * Compute the angle between plane normals on opposite sides of the edge.
245308
+ * * parallel normals have zero angle.
245309
+ * * if the edge cuts inward to the volume behind the faces, the angle is negative.
245310
+ * * if the edge is outward (a convex edge) the the volume, the angle is positive.
245311
+ * @param edgeNodeA node on one side of the edge
245312
+ * @param edgeVector pre-allocated vector to receive vector along edge.
245313
+ * @param averageNormal pre-allocated vector to receive the average normal for a chamfer of the offset edge.
245314
+ * @param offsetDistance distance of offset being constructed. The sign of this resolves angle ambiguity.
245315
+ * @param radiansTolerance tolerance for large angle between normals.
245316
+ * @returns true if this edge has SectorOffsetProperties on both sides and the angle between normals angle exceeds radiansTolerance.
245317
+ */
245318
+ static edgeHasLargeExteriorAngleBetweenNormals(edgeNodeA, edgeVector, averageNormal, offsetDistance, radiansTolerance = Math.PI * 0.5) {
245319
+ const propsA = edgeNodeA.edgeTag;
245320
+ const edgeNodeB = edgeNodeA.edgeMate;
245321
+ const propsB = edgeNodeB.edgeTag;
245322
+ if (propsA !== undefined && propsB !== undefined) {
245323
+ edgeNodeA.vectorToFaceSuccessor(edgeVector);
245324
+ const radians = propsA.normal.signedRadiansTo(propsB.normal, edgeVector);
245325
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.split3WaySign(offsetDistance, -1, 1, 1) * radians >= radiansTolerance) {
245326
+ _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.createAdd2Scaled(propsA.normal, 1.0, propsB.normal, 1.0, averageNormal);
245327
+ if (averageNormal.normalizeInPlace())
245328
+ return true;
245329
+ }
245330
+ }
245331
+ return false;
245332
+ }
245333
+ static almostEqualNormals(sectorA, sectorB, radiansTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallAngleRadians) {
245334
+ return sectorA.normal.radiansTo(sectorB.normal) <= radiansTolerance;
245335
+ }
245336
+ static radiansBetweenNormals(sectorA, sectorB) {
245337
+ return sectorA.normal.radiansTo(sectorB.normal);
245338
+ }
245339
+ // Set the offset point this.xyz as sum of the nodeXyz + distance * this.normal
245340
+ setOffsetPointAtDistanceAtHalfEdge(halfEdge, distance) {
245341
+ halfEdge.getPoint3d(this.xyz);
245342
+ this.xyz.addScaledInPlace(this.normal, distance);
245343
+ }
245344
+ // Copy xyz from parameter into (preexisting object) xyz
245345
+ static setXYZAtHalfEdge(halfEdge, xyz) {
245346
+ const props = halfEdge.edgeTag;
245347
+ if (props !== undefined && xyz !== undefined)
245348
+ props.xyz.set(xyz.x, xyz.y, xyz.z);
245349
+ }
245350
+ // Set the offset point this.xyz directly
245351
+ setXYAndZ(xyz) {
245352
+ this.xyz.set(xyz.x, xyz.y, xyz.z);
245353
+ }
245354
+ // Look through the half edge to its properties. Set the normal there. Optionally set xyz from node xyz and offset distance
245355
+ static setNormalAtHalfEdge(halfEdge, uvw, distance) {
245356
+ const props = halfEdge.edgeTag;
245357
+ if (props !== undefined) {
245358
+ props.normal.set(uvw.x, uvw.y, uvw.z);
245359
+ if (distance !== undefined)
245360
+ props.setOffsetPointAtDistanceAtHalfEdge(halfEdge, distance);
245361
+ }
245362
+ }
245363
+ // Look through the half edge and its vertex successor to properties. Get the two normals. Return the angle sweeping from one to the next
245364
+ static sweepRadiansAroundNormal(nodeA, upVector) {
245365
+ const propsA = nodeA.edgeTag;
245366
+ const propsB = nodeA.vertexSuccessor.edgeTag;
245367
+ if (propsA !== undefined && propsB !== undefined) {
245368
+ return propsA.normal.planarRadiansTo(propsB.normal, upVector);
245369
+ }
245370
+ return undefined;
245371
+ }
245372
+ // Look through the half edge to its properties. return (if possible) the coordinates
245373
+ static getSectorPointAtHalfEdge(halfEdge, xyz, xyzArray) {
245374
+ const props = halfEdge.edgeTag;
245375
+ if (props !== undefined) {
245376
+ if (xyz !== undefined)
245377
+ xyz.setFromPoint3d(props.xyz);
245378
+ if (xyzArray !== undefined)
245379
+ xyzArray.push(props.xyz);
245380
+ return true;
245381
+ }
245382
+ return false;
245383
+ }
245384
+ // access the XYZ and push to the array (which makes copies, not reference)
245385
+ // return pointer to the SectorOffsetProperties
245386
+ static pushXYZ(xyzArray, halfEdge) {
245387
+ const sector = halfEdge.edgeTag;
245388
+ if (sector !== undefined)
245389
+ xyzArray.push(sector.xyz);
245390
+ return sector;
245391
+ }
245392
+ // Dereference to execute: accumulatingVector += halfEdge.edgeTag.normal * scale
245393
+ static accumulateScaledNormalAtHalfEdge(halfEdge, scale, accumulatingVector) {
245394
+ const sector = halfEdge.edgeTag;
245395
+ if (sector !== undefined)
245396
+ accumulatingVector.addScaledInPlace(sector.normal, scale);
245397
+ }
245398
+ }
245399
+ /*
245400
+ About Chamfer Edges ..... as constructed in addChamferTopologyToAllEdges
245401
+
245402
+ When edge vertex X to vertex Y has a sharp angle between normals, a "chamfer face" must be created to "fatten" it.
245403
+
245404
+ The original half edges (nodes) for the edge are AX and AY. These are "mates" in the halfEdge mental model. As always,
245405
+ AX is (as needed)
245406
+ (i) the preferred half edge for the left side of the edge moving from X to Y. (i.e. above the edge)
245407
+ (ii) a part of the face loop for the face to the left when proceeding CCW around the face to the above the drawn edge
245408
+ (iii) a part of the vertex loop around X
245409
+ Likewise, AY is (as needed)
245410
+ (i) the preferred half edge for the left side of the edge moving from Y to X (i.e. below the edge)
245411
+ (ii) a part of the face loop for the face to the left of the edge when proceeding CCW around the face below the edge.
245412
+ (iii) a part of the vertex loop around Y
245413
+
245414
+ AX------>
245415
+ X______________________________________________________________________Y
245416
+ <---AY
245417
+
245418
+ When the chamfer face is created, it needs to have a sliver face "inside the edge" -- something in the space here
245419
+
245420
+ AX------>
245421
+ _____________________________________________________________________
245422
+ / \
245423
+ X Y
245424
+ \_____________________________________________________________________/
245425
+ <---AY
245426
+
245427
+ The chamfer face will have a plane normal is the average of the two faces' plane normals.
245428
+
245429
+ The creation sequence for the chamfer face puts a slit "inside the edge" as above HalfEdges AX and AY remain as parts
245430
+ of their respective face loops. In addition, at each end a singleton edge "sling" face is inserted at each
245431
+ end of the sliver face.
245432
+
245433
+ The sequence is:
245434
+
245435
+ STEP 1: splitEdgeCreateSliver creates the sliver face with 2 half edges DX and DY
245436
+ STEP 2: splitEdge (with undefined as the "prior" edge) creates a sling with HalfEdge CX "inside" and BX "outside".
245437
+ (The sling face is not yet attached to X -- briefly floating in space)
245438
+ STEP 3: pinch of HalfEdges BX and DX inserts the sling face "inside" the slit face at the X end.
245439
+
245440
+ Steps 2 and 3 are executed from each end. Due to the symmetric structure, a 2-pass loop can apply the logic at each end without distinct names in code.
245441
+
245442
+ AX------>
245443
+ _______________________________________________________________
245444
+ / <---DY \
245445
+ / \
245446
+ / BX---> \
245447
+ / _______________ _______________ \
245448
+ | / \ / <----CY \ |
245449
+ |/ \ / \|
245450
+ X | | Y
245451
+ |\ CX---> / \ /|
245452
+ | \_______________/ \_______________/ |
245453
+ \ <---BY /
245454
+ \ /
245455
+ \ DX---> /
245456
+ \ ______________________________________________________________/
245457
+ <---AY
245458
+
245459
+ During the construction, the letters ABCD are used as above, but with prefixes emphasizing their role
245460
+ outsideAX, outsideAY
245461
+ slingB, slingC, sliverD
245462
+
245463
+ The "inside" sling faces (CX and CY) each have their own FacetOffsetProperties and SectorOffsetProperties.
245464
+ The sliver face has its own FacetOffsetProperties which are referenced by DX, BY, DY, BX.
245465
+ Each of those 4 has its own SectorOffSetProperties.
245466
+
245467
+ Important properties during offset construction:
245468
+ 1) the original graph always has original topology and coordinates
245469
+ 2) Each face of the original graph has a FacetOffsetProperties with a representative point and a normal. These are unchanged during the computation.
245470
+ 3) Each node has its own SectorOffsetProperties with a coordinate and normal independent of the parent node.
245471
+ 3.1 The first offset coordinates in each node are directly offset by face normal.
245472
+ 3.2 This creates mismatch across edges and around vertices.
245473
+ 3.3 Various sweeps "around each vertex" try to do intersections among appropriate offset planes to find
245474
+ common coordinates in place of the initial mismatches.
245475
+ 4) The independence of all the sectors allows the offset construction to fix things up in any order it chooses.
245476
+ 5) During the construction, the xyz in SectorOffsetProperties around a single vertex do NOT have to match.
245477
+ 6) At output time, there are three sweeps:
245478
+ 6.1: By face: Go around the face and output a facet with the coordinates in the various sectors.
245479
+ 6.2: By edge: For each edge, if the sector xyz match across both ends output nothing. If not, output a triangle or quad
245480
+ 6.3: By vertex: At each vertex, if all vertex coordinates match output nothing. Otherwise output a facet with all the coordinates.
245481
+ */
245482
+ class OffsetMeshContext {
245483
+ constructor(basePolyface, baseGraph, options) {
245484
+ this._basePolyface = basePolyface;
245485
+ this._baseGraph = baseGraph;
245486
+ this._breakMaskA = baseGraph.grabMask();
245487
+ this._breakMaskB = baseGraph.grabMask();
245488
+ this._insideOfChamferFace = baseGraph.grabMask();
245489
+ this._outsideOfChamferFace = baseGraph.grabMask();
245490
+ this._insideChamferSling = baseGraph.grabMask();
245491
+ this._outsideEndOfChamferFace = baseGraph.grabMask();
245492
+ this._exteriorMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR;
245493
+ this._offsetCoordinatesReassigned = baseGraph.grabMask();
245494
+ this._smoothRadiansBetweenNormals = options.smoothSingleAngleBetweenNormals.radians;
245495
+ this._chamferTurnRadians = options.chamferAngleBetweenNormals.radians;
245496
+ this._smoothAccumulatedRadiansBetweenNormals = options.smoothAccumulatedAngleBetweenNormals.radians;
245497
+ }
245498
+ /** "Exterior" side of a bare edge of the mesh */
245499
+ get exteriorMask() { return this._exteriorMask; }
245500
+ /** "First" sector of a smooth sequence. */
245501
+ get breakMaskA() { return this._breakMaskA; }
245502
+ /** "Last" sector of a smooth sequence. */
245503
+ get breakMaskB() { return this._breakMaskB; }
245504
+ /** This edge is on a chamfered face, and along the original edge */
245505
+ get insideOfChamferFace() { return this._insideOfChamferFace; }
245506
+ /** This is the original edge of a chamfer face */
245507
+ get outsideOfChamferFace() { return this._outsideOfChamferFace; }
245508
+ /** This edge is on a chamfered face, and at the end -- other side may be a sling */
245509
+ get insideChamferSling() { return this._insideChamferSling; }
245510
+ /** This is the outside of the end of a chamfer face -- i.e. the inside of a new face-at-vertex */
245511
+ get outsideEndOfChamferFace() { return this._outsideEndOfChamferFace; }
245512
+ // At each node . .
245513
+ // * Find the sector data
245514
+ // * recompute the sector point using node XYZ and sectorData normal.
245515
+ applyFaceNormalOffsetsToSectorData(distance) {
245516
+ this._baseGraph.announceNodes((_graph, node) => {
245517
+ const sectorData = node.edgeTag;
245518
+ if (sectorData !== undefined) {
245519
+ sectorData.setOffsetPointAtDistanceAtHalfEdge(node, distance);
245520
+ }
245521
+ return true;
245522
+ });
245523
+ }
245524
+ /**
245525
+ * * build a mesh offset by given distance.
245526
+ * * output the mesh to the given builder.
245527
+ * @param basePolyface original mesh
245528
+ * @param builder polyface builder to receive the new mesh.
245529
+ * @param distance signed offset distance.
245530
+ */
245531
+ static buildOffsetMeshWithEdgeChamfers(basePolyface, builder, distance, options) {
245532
+ const baseGraph = this.buildBaseGraph(basePolyface);
245533
+ if (baseGraph !== undefined) {
245534
+ const offsetBuilder = new OffsetMeshContext(basePolyface, baseGraph, options);
245535
+ offsetBuilder.applyFaceNormalOffsetsToSectorData(distance);
245536
+ if (OffsetMeshContext.graphDebugFunction !== undefined)
245537
+ OffsetMeshContext.graphDebugFunction("BaseGraph", baseGraph, offsetBuilder._breakMaskA, offsetBuilder._breakMaskB);
245538
+ const outputSelector = options.outputSelector ? options.outputSelector : {
245539
+ outputOffsetsFromFaces: true,
245540
+ outputOffsetsFromEdges: true,
245541
+ outputOffsetsFromVertices: true,
245542
+ };
245543
+ if (isDefinedAndTrue(outputSelector.outputOffsetsFromFacesBeforeChamfers))
245544
+ offsetBuilder.announceFacetsWithSectorCoordinatesAroundFaces(builder);
245545
+ offsetBuilder.addChamferTopologyToAllEdges(options, distance);
245546
+ offsetBuilder.computeOffsetFacetIntersections(distance);
245547
+ if (OffsetMeshContext.graphDebugFunction !== undefined)
245548
+ OffsetMeshContext.graphDebugFunction("after computeEdgeChamfers", baseGraph, offsetBuilder._breakMaskA, offsetBuilder._breakMaskB);
245549
+ if (isDefinedAndTrue(outputSelector.outputOffsetsFromFaces))
245550
+ offsetBuilder.announceFacetsWithSectorCoordinatesAroundFaces(builder);
245551
+ if (isDefinedAndTrue(outputSelector.outputOffsetsFromEdges))
245552
+ offsetBuilder.announceFacetsWithSectorCoordinatesAroundEdges(builder);
245553
+ if (isDefinedAndTrue(outputSelector.outputOffsetsFromVertices))
245554
+ offsetBuilder.announceFacetsWithSectorCoordinatesAroundVertices(builder);
245555
+ }
245556
+ }
245557
+ /**
245558
+ * For each face of the graph, shift vertices by offsetDistance and emit to the builder as a facet
245559
+ * @param polyfaceBuilder
245560
+ */
245561
+ announceSimpleOffsetFromFaces(polyfaceBuilder, offsetDistance) {
245562
+ const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
245563
+ const xyz = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create(); // reused at each point around each facet.
245564
+ const uvw = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reused once per facet
245565
+ const announceNodeAroundFace = (node) => {
245566
+ node.getPoint3d(xyz);
245567
+ xyz.addInPlace(uvw);
245568
+ xyzLoop.push(xyz);
245569
+ return 0;
245570
+ };
245571
+ this._baseGraph.announceFaceLoops((_graph, seed) => {
245572
+ if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR)) {
245573
+ const facetProperties = seed.faceTag;
245574
+ uvw.setFromVector3d(facetProperties.facetNormal.direction);
245575
+ uvw.scaleInPlace(offsetDistance);
245576
+ xyzLoop.length = 0;
245577
+ seed.sumAroundFace(announceNodeAroundFace);
245578
+ polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
245579
+ }
245580
+ return true;
245581
+ });
245582
+ }
245583
+ /**
245584
+ * For each face of the graph, output the xyz of the sector data
245585
+ * @param polyfaceBuilder
245586
+ */
245587
+ announceFacetsWithSectorCoordinatesAroundFaces(polyfaceBuilder) {
245588
+ const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
245589
+ // For face loop visits .. get the point from the sector data.
245590
+ const announceNodeAroundFace = (node) => {
245591
+ const sectorData = node.edgeTag;
245592
+ if (sectorData !== undefined) {
245593
+ xyzLoop.push(sectorData.xyz);
245594
+ }
245595
+ return 0;
245596
+ };
245597
+ this._baseGraph.announceFaceLoops((_graph, seed) => {
245598
+ if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR)) {
245599
+ xyzLoop.length = 0;
245600
+ seed.sumAroundFace(announceNodeAroundFace);
245601
+ if (xyzLoop.length > 2)
245602
+ polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
245603
+ }
245604
+ return true;
245605
+ });
245606
+ }
245607
+ countBits(mask) {
245608
+ let n = 0;
245609
+ let mask1 = mask;
245610
+ while (mask1 !== 0) {
245611
+ if (mask1 & 0x01)
245612
+ n++;
245613
+ mask1 = mask1 >> 1;
245614
+ }
245615
+ return n;
245616
+ }
245617
+ /**
245618
+ * For each edge of the graph . .
245619
+ * * Collect coordinates in 4 sectors going around the edge
245620
+ * * Compress with tight tolerance so adjacent sectors with clean point match reduce to a single point.
245621
+ * * Emit as a facet.
245622
+ * @param polyfaceBuilder
245623
+ */
245624
+ announceFacetsWithSectorCoordinatesAroundEdges(polyfaceBuilder) {
245625
+ const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
245626
+ const primaryCompressionTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance;
245627
+ const allMasksForEdgesToIgnore = this._exteriorMask
245628
+ | this._outsideEndOfChamferFace
245629
+ | this._outsideOfChamferFace
245630
+ | this._insideOfChamferFace
245631
+ | this._insideChamferSling;
245632
+ this._baseGraph.announceEdges((_graph, nodeA) => {
245633
+ // This starts by looking for EXTERIOR on both sides ...
245634
+ if (nodeA.findMaskAroundEdge(this._exteriorMask) !== undefined) {
245635
+ return true;
245636
+ }
245637
+ else if (!nodeA.isMaskSet(allMasksForEdgesToIgnore)) { // By design, we believe that these two test for allMasksForEdgesToIgnore condition would catch the EXTERIOR case above
245638
+ const nodeB = nodeA.faceSuccessor;
245639
+ const nodeC = nodeA.edgeMate;
245640
+ if (!nodeC.isMaskSet(allMasksForEdgesToIgnore)) {
245641
+ const nodeD = nodeC.faceSuccessor;
245642
+ xyzLoop.clear();
245643
+ SectorOffsetProperties.getSectorPointAtHalfEdge(nodeA, undefined, xyzLoop);
245644
+ SectorOffsetProperties.getSectorPointAtHalfEdge(nodeB, undefined, xyzLoop);
245645
+ SectorOffsetProperties.getSectorPointAtHalfEdge(nodeC, undefined, xyzLoop);
245646
+ SectorOffsetProperties.getSectorPointAtHalfEdge(nodeD, undefined, xyzLoop);
245647
+ _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__.PolylineCompressionContext.compressInPlaceByShortEdgeLength(xyzLoop, primaryCompressionTolerance);
245648
+ if (xyzLoop.length > 2) {
245649
+ polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
245650
+ }
245651
+ }
245652
+ }
245653
+ else {
245654
+ return true;
245655
+ }
245656
+ return true;
245657
+ });
245658
+ }
245659
+ getCoordinateString(node, showXYZ = true, showFaceSuccessorXYZ = false) {
245660
+ if (showXYZ) {
245661
+ if (showFaceSuccessorXYZ) {
245662
+ return `${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node)} ==> ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node.faceSuccessor)}`;
245663
+ }
245664
+ else {
245665
+ return `${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node)}`;
245666
+ }
245667
+ }
245668
+ else {
245669
+ if (showFaceSuccessorXYZ) {
245670
+ return `==> ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node.faceSuccessor)}`;
245671
+ }
245672
+ else {
245673
+ return "";
245674
+ }
245675
+ }
245676
+ }
245677
+ inspectMasks(node, showXYZ = true, showFaceSuccessorXYZ = false) {
245678
+ const s = "[";
245679
+ const v = s.concat(node.id.toString(), node.isMaskSet(this._exteriorMask) ? "X" : "", node.isMaskSet(this.breakMaskA) ? "A" : "", node.isMaskSet(this.breakMaskB) ? "B" : "", node.isMaskSet(this.insideChamferSling) ? "(sling)" : "", node.isMaskSet(this.insideOfChamferFace) ? "(in chamfer)" : "", node.isMaskSet(this.outsideEndOfChamferFace) ? "(@sling)" : "", node.isMaskSet(this.outsideOfChamferFace) ? "(@chamfer)" : "", this.getCoordinateString(node, showXYZ, showFaceSuccessorXYZ), "]");
245680
+ return v;
245681
+ }
245682
+ /**
245683
+ * For each face of the graph, output the xyz of the sector data
245684
+ * @param polyfaceBuilder
245685
+ */
245686
+ announceFacetsWithSectorCoordinatesAroundVertices(polyfaceBuilder) {
245687
+ const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
245688
+ const primaryCompressionTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance;
245689
+ this._baseGraph.announceVertexLoops((_graph, seed) => {
245690
+ if (!seed.findMaskAroundVertex(this._exteriorMask)) {
245691
+ xyzLoop.length = 0;
245692
+ seed.sumAroundVertex((node) => {
245693
+ if (!node.isMaskSet(this._insideChamferSling))
245694
+ SectorOffsetProperties.getSectorPointAtHalfEdge(node, undefined, xyzLoop);
245695
+ return 0.0;
245696
+ });
245697
+ _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__.PolylineCompressionContext.compressInPlaceByShortEdgeLength(xyzLoop, primaryCompressionTolerance);
245698
+ if (xyzLoop.length > 2) {
245699
+ polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
245700
+ }
245701
+ }
245702
+ return true;
245703
+ });
245704
+ }
245705
+ /**
245706
+ * * Exterior half edges have HalfEdgeMask.EXTERIOR
245707
+ * * All interior half edge around a facet have facetTag pointing to a facetProperties object for that facet.
245708
+ * * the facetOffsetProperties object has the simple facet normal.
245709
+ * * Each half edge has edgeTag pointing to to a sectorOffsetProperties object
245710
+ * * the sectorOffsetProperties has a copy of the facet normal.
245711
+ * @param polyface
245712
+ * @returns graph
245713
+ */
245714
+ static buildBaseGraph(polyface) {
245715
+ const graphBuilder = new _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_5__.HalfEdgeGraphFromIndexedLoopsContext();
245716
+ const visitor = polyface.createVisitor();
245717
+ const xyzA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
245718
+ const xyzB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
245719
+ for (visitor.reset(); visitor.moveToNextFacet();) {
245720
+ const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_6__.PolygonOps.centroidAreaNormal(visitor.point);
245721
+ if (normal !== undefined) {
245722
+ const edgeA = graphBuilder.insertLoop(visitor.pointIndex, (insideHalfEdge) => {
245723
+ const mate = insideHalfEdge.edgeMate;
245724
+ polyface.data.getPoint(insideHalfEdge.i, xyzA);
245725
+ insideHalfEdge.setXYZ(xyzA);
245726
+ polyface.data.getPoint(mate.i, xyzB);
245727
+ mate.setXYZ(xyzB);
245728
+ });
245729
+ const facetProperties = new FacetOffsetProperties(visitor.currentReadIndex(), normal);
245730
+ if (edgeA !== undefined) {
245731
+ edgeA.sumAroundFace((edgeB) => {
245732
+ edgeB.faceTag = facetProperties;
245733
+ edgeB.edgeTag = new SectorOffsetProperties(normal.direction.clone(), edgeB.getPoint3d());
245734
+ return 0;
245735
+ });
245736
+ }
245737
+ }
245738
+ }
245739
+ return graphBuilder.graph;
245740
+ }
245741
+ setOffsetAtDistanceAroundVertex(vertexSeed, distance, ignoreChamfers = false) {
245742
+ vertexSeed.sumAroundVertex((nodeAroundVertex) => {
245743
+ const props = nodeAroundVertex.edgeTag;
245744
+ if (props !== undefined) {
245745
+ if (ignoreChamfers && this.isInsideChamferOrSling(vertexSeed)) {
245746
+ // SKIP !!
245747
+ }
245748
+ else {
245749
+ props.setOffsetPointAtDistanceAtHalfEdge(nodeAroundVertex, distance);
245750
+ }
245751
+ }
245752
+ return 0.0;
245753
+ });
245754
+ }
245755
+ setOffsetXYAndZAroundVertex(vertexSeed, xyz) {
245756
+ vertexSeed.sumAroundVertex((nodeAroundVertex) => {
245757
+ const props = nodeAroundVertex.edgeTag;
245758
+ if (props !== undefined) {
245759
+ props.setXYAndZ(xyz);
245760
+ nodeAroundVertex.setMask(this._offsetCoordinatesReassigned);
245761
+ }
245762
+ return 0.0;
245763
+ });
245764
+ }
245765
+ /**
245766
+ * * start at vertexSeed.
245767
+ * * set the offset point at up to (and including) one with (a) this._breakMaskB or (b) this._exteriorMask
245768
+ * *
245769
+ * @param vertexSeed first node to mark.
245770
+ * @param f function to call to announce each node and its sector properties.
245771
+ * @returns number of nodes marked.
245772
+ */
245773
+ announceNodeAndSectorPropertiesInSmoothSector(vertexSeed, f) {
245774
+ let n = 0;
245775
+ for (let currentNode = vertexSeed;; currentNode = currentNode.vertexSuccessor) {
245776
+ const props = currentNode.edgeTag;
245777
+ if (props !== undefined) {
245778
+ f(currentNode, props);
245779
+ n++;
245780
+ }
245781
+ if (currentNode.isMaskSet(this._breakMaskB))
245782
+ return n;
245783
+ // REMARK: these additional exit conditions should not happen if (a) the graph is properly marked and (b) the start node is not exterior.
245784
+ if (currentNode.isMaskSet(this._exteriorMask))
245785
+ return n;
245786
+ if (currentNode === vertexSeed && n === 0)
245787
+ return n;
245788
+ }
245789
+ }
245790
+ computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data) {
245791
+ data.clear();
245792
+ const inactiveNodeMask = this._exteriorMask | this._insideChamferSling;
245793
+ vertexSeed.sumAroundVertex((node) => {
245794
+ const sectorData = node.edgeTag;
245795
+ if (sectorData)
245796
+ data.accumulateNormal(node, sectorData.normal, inactiveNodeMask);
245797
+ return 0.0;
245798
+ });
245799
+ if (!data.finishNormalAveraging()) {
245800
+ return undefined;
245801
+ }
245802
+ vertexSeed.sumAroundVertex((node) => {
245803
+ const sectorData = node.edgeTag;
245804
+ if (sectorData)
245805
+ data.recordDeviation(sectorData.normal, !node.isMaskSet(inactiveNodeMask));
245806
+ return 0.0;
245807
+ });
245808
+ return data.maxDeviationRadians;
245809
+ }
245810
+ assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedDeviationRadians, data, distance) {
245811
+ const maxDeviationRadians = this.computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data);
245812
+ if (OffsetMeshContext.stringDebugFunction) {
245813
+ OffsetMeshContext.stringDebugFunction(`XYZ ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(vertexSeed)} Average Normal ${data.averageNormal.toJSON()}`);
245814
+ OffsetMeshContext.stringDebugFunction(` angle ratio ${data.radiansSum / (2 * Math.PI)} maxDeviation ${data.maxDeviationRadiansFromAverage}`);
245815
+ }
245816
+ if (maxDeviationRadians !== undefined && maxDeviationRadians <= maxAllowedDeviationRadians) {
245817
+ vertexSeed.sumAroundVertex((node) => {
245818
+ SectorOffsetProperties.setNormalAtHalfEdge(node, data.averageNormal, distance);
245819
+ return 0;
245820
+ });
245821
+ return true;
245822
+ }
245823
+ return false;
245824
+ }
245825
+ /** Search around a vertex for a sector which has a different normal from its vertexPredecessor.
245826
+ * * The seed will be the first candidate considered
245827
+ */
245828
+ markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed) {
245829
+ vertexSeed.clearMaskAroundVertex(this._breakMaskA);
245830
+ vertexSeed.clearMaskAroundVertex(this._breakMaskB);
245831
+ const smoothSingleSmoothRadiansBetweenNormals = this._smoothRadiansBetweenNormals;
245832
+ const accumulatedRadiansBetweenNormals = this._smoothAccumulatedRadiansBetweenNormals;
245833
+ // Step 1: Examine the edge between nodeA and the sector on its vertex predecessor side. This (alone) determines single angle breaks.
245834
+ let numBreaks = 0;
245835
+ let nodeP = vertexSeed;
245836
+ let _numSmooth = 0;
245837
+ do {
245838
+ const nodeQ = nodeP.edgeMate;
245839
+ const nodeR = nodeQ.faceSuccessor; // same as nodeA.vertexPredecessor
245840
+ if (nodeP.isMaskSet(this._exteriorMask)) {
245841
+ if (!nodeQ.isMaskSet(this._exteriorMask)) {
245842
+ nodeR.setMask(this._breakMaskB);
245843
+ numBreaks++;
245844
+ }
245845
+ }
245846
+ else {
245847
+ if (nodeP.isMaskSet(this._outsideOfChamferFace)) {
245848
+ nodeP.setMask(this._breakMaskA);
245849
+ }
245850
+ else if (nodeP.isMaskSet(this._outsideEndOfChamferFace)) {
245851
+ nodeP.setMask(this._breakMaskA);
245852
+ nodeP.setMask(this._breakMaskB);
245853
+ }
245854
+ else if (nodeP.isMaskSet(this._insideChamferSling)) {
245855
+ // This is the sling. It's normal is along edge -- not really a break.
245856
+ }
245857
+ else if (nodeP.isMaskSet(this._insideOfChamferFace)) {
245858
+ nodeP.setMask(this._breakMaskA);
245859
+ nodeP.setMask(this._breakMaskB);
245860
+ nodeR.setMask(this._breakMaskB);
245861
+ }
245862
+ else if (nodeQ.isMaskSet(this._exteriorMask)) {
245863
+ numBreaks++;
245864
+ nodeP.setMask(this._breakMaskA);
245865
+ }
245866
+ else if (!SectorOffsetProperties.almostEqualNormals(nodeP.edgeTag, nodeR.edgeTag, smoothSingleSmoothRadiansBetweenNormals)) {
245867
+ nodeP.setMask(this._breakMaskA);
245868
+ numBreaks++;
245869
+ nodeR.setMask(this._breakMaskB);
245870
+ }
245871
+ else {
245872
+ _numSmooth++;
245873
+ }
245874
+ }
245875
+ nodeP = nodeP.vertexSuccessor;
245876
+ } while (nodeP !== vertexSeed);
245877
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
245878
+ OffsetMeshContext.stringDebugFunction(` numSkip ${_numSmooth} `);
245879
+ if (numBreaks === 0) {
245880
+ // make the first vertex a break so subsequent searches have a place to start
245881
+ vertexSeed.setMask(this._breakMaskA);
245882
+ vertexSeed.vertexPredecessor.setMask(this._breakMaskB);
245883
+ numBreaks = 1;
245884
+ }
245885
+ // Step 2: At each single break, sweep forward to its closing breakB. Insert breaks at accumulated angles.
245886
+ // (minor TODO: for the insertion case, try to split more equally.)
245887
+ const nodeAStart = nodeP.findMaskAroundVertex(this._breakMaskA);
245888
+ if (nodeAStart !== undefined) {
245889
+ nodeP = nodeAStart;
245890
+ do {
245891
+ if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) {
245892
+ let accumulatedRadians = 0.0;
245893
+ do {
245894
+ const nodeB = nodeP.vertexSuccessor;
245895
+ accumulatedRadians += SectorOffsetProperties.radiansBetweenNormals(nodeP.edgeTag, nodeB.edgeTag);
245896
+ if (accumulatedRadians > accumulatedRadiansBetweenNormals) {
245897
+ nodeP.setMask(this._breakMaskB);
245898
+ nodeB.setMask(this._breakMaskA);
245899
+ numBreaks++;
245900
+ accumulatedRadians = 0.0;
245901
+ }
245902
+ nodeP = nodeB;
245903
+ } while (!nodeP.isMaskSet(this._breakMaskB));
245904
+ }
245905
+ else {
245906
+ nodeP = nodeP.vertexSuccessor;
245907
+ }
245908
+ } while (nodeP !== nodeAStart);
245909
+ }
245910
+ if (numBreaks > 0 && nodeAStart !== undefined) {
245911
+ // In each compound sector, accumulate and install average normal.
245912
+ nodeP = nodeAStart;
245913
+ const averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
245914
+ const edgeVectorU = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
245915
+ const edgeVectorV = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
245916
+ averageNormal.setZero();
245917
+ do {
245918
+ if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) {
245919
+ let nodeQ = nodeP;
245920
+ averageNormal.setZero();
245921
+ for (;;) {
245922
+ nodeQ.vectorToFaceSuccessor(edgeVectorU);
245923
+ nodeQ.vectorToFacePredecessor(edgeVectorV);
245924
+ let singleSectorRadians = edgeVectorU.signedRadiansTo(edgeVectorV, nodeQ.faceTag.facetNormal.direction);
245925
+ if (singleSectorRadians < 0.0)
245926
+ singleSectorRadians += Math.PI * 2;
245927
+ SectorOffsetProperties.accumulateScaledNormalAtHalfEdge(nodeQ, singleSectorRadians, averageNormal);
245928
+ if (nodeQ.isMaskSet(this._breakMaskB))
245929
+ break;
245930
+ nodeQ = nodeQ.vertexSuccessor;
245931
+ }
245932
+ if (averageNormal.normalizeInPlace()) {
245933
+ nodeQ = nodeP;
245934
+ for (;;) {
245935
+ SectorOffsetProperties.setNormalAtHalfEdge(nodeQ, averageNormal);
245936
+ if (nodeQ.isMaskSet(this._breakMaskB))
245937
+ break;
245938
+ nodeQ = nodeQ.vertexSuccessor;
245939
+ }
245940
+ }
245941
+ }
245942
+ nodeP = nodeP.vertexSuccessor;
245943
+ } while (nodeP !== nodeAStart);
245944
+ }
245945
+ }
245946
+ /** Compute the point of intersection of the planes in the sectors of 3 half edges */
245947
+ compute3SectorIntersection(nodeA, nodeB, nodeC, result) {
245948
+ const sectorA = nodeA.edgeTag;
245949
+ const sectorB = nodeB.edgeTag;
245950
+ const sectorC = nodeC.edgeTag;
245951
+ const vector = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorC.xyz, sectorC.normal, result);
245952
+ return vector;
245953
+ }
245954
+ /** Compute the point of intersection of the planes in the sectors of 3 half edges */
245955
+ compute3SectorIntersectionDebug(nodeA, nodeB, nodeC, result) {
245956
+ const sectorA = nodeA.edgeTag;
245957
+ const sectorB = nodeB.edgeTag;
245958
+ const sectorC = nodeC.edgeTag;
245959
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
245960
+ OffsetMeshContext.stringDebugFunction(`compute3${this.inspectMasks(nodeA)}${this.inspectMasks(nodeB)}${this.inspectMasks(nodeC)} `);
245961
+ for (const sector of [sectorA, sectorB, sectorC])
245962
+ emitSector(sector);
245963
+ }
245964
+ const vector = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorC.xyz, sectorC.normal, result);
245965
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
245966
+ if (vector === undefined)
245967
+ OffsetMeshContext.stringDebugFunction(" NO INTERSECTION");
245968
+ else
245969
+ OffsetMeshContext.stringDebugFunction(` ComputedVector ${vector.x},${vector.y},${vector.z} `);
245970
+ }
245971
+ return vector;
245972
+ }
245973
+ /** Compute the point of intersection of the planes in the sectors of 2 half edges, using cross product of their normals to resolve */
245974
+ compute2SectorIntersection(nodeA, nodeB, result) {
245975
+ const sectorA = nodeA.edgeTag;
245976
+ const sectorB = nodeB.edgeTag;
245977
+ const normalC = sectorA.normal.crossProduct(sectorB.normal);
245978
+ return _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorB.xyz, normalC, result);
245979
+ }
245980
+ /**
245981
+ * * at input, graph has all original faces and edges
245982
+ * * each sector points to a faceProperties with original facet normal
245983
+ * * at exit:
245984
+ * * new "chamfer faces" are added outside of edges with angle between normal sin excess of options.chamferTurnAngleBetweenNormals
245985
+ * * the original edge is split along its length to create space
245986
+ * * one edge "along" each direction inside the slit.
245987
+ * * a sling edge at each end of the slit.
245988
+ * * outside of the sling is part of the slit face loop.
245989
+ * * inside is a single-node face
245990
+ * * thus the slit itself has 4 nodes.
245991
+ * * the two nodes at each end can thus contain the two distinct points at that end of the chamfer.
245992
+ * * all 4 nodes of the slit face point to a new FacetOffsetProperties with the average normal.
245993
+ * * the inside of each sling face has
245994
+ * * original vertex coordinates in the node
245995
+ * * face properties with a normal pointing outward from that end of the original edge -- hence define a plane that can clip the chamfer
245996
+ * * the two points at each end of the chamfer are computed as the intersection of
245997
+ * * chamfer plane
245998
+ * * sling plane
245999
+ * * adjacent plane of the face on the other side of the edge being chamfered.
246000
+ * @param distance distance to offset. The sign of this is important in the chamfer construction.
246001
+ */
246002
+ addChamferTopologyToAllEdges(options, distance) {
246003
+ const edgesToChamfer = [];
246004
+ const chamferRadians = options.chamferAngleBetweenNormals.radians;
246005
+ const vertexXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create(); // reuse
246006
+ const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
246007
+ const outwardEdgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
246008
+ const averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
246009
+ // collect all the edges with sharp turn angle.
246010
+ this._baseGraph.announceEdges((_graph, edgeNode) => {
246011
+ if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(edgeNode, edgeVector, averageNormal, distance, chamferRadians)) {
246012
+ edgesToChamfer.push(edgeNode);
246013
+ return true;
246014
+ }
246015
+ return true;
246016
+ });
246017
+ // Create sliver faces.
246018
+ // Sliver face gets an average normal from its neighbors.
246019
+ // outsideA is the HalfEdge labeled A in the diagram.
246020
+ // sliverDX and sliverDY are the edges "inside the sliver" at the respective X and Y ends.
246021
+ for (const outsideA of edgesToChamfer) {
246022
+ // remark: this recomputes as in collection round.
246023
+ if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(outsideA, edgeVector, averageNormal, chamferRadians)) {
246024
+ // This copies coordinates and vertex id .... sectorOffsetProperties are delayed until late in the 2-pass loop below.
246025
+ // The returned HalfEdge is labeled D in the diagram
246026
+ const sliverDX = this._baseGraph.splitEdgeCreateSliverFace(outsideA);
246027
+ const sliverDY = sliverDX.facePredecessor;
246028
+ const offsetPoint = sliverDX.getPoint3d();
246029
+ offsetPoint.addScaledInPlace(averageNormal, distance);
246030
+ const ray = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__.Ray3d.createCapture(offsetPoint, averageNormal.clone());
246031
+ const facetProperties = new FacetOffsetProperties(-1, ray);
246032
+ // for each side (hence end) of the sliver face, set mask and install a sling loop for the anticipated end of the chamfer face
246033
+ // new node names in the loop omit X or Y suffix because that is implied by which pass is running.
246034
+ let s = -1.0;
246035
+ for (const sliverD of [sliverDX, sliverDY]) {
246036
+ edgeVector.scale(s, outwardEdgeVector);
246037
+ sliverD.getPoint3d(vertexXYZ);
246038
+ sliverD.setMask(this._insideOfChamferFace);
246039
+ sliverD.edgeMate.setMask(this._outsideOfChamferFace);
246040
+ // mark and reference the chamfer face.
246041
+ sliverD.faceTag = facetProperties;
246042
+ // sling at this end
246043
+ const slingB = this._baseGraph.splitEdge(undefined, vertexXYZ.x, vertexXYZ.y, vertexXYZ.z, sliverD.i);
246044
+ const slingC = slingB.edgeMate;
246045
+ slingB.setMask(this._outsideEndOfChamferFace);
246046
+ slingB.faceTag = facetProperties;
246047
+ slingC.setMask(this._insideChamferSling);
246048
+ _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(sliverD, slingB);
246049
+ const endNormal = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__.Ray3d.create(vertexXYZ, outwardEdgeVector); // clones the inputs
246050
+ const slingFaceProperties = new FacetOffsetProperties(-1, endNormal);
246051
+ slingC.faceTag = slingFaceProperties;
246052
+ // initialize sectors with existing vertex point.
246053
+ sliverD.edgeTag = new SectorOffsetProperties(averageNormal.clone(), offsetPoint.clone());
246054
+ slingB.edgeTag = new SectorOffsetProperties(averageNormal.clone(), offsetPoint.clone());
246055
+ slingC.edgeTag = new SectorOffsetProperties(outwardEdgeVector.clone(), vertexXYZ.clone());
246056
+ // OffsetMeshContext.stringDebugFunction("Chamfer Setup");
246057
+ const chamferPointE = this.compute3SectorIntersection(sliverD, sliverD.edgeMate, slingC);
246058
+ const chamferPointF = this.compute3SectorIntersection(slingB, slingB.vertexSuccessor, slingC);
246059
+ // sliverD.edgeTag = new SectorOffsetProperties(averageNormal.clone(), vertexXYZ.clone());
246060
+ SectorOffsetProperties.setXYZAtHalfEdge(sliverD, chamferPointE);
246061
+ SectorOffsetProperties.setXYZAtHalfEdge(slingB, chamferPointF);
246062
+ s *= -1.0;
246063
+ }
246064
+ }
246065
+ }
246066
+ }
246067
+ /**
246068
+ * * at input:
246069
+ * * Each node points to sectorOffsetProperties with previously computed XYZ (presumably mismatched)
246070
+ * * at exit:
246071
+ * * Each sectorOffsetProperties has an offset point computed with consideration of offset planes in the neighborhood.
246072
+ * @param distance distance to offset.
246073
+ */
246074
+ computeOffsetFacetIntersections(distance) {
246075
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
246076
+ OffsetMeshContext.stringDebugFunction("***** recompute intersections");
246077
+ const breakEdges = [];
246078
+ const vertexXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
246079
+ const chamferXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
246080
+ const maxVertexMove = 2.0 * distance;
246081
+ const averageNormalData = new AverageNormalData();
246082
+ const maxAllowedNormalDeviationRadians = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_9__.Angle.degreesToRadians(25.0);
246083
+ //
246084
+ // FOR EACH VERTEX
246085
+ //
246086
+ this._baseGraph.announceVertexLoops((_graph, vertexSeedA) => {
246087
+ // reposition to an important vertex.
246088
+ // first choice: a chamfer face.
246089
+ let vertexSeed = vertexSeedA.findMaskAroundVertex(this._outsideEndOfChamferFace);
246090
+ if (vertexSeed === undefined)
246091
+ vertexSeed = vertexSeedA.findMaskAroundVertex(this._breakMaskA);
246092
+ if (vertexSeed === undefined)
246093
+ vertexSeed = vertexSeedA;
246094
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
246095
+ OffsetMeshContext.stringDebugFunction("");
246096
+ OffsetMeshContext.stringDebugFunction(` VERTEX LOOP ${vertexSeed.getPoint3d().toJSON()} `);
246097
+ vertexSeed.sumAroundVertex((node) => { OffsetMeshContext.stringDebugFunction(this.inspectMasks(node, false, true)); return 0; });
246098
+ }
246099
+ // Take care of the easiest vertices directly . . . note that this returns from the lambda, not computeOffsetFacetIntersections
246100
+ if (this.assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedNormalDeviationRadians, averageNormalData, distance))
246101
+ return true;
246102
+ this.markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed);
246103
+ this.setOffsetAtDistanceAroundVertex(vertexSeed, distance, true);
246104
+ vertexSeed.collectMaskedEdgesAroundVertex(this._breakMaskA, true, breakEdges);
246105
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
246106
+ OffsetMeshContext.stringDebugFunction(` BREAK EDGES from ${this.inspectMasks(vertexSeed, true, false)}`);
246107
+ for (const node of breakEdges) {
246108
+ OffsetMeshContext.stringDebugFunction(this.inspectMasks(node, false, true));
246109
+ }
246110
+ }
246111
+ if (breakEdges.length <= 1) {
246112
+ // just one smooth sequence.
246113
+ // everything is set already.
246114
+ }
246115
+ else if (breakEdges.length === 2) {
246116
+ // exterior vertex with two incident smooth
246117
+ const vectorFromOrigin = this.compute2SectorIntersection(breakEdges[0], breakEdges[1]);
246118
+ if (vectorFromOrigin !== undefined) {
246119
+ this.setOffsetXYAndZAroundVertex(vertexSeed, vectorFromOrigin);
246120
+ }
246121
+ }
246122
+ else if (breakEdges.length === 3) {
246123
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
246124
+ OffsetMeshContext.stringDebugFunction(` Vertex Update just ${breakEdges.length} `);
246125
+ const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[0], breakEdges[1], breakEdges[2]);
246126
+ if (vectorFromOrigin !== undefined) {
246127
+ this.setOffsetXYAndZAroundVertex(vertexSeed, vectorFromOrigin);
246128
+ }
246129
+ // simple 3-face corner . . .
246130
+ }
246131
+ else {
246132
+ // Lots and Lots of edges
246133
+ // each set of 3 sectors independently generates an offset for its central sector.
246134
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
246135
+ OffsetMeshContext.stringDebugFunction(` Vertex Update breakEdges ${breakEdges.length} `);
246136
+ vertexSeed.getPoint3d(vertexXYZ);
246137
+ // Pass 1 -- look for intersection among multiple chamfers
246138
+ for (let i = 0; i < breakEdges.length; i++) {
246139
+ const i0 = i;
246140
+ const i1 = (i0 + 1) % breakEdges.length;
246141
+ const i2 = (i1 + 1) % breakEdges.length;
246142
+ if (breakEdges[i0].isMaskSet(this._outsideEndOfChamferFace)
246143
+ && breakEdges[i1].isMaskSet(this._outsideOfChamferFace)
246144
+ && breakEdges[i2].isMaskSet(this._insideOfChamferFace)) {
246145
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
246146
+ OffsetMeshContext.stringDebugFunction(` ChamferChamfer Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `);
246147
+ const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]);
246148
+ if (vectorFromOrigin !== undefined) {
246149
+ // Treat all 3 spots as possibly compound sequences
246150
+ for (const iOutput of [i0, i1, i2]) {
246151
+ this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[iOutput], (node, properties) => {
246152
+ properties.setXYAndZ(vectorFromOrigin);
246153
+ node.setMask(this._offsetCoordinatesReassigned);
246154
+ });
246155
+ }
246156
+ // Since all three were reset, skip past. This is done on the acyclic integer that controls the loop.
246157
+ i += 2;
246158
+ }
246159
+ }
246160
+ }
246161
+ // Pass 2 -- look for unassigned nodes just before or after a chamfer.
246162
+ // The chamfer wins
246163
+ for (let i = 0; i < breakEdges.length; i++) {
246164
+ const i0 = i;
246165
+ const i1 = (i0 + 1) % breakEdges.length;
246166
+ if (this.isInsideSling(breakEdges[i0], breakEdges[i1]))
246167
+ continue;
246168
+ if (!this.isOffsetAssigned(breakEdges[i0])
246169
+ && breakEdges[i1].isMaskSet(this.insideOfChamferFace)) {
246170
+ this.transferXYZFromNodeToSmoothSector(breakEdges[i1], breakEdges[i0], "push left from chamfer", chamferXYZ);
246171
+ }
246172
+ else if (!this.isOffsetAssigned(breakEdges[i1])
246173
+ && breakEdges[i0].isMaskSet(this.outsideEndOfChamferFace)) {
246174
+ this.transferXYZFromNodeToSmoothSector(breakEdges[i0], breakEdges[i1], "push right from chamfer", chamferXYZ);
246175
+ }
246176
+ }
246177
+ // Pass 3 -- look for unassigned nodes as middle of 3-face intersections
246178
+ for (let i = 0; i < breakEdges.length; i++) {
246179
+ const i0 = i;
246180
+ const i1 = (i0 + 1) % breakEdges.length;
246181
+ const i2 = (i1 + 1) % breakEdges.length;
246182
+ if (this.isInsideSling(breakEdges[i0], breakEdges[i1], breakEdges[i2]))
246183
+ continue;
246184
+ if (this.isOffsetAssigned(breakEdges[i1]))
246185
+ continue;
246186
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
246187
+ OffsetMeshContext.stringDebugFunction(` Intersection Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `);
246188
+ const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]);
246189
+ if (vectorFromOrigin !== undefined) {
246190
+ if (vertexXYZ.distance(vectorFromOrigin) < maxVertexMove) {
246191
+ this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[i1], (node, properties) => {
246192
+ properties.setXYAndZ(vectorFromOrigin);
246193
+ node.setMask(this._offsetCoordinatesReassigned);
246194
+ });
246195
+ }
246196
+ }
246197
+ }
246198
+ }
246199
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
246200
+ const n0 = vertexSeed.countMaskAroundVertex(this._offsetCoordinatesReassigned, false);
246201
+ const n1 = vertexSeed.countMaskAroundVertex(this._offsetCoordinatesReassigned, true);
246202
+ const message = ` **** Vertex offset mask counts(TRUE ${n1})(FALSE ${n0})`;
246203
+ OffsetMeshContext.stringDebugFunction(message);
246204
+ }
246205
+ return true;
246206
+ });
246207
+ }
246208
+ // return true if any of these nodes is "inside" the sling at the end of a chamfer.
246209
+ isInsideSling(node0, node1, node2) {
246210
+ return node0.isMaskSet(this._insideChamferSling)
246211
+ || (node1 !== undefined && node1.isMaskSet(this._insideChamferSling))
246212
+ || (node2 !== undefined && node2.isMaskSet(this._insideChamferSling));
246213
+ }
246214
+ // return true if any of these nodes is "inside" the sling at the end of a chamfer.
246215
+ isInsideChamferOrSling(node0) {
246216
+ return node0.isMaskSet(this._insideChamferSling)
246217
+ || node0.isMaskSet(this._insideOfChamferFace)
246218
+ || node0.isMaskSet(this._outsideEndOfChamferFace);
246219
+ }
246220
+ isOffsetAssigned(node0, node1, node2) {
246221
+ return node0.isMaskSet(this._offsetCoordinatesReassigned)
246222
+ || (node1 !== undefined && node1.isMaskSet(this._offsetCoordinatesReassigned))
246223
+ || (node2 !== undefined && node2.isMaskSet(this._offsetCoordinatesReassigned));
246224
+ }
246225
+ /**
246226
+ *
246227
+ * @param sourceNode node with good xyz
246228
+ * @param destinationStartNode first of a sequence of nodes to set (delimited by masks)
246229
+ * @param description string for debug
246230
+ * @param workPoint point to use for coordinate transfer.
246231
+ */
246232
+ transferXYZFromNodeToSmoothSector(sourceNode, destinationStartNode, description, workPoint) {
246233
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
246234
+ OffsetMeshContext.stringDebugFunction(` ${description} ${this.inspectMasks(sourceNode)} to ${this.inspectMasks(destinationStartNode)}} `);
246235
+ SectorOffsetProperties.getSectorPointAtHalfEdge(sourceNode, workPoint, undefined);
246236
+ this.announceNodeAndSectorPropertiesInSmoothSector(destinationStartNode, (node, properties) => {
246237
+ properties.setXYAndZ(workPoint);
246238
+ node.setMask(this._offsetCoordinatesReassigned);
246239
+ });
246240
+ }
246241
+ }
246242
+
246243
+
244991
246244
  /***/ }),
244992
246245
 
244993
246246
  /***/ "../../core/geometry/lib/esm/polyface/multiclip/RangeSearch.js":
@@ -254196,16 +255449,16 @@ class Sample {
254196
255449
  _curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(5, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 0)), _curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(15, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 360)), _curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(25, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 0)))));
254197
255450
  result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(// 2-pt Interpolation Curve
254198
255451
  _bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
254199
- fitPoints: [pointsA[0], pointsA[1]]
255452
+ fitPoints: [pointsA[0], pointsA[1]],
254200
255453
  })))));
254201
255454
  result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(// 3-pt Interpolation Curve
254202
255455
  _bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
254203
- fitPoints: [pointsA[0], pointsA[1], pointsA[2]]
255456
+ fitPoints: [pointsA[0], pointsA[1], pointsA[2]],
254204
255457
  })))));
254205
255458
  result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
254206
255459
  fitPoints: pointsA,
254207
255460
  startTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(1, -1),
254208
- endTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(-1, -1)
255461
+ endTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(-1, -1),
254209
255462
  })))));
254210
255463
  result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_curve_spiral_IntegratedSpiral3d__WEBPACK_IMPORTED_MODULE_39__.IntegratedSpiral3d.createRadiusRadiusBearingBearing(_geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 100), _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(10, 75), _geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 1), _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createOriginAndMatrix(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.createZero(), _geometry3d_Matrix3d__WEBPACK_IMPORTED_MODULE_12__.Matrix3d.createRotationAroundAxisIndex(2, _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(30))), "bloss"))));
254211
255464
  result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_curve_spiral_DirectSpiral3d__WEBPACK_IMPORTED_MODULE_41__.DirectSpiral3d.createDirectHalfCosine(_geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createOriginAndMatrix(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.createZero(), _geometry3d_Matrix3d__WEBPACK_IMPORTED_MODULE_12__.Matrix3d.createRotationAroundAxisIndex(2, _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(110))), 50, 350, _geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 1)))));
@@ -254319,8 +255572,11 @@ class Sample {
254319
255572
  /** Create swept "solids" that can be capped.
254320
255573
  * * At least one of each solid type.
254321
255574
  * * each is within 10 of the origin all directions.
255575
+ * @param capped true to include caps
255576
+ * @param rotationAngle angle of rotation for the angular sweep. The default is 90 degrees.
255577
+ * Beware that the rotation sweep created with the default or any positive angle produces a mesh with inward normals.
254322
255578
  */
254323
- static createClosedSolidSampler(capped) {
255579
+ static createClosedSolidSampler(capped, rotationAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(90)) {
254324
255580
  const result = [];
254325
255581
  result.push(_solid_Box__WEBPACK_IMPORTED_MODULE_35__.Box.createRange(_geometry3d_Range__WEBPACK_IMPORTED_MODULE_4__.Range3d.createXYZXYZ(0, 0, 0, 3, 2, 5), capped));
254326
255582
  result.push(_solid_Cone__WEBPACK_IMPORTED_MODULE_33__.Cone.createAxisPoints(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 0), _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 5), 1.0, 1.0, capped));
@@ -254332,18 +255588,23 @@ class Sample {
254332
255588
  const pointQ2 = arcA.fractionAndDistanceToPointOnTangent(1.0, 0.5);
254333
255589
  const pointR1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(point0.x, pointQ1.y);
254334
255590
  const pointR2 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(point0.x, pointQ1.y);
255591
+ const pointR3 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(pointQ1.x - 1, pointQ1.y);
255592
+ const pointR4 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(pointQ1.x - 3, pointQ1.y);
254335
255593
  const linestringQ1 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ1, pointR1, point0);
254336
255594
  const linestringQ2 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ2, pointR2, point0);
255595
+ const linestringQ3 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ2, pointR3, pointR4, point0);
254337
255596
  const contourZ = _curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(linestringQ1.clone());
254338
255597
  const contourA = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ1.clone());
254339
255598
  const contourB = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ2.clone());
255599
+ const contourC1 = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ3.clone());
254340
255600
  contourB.tryTransformInPlace(_geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createTranslationXYZ(1, 1, 3));
254341
255601
  // const contourC = contourB.cloneTransformed(Transform.createTranslationXYZ(2, 1, 4))!;
254342
255602
  result.push(_solid_LinearSweep__WEBPACK_IMPORTED_MODULE_30__.LinearSweep.create(contourA, _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(0, 0, 5), capped));
255603
+ result.push(_solid_LinearSweep__WEBPACK_IMPORTED_MODULE_30__.LinearSweep.create(contourC1, _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(0, 0, 5), capped));
254343
255604
  const axis = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_14__.Ray3d.createXYZUVW(0, 8, 0, 1, 0, 0);
254344
- result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourA.clone(), axis.clone(), _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(90), capped));
255605
+ result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourA.clone(), axis.clone(), rotationAngle, capped));
254345
255606
  if (!capped)
254346
- result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourZ.clone(), axis.clone(), _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(90), false));
255607
+ result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourZ.clone(), axis.clone(), rotationAngle, false));
254347
255608
  result.push(_solid_RuledSweep__WEBPACK_IMPORTED_MODULE_36__.RuledSweep.create([contourA.clone(), contourB.clone()], capped));
254348
255609
  const transformC = _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createScaleAboutPoint(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 8), 0.5);
254349
255610
  const contourC = contourB.cloneTransformed(transformC);
@@ -258768,12 +260029,13 @@ __webpack_require__.r(__webpack_exports__);
258768
260029
  /* harmony export */ "HalfEdgeGraph": () => (/* binding */ HalfEdgeGraph),
258769
260030
  /* harmony export */ "HalfEdgeMask": () => (/* binding */ HalfEdgeMask)
258770
260031
  /* harmony export */ });
258771
- /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
260032
+ /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
258772
260033
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
260034
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
258773
260035
  /* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
258774
260036
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
258775
- /* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
258776
- /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
260037
+ /* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
260038
+ /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
258777
260039
  /*---------------------------------------------------------------------------------------------
258778
260040
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
258779
260041
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -258787,6 +260049,7 @@ __webpack_require__.r(__webpack_exports__);
258787
260049
 
258788
260050
 
258789
260051
 
260052
+
258790
260053
  // import { GraphChecker } from "../test/topology/Graph.test";
258791
260054
  /* eslint-disable @typescript-eslint/no-this-alias */
258792
260055
  // cspell:word CONSTU
@@ -258874,6 +260137,7 @@ class HalfEdge {
258874
260137
  this.sortAngle = undefined;
258875
260138
  this.sortData = undefined;
258876
260139
  this.edgeTag = undefined;
260140
+ this.faceTag = undefined;
258877
260141
  // Always created in pairs, init here to make TS compiler and JS runtime happy
258878
260142
  this._facePredecessor = this;
258879
260143
  this._faceSuccessor = this;
@@ -258994,6 +260258,36 @@ class HalfEdge {
258994
260258
  }
258995
260259
  return newA;
258996
260260
  }
260261
+ /**
260262
+ * * Create a new sliver face "inside" an existing edge.
260263
+ * * Insert it "within" the base edge.
260264
+ * * This requires two new half edges.
260265
+ * * if the base is undefined, create a single-edge loop.
260266
+ * * This (unlike pinch) breaks the edgeMate pairing of the base edge.
260267
+ * * This preserves xyz and i properties at all existing vertices.
260268
+ * * The two new half edges are a sliver face (via their predecessor and successor)
260269
+ * * Each new edge mates to one existing edge.
260270
+ * @returns Returns the reference to the half edge created.
260271
+ */
260272
+ static splitEdgeCreateSliverFace(baseA, heArray) {
260273
+ // raw edges ...
260274
+ const newA = new HalfEdge();
260275
+ const newB = new HalfEdge();
260276
+ const baseB = baseA.edgeMate;
260277
+ if (heArray) {
260278
+ heArray.push(newA);
260279
+ heArray.push(newB);
260280
+ }
260281
+ newA._faceSuccessor = newA._facePredecessor = newB;
260282
+ newB._faceSuccessor = newB._facePredecessor = newA;
260283
+ // newA is in vertex loop with baseA etc.
260284
+ // newA mates to baseB
260285
+ HalfEdge.setEdgeMates(newA, baseB);
260286
+ HalfEdge.setEdgeMates(newB, baseA);
260287
+ newA.copyDataFrom(baseA, true, true, false, false);
260288
+ newB.copyDataFrom(baseB, true, true, false, false);
260289
+ return newA;
260290
+ }
258997
260291
  /**
258998
260292
  * Copy "edge based" content of fromNode to toNode
258999
260293
  * * edgeTag
@@ -259204,6 +260498,35 @@ class HalfEdge {
259204
260498
  }
259205
260499
  return count;
259206
260500
  }
260501
+ /** Returns the first node with given mask value around this vertex loop. */
260502
+ findMaskAroundVertex(mask, value = true) {
260503
+ let node = this;
260504
+ do {
260505
+ if (node.isMaskSet(mask) === value)
260506
+ return node;
260507
+ node = node.vertexSuccessor;
260508
+ } while (node !== this);
260509
+ return undefined;
260510
+ }
260511
+ /** Returns the first node with given mask value around this face loop. */
260512
+ findMaskAroundFace(mask, value = true) {
260513
+ let node = this;
260514
+ do {
260515
+ if (node.isMaskSet(mask) === value)
260516
+ return node;
260517
+ node = node.faceSuccessor;
260518
+ } while (node !== this);
260519
+ return undefined;
260520
+ }
260521
+ /** Returns the first node with given mask value on this edge (i.e. examining this and this.mate) */
260522
+ findMaskAroundEdge(mask, value = true) {
260523
+ if (this.isMaskSet(mask) === value)
260524
+ return this;
260525
+ const mate = this.edgeMate;
260526
+ if (mate.isMaskSet(mask) === value)
260527
+ return mate;
260528
+ return undefined;
260529
+ }
259207
260530
  /** Set a mask, and return prior value.
259208
260531
  * @param mask mask to apply
259209
260532
  */
@@ -259221,6 +260544,15 @@ class HalfEdge {
259221
260544
  this.y = node.y;
259222
260545
  this.z = node.z;
259223
260546
  }
260547
+ /**
260548
+ * Set (copy) the this.x, this.y, this.z from xyz.x, xyz.y, xyz.z
260549
+ * @param node source with x,y,z properties
260550
+ */
260551
+ setXYZ(xyz) {
260552
+ this.x = xyz.x;
260553
+ this.y = xyz.y;
260554
+ this.z = xyz.z;
260555
+ }
259224
260556
  /**
259225
260557
  * Test if mask bits are set in the node's bitMask.
259226
260558
  * @return Return true (as a simple boolean, not a mask) if any bits of the mask parameter match bits of the node's bitMask
@@ -259310,6 +260642,10 @@ class HalfEdge {
259310
260642
  const s = `${node.id.toString()}+${HalfEdge.nodeToMaskString(node)}[${node.x},${node.y}]`;
259311
260643
  return s;
259312
260644
  }
260645
+ /** Return the [id, [x,y],z] of a node. Useful for collector methods. */
260646
+ static nodeToIdXYZString(node) {
260647
+ return `[${node.id.toString()}: ${node.x},${node.y},${node.z}]`;
260648
+ }
259313
260649
  /** Create a string representation of the mask
259314
260650
  * * Null mask is empty string.
259315
260651
  * * Appended characters B,P,X for Boundary, Primary, Exterior mask bits.
@@ -259334,7 +260670,13 @@ class HalfEdge {
259334
260670
  }
259335
260671
  /** Return Vector3d to face successor */
259336
260672
  vectorToFaceSuccessor(result) {
259337
- return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(this.faceSuccessor.x - this.x, this.faceSuccessor.y - this.y, this.faceSuccessor.z - this.z, result);
260673
+ const other = this.faceSuccessor;
260674
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
260675
+ }
260676
+ /** Return Vector3d to face successor */
260677
+ vectorToFacePredecessor(result) {
260678
+ const other = this.facePredecessor;
260679
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
259338
260680
  }
259339
260681
  /** test if spaceNode is in the sector at sectorNode */
259340
260682
  static isNodeVisibleInSector(spaceNode, sectorNode) {
@@ -259458,6 +260800,14 @@ class HalfEdge {
259458
260800
  static testNodeMaskNotExterior(node) { return !node.isMaskSet(HalfEdgeMask.EXTERIOR); }
259459
260801
  /** Returns Returns true if the node does NOT have Mask.EXTERIOR_MASK set. */
259460
260802
  static testMateMaskExterior(node) { return node.edgeMate.isMaskSet(HalfEdgeMask.EXTERIOR); }
260803
+ /** Returns radians between this edge and its face predecessor edge, using all three coordinates x,y,z and given normal to resolve sweep direction.
260804
+ * * The returned angle is positive, i.e. may be larger than PI radians.
260805
+ */
260806
+ static sectorSweepRadiansXYZ(node, normal) {
260807
+ const nodeB = node.faceSuccessor;
260808
+ const nodeC = node.facePredecessor;
260809
+ return _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.orientedRadiansBetweenVectorsXYZ(nodeB.x - node.x, nodeB.y - node.y, nodeB.z - node.z, nodeC.x - node.x, nodeC.y - node.y, nodeC.z - node.z, normal.x, normal.y, normal.z, true);
260810
+ }
259461
260811
  /** Returns Returns true if the face has positive area in xy parts. */
259462
260812
  static testFacePositiveAreaXY(node) {
259463
260813
  return node.countEdgesAroundFace() > 2 && node.signedFaceArea() > 0.0;
@@ -259489,6 +260839,26 @@ class HalfEdge {
259489
260839
  } while (node !== this);
259490
260840
  return nodes;
259491
260841
  }
260842
+ /**
260843
+ * search around a vertex for nodes that have a specified mask setting.
260844
+ * @param vertexSeed first node to search
260845
+ * @param mask target mask
260846
+ * @param value target value for mask on half edges.
260847
+ * @param collectedNodes optional array to be cleared and receive masked nodes
260848
+ */
260849
+ collectMaskedEdgesAroundVertex(mask, value = true, result) {
260850
+ if (result === undefined)
260851
+ result = [];
260852
+ else
260853
+ result.length = 0;
260854
+ let node = this;
260855
+ do {
260856
+ if (node.isMaskSet(mask) === value)
260857
+ result.push(node);
260858
+ node = node.vertexSuccessor;
260859
+ } while (node !== this);
260860
+ return result;
260861
+ }
259492
260862
  /**
259493
260863
  *
259494
260864
  * * Evaluate f(node) at each outbound node around this node's vertex loop.
@@ -259672,7 +261042,7 @@ class HalfEdge {
259672
261042
  const nodeB1 = nodeB0.faceSuccessor;
259673
261043
  if (!result)
259674
261044
  result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create();
259675
- if (_numerics_Polynomials__WEBPACK_IMPORTED_MODULE_3__.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))
261045
+ if (_numerics_Polynomials__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))
259676
261046
  return result;
259677
261047
  return undefined;
259678
261048
  }
@@ -259681,8 +261051,7 @@ class HalfEdge {
259681
261051
  * * If the edge is horizontal with (approximate) identical y, return the node.
259682
261052
  * * If the edge is horizontal with different y, return undefined.
259683
261053
  * * If the edge is not horizontal, return the fractional position (possibly outside 0..1) of the intersection.
259684
- * @param nodeA Base node of edge
259685
- * @param result optional preallocated result
261054
+ * @param node0 Base node of edge
259686
261055
  */
259687
261056
  static horizontalScanFraction(node0, y) {
259688
261057
  const node1 = node0.faceSuccessor;
@@ -259697,8 +261066,7 @@ class HalfEdge {
259697
261066
  * * Compute fractional coordinates of the intersection of a horizontal line with an edge.
259698
261067
  * * If the edge is horizontal return undefined (no test for horizontal at y!!!)
259699
261068
  * * If the edge is not horizontal and y is between its end y's, return the fraction
259700
- * @param nodeA Base node of edge
259701
- * @param result optional preallocated result
261069
+ * @param node0 Base node of edge
259702
261070
  */
259703
261071
  static horizontalScanFraction01(node0, y) {
259704
261072
  const node1 = node0.faceSuccessor;
@@ -259712,6 +261080,31 @@ class HalfEdge {
259712
261080
  return fraction;
259713
261081
  return undefined;
259714
261082
  }
261083
+ /**
261084
+ * Copy various data from source to this.
261085
+ * @param source other half edge.
261086
+ * @param XYZ copy simple coordinates
261087
+ * @param copyVertexData true to copy data belonging to the vertex. (i.e. the "i" member)
261088
+ * @param copyVertexData true to copy data belonging to the edge. (i.e. call transferEdgeData)
261089
+ * @param copyFaceData true to copy faceTag
261090
+ */
261091
+ copyDataFrom(source, copyXYZ, copyVertexData, copyEdgeData, copyFaceData) {
261092
+ if (copyXYZ) {
261093
+ this.x = source.x;
261094
+ this.y = source.y;
261095
+ this.z = source.z;
261096
+ }
261097
+ if (copyVertexData) {
261098
+ this.i = source.i;
261099
+ }
261100
+ if (copyEdgeData) {
261101
+ HalfEdge.transferEdgeProperties(source, this);
261102
+ this.edgeTag = source.edgeTag;
261103
+ }
261104
+ if (copyFaceData) {
261105
+ this.faceTag = source.faceTag;
261106
+ }
261107
+ }
259715
261108
  }
259716
261109
  HalfEdge._edgePropertyMasks = [HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.NULL_FACE];
259717
261110
  HalfEdge._totalNodesCreated = 0;
@@ -259725,7 +261118,7 @@ class HalfEdgeGraph {
259725
261118
  constructor() {
259726
261119
  this._numNodesCreated = 0;
259727
261120
  this.allHalfEdges = [];
259728
- this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_4__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
261121
+ this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_5__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
259729
261122
  }
259730
261123
  /** Ask for a mask (from the graph's free pool.) for caller's use.
259731
261124
  * * Optionally clear the mask throughout the graph.
@@ -259752,6 +261145,19 @@ class HalfEdgeGraph {
259752
261145
  const a = HalfEdge.createHalfEdgePairWithCoordinates(xA, yA, zA, iA, xB, yB, zB, iB, this.allHalfEdges);
259753
261146
  return a;
259754
261147
  }
261148
+ /**
261149
+ * * Create 2 half edges forming 2 vertices, 1 edge, and 1 face
261150
+ * * The two edges are joined as edgeMate pair.
261151
+ * * The two edges are a 2-half-edge face loop in both the faceSuccessor and facePredecessor directions.
261152
+ * * The two edges are added to the graph's HalfEdge set
261153
+ * * Coordinates are set to zero.
261154
+ * * ids are installed in the two half edges.
261155
+ * @returns Return pointer to the first half edge created. (This has idA as its id.)
261156
+ */
261157
+ createEdgeIdId(iA = 0, iB = 0) {
261158
+ const a = HalfEdge.createHalfEdgePairWithCoordinates(0.0, 0.0, 0.0, iA, 0.0, 0.0, 0.0, iB, this.allHalfEdges);
261159
+ return a;
261160
+ }
259755
261161
  /**
259756
261162
  * * create an edge from coordinates x,y,z to (the tail of) an existing half edge.
259757
261163
  * @returns Return pointer to the half edge with tail at x,y,z
@@ -259796,6 +261202,20 @@ class HalfEdgeGraph {
259796
261202
  const he = HalfEdge.splitEdge(base, xA, yA, zA, iA, this.allHalfEdges);
259797
261203
  return he;
259798
261204
  }
261205
+ /**
261206
+ * * Create a sliver face "within" an edge.
261207
+ * * this creates two half edges.
261208
+ * * The existing edges both stay in their same face loops and retain coordinates and i value.
261209
+ * * Each existing edge's mate is a new edge (rather than original mate)
261210
+ * * Coordinates are copied to the new edges at respective vertices.
261211
+ * * New faceTag and edgeTag undefined.
261212
+ * * i members are copied around their respective vertices.
261213
+ * @returns Returns the reference to the half edge created.
261214
+ */
261215
+ splitEdgeCreateSliverFace(base) {
261216
+ const he = HalfEdge.splitEdgeCreateSliverFace(base, this.allHalfEdges);
261217
+ return he;
261218
+ }
259799
261219
  /**
259800
261220
  * * Insert a vertex in the edge beginning at base, with coordinates specified as a fraction along the existing edge.
259801
261221
  * * this creates two half edges.
@@ -259864,7 +261284,7 @@ class HalfEdgeGraph {
259864
261284
  const segments = [];
259865
261285
  for (const node of this.allHalfEdges) {
259866
261286
  if (node.id < node.edgeMate.id)
259867
- segments.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_5__.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)));
261287
+ 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)));
259868
261288
  }
259869
261289
  return segments;
259870
261290
  }
@@ -259933,6 +261353,26 @@ class HalfEdgeGraph {
259933
261353
  break;
259934
261354
  }
259935
261355
  }
261356
+ /**
261357
+ * * Visit each edge of the graph once.
261358
+ * * Call the announceEdge function.
261359
+ * * the edge mate will NOT appear in an announceEdge call.
261360
+ * * continue search if announceEdge(graph, node) returns true
261361
+ * * terminate search if announceEdge (graph, node) returns false
261362
+ * @param announceEdge function to apply at one node of each edge.
261363
+ */
261364
+ announceEdges(announceEdge) {
261365
+ this.clearMask(HalfEdgeMask.VISITED);
261366
+ for (const node of this.allHalfEdges) {
261367
+ if (node.getMask(HalfEdgeMask.VISITED))
261368
+ continue;
261369
+ const mate = node.edgeMate;
261370
+ node.setMask(HalfEdgeMask.VISITED);
261371
+ mate.setMask(HalfEdgeMask.VISITED);
261372
+ if (!announceEdge(this, node))
261373
+ break;
261374
+ }
261375
+ }
259936
261376
  /**
259937
261377
  * * Visit each vertex loop of the graph once.
259938
261378
  * * Call the announceVertex function
@@ -259951,8 +261391,8 @@ class HalfEdgeGraph {
259951
261391
  }
259952
261392
  }
259953
261393
  /**
259954
- * * Visit each vertex loop of the graph once.
259955
- * * Call the announceVertex function
261394
+ * * Visit each half edge (node) of the graph once.
261395
+ * * Call the announceNode function
259956
261396
  * * continue search if announceNode(graph, node) returns true
259957
261397
  * * terminate search if announce face (graph, node) returns false
259958
261398
  * @param announceNode function to apply at one node of each face.
@@ -260011,6 +261451,99 @@ class HalfEdgeGraph {
260011
261451
  }
260012
261452
 
260013
261453
 
261454
+ /***/ }),
261455
+
261456
+ /***/ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js":
261457
+ /*!************************************************************************************!*\
261458
+ !*** ../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js ***!
261459
+ \************************************************************************************/
261460
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
261461
+
261462
+ "use strict";
261463
+ __webpack_require__.r(__webpack_exports__);
261464
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
261465
+ /* harmony export */ "HalfEdgeGraphFromIndexedLoopsContext": () => (/* binding */ HalfEdgeGraphFromIndexedLoopsContext)
261466
+ /* harmony export */ });
261467
+ /* harmony import */ var _Graph__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
261468
+ /*---------------------------------------------------------------------------------------------
261469
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
261470
+ * See LICENSE.md in the project root for license terms and full copyright notice.
261471
+ *--------------------------------------------------------------------------------------------*/
261472
+
261473
+ /** @packageDocumentation
261474
+ * @module Topology
261475
+ */
261476
+ /**
261477
+ * Context for building a half edge graph from loops defined only by indices.
261478
+ * * Direct use case:
261479
+ * * Create the context.
261480
+ * * Repeatedly call insertLoop(indicesAroundLoop) to announce various loops.
261481
+ * * Finish by accessing the graph property.
261482
+ * @internal
261483
+ */
261484
+ class HalfEdgeGraphFromIndexedLoopsContext {
261485
+ constructor() {
261486
+ this._unmatchedEdges = new Map();
261487
+ this._graph = new _Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeGraph();
261488
+ this._halfEdgesAroundCurrentLoop = [];
261489
+ }
261490
+ get graph() { return this._graph; }
261491
+ indexPairToString(index0, index1) {
261492
+ return `${index0.toString()},${index1.toString()}`;
261493
+ }
261494
+ /** Create a loop with specified indices at its vertices.
261495
+ * * For an edge with index pair [indexA, indexB]:
261496
+ * * if [indexB, indexA] has never appeared, a HalfEdge mated pair is created.
261497
+ * * One of that mated pair becomes a HalfEdge in this loop.
261498
+ * * The other is "unmatched"
261499
+ * * When announceMatedHalfEdges(halfEdge) is called:
261500
+ * * halfEdge and its mate are "new"
261501
+ * * all coordinates are zeros.
261502
+ * * each contains (as its halfEdge.id property) one index of the [indexA,indexB] pair.
261503
+ * * those coordinates and indices will never be referenced again by this construction sequence -- the caller is free to mutate them as needed.
261504
+ * * if [indexB, indexA] appeared previously (and its outer HalfEdge was left "unmatched"),
261505
+ * the "unmatched" HalfEdge is used in the loop being constructed.
261506
+ * @param indices Array of indices around the edge. This is accessed cyclically.
261507
+ * @param announceMatedHalfEdges optional function to be called as mated pairs are created. At the call,
261508
+ * the given HalfEdge and its mate will have a pair of successive indices from the array.
261509
+ */
261510
+ insertLoop(indices, announceMatedHalfEdges) {
261511
+ const n = indices.length;
261512
+ if (n > 1) {
261513
+ let index0 = indices[indices.length - 1];
261514
+ this._halfEdgesAroundCurrentLoop.length = 0;
261515
+ for (const index1 of indices) {
261516
+ const insideString = this.indexPairToString(index0, index1);
261517
+ const halfEdgePreviouslyConstructedFromOppositeSide = this._unmatchedEdges.get(insideString);
261518
+ if (halfEdgePreviouslyConstructedFromOppositeSide === undefined) {
261519
+ // This is the first appearance of this edge in either direction.
261520
+ const outsideString = this.indexPairToString(index1, index0); // string referencing the "other" side of the new edge.
261521
+ const newHalfEdgeAroundLoop = this._graph.createEdgeIdId(index0, index1);
261522
+ if (announceMatedHalfEdges !== undefined)
261523
+ announceMatedHalfEdges(newHalfEdgeAroundLoop);
261524
+ this._unmatchedEdges.set(outsideString, newHalfEdgeAroundLoop.edgeMate);
261525
+ this._halfEdgesAroundCurrentLoop.push(newHalfEdgeAroundLoop);
261526
+ newHalfEdgeAroundLoop.edgeMate.setMask(_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeMask.EXTERIOR);
261527
+ }
261528
+ else {
261529
+ this._halfEdgesAroundCurrentLoop.push(halfEdgePreviouslyConstructedFromOppositeSide);
261530
+ halfEdgePreviouslyConstructedFromOppositeSide.clearMask(_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeMask.EXTERIOR);
261531
+ }
261532
+ index0 = index1;
261533
+ }
261534
+ let halfEdgeA = this._halfEdgesAroundCurrentLoop[this._halfEdgesAroundCurrentLoop.length - 1];
261535
+ for (const halfEdgeB of this._halfEdgesAroundCurrentLoop) {
261536
+ const halfEdgeC = halfEdgeA.faceSuccessor;
261537
+ _Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdge.pinch(halfEdgeB, halfEdgeC);
261538
+ halfEdgeA = halfEdgeB;
261539
+ }
261540
+ return this._halfEdgesAroundCurrentLoop[0];
261541
+ }
261542
+ return undefined;
261543
+ }
261544
+ }
261545
+
261546
+
260014
261547
  /***/ }),
260015
261548
 
260016
261549
  /***/ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js":
@@ -283839,7 +285372,6 @@ class Capabilities {
283839
285372
  this._maxVertUniformVectors = 0;
283840
285373
  this._maxVaryingVectors = 0;
283841
285374
  this._maxFragUniformVectors = 0;
283842
- this._canRenderDepthWithoutColor = false;
283843
285375
  this._maxAntialiasSamples = 1;
283844
285376
  this._supportsCreateImageBitmap = false;
283845
285377
  this._maxTexSizeAllow = maxTexSizeAllowed;
@@ -283882,7 +285414,6 @@ class Capabilities {
283882
285414
  get supportsStandardDerivatives() { return this._isWebGL2 || this.queryExtensionObject("OES_standard_derivatives") !== undefined; }
283883
285415
  get supportsMRTTransparency() { return this.maxColorAttachments >= 2; }
283884
285416
  get supportsMRTPickShaders() { return this.maxColorAttachments >= 3; }
283885
- get canRenderDepthWithoutColor() { return this._canRenderDepthWithoutColor; }
283886
285417
  get supportsShadowMaps() {
283887
285418
  return this.supportsTextureFloat || this.supportsTextureHalfFloat;
283888
285419
  }
@@ -284013,7 +285544,6 @@ class Capabilities {
284013
285544
  // Determine the maximum depth attachment type.
284014
285545
  // this._maxDepthType = this.queryExtensionObject("WEBGL_depth_texture") !== undefined ? DepthType.TextureUnsignedInt32 : DepthType.RenderBufferUnsignedShort16;
284015
285546
  this._maxDepthType = this._isWebGL2 || this.queryExtensionObject("WEBGL_depth_texture") !== undefined ? DepthType.TextureUnsignedInt24Stencil8 : DepthType.RenderBufferUnsignedShort16;
284016
- this._canRenderDepthWithoutColor = this._maxDepthType === DepthType.TextureUnsignedInt24Stencil8 ? this.isDepthRenderableWithoutColor(gl) : false;
284017
285547
  this._presentFeatures = this._gatherFeatures();
284018
285548
  const missingRequiredFeatures = this._findMissingFeatures(Capabilities.requiredFeatures);
284019
285549
  const missingOptionalFeatures = this._findMissingFeatures(Capabilities.optionalFeatures);
@@ -284058,24 +285588,6 @@ class Capabilities {
284058
285588
  gl.getError(); // clear any errors
284059
285589
  return fbStatus === gl.FRAMEBUFFER_COMPLETE;
284060
285590
  }
284061
- /** Determines if depth textures can be rendered without also having a color attachment bound on the host system. */
284062
- isDepthRenderableWithoutColor(gl) {
284063
- const dtExt = this.queryExtensionObject("WEBGL_depth_texture");
284064
- if (dtExt === undefined)
284065
- return false;
284066
- const tex = gl.createTexture();
284067
- gl.bindTexture(gl.TEXTURE_2D, tex);
284068
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_STENCIL, 1, 1, 0, gl.DEPTH_STENCIL, dtExt.UNSIGNED_INT_24_8_WEBGL, null);
284069
- const fb = gl.createFramebuffer();
284070
- gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
284071
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, tex, 0);
284072
- const fbStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
284073
- gl.bindFramebuffer(gl.FRAMEBUFFER, null);
284074
- gl.deleteFramebuffer(fb);
284075
- gl.deleteTexture(tex);
284076
- gl.getError(); // clear any errors
284077
- return fbStatus === gl.FRAMEBUFFER_COMPLETE;
284078
- }
284079
285591
  setMaxAnisotropy(desiredMax, gl) {
284080
285592
  const ext = this.queryExtensionObject("EXT_texture_filter_anisotropic");
284081
285593
  if (undefined === ext)
@@ -285516,7 +287028,7 @@ class TestContext {
285516
287028
  this.initializeRpcInterfaces({ title: this.settings.Backend.name, version: this.settings.Backend.version });
285517
287029
  const iModelClient = new imodels_client_management_1.IModelsClient({ api: { baseUrl: `https://${(_a = process.env.IMJS_URL_PREFIX) !== null && _a !== void 0 ? _a : ""}api.bentley.com/imodels` } });
285518
287030
  await core_frontend_1.NoRenderApp.startup({
285519
- applicationVersion: "4.0.0-dev.4",
287031
+ applicationVersion: "4.0.0-dev.7",
285520
287032
  applicationId: this.settings.gprid,
285521
287033
  authorizationClient: new frontend_1.TestFrontendAuthorizationClient(this.adminUserAccessToken),
285522
287034
  hubAccess: new imodels_access_frontend_1.FrontendIModelsAccess(iModelClient),
@@ -304945,7 +306457,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
304945
306457
  /***/ ((module) => {
304946
306458
 
304947
306459
  "use strict";
304948
- module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.0.0-dev.4","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","build:ci":"npm run -s build && npm run -s build:esm","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 ES2020 --outDir lib/esm","clean":"rimraf 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","docs":"betools docs --includes=../../generated-docs/extract --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/primitives,**/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-eslintrc -c \\"../../tools/eslint-plugin/dist/configs/extension-exports-config.js\\" \\"./src/**/*.ts\\" 1>&2","lint":"eslint -f visualstudio \\"./src/**/*.ts\\" 1>&2","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run -s webpackTests && certa -r chrome","cover":"npm -s test","test:debug":"certa -r chrome --debug","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core/tree/master/core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:^4.0.0-dev.4","@itwin/core-bentley":"workspace:^4.0.0-dev.4","@itwin/core-common":"workspace:^4.0.0-dev.4","@itwin/core-geometry":"workspace:^4.0.0-dev.4","@itwin/core-orbitgt":"workspace:^4.0.0-dev.4","@itwin/core-quantity":"workspace:^4.0.0-dev.4"},"//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/certa":"workspace:*","@itwin/eslint-plugin":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@types/chai":"4.3.1","@types/chai-as-promised":"^7","@types/deep-assign":"^0.1.0","@types/lodash":"^4.14.0","@types/mocha":"^8.2.2","@types/node":"18.11.5","@types/qs":"^6.5.0","@types/semver":"7.3.10","@types/superagent":"^4.1.14","@types/sinon":"^9.0.0","babel-loader":"~8.2.5","babel-plugin-istanbul":"~6.1.1","chai":"^4.1.2","chai-as-promised":"^7","cpx2":"^3.0.0","eslint":"^7.11.0","glob":"^7.1.2","mocha":"^10.0.0","nyc":"^15.1.0","rimraf":"^3.0.2","sinon":"^9.0.2","source-map-loader":"^4.0.0","typescript":"~4.4.0","webpack":"^5.64.4"},"//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/object-storage-azure":"~1.4.0","@itwin/cloud-agnostic-core":"~1.4.0","@itwin/object-storage-core":"~1.4.0","@itwin/core-i18n":"workspace:*","@itwin/core-telemetry":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","deep-assign":"^2.0.0","fuse.js":"^3.3.0","lodash":"^4.17.10","qs":"^6.5.3","semver":"^7.3.5","superagent":"^7.1.5","wms-capabilities":"0.4.0","reflect-metadata":"0.1.13"},"nyc":{"extends":"./node_modules/@itwin/build-tools/.nycrc"},"eslintConfig":{"plugins":["@itwin"],"extends":"plugin:@itwin/itwinjs-recommended","rules":{"@itwin/no-internal-barrel-imports":["error",{"required-barrel-modules":["./src/tile/internal.ts"]}],"@itwin/public-extension-exports":["error",{"releaseTags":["public","preview"],"outputApiFile":false}]},"overrides":[{"files":["*.test.ts","*.test.tsx","**/test/**/*.ts"],"rules":{"@itwin/no-internal-barrel-imports":"off"}}]}}');
306460
+ module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.0.0-dev.7","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs","build:ci":"npm run -s build && npm run -s build:esm","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 ES2020 --outDir lib/esm","clean":"rimraf 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","docs":"betools docs --includes=../../generated-docs/extract --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/primitives,**/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-eslintrc -c \\"../../tools/eslint-plugin/dist/configs/extension-exports-config.js\\" \\"./src/**/*.ts\\" 1>&2","lint":"eslint -f visualstudio \\"./src/**/*.ts\\" 1>&2","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run -s webpackTests && certa -r chrome","cover":"npm -s test","test:debug":"certa -r chrome --debug","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core/tree/master/core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:^4.0.0-dev.7","@itwin/core-bentley":"workspace:^4.0.0-dev.7","@itwin/core-common":"workspace:^4.0.0-dev.7","@itwin/core-geometry":"workspace:^4.0.0-dev.7","@itwin/core-orbitgt":"workspace:^4.0.0-dev.7","@itwin/core-quantity":"workspace:^4.0.0-dev.7"},"//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/certa":"workspace:*","@itwin/eslint-plugin":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@types/chai":"4.3.1","@types/chai-as-promised":"^7","@types/deep-assign":"^0.1.0","@types/lodash":"^4.14.0","@types/mocha":"^8.2.2","@types/node":"18.11.5","@types/qs":"^6.5.0","@types/semver":"7.3.10","@types/superagent":"^4.1.14","@types/sinon":"^9.0.0","babel-loader":"~8.2.5","babel-plugin-istanbul":"~6.1.1","chai":"^4.1.2","chai-as-promised":"^7","cpx2":"^3.0.0","eslint":"^7.11.0","glob":"^7.1.2","mocha":"^10.0.0","nyc":"^15.1.0","rimraf":"^3.0.2","sinon":"^9.0.2","source-map-loader":"^4.0.0","typescript":"~4.4.0","webpack":"^5.64.4"},"//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/object-storage-azure":"~1.4.0","@itwin/cloud-agnostic-core":"~1.4.0","@itwin/object-storage-core":"~1.4.0","@itwin/core-i18n":"workspace:*","@itwin/core-telemetry":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","deep-assign":"^2.0.0","fuse.js":"^3.3.0","lodash":"^4.17.10","qs":"^6.5.3","semver":"^7.3.5","superagent":"^7.1.5","wms-capabilities":"0.4.0","reflect-metadata":"0.1.13"},"nyc":{"extends":"./node_modules/@itwin/build-tools/.nycrc"},"eslintConfig":{"plugins":["@itwin"],"extends":"plugin:@itwin/itwinjs-recommended","rules":{"@itwin/no-internal-barrel-imports":["error",{"required-barrel-modules":["./src/tile/internal.ts"]}],"@itwin/public-extension-exports":["error",{"releaseTags":["public","preview"],"outputApiFile":false}]},"overrides":[{"files":["*.test.ts","*.test.tsx","**/test/**/*.ts"],"rules":{"@itwin/no-internal-barrel-imports":"off"}}]}}');
304949
306461
 
304950
306462
  /***/ }),
304951
306463