@itwin/ecschema-rpcinterface-tests 4.0.0-dev.6 → 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.
@@ -201233,6 +201233,7 @@ __webpack_require__.r(__webpack_exports__);
201233
201233
  /* harmony export */ "NewtonEvaluatorRtoRD": () => (/* reexport safe */ _numerics_Newton__WEBPACK_IMPORTED_MODULE_51__.NewtonEvaluatorRtoRD),
201234
201234
  /* harmony export */ "NullGeometryHandler": () => (/* reexport safe */ _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_8__.NullGeometryHandler),
201235
201235
  /* harmony export */ "NumberArray": () => (/* reexport safe */ _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_23__.NumberArray),
201236
+ /* harmony export */ "OffsetMeshOptions": () => (/* reexport safe */ _polyface_PolyfaceQuery__WEBPACK_IMPORTED_MODULE_116__.OffsetMeshOptions),
201236
201237
  /* harmony export */ "OffsetOptions": () => (/* reexport safe */ _curve_internalContexts_PolygonOffsetContext__WEBPACK_IMPORTED_MODULE_79__.OffsetOptions),
201237
201238
  /* harmony export */ "Order2Bezier": () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_49__.Order2Bezier),
201238
201239
  /* harmony export */ "Order3Bezier": () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_49__.Order3Bezier),
@@ -219628,6 +219629,44 @@ class Angle {
219628
219629
  const uDotV = ux * vx + uy * vy + uz * vz;
219629
219630
  return Math.atan2(_Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.crossProductMagnitude(ux, uy, uz, vx, vy, vz), uDotV);
219630
219631
  }
219632
+ /**
219633
+ * * 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.
219634
+ * * The returned angle is (-PI < radians <= PI) or (0 <= radians < 2 * PI)
219635
+ * * The angle is in the plane of the U and V vectors.
219636
+ * * The upVector determines a positive side of the plane but need not be strictly perpendicular to the plane.
219637
+ *
219638
+ * @param ux x component of vector u
219639
+ * @param uy y component of vector u
219640
+ * @param uz z component of vector u
219641
+ * @param vx x component of vector v
219642
+ * @param vy y component of vector v
219643
+ * @param vz z component of vector v
219644
+ * @param upVectorX x component of vector to positive side of plane.
219645
+ * @param upVectorY y component of vector to positive side of plane.
219646
+ * @param upVectorZ z component of vector to positive side of plane.
219647
+ * @param adjustToAllPositive if true, return strictly non-negative sweep (0 <= radians < 2*PI). If false, return signed (-PI < radians <= PI)
219648
+ */
219649
+ static orientedRadiansBetweenVectorsXYZ(ux, uy, uz, vx, vy, vz, upVectorX, upVectorY, upVectorZ, adjustToPositive = false) {
219650
+ const uDotV = ux * vx + uy * vy + uz * vz;
219651
+ const wx = uy * vz - uz * vy;
219652
+ const wy = uz * vx - ux * vz;
219653
+ const wz = ux * vy - uy * vx;
219654
+ const upDotW = upVectorX * wx + upVectorY * wy + upVectorZ * wz;
219655
+ const crossMagnitude = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.hypotenuseXYZ(wx, wy, wz);
219656
+ if (upDotW < 0.0) {
219657
+ if (adjustToPositive) {
219658
+ // The turn is greater than 180 degrees. Take a peculiarly oriented atan2 to get the excess-180 part as addition to PI.
219659
+ // This gives the smoothest numerical transition passing PI.
219660
+ return Math.PI + Math.atan2(crossMagnitude, -uDotV);
219661
+ }
219662
+ else {
219663
+ return -Math.atan2(crossMagnitude, uDotV);
219664
+ }
219665
+ }
219666
+ else {
219667
+ return Math.atan2(crossMagnitude, uDotV);
219668
+ }
219669
+ }
219631
219670
  /**
219632
219671
  * Add a multiple of a full circle angle (360 degrees, 2PI) in place.
219633
219672
  * @param multiple multiplier factor
@@ -229328,9 +229367,12 @@ __webpack_require__.r(__webpack_exports__);
229328
229367
  * @module CartesianGeometry
229329
229368
  */
229330
229369
  // cspell:word CWXY
229370
+ // cspell:word arctan
229371
+ // cspell:word Rodrigues
229331
229372
 
229332
229373
 
229333
229374
 
229375
+ // cspell:word CCWXY
229334
229376
  /**
229335
229377
  * * `XYZ` is a minimal object containing x,y,z and operations that are meaningful without change in both point and vector.
229336
229378
  * * `XYZ` is not instantiable.
@@ -230673,18 +230715,17 @@ class Vector3d extends XYZ {
230673
230715
  else
230674
230716
  return theta;
230675
230717
  }
230676
- /**
230677
- * Return the (strongly typed Angle) angle from this vector to vectorB, measured in the plane containing both,
230678
- * with vectorW indicating which side to view to control sign of the angle.
230679
- * * The returned angle can range from negative 180 degrees (negative PI radians) to positive 180 degrees
230680
- * * (positive PI radians), not closed on the negative side.
230681
- * * The returned angle is "in the plane containing the two vectors"
230682
- * * `vectorW` distinguishes between the sides of the plane, but does not have to be perpendicular.
230683
- * * The returned angle has the same sign as vectorW dot product (thisVector cross vectorB)
230684
- * * Use planarRadiansTo to measure the angle between vectors that are projected to another plane.
230685
- * @param vectorB target vector.
230686
- * @param vectorW distinguishes between the sides of the plane.
230687
- */
230718
+ /** Return the (strongly typed Angle) angle from this vector to vectorB, measured in the plane containing both,
230719
+ * with vectorW indicating which side to view to control sign of the angle.
230720
+ * * The returned angle can range from negative 180 degrees (negative PI radians) to positive 180 degrees
230721
+ * * (positive PI radians), not closed on the negative side.
230722
+ * * The returned angle is "in the plane containing the two vectors"
230723
+ * * `vectorW` distinguishes between the sides of the plane, but does not have to be perpendicular.
230724
+ * * The returned angle has the same sign as vectorW dot product (thisVector cross vectorB)
230725
+ * * Use planarRadiansTo to measure the angle between vectors that are projected to another plane.
230726
+ * @param vectorB target vector.
230727
+ * @param vectorW distinguishes between the sides of the plane.
230728
+ */
230688
230729
  signedAngleTo(vectorB, vectorW) {
230689
230730
  return _Angle__WEBPACK_IMPORTED_MODULE_2__.Angle.createRadians(this.signedRadiansTo(vectorB, vectorW));
230690
230731
  }
@@ -243421,6 +243462,20 @@ class SmallSystem {
243421
243462
  }
243422
243463
  return undefined;
243423
243464
  }
243465
+ /**
243466
+ * Compute the intersection of three planes.
243467
+ * @param xyzA point on the first plane
243468
+ * @param normalA normal of the first plane
243469
+ * @param xyzB point on the second plane
243470
+ * @param normalB normal of the second plane
243471
+ * @param xyzC point on the third plane
243472
+ * @param normalC normal of the third plane
243473
+ * @param result optional result
243474
+ * @returns intersection point of the three planes (as a Vector3d), or undefined if at least two planes are parallel.
243475
+ */
243476
+ static intersect3Planes(xyzA, normalA, xyzB, normalB, xyzC, normalC, result) {
243477
+ 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);
243478
+ }
243424
243479
  /**
243425
243480
  * * in rowB, replace `rowB[j] += a * rowB[pivot] * rowA[j] / rowA[pivot]` for `j>pivot`
243426
243481
  * @param rowA row that does not change
@@ -247532,10 +247587,29 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
247532
247587
  if (sector.uv)
247533
247588
  sector.uvIndex = this._polyface.addParam(sector.uv);
247534
247589
  }
247590
+ addSectorTriangle(sectorA0, sectorA1, sectorA2) {
247591
+ if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz)
247592
+ || sectorA1.xyz.isAlmostEqual(sectorA2.xyz)
247593
+ || sectorA2.xyz.isAlmostEqual(sectorA0.xyz)) {
247594
+ // trivially degenerate triangle !!! skip !!!
247595
+ }
247596
+ else {
247597
+ if (this._options.needNormals)
247598
+ this.addIndexedTriangleNormalIndexes(sectorA0.normalIndex, sectorA1.normalIndex, sectorA2.normalIndex);
247599
+ if (this._options.needParams)
247600
+ this.addIndexedTriangleParamIndexes(sectorA0.uvIndex, sectorA1.uvIndex, sectorA2.uvIndex);
247601
+ this.addIndexedTrianglePointIndexes(sectorA0.xyzIndex, sectorA1.xyzIndex, sectorA2.xyzIndex);
247602
+ this._polyface.terminateFacet();
247603
+ }
247604
+ }
247535
247605
  addSectorQuadA01B01(sectorA0, sectorA1, sectorB0, sectorB1) {
247536
247606
  if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz) && sectorB0.xyz.isAlmostEqual(sectorB1.xyz)) {
247537
247607
  // ignore null quad !!
247538
247608
  }
247609
+ else if (this._options.shouldTriangulate) {
247610
+ this.addSectorTriangle(sectorA0, sectorA1, sectorB1);
247611
+ this.addSectorTriangle(sectorB1, sectorB0, sectorA0);
247612
+ }
247539
247613
  else {
247540
247614
  if (this._options.needNormals)
247541
247615
  this.addIndexedQuadNormalIndexes(sectorA0.normalIndex, sectorA1.normalIndex, sectorB0.normalIndex, sectorB1.normalIndex);
@@ -247612,12 +247686,30 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
247612
247686
  }
247613
247687
  const numPoints = pointA.length;
247614
247688
  for (let i = 1; i < numPoints; i++) {
247615
- if (pointA.atUncheckedIndex(i - 1) !== pointA.atUncheckedIndex(i) || pointB.atUncheckedIndex(i - 1) !== pointB.atUncheckedIndex(i)) {
247616
- this.addIndexedQuadPointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i));
247617
- if (normalA && normalB)
247618
- this.addIndexedQuadNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i));
247619
- if (paramA && paramB)
247620
- this.addIndexedQuadParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i));
247689
+ if (this.options.shouldTriangulate) {
247690
+ if (distinctIndices(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i))) {
247691
+ this.addIndexedTrianglePointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i));
247692
+ if (normalA && normalB)
247693
+ this.addIndexedTriangleNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1));
247694
+ if (paramA && paramB)
247695
+ this.addIndexedTriangleParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1));
247696
+ }
247697
+ if (distinctIndices(pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i - 1))) {
247698
+ this.addIndexedTrianglePointIndexes(pointA.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1));
247699
+ if (normalA && normalB)
247700
+ this.addIndexedTriangleNormalIndexes(normalA.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1));
247701
+ if (paramA && paramB)
247702
+ this.addIndexedTriangleParamIndexes(paramA.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1));
247703
+ }
247704
+ }
247705
+ else {
247706
+ if (pointA.atUncheckedIndex(i - 1) !== pointA.atUncheckedIndex(i) || pointB.atUncheckedIndex(i - 1) !== pointB.atUncheckedIndex(i)) {
247707
+ this.addIndexedQuadPointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i));
247708
+ if (normalA && normalB)
247709
+ this.addIndexedQuadNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i));
247710
+ if (paramA && paramB)
247711
+ this.addIndexedQuadParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i));
247712
+ }
247621
247713
  this._polyface.terminateFacet();
247622
247714
  }
247623
247715
  }
@@ -248614,6 +248706,9 @@ function resolveToIndexedXYZCollectionOrCarrier(points) {
248614
248706
  return points.packedPoints;
248615
248707
  return points;
248616
248708
  }
248709
+ function distinctIndices(i0, i1, i2) {
248710
+ return i0 !== i1 && i1 !== i2 && i2 !== i0;
248711
+ }
248617
248712
 
248618
248713
 
248619
248714
  /***/ }),
@@ -249782,38 +249877,41 @@ function compressUnusedGrowableXYZArray(data: GrowableXYZArray, indices: number[
249782
249877
  __webpack_require__.r(__webpack_exports__);
249783
249878
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
249784
249879
  /* harmony export */ "DuplicateFacetClusterSelector": () => (/* binding */ DuplicateFacetClusterSelector),
249880
+ /* harmony export */ "OffsetMeshOptions": () => (/* binding */ OffsetMeshOptions),
249785
249881
  /* harmony export */ "PolyfaceQuery": () => (/* binding */ PolyfaceQuery)
249786
249882
  /* harmony export */ });
249787
249883
  /* harmony import */ var _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../geometry3d/PointHelpers */ "../../core/geometry/lib/esm/geometry3d/PointHelpers.js");
249788
- /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
249884
+ /* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
249789
249885
  /* harmony import */ var _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../curve/internalContexts/MultiChainCollector */ "../../core/geometry/lib/esm/curve/internalContexts/MultiChainCollector.js");
249790
- /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
249791
- /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
249792
- /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
249886
+ /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
249887
+ /* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
249888
+ /* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
249793
249889
  /* harmony import */ var _curve_StrokeOptions__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../curve/StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
249794
- /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
249795
- /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
249890
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
249891
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
249796
249892
  /* harmony import */ var _geometry3d_FrameBuilder__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../geometry3d/FrameBuilder */ "../../core/geometry/lib/esm/geometry3d/FrameBuilder.js");
249797
- /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
249798
- /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
249893
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
249894
+ /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
249799
249895
  /* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
249800
- /* harmony import */ var _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../geometry4d/Matrix4d */ "../../core/geometry/lib/esm/geometry4d/Matrix4d.js");
249801
- /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
249802
- /* harmony import */ var _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../numerics/UnionFind */ "../../core/geometry/lib/esm/numerics/UnionFind.js");
249896
+ /* harmony import */ var _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../geometry4d/Matrix4d */ "../../core/geometry/lib/esm/geometry4d/Matrix4d.js");
249897
+ /* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
249898
+ /* harmony import */ var _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../numerics/UnionFind */ "../../core/geometry/lib/esm/numerics/UnionFind.js");
249803
249899
  /* harmony import */ var _topology_ChainMerge__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../topology/ChainMerge */ "../../core/geometry/lib/esm/topology/ChainMerge.js");
249804
249900
  /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
249805
249901
  /* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
249806
249902
  /* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
249807
- /* harmony import */ var _FacetOrientation__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./FacetOrientation */ "../../core/geometry/lib/esm/polyface/FacetOrientation.js");
249808
- /* harmony import */ var _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./IndexedEdgeMatcher */ "../../core/geometry/lib/esm/polyface/IndexedEdgeMatcher.js");
249903
+ /* harmony import */ var _FacetOrientation__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./FacetOrientation */ "../../core/geometry/lib/esm/polyface/FacetOrientation.js");
249904
+ /* harmony import */ var _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./IndexedEdgeMatcher */ "../../core/geometry/lib/esm/polyface/IndexedEdgeMatcher.js");
249809
249905
  /* harmony import */ var _IndexedPolyfaceVisitor__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./IndexedPolyfaceVisitor */ "../../core/geometry/lib/esm/polyface/IndexedPolyfaceVisitor.js");
249810
- /* harmony import */ var _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./multiclip/BuildAverageNormalsContext */ "../../core/geometry/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js");
249811
- /* harmony import */ var _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./multiclip/SweepLineStringToFacetContext */ "../../core/geometry/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js");
249906
+ /* harmony import */ var _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./multiclip/BuildAverageNormalsContext */ "../../core/geometry/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js");
249907
+ /* harmony import */ var _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./multiclip/SweepLineStringToFacetContext */ "../../core/geometry/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js");
249812
249908
  /* harmony import */ var _multiclip_XYPointBuckets__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./multiclip/XYPointBuckets */ "../../core/geometry/lib/esm/polyface/multiclip/XYPointBuckets.js");
249813
- /* harmony import */ var _Polyface__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Polyface */ "../../core/geometry/lib/esm/polyface/Polyface.js");
249909
+ /* harmony import */ var _Polyface__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Polyface */ "../../core/geometry/lib/esm/polyface/Polyface.js");
249814
249910
  /* harmony import */ var _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./PolyfaceBuilder */ "../../core/geometry/lib/esm/polyface/PolyfaceBuilder.js");
249815
249911
  /* harmony import */ var _RangeLengthData__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./RangeLengthData */ "../../core/geometry/lib/esm/polyface/RangeLengthData.js");
249816
249912
  /* harmony import */ var _topology_SpaceTriangulation__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../topology/SpaceTriangulation */ "../../core/geometry/lib/esm/topology/SpaceTriangulation.js");
