@itwin/rpcinterface-full-stack-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.
- package/lib/dist/_07c5.bundled-tests.js.map +1 -1
- package/lib/dist/bundled-tests.js +1643 -138
- package/lib/dist/bundled-tests.js.map +1 -1
- package/lib/dist/core_frontend_lib_esm_ApproximateTerrainHeightsProps_js.bundled-tests.js.map +1 -1
- package/lib/dist/object-storage.bundled-tests.js.map +1 -1
- package/lib/dist/vendors-common_temp_node_modules_pnpm_itwin_object-storage-azure_1_4_0_node_modules_itwin_obj-3576c6.bundled-tests.js.map +1 -1
- package/lib/dist/vendors-common_temp_node_modules_pnpm_loaders_gl_draco_3_2_13_node_modules_loaders_gl_draco_d-e0d984.bundled-tests.js.map +1 -1
- package/lib/dist/vendors-common_temp_node_modules_pnpm_reflect-metadata_0_1_13_node_modules_reflect-metadata_R-610cb3.bundled-tests.js.map +1 -1
- package/package.json +14 -14
|
@@ -194261,6 +194261,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
194261
194261
|
/* harmony export */ "NewtonEvaluatorRtoRD": () => (/* reexport safe */ _numerics_Newton__WEBPACK_IMPORTED_MODULE_51__.NewtonEvaluatorRtoRD),
|
|
194262
194262
|
/* harmony export */ "NullGeometryHandler": () => (/* reexport safe */ _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_8__.NullGeometryHandler),
|
|
194263
194263
|
/* harmony export */ "NumberArray": () => (/* reexport safe */ _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_23__.NumberArray),
|
|
194264
|
+
/* harmony export */ "OffsetMeshOptions": () => (/* reexport safe */ _polyface_PolyfaceQuery__WEBPACK_IMPORTED_MODULE_116__.OffsetMeshOptions),
|
|
194264
194265
|
/* harmony export */ "OffsetOptions": () => (/* reexport safe */ _curve_internalContexts_PolygonOffsetContext__WEBPACK_IMPORTED_MODULE_79__.OffsetOptions),
|
|
194265
194266
|
/* harmony export */ "Order2Bezier": () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_49__.Order2Bezier),
|
|
194266
194267
|
/* harmony export */ "Order3Bezier": () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_49__.Order3Bezier),
|
|
@@ -212656,6 +212657,44 @@ class Angle {
|
|
|
212656
212657
|
const uDotV = ux * vx + uy * vy + uz * vz;
|
|
212657
212658
|
return Math.atan2(_Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.crossProductMagnitude(ux, uy, uz, vx, vy, vz), uDotV);
|
|
212658
212659
|
}
|
|
212660
|
+
/**
|
|
212661
|
+
* * Returns the angle between two vectors, with the vectors given as xyz components, and an up vector to resolve angle to a full 2PI range.
|
|
212662
|
+
* * The returned angle is (-PI < radians <= PI) or (0 <= radians < 2 * PI)
|
|
212663
|
+
* * The angle is in the plane of the U and V vectors.
|
|
212664
|
+
* * The upVector determines a positive side of the plane but need not be strictly perpendicular to the plane.
|
|
212665
|
+
*
|
|
212666
|
+
* @param ux x component of vector u
|
|
212667
|
+
* @param uy y component of vector u
|
|
212668
|
+
* @param uz z component of vector u
|
|
212669
|
+
* @param vx x component of vector v
|
|
212670
|
+
* @param vy y component of vector v
|
|
212671
|
+
* @param vz z component of vector v
|
|
212672
|
+
* @param upVectorX x component of vector to positive side of plane.
|
|
212673
|
+
* @param upVectorY y component of vector to positive side of plane.
|
|
212674
|
+
* @param upVectorZ z component of vector to positive side of plane.
|
|
212675
|
+
* @param adjustToAllPositive if true, return strictly non-negative sweep (0 <= radians < 2*PI). If false, return signed (-PI < radians <= PI)
|
|
212676
|
+
*/
|
|
212677
|
+
static orientedRadiansBetweenVectorsXYZ(ux, uy, uz, vx, vy, vz, upVectorX, upVectorY, upVectorZ, adjustToPositive = false) {
|
|
212678
|
+
const uDotV = ux * vx + uy * vy + uz * vz;
|
|
212679
|
+
const wx = uy * vz - uz * vy;
|
|
212680
|
+
const wy = uz * vx - ux * vz;
|
|
212681
|
+
const wz = ux * vy - uy * vx;
|
|
212682
|
+
const upDotW = upVectorX * wx + upVectorY * wy + upVectorZ * wz;
|
|
212683
|
+
const crossMagnitude = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.hypotenuseXYZ(wx, wy, wz);
|
|
212684
|
+
if (upDotW < 0.0) {
|
|
212685
|
+
if (adjustToPositive) {
|
|
212686
|
+
// The turn is greater than 180 degrees. Take a peculiarly oriented atan2 to get the excess-180 part as addition to PI.
|
|
212687
|
+
// This gives the smoothest numerical transition passing PI.
|
|
212688
|
+
return Math.PI + Math.atan2(crossMagnitude, -uDotV);
|
|
212689
|
+
}
|
|
212690
|
+
else {
|
|
212691
|
+
return -Math.atan2(crossMagnitude, uDotV);
|
|
212692
|
+
}
|
|
212693
|
+
}
|
|
212694
|
+
else {
|
|
212695
|
+
return Math.atan2(crossMagnitude, uDotV);
|
|
212696
|
+
}
|
|
212697
|
+
}
|
|
212659
212698
|
/**
|
|
212660
212699
|
* Add a multiple of a full circle angle (360 degrees, 2PI) in place.
|
|
212661
212700
|
* @param multiple multiplier factor
|
|
@@ -222356,9 +222395,12 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
222356
222395
|
* @module CartesianGeometry
|
|
222357
222396
|
*/
|
|
222358
222397
|
// cspell:word CWXY
|
|
222398
|
+
// cspell:word arctan
|
|
222399
|
+
// cspell:word Rodrigues
|
|
222359
222400
|
|
|
222360
222401
|
|
|
222361
222402
|
|
|
222403
|
+
// cspell:word CCWXY
|
|
222362
222404
|
/**
|
|
222363
222405
|
* * `XYZ` is a minimal object containing x,y,z and operations that are meaningful without change in both point and vector.
|
|
222364
222406
|
* * `XYZ` is not instantiable.
|
|
@@ -223701,18 +223743,17 @@ class Vector3d extends XYZ {
|
|
|
223701
223743
|
else
|
|
223702
223744
|
return theta;
|
|
223703
223745
|
}
|
|
223704
|
-
/**
|
|
223705
|
-
|
|
223706
|
-
|
|
223707
|
-
|
|
223708
|
-
|
|
223709
|
-
|
|
223710
|
-
|
|
223711
|
-
|
|
223712
|
-
|
|
223713
|
-
|
|
223714
|
-
|
|
223715
|
-
*/
|
|
223746
|
+
/** Return the (strongly typed Angle) angle from this vector to vectorB, measured in the plane containing both,
|
|
223747
|
+
* with vectorW indicating which side to view to control sign of the angle.
|
|
223748
|
+
* * The returned angle can range from negative 180 degrees (negative PI radians) to positive 180 degrees
|
|
223749
|
+
* * (positive PI radians), not closed on the negative side.
|
|
223750
|
+
* * The returned angle is "in the plane containing the two vectors"
|
|
223751
|
+
* * `vectorW` distinguishes between the sides of the plane, but does not have to be perpendicular.
|
|
223752
|
+
* * The returned angle has the same sign as vectorW dot product (thisVector cross vectorB)
|
|
223753
|
+
* * Use planarRadiansTo to measure the angle between vectors that are projected to another plane.
|
|
223754
|
+
* @param vectorB target vector.
|
|
223755
|
+
* @param vectorW distinguishes between the sides of the plane.
|
|
223756
|
+
*/
|
|
223716
223757
|
signedAngleTo(vectorB, vectorW) {
|
|
223717
223758
|
return _Angle__WEBPACK_IMPORTED_MODULE_2__.Angle.createRadians(this.signedRadiansTo(vectorB, vectorW));
|
|
223718
223759
|
}
|
|
@@ -236449,6 +236490,20 @@ class SmallSystem {
|
|
|
236449
236490
|
}
|
|
236450
236491
|
return undefined;
|
|
236451
236492
|
}
|
|
236493
|
+
/**
|
|
236494
|
+
* Compute the intersection of three planes.
|
|
236495
|
+
* @param xyzA point on the first plane
|
|
236496
|
+
* @param normalA normal of the first plane
|
|
236497
|
+
* @param xyzB point on the second plane
|
|
236498
|
+
* @param normalB normal of the second plane
|
|
236499
|
+
* @param xyzC point on the third plane
|
|
236500
|
+
* @param normalC normal of the third plane
|
|
236501
|
+
* @param result optional result
|
|
236502
|
+
* @returns intersection point of the three planes (as a Vector3d), or undefined if at least two planes are parallel.
|
|
236503
|
+
*/
|
|
236504
|
+
static intersect3Planes(xyzA, normalA, xyzB, normalB, xyzC, normalC, result) {
|
|
236505
|
+
return this.linearSystem3d(normalA.x, normalA.y, normalA.z, normalB.x, normalB.y, normalB.z, normalC.x, normalC.y, normalC.z, _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzA.x, xyzA.y, xyzA.z, normalA.x, normalA.y, normalA.z), _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzB.x, xyzB.y, xyzB.z, normalB.x, normalB.y, normalB.z), _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzC.x, xyzC.y, xyzC.z, normalC.x, normalC.y, normalC.z), result);
|
|
236506
|
+
}
|
|
236452
236507
|
/**
|
|
236453
236508
|
* * in rowB, replace `rowB[j] += a * rowB[pivot] * rowA[j] / rowA[pivot]` for `j>pivot`
|
|
236454
236509
|
* @param rowA row that does not change
|
|
@@ -240560,10 +240615,29 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
|
|
|
240560
240615
|
if (sector.uv)
|
|
240561
240616
|
sector.uvIndex = this._polyface.addParam(sector.uv);
|
|
240562
240617
|
}
|
|
240618
|
+
addSectorTriangle(sectorA0, sectorA1, sectorA2) {
|
|
240619
|
+
if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz)
|
|
240620
|
+
|| sectorA1.xyz.isAlmostEqual(sectorA2.xyz)
|
|
240621
|
+
|| sectorA2.xyz.isAlmostEqual(sectorA0.xyz)) {
|
|
240622
|
+
// trivially degenerate triangle !!! skip !!!
|
|
240623
|
+
}
|
|
240624
|
+
else {
|
|
240625
|
+
if (this._options.needNormals)
|
|
240626
|
+
this.addIndexedTriangleNormalIndexes(sectorA0.normalIndex, sectorA1.normalIndex, sectorA2.normalIndex);
|
|
240627
|
+
if (this._options.needParams)
|
|
240628
|
+
this.addIndexedTriangleParamIndexes(sectorA0.uvIndex, sectorA1.uvIndex, sectorA2.uvIndex);
|
|
240629
|
+
this.addIndexedTrianglePointIndexes(sectorA0.xyzIndex, sectorA1.xyzIndex, sectorA2.xyzIndex);
|
|
240630
|
+
this._polyface.terminateFacet();
|
|
240631
|
+
}
|
|
240632
|
+
}
|
|
240563
240633
|
addSectorQuadA01B01(sectorA0, sectorA1, sectorB0, sectorB1) {
|
|
240564
240634
|
if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz) && sectorB0.xyz.isAlmostEqual(sectorB1.xyz)) {
|
|
240565
240635
|
// ignore null quad !!
|
|
240566
240636
|
}
|
|
240637
|
+
else if (this._options.shouldTriangulate) {
|
|
240638
|
+
this.addSectorTriangle(sectorA0, sectorA1, sectorB1);
|
|
240639
|
+
this.addSectorTriangle(sectorB1, sectorB0, sectorA0);
|
|
240640
|
+
}
|
|
240567
240641
|
else {
|
|
240568
240642
|
if (this._options.needNormals)
|
|
240569
240643
|
this.addIndexedQuadNormalIndexes(sectorA0.normalIndex, sectorA1.normalIndex, sectorB0.normalIndex, sectorB1.normalIndex);
|
|
@@ -240640,12 +240714,30 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
|
|
|
240640
240714
|
}
|
|
240641
240715
|
const numPoints = pointA.length;
|
|
240642
240716
|
for (let i = 1; i < numPoints; i++) {
|
|
240643
|
-
if (
|
|
240644
|
-
|
|
240645
|
-
|
|
240646
|
-
|
|
240647
|
-
|
|
240648
|
-
|
|
240717
|
+
if (this.options.shouldTriangulate) {
|
|
240718
|
+
if (distinctIndices(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i))) {
|
|
240719
|
+
this.addIndexedTrianglePointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i));
|
|
240720
|
+
if (normalA && normalB)
|
|
240721
|
+
this.addIndexedTriangleNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1));
|
|
240722
|
+
if (paramA && paramB)
|
|
240723
|
+
this.addIndexedTriangleParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1));
|
|
240724
|
+
}
|
|
240725
|
+
if (distinctIndices(pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i - 1))) {
|
|
240726
|
+
this.addIndexedTrianglePointIndexes(pointA.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1));
|
|
240727
|
+
if (normalA && normalB)
|
|
240728
|
+
this.addIndexedTriangleNormalIndexes(normalA.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1));
|
|
240729
|
+
if (paramA && paramB)
|
|
240730
|
+
this.addIndexedTriangleParamIndexes(paramA.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1));
|
|
240731
|
+
}
|
|
240732
|
+
}
|
|
240733
|
+
else {
|
|
240734
|
+
if (pointA.atUncheckedIndex(i - 1) !== pointA.atUncheckedIndex(i) || pointB.atUncheckedIndex(i - 1) !== pointB.atUncheckedIndex(i)) {
|
|
240735
|
+
this.addIndexedQuadPointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i));
|
|
240736
|
+
if (normalA && normalB)
|
|
240737
|
+
this.addIndexedQuadNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i));
|
|
240738
|
+
if (paramA && paramB)
|
|
240739
|
+
this.addIndexedQuadParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i));
|
|
240740
|
+
}
|
|
240649
240741
|
this._polyface.terminateFacet();
|
|
240650
240742
|
}
|
|
240651
240743
|
}
|
|
@@ -241642,6 +241734,9 @@ function resolveToIndexedXYZCollectionOrCarrier(points) {
|
|
|
241642
241734
|
return points.packedPoints;
|
|
241643
241735
|
return points;
|
|
241644
241736
|
}
|
|
241737
|
+
function distinctIndices(i0, i1, i2) {
|
|
241738
|
+
return i0 !== i1 && i1 !== i2 && i2 !== i0;
|
|
241739
|
+
}
|
|
241645
241740
|
|
|
241646
241741
|
|
|
241647
241742
|
/***/ }),
|
|
@@ -242810,38 +242905,41 @@ function compressUnusedGrowableXYZArray(data: GrowableXYZArray, indices: number[
|
|
|
242810
242905
|
__webpack_require__.r(__webpack_exports__);
|
|
242811
242906
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
242812
242907
|
/* harmony export */ "DuplicateFacetClusterSelector": () => (/* binding */ DuplicateFacetClusterSelector),
|
|
242908
|
+
/* harmony export */ "OffsetMeshOptions": () => (/* binding */ OffsetMeshOptions),
|
|
242813
242909
|
/* harmony export */ "PolyfaceQuery": () => (/* binding */ PolyfaceQuery)
|
|
242814
242910
|
/* harmony export */ });
|
|
242815
242911
|
/* harmony import */ var _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../geometry3d/PointHelpers */ "../../core/geometry/lib/esm/geometry3d/PointHelpers.js");
|
|
242816
|
-
/* harmony import */ var
|
|
242912
|
+
/* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
|
|
242817
242913
|
/* harmony import */ var _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../curve/internalContexts/MultiChainCollector */ "../../core/geometry/lib/esm/curve/internalContexts/MultiChainCollector.js");
|
|
242818
|
-
/* harmony import */ var
|
|
242819
|
-
/* harmony import */ var
|
|
242820
|
-
/* harmony import */ var
|
|
242914
|
+
/* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
|
|
242915
|
+
/* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
|
|
242916
|
+
/* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
|
|
242821
242917
|
/* harmony import */ var _curve_StrokeOptions__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../curve/StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
|
|
242822
|
-
/* harmony import */ var
|
|
242823
|
-
/* harmony import */ var
|
|
242918
|
+
/* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
|
|
242919
|
+
/* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
|
|
242824
242920
|
/* harmony import */ var _geometry3d_FrameBuilder__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../geometry3d/FrameBuilder */ "../../core/geometry/lib/esm/geometry3d/FrameBuilder.js");
|
|
242825
|
-
/* harmony import */ var
|
|
242826
|
-
/* harmony import */ var
|
|
242921
|
+
/* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
|
|
242922
|
+
/* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
|
|
242827
242923
|
/* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
|
|
242828
|
-
/* harmony import */ var
|
|
242829
|
-
/* harmony import */ var
|
|
242830
|
-
/* harmony import */ var
|
|
242924
|
+
/* harmony import */ var _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../geometry4d/Matrix4d */ "../../core/geometry/lib/esm/geometry4d/Matrix4d.js");
|
|
242925
|
+
/* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
|
|
242926
|
+
/* harmony import */ var _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../numerics/UnionFind */ "../../core/geometry/lib/esm/numerics/UnionFind.js");
|
|
242831
242927
|
/* harmony import */ var _topology_ChainMerge__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../topology/ChainMerge */ "../../core/geometry/lib/esm/topology/ChainMerge.js");
|
|
242832
242928
|
/* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
|
|
242833
242929
|
/* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
|
|
242834
242930
|
/* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
|
|
242835
|
-
/* harmony import */ var
|
|
242836
|
-
/* harmony import */ var
|
|
242931
|
+
/* harmony import */ var _FacetOrientation__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./FacetOrientation */ "../../core/geometry/lib/esm/polyface/FacetOrientation.js");
|
|
242932
|
+
/* harmony import */ var _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./IndexedEdgeMatcher */ "../../core/geometry/lib/esm/polyface/IndexedEdgeMatcher.js");
|
|
242837
242933
|
/* harmony import */ var _IndexedPolyfaceVisitor__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./IndexedPolyfaceVisitor */ "../../core/geometry/lib/esm/polyface/IndexedPolyfaceVisitor.js");
|
|
242838
|
-
/* harmony import */ var
|
|
242839
|
-
/* harmony import */ var
|
|
242934
|
+
/* harmony import */ var _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./multiclip/BuildAverageNormalsContext */ "../../core/geometry/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js");
|
|
242935
|
+
/* harmony import */ var _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./multiclip/SweepLineStringToFacetContext */ "../../core/geometry/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js");
|
|
242840
242936
|
/* harmony import */ var _multiclip_XYPointBuckets__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./multiclip/XYPointBuckets */ "../../core/geometry/lib/esm/polyface/multiclip/XYPointBuckets.js");
|
|
242841
|
-
/* harmony import */ var
|
|
242937
|
+
/* harmony import */ var _Polyface__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Polyface */ "../../core/geometry/lib/esm/polyface/Polyface.js");
|
|
242842
242938
|
/* harmony import */ var _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./PolyfaceBuilder */ "../../core/geometry/lib/esm/polyface/PolyfaceBuilder.js");
|
|
242843
242939
|
/* harmony import */ var _RangeLengthData__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./RangeLengthData */ "../../core/geometry/lib/esm/polyface/RangeLengthData.js");
|
|
242844
242940
|
/* harmony import */ var _topology_SpaceTriangulation__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../topology/SpaceTriangulation */ "../../core/geometry/lib/esm/topology/SpaceTriangulation.js");
|
|
242941
|
+
/* harmony import */ var _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../topology/HalfEdgeGraphFromIndexedLoopsContext */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js");
|
|
242942
|
+
/* harmony import */ var _multiclip_OffsetMeshContext__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./multiclip/OffsetMeshContext */ "../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js");
|
|
242845
242943
|
/*---------------------------------------------------------------------------------------------
|
|
242846
242944
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
242847
242945
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
@@ -242881,6 +242979,41 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
242881
242979
|
|
|
242882
242980
|
|
|
242883
242981
|
|
|
242982
|
+
|
|
242983
|
+
|
|
242984
|
+
/**
|
|
242985
|
+
* Options carrier for [[PolyfaceQuery.cloneOffset]].
|
|
242986
|
+
* * Default options are strongly recommended.
|
|
242987
|
+
* * The option most likely to be changed is chamferTurnAngle
|
|
242988
|
+
* @public
|
|
242989
|
+
*/
|
|
242990
|
+
class OffsetMeshOptions {
|
|
242991
|
+
/** Constructor -- CAPTURE parameters ... */
|
|
242992
|
+
constructor(smoothSingleAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(25), smoothAccumulatedAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(60), chamferTurnAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(90)) {
|
|
242993
|
+
this.smoothSingleAngleBetweenNormals = smoothSingleAngleBetweenNormals.clone();
|
|
242994
|
+
this.smoothAccumulatedAngleBetweenNormals = smoothAccumulatedAngleBetweenNormals.clone();
|
|
242995
|
+
this.chamferAngleBetweenNormals = chamferTurnAngle.clone();
|
|
242996
|
+
}
|
|
242997
|
+
/** construct and return an OffsetMeshOptions with given parameters.
|
|
242998
|
+
* * Angles are forced to minimum values.
|
|
242999
|
+
* * Clones of the angles are given to the constructor.
|
|
243000
|
+
* @param smoothSingleRadiansBetweenNormals an angle larger than this (between facets) is considered a sharp edge
|
|
243001
|
+
* @param smoothAccumulatedAngleBetweenNormals angles that sum to this much may be consolidated for average normal
|
|
243002
|
+
* @param chamferTurnAngleBetweenNormals when facets meet with larger angle, a chamfer edge may be added if the angle between facet normals is larger than this.
|
|
243003
|
+
*/
|
|
243004
|
+
static create(smoothSingleAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(25), smoothAccumulatedAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(60), chamferTurnAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(120)) {
|
|
243005
|
+
const mySmoothSingleRadiansBetweenNormals = smoothSingleAngleBetweenNormals.clone();
|
|
243006
|
+
const mySmoothAccumulatedRadiansBetweenNormals = smoothAccumulatedAngleBetweenNormals.clone();
|
|
243007
|
+
const myChamferTurnAngleBetweenNormals = chamferTurnAngleBetweenNormals.clone();
|
|
243008
|
+
if (mySmoothSingleRadiansBetweenNormals.degrees < 1)
|
|
243009
|
+
mySmoothAccumulatedRadiansBetweenNormals.setDegrees(1.0);
|
|
243010
|
+
if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 1.0)
|
|
243011
|
+
mySmoothAccumulatedRadiansBetweenNormals.setDegrees(1.0);
|
|
243012
|
+
if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 15.0)
|
|
243013
|
+
mySmoothAccumulatedRadiansBetweenNormals.setDegrees(15.0);
|
|
243014
|
+
return new OffsetMeshOptions(mySmoothSingleRadiansBetweenNormals, mySmoothAccumulatedRadiansBetweenNormals, myChamferTurnAngleBetweenNormals);
|
|
243015
|
+
}
|
|
243016
|
+
}
|
|
242884
243017
|
/**
|
|
242885
243018
|
* Enumeration of cases for retaining facets among duplicates
|
|
242886
243019
|
* @public
|
|
@@ -242902,12 +243035,12 @@ var DuplicateFacetClusterSelector;
|
|
|
242902
243035
|
class PolyfaceQuery {
|
|
242903
243036
|
/** copy the points from a visitor into a Linestring3d in a Loop object */
|
|
242904
243037
|
static visitorToLoop(visitor) {
|
|
242905
|
-
const ls =
|
|
242906
|
-
return
|
|
243038
|
+
const ls = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_1__.LineString3d.createPoints(visitor.point.getPoint3dArray());
|
|
243039
|
+
return _curve_Loop__WEBPACK_IMPORTED_MODULE_2__.Loop.create(ls);
|
|
242907
243040
|
}
|
|
242908
243041
|
/** Create a linestring loop for each facet of the polyface. */
|
|
242909
243042
|
static indexedPolyfaceToLoops(polyface) {
|
|
242910
|
-
const result =
|
|
243043
|
+
const result = _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.BagOfCurves.create();
|
|
242911
243044
|
const visitor = polyface.createVisitor(1);
|
|
242912
243045
|
while (visitor.moveToNextFacet()) {
|
|
242913
243046
|
const loop = PolyfaceQuery.visitorToLoop(visitor);
|
|
@@ -242921,17 +243054,17 @@ class PolyfaceQuery {
|
|
|
242921
243054
|
static sumFacetAreas(source, vectorToEye) {
|
|
242922
243055
|
let s = 0;
|
|
242923
243056
|
if (source !== undefined) {
|
|
242924
|
-
if (source instanceof
|
|
243057
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
242925
243058
|
return PolyfaceQuery.sumFacetAreas(source.createVisitor(1), vectorToEye);
|
|
242926
243059
|
let unitVectorToEye;
|
|
242927
243060
|
if (vectorToEye !== undefined)
|
|
242928
243061
|
unitVectorToEye = vectorToEye.normalize();
|
|
242929
243062
|
source.reset();
|
|
242930
243063
|
while (source.moveToNextFacet()) {
|
|
242931
|
-
const scaledNormal =
|
|
243064
|
+
const scaledNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.areaNormal(source.point.getPoint3dArray());
|
|
242932
243065
|
let area = scaledNormal.magnitude();
|
|
242933
243066
|
if (unitVectorToEye !== undefined) {
|
|
242934
|
-
const scale =
|
|
243067
|
+
const scale = _Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.conditionalDivideCoordinate(1.0, area);
|
|
242935
243068
|
if (scale !== undefined)
|
|
242936
243069
|
area *= scaledNormal.dotProduct(unitVectorToEye) * scale;
|
|
242937
243070
|
}
|
|
@@ -242948,12 +243081,12 @@ class PolyfaceQuery {
|
|
|
242948
243081
|
*/
|
|
242949
243082
|
static sumTetrahedralVolumes(source, origin) {
|
|
242950
243083
|
let s = 0;
|
|
242951
|
-
if (source instanceof
|
|
243084
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
242952
243085
|
return PolyfaceQuery.sumTetrahedralVolumes(source.createVisitor(0), origin);
|
|
242953
243086
|
let myOrigin = origin;
|
|
242954
|
-
const facetOrigin =
|
|
242955
|
-
const targetA =
|
|
242956
|
-
const targetB =
|
|
243087
|
+
const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
243088
|
+
const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
243089
|
+
const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
242957
243090
|
source.reset();
|
|
242958
243091
|
while (source.moveToNextFacet()) {
|
|
242959
243092
|
if (myOrigin === undefined)
|
|
@@ -242974,20 +243107,20 @@ class PolyfaceQuery {
|
|
|
242974
243107
|
*
|
|
242975
243108
|
*/
|
|
242976
243109
|
static sumVolumeBetweenFacetsAndPlane(source, plane) {
|
|
242977
|
-
if (source instanceof
|
|
243110
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
242978
243111
|
return PolyfaceQuery.sumVolumeBetweenFacetsAndPlane(source.createVisitor(0), plane);
|
|
242979
|
-
const facetOrigin =
|
|
242980
|
-
const targetA =
|
|
242981
|
-
const targetB =
|
|
242982
|
-
const triangleNormal =
|
|
243112
|
+
const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
243113
|
+
const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
243114
|
+
const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
243115
|
+
const triangleNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
242983
243116
|
const planeNormal = plane.getNormalRef();
|
|
242984
243117
|
let h0, hA, hB;
|
|
242985
243118
|
let signedVolumeSum = 0.0;
|
|
242986
243119
|
let signedTriangleArea;
|
|
242987
243120
|
let singleFacetArea;
|
|
242988
|
-
const positiveAreaMomentSums =
|
|
242989
|
-
const negativeAreaMomentSums =
|
|
242990
|
-
const singleFacetProducts =
|
|
243121
|
+
const positiveAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.create(undefined, true);
|
|
243122
|
+
const negativeAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.create(undefined, true);
|
|
243123
|
+
const singleFacetProducts = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
|
|
242991
243124
|
const projectToPlane = plane.getProjectionToPlane();
|
|
242992
243125
|
source.reset();
|
|
242993
243126
|
// For each facet ..
|
|
@@ -243014,7 +243147,7 @@ class PolyfaceQuery {
|
|
|
243014
243147
|
}
|
|
243015
243148
|
singleFacetProducts.setZero();
|
|
243016
243149
|
source.point.multiplyTransformInPlace(projectToPlane);
|
|
243017
|
-
|
|
243150
|
+
_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentAreaProducts(source.point, facetOrigin, singleFacetProducts);
|
|
243018
243151
|
if (singleFacetArea > 0) {
|
|
243019
243152
|
positiveAreaMomentSums.accumulateProductsFromOrigin(facetOrigin, singleFacetProducts, 1.0);
|
|
243020
243153
|
}
|
|
@@ -243024,8 +243157,8 @@ class PolyfaceQuery {
|
|
|
243024
243157
|
}
|
|
243025
243158
|
positiveAreaMomentSums.shiftOriginAndSumsToCentroidOfSums();
|
|
243026
243159
|
negativeAreaMomentSums.shiftOriginAndSumsToCentroidOfSums();
|
|
243027
|
-
const positiveAreaMoments =
|
|
243028
|
-
const negativeAreaMoments =
|
|
243160
|
+
const positiveAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(positiveAreaMomentSums.origin, positiveAreaMomentSums.sums);
|
|
243161
|
+
const negativeAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(negativeAreaMomentSums.origin, negativeAreaMomentSums.sums);
|
|
243029
243162
|
return {
|
|
243030
243163
|
volume: signedVolumeSum / 6.0,
|
|
243031
243164
|
positiveProjectedFacetAreaMoments: positiveAreaMoments,
|
|
@@ -243034,23 +243167,23 @@ class PolyfaceQuery {
|
|
|
243034
243167
|
}
|
|
243035
243168
|
/** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all all facets, as viewed from origin. */
|
|
243036
243169
|
static sumFacetSecondAreaMomentProducts(source, origin) {
|
|
243037
|
-
if (source instanceof
|
|
243170
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
243038
243171
|
return PolyfaceQuery.sumFacetSecondAreaMomentProducts(source.createVisitor(0), origin);
|
|
243039
|
-
const products =
|
|
243172
|
+
const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
|
|
243040
243173
|
source.reset();
|
|
243041
243174
|
while (source.moveToNextFacet()) {
|
|
243042
|
-
|
|
243175
|
+
_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentAreaProducts(source.point, origin, products);
|
|
243043
243176
|
}
|
|
243044
243177
|
return products;
|
|
243045
243178
|
}
|
|
243046
243179
|
/** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all tetrahedral volumes from origin */
|
|
243047
243180
|
static sumFacetSecondVolumeMomentProducts(source, origin) {
|
|
243048
|
-
if (source instanceof
|
|
243181
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
243049
243182
|
return PolyfaceQuery.sumFacetSecondVolumeMomentProducts(source.createVisitor(0), origin);
|
|
243050
|
-
const products =
|
|
243183
|
+
const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
|
|
243051
243184
|
source.reset();
|
|
243052
243185
|
while (source.moveToNextFacet()) {
|
|
243053
|
-
|
|
243186
|
+
_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentVolumeProducts(source.point, origin, products);
|
|
243054
243187
|
}
|
|
243055
243188
|
return products;
|
|
243056
243189
|
}
|
|
@@ -243064,7 +243197,7 @@ class PolyfaceQuery {
|
|
|
243064
243197
|
if (!origin)
|
|
243065
243198
|
return undefined;
|
|
243066
243199
|
const inertiaProducts = PolyfaceQuery.sumFacetSecondAreaMomentProducts(source, origin);
|
|
243067
|
-
return
|
|
243200
|
+
return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
|
|
243068
243201
|
}
|
|
243069
243202
|
/** Compute area moments for the mesh. In the returned MomentData:
|
|
243070
243203
|
* * origin is the centroid.
|
|
@@ -243078,7 +243211,7 @@ class PolyfaceQuery {
|
|
|
243078
243211
|
if (!origin)
|
|
243079
243212
|
return undefined;
|
|
243080
243213
|
const inertiaProducts = PolyfaceQuery.sumFacetSecondVolumeMomentProducts(source, origin);
|
|
243081
|
-
return
|
|
243214
|
+
return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
|
|
243082
243215
|
}
|
|
243083
243216
|
/**
|
|
243084
243217
|
* Test for convex volume by dihedral angle tests on all edges.
|
|
@@ -243110,14 +243243,14 @@ class PolyfaceQuery {
|
|
|
243110
243243
|
* * (but null edges are permitted -- These occur naturally at edges of quads at north or south pole)
|
|
243111
243244
|
*/
|
|
243112
243245
|
static dihedralAngleSummary(source, ignoreBoundaries = false) {
|
|
243113
|
-
const edges = new
|
|
243246
|
+
const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
243114
243247
|
const visitor = source.createVisitor(1);
|
|
243115
243248
|
visitor.reset();
|
|
243116
243249
|
const centroidNormal = [];
|
|
243117
243250
|
let normalCounter = 0;
|
|
243118
243251
|
while (visitor.moveToNextFacet()) {
|
|
243119
243252
|
const numEdges = visitor.pointCount - 1;
|
|
243120
|
-
const normal =
|
|
243253
|
+
const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.centroidAreaNormal(visitor.point);
|
|
243121
243254
|
if (normal === undefined)
|
|
243122
243255
|
return 0;
|
|
243123
243256
|
centroidNormal.push(normal);
|
|
@@ -243134,12 +243267,12 @@ class PolyfaceQuery {
|
|
|
243134
243267
|
let numPositive = 0;
|
|
243135
243268
|
let numPlanar = 0;
|
|
243136
243269
|
let numNegative = 0;
|
|
243137
|
-
const edgeVector =
|
|
243270
|
+
const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
243138
243271
|
for (const cluster of manifoldClusters) {
|
|
243139
243272
|
const sideA = cluster[0];
|
|
243140
243273
|
const sideB = cluster[1];
|
|
243141
|
-
if (sideA instanceof
|
|
243142
|
-
&& sideB instanceof
|
|
243274
|
+
if (sideA instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge
|
|
243275
|
+
&& sideB instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge
|
|
243143
243276
|
&& source.data.point.vectorIndexIndex(sideA.vertexIndexA, sideA.vertexIndexB, edgeVector)) {
|
|
243144
243277
|
const dihedralAngle = centroidNormal[sideA.facetIndex].direction.signedAngleTo(centroidNormal[sideB.facetIndex].direction, edgeVector);
|
|
243145
243278
|
if (dihedralAngle.isAlmostZero)
|
|
@@ -243172,7 +243305,7 @@ class PolyfaceQuery {
|
|
|
243172
243305
|
* * Any edge with 2 incident facets in the same direction triggers a `false` return.
|
|
243173
243306
|
*/
|
|
243174
243307
|
static isPolyfaceManifold(source, allowSimpleBoundaries = false) {
|
|
243175
|
-
const edges = new
|
|
243308
|
+
const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
243176
243309
|
const visitor = source.createVisitor(1);
|
|
243177
243310
|
visitor.reset();
|
|
243178
243311
|
while (visitor.moveToNextFacet()) {
|
|
@@ -243195,9 +243328,9 @@ class PolyfaceQuery {
|
|
|
243195
243328
|
* @returns
|
|
243196
243329
|
*/
|
|
243197
243330
|
static boundaryEdges(source, includeDanglers = true, includeMismatch = true, includeNull = true) {
|
|
243198
|
-
const result = new
|
|
243331
|
+
const result = new _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.BagOfCurves();
|
|
243199
243332
|
const announceEdge = (pointA, pointB, _indexA, _indexB, _readIndex) => {
|
|
243200
|
-
result.tryAddChild(
|
|
243333
|
+
result.tryAddChild(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB));
|
|
243201
243334
|
};
|
|
243202
243335
|
PolyfaceQuery.announceBoundaryEdges(source, announceEdge, includeDanglers, includeMismatch, includeNull);
|
|
243203
243336
|
if (result.children.length === 0)
|
|
@@ -243216,8 +243349,8 @@ class PolyfaceQuery {
|
|
|
243216
243349
|
static announceBoundaryEdges(source, announceEdge, includeDanglers = true, includeMismatch = true, includeNull = true) {
|
|
243217
243350
|
if (source === undefined)
|
|
243218
243351
|
return undefined;
|
|
243219
|
-
const edges = new
|
|
243220
|
-
const visitor = source instanceof
|
|
243352
|
+
const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
243353
|
+
const visitor = source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface ? source.createVisitor(1) : source;
|
|
243221
243354
|
visitor.setNumWrap(1);
|
|
243222
243355
|
visitor.reset();
|
|
243223
243356
|
while (visitor.moveToNextFacet()) {
|
|
@@ -243242,7 +243375,7 @@ class PolyfaceQuery {
|
|
|
243242
243375
|
const sourcePolyface = visitor.clientPolyface();
|
|
243243
243376
|
for (const list of badList) {
|
|
243244
243377
|
for (const e of list) {
|
|
243245
|
-
const e1 = e instanceof
|
|
243378
|
+
const e1 = e instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge ? e : e[0];
|
|
243246
243379
|
const indexA = e1.vertexIndexA;
|
|
243247
243380
|
const indexB = e1.vertexIndexB;
|
|
243248
243381
|
const pointA = sourcePolyface.data.getPoint(indexA);
|
|
@@ -243257,7 +243390,7 @@ class PolyfaceQuery {
|
|
|
243257
243390
|
* * Facets are ASSUMED to be convex and planar.
|
|
243258
243391
|
*/
|
|
243259
243392
|
static announceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, announce) {
|
|
243260
|
-
const context =
|
|
243393
|
+
const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__.SweepLineStringToFacetContext.create(linestringPoints);
|
|
243261
243394
|
if (context) {
|
|
243262
243395
|
const visitor = polyface.createVisitor(0);
|
|
243263
243396
|
for (visitor.reset(); visitor.moveToNextFacet();) {
|
|
@@ -243290,7 +243423,7 @@ class PolyfaceQuery {
|
|
|
243290
243423
|
* @internal
|
|
243291
243424
|
*/
|
|
243292
243425
|
static async asyncAnnounceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, announce) {
|
|
243293
|
-
const context =
|
|
243426
|
+
const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__.SweepLineStringToFacetContext.create(linestringPoints);
|
|
243294
243427
|
this.awaitBlockCount = 0;
|
|
243295
243428
|
let workTotal = 0;
|
|
243296
243429
|
if (context) {
|
|
@@ -243310,11 +243443,11 @@ class PolyfaceQuery {
|
|
|
243310
243443
|
* * Return array of arrays of facet indices.
|
|
243311
243444
|
*/
|
|
243312
243445
|
static partitionFacetIndicesByVertexConnectedComponent(polyface) {
|
|
243313
|
-
if (polyface instanceof
|
|
243446
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
243314
243447
|
return this.partitionFacetIndicesByVertexConnectedComponent(polyface.createVisitor(0));
|
|
243315
243448
|
}
|
|
243316
243449
|
// The polyface is really a visitor !!!
|
|
243317
|
-
const context = new
|
|
243450
|
+
const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__.UnionFindContext(this.visitorClientPointCount(polyface));
|
|
243318
243451
|
for (polyface.reset(); polyface.moveToNextFacet();) {
|
|
243319
243452
|
const firstVertexIndexOnThisFacet = polyface.pointIndex[0];
|
|
243320
243453
|
for (const vertexIndex of polyface.pointIndex)
|
|
@@ -243347,7 +243480,7 @@ class PolyfaceQuery {
|
|
|
243347
243480
|
* * Return array of arrays of facet indices.
|
|
243348
243481
|
*/
|
|
243349
243482
|
static partitionFacetIndicesByVisibilityVector(polyface, vectorToEye, sideAngleTolerance) {
|
|
243350
|
-
if (polyface instanceof
|
|
243483
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
243351
243484
|
return this.partitionFacetIndicesByVisibilityVector(polyface.createVisitor(0), vectorToEye, sideAngleTolerance);
|
|
243352
243485
|
}
|
|
243353
243486
|
const facetsInComponent = [];
|
|
@@ -243359,7 +243492,7 @@ class PolyfaceQuery {
|
|
|
243359
243492
|
const sideComponent = facetsInComponent[2];
|
|
243360
243493
|
const radiansTol = Math.max(sideAngleTolerance.radians, 1.0e-8);
|
|
243361
243494
|
for (polyface.reset(); polyface.moveToNextFacet();) {
|
|
243362
|
-
const areaNormal =
|
|
243495
|
+
const areaNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.areaNormalGo(polyface.point);
|
|
243363
243496
|
const index = polyface.currentReadIndex();
|
|
243364
243497
|
if (areaNormal) {
|
|
243365
243498
|
const angle = areaNormal.angleFromPerpendicular(vectorToEye);
|
|
@@ -243386,7 +243519,7 @@ class PolyfaceQuery {
|
|
|
243386
243519
|
* @param vectorToEye
|
|
243387
243520
|
* @param sideAngleTolerance
|
|
243388
243521
|
*/
|
|
243389
|
-
static boundaryOfVisibleSubset(polyface, visibilitySelect, vectorToEye, sideAngleTolerance =
|
|
243522
|
+
static boundaryOfVisibleSubset(polyface, visibilitySelect, vectorToEye, sideAngleTolerance = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(1.0e-3)) {
|
|
243390
243523
|
const partitionedIndices = this.partitionFacetIndicesByVisibilityVector(polyface, vectorToEye, sideAngleTolerance);
|
|
243391
243524
|
if (partitionedIndices[visibilitySelect].length === 0)
|
|
243392
243525
|
return undefined;
|
|
@@ -243400,8 +243533,8 @@ class PolyfaceQuery {
|
|
|
243400
243533
|
* @param mesh
|
|
243401
243534
|
*/
|
|
243402
243535
|
static announceBoundaryChainsAsLineString3d(mesh, announceLoop) {
|
|
243403
|
-
const collector = new _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.MultiChainCollector(
|
|
243404
|
-
PolyfaceQuery.announceBoundaryEdges(mesh, (pointA, pointB, _indexA, _indexB) => collector.captureCurve(
|
|
243536
|
+
const collector = new _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.MultiChainCollector(_Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallMetricDistance, 1000);
|
|
243537
|
+
PolyfaceQuery.announceBoundaryEdges(mesh, (pointA, pointB, _indexA, _indexB) => collector.captureCurve(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB)), true, false, false);
|
|
243405
243538
|
collector.announceChainsAsLineString3d(announceLoop);
|
|
243406
243539
|
}
|
|
243407
243540
|
/**
|
|
@@ -243412,7 +243545,7 @@ class PolyfaceQuery {
|
|
|
243412
243545
|
* @returns
|
|
243413
243546
|
*/
|
|
243414
243547
|
static cloneWithMaximalPlanarFacets(mesh) {
|
|
243415
|
-
if (mesh instanceof
|
|
243548
|
+
if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
243416
243549
|
return this.cloneWithMaximalPlanarFacets(mesh.createVisitor(0));
|
|
243417
243550
|
const numFacets = PolyfaceQuery.visitorClientFacetCount(mesh);
|
|
243418
243551
|
const smoothEdges = PolyfaceQuery.collectEdgesByDihedralAngle(mesh);
|
|
@@ -243437,7 +243570,7 @@ class PolyfaceQuery {
|
|
|
243437
243570
|
const edges = [];
|
|
243438
243571
|
const edgeStrings = [];
|
|
243439
243572
|
PolyfaceQuery.announceBoundaryEdges(fragment, (pointA, pointB, _indexA, _indexB) => {
|
|
243440
|
-
edges.push(
|
|
243573
|
+
edges.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB));
|
|
243441
243574
|
edgeStrings.push([pointA.clone(), pointB.clone()]);
|
|
243442
243575
|
});
|
|
243443
243576
|
const chains = _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.OffsetHelpers.collectChains(edges, gapTolerance, planarityTolerance);
|
|
@@ -243478,7 +243611,7 @@ class PolyfaceQuery {
|
|
|
243478
243611
|
* @returns
|
|
243479
243612
|
*/
|
|
243480
243613
|
static fillSimpleHoles(mesh, options, unfilledChains) {
|
|
243481
|
-
if (mesh instanceof
|
|
243614
|
+
if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
243482
243615
|
return this.fillSimpleHoles(mesh.createVisitor(0), options, unfilledChains);
|
|
243483
243616
|
const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
|
|
243484
243617
|
const chains = [];
|
|
@@ -243492,7 +243625,7 @@ class PolyfaceQuery {
|
|
|
243492
243625
|
rejected = true;
|
|
243493
243626
|
else if (options.maxPerimeter !== undefined && _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_21__.Point3dArray.sumEdgeLengths(points, false) > options.maxPerimeter)
|
|
243494
243627
|
rejected = true;
|
|
243495
|
-
else if (options.upVector !== undefined &&
|
|
243628
|
+
else if (options.upVector !== undefined && _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.sumTriangleAreasPerpendicularToUpVector(points, options.upVector) <= 0.0)
|
|
243496
243629
|
rejected = true;
|
|
243497
243630
|
if (!rejected && _topology_SpaceTriangulation__WEBPACK_IMPORTED_MODULE_22__.SpacePolygonTriangulation.triangulateSimplestSpaceLoop(points, (_loop, triangles) => {
|
|
243498
243631
|
for (const t of triangles)
|
|
@@ -243515,7 +243648,7 @@ class PolyfaceQuery {
|
|
|
243515
243648
|
*
|
|
243516
243649
|
*/
|
|
243517
243650
|
static clonePartitions(polyface, partitions) {
|
|
243518
|
-
if (polyface instanceof
|
|
243651
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
243519
243652
|
return this.clonePartitions(polyface.createVisitor(0), partitions);
|
|
243520
243653
|
}
|
|
243521
243654
|
polyface.setNumWrap(0);
|
|
@@ -243539,7 +243672,7 @@ class PolyfaceQuery {
|
|
|
243539
243672
|
/** Clone facets that pass an filter function
|
|
243540
243673
|
*/
|
|
243541
243674
|
static cloneFiltered(source, filter) {
|
|
243542
|
-
if (source instanceof
|
|
243675
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
243543
243676
|
return this.cloneFiltered(source.createVisitor(0), filter);
|
|
243544
243677
|
}
|
|
243545
243678
|
source.setNumWrap(0);
|
|
@@ -243591,9 +243724,9 @@ class PolyfaceQuery {
|
|
|
243591
243724
|
* @return collection of facet index arrays, one array per connected component
|
|
243592
243725
|
*/
|
|
243593
243726
|
static partitionFacetIndicesBySortableEdgeClusters(edgeClusters, numFacets) {
|
|
243594
|
-
const context = new
|
|
243727
|
+
const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__.UnionFindContext(numFacets);
|
|
243595
243728
|
for (const cluster of edgeClusters) {
|
|
243596
|
-
if (cluster instanceof
|
|
243729
|
+
if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge) {
|
|
243597
243730
|
// this edge does not connect anywhere. Ignore it!!
|
|
243598
243731
|
}
|
|
243599
243732
|
else {
|
|
@@ -243625,11 +243758,11 @@ class PolyfaceQuery {
|
|
|
243625
243758
|
* @return collection of facet index arrays, one per connected component
|
|
243626
243759
|
*/
|
|
243627
243760
|
static partitionFacetIndicesByEdgeConnectedComponent(polyface, stopAtVisibleEdges = false) {
|
|
243628
|
-
if (polyface instanceof
|
|
243761
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
243629
243762
|
return this.partitionFacetIndicesByEdgeConnectedComponent(polyface.createVisitor(0), stopAtVisibleEdges);
|
|
243630
243763
|
}
|
|
243631
243764
|
polyface.setNumWrap(1);
|
|
243632
|
-
const matcher = new
|
|
243765
|
+
const matcher = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
243633
243766
|
polyface.reset();
|
|
243634
243767
|
let numFacets = 0;
|
|
243635
243768
|
while (polyface.moveToNextFacet()) {
|
|
@@ -243667,7 +243800,7 @@ class PolyfaceQuery {
|
|
|
243667
243800
|
static sweepLinestringToFacetsXYReturnLines(linestringPoints, polyface) {
|
|
243668
243801
|
const drapeGeometry = [];
|
|
243669
243802
|
this.announceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, (_linestring, _segmentIndex, _polyface, _facetIndex, points, indexA, indexB) => {
|
|
243670
|
-
drapeGeometry.push(
|
|
243803
|
+
drapeGeometry.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(points[indexA], points[indexB]));
|
|
243671
243804
|
});
|
|
243672
243805
|
return drapeGeometry;
|
|
243673
243806
|
}
|
|
@@ -243702,7 +243835,7 @@ class PolyfaceQuery {
|
|
|
243702
243835
|
* * Return statistical summary of x,y,z ranges.
|
|
243703
243836
|
*/
|
|
243704
243837
|
static collectRangeLengthData(polyface) {
|
|
243705
|
-
if (polyface instanceof
|
|
243838
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
243706
243839
|
return this.collectRangeLengthData(polyface.createVisitor(0));
|
|
243707
243840
|
}
|
|
243708
243841
|
const rangeData = new _RangeLengthData__WEBPACK_IMPORTED_MODULE_25__.RangeLengthData();
|
|
@@ -243720,10 +243853,10 @@ class PolyfaceQuery {
|
|
|
243720
243853
|
const rangeSearcher = _multiclip_XYPointBuckets__WEBPACK_IMPORTED_MODULE_26__.XYPointBuckets.create(polyface.data.point, 30);
|
|
243721
243854
|
const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
|
|
243722
243855
|
const edgeRange = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_27__.Range3d.createNull();
|
|
243723
|
-
const point0 =
|
|
243724
|
-
const point1 =
|
|
243725
|
-
const spacePoint =
|
|
243726
|
-
const segment =
|
|
243856
|
+
const point0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
243857
|
+
const point1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
243858
|
+
const spacePoint = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
243859
|
+
const segment = _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(point0, point1);
|
|
243727
243860
|
for (oldFacetVisitor.reset(); oldFacetVisitor.moveToNextFacet();) {
|
|
243728
243861
|
newFacetVisitor.clearArrays();
|
|
243729
243862
|
for (let i = 0; i + 1 < oldFacetVisitor.point.length; i++) {
|
|
@@ -243732,7 +243865,7 @@ class PolyfaceQuery {
|
|
|
243732
243865
|
oldFacetVisitor.point.getPoint3dAtUncheckedPointIndex(i + 1, point1);
|
|
243733
243866
|
newFacetVisitor.pushDataFrom(oldFacetVisitor, i);
|
|
243734
243867
|
edgeRange.setNull();
|
|
243735
|
-
|
|
243868
|
+
_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(point0, point1, segment);
|
|
243736
243869
|
let detailArray;
|
|
243737
243870
|
edgeRange.extend(point0);
|
|
243738
243871
|
edgeRange.extend(point1);
|
|
@@ -243877,8 +244010,8 @@ class PolyfaceQuery {
|
|
|
243877
244010
|
const oldFacetVisitor = polyface.createVisitor(2); // This is to visit the existing facets.
|
|
243878
244011
|
const newFacetVisitor = polyface.createVisitor(0); // This is to build the new facets.
|
|
243879
244012
|
const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
|
|
243880
|
-
const vector01 =
|
|
243881
|
-
const vector12 =
|
|
244013
|
+
const vector01 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
244014
|
+
const vector12 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
243882
244015
|
const numPoint = polyface.data.point.length;
|
|
243883
244016
|
const pointState = new Int32Array(numPoint);
|
|
243884
244017
|
// FIRST PASS -- in each sector of each facet, determine if the sector has colinear incoming and outgoing vectors.
|
|
@@ -243925,7 +244058,7 @@ class PolyfaceQuery {
|
|
|
243925
244058
|
*/
|
|
243926
244059
|
static setEdgeVisibility(polyface, clusters, value) {
|
|
243927
244060
|
for (const cluster of clusters) {
|
|
243928
|
-
if (cluster instanceof
|
|
244061
|
+
if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge) {
|
|
243929
244062
|
this.setSingleEdgeVisibility(polyface, cluster.facetIndex, cluster.vertexIndexA, value);
|
|
243930
244063
|
}
|
|
243931
244064
|
else if (Array.isArray(cluster)) {
|
|
@@ -243968,9 +244101,9 @@ class PolyfaceQuery {
|
|
|
243968
244101
|
* @param polyface a mesh, or a visitor assumed to have numWrap === 1
|
|
243969
244102
|
*/
|
|
243970
244103
|
static createIndexedEdges(polyface) {
|
|
243971
|
-
if (polyface instanceof
|
|
244104
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
243972
244105
|
return this.createIndexedEdges(polyface.createVisitor(1));
|
|
243973
|
-
const edges = new
|
|
244106
|
+
const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
243974
244107
|
polyface.reset();
|
|
243975
244108
|
while (polyface.moveToNextFacet()) {
|
|
243976
244109
|
const numEdges = polyface.pointCount - 1;
|
|
@@ -243989,17 +244122,17 @@ class PolyfaceQuery {
|
|
|
243989
244122
|
* @param sharpEdges true to reverse the angle threshold test and return sharp edges; otherwise return smooth edges (default)
|
|
243990
244123
|
*/
|
|
243991
244124
|
static collectEdgesByDihedralAngle(mesh, maxSmoothEdgeAngle, sharpEdges = false) {
|
|
243992
|
-
if (mesh instanceof
|
|
244125
|
+
if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
243993
244126
|
return this.collectEdgesByDihedralAngle(mesh.createVisitor(1), maxSmoothEdgeAngle, sharpEdges);
|
|
243994
244127
|
mesh.setNumWrap(1);
|
|
243995
244128
|
const allEdges = this.createIndexedEdges(mesh);
|
|
243996
244129
|
const manifoldEdges = [];
|
|
243997
244130
|
allEdges.sortAndCollectClusters(manifoldEdges);
|
|
243998
244131
|
if (undefined === maxSmoothEdgeAngle || maxSmoothEdgeAngle.radians < 0)
|
|
243999
|
-
maxSmoothEdgeAngle =
|
|
244132
|
+
maxSmoothEdgeAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createRadians(_Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallAngleRadians);
|
|
244000
244133
|
const outEdges = [];
|
|
244001
|
-
const normal0 =
|
|
244002
|
-
const normal1 =
|
|
244134
|
+
const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
244135
|
+
const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
244003
244136
|
for (const pair of manifoldEdges) {
|
|
244004
244137
|
if (Array.isArray(pair) && pair.length === 2) {
|
|
244005
244138
|
const e0 = pair[0];
|
|
@@ -244038,8 +244171,8 @@ class PolyfaceQuery {
|
|
|
244038
244171
|
this.markAllEdgeVisibility(mesh, false);
|
|
244039
244172
|
this.setEdgeVisibility(mesh, boundaryEdges, true);
|
|
244040
244173
|
if (sharpEdgeAngle !== undefined) {
|
|
244041
|
-
const normal0 =
|
|
244042
|
-
const normal1 =
|
|
244174
|
+
const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
244175
|
+
const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
244043
244176
|
for (const pair of pairedEdges) {
|
|
244044
244177
|
if (Array.isArray(pair) && pair.length === 2) {
|
|
244045
244178
|
const e0 = pair[0];
|
|
@@ -244061,9 +244194,9 @@ class PolyfaceQuery {
|
|
|
244061
244194
|
*/
|
|
244062
244195
|
static computeFacetUnitNormal(visitor, facetIndex, result) {
|
|
244063
244196
|
if (!result)
|
|
244064
|
-
result =
|
|
244197
|
+
result = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
244065
244198
|
if (visitor.moveToReadIndex(facetIndex)) {
|
|
244066
|
-
if (
|
|
244199
|
+
if (_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.unitNormal(visitor.point, result))
|
|
244067
244200
|
return result;
|
|
244068
244201
|
}
|
|
244069
244202
|
return undefined;
|
|
@@ -244078,20 +244211,41 @@ class PolyfaceQuery {
|
|
|
244078
244211
|
for (let i = 0; i < data.edgeVisible.length; i++)
|
|
244079
244212
|
data.edgeVisible[i] = value;
|
|
244080
244213
|
}
|
|
244214
|
+
/**
|
|
244215
|
+
* Create a HalfEdgeGraph with a face for each facet of the IndexedPolyface
|
|
244216
|
+
* @param mesh mesh to convert
|
|
244217
|
+
* @internal
|
|
244218
|
+
*/
|
|
244219
|
+
static convertToHalfEdgeGraph(mesh) {
|
|
244220
|
+
const builder = new _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_28__.HalfEdgeGraphFromIndexedLoopsContext();
|
|
244221
|
+
const visitor = mesh.createVisitor(0);
|
|
244222
|
+
for (visitor.reset(); visitor.moveToNextFacet();) {
|
|
244223
|
+
builder.insertLoop(visitor.pointIndex);
|
|
244224
|
+
}
|
|
244225
|
+
const graph = builder.graph;
|
|
244226
|
+
const xyz = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
244227
|
+
graph.announceNodes((_graph, halfEdge) => {
|
|
244228
|
+
const vertexIndex = halfEdge.i;
|
|
244229
|
+
mesh.data.getPoint(vertexIndex, xyz);
|
|
244230
|
+
halfEdge.setXYZ(xyz);
|
|
244231
|
+
return true;
|
|
244232
|
+
});
|
|
244233
|
+
return graph;
|
|
244234
|
+
}
|
|
244081
244235
|
/**
|
|
244082
244236
|
* * Examine adjacent facet orientations throughout the mesh
|
|
244083
244237
|
* * If possible, reverse a subset to achieve proper pairing.
|
|
244084
244238
|
* @param mesh
|
|
244085
244239
|
*/
|
|
244086
244240
|
static reorientVertexOrderAroundFacetsForConsistentOrientation(mesh) {
|
|
244087
|
-
return
|
|
244241
|
+
return _FacetOrientation__WEBPACK_IMPORTED_MODULE_29__.FacetOrientationFixup.doFixup(mesh);
|
|
244088
244242
|
}
|
|
244089
244243
|
/**
|
|
244090
244244
|
* Set up indexed normals with one normal in the plane of each facet of the mesh.
|
|
244091
244245
|
* @param polyface
|
|
244092
244246
|
*/
|
|
244093
244247
|
static buildPerFaceNormals(polyface) {
|
|
244094
|
-
|
|
244248
|
+
_multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__.BuildAverageNormalsContext.buildPerFaceNormals(polyface);
|
|
244095
244249
|
}
|
|
244096
244250
|
/**
|
|
244097
244251
|
* * At each vertex of the mesh
|
|
@@ -244103,8 +244257,21 @@ class PolyfaceQuery {
|
|
|
244103
244257
|
* @param polyface polyface to update.
|
|
244104
244258
|
* @param toleranceAngle averaging is done between normals up to this angle.
|
|
244105
244259
|
*/
|
|
244106
|
-
static buildAverageNormals(polyface, toleranceAngle =
|
|
244107
|
-
|
|
244260
|
+
static buildAverageNormals(polyface, toleranceAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(31.0)) {
|
|
244261
|
+
_multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__.BuildAverageNormalsContext.buildFastAverageNormals(polyface, toleranceAngle);
|
|
244262
|
+
}
|
|
244263
|
+
/**
|
|
244264
|
+
* Offset the faces of the mesh.
|
|
244265
|
+
* @param source original mesh
|
|
244266
|
+
* @param signedOffsetDistance distance to offset
|
|
244267
|
+
* @param offsetOptions angle options. The default options are recommended.
|
|
244268
|
+
* @returns shifted mesh.
|
|
244269
|
+
*/
|
|
244270
|
+
static cloneOffset(source, signedOffsetDistance, offsetOptions = OffsetMeshOptions.create()) {
|
|
244271
|
+
const strokeOptions = _curve_StrokeOptions__WEBPACK_IMPORTED_MODULE_23__.StrokeOptions.createForFacets();
|
|
244272
|
+
const offsetBuilder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create(strokeOptions);
|
|
244273
|
+
_multiclip_OffsetMeshContext__WEBPACK_IMPORTED_MODULE_31__.OffsetMeshContext.buildOffsetMeshWithEdgeChamfers(source, offsetBuilder, signedOffsetDistance, offsetOptions);
|
|
244274
|
+
return offsetBuilder.claimPolyface();
|
|
244108
244275
|
}
|
|
244109
244276
|
}
|
|
244110
244277
|
// amount of computation to do per step of async methods.
|
|
@@ -245016,6 +245183,1064 @@ class LinearSearchRange2dArray {
|
|
|
245016
245183
|
}
|
|
245017
245184
|
|
|
245018
245185
|
|
|
245186
|
+
/***/ }),
|
|
245187
|
+
|
|
245188
|
+
/***/ "../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js":
|
|
245189
|
+
/*!***************************************************************************!*\
|
|
245190
|
+
!*** ../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js ***!
|
|
245191
|
+
\***************************************************************************/
|
|
245192
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
245193
|
+
|
|
245194
|
+
"use strict";
|
|
245195
|
+
__webpack_require__.r(__webpack_exports__);
|
|
245196
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
245197
|
+
/* harmony export */ "FacetOffsetProperties": () => (/* binding */ FacetOffsetProperties),
|
|
245198
|
+
/* harmony export */ "OffsetMeshContext": () => (/* binding */ OffsetMeshContext),
|
|
245199
|
+
/* harmony export */ "SectorOffsetProperties": () => (/* binding */ SectorOffsetProperties)
|
|
245200
|
+
/* harmony export */ });
|
|
245201
|
+
/* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
|
|
245202
|
+
/* harmony import */ var _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../geometry3d/GrowableXYZArray */ "../../core/geometry/lib/esm/geometry3d/GrowableXYZArray.js");
|
|
245203
|
+
/* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
|
|
245204
|
+
/* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
|
|
245205
|
+
/* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
|
|
245206
|
+
/* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
|
|
245207
|
+
/* harmony import */ var _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphFromIndexedLoopsContext */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js");
|
|
245208
|
+
/* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
|
|
245209
|
+
/* harmony import */ var _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../geometry3d/PolylineCompressionByEdgeOffset */ "../../core/geometry/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js");
|
|
245210
|
+
/* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
|
|
245211
|
+
/*---------------------------------------------------------------------------------------------
|
|
245212
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
245213
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
245214
|
+
*--------------------------------------------------------------------------------------------*/
|
|
245215
|
+
/** @packageDocumentation
|
|
245216
|
+
* @module Polyface
|
|
245217
|
+
*/
|
|
245218
|
+
|
|
245219
|
+
|
|
245220
|
+
|
|
245221
|
+
|
|
245222
|
+
|
|
245223
|
+
|
|
245224
|
+
|
|
245225
|
+
|
|
245226
|
+
|
|
245227
|
+
|
|
245228
|
+
function isDefinedAndTrue(value) {
|
|
245229
|
+
if (value === undefined)
|
|
245230
|
+
return false;
|
|
245231
|
+
return value;
|
|
245232
|
+
}
|
|
245233
|
+
class AverageNormalData {
|
|
245234
|
+
constructor() {
|
|
245235
|
+
this.numActiveSectors = 0;
|
|
245236
|
+
this.numInactiveSectors = 0; // exterior and sling.
|
|
245237
|
+
this.averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
|
|
245238
|
+
this.radiansSum = 0.0;
|
|
245239
|
+
this.maxDeviationRadiansFromAverage = 0.0;
|
|
245240
|
+
}
|
|
245241
|
+
clear() {
|
|
245242
|
+
this.numActiveSectors = 0;
|
|
245243
|
+
this.numInactiveSectors = 0; // exterior and sling.
|
|
245244
|
+
this.averageNormal.setZero();
|
|
245245
|
+
this.radiansSum = 0.0;
|
|
245246
|
+
this.maxDeviationRadiansFromAverage = 0.0;
|
|
245247
|
+
}
|
|
245248
|
+
/** Add a normal to the evolving sum, scaled by radians in the corner */
|
|
245249
|
+
accumulateNormal(node, normal, inactiveMask) {
|
|
245250
|
+
if (node.isMaskSet(inactiveMask)) {
|
|
245251
|
+
this.numInactiveSectors++;
|
|
245252
|
+
}
|
|
245253
|
+
else {
|
|
245254
|
+
const sectorSweepRadians = _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.sectorSweepRadiansXYZ(node, normal);
|
|
245255
|
+
this.averageNormal.addScaledInPlace(normal, sectorSweepRadians);
|
|
245256
|
+
this.radiansSum += sectorSweepRadians;
|
|
245257
|
+
this.numActiveSectors++;
|
|
245258
|
+
}
|
|
245259
|
+
}
|
|
245260
|
+
/** normalize the accumulated normals. */
|
|
245261
|
+
finishNormalAveraging() {
|
|
245262
|
+
if (this.numActiveSectors > 0 && this.averageNormal.normalizeInPlace()) {
|
|
245263
|
+
return true;
|
|
245264
|
+
}
|
|
245265
|
+
return false;
|
|
245266
|
+
}
|
|
245267
|
+
/** Compute the deviation from average. update max deviation member */
|
|
245268
|
+
recordDeviation(normal, isActive) {
|
|
245269
|
+
if (isActive) {
|
|
245270
|
+
const radians = this.averageNormal.radiansTo(normal);
|
|
245271
|
+
this.maxDeviationRadiansFromAverage = Math.max(Math.abs(this.maxDeviationRadiansFromAverage), radians);
|
|
245272
|
+
}
|
|
245273
|
+
else {
|
|
245274
|
+
}
|
|
245275
|
+
}
|
|
245276
|
+
/** Return the max deviation as computed on prior calls to recordDeviation */
|
|
245277
|
+
get maxDeviationRadians() { return this.maxDeviationRadiansFromAverage; }
|
|
245278
|
+
}
|
|
245279
|
+
function emitSector(sector) {
|
|
245280
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
245281
|
+
OffsetMeshContext.stringDebugFunction(` Sector xyz ${sector.xyz.x},${sector.xyz.y},${sector.xyz.z} `);
|
|
245282
|
+
OffsetMeshContext.stringDebugFunction(` normal ${sector.normal.x},${sector.normal.y},${sector.normal.z} `);
|
|
245283
|
+
}
|
|
245284
|
+
}
|
|
245285
|
+
// facet properties used during offset.
|
|
245286
|
+
//
|
|
245287
|
+
class FacetOffsetProperties {
|
|
245288
|
+
constructor(facetIndex, normal) {
|
|
245289
|
+
this.facetIndex = facetIndex;
|
|
245290
|
+
this.facetNormal = normal;
|
|
245291
|
+
}
|
|
245292
|
+
}
|
|
245293
|
+
/**
|
|
245294
|
+
* Sector properties during offset.
|
|
245295
|
+
* * this.normal may be initially assigned as the facet normal but can mutate by
|
|
245296
|
+
* averaging with neighbors.
|
|
245297
|
+
* * this.xyz is initially the base mesh xyz but is expected to move along the normal.
|
|
245298
|
+
* * this.count is used locally in computations.
|
|
245299
|
+
*/
|
|
245300
|
+
class SectorOffsetProperties {
|
|
245301
|
+
constructor(normal, xyz) {
|
|
245302
|
+
this.xyz = xyz;
|
|
245303
|
+
this.normal = normal;
|
|
245304
|
+
this.count = 0;
|
|
245305
|
+
}
|
|
245306
|
+
/**
|
|
245307
|
+
* Compute the angle between plane normals on opposite sides of the edge.
|
|
245308
|
+
* * parallel normals have zero angle.
|
|
245309
|
+
* * if the edge cuts inward to the volume behind the faces, the angle is negative.
|
|
245310
|
+
* * if the edge is outward (a convex edge) the the volume, the angle is positive.
|
|
245311
|
+
* @param edgeNodeA node on one side of the edge
|
|
245312
|
+
* @param edgeVector pre-allocated vector to receive vector along edge.
|
|
245313
|
+
* @param averageNormal pre-allocated vector to receive the average normal for a chamfer of the offset edge.
|
|
245314
|
+
* @param offsetDistance distance of offset being constructed. The sign of this resolves angle ambiguity.
|
|
245315
|
+
* @param radiansTolerance tolerance for large angle between normals.
|
|
245316
|
+
* @returns true if this edge has SectorOffsetProperties on both sides and the angle between normals angle exceeds radiansTolerance.
|
|
245317
|
+
*/
|
|
245318
|
+
static edgeHasLargeExteriorAngleBetweenNormals(edgeNodeA, edgeVector, averageNormal, offsetDistance, radiansTolerance = Math.PI * 0.5) {
|
|
245319
|
+
const propsA = edgeNodeA.edgeTag;
|
|
245320
|
+
const edgeNodeB = edgeNodeA.edgeMate;
|
|
245321
|
+
const propsB = edgeNodeB.edgeTag;
|
|
245322
|
+
if (propsA !== undefined && propsB !== undefined) {
|
|
245323
|
+
edgeNodeA.vectorToFaceSuccessor(edgeVector);
|
|
245324
|
+
const radians = propsA.normal.signedRadiansTo(propsB.normal, edgeVector);
|
|
245325
|
+
if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.split3WaySign(offsetDistance, -1, 1, 1) * radians >= radiansTolerance) {
|
|
245326
|
+
_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.createAdd2Scaled(propsA.normal, 1.0, propsB.normal, 1.0, averageNormal);
|
|
245327
|
+
if (averageNormal.normalizeInPlace())
|
|
245328
|
+
return true;
|
|
245329
|
+
}
|
|
245330
|
+
}
|
|
245331
|
+
return false;
|
|
245332
|
+
}
|
|
245333
|
+
static almostEqualNormals(sectorA, sectorB, radiansTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallAngleRadians) {
|
|
245334
|
+
return sectorA.normal.radiansTo(sectorB.normal) <= radiansTolerance;
|
|
245335
|
+
}
|
|
245336
|
+
static radiansBetweenNormals(sectorA, sectorB) {
|
|
245337
|
+
return sectorA.normal.radiansTo(sectorB.normal);
|
|
245338
|
+
}
|
|
245339
|
+
// Set the offset point this.xyz as sum of the nodeXyz + distance * this.normal
|
|
245340
|
+
setOffsetPointAtDistanceAtHalfEdge(halfEdge, distance) {
|
|
245341
|
+
halfEdge.getPoint3d(this.xyz);
|
|
245342
|
+
this.xyz.addScaledInPlace(this.normal, distance);
|
|
245343
|
+
}
|
|
245344
|
+
// Copy xyz from parameter into (preexisting object) xyz
|
|
245345
|
+
static setXYZAtHalfEdge(halfEdge, xyz) {
|
|
245346
|
+
const props = halfEdge.edgeTag;
|
|
245347
|
+
if (props !== undefined && xyz !== undefined)
|
|
245348
|
+
props.xyz.set(xyz.x, xyz.y, xyz.z);
|
|
245349
|
+
}
|
|
245350
|
+
// Set the offset point this.xyz directly
|
|
245351
|
+
setXYAndZ(xyz) {
|
|
245352
|
+
this.xyz.set(xyz.x, xyz.y, xyz.z);
|
|
245353
|
+
}
|
|
245354
|
+
// Look through the half edge to its properties. Set the normal there. Optionally set xyz from node xyz and offset distance
|
|
245355
|
+
static setNormalAtHalfEdge(halfEdge, uvw, distance) {
|
|
245356
|
+
const props = halfEdge.edgeTag;
|
|
245357
|
+
if (props !== undefined) {
|
|
245358
|
+
props.normal.set(uvw.x, uvw.y, uvw.z);
|
|
245359
|
+
if (distance !== undefined)
|
|
245360
|
+
props.setOffsetPointAtDistanceAtHalfEdge(halfEdge, distance);
|
|
245361
|
+
}
|
|
245362
|
+
}
|
|
245363
|
+
// Look through the half edge and its vertex successor to properties. Get the two normals. Return the angle sweeping from one to the next
|
|
245364
|
+
static sweepRadiansAroundNormal(nodeA, upVector) {
|
|
245365
|
+
const propsA = nodeA.edgeTag;
|
|
245366
|
+
const propsB = nodeA.vertexSuccessor.edgeTag;
|
|
245367
|
+
if (propsA !== undefined && propsB !== undefined) {
|
|
245368
|
+
return propsA.normal.planarRadiansTo(propsB.normal, upVector);
|
|
245369
|
+
}
|
|
245370
|
+
return undefined;
|
|
245371
|
+
}
|
|
245372
|
+
// Look through the half edge to its properties. return (if possible) the coordinates
|
|
245373
|
+
static getSectorPointAtHalfEdge(halfEdge, xyz, xyzArray) {
|
|
245374
|
+
const props = halfEdge.edgeTag;
|
|
245375
|
+
if (props !== undefined) {
|
|
245376
|
+
if (xyz !== undefined)
|
|
245377
|
+
xyz.setFromPoint3d(props.xyz);
|
|
245378
|
+
if (xyzArray !== undefined)
|
|
245379
|
+
xyzArray.push(props.xyz);
|
|
245380
|
+
return true;
|
|
245381
|
+
}
|
|
245382
|
+
return false;
|
|
245383
|
+
}
|
|
245384
|
+
// access the XYZ and push to the array (which makes copies, not reference)
|
|
245385
|
+
// return pointer to the SectorOffsetProperties
|
|
245386
|
+
static pushXYZ(xyzArray, halfEdge) {
|
|
245387
|
+
const sector = halfEdge.edgeTag;
|
|
245388
|
+
if (sector !== undefined)
|
|
245389
|
+
xyzArray.push(sector.xyz);
|
|
245390
|
+
return sector;
|
|
245391
|
+
}
|
|
245392
|
+
// Dereference to execute: accumulatingVector += halfEdge.edgeTag.normal * scale
|
|
245393
|
+
static accumulateScaledNormalAtHalfEdge(halfEdge, scale, accumulatingVector) {
|
|
245394
|
+
const sector = halfEdge.edgeTag;
|
|
245395
|
+
if (sector !== undefined)
|
|
245396
|
+
accumulatingVector.addScaledInPlace(sector.normal, scale);
|
|
245397
|
+
}
|
|
245398
|
+
}
|
|
245399
|
+
/*
|
|
245400
|
+
About Chamfer Edges ..... as constructed in addChamferTopologyToAllEdges
|
|
245401
|
+
|
|
245402
|
+
When edge vertex X to vertex Y has a sharp angle between normals, a "chamfer face" must be created to "fatten" it.
|
|
245403
|
+
|
|
245404
|
+
The original half edges (nodes) for the edge are AX and AY. These are "mates" in the halfEdge mental model. As always,
|
|
245405
|
+
AX is (as needed)
|
|
245406
|
+
(i) the preferred half edge for the left side of the edge moving from X to Y. (i.e. above the edge)
|
|
245407
|
+
(ii) a part of the face loop for the face to the left when proceeding CCW around the face to the above the drawn edge
|
|
245408
|
+
(iii) a part of the vertex loop around X
|
|
245409
|
+
Likewise, AY is (as needed)
|
|
245410
|
+
(i) the preferred half edge for the left side of the edge moving from Y to X (i.e. below the edge)
|
|
245411
|
+
(ii) a part of the face loop for the face to the left of the edge when proceeding CCW around the face below the edge.
|
|
245412
|
+
(iii) a part of the vertex loop around Y
|
|
245413
|
+
|
|
245414
|
+
AX------>
|
|
245415
|
+
X______________________________________________________________________Y
|
|
245416
|
+
<---AY
|
|
245417
|
+
|
|
245418
|
+
When the chamfer face is created, it needs to have a sliver face "inside the edge" -- something in the space here
|
|
245419
|
+
|
|
245420
|
+
AX------>
|
|
245421
|
+
_____________________________________________________________________
|
|
245422
|
+
/ \
|
|
245423
|
+
X Y
|
|
245424
|
+
\_____________________________________________________________________/
|
|
245425
|
+
<---AY
|
|
245426
|
+
|
|
245427
|
+
The chamfer face will have a plane normal is the average of the two faces' plane normals.
|
|
245428
|
+
|
|
245429
|
+
The creation sequence for the chamfer face puts a slit "inside the edge" as above HalfEdges AX and AY remain as parts
|
|
245430
|
+
of their respective face loops. In addition, at each end a singleton edge "sling" face is inserted at each
|
|
245431
|
+
end of the sliver face.
|
|
245432
|
+
|
|
245433
|
+
The sequence is:
|
|
245434
|
+
|
|
245435
|
+
STEP 1: splitEdgeCreateSliver creates the sliver face with 2 half edges DX and DY
|
|
245436
|
+
STEP 2: splitEdge (with undefined as the "prior" edge) creates a sling with HalfEdge CX "inside" and BX "outside".
|
|
245437
|
+
(The sling face is not yet attached to X -- briefly floating in space)
|
|
245438
|
+
STEP 3: pinch of HalfEdges BX and DX inserts the sling face "inside" the slit face at the X end.
|
|
245439
|
+
|
|
245440
|
+
Steps 2 and 3 are executed from each end. Due to the symmetric structure, a 2-pass loop can apply the logic at each end without distinct names in code.
|
|
245441
|
+
|
|
245442
|
+
AX------>
|
|
245443
|
+
_______________________________________________________________
|
|
245444
|
+
/ <---DY \
|
|
245445
|
+
/ \
|
|
245446
|
+
/ BX---> \
|
|
245447
|
+
/ _______________ _______________ \
|
|
245448
|
+
| / \ / <----CY \ |
|
|
245449
|
+
|/ \ / \|
|
|
245450
|
+
X | | Y
|
|
245451
|
+
|\ CX---> / \ /|
|
|
245452
|
+
| \_______________/ \_______________/ |
|
|
245453
|
+
\ <---BY /
|
|
245454
|
+
\ /
|
|
245455
|
+
\ DX---> /
|
|
245456
|
+
\ ______________________________________________________________/
|
|
245457
|
+
<---AY
|
|
245458
|
+
|
|
245459
|
+
During the construction, the letters ABCD are used as above, but with prefixes emphasizing their role
|
|
245460
|
+
outsideAX, outsideAY
|
|
245461
|
+
slingB, slingC, sliverD
|
|
245462
|
+
|
|
245463
|
+
The "inside" sling faces (CX and CY) each have their own FacetOffsetProperties and SectorOffsetProperties.
|
|
245464
|
+
The sliver face has its own FacetOffsetProperties which are referenced by DX, BY, DY, BX.
|
|
245465
|
+
Each of those 4 has its own SectorOffSetProperties.
|
|
245466
|
+
|
|
245467
|
+
Important properties during offset construction:
|
|
245468
|
+
1) the original graph always has original topology and coordinates
|
|
245469
|
+
2) Each face of the original graph has a FacetOffsetProperties with a representative point and a normal. These are unchanged during the computation.
|
|
245470
|
+
3) Each node has its own SectorOffsetProperties with a coordinate and normal independent of the parent node.
|
|
245471
|
+
3.1 The first offset coordinates in each node are directly offset by face normal.
|
|
245472
|
+
3.2 This creates mismatch across edges and around vertices.
|
|
245473
|
+
3.3 Various sweeps "around each vertex" try to do intersections among appropriate offset planes to find
|
|
245474
|
+
common coordinates in place of the initial mismatches.
|
|
245475
|
+
4) The independence of all the sectors allows the offset construction to fix things up in any order it chooses.
|
|
245476
|
+
5) During the construction, the xyz in SectorOffsetProperties around a single vertex do NOT have to match.
|
|
245477
|
+
6) At output time, there are three sweeps:
|
|
245478
|
+
6.1: By face: Go around the face and output a facet with the coordinates in the various sectors.
|
|
245479
|
+
6.2: By edge: For each edge, if the sector xyz match across both ends output nothing. If not, output a triangle or quad
|
|
245480
|
+
6.3: By vertex: At each vertex, if all vertex coordinates match output nothing. Otherwise output a facet with all the coordinates.
|
|
245481
|
+
*/
|
|
245482
|
+
class OffsetMeshContext {
|
|
245483
|
+
constructor(basePolyface, baseGraph, options) {
|
|
245484
|
+
this._basePolyface = basePolyface;
|
|
245485
|
+
this._baseGraph = baseGraph;
|
|
245486
|
+
this._breakMaskA = baseGraph.grabMask();
|
|
245487
|
+
this._breakMaskB = baseGraph.grabMask();
|
|
245488
|
+
this._insideOfChamferFace = baseGraph.grabMask();
|
|
245489
|
+
this._outsideOfChamferFace = baseGraph.grabMask();
|
|
245490
|
+
this._insideChamferSling = baseGraph.grabMask();
|
|
245491
|
+
this._outsideEndOfChamferFace = baseGraph.grabMask();
|
|
245492
|
+
this._exteriorMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR;
|
|
245493
|
+
this._offsetCoordinatesReassigned = baseGraph.grabMask();
|
|
245494
|
+
this._smoothRadiansBetweenNormals = options.smoothSingleAngleBetweenNormals.radians;
|
|
245495
|
+
this._chamferTurnRadians = options.chamferAngleBetweenNormals.radians;
|
|
245496
|
+
this._smoothAccumulatedRadiansBetweenNormals = options.smoothAccumulatedAngleBetweenNormals.radians;
|
|
245497
|
+
}
|
|
245498
|
+
/** "Exterior" side of a bare edge of the mesh */
|
|
245499
|
+
get exteriorMask() { return this._exteriorMask; }
|
|
245500
|
+
/** "First" sector of a smooth sequence. */
|
|
245501
|
+
get breakMaskA() { return this._breakMaskA; }
|
|
245502
|
+
/** "Last" sector of a smooth sequence. */
|
|
245503
|
+
get breakMaskB() { return this._breakMaskB; }
|
|
245504
|
+
/** This edge is on a chamfered face, and along the original edge */
|
|
245505
|
+
get insideOfChamferFace() { return this._insideOfChamferFace; }
|
|
245506
|
+
/** This is the original edge of a chamfer face */
|
|
245507
|
+
get outsideOfChamferFace() { return this._outsideOfChamferFace; }
|
|
245508
|
+
/** This edge is on a chamfered face, and at the end -- other side may be a sling */
|
|
245509
|
+
get insideChamferSling() { return this._insideChamferSling; }
|
|
245510
|
+
/** This is the outside of the end of a chamfer face -- i.e. the inside of a new face-at-vertex */
|
|
245511
|
+
get outsideEndOfChamferFace() { return this._outsideEndOfChamferFace; }
|
|
245512
|
+
// At each node . .
|
|
245513
|
+
// * Find the sector data
|
|
245514
|
+
// * recompute the sector point using node XYZ and sectorData normal.
|
|
245515
|
+
applyFaceNormalOffsetsToSectorData(distance) {
|
|
245516
|
+
this._baseGraph.announceNodes((_graph, node) => {
|
|
245517
|
+
const sectorData = node.edgeTag;
|
|
245518
|
+
if (sectorData !== undefined) {
|
|
245519
|
+
sectorData.setOffsetPointAtDistanceAtHalfEdge(node, distance);
|
|
245520
|
+
}
|
|
245521
|
+
return true;
|
|
245522
|
+
});
|
|
245523
|
+
}
|
|
245524
|
+
/**
|
|
245525
|
+
* * build a mesh offset by given distance.
|
|
245526
|
+
* * output the mesh to the given builder.
|
|
245527
|
+
* @param basePolyface original mesh
|
|
245528
|
+
* @param builder polyface builder to receive the new mesh.
|
|
245529
|
+
* @param distance signed offset distance.
|
|
245530
|
+
*/
|
|
245531
|
+
static buildOffsetMeshWithEdgeChamfers(basePolyface, builder, distance, options) {
|
|
245532
|
+
const baseGraph = this.buildBaseGraph(basePolyface);
|
|
245533
|
+
if (baseGraph !== undefined) {
|
|
245534
|
+
const offsetBuilder = new OffsetMeshContext(basePolyface, baseGraph, options);
|
|
245535
|
+
offsetBuilder.applyFaceNormalOffsetsToSectorData(distance);
|
|
245536
|
+
if (OffsetMeshContext.graphDebugFunction !== undefined)
|
|
245537
|
+
OffsetMeshContext.graphDebugFunction("BaseGraph", baseGraph, offsetBuilder._breakMaskA, offsetBuilder._breakMaskB);
|
|
245538
|
+
const outputSelector = options.outputSelector ? options.outputSelector : {
|
|
245539
|
+
outputOffsetsFromFaces: true,
|
|
245540
|
+
outputOffsetsFromEdges: true,
|
|
245541
|
+
outputOffsetsFromVertices: true,
|
|
245542
|
+
};
|
|
245543
|
+
if (isDefinedAndTrue(outputSelector.outputOffsetsFromFacesBeforeChamfers))
|
|
245544
|
+
offsetBuilder.announceFacetsWithSectorCoordinatesAroundFaces(builder);
|
|
245545
|
+
offsetBuilder.addChamferTopologyToAllEdges(options, distance);
|
|
245546
|
+
offsetBuilder.computeOffsetFacetIntersections(distance);
|
|
245547
|
+
if (OffsetMeshContext.graphDebugFunction !== undefined)
|
|
245548
|
+
OffsetMeshContext.graphDebugFunction("after computeEdgeChamfers", baseGraph, offsetBuilder._breakMaskA, offsetBuilder._breakMaskB);
|
|
245549
|
+
if (isDefinedAndTrue(outputSelector.outputOffsetsFromFaces))
|
|
245550
|
+
offsetBuilder.announceFacetsWithSectorCoordinatesAroundFaces(builder);
|
|
245551
|
+
if (isDefinedAndTrue(outputSelector.outputOffsetsFromEdges))
|
|
245552
|
+
offsetBuilder.announceFacetsWithSectorCoordinatesAroundEdges(builder);
|
|
245553
|
+
if (isDefinedAndTrue(outputSelector.outputOffsetsFromVertices))
|
|
245554
|
+
offsetBuilder.announceFacetsWithSectorCoordinatesAroundVertices(builder);
|
|
245555
|
+
}
|
|
245556
|
+
}
|
|
245557
|
+
/**
|
|
245558
|
+
* For each face of the graph, shift vertices by offsetDistance and emit to the builder as a facet
|
|
245559
|
+
* @param polyfaceBuilder
|
|
245560
|
+
*/
|
|
245561
|
+
announceSimpleOffsetFromFaces(polyfaceBuilder, offsetDistance) {
|
|
245562
|
+
const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
|
|
245563
|
+
const xyz = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create(); // reused at each point around each facet.
|
|
245564
|
+
const uvw = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reused once per facet
|
|
245565
|
+
const announceNodeAroundFace = (node) => {
|
|
245566
|
+
node.getPoint3d(xyz);
|
|
245567
|
+
xyz.addInPlace(uvw);
|
|
245568
|
+
xyzLoop.push(xyz);
|
|
245569
|
+
return 0;
|
|
245570
|
+
};
|
|
245571
|
+
this._baseGraph.announceFaceLoops((_graph, seed) => {
|
|
245572
|
+
if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR)) {
|
|
245573
|
+
const facetProperties = seed.faceTag;
|
|
245574
|
+
uvw.setFromVector3d(facetProperties.facetNormal.direction);
|
|
245575
|
+
uvw.scaleInPlace(offsetDistance);
|
|
245576
|
+
xyzLoop.length = 0;
|
|
245577
|
+
seed.sumAroundFace(announceNodeAroundFace);
|
|
245578
|
+
polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
|
|
245579
|
+
}
|
|
245580
|
+
return true;
|
|
245581
|
+
});
|
|
245582
|
+
}
|
|
245583
|
+
/**
|
|
245584
|
+
* For each face of the graph, output the xyz of the sector data
|
|
245585
|
+
* @param polyfaceBuilder
|
|
245586
|
+
*/
|
|
245587
|
+
announceFacetsWithSectorCoordinatesAroundFaces(polyfaceBuilder) {
|
|
245588
|
+
const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
|
|
245589
|
+
// For face loop visits .. get the point from the sector data.
|
|
245590
|
+
const announceNodeAroundFace = (node) => {
|
|
245591
|
+
const sectorData = node.edgeTag;
|
|
245592
|
+
if (sectorData !== undefined) {
|
|
245593
|
+
xyzLoop.push(sectorData.xyz);
|
|
245594
|
+
}
|
|
245595
|
+
return 0;
|
|
245596
|
+
};
|
|
245597
|
+
this._baseGraph.announceFaceLoops((_graph, seed) => {
|
|
245598
|
+
if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR)) {
|
|
245599
|
+
xyzLoop.length = 0;
|
|
245600
|
+
seed.sumAroundFace(announceNodeAroundFace);
|
|
245601
|
+
if (xyzLoop.length > 2)
|
|
245602
|
+
polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
|
|
245603
|
+
}
|
|
245604
|
+
return true;
|
|
245605
|
+
});
|
|
245606
|
+
}
|
|
245607
|
+
countBits(mask) {
|
|
245608
|
+
let n = 0;
|
|
245609
|
+
let mask1 = mask;
|
|
245610
|
+
while (mask1 !== 0) {
|
|
245611
|
+
if (mask1 & 0x01)
|
|
245612
|
+
n++;
|
|
245613
|
+
mask1 = mask1 >> 1;
|
|
245614
|
+
}
|
|
245615
|
+
return n;
|
|
245616
|
+
}
|
|
245617
|
+
/**
|
|
245618
|
+
* For each edge of the graph . .
|
|
245619
|
+
* * Collect coordinates in 4 sectors going around the edge
|
|
245620
|
+
* * Compress with tight tolerance so adjacent sectors with clean point match reduce to a single point.
|
|
245621
|
+
* * Emit as a facet.
|
|
245622
|
+
* @param polyfaceBuilder
|
|
245623
|
+
*/
|
|
245624
|
+
announceFacetsWithSectorCoordinatesAroundEdges(polyfaceBuilder) {
|
|
245625
|
+
const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
|
|
245626
|
+
const primaryCompressionTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance;
|
|
245627
|
+
const allMasksForEdgesToIgnore = this._exteriorMask
|
|
245628
|
+
| this._outsideEndOfChamferFace
|
|
245629
|
+
| this._outsideOfChamferFace
|
|
245630
|
+
| this._insideOfChamferFace
|
|
245631
|
+
| this._insideChamferSling;
|
|
245632
|
+
this._baseGraph.announceEdges((_graph, nodeA) => {
|
|
245633
|
+
// This starts by looking for EXTERIOR on both sides ...
|
|
245634
|
+
if (nodeA.findMaskAroundEdge(this._exteriorMask) !== undefined) {
|
|
245635
|
+
return true;
|
|
245636
|
+
}
|
|
245637
|
+
else if (!nodeA.isMaskSet(allMasksForEdgesToIgnore)) { // By design, we believe that these two test for allMasksForEdgesToIgnore condition would catch the EXTERIOR case above
|
|
245638
|
+
const nodeB = nodeA.faceSuccessor;
|
|
245639
|
+
const nodeC = nodeA.edgeMate;
|
|
245640
|
+
if (!nodeC.isMaskSet(allMasksForEdgesToIgnore)) {
|
|
245641
|
+
const nodeD = nodeC.faceSuccessor;
|
|
245642
|
+
xyzLoop.clear();
|
|
245643
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(nodeA, undefined, xyzLoop);
|
|
245644
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(nodeB, undefined, xyzLoop);
|
|
245645
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(nodeC, undefined, xyzLoop);
|
|
245646
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(nodeD, undefined, xyzLoop);
|
|
245647
|
+
_geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__.PolylineCompressionContext.compressInPlaceByShortEdgeLength(xyzLoop, primaryCompressionTolerance);
|
|
245648
|
+
if (xyzLoop.length > 2) {
|
|
245649
|
+
polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
|
|
245650
|
+
}
|
|
245651
|
+
}
|
|
245652
|
+
}
|
|
245653
|
+
else {
|
|
245654
|
+
return true;
|
|
245655
|
+
}
|
|
245656
|
+
return true;
|
|
245657
|
+
});
|
|
245658
|
+
}
|
|
245659
|
+
getCoordinateString(node, showXYZ = true, showFaceSuccessorXYZ = false) {
|
|
245660
|
+
if (showXYZ) {
|
|
245661
|
+
if (showFaceSuccessorXYZ) {
|
|
245662
|
+
return `${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node)} ==> ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node.faceSuccessor)}`;
|
|
245663
|
+
}
|
|
245664
|
+
else {
|
|
245665
|
+
return `${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node)}`;
|
|
245666
|
+
}
|
|
245667
|
+
}
|
|
245668
|
+
else {
|
|
245669
|
+
if (showFaceSuccessorXYZ) {
|
|
245670
|
+
return `==> ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node.faceSuccessor)}`;
|
|
245671
|
+
}
|
|
245672
|
+
else {
|
|
245673
|
+
return "";
|
|
245674
|
+
}
|
|
245675
|
+
}
|
|
245676
|
+
}
|
|
245677
|
+
inspectMasks(node, showXYZ = true, showFaceSuccessorXYZ = false) {
|
|
245678
|
+
const s = "[";
|
|
245679
|
+
const v = s.concat(node.id.toString(), node.isMaskSet(this._exteriorMask) ? "X" : "", node.isMaskSet(this.breakMaskA) ? "A" : "", node.isMaskSet(this.breakMaskB) ? "B" : "", node.isMaskSet(this.insideChamferSling) ? "(sling)" : "", node.isMaskSet(this.insideOfChamferFace) ? "(in chamfer)" : "", node.isMaskSet(this.outsideEndOfChamferFace) ? "(@sling)" : "", node.isMaskSet(this.outsideOfChamferFace) ? "(@chamfer)" : "", this.getCoordinateString(node, showXYZ, showFaceSuccessorXYZ), "]");
|
|
245680
|
+
return v;
|
|
245681
|
+
}
|
|
245682
|
+
/**
|
|
245683
|
+
* For each face of the graph, output the xyz of the sector data
|
|
245684
|
+
* @param polyfaceBuilder
|
|
245685
|
+
*/
|
|
245686
|
+
announceFacetsWithSectorCoordinatesAroundVertices(polyfaceBuilder) {
|
|
245687
|
+
const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
|
|
245688
|
+
const primaryCompressionTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance;
|
|
245689
|
+
this._baseGraph.announceVertexLoops((_graph, seed) => {
|
|
245690
|
+
if (!seed.findMaskAroundVertex(this._exteriorMask)) {
|
|
245691
|
+
xyzLoop.length = 0;
|
|
245692
|
+
seed.sumAroundVertex((node) => {
|
|
245693
|
+
if (!node.isMaskSet(this._insideChamferSling))
|
|
245694
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(node, undefined, xyzLoop);
|
|
245695
|
+
return 0.0;
|
|
245696
|
+
});
|
|
245697
|
+
_geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__.PolylineCompressionContext.compressInPlaceByShortEdgeLength(xyzLoop, primaryCompressionTolerance);
|
|
245698
|
+
if (xyzLoop.length > 2) {
|
|
245699
|
+
polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
|
|
245700
|
+
}
|
|
245701
|
+
}
|
|
245702
|
+
return true;
|
|
245703
|
+
});
|
|
245704
|
+
}
|
|
245705
|
+
/**
|
|
245706
|
+
* * Exterior half edges have HalfEdgeMask.EXTERIOR
|
|
245707
|
+
* * All interior half edge around a facet have facetTag pointing to a facetProperties object for that facet.
|
|
245708
|
+
* * the facetOffsetProperties object has the simple facet normal.
|
|
245709
|
+
* * Each half edge has edgeTag pointing to to a sectorOffsetProperties object
|
|
245710
|
+
* * the sectorOffsetProperties has a copy of the facet normal.
|
|
245711
|
+
* @param polyface
|
|
245712
|
+
* @returns graph
|
|
245713
|
+
*/
|
|
245714
|
+
static buildBaseGraph(polyface) {
|
|
245715
|
+
const graphBuilder = new _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_5__.HalfEdgeGraphFromIndexedLoopsContext();
|
|
245716
|
+
const visitor = polyface.createVisitor();
|
|
245717
|
+
const xyzA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
|
|
245718
|
+
const xyzB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
|
|
245719
|
+
for (visitor.reset(); visitor.moveToNextFacet();) {
|
|
245720
|
+
const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_6__.PolygonOps.centroidAreaNormal(visitor.point);
|
|
245721
|
+
if (normal !== undefined) {
|
|
245722
|
+
const edgeA = graphBuilder.insertLoop(visitor.pointIndex, (insideHalfEdge) => {
|
|
245723
|
+
const mate = insideHalfEdge.edgeMate;
|
|
245724
|
+
polyface.data.getPoint(insideHalfEdge.i, xyzA);
|
|
245725
|
+
insideHalfEdge.setXYZ(xyzA);
|
|
245726
|
+
polyface.data.getPoint(mate.i, xyzB);
|
|
245727
|
+
mate.setXYZ(xyzB);
|
|
245728
|
+
});
|
|
245729
|
+
const facetProperties = new FacetOffsetProperties(visitor.currentReadIndex(), normal);
|
|
245730
|
+
if (edgeA !== undefined) {
|
|
245731
|
+
edgeA.sumAroundFace((edgeB) => {
|
|
245732
|
+
edgeB.faceTag = facetProperties;
|
|
245733
|
+
edgeB.edgeTag = new SectorOffsetProperties(normal.direction.clone(), edgeB.getPoint3d());
|
|
245734
|
+
return 0;
|
|
245735
|
+
});
|
|
245736
|
+
}
|
|
245737
|
+
}
|
|
245738
|
+
}
|
|
245739
|
+
return graphBuilder.graph;
|
|
245740
|
+
}
|
|
245741
|
+
setOffsetAtDistanceAroundVertex(vertexSeed, distance, ignoreChamfers = false) {
|
|
245742
|
+
vertexSeed.sumAroundVertex((nodeAroundVertex) => {
|
|
245743
|
+
const props = nodeAroundVertex.edgeTag;
|
|
245744
|
+
if (props !== undefined) {
|
|
245745
|
+
if (ignoreChamfers && this.isInsideChamferOrSling(vertexSeed)) {
|
|
245746
|
+
// SKIP !!
|
|
245747
|
+
}
|
|
245748
|
+
else {
|
|
245749
|
+
props.setOffsetPointAtDistanceAtHalfEdge(nodeAroundVertex, distance);
|
|
245750
|
+
}
|
|
245751
|
+
}
|
|
245752
|
+
return 0.0;
|
|
245753
|
+
});
|
|
245754
|
+
}
|
|
245755
|
+
setOffsetXYAndZAroundVertex(vertexSeed, xyz) {
|
|
245756
|
+
vertexSeed.sumAroundVertex((nodeAroundVertex) => {
|
|
245757
|
+
const props = nodeAroundVertex.edgeTag;
|
|
245758
|
+
if (props !== undefined) {
|
|
245759
|
+
props.setXYAndZ(xyz);
|
|
245760
|
+
nodeAroundVertex.setMask(this._offsetCoordinatesReassigned);
|
|
245761
|
+
}
|
|
245762
|
+
return 0.0;
|
|
245763
|
+
});
|
|
245764
|
+
}
|
|
245765
|
+
/**
|
|
245766
|
+
* * start at vertexSeed.
|
|
245767
|
+
* * set the offset point at up to (and including) one with (a) this._breakMaskB or (b) this._exteriorMask
|
|
245768
|
+
* *
|
|
245769
|
+
* @param vertexSeed first node to mark.
|
|
245770
|
+
* @param f function to call to announce each node and its sector properties.
|
|
245771
|
+
* @returns number of nodes marked.
|
|
245772
|
+
*/
|
|
245773
|
+
announceNodeAndSectorPropertiesInSmoothSector(vertexSeed, f) {
|
|
245774
|
+
let n = 0;
|
|
245775
|
+
for (let currentNode = vertexSeed;; currentNode = currentNode.vertexSuccessor) {
|
|
245776
|
+
const props = currentNode.edgeTag;
|
|
245777
|
+
if (props !== undefined) {
|
|
245778
|
+
f(currentNode, props);
|
|
245779
|
+
n++;
|
|
245780
|
+
}
|
|
245781
|
+
if (currentNode.isMaskSet(this._breakMaskB))
|
|
245782
|
+
return n;
|
|
245783
|
+
// REMARK: these additional exit conditions should not happen if (a) the graph is properly marked and (b) the start node is not exterior.
|
|
245784
|
+
if (currentNode.isMaskSet(this._exteriorMask))
|
|
245785
|
+
return n;
|
|
245786
|
+
if (currentNode === vertexSeed && n === 0)
|
|
245787
|
+
return n;
|
|
245788
|
+
}
|
|
245789
|
+
}
|
|
245790
|
+
computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data) {
|
|
245791
|
+
data.clear();
|
|
245792
|
+
const inactiveNodeMask = this._exteriorMask | this._insideChamferSling;
|
|
245793
|
+
vertexSeed.sumAroundVertex((node) => {
|
|
245794
|
+
const sectorData = node.edgeTag;
|
|
245795
|
+
if (sectorData)
|
|
245796
|
+
data.accumulateNormal(node, sectorData.normal, inactiveNodeMask);
|
|
245797
|
+
return 0.0;
|
|
245798
|
+
});
|
|
245799
|
+
if (!data.finishNormalAveraging()) {
|
|
245800
|
+
return undefined;
|
|
245801
|
+
}
|
|
245802
|
+
vertexSeed.sumAroundVertex((node) => {
|
|
245803
|
+
const sectorData = node.edgeTag;
|
|
245804
|
+
if (sectorData)
|
|
245805
|
+
data.recordDeviation(sectorData.normal, !node.isMaskSet(inactiveNodeMask));
|
|
245806
|
+
return 0.0;
|
|
245807
|
+
});
|
|
245808
|
+
return data.maxDeviationRadians;
|
|
245809
|
+
}
|
|
245810
|
+
assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedDeviationRadians, data, distance) {
|
|
245811
|
+
const maxDeviationRadians = this.computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data);
|
|
245812
|
+
if (OffsetMeshContext.stringDebugFunction) {
|
|
245813
|
+
OffsetMeshContext.stringDebugFunction(`XYZ ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(vertexSeed)} Average Normal ${data.averageNormal.toJSON()}`);
|
|
245814
|
+
OffsetMeshContext.stringDebugFunction(` angle ratio ${data.radiansSum / (2 * Math.PI)} maxDeviation ${data.maxDeviationRadiansFromAverage}`);
|
|
245815
|
+
}
|
|
245816
|
+
if (maxDeviationRadians !== undefined && maxDeviationRadians <= maxAllowedDeviationRadians) {
|
|
245817
|
+
vertexSeed.sumAroundVertex((node) => {
|
|
245818
|
+
SectorOffsetProperties.setNormalAtHalfEdge(node, data.averageNormal, distance);
|
|
245819
|
+
return 0;
|
|
245820
|
+
});
|
|
245821
|
+
return true;
|
|
245822
|
+
}
|
|
245823
|
+
return false;
|
|
245824
|
+
}
|
|
245825
|
+
/** Search around a vertex for a sector which has a different normal from its vertexPredecessor.
|
|
245826
|
+
* * The seed will be the first candidate considered
|
|
245827
|
+
*/
|
|
245828
|
+
markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed) {
|
|
245829
|
+
vertexSeed.clearMaskAroundVertex(this._breakMaskA);
|
|
245830
|
+
vertexSeed.clearMaskAroundVertex(this._breakMaskB);
|
|
245831
|
+
const smoothSingleSmoothRadiansBetweenNormals = this._smoothRadiansBetweenNormals;
|
|
245832
|
+
const accumulatedRadiansBetweenNormals = this._smoothAccumulatedRadiansBetweenNormals;
|
|
245833
|
+
// Step 1: Examine the edge between nodeA and the sector on its vertex predecessor side. This (alone) determines single angle breaks.
|
|
245834
|
+
let numBreaks = 0;
|
|
245835
|
+
let nodeP = vertexSeed;
|
|
245836
|
+
let _numSmooth = 0;
|
|
245837
|
+
do {
|
|
245838
|
+
const nodeQ = nodeP.edgeMate;
|
|
245839
|
+
const nodeR = nodeQ.faceSuccessor; // same as nodeA.vertexPredecessor
|
|
245840
|
+
if (nodeP.isMaskSet(this._exteriorMask)) {
|
|
245841
|
+
if (!nodeQ.isMaskSet(this._exteriorMask)) {
|
|
245842
|
+
nodeR.setMask(this._breakMaskB);
|
|
245843
|
+
numBreaks++;
|
|
245844
|
+
}
|
|
245845
|
+
}
|
|
245846
|
+
else {
|
|
245847
|
+
if (nodeP.isMaskSet(this._outsideOfChamferFace)) {
|
|
245848
|
+
nodeP.setMask(this._breakMaskA);
|
|
245849
|
+
}
|
|
245850
|
+
else if (nodeP.isMaskSet(this._outsideEndOfChamferFace)) {
|
|
245851
|
+
nodeP.setMask(this._breakMaskA);
|
|
245852
|
+
nodeP.setMask(this._breakMaskB);
|
|
245853
|
+
}
|
|
245854
|
+
else if (nodeP.isMaskSet(this._insideChamferSling)) {
|
|
245855
|
+
// This is the sling. It's normal is along edge -- not really a break.
|
|
245856
|
+
}
|
|
245857
|
+
else if (nodeP.isMaskSet(this._insideOfChamferFace)) {
|
|
245858
|
+
nodeP.setMask(this._breakMaskA);
|
|
245859
|
+
nodeP.setMask(this._breakMaskB);
|
|
245860
|
+
nodeR.setMask(this._breakMaskB);
|
|
245861
|
+
}
|
|
245862
|
+
else if (nodeQ.isMaskSet(this._exteriorMask)) {
|
|
245863
|
+
numBreaks++;
|
|
245864
|
+
nodeP.setMask(this._breakMaskA);
|
|
245865
|
+
}
|
|
245866
|
+
else if (!SectorOffsetProperties.almostEqualNormals(nodeP.edgeTag, nodeR.edgeTag, smoothSingleSmoothRadiansBetweenNormals)) {
|
|
245867
|
+
nodeP.setMask(this._breakMaskA);
|
|
245868
|
+
numBreaks++;
|
|
245869
|
+
nodeR.setMask(this._breakMaskB);
|
|
245870
|
+
}
|
|
245871
|
+
else {
|
|
245872
|
+
_numSmooth++;
|
|
245873
|
+
}
|
|
245874
|
+
}
|
|
245875
|
+
nodeP = nodeP.vertexSuccessor;
|
|
245876
|
+
} while (nodeP !== vertexSeed);
|
|
245877
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
245878
|
+
OffsetMeshContext.stringDebugFunction(` numSkip ${_numSmooth} `);
|
|
245879
|
+
if (numBreaks === 0) {
|
|
245880
|
+
// make the first vertex a break so subsequent searches have a place to start
|
|
245881
|
+
vertexSeed.setMask(this._breakMaskA);
|
|
245882
|
+
vertexSeed.vertexPredecessor.setMask(this._breakMaskB);
|
|
245883
|
+
numBreaks = 1;
|
|
245884
|
+
}
|
|
245885
|
+
// Step 2: At each single break, sweep forward to its closing breakB. Insert breaks at accumulated angles.
|
|
245886
|
+
// (minor TODO: for the insertion case, try to split more equally.)
|
|
245887
|
+
const nodeAStart = nodeP.findMaskAroundVertex(this._breakMaskA);
|
|
245888
|
+
if (nodeAStart !== undefined) {
|
|
245889
|
+
nodeP = nodeAStart;
|
|
245890
|
+
do {
|
|
245891
|
+
if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) {
|
|
245892
|
+
let accumulatedRadians = 0.0;
|
|
245893
|
+
do {
|
|
245894
|
+
const nodeB = nodeP.vertexSuccessor;
|
|
245895
|
+
accumulatedRadians += SectorOffsetProperties.radiansBetweenNormals(nodeP.edgeTag, nodeB.edgeTag);
|
|
245896
|
+
if (accumulatedRadians > accumulatedRadiansBetweenNormals) {
|
|
245897
|
+
nodeP.setMask(this._breakMaskB);
|
|
245898
|
+
nodeB.setMask(this._breakMaskA);
|
|
245899
|
+
numBreaks++;
|
|
245900
|
+
accumulatedRadians = 0.0;
|
|
245901
|
+
}
|
|
245902
|
+
nodeP = nodeB;
|
|
245903
|
+
} while (!nodeP.isMaskSet(this._breakMaskB));
|
|
245904
|
+
}
|
|
245905
|
+
else {
|
|
245906
|
+
nodeP = nodeP.vertexSuccessor;
|
|
245907
|
+
}
|
|
245908
|
+
} while (nodeP !== nodeAStart);
|
|
245909
|
+
}
|
|
245910
|
+
if (numBreaks > 0 && nodeAStart !== undefined) {
|
|
245911
|
+
// In each compound sector, accumulate and install average normal.
|
|
245912
|
+
nodeP = nodeAStart;
|
|
245913
|
+
const averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
|
|
245914
|
+
const edgeVectorU = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
|
|
245915
|
+
const edgeVectorV = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
|
|
245916
|
+
averageNormal.setZero();
|
|
245917
|
+
do {
|
|
245918
|
+
if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) {
|
|
245919
|
+
let nodeQ = nodeP;
|
|
245920
|
+
averageNormal.setZero();
|
|
245921
|
+
for (;;) {
|
|
245922
|
+
nodeQ.vectorToFaceSuccessor(edgeVectorU);
|
|
245923
|
+
nodeQ.vectorToFacePredecessor(edgeVectorV);
|
|
245924
|
+
let singleSectorRadians = edgeVectorU.signedRadiansTo(edgeVectorV, nodeQ.faceTag.facetNormal.direction);
|
|
245925
|
+
if (singleSectorRadians < 0.0)
|
|
245926
|
+
singleSectorRadians += Math.PI * 2;
|
|
245927
|
+
SectorOffsetProperties.accumulateScaledNormalAtHalfEdge(nodeQ, singleSectorRadians, averageNormal);
|
|
245928
|
+
if (nodeQ.isMaskSet(this._breakMaskB))
|
|
245929
|
+
break;
|
|
245930
|
+
nodeQ = nodeQ.vertexSuccessor;
|
|
245931
|
+
}
|
|
245932
|
+
if (averageNormal.normalizeInPlace()) {
|
|
245933
|
+
nodeQ = nodeP;
|
|
245934
|
+
for (;;) {
|
|
245935
|
+
SectorOffsetProperties.setNormalAtHalfEdge(nodeQ, averageNormal);
|
|
245936
|
+
if (nodeQ.isMaskSet(this._breakMaskB))
|
|
245937
|
+
break;
|
|
245938
|
+
nodeQ = nodeQ.vertexSuccessor;
|
|
245939
|
+
}
|
|
245940
|
+
}
|
|
245941
|
+
}
|
|
245942
|
+
nodeP = nodeP.vertexSuccessor;
|
|
245943
|
+
} while (nodeP !== nodeAStart);
|
|
245944
|
+
}
|
|
245945
|
+
}
|
|
245946
|
+
/** Compute the point of intersection of the planes in the sectors of 3 half edges */
|
|
245947
|
+
compute3SectorIntersection(nodeA, nodeB, nodeC, result) {
|
|
245948
|
+
const sectorA = nodeA.edgeTag;
|
|
245949
|
+
const sectorB = nodeB.edgeTag;
|
|
245950
|
+
const sectorC = nodeC.edgeTag;
|
|
245951
|
+
const vector = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorC.xyz, sectorC.normal, result);
|
|
245952
|
+
return vector;
|
|
245953
|
+
}
|
|
245954
|
+
/** Compute the point of intersection of the planes in the sectors of 3 half edges */
|
|
245955
|
+
compute3SectorIntersectionDebug(nodeA, nodeB, nodeC, result) {
|
|
245956
|
+
const sectorA = nodeA.edgeTag;
|
|
245957
|
+
const sectorB = nodeB.edgeTag;
|
|
245958
|
+
const sectorC = nodeC.edgeTag;
|
|
245959
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
245960
|
+
OffsetMeshContext.stringDebugFunction(`compute3${this.inspectMasks(nodeA)}${this.inspectMasks(nodeB)}${this.inspectMasks(nodeC)} `);
|
|
245961
|
+
for (const sector of [sectorA, sectorB, sectorC])
|
|
245962
|
+
emitSector(sector);
|
|
245963
|
+
}
|
|
245964
|
+
const vector = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorC.xyz, sectorC.normal, result);
|
|
245965
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
245966
|
+
if (vector === undefined)
|
|
245967
|
+
OffsetMeshContext.stringDebugFunction(" NO INTERSECTION");
|
|
245968
|
+
else
|
|
245969
|
+
OffsetMeshContext.stringDebugFunction(` ComputedVector ${vector.x},${vector.y},${vector.z} `);
|
|
245970
|
+
}
|
|
245971
|
+
return vector;
|
|
245972
|
+
}
|
|
245973
|
+
/** Compute the point of intersection of the planes in the sectors of 2 half edges, using cross product of their normals to resolve */
|
|
245974
|
+
compute2SectorIntersection(nodeA, nodeB, result) {
|
|
245975
|
+
const sectorA = nodeA.edgeTag;
|
|
245976
|
+
const sectorB = nodeB.edgeTag;
|
|
245977
|
+
const normalC = sectorA.normal.crossProduct(sectorB.normal);
|
|
245978
|
+
return _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorB.xyz, normalC, result);
|
|
245979
|
+
}
|
|
245980
|
+
/**
|
|
245981
|
+
* * at input, graph has all original faces and edges
|
|
245982
|
+
* * each sector points to a faceProperties with original facet normal
|
|
245983
|
+
* * at exit:
|
|
245984
|
+
* * new "chamfer faces" are added outside of edges with angle between normal sin excess of options.chamferTurnAngleBetweenNormals
|
|
245985
|
+
* * the original edge is split along its length to create space
|
|
245986
|
+
* * one edge "along" each direction inside the slit.
|
|
245987
|
+
* * a sling edge at each end of the slit.
|
|
245988
|
+
* * outside of the sling is part of the slit face loop.
|
|
245989
|
+
* * inside is a single-node face
|
|
245990
|
+
* * thus the slit itself has 4 nodes.
|
|
245991
|
+
* * the two nodes at each end can thus contain the two distinct points at that end of the chamfer.
|
|
245992
|
+
* * all 4 nodes of the slit face point to a new FacetOffsetProperties with the average normal.
|
|
245993
|
+
* * the inside of each sling face has
|
|
245994
|
+
* * original vertex coordinates in the node
|
|
245995
|
+
* * face properties with a normal pointing outward from that end of the original edge -- hence define a plane that can clip the chamfer
|
|
245996
|
+
* * the two points at each end of the chamfer are computed as the intersection of
|
|
245997
|
+
* * chamfer plane
|
|
245998
|
+
* * sling plane
|
|
245999
|
+
* * adjacent plane of the face on the other side of the edge being chamfered.
|
|
246000
|
+
* @param distance distance to offset. The sign of this is important in the chamfer construction.
|
|
246001
|
+
*/
|
|
246002
|
+
addChamferTopologyToAllEdges(options, distance) {
|
|
246003
|
+
const edgesToChamfer = [];
|
|
246004
|
+
const chamferRadians = options.chamferAngleBetweenNormals.radians;
|
|
246005
|
+
const vertexXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create(); // reuse
|
|
246006
|
+
const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
|
|
246007
|
+
const outwardEdgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
|
|
246008
|
+
const averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
|
|
246009
|
+
// collect all the edges with sharp turn angle.
|
|
246010
|
+
this._baseGraph.announceEdges((_graph, edgeNode) => {
|
|
246011
|
+
if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(edgeNode, edgeVector, averageNormal, distance, chamferRadians)) {
|
|
246012
|
+
edgesToChamfer.push(edgeNode);
|
|
246013
|
+
return true;
|
|
246014
|
+
}
|
|
246015
|
+
return true;
|
|
246016
|
+
});
|
|
246017
|
+
// Create sliver faces.
|
|
246018
|
+
// Sliver face gets an average normal from its neighbors.
|
|
246019
|
+
// outsideA is the HalfEdge labeled A in the diagram.
|
|
246020
|
+
// sliverDX and sliverDY are the edges "inside the sliver" at the respective X and Y ends.
|
|
246021
|
+
for (const outsideA of edgesToChamfer) {
|
|
246022
|
+
// remark: this recomputes as in collection round.
|
|
246023
|
+
if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(outsideA, edgeVector, averageNormal, chamferRadians)) {
|
|
246024
|
+
// This copies coordinates and vertex id .... sectorOffsetProperties are delayed until late in the 2-pass loop below.
|
|
246025
|
+
// The returned HalfEdge is labeled D in the diagram
|
|
246026
|
+
const sliverDX = this._baseGraph.splitEdgeCreateSliverFace(outsideA);
|
|
246027
|
+
const sliverDY = sliverDX.facePredecessor;
|
|
246028
|
+
const offsetPoint = sliverDX.getPoint3d();
|
|
246029
|
+
offsetPoint.addScaledInPlace(averageNormal, distance);
|
|
246030
|
+
const ray = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__.Ray3d.createCapture(offsetPoint, averageNormal.clone());
|
|
246031
|
+
const facetProperties = new FacetOffsetProperties(-1, ray);
|
|
246032
|
+
// for each side (hence end) of the sliver face, set mask and install a sling loop for the anticipated end of the chamfer face
|
|
246033
|
+
// new node names in the loop omit X or Y suffix because that is implied by which pass is running.
|
|
246034
|
+
let s = -1.0;
|
|
246035
|
+
for (const sliverD of [sliverDX, sliverDY]) {
|
|
246036
|
+
edgeVector.scale(s, outwardEdgeVector);
|
|
246037
|
+
sliverD.getPoint3d(vertexXYZ);
|
|
246038
|
+
sliverD.setMask(this._insideOfChamferFace);
|
|
246039
|
+
sliverD.edgeMate.setMask(this._outsideOfChamferFace);
|
|
246040
|
+
// mark and reference the chamfer face.
|
|
246041
|
+
sliverD.faceTag = facetProperties;
|
|
246042
|
+
// sling at this end
|
|
246043
|
+
const slingB = this._baseGraph.splitEdge(undefined, vertexXYZ.x, vertexXYZ.y, vertexXYZ.z, sliverD.i);
|
|
246044
|
+
const slingC = slingB.edgeMate;
|
|
246045
|
+
slingB.setMask(this._outsideEndOfChamferFace);
|
|
246046
|
+
slingB.faceTag = facetProperties;
|
|
246047
|
+
slingC.setMask(this._insideChamferSling);
|
|
246048
|
+
_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(sliverD, slingB);
|
|
246049
|
+
const endNormal = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__.Ray3d.create(vertexXYZ, outwardEdgeVector); // clones the inputs
|
|
246050
|
+
const slingFaceProperties = new FacetOffsetProperties(-1, endNormal);
|
|
246051
|
+
slingC.faceTag = slingFaceProperties;
|
|
246052
|
+
// initialize sectors with existing vertex point.
|
|
246053
|
+
sliverD.edgeTag = new SectorOffsetProperties(averageNormal.clone(), offsetPoint.clone());
|
|
246054
|
+
slingB.edgeTag = new SectorOffsetProperties(averageNormal.clone(), offsetPoint.clone());
|
|
246055
|
+
slingC.edgeTag = new SectorOffsetProperties(outwardEdgeVector.clone(), vertexXYZ.clone());
|
|
246056
|
+
// OffsetMeshContext.stringDebugFunction("Chamfer Setup");
|
|
246057
|
+
const chamferPointE = this.compute3SectorIntersection(sliverD, sliverD.edgeMate, slingC);
|
|
246058
|
+
const chamferPointF = this.compute3SectorIntersection(slingB, slingB.vertexSuccessor, slingC);
|
|
246059
|
+
// sliverD.edgeTag = new SectorOffsetProperties(averageNormal.clone(), vertexXYZ.clone());
|
|
246060
|
+
SectorOffsetProperties.setXYZAtHalfEdge(sliverD, chamferPointE);
|
|
246061
|
+
SectorOffsetProperties.setXYZAtHalfEdge(slingB, chamferPointF);
|
|
246062
|
+
s *= -1.0;
|
|
246063
|
+
}
|
|
246064
|
+
}
|
|
246065
|
+
}
|
|
246066
|
+
}
|
|
246067
|
+
/**
|
|
246068
|
+
* * at input:
|
|
246069
|
+
* * Each node points to sectorOffsetProperties with previously computed XYZ (presumably mismatched)
|
|
246070
|
+
* * at exit:
|
|
246071
|
+
* * Each sectorOffsetProperties has an offset point computed with consideration of offset planes in the neighborhood.
|
|
246072
|
+
* @param distance distance to offset.
|
|
246073
|
+
*/
|
|
246074
|
+
computeOffsetFacetIntersections(distance) {
|
|
246075
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
246076
|
+
OffsetMeshContext.stringDebugFunction("***** recompute intersections");
|
|
246077
|
+
const breakEdges = [];
|
|
246078
|
+
const vertexXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
|
|
246079
|
+
const chamferXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
|
|
246080
|
+
const maxVertexMove = 2.0 * distance;
|
|
246081
|
+
const averageNormalData = new AverageNormalData();
|
|
246082
|
+
const maxAllowedNormalDeviationRadians = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_9__.Angle.degreesToRadians(25.0);
|
|
246083
|
+
//
|
|
246084
|
+
// FOR EACH VERTEX
|
|
246085
|
+
//
|
|
246086
|
+
this._baseGraph.announceVertexLoops((_graph, vertexSeedA) => {
|
|
246087
|
+
// reposition to an important vertex.
|
|
246088
|
+
// first choice: a chamfer face.
|
|
246089
|
+
let vertexSeed = vertexSeedA.findMaskAroundVertex(this._outsideEndOfChamferFace);
|
|
246090
|
+
if (vertexSeed === undefined)
|
|
246091
|
+
vertexSeed = vertexSeedA.findMaskAroundVertex(this._breakMaskA);
|
|
246092
|
+
if (vertexSeed === undefined)
|
|
246093
|
+
vertexSeed = vertexSeedA;
|
|
246094
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
246095
|
+
OffsetMeshContext.stringDebugFunction("");
|
|
246096
|
+
OffsetMeshContext.stringDebugFunction(` VERTEX LOOP ${vertexSeed.getPoint3d().toJSON()} `);
|
|
246097
|
+
vertexSeed.sumAroundVertex((node) => { OffsetMeshContext.stringDebugFunction(this.inspectMasks(node, false, true)); return 0; });
|
|
246098
|
+
}
|
|
246099
|
+
// Take care of the easiest vertices directly . . . note that this returns from the lambda, not computeOffsetFacetIntersections
|
|
246100
|
+
if (this.assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedNormalDeviationRadians, averageNormalData, distance))
|
|
246101
|
+
return true;
|
|
246102
|
+
this.markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed);
|
|
246103
|
+
this.setOffsetAtDistanceAroundVertex(vertexSeed, distance, true);
|
|
246104
|
+
vertexSeed.collectMaskedEdgesAroundVertex(this._breakMaskA, true, breakEdges);
|
|
246105
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
246106
|
+
OffsetMeshContext.stringDebugFunction(` BREAK EDGES from ${this.inspectMasks(vertexSeed, true, false)}`);
|
|
246107
|
+
for (const node of breakEdges) {
|
|
246108
|
+
OffsetMeshContext.stringDebugFunction(this.inspectMasks(node, false, true));
|
|
246109
|
+
}
|
|
246110
|
+
}
|
|
246111
|
+
if (breakEdges.length <= 1) {
|
|
246112
|
+
// just one smooth sequence.
|
|
246113
|
+
// everything is set already.
|
|
246114
|
+
}
|
|
246115
|
+
else if (breakEdges.length === 2) {
|
|
246116
|
+
// exterior vertex with two incident smooth
|
|
246117
|
+
const vectorFromOrigin = this.compute2SectorIntersection(breakEdges[0], breakEdges[1]);
|
|
246118
|
+
if (vectorFromOrigin !== undefined) {
|
|
246119
|
+
this.setOffsetXYAndZAroundVertex(vertexSeed, vectorFromOrigin);
|
|
246120
|
+
}
|
|
246121
|
+
}
|
|
246122
|
+
else if (breakEdges.length === 3) {
|
|
246123
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
246124
|
+
OffsetMeshContext.stringDebugFunction(` Vertex Update just ${breakEdges.length} `);
|
|
246125
|
+
const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[0], breakEdges[1], breakEdges[2]);
|
|
246126
|
+
if (vectorFromOrigin !== undefined) {
|
|
246127
|
+
this.setOffsetXYAndZAroundVertex(vertexSeed, vectorFromOrigin);
|
|
246128
|
+
}
|
|
246129
|
+
// simple 3-face corner . . .
|
|
246130
|
+
}
|
|
246131
|
+
else {
|
|
246132
|
+
// Lots and Lots of edges
|
|
246133
|
+
// each set of 3 sectors independently generates an offset for its central sector.
|
|
246134
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
246135
|
+
OffsetMeshContext.stringDebugFunction(` Vertex Update breakEdges ${breakEdges.length} `);
|
|
246136
|
+
vertexSeed.getPoint3d(vertexXYZ);
|
|
246137
|
+
// Pass 1 -- look for intersection among multiple chamfers
|
|
246138
|
+
for (let i = 0; i < breakEdges.length; i++) {
|
|
246139
|
+
const i0 = i;
|
|
246140
|
+
const i1 = (i0 + 1) % breakEdges.length;
|
|
246141
|
+
const i2 = (i1 + 1) % breakEdges.length;
|
|
246142
|
+
if (breakEdges[i0].isMaskSet(this._outsideEndOfChamferFace)
|
|
246143
|
+
&& breakEdges[i1].isMaskSet(this._outsideOfChamferFace)
|
|
246144
|
+
&& breakEdges[i2].isMaskSet(this._insideOfChamferFace)) {
|
|
246145
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
246146
|
+
OffsetMeshContext.stringDebugFunction(` ChamferChamfer Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `);
|
|
246147
|
+
const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]);
|
|
246148
|
+
if (vectorFromOrigin !== undefined) {
|
|
246149
|
+
// Treat all 3 spots as possibly compound sequences
|
|
246150
|
+
for (const iOutput of [i0, i1, i2]) {
|
|
246151
|
+
this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[iOutput], (node, properties) => {
|
|
246152
|
+
properties.setXYAndZ(vectorFromOrigin);
|
|
246153
|
+
node.setMask(this._offsetCoordinatesReassigned);
|
|
246154
|
+
});
|
|
246155
|
+
}
|
|
246156
|
+
// Since all three were reset, skip past. This is done on the acyclic integer that controls the loop.
|
|
246157
|
+
i += 2;
|
|
246158
|
+
}
|
|
246159
|
+
}
|
|
246160
|
+
}
|
|
246161
|
+
// Pass 2 -- look for unassigned nodes just before or after a chamfer.
|
|
246162
|
+
// The chamfer wins
|
|
246163
|
+
for (let i = 0; i < breakEdges.length; i++) {
|
|
246164
|
+
const i0 = i;
|
|
246165
|
+
const i1 = (i0 + 1) % breakEdges.length;
|
|
246166
|
+
if (this.isInsideSling(breakEdges[i0], breakEdges[i1]))
|
|
246167
|
+
continue;
|
|
246168
|
+
if (!this.isOffsetAssigned(breakEdges[i0])
|
|
246169
|
+
&& breakEdges[i1].isMaskSet(this.insideOfChamferFace)) {
|
|
246170
|
+
this.transferXYZFromNodeToSmoothSector(breakEdges[i1], breakEdges[i0], "push left from chamfer", chamferXYZ);
|
|
246171
|
+
}
|
|
246172
|
+
else if (!this.isOffsetAssigned(breakEdges[i1])
|
|
246173
|
+
&& breakEdges[i0].isMaskSet(this.outsideEndOfChamferFace)) {
|
|
246174
|
+
this.transferXYZFromNodeToSmoothSector(breakEdges[i0], breakEdges[i1], "push right from chamfer", chamferXYZ);
|
|
246175
|
+
}
|
|
246176
|
+
}
|
|
246177
|
+
// Pass 3 -- look for unassigned nodes as middle of 3-face intersections
|
|
246178
|
+
for (let i = 0; i < breakEdges.length; i++) {
|
|
246179
|
+
const i0 = i;
|
|
246180
|
+
const i1 = (i0 + 1) % breakEdges.length;
|
|
246181
|
+
const i2 = (i1 + 1) % breakEdges.length;
|
|
246182
|
+
if (this.isInsideSling(breakEdges[i0], breakEdges[i1], breakEdges[i2]))
|
|
246183
|
+
continue;
|
|
246184
|
+
if (this.isOffsetAssigned(breakEdges[i1]))
|
|
246185
|
+
continue;
|
|
246186
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
246187
|
+
OffsetMeshContext.stringDebugFunction(` Intersection Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `);
|
|
246188
|
+
const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]);
|
|
246189
|
+
if (vectorFromOrigin !== undefined) {
|
|
246190
|
+
if (vertexXYZ.distance(vectorFromOrigin) < maxVertexMove) {
|
|
246191
|
+
this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[i1], (node, properties) => {
|
|
246192
|
+
properties.setXYAndZ(vectorFromOrigin);
|
|
246193
|
+
node.setMask(this._offsetCoordinatesReassigned);
|
|
246194
|
+
});
|
|
246195
|
+
}
|
|
246196
|
+
}
|
|
246197
|
+
}
|
|
246198
|
+
}
|
|
246199
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
246200
|
+
const n0 = vertexSeed.countMaskAroundVertex(this._offsetCoordinatesReassigned, false);
|
|
246201
|
+
const n1 = vertexSeed.countMaskAroundVertex(this._offsetCoordinatesReassigned, true);
|
|
246202
|
+
const message = ` **** Vertex offset mask counts(TRUE ${n1})(FALSE ${n0})`;
|
|
246203
|
+
OffsetMeshContext.stringDebugFunction(message);
|
|
246204
|
+
}
|
|
246205
|
+
return true;
|
|
246206
|
+
});
|
|
246207
|
+
}
|
|
246208
|
+
// return true if any of these nodes is "inside" the sling at the end of a chamfer.
|
|
246209
|
+
isInsideSling(node0, node1, node2) {
|
|
246210
|
+
return node0.isMaskSet(this._insideChamferSling)
|
|
246211
|
+
|| (node1 !== undefined && node1.isMaskSet(this._insideChamferSling))
|
|
246212
|
+
|| (node2 !== undefined && node2.isMaskSet(this._insideChamferSling));
|
|
246213
|
+
}
|
|
246214
|
+
// return true if any of these nodes is "inside" the sling at the end of a chamfer.
|
|
246215
|
+
isInsideChamferOrSling(node0) {
|
|
246216
|
+
return node0.isMaskSet(this._insideChamferSling)
|
|
246217
|
+
|| node0.isMaskSet(this._insideOfChamferFace)
|
|
246218
|
+
|| node0.isMaskSet(this._outsideEndOfChamferFace);
|
|
246219
|
+
}
|
|
246220
|
+
isOffsetAssigned(node0, node1, node2) {
|
|
246221
|
+
return node0.isMaskSet(this._offsetCoordinatesReassigned)
|
|
246222
|
+
|| (node1 !== undefined && node1.isMaskSet(this._offsetCoordinatesReassigned))
|
|
246223
|
+
|| (node2 !== undefined && node2.isMaskSet(this._offsetCoordinatesReassigned));
|
|
246224
|
+
}
|
|
246225
|
+
/**
|
|
246226
|
+
*
|
|
246227
|
+
* @param sourceNode node with good xyz
|
|
246228
|
+
* @param destinationStartNode first of a sequence of nodes to set (delimited by masks)
|
|
246229
|
+
* @param description string for debug
|
|
246230
|
+
* @param workPoint point to use for coordinate transfer.
|
|
246231
|
+
*/
|
|
246232
|
+
transferXYZFromNodeToSmoothSector(sourceNode, destinationStartNode, description, workPoint) {
|
|
246233
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
246234
|
+
OffsetMeshContext.stringDebugFunction(` ${description} ${this.inspectMasks(sourceNode)} to ${this.inspectMasks(destinationStartNode)}} `);
|
|
246235
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(sourceNode, workPoint, undefined);
|
|
246236
|
+
this.announceNodeAndSectorPropertiesInSmoothSector(destinationStartNode, (node, properties) => {
|
|
246237
|
+
properties.setXYAndZ(workPoint);
|
|
246238
|
+
node.setMask(this._offsetCoordinatesReassigned);
|
|
246239
|
+
});
|
|
246240
|
+
}
|
|
246241
|
+
}
|
|
246242
|
+
|
|
246243
|
+
|
|
245019
246244
|
/***/ }),
|
|
245020
246245
|
|
|
245021
246246
|
/***/ "../../core/geometry/lib/esm/polyface/multiclip/RangeSearch.js":
|
|
@@ -254224,16 +255449,16 @@ class Sample {
|
|
|
254224
255449
|
_curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(5, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 0)), _curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(15, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 360)), _curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(25, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 0)))));
|
|
254225
255450
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(// 2-pt Interpolation Curve
|
|
254226
255451
|
_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
|
|
254227
|
-
fitPoints: [pointsA[0], pointsA[1]]
|
|
255452
|
+
fitPoints: [pointsA[0], pointsA[1]],
|
|
254228
255453
|
})))));
|
|
254229
255454
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(// 3-pt Interpolation Curve
|
|
254230
255455
|
_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
|
|
254231
|
-
fitPoints: [pointsA[0], pointsA[1], pointsA[2]]
|
|
255456
|
+
fitPoints: [pointsA[0], pointsA[1], pointsA[2]],
|
|
254232
255457
|
})))));
|
|
254233
255458
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
|
|
254234
255459
|
fitPoints: pointsA,
|
|
254235
255460
|
startTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(1, -1),
|
|
254236
|
-
endTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(-1, -1)
|
|
255461
|
+
endTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(-1, -1),
|
|
254237
255462
|
})))));
|
|
254238
255463
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_curve_spiral_IntegratedSpiral3d__WEBPACK_IMPORTED_MODULE_39__.IntegratedSpiral3d.createRadiusRadiusBearingBearing(_geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 100), _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(10, 75), _geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 1), _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createOriginAndMatrix(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.createZero(), _geometry3d_Matrix3d__WEBPACK_IMPORTED_MODULE_12__.Matrix3d.createRotationAroundAxisIndex(2, _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(30))), "bloss"))));
|
|
254239
255464
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_curve_spiral_DirectSpiral3d__WEBPACK_IMPORTED_MODULE_41__.DirectSpiral3d.createDirectHalfCosine(_geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createOriginAndMatrix(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.createZero(), _geometry3d_Matrix3d__WEBPACK_IMPORTED_MODULE_12__.Matrix3d.createRotationAroundAxisIndex(2, _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(110))), 50, 350, _geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 1)))));
|
|
@@ -254347,8 +255572,11 @@ class Sample {
|
|
|
254347
255572
|
/** Create swept "solids" that can be capped.
|
|
254348
255573
|
* * At least one of each solid type.
|
|
254349
255574
|
* * each is within 10 of the origin all directions.
|
|
255575
|
+
* @param capped true to include caps
|
|
255576
|
+
* @param rotationAngle angle of rotation for the angular sweep. The default is 90 degrees.
|
|
255577
|
+
* Beware that the rotation sweep created with the default or any positive angle produces a mesh with inward normals.
|
|
254350
255578
|
*/
|
|
254351
|
-
static createClosedSolidSampler(capped) {
|
|
255579
|
+
static createClosedSolidSampler(capped, rotationAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(90)) {
|
|
254352
255580
|
const result = [];
|
|
254353
255581
|
result.push(_solid_Box__WEBPACK_IMPORTED_MODULE_35__.Box.createRange(_geometry3d_Range__WEBPACK_IMPORTED_MODULE_4__.Range3d.createXYZXYZ(0, 0, 0, 3, 2, 5), capped));
|
|
254354
255582
|
result.push(_solid_Cone__WEBPACK_IMPORTED_MODULE_33__.Cone.createAxisPoints(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 0), _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 5), 1.0, 1.0, capped));
|
|
@@ -254360,18 +255588,23 @@ class Sample {
|
|
|
254360
255588
|
const pointQ2 = arcA.fractionAndDistanceToPointOnTangent(1.0, 0.5);
|
|
254361
255589
|
const pointR1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(point0.x, pointQ1.y);
|
|
254362
255590
|
const pointR2 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(point0.x, pointQ1.y);
|
|
255591
|
+
const pointR3 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(pointQ1.x - 1, pointQ1.y);
|
|
255592
|
+
const pointR4 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(pointQ1.x - 3, pointQ1.y);
|
|
254363
255593
|
const linestringQ1 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ1, pointR1, point0);
|
|
254364
255594
|
const linestringQ2 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ2, pointR2, point0);
|
|
255595
|
+
const linestringQ3 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ2, pointR3, pointR4, point0);
|
|
254365
255596
|
const contourZ = _curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(linestringQ1.clone());
|
|
254366
255597
|
const contourA = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ1.clone());
|
|
254367
255598
|
const contourB = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ2.clone());
|
|
255599
|
+
const contourC1 = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ3.clone());
|
|
254368
255600
|
contourB.tryTransformInPlace(_geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createTranslationXYZ(1, 1, 3));
|
|
254369
255601
|
// const contourC = contourB.cloneTransformed(Transform.createTranslationXYZ(2, 1, 4))!;
|
|
254370
255602
|
result.push(_solid_LinearSweep__WEBPACK_IMPORTED_MODULE_30__.LinearSweep.create(contourA, _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(0, 0, 5), capped));
|
|
255603
|
+
result.push(_solid_LinearSweep__WEBPACK_IMPORTED_MODULE_30__.LinearSweep.create(contourC1, _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(0, 0, 5), capped));
|
|
254371
255604
|
const axis = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_14__.Ray3d.createXYZUVW(0, 8, 0, 1, 0, 0);
|
|
254372
|
-
result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourA.clone(), axis.clone(),
|
|
255605
|
+
result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourA.clone(), axis.clone(), rotationAngle, capped));
|
|
254373
255606
|
if (!capped)
|
|
254374
|
-
result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourZ.clone(), axis.clone(),
|
|
255607
|
+
result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourZ.clone(), axis.clone(), rotationAngle, false));
|
|
254375
255608
|
result.push(_solid_RuledSweep__WEBPACK_IMPORTED_MODULE_36__.RuledSweep.create([contourA.clone(), contourB.clone()], capped));
|
|
254376
255609
|
const transformC = _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createScaleAboutPoint(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 8), 0.5);
|
|
254377
255610
|
const contourC = contourB.cloneTransformed(transformC);
|
|
@@ -258796,12 +260029,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
258796
260029
|
/* harmony export */ "HalfEdgeGraph": () => (/* binding */ HalfEdgeGraph),
|
|
258797
260030
|
/* harmony export */ "HalfEdgeMask": () => (/* binding */ HalfEdgeMask)
|
|
258798
260031
|
/* harmony export */ });
|
|
258799
|
-
/* harmony import */ var
|
|
260032
|
+
/* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
|
|
258800
260033
|
/* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
|
|
260034
|
+
/* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
|
|
258801
260035
|
/* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
|
|
258802
260036
|
/* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
|
|
258803
|
-
/* harmony import */ var
|
|
258804
|
-
/* harmony import */ var
|
|
260037
|
+
/* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
|
|
260038
|
+
/* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
|
|
258805
260039
|
/*---------------------------------------------------------------------------------------------
|
|
258806
260040
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
258807
260041
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
@@ -258815,6 +260049,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
258815
260049
|
|
|
258816
260050
|
|
|
258817
260051
|
|
|
260052
|
+
|
|
258818
260053
|
// import { GraphChecker } from "../test/topology/Graph.test";
|
|
258819
260054
|
/* eslint-disable @typescript-eslint/no-this-alias */
|
|
258820
260055
|
// cspell:word CONSTU
|
|
@@ -258902,6 +260137,7 @@ class HalfEdge {
|
|
|
258902
260137
|
this.sortAngle = undefined;
|
|
258903
260138
|
this.sortData = undefined;
|
|
258904
260139
|
this.edgeTag = undefined;
|
|
260140
|
+
this.faceTag = undefined;
|
|
258905
260141
|
// Always created in pairs, init here to make TS compiler and JS runtime happy
|
|
258906
260142
|
this._facePredecessor = this;
|
|
258907
260143
|
this._faceSuccessor = this;
|
|
@@ -259022,6 +260258,36 @@ class HalfEdge {
|
|
|
259022
260258
|
}
|
|
259023
260259
|
return newA;
|
|
259024
260260
|
}
|
|
260261
|
+
/**
|
|
260262
|
+
* * Create a new sliver face "inside" an existing edge.
|
|
260263
|
+
* * Insert it "within" the base edge.
|
|
260264
|
+
* * This requires two new half edges.
|
|
260265
|
+
* * if the base is undefined, create a single-edge loop.
|
|
260266
|
+
* * This (unlike pinch) breaks the edgeMate pairing of the base edge.
|
|
260267
|
+
* * This preserves xyz and i properties at all existing vertices.
|
|
260268
|
+
* * The two new half edges are a sliver face (via their predecessor and successor)
|
|
260269
|
+
* * Each new edge mates to one existing edge.
|
|
260270
|
+
* @returns Returns the reference to the half edge created.
|
|
260271
|
+
*/
|
|
260272
|
+
static splitEdgeCreateSliverFace(baseA, heArray) {
|
|
260273
|
+
// raw edges ...
|
|
260274
|
+
const newA = new HalfEdge();
|
|
260275
|
+
const newB = new HalfEdge();
|
|
260276
|
+
const baseB = baseA.edgeMate;
|
|
260277
|
+
if (heArray) {
|
|
260278
|
+
heArray.push(newA);
|
|
260279
|
+
heArray.push(newB);
|
|
260280
|
+
}
|
|
260281
|
+
newA._faceSuccessor = newA._facePredecessor = newB;
|
|
260282
|
+
newB._faceSuccessor = newB._facePredecessor = newA;
|
|
260283
|
+
// newA is in vertex loop with baseA etc.
|
|
260284
|
+
// newA mates to baseB
|
|
260285
|
+
HalfEdge.setEdgeMates(newA, baseB);
|
|
260286
|
+
HalfEdge.setEdgeMates(newB, baseA);
|
|
260287
|
+
newA.copyDataFrom(baseA, true, true, false, false);
|
|
260288
|
+
newB.copyDataFrom(baseB, true, true, false, false);
|
|
260289
|
+
return newA;
|
|
260290
|
+
}
|
|
259025
260291
|
/**
|
|
259026
260292
|
* Copy "edge based" content of fromNode to toNode
|
|
259027
260293
|
* * edgeTag
|
|
@@ -259232,6 +260498,35 @@ class HalfEdge {
|
|
|
259232
260498
|
}
|
|
259233
260499
|
return count;
|
|
259234
260500
|
}
|
|
260501
|
+
/** Returns the first node with given mask value around this vertex loop. */
|
|
260502
|
+
findMaskAroundVertex(mask, value = true) {
|
|
260503
|
+
let node = this;
|
|
260504
|
+
do {
|
|
260505
|
+
if (node.isMaskSet(mask) === value)
|
|
260506
|
+
return node;
|
|
260507
|
+
node = node.vertexSuccessor;
|
|
260508
|
+
} while (node !== this);
|
|
260509
|
+
return undefined;
|
|
260510
|
+
}
|
|
260511
|
+
/** Returns the first node with given mask value around this face loop. */
|
|
260512
|
+
findMaskAroundFace(mask, value = true) {
|
|
260513
|
+
let node = this;
|
|
260514
|
+
do {
|
|
260515
|
+
if (node.isMaskSet(mask) === value)
|
|
260516
|
+
return node;
|
|
260517
|
+
node = node.faceSuccessor;
|
|
260518
|
+
} while (node !== this);
|
|
260519
|
+
return undefined;
|
|
260520
|
+
}
|
|
260521
|
+
/** Returns the first node with given mask value on this edge (i.e. examining this and this.mate) */
|
|
260522
|
+
findMaskAroundEdge(mask, value = true) {
|
|
260523
|
+
if (this.isMaskSet(mask) === value)
|
|
260524
|
+
return this;
|
|
260525
|
+
const mate = this.edgeMate;
|
|
260526
|
+
if (mate.isMaskSet(mask) === value)
|
|
260527
|
+
return mate;
|
|
260528
|
+
return undefined;
|
|
260529
|
+
}
|
|
259235
260530
|
/** Set a mask, and return prior value.
|
|
259236
260531
|
* @param mask mask to apply
|
|
259237
260532
|
*/
|
|
@@ -259249,6 +260544,15 @@ class HalfEdge {
|
|
|
259249
260544
|
this.y = node.y;
|
|
259250
260545
|
this.z = node.z;
|
|
259251
260546
|
}
|
|
260547
|
+
/**
|
|
260548
|
+
* Set (copy) the this.x, this.y, this.z from xyz.x, xyz.y, xyz.z
|
|
260549
|
+
* @param node source with x,y,z properties
|
|
260550
|
+
*/
|
|
260551
|
+
setXYZ(xyz) {
|
|
260552
|
+
this.x = xyz.x;
|
|
260553
|
+
this.y = xyz.y;
|
|
260554
|
+
this.z = xyz.z;
|
|
260555
|
+
}
|
|
259252
260556
|
/**
|
|
259253
260557
|
* Test if mask bits are set in the node's bitMask.
|
|
259254
260558
|
* @return Return true (as a simple boolean, not a mask) if any bits of the mask parameter match bits of the node's bitMask
|
|
@@ -259338,6 +260642,10 @@ class HalfEdge {
|
|
|
259338
260642
|
const s = `${node.id.toString()}+${HalfEdge.nodeToMaskString(node)}[${node.x},${node.y}]`;
|
|
259339
260643
|
return s;
|
|
259340
260644
|
}
|
|
260645
|
+
/** Return the [id, [x,y],z] of a node. Useful for collector methods. */
|
|
260646
|
+
static nodeToIdXYZString(node) {
|
|
260647
|
+
return `[${node.id.toString()}: ${node.x},${node.y},${node.z}]`;
|
|
260648
|
+
}
|
|
259341
260649
|
/** Create a string representation of the mask
|
|
259342
260650
|
* * Null mask is empty string.
|
|
259343
260651
|
* * Appended characters B,P,X for Boundary, Primary, Exterior mask bits.
|
|
@@ -259362,7 +260670,13 @@ class HalfEdge {
|
|
|
259362
260670
|
}
|
|
259363
260671
|
/** Return Vector3d to face successor */
|
|
259364
260672
|
vectorToFaceSuccessor(result) {
|
|
259365
|
-
|
|
260673
|
+
const other = this.faceSuccessor;
|
|
260674
|
+
return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
|
|
260675
|
+
}
|
|
260676
|
+
/** Return Vector3d to face successor */
|
|
260677
|
+
vectorToFacePredecessor(result) {
|
|
260678
|
+
const other = this.facePredecessor;
|
|
260679
|
+
return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
|
|
259366
260680
|
}
|
|
259367
260681
|
/** test if spaceNode is in the sector at sectorNode */
|
|
259368
260682
|
static isNodeVisibleInSector(spaceNode, sectorNode) {
|
|
@@ -259486,6 +260800,14 @@ class HalfEdge {
|
|
|
259486
260800
|
static testNodeMaskNotExterior(node) { return !node.isMaskSet(HalfEdgeMask.EXTERIOR); }
|
|
259487
260801
|
/** Returns Returns true if the node does NOT have Mask.EXTERIOR_MASK set. */
|
|
259488
260802
|
static testMateMaskExterior(node) { return node.edgeMate.isMaskSet(HalfEdgeMask.EXTERIOR); }
|
|
260803
|
+
/** Returns radians between this edge and its face predecessor edge, using all three coordinates x,y,z and given normal to resolve sweep direction.
|
|
260804
|
+
* * The returned angle is positive, i.e. may be larger than PI radians.
|
|
260805
|
+
*/
|
|
260806
|
+
static sectorSweepRadiansXYZ(node, normal) {
|
|
260807
|
+
const nodeB = node.faceSuccessor;
|
|
260808
|
+
const nodeC = node.facePredecessor;
|
|
260809
|
+
return _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.orientedRadiansBetweenVectorsXYZ(nodeB.x - node.x, nodeB.y - node.y, nodeB.z - node.z, nodeC.x - node.x, nodeC.y - node.y, nodeC.z - node.z, normal.x, normal.y, normal.z, true);
|
|
260810
|
+
}
|
|
259489
260811
|
/** Returns Returns true if the face has positive area in xy parts. */
|
|
259490
260812
|
static testFacePositiveAreaXY(node) {
|
|
259491
260813
|
return node.countEdgesAroundFace() > 2 && node.signedFaceArea() > 0.0;
|
|
@@ -259517,6 +260839,26 @@ class HalfEdge {
|
|
|
259517
260839
|
} while (node !== this);
|
|
259518
260840
|
return nodes;
|
|
259519
260841
|
}
|
|
260842
|
+
/**
|
|
260843
|
+
* search around a vertex for nodes that have a specified mask setting.
|
|
260844
|
+
* @param vertexSeed first node to search
|
|
260845
|
+
* @param mask target mask
|
|
260846
|
+
* @param value target value for mask on half edges.
|
|
260847
|
+
* @param collectedNodes optional array to be cleared and receive masked nodes
|
|
260848
|
+
*/
|
|
260849
|
+
collectMaskedEdgesAroundVertex(mask, value = true, result) {
|
|
260850
|
+
if (result === undefined)
|
|
260851
|
+
result = [];
|
|
260852
|
+
else
|
|
260853
|
+
result.length = 0;
|
|
260854
|
+
let node = this;
|
|
260855
|
+
do {
|
|
260856
|
+
if (node.isMaskSet(mask) === value)
|
|
260857
|
+
result.push(node);
|
|
260858
|
+
node = node.vertexSuccessor;
|
|
260859
|
+
} while (node !== this);
|
|
260860
|
+
return result;
|
|
260861
|
+
}
|
|
259520
260862
|
/**
|
|
259521
260863
|
*
|
|
259522
260864
|
* * Evaluate f(node) at each outbound node around this node's vertex loop.
|
|
@@ -259700,7 +261042,7 @@ class HalfEdge {
|
|
|
259700
261042
|
const nodeB1 = nodeB0.faceSuccessor;
|
|
259701
261043
|
if (!result)
|
|
259702
261044
|
result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create();
|
|
259703
|
-
if (
|
|
261045
|
+
if (_numerics_Polynomials__WEBPACK_IMPORTED_MODULE_4__.SmallSystem.linearSystem2d(nodeA1.x - nodeA0.x, nodeB0.x - nodeB1.x, nodeA1.y - nodeA0.y, nodeB0.y - nodeB1.y, nodeB0.x - nodeA0.x, nodeB0.y - nodeA0.y, result))
|
|
259704
261046
|
return result;
|
|
259705
261047
|
return undefined;
|
|
259706
261048
|
}
|
|
@@ -259709,8 +261051,7 @@ class HalfEdge {
|
|
|
259709
261051
|
* * If the edge is horizontal with (approximate) identical y, return the node.
|
|
259710
261052
|
* * If the edge is horizontal with different y, return undefined.
|
|
259711
261053
|
* * If the edge is not horizontal, return the fractional position (possibly outside 0..1) of the intersection.
|
|
259712
|
-
* @param
|
|
259713
|
-
* @param result optional preallocated result
|
|
261054
|
+
* @param node0 Base node of edge
|
|
259714
261055
|
*/
|
|
259715
261056
|
static horizontalScanFraction(node0, y) {
|
|
259716
261057
|
const node1 = node0.faceSuccessor;
|
|
@@ -259725,8 +261066,7 @@ class HalfEdge {
|
|
|
259725
261066
|
* * Compute fractional coordinates of the intersection of a horizontal line with an edge.
|
|
259726
261067
|
* * If the edge is horizontal return undefined (no test for horizontal at y!!!)
|
|
259727
261068
|
* * If the edge is not horizontal and y is between its end y's, return the fraction
|
|
259728
|
-
* @param
|
|
259729
|
-
* @param result optional preallocated result
|
|
261069
|
+
* @param node0 Base node of edge
|
|
259730
261070
|
*/
|
|
259731
261071
|
static horizontalScanFraction01(node0, y) {
|
|
259732
261072
|
const node1 = node0.faceSuccessor;
|
|
@@ -259740,6 +261080,31 @@ class HalfEdge {
|
|
|
259740
261080
|
return fraction;
|
|
259741
261081
|
return undefined;
|
|
259742
261082
|
}
|
|
261083
|
+
/**
|
|
261084
|
+
* Copy various data from source to this.
|
|
261085
|
+
* @param source other half edge.
|
|
261086
|
+
* @param XYZ copy simple coordinates
|
|
261087
|
+
* @param copyVertexData true to copy data belonging to the vertex. (i.e. the "i" member)
|
|
261088
|
+
* @param copyVertexData true to copy data belonging to the edge. (i.e. call transferEdgeData)
|
|
261089
|
+
* @param copyFaceData true to copy faceTag
|
|
261090
|
+
*/
|
|
261091
|
+
copyDataFrom(source, copyXYZ, copyVertexData, copyEdgeData, copyFaceData) {
|
|
261092
|
+
if (copyXYZ) {
|
|
261093
|
+
this.x = source.x;
|
|
261094
|
+
this.y = source.y;
|
|
261095
|
+
this.z = source.z;
|
|
261096
|
+
}
|
|
261097
|
+
if (copyVertexData) {
|
|
261098
|
+
this.i = source.i;
|
|
261099
|
+
}
|
|
261100
|
+
if (copyEdgeData) {
|
|
261101
|
+
HalfEdge.transferEdgeProperties(source, this);
|
|
261102
|
+
this.edgeTag = source.edgeTag;
|
|
261103
|
+
}
|
|
261104
|
+
if (copyFaceData) {
|
|
261105
|
+
this.faceTag = source.faceTag;
|
|
261106
|
+
}
|
|
261107
|
+
}
|
|
259743
261108
|
}
|
|
259744
261109
|
HalfEdge._edgePropertyMasks = [HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.NULL_FACE];
|
|
259745
261110
|
HalfEdge._totalNodesCreated = 0;
|
|
@@ -259753,7 +261118,7 @@ class HalfEdgeGraph {
|
|
|
259753
261118
|
constructor() {
|
|
259754
261119
|
this._numNodesCreated = 0;
|
|
259755
261120
|
this.allHalfEdges = [];
|
|
259756
|
-
this._maskManager =
|
|
261121
|
+
this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_5__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
|
|
259757
261122
|
}
|
|
259758
261123
|
/** Ask for a mask (from the graph's free pool.) for caller's use.
|
|
259759
261124
|
* * Optionally clear the mask throughout the graph.
|
|
@@ -259780,6 +261145,19 @@ class HalfEdgeGraph {
|
|
|
259780
261145
|
const a = HalfEdge.createHalfEdgePairWithCoordinates(xA, yA, zA, iA, xB, yB, zB, iB, this.allHalfEdges);
|
|
259781
261146
|
return a;
|
|
259782
261147
|
}
|
|
261148
|
+
/**
|
|
261149
|
+
* * Create 2 half edges forming 2 vertices, 1 edge, and 1 face
|
|
261150
|
+
* * The two edges are joined as edgeMate pair.
|
|
261151
|
+
* * The two edges are a 2-half-edge face loop in both the faceSuccessor and facePredecessor directions.
|
|
261152
|
+
* * The two edges are added to the graph's HalfEdge set
|
|
261153
|
+
* * Coordinates are set to zero.
|
|
261154
|
+
* * ids are installed in the two half edges.
|
|
261155
|
+
* @returns Return pointer to the first half edge created. (This has idA as its id.)
|
|
261156
|
+
*/
|
|
261157
|
+
createEdgeIdId(iA = 0, iB = 0) {
|
|
261158
|
+
const a = HalfEdge.createHalfEdgePairWithCoordinates(0.0, 0.0, 0.0, iA, 0.0, 0.0, 0.0, iB, this.allHalfEdges);
|
|
261159
|
+
return a;
|
|
261160
|
+
}
|
|
259783
261161
|
/**
|
|
259784
261162
|
* * create an edge from coordinates x,y,z to (the tail of) an existing half edge.
|
|
259785
261163
|
* @returns Return pointer to the half edge with tail at x,y,z
|
|
@@ -259824,6 +261202,20 @@ class HalfEdgeGraph {
|
|
|
259824
261202
|
const he = HalfEdge.splitEdge(base, xA, yA, zA, iA, this.allHalfEdges);
|
|
259825
261203
|
return he;
|
|
259826
261204
|
}
|
|
261205
|
+
/**
|
|
261206
|
+
* * Create a sliver face "within" an edge.
|
|
261207
|
+
* * this creates two half edges.
|
|
261208
|
+
* * The existing edges both stay in their same face loops and retain coordinates and i value.
|
|
261209
|
+
* * Each existing edge's mate is a new edge (rather than original mate)
|
|
261210
|
+
* * Coordinates are copied to the new edges at respective vertices.
|
|
261211
|
+
* * New faceTag and edgeTag undefined.
|
|
261212
|
+
* * i members are copied around their respective vertices.
|
|
261213
|
+
* @returns Returns the reference to the half edge created.
|
|
261214
|
+
*/
|
|
261215
|
+
splitEdgeCreateSliverFace(base) {
|
|
261216
|
+
const he = HalfEdge.splitEdgeCreateSliverFace(base, this.allHalfEdges);
|
|
261217
|
+
return he;
|
|
261218
|
+
}
|
|
259827
261219
|
/**
|
|
259828
261220
|
* * Insert a vertex in the edge beginning at base, with coordinates specified as a fraction along the existing edge.
|
|
259829
261221
|
* * this creates two half edges.
|
|
@@ -259892,7 +261284,7 @@ class HalfEdgeGraph {
|
|
|
259892
261284
|
const segments = [];
|
|
259893
261285
|
for (const node of this.allHalfEdges) {
|
|
259894
261286
|
if (node.id < node.edgeMate.id)
|
|
259895
|
-
segments.push(
|
|
261287
|
+
segments.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__.LineSegment3d.create(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(node.x, node.y), _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(node.faceSuccessor.x, node.faceSuccessor.y)));
|
|
259896
261288
|
}
|
|
259897
261289
|
return segments;
|
|
259898
261290
|
}
|
|
@@ -259961,6 +261353,26 @@ class HalfEdgeGraph {
|
|
|
259961
261353
|
break;
|
|
259962
261354
|
}
|
|
259963
261355
|
}
|
|
261356
|
+
/**
|
|
261357
|
+
* * Visit each edge of the graph once.
|
|
261358
|
+
* * Call the announceEdge function.
|
|
261359
|
+
* * the edge mate will NOT appear in an announceEdge call.
|
|
261360
|
+
* * continue search if announceEdge(graph, node) returns true
|
|
261361
|
+
* * terminate search if announceEdge (graph, node) returns false
|
|
261362
|
+
* @param announceEdge function to apply at one node of each edge.
|
|
261363
|
+
*/
|
|
261364
|
+
announceEdges(announceEdge) {
|
|
261365
|
+
this.clearMask(HalfEdgeMask.VISITED);
|
|
261366
|
+
for (const node of this.allHalfEdges) {
|
|
261367
|
+
if (node.getMask(HalfEdgeMask.VISITED))
|
|
261368
|
+
continue;
|
|
261369
|
+
const mate = node.edgeMate;
|
|
261370
|
+
node.setMask(HalfEdgeMask.VISITED);
|
|
261371
|
+
mate.setMask(HalfEdgeMask.VISITED);
|
|
261372
|
+
if (!announceEdge(this, node))
|
|
261373
|
+
break;
|
|
261374
|
+
}
|
|
261375
|
+
}
|
|
259964
261376
|
/**
|
|
259965
261377
|
* * Visit each vertex loop of the graph once.
|
|
259966
261378
|
* * Call the announceVertex function
|
|
@@ -259979,8 +261391,8 @@ class HalfEdgeGraph {
|
|
|
259979
261391
|
}
|
|
259980
261392
|
}
|
|
259981
261393
|
/**
|
|
259982
|
-
* * Visit each
|
|
259983
|
-
* * Call the
|
|
261394
|
+
* * Visit each half edge (node) of the graph once.
|
|
261395
|
+
* * Call the announceNode function
|
|
259984
261396
|
* * continue search if announceNode(graph, node) returns true
|
|
259985
261397
|
* * terminate search if announce face (graph, node) returns false
|
|
259986
261398
|
* @param announceNode function to apply at one node of each face.
|
|
@@ -260039,6 +261451,99 @@ class HalfEdgeGraph {
|
|
|
260039
261451
|
}
|
|
260040
261452
|
|
|
260041
261453
|
|
|
261454
|
+
/***/ }),
|
|
261455
|
+
|
|
261456
|
+
/***/ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js":
|
|
261457
|
+
/*!************************************************************************************!*\
|
|
261458
|
+
!*** ../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js ***!
|
|
261459
|
+
\************************************************************************************/
|
|
261460
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
261461
|
+
|
|
261462
|
+
"use strict";
|
|
261463
|
+
__webpack_require__.r(__webpack_exports__);
|
|
261464
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
261465
|
+
/* harmony export */ "HalfEdgeGraphFromIndexedLoopsContext": () => (/* binding */ HalfEdgeGraphFromIndexedLoopsContext)
|
|
261466
|
+
/* harmony export */ });
|
|
261467
|
+
/* harmony import */ var _Graph__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
|
|
261468
|
+
/*---------------------------------------------------------------------------------------------
|
|
261469
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
261470
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
261471
|
+
*--------------------------------------------------------------------------------------------*/
|
|
261472
|
+
|
|
261473
|
+
/** @packageDocumentation
|
|
261474
|
+
* @module Topology
|
|
261475
|
+
*/
|
|
261476
|
+
/**
|
|
261477
|
+
* Context for building a half edge graph from loops defined only by indices.
|
|
261478
|
+
* * Direct use case:
|
|
261479
|
+
* * Create the context.
|
|
261480
|
+
* * Repeatedly call insertLoop(indicesAroundLoop) to announce various loops.
|
|
261481
|
+
* * Finish by accessing the graph property.
|
|
261482
|
+
* @internal
|
|
261483
|
+
*/
|
|
261484
|
+
class HalfEdgeGraphFromIndexedLoopsContext {
|
|
261485
|
+
constructor() {
|
|
261486
|
+
this._unmatchedEdges = new Map();
|
|
261487
|
+
this._graph = new _Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeGraph();
|
|
261488
|
+
this._halfEdgesAroundCurrentLoop = [];
|
|
261489
|
+
}
|
|
261490
|
+
get graph() { return this._graph; }
|
|
261491
|
+
indexPairToString(index0, index1) {
|
|
261492
|
+
return `${index0.toString()},${index1.toString()}`;
|
|
261493
|
+
}
|
|
261494
|
+
/** Create a loop with specified indices at its vertices.
|
|
261495
|
+
* * For an edge with index pair [indexA, indexB]:
|
|
261496
|
+
* * if [indexB, indexA] has never appeared, a HalfEdge mated pair is created.
|
|
261497
|
+
* * One of that mated pair becomes a HalfEdge in this loop.
|
|
261498
|
+
* * The other is "unmatched"
|
|
261499
|
+
* * When announceMatedHalfEdges(halfEdge) is called:
|
|
261500
|
+
* * halfEdge and its mate are "new"
|
|
261501
|
+
* * all coordinates are zeros.
|
|
261502
|
+
* * each contains (as its halfEdge.id property) one index of the [indexA,indexB] pair.
|
|
261503
|
+
* * those coordinates and indices will never be referenced again by this construction sequence -- the caller is free to mutate them as needed.
|
|
261504
|
+
* * if [indexB, indexA] appeared previously (and its outer HalfEdge was left "unmatched"),
|
|
261505
|
+
* the "unmatched" HalfEdge is used in the loop being constructed.
|
|
261506
|
+
* @param indices Array of indices around the edge. This is accessed cyclically.
|
|
261507
|
+
* @param announceMatedHalfEdges optional function to be called as mated pairs are created. At the call,
|
|
261508
|
+
* the given HalfEdge and its mate will have a pair of successive indices from the array.
|
|
261509
|
+
*/
|
|
261510
|
+
insertLoop(indices, announceMatedHalfEdges) {
|
|
261511
|
+
const n = indices.length;
|
|
261512
|
+
if (n > 1) {
|
|
261513
|
+
let index0 = indices[indices.length - 1];
|
|
261514
|
+
this._halfEdgesAroundCurrentLoop.length = 0;
|
|
261515
|
+
for (const index1 of indices) {
|
|
261516
|
+
const insideString = this.indexPairToString(index0, index1);
|
|
261517
|
+
const halfEdgePreviouslyConstructedFromOppositeSide = this._unmatchedEdges.get(insideString);
|
|
261518
|
+
if (halfEdgePreviouslyConstructedFromOppositeSide === undefined) {
|
|
261519
|
+
// This is the first appearance of this edge in either direction.
|
|
261520
|
+
const outsideString = this.indexPairToString(index1, index0); // string referencing the "other" side of the new edge.
|
|
261521
|
+
const newHalfEdgeAroundLoop = this._graph.createEdgeIdId(index0, index1);
|
|
261522
|
+
if (announceMatedHalfEdges !== undefined)
|
|
261523
|
+
announceMatedHalfEdges(newHalfEdgeAroundLoop);
|
|
261524
|
+
this._unmatchedEdges.set(outsideString, newHalfEdgeAroundLoop.edgeMate);
|
|
261525
|
+
this._halfEdgesAroundCurrentLoop.push(newHalfEdgeAroundLoop);
|
|
261526
|
+
newHalfEdgeAroundLoop.edgeMate.setMask(_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeMask.EXTERIOR);
|
|
261527
|
+
}
|
|
261528
|
+
else {
|
|
261529
|
+
this._halfEdgesAroundCurrentLoop.push(halfEdgePreviouslyConstructedFromOppositeSide);
|
|
261530
|
+
halfEdgePreviouslyConstructedFromOppositeSide.clearMask(_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeMask.EXTERIOR);
|
|
261531
|
+
}
|
|
261532
|
+
index0 = index1;
|
|
261533
|
+
}
|
|
261534
|
+
let halfEdgeA = this._halfEdgesAroundCurrentLoop[this._halfEdgesAroundCurrentLoop.length - 1];
|
|
261535
|
+
for (const halfEdgeB of this._halfEdgesAroundCurrentLoop) {
|
|
261536
|
+
const halfEdgeC = halfEdgeA.faceSuccessor;
|
|
261537
|
+
_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdge.pinch(halfEdgeB, halfEdgeC);
|
|
261538
|
+
halfEdgeA = halfEdgeB;
|
|
261539
|
+
}
|
|
261540
|
+
return this._halfEdgesAroundCurrentLoop[0];
|
|
261541
|
+
}
|
|
261542
|
+
return undefined;
|
|
261543
|
+
}
|
|
261544
|
+
}
|
|
261545
|
+
|
|
261546
|
+
|
|
260042
261547
|
/***/ }),
|
|
260043
261548
|
|
|
260044
261549
|
/***/ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js":
|
|
@@ -285523,7 +287028,7 @@ class TestContext {
|
|
|
285523
287028
|
this.initializeRpcInterfaces({ title: this.settings.Backend.name, version: this.settings.Backend.version });
|
|
285524
287029
|
const iModelClient = new imodels_client_management_1.IModelsClient({ api: { baseUrl: `https://${(_a = process.env.IMJS_URL_PREFIX) !== null && _a !== void 0 ? _a : ""}api.bentley.com/imodels` } });
|
|
285525
287030
|
await core_frontend_1.NoRenderApp.startup({
|
|
285526
|
-
applicationVersion: "4.0.0-dev.
|
|
287031
|
+
applicationVersion: "4.0.0-dev.7",
|
|
285527
287032
|
applicationId: this.settings.gprid,
|
|
285528
287033
|
authorizationClient: new frontend_1.TestFrontendAuthorizationClient(this.adminUserAccessToken),
|
|
285529
287034
|
hubAccess: new imodels_access_frontend_1.FrontendIModelsAccess(iModelClient),
|
|
@@ -304952,7 +306457,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
|
|
|
304952
306457
|
/***/ ((module) => {
|
|
304953
306458
|
|
|
304954
306459
|
"use strict";
|
|
304955
|
-
module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.0.0-dev.
|
|
306460
|
+
module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.0.0-dev.7","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs","build:ci":"npm run -s build && npm run -s build:esm","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2020 --outDir lib/esm","clean":"rimraf lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","docs":"betools docs --includes=../../generated-docs/extract --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/primitives,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-eslintrc -c \\"../../tools/eslint-plugin/dist/configs/extension-exports-config.js\\" \\"./src/**/*.ts\\" 1>&2","lint":"eslint -f visualstudio \\"./src/**/*.ts\\" 1>&2","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run -s webpackTests && certa -r chrome","cover":"npm -s test","test:debug":"certa -r chrome --debug","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core/tree/master/core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:^4.0.0-dev.7","@itwin/core-bentley":"workspace:^4.0.0-dev.7","@itwin/core-common":"workspace:^4.0.0-dev.7","@itwin/core-geometry":"workspace:^4.0.0-dev.7","@itwin/core-orbitgt":"workspace:^4.0.0-dev.7","@itwin/core-quantity":"workspace:^4.0.0-dev.7"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/certa":"workspace:*","@itwin/eslint-plugin":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@types/chai":"4.3.1","@types/chai-as-promised":"^7","@types/deep-assign":"^0.1.0","@types/lodash":"^4.14.0","@types/mocha":"^8.2.2","@types/node":"18.11.5","@types/qs":"^6.5.0","@types/semver":"7.3.10","@types/superagent":"^4.1.14","@types/sinon":"^9.0.0","babel-loader":"~8.2.5","babel-plugin-istanbul":"~6.1.1","chai":"^4.1.2","chai-as-promised":"^7","cpx2":"^3.0.0","eslint":"^7.11.0","glob":"^7.1.2","mocha":"^10.0.0","nyc":"^15.1.0","rimraf":"^3.0.2","sinon":"^9.0.2","source-map-loader":"^4.0.0","typescript":"~4.4.0","webpack":"^5.64.4"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/object-storage-azure":"~1.4.0","@itwin/cloud-agnostic-core":"~1.4.0","@itwin/object-storage-core":"~1.4.0","@itwin/core-i18n":"workspace:*","@itwin/core-telemetry":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","deep-assign":"^2.0.0","fuse.js":"^3.3.0","lodash":"^4.17.10","qs":"^6.5.3","semver":"^7.3.5","superagent":"^7.1.5","wms-capabilities":"0.4.0","reflect-metadata":"0.1.13"},"nyc":{"extends":"./node_modules/@itwin/build-tools/.nycrc"},"eslintConfig":{"plugins":["@itwin"],"extends":"plugin:@itwin/itwinjs-recommended","rules":{"@itwin/no-internal-barrel-imports":["error",{"required-barrel-modules":["./src/tile/internal.ts"]}],"@itwin/public-extension-exports":["error",{"releaseTags":["public","preview"],"outputApiFile":false}]},"overrides":[{"files":["*.test.ts","*.test.tsx","**/test/**/*.ts"],"rules":{"@itwin/no-internal-barrel-imports":"off"}}]}}');
|
|
304956
306461
|
|
|
304957
306462
|
/***/ }),
|
|
304958
306463
|
|