249913
+ /* harmony import */ var _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../topology/HalfEdgeGraphFromIndexedLoopsContext */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js");
249914
+ /* harmony import */ var _multiclip_OffsetMeshContext__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./multiclip/OffsetMeshContext */ "../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js");
249817
249915
  /*---------------------------------------------------------------------------------------------
249818
249916
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
249819
249917
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -249853,6 +249951,41 @@ __webpack_require__.r(__webpack_exports__);
249853
249951
 
249854
249952
 
249855
249953
 
249954
+
249955
+
249956
+ /**
249957
+ * Options carrier for [[PolyfaceQuery.cloneOffset]].
249958
+ * * Default options are strongly recommended.
249959
+ * * The option most likely to be changed is chamferTurnAngle
249960
+ * @public
249961
+ */
249962
+ class OffsetMeshOptions {
249963
+ /** Constructor -- CAPTURE parameters ... */
249964
+ 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)) {
249965
+ this.smoothSingleAngleBetweenNormals = smoothSingleAngleBetweenNormals.clone();
249966
+ this.smoothAccumulatedAngleBetweenNormals = smoothAccumulatedAngleBetweenNormals.clone();
249967
+ this.chamferAngleBetweenNormals = chamferTurnAngle.clone();
249968
+ }
249969
+ /** construct and return an OffsetMeshOptions with given parameters.
249970
+ * * Angles are forced to minimum values.
249971
+ * * Clones of the angles are given to the constructor.
249972
+ * @param smoothSingleRadiansBetweenNormals an angle larger than this (between facets) is considered a sharp edge
249973
+ * @param smoothAccumulatedAngleBetweenNormals angles that sum to this much may be consolidated for average normal
249974
+ * @param chamferTurnAngleBetweenNormals when facets meet with larger angle, a chamfer edge may be added if the angle between facet normals is larger than this.
249975
+ */
249976
+ 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)) {
249977
+ const mySmoothSingleRadiansBetweenNormals = smoothSingleAngleBetweenNormals.clone();
249978
+ const mySmoothAccumulatedRadiansBetweenNormals = smoothAccumulatedAngleBetweenNormals.clone();
249979
+ const myChamferTurnAngleBetweenNormals = chamferTurnAngleBetweenNormals.clone();
249980
+ if (mySmoothSingleRadiansBetweenNormals.degrees < 1)
249981
+ mySmoothAccumulatedRadiansBetweenNormals.setDegrees(1.0);
249982
+ if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 1.0)
249983
+ mySmoothAccumulatedRadiansBetweenNormals.setDegrees(1.0);
249984
+ if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 15.0)
249985
+ mySmoothAccumulatedRadiansBetweenNormals.setDegrees(15.0);
249986
+ return new OffsetMeshOptions(mySmoothSingleRadiansBetweenNormals, mySmoothAccumulatedRadiansBetweenNormals, myChamferTurnAngleBetweenNormals);
249987
+ }
249988
+ }
249856
249989
  /**
249857
249990
  * Enumeration of cases for retaining facets among duplicates
249858
249991
  * @public
@@ -249874,12 +250007,12 @@ var DuplicateFacetClusterSelector;
249874
250007
  class PolyfaceQuery {
249875
250008
  /** copy the points from a visitor into a Linestring3d in a Loop object */
249876
250009
  static visitorToLoop(visitor) {
249877
- const ls = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_0__.LineString3d.createPoints(visitor.point.getPoint3dArray());
249878
- return _curve_Loop__WEBPACK_IMPORTED_MODULE_1__.Loop.create(ls);
250010
+ const ls = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_1__.LineString3d.createPoints(visitor.point.getPoint3dArray());
250011
+ return _curve_Loop__WEBPACK_IMPORTED_MODULE_2__.Loop.create(ls);
249879
250012
  }
249880
250013
  /** Create a linestring loop for each facet of the polyface. */
249881
250014
  static indexedPolyfaceToLoops(polyface) {
249882
- const result = _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_2__.BagOfCurves.create();
250015
+ const result = _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.BagOfCurves.create();
249883
250016
  const visitor = polyface.createVisitor(1);
249884
250017
  while (visitor.moveToNextFacet()) {
249885
250018
  const loop = PolyfaceQuery.visitorToLoop(visitor);
@@ -249893,17 +250026,17 @@ class PolyfaceQuery {
249893
250026
  static sumFacetAreas(source, vectorToEye) {
249894
250027
  let s = 0;
249895
250028
  if (source !== undefined) {
249896
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
250029
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
249897
250030
  return PolyfaceQuery.sumFacetAreas(source.createVisitor(1), vectorToEye);
249898
250031
  let unitVectorToEye;
249899
250032
  if (vectorToEye !== undefined)
249900
250033
  unitVectorToEye = vectorToEye.normalize();
249901
250034
  source.reset();
249902
250035
  while (source.moveToNextFacet()) {
249903
- const scaledNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.areaNormal(source.point.getPoint3dArray());
250036
+ const scaledNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.areaNormal(source.point.getPoint3dArray());
249904
250037
  let area = scaledNormal.magnitude();
249905
250038
  if (unitVectorToEye !== undefined) {
249906
- const scale = _Geometry__WEBPACK_IMPORTED_MODULE_5__.Geometry.conditionalDivideCoordinate(1.0, area);
250039
+ const scale = _Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.conditionalDivideCoordinate(1.0, area);
249907
250040
  if (scale !== undefined)
249908
250041
  area *= scaledNormal.dotProduct(unitVectorToEye) * scale;
249909
250042
  }
@@ -249920,12 +250053,12 @@ class PolyfaceQuery {
249920
250053
  */
249921
250054
  static sumTetrahedralVolumes(source, origin) {
249922
250055
  let s = 0;
249923
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
250056
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
249924
250057
  return PolyfaceQuery.sumTetrahedralVolumes(source.createVisitor(0), origin);
249925
250058
  let myOrigin = origin;
249926
- const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
249927
- const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
249928
- const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
250059
+ const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
250060
+ const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
250061
+ const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
249929
250062
  source.reset();
249930
250063
  while (source.moveToNextFacet()) {
249931
250064
  if (myOrigin === undefined)
@@ -249946,20 +250079,20 @@ class PolyfaceQuery {
249946
250079
  *
249947
250080
  */
249948
250081
  static sumVolumeBetweenFacetsAndPlane(source, plane) {
249949
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
250082
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
249950
250083
  return PolyfaceQuery.sumVolumeBetweenFacetsAndPlane(source.createVisitor(0), plane);
249951
- const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
249952
- const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
249953
- const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
249954
- const triangleNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
250084
+ const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
250085
+ const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
250086
+ const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
250087
+ const triangleNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
249955
250088
  const planeNormal = plane.getNormalRef();
249956
250089
  let h0, hA, hB;
249957
250090
  let signedVolumeSum = 0.0;
249958
250091
  let signedTriangleArea;
249959
250092
  let singleFacetArea;
249960
- const positiveAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.create(undefined, true);
249961
- const negativeAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.create(undefined, true);
249962
- const singleFacetProducts = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_8__.Matrix4d.createZero();
250093
+ const positiveAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.create(undefined, true);
250094
+ const negativeAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.create(undefined, true);
250095
+ const singleFacetProducts = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
249963
250096
  const projectToPlane = plane.getProjectionToPlane();
249964
250097
  source.reset();
249965
250098
  // For each facet ..
@@ -249986,7 +250119,7 @@ class PolyfaceQuery {
249986
250119
  }
249987
250120
  singleFacetProducts.setZero();
249988
250121
  source.point.multiplyTransformInPlace(projectToPlane);
249989
- _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.addSecondMomentAreaProducts(source.point, facetOrigin, singleFacetProducts);
250122
+ _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentAreaProducts(source.point, facetOrigin, singleFacetProducts);
249990
250123
  if (singleFacetArea > 0) {
249991
250124
  positiveAreaMomentSums.accumulateProductsFromOrigin(facetOrigin, singleFacetProducts, 1.0);
249992
250125
  }
@@ -249996,8 +250129,8 @@ class PolyfaceQuery {
249996
250129
  }
249997
250130
  positiveAreaMomentSums.shiftOriginAndSumsToCentroidOfSums();
249998
250131
  negativeAreaMomentSums.shiftOriginAndSumsToCentroidOfSums();
249999
- const positiveAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.inertiaProductsToPrincipalAxes(positiveAreaMomentSums.origin, positiveAreaMomentSums.sums);
250000
- const negativeAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.inertiaProductsToPrincipalAxes(negativeAreaMomentSums.origin, negativeAreaMomentSums.sums);
250132
+ const positiveAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(positiveAreaMomentSums.origin, positiveAreaMomentSums.sums);
250133
+ const negativeAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(negativeAreaMomentSums.origin, negativeAreaMomentSums.sums);
250001
250134
  return {
250002
250135
  volume: signedVolumeSum / 6.0,
250003
250136
  positiveProjectedFacetAreaMoments: positiveAreaMoments,
@@ -250006,23 +250139,23 @@ class PolyfaceQuery {
250006
250139
  }
250007
250140
  /** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all all facets, as viewed from origin. */
250008
250141
  static sumFacetSecondAreaMomentProducts(source, origin) {
250009
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
250142
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
250010
250143
  return PolyfaceQuery.sumFacetSecondAreaMomentProducts(source.createVisitor(0), origin);
250011
- const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_8__.Matrix4d.createZero();
250144
+ const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
250012
250145
  source.reset();
250013
250146
  while (source.moveToNextFacet()) {
250014
- _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.addSecondMomentAreaProducts(source.point, origin, products);
250147
+ _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentAreaProducts(source.point, origin, products);
250015
250148
  }
250016
250149
  return products;
250017
250150
  }
250018
250151
  /** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all tetrahedral volumes from origin */
250019
250152
  static sumFacetSecondVolumeMomentProducts(source, origin) {
250020
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
250153
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
250021
250154
  return PolyfaceQuery.sumFacetSecondVolumeMomentProducts(source.createVisitor(0), origin);
250022
- const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_8__.Matrix4d.createZero();
250155
+ const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
250023
250156
  source.reset();
250024
250157
  while (source.moveToNextFacet()) {
250025
- _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.addSecondMomentVolumeProducts(source.point, origin, products);
250158
+ _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentVolumeProducts(source.point, origin, products);
250026
250159
  }
250027
250160
  return products;
250028
250161
  }
@@ -250036,7 +250169,7 @@ class PolyfaceQuery {
250036
250169
  if (!origin)
250037
250170
  return undefined;
250038
250171
  const inertiaProducts = PolyfaceQuery.sumFacetSecondAreaMomentProducts(source, origin);
250039
- return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
250172
+ return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
250040
250173
  }
250041
250174
  /** Compute area moments for the mesh. In the returned MomentData:
250042
250175
  * * origin is the centroid.
@@ -250050,7 +250183,7 @@ class PolyfaceQuery {
250050
250183
  if (!origin)
250051
250184
  return undefined;
250052
250185
  const inertiaProducts = PolyfaceQuery.sumFacetSecondVolumeMomentProducts(source, origin);
250053
- return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_7__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
250186
+ return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
250054
250187
  }
250055
250188
  /**
250056
250189
  * Test for convex volume by dihedral angle tests on all edges.
@@ -250082,14 +250215,14 @@ class PolyfaceQuery {
250082
250215
  * * (but null edges are permitted -- These occur naturally at edges of quads at north or south pole)
250083
250216
  */
250084
250217
  static dihedralAngleSummary(source, ignoreBoundaries = false) {
250085
- const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
250218
+ const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
250086
250219
  const visitor = source.createVisitor(1);
250087
250220
  visitor.reset();
250088
250221
  const centroidNormal = [];
250089
250222
  let normalCounter = 0;
250090
250223
  while (visitor.moveToNextFacet()) {
250091
250224
  const numEdges = visitor.pointCount - 1;
250092
- const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.centroidAreaNormal(visitor.point);
250225
+ const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.centroidAreaNormal(visitor.point);
250093
250226
  if (normal === undefined)
250094
250227
  return 0;
250095
250228
  centroidNormal.push(normal);
@@ -250106,12 +250239,12 @@ class PolyfaceQuery {
250106
250239
  let numPositive = 0;
250107
250240
  let numPlanar = 0;
250108
250241
  let numNegative = 0;
250109
- const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
250242
+ const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
250110
250243
  for (const cluster of manifoldClusters) {
250111
250244
  const sideA = cluster[0];
250112
250245
  const sideB = cluster[1];
250113
- if (sideA instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge
250114
- && sideB instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge
250246
+ if (sideA instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge
250247
+ && sideB instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge
250115
250248
  && source.data.point.vectorIndexIndex(sideA.vertexIndexA, sideA.vertexIndexB, edgeVector)) {
250116
250249
  const dihedralAngle = centroidNormal[sideA.facetIndex].direction.signedAngleTo(centroidNormal[sideB.facetIndex].direction, edgeVector);
250117
250250
  if (dihedralAngle.isAlmostZero)
@@ -250144,7 +250277,7 @@ class PolyfaceQuery {
250144
250277
  * * Any edge with 2 incident facets in the same direction triggers a `false` return.
250145
250278
  */
250146
250279
  static isPolyfaceManifold(source, allowSimpleBoundaries = false) {
250147
- const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
250280
+ const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
250148
250281
  const visitor = source.createVisitor(1);
250149
250282
  visitor.reset();
250150
250283
  while (visitor.moveToNextFacet()) {
@@ -250167,9 +250300,9 @@ class PolyfaceQuery {
250167
250300
  * @returns
250168
250301
  */
250169
250302
  static boundaryEdges(source, includeDanglers = true, includeMismatch = true, includeNull = true) {
250170
- const result = new _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_2__.BagOfCurves();
250303
+ const result = new _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.BagOfCurves();
250171
250304
  const announceEdge = (pointA, pointB, _indexA, _indexB, _readIndex) => {
250172
- result.tryAddChild(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(pointA, pointB));
250305
+ result.tryAddChild(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB));
250173
250306
  };
250174
250307
  PolyfaceQuery.announceBoundaryEdges(source, announceEdge, includeDanglers, includeMismatch, includeNull);
250175
250308
  if (result.children.length === 0)
@@ -250188,8 +250321,8 @@ class PolyfaceQuery {
250188
250321
  static announceBoundaryEdges(source, announceEdge, includeDanglers = true, includeMismatch = true, includeNull = true) {
250189
250322
  if (source === undefined)
250190
250323
  return undefined;
250191
- const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
250192
- const visitor = source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface ? source.createVisitor(1) : source;
250324
+ const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
250325
+ const visitor = source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface ? source.createVisitor(1) : source;
250193
250326
  visitor.setNumWrap(1);
250194
250327
  visitor.reset();
250195
250328
  while (visitor.moveToNextFacet()) {
@@ -250214,7 +250347,7 @@ class PolyfaceQuery {
250214
250347
  const sourcePolyface = visitor.clientPolyface();
250215
250348
  for (const list of badList) {
250216
250349
  for (const e of list) {
250217
- const e1 = e instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge ? e : e[0];
250350
+ const e1 = e instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge ? e : e[0];
250218
250351
  const indexA = e1.vertexIndexA;
250219
250352
  const indexB = e1.vertexIndexB;
250220
250353
  const pointA = sourcePolyface.data.getPoint(indexA);
@@ -250229,7 +250362,7 @@ class PolyfaceQuery {
250229
250362
  * * Facets are ASSUMED to be convex and planar.
250230
250363
  */
250231
250364
  static announceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, announce) {
250232
- const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_11__.SweepLineStringToFacetContext.create(linestringPoints);
250365
+ const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__.SweepLineStringToFacetContext.create(linestringPoints);
250233
250366
  if (context) {
250234
250367
  const visitor = polyface.createVisitor(0);
250235
250368
  for (visitor.reset(); visitor.moveToNextFacet();) {
@@ -250262,7 +250395,7 @@ class PolyfaceQuery {
250262
250395
  * @internal
250263
250396
  */
250264
250397
  static async asyncAnnounceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, announce) {
250265
- const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_11__.SweepLineStringToFacetContext.create(linestringPoints);
250398
+ const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__.SweepLineStringToFacetContext.create(linestringPoints);
250266
250399
  this.awaitBlockCount = 0;
250267
250400
  let workTotal = 0;
250268
250401
  if (context) {
@@ -250282,11 +250415,11 @@ class PolyfaceQuery {
250282
250415
  * * Return array of arrays of facet indices.
250283
250416
  */
250284
250417
  static partitionFacetIndicesByVertexConnectedComponent(polyface) {
250285
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
250418
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
250286
250419
  return this.partitionFacetIndicesByVertexConnectedComponent(polyface.createVisitor(0));
250287
250420
  }
250288
250421
  // The polyface is really a visitor !!!
250289
- const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_12__.UnionFindContext(this.visitorClientPointCount(polyface));
250422
+ const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__.UnionFindContext(this.visitorClientPointCount(polyface));
250290
250423
  for (polyface.reset(); polyface.moveToNextFacet();) {
250291
250424
  const firstVertexIndexOnThisFacet = polyface.pointIndex[0];
250292
250425
  for (const vertexIndex of polyface.pointIndex)
@@ -250319,7 +250452,7 @@ class PolyfaceQuery {
250319
250452
  * * Return array of arrays of facet indices.
250320
250453
  */
250321
250454
  static partitionFacetIndicesByVisibilityVector(polyface, vectorToEye, sideAngleTolerance) {
250322
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
250455
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
250323
250456
  return this.partitionFacetIndicesByVisibilityVector(polyface.createVisitor(0), vectorToEye, sideAngleTolerance);
250324
250457
  }
250325
250458
  const facetsInComponent = [];
@@ -250331,7 +250464,7 @@ class PolyfaceQuery {
250331
250464
  const sideComponent = facetsInComponent[2];
250332
250465
  const radiansTol = Math.max(sideAngleTolerance.radians, 1.0e-8);
250333
250466
  for (polyface.reset(); polyface.moveToNextFacet();) {
250334
- const areaNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.areaNormalGo(polyface.point);
250467
+ const areaNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.areaNormalGo(polyface.point);
250335
250468
  const index = polyface.currentReadIndex();
250336
250469
  if (areaNormal) {
250337
250470
  const angle = areaNormal.angleFromPerpendicular(vectorToEye);
@@ -250358,7 +250491,7 @@ class PolyfaceQuery {
250358
250491
  * @param vectorToEye
250359
250492
  * @param sideAngleTolerance
250360
250493
  */
250361
- static boundaryOfVisibleSubset(polyface, visibilitySelect, vectorToEye, sideAngleTolerance = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_13__.Angle.createDegrees(1.0e-3)) {
250494
+ static boundaryOfVisibleSubset(polyface, visibilitySelect, vectorToEye, sideAngleTolerance = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(1.0e-3)) {
250362
250495
  const partitionedIndices = this.partitionFacetIndicesByVisibilityVector(polyface, vectorToEye, sideAngleTolerance);
250363
250496
  if (partitionedIndices[visibilitySelect].length === 0)
250364
250497
  return undefined;
@@ -250372,8 +250505,8 @@ class PolyfaceQuery {
250372
250505
  * @param mesh
250373
250506
  */
250374
250507
  static announceBoundaryChainsAsLineString3d(mesh, announceLoop) {
250375
- const collector = new _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.MultiChainCollector(_Geometry__WEBPACK_IMPORTED_MODULE_5__.Geometry.smallMetricDistance, 1000);
250376
- PolyfaceQuery.announceBoundaryEdges(mesh, (pointA, pointB, _indexA, _indexB) => collector.captureCurve(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(pointA, pointB)), true, false, false);
250508
+ const collector = new _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.MultiChainCollector(_Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallMetricDistance, 1000);
250509
+ PolyfaceQuery.announceBoundaryEdges(mesh, (pointA, pointB, _indexA, _indexB) => collector.captureCurve(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB)), true, false, false);
250377
250510
  collector.announceChainsAsLineString3d(announceLoop);
250378
250511
  }
250379
250512
  /**
@@ -250384,7 +250517,7 @@ class PolyfaceQuery {
250384
250517
  * @returns
250385
250518
  */
250386
250519
  static cloneWithMaximalPlanarFacets(mesh) {
250387
- if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
250520
+ if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
250388
250521
  return this.cloneWithMaximalPlanarFacets(mesh.createVisitor(0));
250389
250522
  const numFacets = PolyfaceQuery.visitorClientFacetCount(mesh);
250390
250523
  const smoothEdges = PolyfaceQuery.collectEdgesByDihedralAngle(mesh);
@@ -250409,7 +250542,7 @@ class PolyfaceQuery {
250409
250542
  const edges = [];
250410
250543
  const edgeStrings = [];
250411
250544
  PolyfaceQuery.announceBoundaryEdges(fragment, (pointA, pointB, _indexA, _indexB) => {
250412
- edges.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(pointA, pointB));
250545
+ edges.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB));
250413
250546
  edgeStrings.push([pointA.clone(), pointB.clone()]);
250414
250547
  });
250415
250548
  const chains = _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.OffsetHelpers.collectChains(edges, gapTolerance, planarityTolerance);
@@ -250450,7 +250583,7 @@ class PolyfaceQuery {
250450
250583
  * @returns
250451
250584
  */
250452
250585
  static fillSimpleHoles(mesh, options, unfilledChains) {
250453
- if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
250586
+ if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
250454
250587
  return this.fillSimpleHoles(mesh.createVisitor(0), options, unfilledChains);
250455
250588
  const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
250456
250589
  const chains = [];
@@ -250464,7 +250597,7 @@ class PolyfaceQuery {
250464
250597
  rejected = true;
250465
250598
  else if (options.maxPerimeter !== undefined && _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_21__.Point3dArray.sumEdgeLengths(points, false) > options.maxPerimeter)
250466
250599
  rejected = true;
250467
- else if (options.upVector !== undefined && _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.sumTriangleAreasPerpendicularToUpVector(points, options.upVector) <= 0.0)
250600
+ else if (options.upVector !== undefined && _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.sumTriangleAreasPerpendicularToUpVector(points, options.upVector) <= 0.0)
250468
250601
  rejected = true;
250469
250602
  if (!rejected && _topology_SpaceTriangulation__WEBPACK_IMPORTED_MODULE_22__.SpacePolygonTriangulation.triangulateSimplestSpaceLoop(points, (_loop, triangles) => {
250470
250603
  for (const t of triangles)
@@ -250487,7 +250620,7 @@ class PolyfaceQuery {
250487
250620
  *
250488
250621
  */
250489
250622
  static clonePartitions(polyface, partitions) {
250490
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
250623
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
250491
250624
  return this.clonePartitions(polyface.createVisitor(0), partitions);
250492
250625
  }
250493
250626
  polyface.setNumWrap(0);
@@ -250511,7 +250644,7 @@ class PolyfaceQuery {
250511
250644
  /** Clone facets that pass an filter function
250512
250645
  */
250513
250646
  static cloneFiltered(source, filter) {
250514
- if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
250647
+ if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
250515
250648
  return this.cloneFiltered(source.createVisitor(0), filter);
250516
250649
  }
250517
250650
  source.setNumWrap(0);
@@ -250563,9 +250696,9 @@ class PolyfaceQuery {
250563
250696
  * @return collection of facet index arrays, one array per connected component
250564
250697
  */
250565
250698
  static partitionFacetIndicesBySortableEdgeClusters(edgeClusters, numFacets) {
250566
- const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_12__.UnionFindContext(numFacets);
250699
+ const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__.UnionFindContext(numFacets);
250567
250700
  for (const cluster of edgeClusters) {
250568
- if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge) {
250701
+ if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge) {
250569
250702
  // this edge does not connect anywhere. Ignore it!!
250570
250703
  }
250571
250704
  else {
@@ -250597,11 +250730,11 @@ class PolyfaceQuery {
250597
250730
  * @return collection of facet index arrays, one per connected component
250598
250731
  */
250599
250732
  static partitionFacetIndicesByEdgeConnectedComponent(polyface, stopAtVisibleEdges = false) {
250600
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
250733
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
250601
250734
  return this.partitionFacetIndicesByEdgeConnectedComponent(polyface.createVisitor(0), stopAtVisibleEdges);
250602
250735
  }
250603
250736
  polyface.setNumWrap(1);
250604
- const matcher = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
250737
+ const matcher = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
250605
250738
  polyface.reset();
250606
250739
  let numFacets = 0;
250607
250740
  while (polyface.moveToNextFacet()) {
@@ -250639,7 +250772,7 @@ class PolyfaceQuery {
250639
250772
  static sweepLinestringToFacetsXYReturnLines(linestringPoints, polyface) {
250640
250773
  const drapeGeometry = [];
250641
250774
  this.announceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, (_linestring, _segmentIndex, _polyface, _facetIndex, points, indexA, indexB) => {
250642
- drapeGeometry.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(points[indexA], points[indexB]));
250775
+ drapeGeometry.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(points[indexA], points[indexB]));
250643
250776
  });
250644
250777
  return drapeGeometry;
250645
250778
  }
@@ -250674,7 +250807,7 @@ class PolyfaceQuery {
250674
250807
  * * Return statistical summary of x,y,z ranges.
250675
250808
  */
250676
250809
  static collectRangeLengthData(polyface) {
250677
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface) {
250810
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
250678
250811
  return this.collectRangeLengthData(polyface.createVisitor(0));
250679
250812
  }
250680
250813
  const rangeData = new _RangeLengthData__WEBPACK_IMPORTED_MODULE_25__.RangeLengthData();
@@ -250692,10 +250825,10 @@ class PolyfaceQuery {
250692
250825
  const rangeSearcher = _multiclip_XYPointBuckets__WEBPACK_IMPORTED_MODULE_26__.XYPointBuckets.create(polyface.data.point, 30);
250693
250826
  const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
250694
250827
  const edgeRange = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_27__.Range3d.createNull();
250695
- const point0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
250696
- const point1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
250697
- const spacePoint = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Point3d.create();
250698
- const segment = _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(point0, point1);
250828
+ const point0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
250829
+ const point1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
250830
+ const spacePoint = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
250831
+ const segment = _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(point0, point1);
250699
250832
  for (oldFacetVisitor.reset(); oldFacetVisitor.moveToNextFacet();) {
250700
250833
  newFacetVisitor.clearArrays();
250701
250834
  for (let i = 0; i + 1 < oldFacetVisitor.point.length; i++) {
@@ -250704,7 +250837,7 @@ class PolyfaceQuery {
250704
250837
  oldFacetVisitor.point.getPoint3dAtUncheckedPointIndex(i + 1, point1);
250705
250838
  newFacetVisitor.pushDataFrom(oldFacetVisitor, i);
250706
250839
  edgeRange.setNull();
250707
- _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_10__.LineSegment3d.create(point0, point1, segment);
250840
+ _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(point0, point1, segment);
250708
250841
  let detailArray;
250709
250842
  edgeRange.extend(point0);
250710
250843
  edgeRange.extend(point1);
@@ -250849,8 +250982,8 @@ class PolyfaceQuery {
250849
250982
  const oldFacetVisitor = polyface.createVisitor(2); // This is to visit the existing facets.
250850
250983
  const newFacetVisitor = polyface.createVisitor(0); // This is to build the new facets.
250851
250984
  const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
250852
- const vector01 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
250853
- const vector12 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
250985
+ const vector01 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
250986
+ const vector12 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
250854
250987
  const numPoint = polyface.data.point.length;
250855
250988
  const pointState = new Int32Array(numPoint);
250856
250989
  // FIRST PASS -- in each sector of each facet, determine if the sector has colinear incoming and outgoing vectors.
@@ -250897,7 +251030,7 @@ class PolyfaceQuery {
250897
251030
  */
250898
251031
  static setEdgeVisibility(polyface, clusters, value) {
250899
251032
  for (const cluster of clusters) {
250900
- if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.SortableEdge) {
251033
+ if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge) {
250901
251034
  this.setSingleEdgeVisibility(polyface, cluster.facetIndex, cluster.vertexIndexA, value);
250902
251035
  }
250903
251036
  else if (Array.isArray(cluster)) {
@@ -250940,9 +251073,9 @@ class PolyfaceQuery {
250940
251073
  * @param polyface a mesh, or a visitor assumed to have numWrap === 1
250941
251074
  */
250942
251075
  static createIndexedEdges(polyface) {
250943
- if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
251076
+ if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
250944
251077
  return this.createIndexedEdges(polyface.createVisitor(1));
250945
- const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_9__.IndexedEdgeMatcher();
251078
+ const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
250946
251079
  polyface.reset();
250947
251080
  while (polyface.moveToNextFacet()) {
250948
251081
  const numEdges = polyface.pointCount - 1;
@@ -250961,17 +251094,17 @@ class PolyfaceQuery {
250961
251094
  * @param sharpEdges true to reverse the angle threshold test and return sharp edges; otherwise return smooth edges (default)
250962
251095
  */
250963
251096
  static collectEdgesByDihedralAngle(mesh, maxSmoothEdgeAngle, sharpEdges = false) {
250964
- if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_3__.Polyface)
251097
+ if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
250965
251098
  return this.collectEdgesByDihedralAngle(mesh.createVisitor(1), maxSmoothEdgeAngle, sharpEdges);
250966
251099
  mesh.setNumWrap(1);
250967
251100
  const allEdges = this.createIndexedEdges(mesh);
250968
251101
  const manifoldEdges = [];
250969
251102
  allEdges.sortAndCollectClusters(manifoldEdges);
250970
251103
  if (undefined === maxSmoothEdgeAngle || maxSmoothEdgeAngle.radians < 0)
250971
- maxSmoothEdgeAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_13__.Angle.createRadians(_Geometry__WEBPACK_IMPORTED_MODULE_5__.Geometry.smallAngleRadians);
251104
+ maxSmoothEdgeAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createRadians(_Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallAngleRadians);
250972
251105
  const outEdges = [];
250973
- const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
250974
- const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
251106
+ const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
251107
+ const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
250975
251108
  for (const pair of manifoldEdges) {
250976
251109
  if (Array.isArray(pair) && pair.length === 2) {
250977
251110
  const e0 = pair[0];
@@ -251010,8 +251143,8 @@ class PolyfaceQuery {
251010
251143
  this.markAllEdgeVisibility(mesh, false);
251011
251144
  this.setEdgeVisibility(mesh, boundaryEdges, true);
251012
251145
  if (sharpEdgeAngle !== undefined) {
251013
- const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
251014
- const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
251146
+ const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
251147
+ const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
251015
251148
  for (const pair of pairedEdges) {
251016
251149
  if (Array.isArray(pair) && pair.length === 2) {
251017
251150
  const e0 = pair[0];
@@ -251033,9 +251166,9 @@ class PolyfaceQuery {
251033
251166
  */
251034
251167
  static computeFacetUnitNormal(visitor, facetIndex, result) {
251035
251168
  if (!result)
251036
- result = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_6__.Vector3d.create();
251169
+ result = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
251037
251170
  if (visitor.moveToReadIndex(facetIndex)) {
251038
- if (_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_4__.PolygonOps.unitNormal(visitor.point, result))
251171
+ if (_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.unitNormal(visitor.point, result))
251039
251172
  return result;
251040
251173
  }
251041
251174
  return undefined;
@@ -251050,20 +251183,41 @@ class PolyfaceQuery {
251050
251183
  for (let i = 0; i < data.edgeVisible.length; i++)
251051
251184
  data.edgeVisible[i] = value;
251052
251185
  }
251186
+ /**
251187
+ * Create a HalfEdgeGraph with a face for each facet of the IndexedPolyface
251188
+ * @param mesh mesh to convert
251189
+ * @internal
251190
+ */
251191
+ static convertToHalfEdgeGraph(mesh) {
251192
+ const builder = new _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_28__.HalfEdgeGraphFromIndexedLoopsContext();
251193
+ const visitor = mesh.createVisitor(0);
251194
+ for (visitor.reset(); visitor.moveToNextFacet();) {
251195
+ builder.insertLoop(visitor.pointIndex);
251196
+ }
251197
+ const graph = builder.graph;
251198
+ const xyz = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
251199
+ graph.announceNodes((_graph, halfEdge) => {
251200
+ const vertexIndex = halfEdge.i;
251201
+ mesh.data.getPoint(vertexIndex, xyz);
251202
+ halfEdge.setXYZ(xyz);
251203
+ return true;
251204
+ });
251205
+ return graph;
251206
+ }
251053
251207
  /**
251054
251208
  * * Examine adjacent facet orientations throughout the mesh
251055
251209
  * * If possible, reverse a subset to achieve proper pairing.
251056
251210
  * @param mesh
251057
251211
  */
251058
251212
  static reorientVertexOrderAroundFacetsForConsistentOrientation(mesh) {
251059
- return _FacetOrientation__WEBPACK_IMPORTED_MODULE_28__.FacetOrientationFixup.doFixup(mesh);
251213
+ return _FacetOrientation__WEBPACK_IMPORTED_MODULE_29__.FacetOrientationFixup.doFixup(mesh);
251060
251214
  }
251061
251215
  /**
251062
251216
  * Set up indexed normals with one normal in the plane of each facet of the mesh.
251063
251217
  * @param polyface
251064
251218
  */
251065
251219
  static buildPerFaceNormals(polyface) {
251066
- _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_29__.BuildAverageNormalsContext.buildPerFaceNormals(polyface);
251220
+ _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__.BuildAverageNormalsContext.buildPerFaceNormals(polyface);
251067
251221
  }
251068
251222
  /**
251069
251223
  * * At each vertex of the mesh
@@ -251075,8 +251229,21 @@ class PolyfaceQuery {
251075
251229
  * @param polyface polyface to update.
251076
251230
  * @param toleranceAngle averaging is done between normals up to this angle.
251077
251231
  */
251078
- static buildAverageNormals(polyface, toleranceAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_13__.Angle.createDegrees(31.0)) {
251079
- _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_29__.BuildAverageNormalsContext.buildFastAverageNormals(polyface, toleranceAngle);
251232
+ static buildAverageNormals(polyface, toleranceAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(31.0)) {
251233
+ _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__.BuildAverageNormalsContext.buildFastAverageNormals(polyface, toleranceAngle);
251234
+ }
251235
+ /**
251236
+ * Offset the faces of the mesh.
251237
+ * @param source original mesh
251238
+ * @param signedOffsetDistance distance to offset
251239
+ * @param offsetOptions angle options. The default options are recommended.
251240
+ * @returns shifted mesh.
251241
+ */
251242
+ static cloneOffset(source, signedOffsetDistance, offsetOptions = OffsetMeshOptions.create()) {
251243
+ const strokeOptions = _curve_StrokeOptions__WEBPACK_IMPORTED_MODULE_23__.StrokeOptions.createForFacets();
251244
+ const offsetBuilder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create(strokeOptions);
251245
+ _multiclip_OffsetMeshContext__WEBPACK_IMPORTED_MODULE_31__.OffsetMeshContext.buildOffsetMeshWithEdgeChamfers(source, offsetBuilder, signedOffsetDistance, offsetOptions);
251246
+ return offsetBuilder.claimPolyface();
251080
251247
  }
251081
251248
  }
251082
251249
  // amount of computation to do per step of async methods.
@@ -251988,6 +252155,1064 @@ class LinearSearchRange2dArray {
251988
252155
  }
251989
252156
 
251990
252157
 
252158
+ /***/ }),
252159
+
252160
+ /***/ "../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js":
252161
+ /*!***************************************************************************!*\
252162
+ !*** ../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js ***!
252163
+ \***************************************************************************/
252164
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
252165
+
252166
+ "use strict";
252167
+ __webpack_require__.r(__webpack_exports__);
252168
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
252169
+ /* harmony export */ "FacetOffsetProperties": () => (/* binding */ FacetOffsetProperties),
252170
+ /* harmony export */ "OffsetMeshContext": () => (/* binding */ OffsetMeshContext),
252171
+ /* harmony export */ "SectorOffsetProperties": () => (/* binding */ SectorOffsetProperties)
252172
+ /* harmony export */ });
252173
+ /* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
252174
+ /* harmony import */ var _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../geometry3d/GrowableXYZArray */ "../../core/geometry/lib/esm/geometry3d/GrowableXYZArray.js");
252175
+ /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
252176
+ /* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
252177
+ /* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
252178
+ /* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
252179
+ /* harmony import */ var _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphFromIndexedLoopsContext */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js");
252180
+ /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
252181
+ /* harmony import */ var _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../geometry3d/PolylineCompressionByEdgeOffset */ "../../core/geometry/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js");
252182
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
252183
+ /*---------------------------------------------------------------------------------------------
252184
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
252185
+ * See LICENSE.md in the project root for license terms and full copyright notice.
252186
+ *--------------------------------------------------------------------------------------------*/
252187
+ /** @packageDocumentation
252188
+ * @module Polyface
252189
+ */
252190
+
252191
+
252192
+
252193
+
252194
+
252195
+
252196
+
252197
+
252198
+
252199
+
252200
+ function isDefinedAndTrue(value) {
252201
+ if (value === undefined)
252202
+ return false;
252203
+ return value;
252204
+ }
252205
+ class AverageNormalData {
252206
+ constructor() {
252207
+ this.numActiveSectors = 0;
252208
+ this.numInactiveSectors = 0; // exterior and sling.
252209
+ this.averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
252210
+ this.radiansSum = 0.0;
252211
+ this.maxDeviationRadiansFromAverage = 0.0;
252212
+ }
252213
+ clear() {
252214
+ this.numActiveSectors = 0;
252215
+ this.numInactiveSectors = 0; // exterior and sling.
252216
+ this.averageNormal.setZero();
252217
+ this.radiansSum = 0.0;
252218
+ this.maxDeviationRadiansFromAverage = 0.0;
252219
+ }
252220
+ /** Add a normal to the evolving sum, scaled by radians in the corner */
252221
+ accumulateNormal(node, normal, inactiveMask) {
252222
+ if (node.isMaskSet(inactiveMask)) {
252223
+ this.numInactiveSectors++;
252224
+ }
252225
+ else {
252226
+ const sectorSweepRadians = _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.sectorSweepRadiansXYZ(node, normal);
252227
+ this.averageNormal.addScaledInPlace(normal, sectorSweepRadians);
252228
+ this.radiansSum += sectorSweepRadians;
252229
+ this.numActiveSectors++;
252230
+ }
252231
+ }
252232
+ /** normalize the accumulated normals. */
252233
+ finishNormalAveraging() {
252234
+ if (this.numActiveSectors > 0 && this.averageNormal.normalizeInPlace()) {
252235
+ return true;
252236
+ }
252237
+ return false;
252238
+ }
252239
+ /** Compute the deviation from average. update max deviation member */
252240
+ recordDeviation(normal, isActive) {
252241
+ if (isActive) {
252242
+ const radians = this.averageNormal.radiansTo(normal);
252243
+ this.maxDeviationRadiansFromAverage = Math.max(Math.abs(this.maxDeviationRadiansFromAverage), radians);
252244
+ }
252245
+ else {
252246
+ }
252247
+ }
252248
+ /** Return the max deviation as computed on prior calls to recordDeviation */
252249
+ get maxDeviationRadians() { return this.maxDeviationRadiansFromAverage; }
252250
+ }
252251
+ function emitSector(sector) {
252252
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
252253
+ OffsetMeshContext.stringDebugFunction(` Sector xyz ${sector.xyz.x},${sector.xyz.y},${sector.xyz.z} `);
252254
+ OffsetMeshContext.stringDebugFunction(` normal ${sector.normal.x},${sector.normal.y},${sector.normal.z} `);
252255
+ }
252256
+ }
252257
+ // facet properties used during offset.
252258
+ //
252259
+ class FacetOffsetProperties {
252260
+ constructor(facetIndex, normal) {
252261
+ this.facetIndex = facetIndex;
252262
+ this.facetNormal = normal;
252263
+ }
252264
+ }
252265
+ /**
252266
+ * Sector properties during offset.
252267
+ * * this.normal may be initially assigned as the facet normal but can mutate by
252268
+ * averaging with neighbors.
252269
+ * * this.xyz is initially the base mesh xyz but is expected to move along the normal.
252270
+ * * this.count is used locally in computations.
252271
+ */
252272
+ class SectorOffsetProperties {
252273
+ constructor(normal, xyz) {
252274
+ this.xyz = xyz;
252275
+ this.normal = normal;
252276
+ this.count = 0;
252277
+ }
252278
+ /**
252279
+ * Compute the angle between plane normals on opposite sides of the edge.
252280
+ * * parallel normals have zero angle.
252281
+ * * if the edge cuts inward to the volume behind the faces, the angle is negative.
252282
+ * * if the edge is outward (a convex edge) the the volume, the angle is positive.
252283
+ * @param edgeNodeA node on one side of the edge
252284
+ * @param edgeVector pre-allocated vector to receive vector along edge.
252285
+ * @param averageNormal pre-allocated vector to receive the average normal for a chamfer of the offset edge.
252286
+ * @param offsetDistance distance of offset being constructed. The sign of this resolves angle ambiguity.
252287
+ * @param radiansTolerance tolerance for large angle between normals.
252288
+ * @returns true if this edge has SectorOffsetProperties on both sides and the angle between normals angle exceeds radiansTolerance.
252289
+ */
252290
+ static edgeHasLargeExteriorAngleBetweenNormals(edgeNodeA, edgeVector, averageNormal, offsetDistance, radiansTolerance = Math.PI * 0.5) {
252291
+ const propsA = edgeNodeA.edgeTag;
252292
+ const edgeNodeB = edgeNodeA.edgeMate;
252293
+ const propsB = edgeNodeB.edgeTag;
252294
+ if (propsA !== undefined && propsB !== undefined) {
252295
+ edgeNodeA.vectorToFaceSuccessor(edgeVector);
252296
+ const radians = propsA.normal.signedRadiansTo(propsB.normal, edgeVector);
252297
+ if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.split3WaySign(offsetDistance, -1, 1, 1) * radians >= radiansTolerance) {
252298
+ _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.createAdd2Scaled(propsA.normal, 1.0, propsB.normal, 1.0, averageNormal);
252299
+ if (averageNormal.normalizeInPlace())
252300
+ return true;
252301
+ }
252302
+ }
252303
+ return false;
252304
+ }
252305
+ static almostEqualNormals(sectorA, sectorB, radiansTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallAngleRadians) {
252306
+ return sectorA.normal.radiansTo(sectorB.normal) <= radiansTolerance;
252307
+ }
252308
+ static radiansBetweenNormals(sectorA, sectorB) {
252309
+ return sectorA.normal.radiansTo(sectorB.normal);
252310
+ }
252311
+ // Set the offset point this.xyz as sum of the nodeXyz + distance * this.normal
252312
+ setOffsetPointAtDistanceAtHalfEdge(halfEdge, distance) {
252313
+ halfEdge.getPoint3d(this.xyz);
252314
+ this.xyz.addScaledInPlace(this.normal, distance);
252315
+ }
252316
+ // Copy xyz from parameter into (preexisting object) xyz
252317
+ static setXYZAtHalfEdge(halfEdge, xyz) {
252318
+ const props = halfEdge.edgeTag;
252319
+ if (props !== undefined && xyz !== undefined)
252320
+ props.xyz.set(xyz.x, xyz.y, xyz.z);
252321
+ }
252322
+ // Set the offset point this.xyz directly
252323
+ setXYAndZ(xyz) {
252324
+ this.xyz.set(xyz.x, xyz.y, xyz.z);
252325
+ }
252326
+ // Look through the half edge to its properties. Set the normal there. Optionally set xyz from node xyz and offset distance
252327
+ static setNormalAtHalfEdge(halfEdge, uvw, distance) {
252328
+ const props = halfEdge.edgeTag;
252329
+ if (props !== undefined) {
252330
+ props.normal.set(uvw.x, uvw.y, uvw.z);
252331
+ if (distance !== undefined)
252332
+ props.setOffsetPointAtDistanceAtHalfEdge(halfEdge, distance);
252333
+ }
252334
+ }
252335
+ // Look through the half edge and its vertex successor to properties. Get the two normals. Return the angle sweeping from one to the next
252336
+ static sweepRadiansAroundNormal(nodeA, upVector) {
252337
+ const propsA = nodeA.edgeTag;
252338
+ const propsB = nodeA.vertexSuccessor.edgeTag;
252339
+ if (propsA !== undefined && propsB !== undefined) {
252340
+ return propsA.normal.planarRadiansTo(propsB.normal, upVector);
252341
+ }
252342
+ return undefined;
252343
+ }
252344
+ // Look through the half edge to its properties. return (if possible) the coordinates
252345
+ static getSectorPointAtHalfEdge(halfEdge, xyz, xyzArray) {
252346
+ const props = halfEdge.edgeTag;
252347
+ if (props !== undefined) {
252348
+ if (xyz !== undefined)
252349
+ xyz.setFromPoint3d(props.xyz);
252350
+ if (xyzArray !== undefined)
252351
+ xyzArray.push(props.xyz);
252352
+ return true;
252353
+ }
252354
+ return false;
252355
+ }
252356
+ // access the XYZ and push to the array (which makes copies, not reference)
252357
+ // return pointer to the SectorOffsetProperties
252358
+ static pushXYZ(xyzArray, halfEdge) {
252359
+ const sector = halfEdge.edgeTag;
252360
+ if (sector !== undefined)
252361
+ xyzArray.push(sector.xyz);
252362
+ return sector;
252363
+ }
252364
+ // Dereference to execute: accumulatingVector += halfEdge.edgeTag.normal * scale
252365
+ static accumulateScaledNormalAtHalfEdge(halfEdge, scale, accumulatingVector) {
252366
+ const sector = halfEdge.edgeTag;
252367
+ if (sector !== undefined)
252368
+ accumulatingVector.addScaledInPlace(sector.normal, scale);
252369
+ }
252370
+ }
252371
+ /*
252372
+ About Chamfer Edges ..... as constructed in addChamferTopologyToAllEdges
252373
+
252374
+ When edge vertex X to vertex Y has a sharp angle between normals, a "chamfer face" must be created to "fatten" it.
252375
+
252376
+ The original half edges (nodes) for the edge are AX and AY. These are "mates" in the halfEdge mental model. As always,
252377
+ AX is (as needed)
252378
+ (i) the preferred half edge for the left side of the edge moving from X to Y. (i.e. above the edge)
252379
+ (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
252380
+ (iii) a part of the vertex loop around X
252381
+ Likewise, AY is (as needed)
252382
+ (i) the preferred half edge for the left side of the edge moving from Y to X (i.e. below the edge)
252383
+ (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.
252384
+ (iii) a part of the vertex loop around Y
252385
+
252386
+ AX------>
252387
+ X______________________________________________________________________Y
252388
+ <---AY
252389
+
252390
+ When the chamfer face is created, it needs to have a sliver face "inside the edge" -- something in the space here
252391
+
252392
+ AX------>
252393
+ _____________________________________________________________________
252394
+ / \
252395
+ X Y
252396
+ \_____________________________________________________________________/
252397
+ <---AY
252398
+
252399
+ The chamfer face will have a plane normal is the average of the two faces' plane normals.
252400
+
252401
+ The creation sequence for the chamfer face puts a slit "inside the edge" as above HalfEdges AX and AY remain as parts
252402
+ of their respective face loops. In addition, at each end a singleton edge "sling" face is inserted at each
252403
+ end of the sliver face.
252404
+
252405
+ The sequence is:
252406
+
252407
+ STEP 1: splitEdgeCreateSliver creates the sliver face with 2 half edges DX and DY
252408
+ STEP 2: splitEdge (with undefined as the "prior" edge) creates a sling with HalfEdge CX "inside" and BX "outside".
252409
+ (The sling face is not yet attached to X -- briefly floating in space)
252410
+ STEP 3: pinch of HalfEdges BX and DX inserts the sling face "inside" the slit face at the X end.
252411
+
252412
+ 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.
252413
+
252414
+ AX------>
252415
+ _______________________________________________________________
252416
+ / <---DY \
252417
+ / \
252418
+ / BX---> \
252419
+ / _______________ _______________ \
252420
+ | / \ / <----CY \ |
252421
+ |/ \ / \|
252422
+ X | | Y
252423
+ |\ CX---> / \ /|
252424
+ | \_______________/ \_______________/ |
252425
+ \ <---BY /
252426
+ \ /
252427
+ \ DX---> /
252428
+ \ ______________________________________________________________/
252429
+ <---AY
252430
+
252431
+ During the construction, the letters ABCD are used as above, but with prefixes emphasizing their role
252432
+ outsideAX, outsideAY
252433
+ slingB, slingC, sliverD
252434
+
252435
+ The "inside" sling faces (CX and CY) each have their own FacetOffsetProperties and SectorOffsetProperties.
252436
+ The sliver face has its own FacetOffsetProperties which are referenced by DX, BY, DY, BX.
252437
+ Each of those 4 has its own SectorOffSetProperties.
252438
+
252439
+ Important properties during offset construction:
252440
+ 1) the original graph always has original topology and coordinates
252441
+ 2) Each face of the original graph has a FacetOffsetProperties with a representative point and a normal. These are unchanged during the computation.
252442
+ 3) Each node has its own SectorOffsetProperties with a coordinate and normal independent of the parent node.
252443
+ 3.1 The first offset coordinates in each node are directly offset by face normal.
252444
+ 3.2 This creates mismatch across edges and around vertices.
252445
+ 3.3 Various sweeps "around each vertex" try to do intersections among appropriate offset planes to find
252446
+ common coordinates in place of the initial mismatches.
252447
+ 4) The independence of all the sectors allows the offset construction to fix things up in any order it chooses.
252448
+ 5) During the construction, the xyz in SectorOffsetProperties around a single vertex do NOT have to match.
252449
+ 6) At output time, there are three sweeps:
252450
+ 6.1: By face: Go around the face and output a facet with the coordinates in the various sectors.
252451
+ 6.2: By edge: For each edge, if the sector xyz match across both ends output nothing. If not, output a triangle or quad
252452
+ 6.3: By vertex: At each vertex, if all vertex coordinates match output nothing. Otherwise output a facet with all the coordinates.
252453
+ */
252454
+ class OffsetMeshContext {
252455
+ constructor(basePolyface, baseGraph, options) {
252456
+ this._basePolyface = basePolyface;
252457
+ this._baseGraph = baseGraph;
252458
+ this._breakMaskA = baseGraph.grabMask();
252459
+ this._breakMaskB = baseGraph.grabMask();
252460
+ this._insideOfChamferFace = baseGraph.grabMask();
252461
+ this._outsideOfChamferFace = baseGraph.grabMask();
252462
+ this._insideChamferSling = baseGraph.grabMask();
252463
+ this._outsideEndOfChamferFace = baseGraph.grabMask();
252464
+ this._exteriorMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR;
252465
+ this._offsetCoordinatesReassigned = baseGraph.grabMask();
252466
+ this._smoothRadiansBetweenNormals = options.smoothSingleAngleBetweenNormals.radians;
252467
+ this._chamferTurnRadians = options.chamferAngleBetweenNormals.radians;
252468
+ this._smoothAccumulatedRadiansBetweenNormals = options.smoothAccumulatedAngleBetweenNormals.radians;
252469
+ }
252470
+ /** "Exterior" side of a bare edge of the mesh */
252471
+ get exteriorMask() { return this._exteriorMask; }
252472
+ /** "First" sector of a smooth sequence. */
252473
+ get breakMaskA() { return this._breakMaskA; }
252474
+ /** "Last" sector of a smooth sequence. */
252475
+ get breakMaskB() { return this._breakMaskB; }
252476
+ /** This edge is on a chamfered face, and along the original edge */
252477
+ get insideOfChamferFace() { return this._insideOfChamferFace; }
252478
+ /** This is the original edge of a chamfer face */
252479
+ get outsideOfChamferFace() { return this._outsideOfChamferFace; }
252480
+ /** This edge is on a chamfered face, and at the end -- other side may be a sling */
252481
+ get insideChamferSling() { return this._insideChamferSling; }
252482
+ /** This is the outside of the end of a chamfer face -- i.e. the inside of a new face-at-vertex */
252483
+ get outsideEndOfChamferFace() { return this._outsideEndOfChamferFace; }
252484
+ // At each node . .
252485
+ // * Find the sector data
252486
+ // * recompute the sector point using node XYZ and sectorData normal.
252487
+ applyFaceNormalOffsetsToSectorData(distance) {
252488
+ this._baseGraph.announceNodes((_graph, node) => {
252489
+ const sectorData = node.edgeTag;
252490
+ if (sectorData !== undefined) {
252491
+ sectorData.setOffsetPointAtDistanceAtHalfEdge(node, distance);
252492
+ }
252493
+ return true;
252494
+ });
252495
+ }
252496
+ /**
252497
+ * * build a mesh offset by given distance.
252498
+ * * output the mesh to the given builder.
252499
+ * @param basePolyface original mesh
252500
+ * @param builder polyface builder to receive the new mesh.
252501
+ * @param distance signed offset distance.
252502
+ */
252503
+ static buildOffsetMeshWithEdgeChamfers(basePolyface, builder, distance, options) {
252504
+ const baseGraph = this.buildBaseGraph(basePolyface);
252505
+ if (baseGraph !== undefined) {
252506
+ const offsetBuilder = new OffsetMeshContext(basePolyface, baseGraph, options);
252507
+ offsetBuilder.applyFaceNormalOffsetsToSectorData(distance);
252508
+ if (OffsetMeshContext.graphDebugFunction !== undefined)
252509
+ OffsetMeshContext.graphDebugFunction("BaseGraph", baseGraph, offsetBuilder._breakMaskA, offsetBuilder._breakMaskB);
252510
+ const outputSelector = options.outputSelector ? options.outputSelector : {
252511
+ outputOffsetsFromFaces: true,
252512
+ outputOffsetsFromEdges: true,
252513
+ outputOffsetsFromVertices: true,
252514
+ };
252515
+ if (isDefinedAndTrue(outputSelector.outputOffsetsFromFacesBeforeChamfers))
252516
+ offsetBuilder.announceFacetsWithSectorCoordinatesAroundFaces(builder);
252517
+ offsetBuilder.addChamferTopologyToAllEdges(options, distance);
252518
+ offsetBuilder.computeOffsetFacetIntersections(distance);
252519
+ if (OffsetMeshContext.graphDebugFunction !== undefined)
252520
+ OffsetMeshContext.graphDebugFunction("after computeEdgeChamfers", baseGraph, offsetBuilder._breakMaskA, offsetBuilder._breakMaskB);
252521
+ if (isDefinedAndTrue(outputSelector.outputOffsetsFromFaces))
252522
+ offsetBuilder.announceFacetsWithSectorCoordinatesAroundFaces(builder);
252523
+ if (isDefinedAndTrue(outputSelector.outputOffsetsFromEdges))
252524
+ offsetBuilder.announceFacetsWithSectorCoordinatesAroundEdges(builder);
252525
+ if (isDefinedAndTrue(outputSelector.outputOffsetsFromVertices))
252526
+ offsetBuilder.announceFacetsWithSectorCoordinatesAroundVertices(builder);
252527
+ }
252528
+ }
252529
+ /**
252530
+ * For each face of the graph, shift vertices by offsetDistance and emit to the builder as a facet
252531
+ * @param polyfaceBuilder
252532
+ */
252533
+ announceSimpleOffsetFromFaces(polyfaceBuilder, offsetDistance) {
252534
+ const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
252535
+ const xyz = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create(); // reused at each point around each facet.
252536
+ const uvw = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reused once per facet
252537
+ const announceNodeAroundFace = (node) => {
252538
+ node.getPoint3d(xyz);
252539
+ xyz.addInPlace(uvw);
252540
+ xyzLoop.push(xyz);
252541
+ return 0;
252542
+ };
252543
+ this._baseGraph.announceFaceLoops((_graph, seed) => {
252544
+ if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR)) {
252545
+ const facetProperties = seed.faceTag;
252546
+ uvw.setFromVector3d(facetProperties.facetNormal.direction);
252547
+ uvw.scaleInPlace(offsetDistance);
252548
+ xyzLoop.length = 0;
252549
+ seed.sumAroundFace(announceNodeAroundFace);
252550
+ polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
252551
+ }
252552
+ return true;
252553
+ });
252554
+ }
252555
+ /**
252556
+ * For each face of the graph, output the xyz of the sector data
252557
+ * @param polyfaceBuilder
252558
+ */
252559
+ announceFacetsWithSectorCoordinatesAroundFaces(polyfaceBuilder) {
252560
+ const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
252561
+ // For face loop visits .. get the point from the sector data.
252562
+ const announceNodeAroundFace = (node) => {
252563
+ const sectorData = node.edgeTag;
252564
+ if (sectorData !== undefined) {
252565
+ xyzLoop.push(sectorData.xyz);
252566
+ }
252567
+ return 0;
252568
+ };
252569
+ this._baseGraph.announceFaceLoops((_graph, seed) => {
252570
+ if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR)) {
252571
+ xyzLoop.length = 0;
252572
+ seed.sumAroundFace(announceNodeAroundFace);
252573
+ if (xyzLoop.length > 2)
252574
+ polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
252575
+ }
252576
+ return true;
252577
+ });
252578
+ }
252579
+ countBits(mask) {
252580
+ let n = 0;
252581
+ let mask1 = mask;
252582
+ while (mask1 !== 0) {
252583
+ if (mask1 & 0x01)
252584
+ n++;
252585
+ mask1 = mask1 >> 1;
252586
+ }
252587
+ return n;
252588
+ }
252589
+ /**
252590
+ * For each edge of the graph . .
252591
+ * * Collect coordinates in 4 sectors going around the edge
252592
+ * * Compress with tight tolerance so adjacent sectors with clean point match reduce to a single point.
252593
+ * * Emit as a facet.
252594
+ * @param polyfaceBuilder
252595
+ */
252596
+ announceFacetsWithSectorCoordinatesAroundEdges(polyfaceBuilder) {
252597
+ const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
252598
+ const primaryCompressionTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance;
252599
+ const allMasksForEdgesToIgnore = this._exteriorMask
252600
+ | this._outsideEndOfChamferFace
252601
+ | this._outsideOfChamferFace
252602
+ | this._insideOfChamferFace
252603
+ | this._insideChamferSling;
252604
+ this._baseGraph.announceEdges((_graph, nodeA) => {
252605
+ // This starts by looking for EXTERIOR on both sides ...
252606
+ if (nodeA.findMaskAroundEdge(this._exteriorMask) !== undefined) {
252607
+ return true;
252608
+ }
252609
+ else if (!nodeA.isMaskSet(allMasksForEdgesToIgnore)) { // By design, we believe that these two test for allMasksForEdgesToIgnore condition would catch the EXTERIOR case above
252610
+ const nodeB = nodeA.faceSuccessor;
252611
+ const nodeC = nodeA.edgeMate;
252612
+ if (!nodeC.isMaskSet(allMasksForEdgesToIgnore)) {
252613
+ const nodeD = nodeC.faceSuccessor;
252614
+ xyzLoop.clear();
252615
+ SectorOffsetProperties.getSectorPointAtHalfEdge(nodeA, undefined, xyzLoop);
252616
+ SectorOffsetProperties.getSectorPointAtHalfEdge(nodeB, undefined, xyzLoop);
252617
+ SectorOffsetProperties.getSectorPointAtHalfEdge(nodeC, undefined, xyzLoop);
252618
+ SectorOffsetProperties.getSectorPointAtHalfEdge(nodeD, undefined, xyzLoop);
252619
+ _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__.PolylineCompressionContext.compressInPlaceByShortEdgeLength(xyzLoop, primaryCompressionTolerance);
252620
+ if (xyzLoop.length > 2) {
252621
+ polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
252622
+ }
252623
+ }
252624
+ }
252625
+ else {
252626
+ return true;
252627
+ }
252628
+ return true;
252629
+ });
252630
+ }
252631
+ getCoordinateString(node, showXYZ = true, showFaceSuccessorXYZ = false) {
252632
+ if (showXYZ) {
252633
+ if (showFaceSuccessorXYZ) {
252634
+ return `${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node)} ==> ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node.faceSuccessor)}`;
252635
+ }
252636
+ else {
252637
+ return `${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node)}`;
252638
+ }
252639
+ }
252640
+ else {
252641
+ if (showFaceSuccessorXYZ) {
252642
+ return `==> ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node.faceSuccessor)}`;
252643
+ }
252644
+ else {
252645
+ return "";
252646
+ }
252647
+ }
252648
+ }
252649
+ inspectMasks(node, showXYZ = true, showFaceSuccessorXYZ = false) {
252650
+ const s = "[";
252651
+ 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), "]");
252652
+ return v;
252653
+ }
252654
+ /**
252655
+ * For each face of the graph, output the xyz of the sector data
252656
+ * @param polyfaceBuilder
252657
+ */
252658
+ announceFacetsWithSectorCoordinatesAroundVertices(polyfaceBuilder) {
252659
+ const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
252660
+ const primaryCompressionTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance;
252661
+ this._baseGraph.announceVertexLoops((_graph, seed) => {
252662
+ if (!seed.findMaskAroundVertex(this._exteriorMask)) {
252663
+ xyzLoop.length = 0;
252664
+ seed.sumAroundVertex((node) => {
252665
+ if (!node.isMaskSet(this._insideChamferSling))
252666
+ SectorOffsetProperties.getSectorPointAtHalfEdge(node, undefined, xyzLoop);
252667
+ return 0.0;
252668
+ });
252669
+ _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__.PolylineCompressionContext.compressInPlaceByShortEdgeLength(xyzLoop, primaryCompressionTolerance);
252670
+ if (xyzLoop.length > 2) {
252671
+ polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
252672
+ }
252673
+ }
252674
+ return true;
252675
+ });
252676
+ }
252677
+ /**
252678
+ * * Exterior half edges have HalfEdgeMask.EXTERIOR
252679
+ * * All interior half edge around a facet have facetTag pointing to a facetProperties object for that facet.
252680
+ * * the facetOffsetProperties object has the simple facet normal.
252681
+ * * Each half edge has edgeTag pointing to to a sectorOffsetProperties object
252682
+ * * the sectorOffsetProperties has a copy of the facet normal.
252683
+ * @param polyface
252684
+ * @returns graph
252685
+ */
252686
+ static buildBaseGraph(polyface) {
252687
+ const graphBuilder = new _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_5__.HalfEdgeGraphFromIndexedLoopsContext();
252688
+ const visitor = polyface.createVisitor();
252689
+ const xyzA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
252690
+ const xyzB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
252691
+ for (visitor.reset(); visitor.moveToNextFacet();) {
252692
+ const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_6__.PolygonOps.centroidAreaNormal(visitor.point);
252693
+ if (normal !== undefined) {
252694
+ const edgeA = graphBuilder.insertLoop(visitor.pointIndex, (insideHalfEdge) => {
252695
+ const mate = insideHalfEdge.edgeMate;
252696
+ polyface.data.getPoint(insideHalfEdge.i, xyzA);
252697
+ insideHalfEdge.setXYZ(xyzA);
252698
+ polyface.data.getPoint(mate.i, xyzB);
252699
+ mate.setXYZ(xyzB);
252700
+ });
252701
+ const facetProperties = new FacetOffsetProperties(visitor.currentReadIndex(), normal);
252702
+ if (edgeA !== undefined) {
252703
+ edgeA.sumAroundFace((edgeB) => {
252704
+ edgeB.faceTag = facetProperties;
252705
+ edgeB.edgeTag = new SectorOffsetProperties(normal.direction.clone(), edgeB.getPoint3d());
252706
+ return 0;
252707
+ });
252708
+ }
252709
+ }
252710
+ }
252711
+ return graphBuilder.graph;
252712
+ }
252713
+ setOffsetAtDistanceAroundVertex(vertexSeed, distance, ignoreChamfers = false) {
252714
+ vertexSeed.sumAroundVertex((nodeAroundVertex) => {
252715
+ const props = nodeAroundVertex.edgeTag;
252716
+ if (props !== undefined) {
252717
+ if (ignoreChamfers && this.isInsideChamferOrSling(vertexSeed)) {
252718
+ // SKIP !!
252719
+ }
252720
+ else {
252721
+ props.setOffsetPointAtDistanceAtHalfEdge(nodeAroundVertex, distance);
252722
+ }
252723
+ }
252724
+ return 0.0;
252725
+ });
252726
+ }
252727
+ setOffsetXYAndZAroundVertex(vertexSeed, xyz) {
252728
+ vertexSeed.sumAroundVertex((nodeAroundVertex) => {
252729
+ const props = nodeAroundVertex.edgeTag;
252730
+ if (props !== undefined) {
252731
+ props.setXYAndZ(xyz);
252732
+ nodeAroundVertex.setMask(this._offsetCoordinatesReassigned);
252733
+ }
252734
+ return 0.0;
252735
+ });
252736
+ }
252737
+ /**
252738
+ * * start at vertexSeed.
252739
+ * * set the offset point at up to (and including) one with (a) this._breakMaskB or (b) this._exteriorMask
252740
+ * *
252741
+ * @param vertexSeed first node to mark.
252742
+ * @param f function to call to announce each node and its sector properties.
252743
+ * @returns number of nodes marked.
252744
+ */
252745
+ announceNodeAndSectorPropertiesInSmoothSector(vertexSeed, f) {
252746
+ let n = 0;
252747
+ for (let currentNode = vertexSeed;; currentNode = currentNode.vertexSuccessor) {
252748
+ const props = currentNode.edgeTag;
252749
+ if (props !== undefined) {
252750
+ f(currentNode, props);
252751
+ n++;
252752
+ }
252753
+ if (currentNode.isMaskSet(this._breakMaskB))
252754
+ return n;
252755
+ // REMARK: these additional exit conditions should not happen if (a) the graph is properly marked and (b) the start node is not exterior.
252756
+ if (currentNode.isMaskSet(this._exteriorMask))
252757
+ return n;
252758
+ if (currentNode === vertexSeed && n === 0)
252759
+ return n;
252760
+ }
252761
+ }
252762
+ computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data) {
252763
+ data.clear();
252764
+ const inactiveNodeMask = this._exteriorMask | this._insideChamferSling;
252765
+ vertexSeed.sumAroundVertex((node) => {
252766
+ const sectorData = node.edgeTag;
252767
+ if (sectorData)
252768
+ data.accumulateNormal(node, sectorData.normal, inactiveNodeMask);
252769
+ return 0.0;
252770
+ });
252771
+ if (!data.finishNormalAveraging()) {
252772
+ return undefined;
252773
+ }
252774
+ vertexSeed.sumAroundVertex((node) => {
252775
+ const sectorData = node.edgeTag;
252776
+ if (sectorData)
252777
+ data.recordDeviation(sectorData.normal, !node.isMaskSet(inactiveNodeMask));
252778
+ return 0.0;
252779
+ });
252780
+ return data.maxDeviationRadians;
252781
+ }
252782
+ assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedDeviationRadians, data, distance) {
252783
+ const maxDeviationRadians = this.computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data);
252784
+ if (OffsetMeshContext.stringDebugFunction) {
252785
+ OffsetMeshContext.stringDebugFunction(`XYZ ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(vertexSeed)} Average Normal ${data.averageNormal.toJSON()}`);
252786
+ OffsetMeshContext.stringDebugFunction(` angle ratio ${data.radiansSum / (2 * Math.PI)} maxDeviation ${data.maxDeviationRadiansFromAverage}`);
252787
+ }
252788
+ if (maxDeviationRadians !== undefined && maxDeviationRadians <= maxAllowedDeviationRadians) {
252789
+ vertexSeed.sumAroundVertex((node) => {
252790
+ SectorOffsetProperties.setNormalAtHalfEdge(node, data.averageNormal, distance);
252791
+ return 0;
252792
+ });
252793
+ return true;
252794
+ }
252795
+ return false;
252796
+ }
252797
+ /** Search around a vertex for a sector which has a different normal from its vertexPredecessor.
252798
+ * * The seed will be the first candidate considered
252799
+ */
252800
+ markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed) {
252801
+ vertexSeed.clearMaskAroundVertex(this._breakMaskA);
252802
+ vertexSeed.clearMaskAroundVertex(this._breakMaskB);
252803
+ const smoothSingleSmoothRadiansBetweenNormals = this._smoothRadiansBetweenNormals;
252804
+ const accumulatedRadiansBetweenNormals = this._smoothAccumulatedRadiansBetweenNormals;
252805
+ // Step 1: Examine the edge between nodeA and the sector on its vertex predecessor side. This (alone) determines single angle breaks.
252806
+ let numBreaks = 0;
252807
+ let nodeP = vertexSeed;
252808
+ let _numSmooth = 0;
252809
+ do {
252810
+ const nodeQ = nodeP.edgeMate;
252811
+ const nodeR = nodeQ.faceSuccessor; // same as nodeA.vertexPredecessor
252812
+ if (nodeP.isMaskSet(this._exteriorMask)) {
252813
+ if (!nodeQ.isMaskSet(this._exteriorMask)) {
252814
+ nodeR.setMask(this._breakMaskB);
252815
+ numBreaks++;
252816
+ }
252817
+ }
252818
+ else {
252819
+ if (nodeP.isMaskSet(this._outsideOfChamferFace)) {
252820
+ nodeP.setMask(this._breakMaskA);
252821
+ }
252822
+ else if (nodeP.isMaskSet(this._outsideEndOfChamferFace)) {
252823
+ nodeP.setMask(this._breakMaskA);
252824
+ nodeP.setMask(this._breakMaskB);
252825
+ }
252826
+ else if (nodeP.isMaskSet(this._insideChamferSling)) {
252827
+ // This is the sling. It's normal is along edge -- not really a break.
252828
+ }
252829
+ else if (nodeP.isMaskSet(this._insideOfChamferFace)) {
252830
+ nodeP.setMask(this._breakMaskA);
252831
+ nodeP.setMask(this._breakMaskB);
252832
+ nodeR.setMask(this._breakMaskB);
252833
+ }
252834
+ else if (nodeQ.isMaskSet(this._exteriorMask)) {
252835
+ numBreaks++;
252836
+ nodeP.setMask(this._breakMaskA);
252837
+ }
252838
+ else if (!SectorOffsetProperties.almostEqualNormals(nodeP.edgeTag, nodeR.edgeTag, smoothSingleSmoothRadiansBetweenNormals)) {
252839
+ nodeP.setMask(this._breakMaskA);
252840
+ numBreaks++;
252841
+ nodeR.setMask(this._breakMaskB);
252842
+ }
252843
+ else {
252844
+ _numSmooth++;
252845
+ }
252846
+ }
252847
+ nodeP = nodeP.vertexSuccessor;
252848
+ } while (nodeP !== vertexSeed);
252849
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
252850
+ OffsetMeshContext.stringDebugFunction(` numSkip ${_numSmooth} `);
252851
+ if (numBreaks === 0) {
252852
+ // make the first vertex a break so subsequent searches have a place to start
252853
+ vertexSeed.setMask(this._breakMaskA);
252854
+ vertexSeed.vertexPredecessor.setMask(this._breakMaskB);
252855
+ numBreaks = 1;
252856
+ }
252857
+ // Step 2: At each single break, sweep forward to its closing breakB. Insert breaks at accumulated angles.
252858
+ // (minor TODO: for the insertion case, try to split more equally.)
252859
+ const nodeAStart = nodeP.findMaskAroundVertex(this._breakMaskA);
252860
+ if (nodeAStart !== undefined) {
252861
+ nodeP = nodeAStart;
252862
+ do {
252863
+ if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) {
252864
+ let accumulatedRadians = 0.0;
252865
+ do {
252866
+ const nodeB = nodeP.vertexSuccessor;
252867
+ accumulatedRadians += SectorOffsetProperties.radiansBetweenNormals(nodeP.edgeTag, nodeB.edgeTag);
252868
+ if (accumulatedRadians > accumulatedRadiansBetweenNormals) {
252869
+ nodeP.setMask(this._breakMaskB);
252870
+ nodeB.setMask(this._breakMaskA);
252871
+ numBreaks++;
252872
+ accumulatedRadians = 0.0;
252873
+ }
252874
+ nodeP = nodeB;
252875
+ } while (!nodeP.isMaskSet(this._breakMaskB));
252876
+ }
252877
+ else {
252878
+ nodeP = nodeP.vertexSuccessor;
252879
+ }
252880
+ } while (nodeP !== nodeAStart);
252881
+ }
252882
+ if (numBreaks > 0 && nodeAStart !== undefined) {
252883
+ // In each compound sector, accumulate and install average normal.
252884
+ nodeP = nodeAStart;
252885
+ const averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
252886
+ const edgeVectorU = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
252887
+ const edgeVectorV = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
252888
+ averageNormal.setZero();
252889
+ do {
252890
+ if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) {
252891
+ let nodeQ = nodeP;
252892
+ averageNormal.setZero();
252893
+ for (;;) {
252894
+ nodeQ.vectorToFaceSuccessor(edgeVectorU);
252895
+ nodeQ.vectorToFacePredecessor(edgeVectorV);
252896
+ let singleSectorRadians = edgeVectorU.signedRadiansTo(edgeVectorV, nodeQ.faceTag.facetNormal.direction);
252897
+ if (singleSectorRadians < 0.0)
252898
+ singleSectorRadians += Math.PI * 2;
252899
+ SectorOffsetProperties.accumulateScaledNormalAtHalfEdge(nodeQ, singleSectorRadians, averageNormal);
252900
+ if (nodeQ.isMaskSet(this._breakMaskB))
252901
+ break;
252902
+ nodeQ = nodeQ.vertexSuccessor;
252903
+ }
252904
+ if (averageNormal.normalizeInPlace()) {
252905
+ nodeQ = nodeP;
252906
+ for (;;) {
252907
+ SectorOffsetProperties.setNormalAtHalfEdge(nodeQ, averageNormal);
252908
+ if (nodeQ.isMaskSet(this._breakMaskB))
252909
+ break;
252910
+ nodeQ = nodeQ.vertexSuccessor;
252911
+ }
252912
+ }
252913
+ }
252914
+ nodeP = nodeP.vertexSuccessor;
252915
+ } while (nodeP !== nodeAStart);
252916
+ }
252917
+ }
252918
+ /** Compute the point of intersection of the planes in the sectors of 3 half edges */
252919
+ compute3SectorIntersection(nodeA, nodeB, nodeC, result) {
252920
+ const sectorA = nodeA.edgeTag;
252921
+ const sectorB = nodeB.edgeTag;
252922
+ const sectorC = nodeC.edgeTag;
252923
+ const vector = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorC.xyz, sectorC.normal, result);
252924
+ return vector;
252925
+ }
252926
+ /** Compute the point of intersection of the planes in the sectors of 3 half edges */
252927
+ compute3SectorIntersectionDebug(nodeA, nodeB, nodeC, result) {
252928
+ const sectorA = nodeA.edgeTag;
252929
+ const sectorB = nodeB.edgeTag;
252930
+ const sectorC = nodeC.edgeTag;
252931
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
252932
+ OffsetMeshContext.stringDebugFunction(`compute3${this.inspectMasks(nodeA)}${this.inspectMasks(nodeB)}${this.inspectMasks(nodeC)} `);
252933
+ for (const sector of [sectorA, sectorB, sectorC])
252934
+ emitSector(sector);
252935
+ }
252936
+ const vector = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorC.xyz, sectorC.normal, result);
252937
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
252938
+ if (vector === undefined)
252939
+ OffsetMeshContext.stringDebugFunction(" NO INTERSECTION");
252940
+ else
252941
+ OffsetMeshContext.stringDebugFunction(` ComputedVector ${vector.x},${vector.y},${vector.z} `);
252942
+ }
252943
+ return vector;
252944
+ }
252945
+ /** Compute the point of intersection of the planes in the sectors of 2 half edges, using cross product of their normals to resolve */
252946
+ compute2SectorIntersection(nodeA, nodeB, result) {
252947
+ const sectorA = nodeA.edgeTag;
252948
+ const sectorB = nodeB.edgeTag;
252949
+ const normalC = sectorA.normal.crossProduct(sectorB.normal);
252950
+ return _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorB.xyz, normalC, result);
252951
+ }
252952
+ /**
252953
+ * * at input, graph has all original faces and edges
252954
+ * * each sector points to a faceProperties with original facet normal
252955
+ * * at exit:
252956
+ * * new "chamfer faces" are added outside of edges with angle between normal sin excess of options.chamferTurnAngleBetweenNormals
252957
+ * * the original edge is split along its length to create space
252958
+ * * one edge "along" each direction inside the slit.
252959
+ * * a sling edge at each end of the slit.
252960
+ * * outside of the sling is part of the slit face loop.
252961
+ * * inside is a single-node face
252962
+ * * thus the slit itself has 4 nodes.
252963
+ * * the two nodes at each end can thus contain the two distinct points at that end of the chamfer.
252964
+ * * all 4 nodes of the slit face point to a new FacetOffsetProperties with the average normal.
252965
+ * * the inside of each sling face has
252966
+ * * original vertex coordinates in the node
252967
+ * * face properties with a normal pointing outward from that end of the original edge -- hence define a plane that can clip the chamfer
252968
+ * * the two points at each end of the chamfer are computed as the intersection of
252969
+ * * chamfer plane
252970
+ * * sling plane
252971
+ * * adjacent plane of the face on the other side of the edge being chamfered.
252972
+ * @param distance distance to offset. The sign of this is important in the chamfer construction.
252973
+ */
252974
+ addChamferTopologyToAllEdges(options, distance) {
252975
+ const edgesToChamfer = [];
252976
+ const chamferRadians = options.chamferAngleBetweenNormals.radians;
252977
+ const vertexXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create(); // reuse
252978
+ const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
252979
+ const outwardEdgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
252980
+ const averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
252981
+ // collect all the edges with sharp turn angle.
252982
+ this._baseGraph.announceEdges((_graph, edgeNode) => {
252983
+ if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(edgeNode, edgeVector, averageNormal, distance, chamferRadians)) {
252984
+ edgesToChamfer.push(edgeNode);
252985
+ return true;
252986
+ }
252987
+ return true;
252988
+ });
252989
+ // Create sliver faces.
252990
+ // Sliver face gets an average normal from its neighbors.
252991
+ // outsideA is the HalfEdge labeled A in the diagram.
252992
+ // sliverDX and sliverDY are the edges "inside the sliver" at the respective X and Y ends.
252993
+ for (const outsideA of edgesToChamfer) {
252994
+ // remark: this recomputes as in collection round.
252995
+ if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(outsideA, edgeVector, averageNormal, chamferRadians)) {
252996
+ // This copies coordinates and vertex id .... sectorOffsetProperties are delayed until late in the 2-pass loop below.
252997
+ // The returned HalfEdge is labeled D in the diagram
252998
+ const sliverDX = this._baseGraph.splitEdgeCreateSliverFace(outsideA);
252999
+ const sliverDY = sliverDX.facePredecessor;
253000
+ const offsetPoint = sliverDX.getPoint3d();
253001
+ offsetPoint.addScaledInPlace(averageNormal, distance);
253002
+ const ray = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__.Ray3d.createCapture(offsetPoint, averageNormal.clone());
253003
+ const facetProperties = new FacetOffsetProperties(-1, ray);
253004
+ // for each side (hence end) of the sliver face, set mask and install a sling loop for the anticipated end of the chamfer face
253005
+ // new node names in the loop omit X or Y suffix because that is implied by which pass is running.
253006
+ let s = -1.0;
253007
+ for (const sliverD of [sliverDX, sliverDY]) {
253008
+ edgeVector.scale(s, outwardEdgeVector);
253009
+ sliverD.getPoint3d(vertexXYZ);
253010
+ sliverD.setMask(this._insideOfChamferFace);
253011
+ sliverD.edgeMate.setMask(this._outsideOfChamferFace);
253012
+ // mark and reference the chamfer face.
253013
+ sliverD.faceTag = facetProperties;
253014
+ // sling at this end
253015
+ const slingB = this._baseGraph.splitEdge(undefined, vertexXYZ.x, vertexXYZ.y, vertexXYZ.z, sliverD.i);
253016
+ const slingC = slingB.edgeMate;
253017
+ slingB.setMask(this._outsideEndOfChamferFace);
253018
+ slingB.faceTag = facetProperties;
253019
+ slingC.setMask(this._insideChamferSling);
253020
+ _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(sliverD, slingB);
253021
+ const endNormal = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__.Ray3d.create(vertexXYZ, outwardEdgeVector); // clones the inputs
253022
+ const slingFaceProperties = new FacetOffsetProperties(-1, endNormal);
253023
+ slingC.faceTag = slingFaceProperties;
253024
+ // initialize sectors with existing vertex point.
253025
+ sliverD.edgeTag = new SectorOffsetProperties(averageNormal.clone(), offsetPoint.clone());
253026
+ slingB.edgeTag = new SectorOffsetProperties(averageNormal.clone(), offsetPoint.clone());
253027
+ slingC.edgeTag = new SectorOffsetProperties(outwardEdgeVector.clone(), vertexXYZ.clone());
253028
+ // OffsetMeshContext.stringDebugFunction("Chamfer Setup");
253029
+ const chamferPointE = this.compute3SectorIntersection(sliverD, sliverD.edgeMate, slingC);
253030
+ const chamferPointF = this.compute3SectorIntersection(slingB, slingB.vertexSuccessor, slingC);
253031
+ // sliverD.edgeTag = new SectorOffsetProperties(averageNormal.clone(), vertexXYZ.clone());
253032
+ SectorOffsetProperties.setXYZAtHalfEdge(sliverD, chamferPointE);
253033
+ SectorOffsetProperties.setXYZAtHalfEdge(slingB, chamferPointF);
253034
+ s *= -1.0;
253035
+ }
253036
+ }
253037
+ }
253038
+ }
253039
+ /**
253040
+ * * at input:
253041
+ * * Each node points to sectorOffsetProperties with previously computed XYZ (presumably mismatched)
253042
+ * * at exit:
253043
+ * * Each sectorOffsetProperties has an offset point computed with consideration of offset planes in the neighborhood.
253044
+ * @param distance distance to offset.
253045
+ */
253046
+ computeOffsetFacetIntersections(distance) {
253047
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
253048
+ OffsetMeshContext.stringDebugFunction("***** recompute intersections");
253049
+ const breakEdges = [];
253050
+ const vertexXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
253051
+ const chamferXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
253052
+ const maxVertexMove = 2.0 * distance;
253053
+ const averageNormalData = new AverageNormalData();
253054
+ const maxAllowedNormalDeviationRadians = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_9__.Angle.degreesToRadians(25.0);
253055
+ //
253056
+ // FOR EACH VERTEX
253057
+ //
253058
+ this._baseGraph.announceVertexLoops((_graph, vertexSeedA) => {
253059
+ // reposition to an important vertex.
253060
+ // first choice: a chamfer face.
253061
+ let vertexSeed = vertexSeedA.findMaskAroundVertex(this._outsideEndOfChamferFace);
253062
+ if (vertexSeed === undefined)
253063
+ vertexSeed = vertexSeedA.findMaskAroundVertex(this._breakMaskA);
253064
+ if (vertexSeed === undefined)
253065
+ vertexSeed = vertexSeedA;
253066
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
253067
+ OffsetMeshContext.stringDebugFunction("");
253068
+ OffsetMeshContext.stringDebugFunction(` VERTEX LOOP ${vertexSeed.getPoint3d().toJSON()} `);
253069
+ vertexSeed.sumAroundVertex((node) => { OffsetMeshContext.stringDebugFunction(this.inspectMasks(node, false, true)); return 0; });
253070
+ }
253071
+ // Take care of the easiest vertices directly . . . note that this returns from the lambda, not computeOffsetFacetIntersections
253072
+ if (this.assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedNormalDeviationRadians, averageNormalData, distance))
253073
+ return true;
253074
+ this.markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed);
253075
+ this.setOffsetAtDistanceAroundVertex(vertexSeed, distance, true);
253076
+ vertexSeed.collectMaskedEdgesAroundVertex(this._breakMaskA, true, breakEdges);
253077
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
253078
+ OffsetMeshContext.stringDebugFunction(` BREAK EDGES from ${this.inspectMasks(vertexSeed, true, false)}`);
253079
+ for (const node of breakEdges) {
253080
+ OffsetMeshContext.stringDebugFunction(this.inspectMasks(node, false, true));
253081
+ }
253082
+ }
253083
+ if (breakEdges.length <= 1) {
253084
+ // just one smooth sequence.
253085
+ // everything is set already.
253086
+ }
253087
+ else if (breakEdges.length === 2) {
253088
+ // exterior vertex with two incident smooth
253089
+ const vectorFromOrigin = this.compute2SectorIntersection(breakEdges[0], breakEdges[1]);
253090
+ if (vectorFromOrigin !== undefined) {
253091
+ this.setOffsetXYAndZAroundVertex(vertexSeed, vectorFromOrigin);
253092
+ }
253093
+ }
253094
+ else if (breakEdges.length === 3) {
253095
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
253096
+ OffsetMeshContext.stringDebugFunction(` Vertex Update just ${breakEdges.length} `);
253097
+ const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[0], breakEdges[1], breakEdges[2]);
253098
+ if (vectorFromOrigin !== undefined) {
253099
+ this.setOffsetXYAndZAroundVertex(vertexSeed, vectorFromOrigin);
253100
+ }
253101
+ // simple 3-face corner . . .
253102
+ }
253103
+ else {
253104
+ // Lots and Lots of edges
253105
+ // each set of 3 sectors independently generates an offset for its central sector.
253106
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
253107
+ OffsetMeshContext.stringDebugFunction(` Vertex Update breakEdges ${breakEdges.length} `);
253108
+ vertexSeed.getPoint3d(vertexXYZ);
253109
+ // Pass 1 -- look for intersection among multiple chamfers
253110
+ for (let i = 0; i < breakEdges.length; i++) {
253111
+ const i0 = i;
253112
+ const i1 = (i0 + 1) % breakEdges.length;
253113
+ const i2 = (i1 + 1) % breakEdges.length;
253114
+ if (breakEdges[i0].isMaskSet(this._outsideEndOfChamferFace)
253115
+ && breakEdges[i1].isMaskSet(this._outsideOfChamferFace)
253116
+ && breakEdges[i2].isMaskSet(this._insideOfChamferFace)) {
253117
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
253118
+ OffsetMeshContext.stringDebugFunction(` ChamferChamfer Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `);
253119
+ const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]);
253120
+ if (vectorFromOrigin !== undefined) {
253121
+ // Treat all 3 spots as possibly compound sequences
253122
+ for (const iOutput of [i0, i1, i2]) {
253123
+ this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[iOutput], (node, properties) => {
253124
+ properties.setXYAndZ(vectorFromOrigin);
253125
+ node.setMask(this._offsetCoordinatesReassigned);
253126
+ });
253127
+ }
253128
+ // Since all three were reset, skip past. This is done on the acyclic integer that controls the loop.
253129
+ i += 2;
253130
+ }
253131
+ }
253132
+ }
253133
+ // Pass 2 -- look for unassigned nodes just before or after a chamfer.
253134
+ // The chamfer wins
253135
+ for (let i = 0; i < breakEdges.length; i++) {
253136
+ const i0 = i;
253137
+ const i1 = (i0 + 1) % breakEdges.length;
253138
+ if (this.isInsideSling(breakEdges[i0], breakEdges[i1]))
253139
+ continue;
253140
+ if (!this.isOffsetAssigned(breakEdges[i0])
253141
+ && breakEdges[i1].isMaskSet(this.insideOfChamferFace)) {
253142
+ this.transferXYZFromNodeToSmoothSector(breakEdges[i1], breakEdges[i0], "push left from chamfer", chamferXYZ);
253143
+ }
253144
+ else if (!this.isOffsetAssigned(breakEdges[i1])
253145
+ && breakEdges[i0].isMaskSet(this.outsideEndOfChamferFace)) {
253146
+ this.transferXYZFromNodeToSmoothSector(breakEdges[i0], breakEdges[i1], "push right from chamfer", chamferXYZ);
253147
+ }
253148
+ }
253149
+ // Pass 3 -- look for unassigned nodes as middle of 3-face intersections
253150
+ for (let i = 0; i < breakEdges.length; i++) {
253151
+ const i0 = i;
253152
+ const i1 = (i0 + 1) % breakEdges.length;
253153
+ const i2 = (i1 + 1) % breakEdges.length;
253154
+ if (this.isInsideSling(breakEdges[i0], breakEdges[i1], breakEdges[i2]))
253155
+ continue;
253156
+ if (this.isOffsetAssigned(breakEdges[i1]))
253157
+ continue;
253158
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
253159
+ OffsetMeshContext.stringDebugFunction(` Intersection Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `);
253160
+ const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]);
253161
+ if (vectorFromOrigin !== undefined) {
253162
+ if (vertexXYZ.distance(vectorFromOrigin) < maxVertexMove) {
253163
+ this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[i1], (node, properties) => {
253164
+ properties.setXYAndZ(vectorFromOrigin);
253165
+ node.setMask(this._offsetCoordinatesReassigned);
253166
+ });
253167
+ }
253168
+ }
253169
+ }
253170
+ }
253171
+ if (OffsetMeshContext.stringDebugFunction !== undefined) {
253172
+ const n0 = vertexSeed.countMaskAroundVertex(this._offsetCoordinatesReassigned, false);
253173
+ const n1 = vertexSeed.countMaskAroundVertex(this._offsetCoordinatesReassigned, true);
253174
+ const message = ` **** Vertex offset mask counts(TRUE ${n1})(FALSE ${n0})`;
253175
+ OffsetMeshContext.stringDebugFunction(message);
253176
+ }
253177
+ return true;
253178
+ });
253179
+ }
253180
+ // return true if any of these nodes is "inside" the sling at the end of a chamfer.
253181
+ isInsideSling(node0, node1, node2) {
253182
+ return node0.isMaskSet(this._insideChamferSling)
253183
+ || (node1 !== undefined && node1.isMaskSet(this._insideChamferSling))
253184
+ || (node2 !== undefined && node2.isMaskSet(this._insideChamferSling));
253185
+ }
253186
+ // return true if any of these nodes is "inside" the sling at the end of a chamfer.
253187
+ isInsideChamferOrSling(node0) {
253188
+ return node0.isMaskSet(this._insideChamferSling)
253189
+ || node0.isMaskSet(this._insideOfChamferFace)
253190
+ || node0.isMaskSet(this._outsideEndOfChamferFace);
253191
+ }
253192
+ isOffsetAssigned(node0, node1, node2) {
253193
+ return node0.isMaskSet(this._offsetCoordinatesReassigned)
253194
+ || (node1 !== undefined && node1.isMaskSet(this._offsetCoordinatesReassigned))
253195
+ || (node2 !== undefined && node2.isMaskSet(this._offsetCoordinatesReassigned));
253196
+ }
253197
+ /**
253198
+ *
253199
+ * @param sourceNode node with good xyz
253200
+ * @param destinationStartNode first of a sequence of nodes to set (delimited by masks)
253201
+ * @param description string for debug
253202
+ * @param workPoint point to use for coordinate transfer.
253203
+ */
253204
+ transferXYZFromNodeToSmoothSector(sourceNode, destinationStartNode, description, workPoint) {
253205
+ if (OffsetMeshContext.stringDebugFunction !== undefined)
253206
+ OffsetMeshContext.stringDebugFunction(` ${description} ${this.inspectMasks(sourceNode)} to ${this.inspectMasks(destinationStartNode)}} `);
253207
+ SectorOffsetProperties.getSectorPointAtHalfEdge(sourceNode, workPoint, undefined);
253208
+ this.announceNodeAndSectorPropertiesInSmoothSector(destinationStartNode, (node, properties) => {
253209
+ properties.setXYAndZ(workPoint);
253210
+ node.setMask(this._offsetCoordinatesReassigned);
253211
+ });
253212
+ }
253213
+ }
253214
+
253215
+
251991
253216
  /***/ }),
251992
253217
 
251993
253218
  /***/ "../../core/geometry/lib/esm/polyface/multiclip/RangeSearch.js":
@@ -261196,16 +262421,16 @@ class Sample {
261196
262421
  _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)))));
261197
262422
  result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(// 2-pt Interpolation Curve
261198
262423
  _bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
261199
- fitPoints: [pointsA[0], pointsA[1]]
262424
+ fitPoints: [pointsA[0], pointsA[1]],
261200
262425
  })))));
261201
262426
  result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(// 3-pt Interpolation Curve
261202
262427
  _bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
261203
- fitPoints: [pointsA[0], pointsA[1], pointsA[2]]
262428
+ fitPoints: [pointsA[0], pointsA[1], pointsA[2]],
261204
262429
  })))));
261205
262430
  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({
261206
262431
  fitPoints: pointsA,
261207
262432
  startTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(1, -1),
261208
- endTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(-1, -1)
262433
+ endTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(-1, -1),
261209
262434
  })))));
261210
262435
  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"))));
261211
262436
  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)))));
@@ -261319,8 +262544,11 @@ class Sample {
261319
262544
  /** Create swept "solids" that can be capped.
261320
262545
  * * At least one of each solid type.
261321
262546
  * * each is within 10 of the origin all directions.
262547
+ * @param capped true to include caps
262548
+ * @param rotationAngle angle of rotation for the angular sweep. The default is 90 degrees.
262549
+ * Beware that the rotation sweep created with the default or any positive angle produces a mesh with inward normals.
261322
262550
  */
261323
- static createClosedSolidSampler(capped) {
262551
+ static createClosedSolidSampler(capped, rotationAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(90)) {
261324
262552
  const result = [];
261325
262553
  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));
261326
262554
  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));
@@ -261332,18 +262560,23 @@ class Sample {
261332
262560
  const pointQ2 = arcA.fractionAndDistanceToPointOnTangent(1.0, 0.5);
261333
262561
  const pointR1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(point0.x, pointQ1.y);
261334
262562
  const pointR2 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(point0.x, pointQ1.y);
262563
+ const pointR3 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(pointQ1.x - 1, pointQ1.y);
262564
+ const pointR4 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(pointQ1.x - 3, pointQ1.y);
261335
262565
  const linestringQ1 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ1, pointR1, point0);
261336
262566
  const linestringQ2 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ2, pointR2, point0);
262567
+ const linestringQ3 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ2, pointR3, pointR4, point0);
261337
262568
  const contourZ = _curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(linestringQ1.clone());
261338
262569
  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());
261339
262570
  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());
262571
+ 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());
261340
262572
  contourB.tryTransformInPlace(_geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createTranslationXYZ(1, 1, 3));
261341
262573
  // const contourC = contourB.cloneTransformed(Transform.createTranslationXYZ(2, 1, 4))!;
261342
262574
  result.push(_solid_LinearSweep__WEBPACK_IMPORTED_MODULE_30__.LinearSweep.create(contourA, _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(0, 0, 5), capped));
262575
+ result.push(_solid_LinearSweep__WEBPACK_IMPORTED_MODULE_30__.LinearSweep.create(contourC1, _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(0, 0, 5), capped));
261343
262576
  const axis = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_14__.Ray3d.createXYZUVW(0, 8, 0, 1, 0, 0);
261344
- result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourA.clone(), axis.clone(), _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(90), capped));
262577
+ result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourA.clone(), axis.clone(), rotationAngle, capped));
261345
262578
  if (!capped)
261346
- result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourZ.clone(), axis.clone(), _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(90), false));
262579
+ result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourZ.clone(), axis.clone(), rotationAngle, false));
261347
262580
  result.push(_solid_RuledSweep__WEBPACK_IMPORTED_MODULE_36__.RuledSweep.create([contourA.clone(), contourB.clone()], capped));
261348
262581
  const transformC = _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createScaleAboutPoint(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 8), 0.5);
261349
262582
  const contourC = contourB.cloneTransformed(transformC);
@@ -265768,12 +267001,13 @@ __webpack_require__.r(__webpack_exports__);
265768
267001
  /* harmony export */ "HalfEdgeGraph": () => (/* binding */ HalfEdgeGraph),
265769
267002
  /* harmony export */ "HalfEdgeMask": () => (/* binding */ HalfEdgeMask)
265770
267003
  /* harmony export */ });
265771
- /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
267004
+ /* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
265772
267005
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
267006
+ /* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
265773
267007
  /* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
265774
267008
  /* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
265775
- /* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
265776
- /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
267009
+ /* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
267010
+ /* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
265777
267011
  /*---------------------------------------------------------------------------------------------
265778
267012
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
265779
267013
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -265787,6 +267021,7 @@ __webpack_require__.r(__webpack_exports__);
265787
267021
 
265788
267022
 
265789
267023
 
267024
+
265790
267025
  // import { GraphChecker } from "../test/topology/Graph.test";
265791
267026
  /* eslint-disable @typescript-eslint/no-this-alias */
265792
267027
  // cspell:word CONSTU
@@ -265874,6 +267109,7 @@ class HalfEdge {
265874
267109
  this.sortAngle = undefined;
265875
267110
  this.sortData = undefined;
265876
267111
  this.edgeTag = undefined;
267112
+ this.faceTag = undefined;
265877
267113
  // Always created in pairs, init here to make TS compiler and JS runtime happy
265878
267114
  this._facePredecessor = this;
265879
267115
  this._faceSuccessor = this;
@@ -265994,6 +267230,36 @@ class HalfEdge {
265994
267230
  }
265995
267231
  return newA;
265996
267232
  }
267233
+ /**
267234
+ * * Create a new sliver face "inside" an existing edge.
267235
+ * * Insert it "within" the base edge.
267236
+ * * This requires two new half edges.
267237
+ * * if the base is undefined, create a single-edge loop.
267238
+ * * This (unlike pinch) breaks the edgeMate pairing of the base edge.
267239
+ * * This preserves xyz and i properties at all existing vertices.
267240
+ * * The two new half edges are a sliver face (via their predecessor and successor)
267241
+ * * Each new edge mates to one existing edge.
267242
+ * @returns Returns the reference to the half edge created.
267243
+ */
267244
+ static splitEdgeCreateSliverFace(baseA, heArray) {
267245
+ // raw edges ...
267246
+ const newA = new HalfEdge();
267247
+ const newB = new HalfEdge();
267248
+ const baseB = baseA.edgeMate;
267249
+ if (heArray) {
267250
+ heArray.push(newA);
267251
+ heArray.push(newB);
267252
+ }
267253
+ newA._faceSuccessor = newA._facePredecessor = newB;
267254
+ newB._faceSuccessor = newB._facePredecessor = newA;
267255
+ // newA is in vertex loop with baseA etc.
267256
+ // newA mates to baseB
267257
+ HalfEdge.setEdgeMates(newA, baseB);
267258
+ HalfEdge.setEdgeMates(newB, baseA);
267259
+ newA.copyDataFrom(baseA, true, true, false, false);
267260
+ newB.copyDataFrom(baseB, true, true, false, false);
267261
+ return newA;
267262
+ }
265997
267263
  /**
265998
267264
  * Copy "edge based" content of fromNode to toNode
265999
267265
  * * edgeTag
@@ -266204,6 +267470,35 @@ class HalfEdge {
266204
267470
  }
266205
267471
  return count;
266206
267472
  }
267473
+ /** Returns the first node with given mask value around this vertex loop. */
267474
+ findMaskAroundVertex(mask, value = true) {
267475
+ let node = this;
267476
+ do {
267477
+ if (node.isMaskSet(mask) === value)
267478
+ return node;
267479
+ node = node.vertexSuccessor;
267480
+ } while (node !== this);
267481
+ return undefined;
267482
+ }
267483
+ /** Returns the first node with given mask value around this face loop. */
267484
+ findMaskAroundFace(mask, value = true) {
267485
+ let node = this;
267486
+ do {
267487
+ if (node.isMaskSet(mask) === value)
267488
+ return node;
267489
+ node = node.faceSuccessor;
267490
+ } while (node !== this);
267491
+ return undefined;
267492
+ }
267493
+ /** Returns the first node with given mask value on this edge (i.e. examining this and this.mate) */
267494
+ findMaskAroundEdge(mask, value = true) {
267495
+ if (this.isMaskSet(mask) === value)
267496
+ return this;
267497
+ const mate = this.edgeMate;
267498
+ if (mate.isMaskSet(mask) === value)
267499
+ return mate;
267500
+ return undefined;
267501
+ }
266207
267502
  /** Set a mask, and return prior value.
266208
267503
  * @param mask mask to apply
266209
267504
  */
@@ -266221,6 +267516,15 @@ class HalfEdge {
266221
267516
  this.y = node.y;
266222
267517
  this.z = node.z;
266223
267518
  }
267519
+ /**
267520
+ * Set (copy) the this.x, this.y, this.z from xyz.x, xyz.y, xyz.z
267521
+ * @param node source with x,y,z properties
267522
+ */
267523
+ setXYZ(xyz) {
267524
+ this.x = xyz.x;
267525
+ this.y = xyz.y;
267526
+ this.z = xyz.z;
267527
+ }
266224
267528
  /**
266225
267529
  * Test if mask bits are set in the node's bitMask.
266226
267530
  * @return Return true (as a simple boolean, not a mask) if any bits of the mask parameter match bits of the node's bitMask
@@ -266310,6 +267614,10 @@ class HalfEdge {
266310
267614
  const s = `${node.id.toString()}+${HalfEdge.nodeToMaskString(node)}[${node.x},${node.y}]`;
266311
267615
  return s;
266312
267616
  }
267617
+ /** Return the [id, [x,y],z] of a node. Useful for collector methods. */
267618
+ static nodeToIdXYZString(node) {
267619
+ return `[${node.id.toString()}: ${node.x},${node.y},${node.z}]`;
267620
+ }
266313
267621
  /** Create a string representation of the mask
266314
267622
  * * Null mask is empty string.
266315
267623
  * * Appended characters B,P,X for Boundary, Primary, Exterior mask bits.
@@ -266334,7 +267642,13 @@ class HalfEdge {
266334
267642
  }
266335
267643
  /** Return Vector3d to face successor */
266336
267644
  vectorToFaceSuccessor(result) {
266337
- 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);
267645
+ const other = this.faceSuccessor;
267646
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
267647
+ }
267648
+ /** Return Vector3d to face successor */
267649
+ vectorToFacePredecessor(result) {
267650
+ const other = this.facePredecessor;
267651
+ return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
266338
267652
  }
266339
267653
  /** test if spaceNode is in the sector at sectorNode */
266340
267654
  static isNodeVisibleInSector(spaceNode, sectorNode) {
@@ -266458,6 +267772,14 @@ class HalfEdge {
266458
267772
  static testNodeMaskNotExterior(node) { return !node.isMaskSet(HalfEdgeMask.EXTERIOR); }
266459
267773
  /** Returns Returns true if the node does NOT have Mask.EXTERIOR_MASK set. */
266460
267774
  static testMateMaskExterior(node) { return node.edgeMate.isMaskSet(HalfEdgeMask.EXTERIOR); }
267775
+ /** Returns radians between this edge and its face predecessor edge, using all three coordinates x,y,z and given normal to resolve sweep direction.
267776
+ * * The returned angle is positive, i.e. may be larger than PI radians.
267777
+ */
267778
+ static sectorSweepRadiansXYZ(node, normal) {
267779
+ const nodeB = node.faceSuccessor;
267780
+ const nodeC = node.facePredecessor;
267781
+ 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);
267782
+ }
266461
267783
  /** Returns Returns true if the face has positive area in xy parts. */
266462
267784
  static testFacePositiveAreaXY(node) {
266463
267785
  return node.countEdgesAroundFace() > 2 && node.signedFaceArea() > 0.0;
@@ -266489,6 +267811,26 @@ class HalfEdge {
266489
267811
  } while (node !== this);
266490
267812
  return nodes;
266491
267813
  }
267814
+ /**
267815
+ * search around a vertex for nodes that have a specified mask setting.
267816
+ * @param vertexSeed first node to search
267817
+ * @param mask target mask
267818
+ * @param value target value for mask on half edges.
267819
+ * @param collectedNodes optional array to be cleared and receive masked nodes
267820
+ */
267821
+ collectMaskedEdgesAroundVertex(mask, value = true, result) {
267822
+ if (result === undefined)
267823
+ result = [];
267824
+ else
267825
+ result.length = 0;
267826
+ let node = this;
267827
+ do {
267828
+ if (node.isMaskSet(mask) === value)
267829
+ result.push(node);
267830
+ node = node.vertexSuccessor;
267831
+ } while (node !== this);
267832
+ return result;
267833
+ }
266492
267834
  /**
266493
267835
  *
266494
267836
  * * Evaluate f(node) at each outbound node around this node's vertex loop.
@@ -266672,7 +268014,7 @@ class HalfEdge {
266672
268014
  const nodeB1 = nodeB0.faceSuccessor;
266673
268015
  if (!result)
266674
268016
  result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create();
266675
- 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))
268017
+ 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))
266676
268018
  return result;
266677
268019
  return undefined;
266678
268020
  }
@@ -266681,8 +268023,7 @@ class HalfEdge {
266681
268023
  * * If the edge is horizontal with (approximate) identical y, return the node.
266682
268024
  * * If the edge is horizontal with different y, return undefined.
266683
268025
  * * If the edge is not horizontal, return the fractional position (possibly outside 0..1) of the intersection.
266684
- * @param nodeA Base node of edge
266685
- * @param result optional preallocated result
268026
+ * @param node0 Base node of edge
266686
268027
  */
266687
268028
  static horizontalScanFraction(node0, y) {
266688
268029
  const node1 = node0.faceSuccessor;
@@ -266697,8 +268038,7 @@ class HalfEdge {
266697
268038
  * * Compute fractional coordinates of the intersection of a horizontal line with an edge.
266698
268039
  * * If the edge is horizontal return undefined (no test for horizontal at y!!!)
266699
268040
  * * If the edge is not horizontal and y is between its end y's, return the fraction
266700
- * @param nodeA Base node of edge
266701
- * @param result optional preallocated result
268041
+ * @param node0 Base node of edge
266702
268042
  */
266703
268043
  static horizontalScanFraction01(node0, y) {
266704
268044
  const node1 = node0.faceSuccessor;
@@ -266712,6 +268052,31 @@ class HalfEdge {
266712
268052
  return fraction;
266713
268053
  return undefined;
266714
268054
  }
268055
+ /**
268056
+ * Copy various data from source to this.
268057
+ * @param source other half edge.
268058
+ * @param XYZ copy simple coordinates
268059
+ * @param copyVertexData true to copy data belonging to the vertex. (i.e. the "i" member)
268060
+ * @param copyVertexData true to copy data belonging to the edge. (i.e. call transferEdgeData)
268061
+ * @param copyFaceData true to copy faceTag
268062
+ */
268063
+ copyDataFrom(source, copyXYZ, copyVertexData, copyEdgeData, copyFaceData) {
268064
+ if (copyXYZ) {
268065
+ this.x = source.x;
268066
+ this.y = source.y;
268067
+ this.z = source.z;
268068
+ }
268069
+ if (copyVertexData) {
268070
+ this.i = source.i;
268071
+ }
268072
+ if (copyEdgeData) {
268073
+ HalfEdge.transferEdgeProperties(source, this);
268074
+ this.edgeTag = source.edgeTag;
268075
+ }
268076
+ if (copyFaceData) {
268077
+ this.faceTag = source.faceTag;
268078
+ }
268079
+ }
266715
268080
  }
266716
268081
  HalfEdge._edgePropertyMasks = [HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.NULL_FACE];
266717
268082
  HalfEdge._totalNodesCreated = 0;
@@ -266725,7 +268090,7 @@ class HalfEdgeGraph {
266725
268090
  constructor() {
266726
268091
  this._numNodesCreated = 0;
266727
268092
  this.allHalfEdges = [];
266728
- this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_4__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
268093
+ this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_5__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
266729
268094
  }
266730
268095
  /** Ask for a mask (from the graph's free pool.) for caller's use.
266731
268096
  * * Optionally clear the mask throughout the graph.
@@ -266752,6 +268117,19 @@ class HalfEdgeGraph {
266752
268117
  const a = HalfEdge.createHalfEdgePairWithCoordinates(xA, yA, zA, iA, xB, yB, zB, iB, this.allHalfEdges);
266753
268118
  return a;
266754
268119
  }
268120
+ /**
268121
+ * * Create 2 half edges forming 2 vertices, 1 edge, and 1 face
268122
+ * * The two edges are joined as edgeMate pair.
268123
+ * * The two edges are a 2-half-edge face loop in both the faceSuccessor and facePredecessor directions.
268124
+ * * The two edges are added to the graph's HalfEdge set
268125
+ * * Coordinates are set to zero.
268126
+ * * ids are installed in the two half edges.
268127
+ * @returns Return pointer to the first half edge created. (This has idA as its id.)
268128
+ */
268129
+ createEdgeIdId(iA = 0, iB = 0) {
268130
+ const a = HalfEdge.createHalfEdgePairWithCoordinates(0.0, 0.0, 0.0, iA, 0.0, 0.0, 0.0, iB, this.allHalfEdges);
268131
+ return a;
268132
+ }
266755
268133
  /**
266756
268134
  * * create an edge from coordinates x,y,z to (the tail of) an existing half edge.
266757
268135
  * @returns Return pointer to the half edge with tail at x,y,z
@@ -266796,6 +268174,20 @@ class HalfEdgeGraph {
266796
268174
  const he = HalfEdge.splitEdge(base, xA, yA, zA, iA, this.allHalfEdges);
266797
268175
  return he;
266798
268176
  }
268177
+ /**
268178
+ * * Create a sliver face "within" an edge.
268179
+ * * this creates two half edges.
268180
+ * * The existing edges both stay in their same face loops and retain coordinates and i value.
268181
+ * * Each existing edge's mate is a new edge (rather than original mate)
268182
+ * * Coordinates are copied to the new edges at respective vertices.
268183
+ * * New faceTag and edgeTag undefined.
268184
+ * * i members are copied around their respective vertices.
268185
+ * @returns Returns the reference to the half edge created.
268186
+ */
268187
+ splitEdgeCreateSliverFace(base) {
268188
+ const he = HalfEdge.splitEdgeCreateSliverFace(base, this.allHalfEdges);
268189
+ return he;
268190
+ }
266799
268191
  /**
266800
268192
  * * Insert a vertex in the edge beginning at base, with coordinates specified as a fraction along the existing edge.
266801
268193
  * * this creates two half edges.
@@ -266864,7 +268256,7 @@ class HalfEdgeGraph {
266864
268256
  const segments = [];
266865
268257
  for (const node of this.allHalfEdges) {
266866
268258
  if (node.id < node.edgeMate.id)
266867
- 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)));
268259
+ 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)));
266868
268260
  }
266869
268261
  return segments;
266870
268262
  }
@@ -266933,6 +268325,26 @@ class HalfEdgeGraph {
266933
268325
  break;
266934
268326
  }
266935
268327
  }
268328
+ /**
268329
+ * * Visit each edge of the graph once.
268330
+ * * Call the announceEdge function.
268331
+ * * the edge mate will NOT appear in an announceEdge call.
268332
+ * * continue search if announceEdge(graph, node) returns true
268333
+ * * terminate search if announceEdge (graph, node) returns false
268334
+ * @param announceEdge function to apply at one node of each edge.
268335
+ */
268336
+ announceEdges(announceEdge) {
268337
+ this.clearMask(HalfEdgeMask.VISITED);
268338
+ for (const node of this.allHalfEdges) {
268339
+ if (node.getMask(HalfEdgeMask.VISITED))
268340
+ continue;
268341
+ const mate = node.edgeMate;
268342
+ node.setMask(HalfEdgeMask.VISITED);
268343
+ mate.setMask(HalfEdgeMask.VISITED);
268344
+ if (!announceEdge(this, node))
268345
+ break;
268346
+ }
268347
+ }
266936
268348
  /**
266937
268349
  * * Visit each vertex loop of the graph once.
266938
268350
  * * Call the announceVertex function
@@ -266951,8 +268363,8 @@ class HalfEdgeGraph {
266951
268363
  }
266952
268364
  }
266953
268365
  /**
266954
- * * Visit each vertex loop of the graph once.
266955
- * * Call the announceVertex function
268366
+ * * Visit each half edge (node) of the graph once.
268367
+ * * Call the announceNode function
266956
268368
  * * continue search if announceNode(graph, node) returns true
266957
268369
  * * terminate search if announce face (graph, node) returns false
266958
268370
  * @param announceNode function to apply at one node of each face.
@@ -267011,6 +268423,99 @@ class HalfEdgeGraph {
267011
268423
  }
267012
268424
 
267013
268425
 
268426
+ /***/ }),
268427
+
268428
+ /***/ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js":
268429
+ /*!************************************************************************************!*\
268430
+ !*** ../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js ***!
268431
+ \************************************************************************************/
268432
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
268433
+
268434
+ "use strict";
268435
+ __webpack_require__.r(__webpack_exports__);
268436
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
268437
+ /* harmony export */ "HalfEdgeGraphFromIndexedLoopsContext": () => (/* binding */ HalfEdgeGraphFromIndexedLoopsContext)
268438
+ /* harmony export */ });
268439
+ /* harmony import */ var _Graph__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
268440
+ /*---------------------------------------------------------------------------------------------
268441
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
268442
+ * See LICENSE.md in the project root for license terms and full copyright notice.
268443
+ *--------------------------------------------------------------------------------------------*/
268444
+
268445
+ /** @packageDocumentation
268446
+ * @module Topology
268447
+ */
268448
+ /**
268449
+ * Context for building a half edge graph from loops defined only by indices.
268450
+ * * Direct use case:
268451
+ * * Create the context.
268452
+ * * Repeatedly call insertLoop(indicesAroundLoop) to announce various loops.
268453
+ * * Finish by accessing the graph property.
268454
+ * @internal
268455
+ */
268456
+ class HalfEdgeGraphFromIndexedLoopsContext {
268457
+ constructor() {
268458
+ this._unmatchedEdges = new Map();
268459
+ this._graph = new _Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeGraph();
268460
+ this._halfEdgesAroundCurrentLoop = [];
268461
+ }
268462
+ get graph() { return this._graph; }
268463
+ indexPairToString(index0, index1) {
268464
+ return `${index0.toString()},${index1.toString()}`;
268465
+ }
268466
+ /** Create a loop with specified indices at its vertices.
268467
+ * * For an edge with index pair [indexA, indexB]:
268468
+ * * if [indexB, indexA] has never appeared, a HalfEdge mated pair is created.
268469
+ * * One of that mated pair becomes a HalfEdge in this loop.
268470
+ * * The other is "unmatched"
268471
+ * * When announceMatedHalfEdges(halfEdge) is called:
268472
+ * * halfEdge and its mate are "new"
268473
+ * * all coordinates are zeros.
268474
+ * * each contains (as its halfEdge.id property) one index of the [indexA,indexB] pair.
268475
+ * * those coordinates and indices will never be referenced again by this construction sequence -- the caller is free to mutate them as needed.
268476
+ * * if [indexB, indexA] appeared previously (and its outer HalfEdge was left "unmatched"),
268477
+ * the "unmatched" HalfEdge is used in the loop being constructed.
268478
+ * @param indices Array of indices around the edge. This is accessed cyclically.
268479
+ * @param announceMatedHalfEdges optional function to be called as mated pairs are created. At the call,
268480
+ * the given HalfEdge and its mate will have a pair of successive indices from the array.
268481
+ */
268482
+ insertLoop(indices, announceMatedHalfEdges) {
268483
+ const n = indices.length;
268484
+ if (n > 1) {
268485
+ let index0 = indices[indices.length - 1];
268486
+ this._halfEdgesAroundCurrentLoop.length = 0;
268487
+ for (const index1 of indices) {
268488
+ const insideString = this.indexPairToString(index0, index1);
268489
+ const halfEdgePreviouslyConstructedFromOppositeSide = this._unmatchedEdges.get(insideString);
268490
+ if (halfEdgePreviouslyConstructedFromOppositeSide === undefined) {
268491
+ // This is the first appearance of this edge in either direction.
268492
+ const outsideString = this.indexPairToString(index1, index0); // string referencing the "other" side of the new edge.
268493
+ const newHalfEdgeAroundLoop = this._graph.createEdgeIdId(index0, index1);
268494
+ if (announceMatedHalfEdges !== undefined)
268495
+ announceMatedHalfEdges(newHalfEdgeAroundLoop);
268496
+ this._unmatchedEdges.set(outsideString, newHalfEdgeAroundLoop.edgeMate);
268497
+ this._halfEdgesAroundCurrentLoop.push(newHalfEdgeAroundLoop);
268498
+ newHalfEdgeAroundLoop.edgeMate.setMask(_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeMask.EXTERIOR);
268499
+ }
268500
+ else {
268501
+ this._halfEdgesAroundCurrentLoop.push(halfEdgePreviouslyConstructedFromOppositeSide);
268502
+ halfEdgePreviouslyConstructedFromOppositeSide.clearMask(_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeMask.EXTERIOR);
268503
+ }
268504
+ index0 = index1;
268505
+ }
268506
+ let halfEdgeA = this._halfEdgesAroundCurrentLoop[this._halfEdgesAroundCurrentLoop.length - 1];
268507
+ for (const halfEdgeB of this._halfEdgesAroundCurrentLoop) {
268508
+ const halfEdgeC = halfEdgeA.faceSuccessor;
268509
+ _Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdge.pinch(halfEdgeB, halfEdgeC);
268510
+ halfEdgeA = halfEdgeB;
268511
+ }
268512
+ return this._halfEdgesAroundCurrentLoop[0];
268513
+ }
268514
+ return undefined;
268515
+ }
268516
+ }
268517
+
268518
+
267014
268519
  /***/ }),
267015
268520
 
267016
268521
  /***/ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js":
@@ -301943,7 +303448,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
301943
303448
  /***/ ((module) => {
301944
303449
 
301945
303450
  "use strict";
301946
- module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.0.0-dev.6","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.6","@itwin/core-bentley":"workspace:^4.0.0-dev.6","@itwin/core-common":"workspace:^4.0.0-dev.6","@itwin/core-geometry":"workspace:^4.0.0-dev.6","@itwin/core-orbitgt":"workspace:^4.0.0-dev.6","@itwin/core-quantity":"workspace:^4.0.0-dev.6"},"//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"}}]}}');
303451
+ 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"}}]}}');
301947
303452
 
301948
303453
  /***/ })
301949
303454